/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under GNU AFFERO GENERAL PUBLIC LICENSE Version 3.
*/
package com.ttProject.humble.test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import io.humble.ferry.Buffer;
import io.humble.video.AudioChannel.Layout;
import io.humble.video.AudioFormat.Type;
import io.humble.video.Codec;
import io.humble.video.Coder.Flag;
import io.humble.video.Encoder;
import io.humble.video.MediaAudio;
import io.humble.video.MediaAudioResampler;
import io.humble.video.MediaPacket;
import io.humble.video.Muxer;
import io.humble.video.Rational;
import org.apache.log4j.Logger;
/**
* make beep sound.
* @author taktod
*/
public class BeepSoundTest {
/** logger */
private Logger logger = Logger.getLogger(BeepSoundTest.class);
/**
* play beep Test.
*/
// @Test
public void playTest() throws Exception {
logger.info("start playTest");
SourceDataLine audioLine = null;
MediaAudio samples = beepSamples();
logger.info("sample is ready");
AudioFormat format = new AudioFormat((float)samples.getSampleRate(), (int)samples.getBytesPerSample() * 8, samples.getChannels(), true, false);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
audioLine = (SourceDataLine)AudioSystem.getLine(info);
audioLine.open(format);
logger.info("beepstart");
audioLine.start();
Buffer buffer = samples.getData(0);
audioLine.write(buffer.getByteArray(0, samples.getDataPlaneSize(0)), 0, samples.getDataPlaneSize(0));
audioLine.drain();
logger.info("beepend");
audioLine.close();
audioLine = null;
}
// @Test
public void flvNellymoserTest() throws Exception {
logger.info("flvNellymoserTest");
Muxer muxer = Muxer.make("flv_nellymoser.flv", null, null);
Encoder encoder = Encoder.make(Codec.findEncodingCodec(Codec.ID.CODEC_ID_NELLYMOSER));
Type findType = null;
for(Type type : encoder.getCodec().getSupportedAudioFormats()) {
logger.info(type);
if(findType == null) {
findType = type;
}
if(type == Type.SAMPLE_FMT_S16) {
findType = type;
break;
}
}
logger.info(findType);
encoder.setSampleRate(44100);
encoder.setChannels(1);
encoder.setChannelLayout(Layout.CH_LAYOUT_MONO);
encoder.setSampleFormat(findType);
encoder.setFlag(Flag.FLAG_GLOBAL_HEADER, true);
encoder.open(null, null);
muxer.addNewStream(encoder);
processConvert(muxer, encoder);
logger.info("done");
}
// @Test
public void oggVorbisTest() throws Exception {
logger.info("oggVorbisTest");
Muxer muxer = Muxer.make("ogg_vorbis.ogg", null, null);
Encoder encoder = Encoder.make(Codec.findEncodingCodec(Codec.ID.CODEC_ID_VORBIS));
Type findType = null;
for(Type type : encoder.getCodec().getSupportedAudioFormats()) {
logger.info(type);
if(findType == null) {
findType = type;
}
if(type == Type.SAMPLE_FMT_S16) {
findType = type;
break;
}
}
logger.info(findType);
encoder.setSampleRate(44100);
encoder.setChannels(2);
encoder.setChannelLayout(Layout.CH_LAYOUT_STEREO);
encoder.setSampleFormat(findType);
encoder.setFlag(Flag.FLAG_GLOBAL_HEADER, true);
encoder.open(null, null);
muxer.addNewStream(encoder);
processConvert(muxer, encoder);
logger.info("done");
}
// @Test
public void flvMp3Test() throws Exception {
logger.info("flvMp3Test");
Muxer muxer = Muxer.make("flvMp3.flv", null, null);
Encoder encoder = Encoder.make(Codec.findEncodingCodec(Codec.ID.CODEC_ID_MP3));
Type findType = null;
for(Type type : encoder.getCodec().getSupportedAudioFormats()) {
logger.info(type);
if(findType == null) {
findType = type;
}
if(type == Type.SAMPLE_FMT_S16) {
findType = type;
break;
}
}
logger.info(findType);
encoder.setSampleRate(44100);
encoder.setChannels(2);
encoder.setChannelLayout(Layout.CH_LAYOUT_STEREO);
encoder.setSampleFormat(findType);
encoder.setFlag(Flag.FLAG_GLOBAL_HEADER, true);
encoder.open(null, null);
muxer.addNewStream(encoder);
processConvert(muxer, encoder);
logger.info("done");
}
private void processConvert(Muxer muxer, Encoder encoder) throws Exception {
muxer.open(null, null);
MediaPacket packet = MediaPacket.make();
MediaAudio samples = beepSamples();
logger.info(samples);
if(samples.getSampleRate() != encoder.getSampleRate()
|| samples.getFormat() != encoder.getSampleFormat()
|| samples.getChannelLayout() != encoder.getChannelLayout()) {
MediaAudioResampler resampler = MediaAudioResampler.make(
encoder.getChannelLayout(), encoder.getSampleRate(), encoder.getSampleFormat(),
samples.getChannelLayout(), samples.getSampleRate(), samples.getFormat());
resampler.open();
MediaAudio spl = MediaAudio.make(samples.getNumSamples(), encoder.getSampleRate(), encoder.getChannels(), encoder.getChannelLayout(), encoder.getSampleFormat());
resampler.resample(spl, samples);
logger.info(spl);
logger.info(spl.getNumSamples());
samples = spl;
}
logger.info(samples);
while(true) {
// need to resample.
encoder.encodeAudio(packet, samples);
if(!packet.isComplete()) {
break;
}
logger.info(packet);
muxer.write(packet, false);
}
muxer.close();
}
/**
* resample MediaAudio from non planed buffer to planed buffer.
* (ex: S16 -> S16P)
* @param input
* @return
*/
public MediaAudio resample(MediaAudio input) {
return null;
}
/**
* make sine wave humble MediaAudio.
* @return
*/
private MediaAudio beepSamples() {
int sampleRate = 44100; // 44.1KHz
int sampleNum = 44100; // 44100 samples(1sec)
int channel = 2; // 2channel(stereo)
int tone = 440; // 440Hz tone.
int bit = 16; // 16bit
ByteBuffer buffer = ByteBuffer.allocate((int)sampleNum * bit * channel / 8);
double rad = tone * 2 * Math.PI / sampleRate; // radian for each sample.
double max = (1 << (bit - 2)) - 1; // ampletude
buffer.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0;i < sampleNum;i ++) {
short data = (short)(Math.sin(rad * i) * max);
for(int j = 0;j < channel;j ++) {
buffer.putShort(data);
}
}
buffer.flip();
logger.info("data size for 1sec buffer.:" + buffer.remaining());
MediaAudio samples = MediaAudio.make(sampleNum, sampleRate, channel, Layout.CH_LAYOUT_STEREO, Type.SAMPLE_FMT_S16);
samples.getData(0).put(buffer.array(), 0, 0, buffer.remaining());
logger.info(samples.getDataPlaneSize(0)); // why this size is little bit bigger than original buffer?
samples.setComplete(true);
samples.setTimeBase(Rational.make(1, 44100));
samples.setTimeStamp(0);
samples.setNumSamples(sampleNum);
return samples;
}
}