package org.mobicents.media.server.impl.resource.tone;
import java.util.List;
import org.mobicents.media.Buffer;
import org.mobicents.media.Format;
import org.mobicents.media.format.AudioFormat;
import org.mobicents.media.server.impl.AbstractSource;
import org.mobicents.media.server.spi.SyncSource;
import org.mobicents.media.server.spi.resource.FrequencyBean;
import org.mobicents.media.server.spi.resource.MultiFreqToneGenerator;
/**
*
* @author amit bhayani
*
*/
public class MultiFreqToneGeneratorImpl extends AbstractSource implements MultiFreqToneGenerator {
private final static AudioFormat LINEAR_AUDIO = new AudioFormat(AudioFormat.LINEAR, 8000, 16, 1,
AudioFormat.LITTLE_ENDIAN, AudioFormat.SIGNED);
private double dt;
private int pSize;
private short A = (short)(Short.MAX_VALUE /2);
private int volume = 0;
private double time = 0;
private int count = 0;
private double totalDuration = 0;
private volatile List<FrequencyBean> frequencies;
public MultiFreqToneGeneratorImpl(String name, SyncSource syncSource) {
super(name);
setSyncSource(syncSource);
dt = 1 / LINEAR_AUDIO.getSampleRate();
}
@Override
public void beforeStart() throws Exception {
for (FrequencyBean freqBean : this.frequencies) {
this.totalDuration = this.totalDuration + freqBean.getDuration();
}
this.totalDuration = this.totalDuration / 1000.0;
this.time = 0;
this.count = 0;
}
public int getVolume() {
return this.volume;
}
public void setVolume(int volume) {
// if (volume > 0) {
// throw new IllegalArgumentException("Volume has to be negative value expressed in dBm0");
// }
this.volume = volume;
A = (short) (Math.pow(Math.pow(10, volume), 0.1) * (Short.MAX_VALUE / 2));
}
@Override
public void evolve(Buffer buffer, long timestamp, long seq) {
try {
byte[] data = (byte[]) buffer.getData();
int k = 0;
int tempDuration = 0;
for (FrequencyBean freqBean : frequencies) {
int lowFreq = freqBean.getLowFreq();
int highFreq = freqBean.getHighFreq();
int duration = freqBean.getDuration();
tempDuration = tempDuration + duration;
if (time < (tempDuration / 1000.0)) {
pSize = (int) ((double) getDuration() / 1000.0 / dt);
for (int i = 0; i < pSize; i++) {
short v;
if (lowFreq == 0 || highFreq == 0) {
v = 0;
} else {
v = getValue(time + dt * i, lowFreq, highFreq);
}
data[k++] = (byte) v;
data[k++] = (byte) (v >> 8);
}
buffer.setFormat(LINEAR_AUDIO);
buffer.setSequenceNumber(seq);
buffer.setTimeStamp(getSyncSource().getTimestamp());
buffer.setDuration(getDuration());
buffer.setOffset(0);
buffer.setLength(2 * pSize);
time += ((double) getDuration()) / 1000.0;
buffer.setEOM(false);
if (time >= totalDuration) {
time = 0.0;
}
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private short getValue(double t, int lowFreq, int highFreq) {
return (short) (A * (Math.sin(2 * Math.PI * lowFreq * t) + Math.sin(2 * Math.PI * highFreq * t)));
}
public Format[] getFormats() {
return new Format[] { LINEAR_AUDIO };
}
public List<FrequencyBean> getFreqBeanList() {
return this.frequencies;
}
public void setFreqBeanList(List<FrequencyBean> freqBeans) {
this.frequencies = freqBeans;
}
}