package org.jcodec.samples.audio;
import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.HashMap;
import org.jcodec.audio.Audio;
import org.jcodec.audio.AudioSource;
import org.jcodec.codecs.wav.WavOutput;
import org.jcodec.codecs.wav.WavOutput.Sink;
import org.jcodec.codecs.wav.WavOutput.WavOutFile;
import org.jcodec.common.AudioFormat;
import org.jcodec.common.tools.MainUtils;
import org.jcodec.common.tools.MainUtils.Cmd;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Illustrates work with Wave files
*
* @author The JCodec project
*
*/
public class ToneGen {
public static void main(String[] args) throws IOException {
Cmd cmd = MainUtils.parseArguments(args);
if (cmd.args.length < 1) {
MainUtils.printHelpVarArgs(new HashMap<String, String>() {
{
put("freq", "Frequency of tone");
put("channels", "Number of channels");
}
}, "filename");
System.exit(-1);
}
int channels = cmd.getIntegerFlagD("channels", 1);
int[] freq = cmd.getMultiIntegerFlagD("freq", new int[] { 500 });
ToneSource tone = new ToneSource(channels, freq);
WavOutFile wavOutFile = new WavOutput.WavOutFile(new File(cmd.getArg(0)), tone.getFormat());
Sink wavOutput = new WavOutput.Sink(wavOutFile);
Audio.transfer(tone, wavOutput);
wavOutput.close();
}
public static class ToneSource implements AudioSource {
private double[] coeff;
private double[] mul;
private int[] sample;
private int[] freq;
private int channels;
public ToneSource(int channels, int[] freq) {
this.freq = freq;
this.channels = channels;
coeff = new double[freq.length];
mul = new double[freq.length];
sample = new int[channels];
for (int i = 0; i < coeff.length; i++) {
coeff[i] = 2 * Math.PI * freq[i] / 48000;
mul[i] = .5 / (1 << i);
}
for (int i = 0; i < sample.length; i++) {
sample[i] = i * (freq[0] / sample.length);
}
}
@Override
public int readFloat(FloatBuffer buffer) throws IOException {
if (sample[0] > 480000)
return -1;
int rem = buffer.remaining();
while (buffer.hasRemaining()) {
for (int ch = 0; ch < channels; ch++) {
double result = 0;
for (int fi = 0; fi < freq.length; fi++)
result += (float) (Math.sin(sample[ch] * coeff[fi]) * mul[fi]);
++sample[ch];
buffer.put((float) result);
}
}
return buffer.remaining() - rem;
}
@Override
public AudioFormat getFormat() {
return AudioFormat.NCH_48K_S16_LE(channels);
}
}
}