package org.mobicents.media.server.impl.resource.tone;
import java.io.IOException;
import org.apache.log4j.Logger;
import org.mobicents.media.Buffer;
import org.mobicents.media.Format;
import org.mobicents.media.server.impl.AbstractSink;
import org.mobicents.media.server.impl.resource.GoertzelFilter;
import org.mobicents.media.server.spi.dsp.Codec;
import org.mobicents.media.server.spi.resource.FrequencyBean;
import org.mobicents.media.server.spi.resource.MultiFreqToneDetector;
/**
*
* @author amit.bhayani
*
*/
public class MultiFreqToneDetectorImpl extends AbstractSink implements MultiFreqToneDetector {
private static transient Logger logger = Logger.getLogger(MultiFreqToneDetectorImpl.class);
private final static int STATE_IDLE = 0;
private final static int STATE_SIGNAL = 1;
private final static int STATE_SILENCE = 2;
private int POWER = 10000;
private int state = STATE_IDLE;
private final static double E = 100;
private final static int PACKET_DURATION = 50;
private final static Format[] FORMATS = new Format[] { Codec.LINEAR_AUDIO };
private int offset;
private int toneDuration = PACKET_DURATION;
private int N = 8 * toneDuration;
private double scale = (double) toneDuration / (double) 1000;
private GoertzelFilter[] freqFilters;
private double[] signal;
private double maxAmpl;
private int level = -30;
private double threshold = Math.pow(Math.pow(10, level), 0.1) * Short.MAX_VALUE;
private double p[];
private FrequencyBean freqBean;
private MultiFreqToneEvent event;
public MultiFreqToneDetectorImpl(String name) {
super(name);
event = new MultiFreqToneEvent(this);
}
public void onMediaTransfer(Buffer buffer) throws IOException {
byte[] data = (byte[]) buffer.getData();
int M = buffer.getOffset() + buffer.getLength();
int k = buffer.getOffset();
while (k < M) {
while (offset < N && k < M - 1) {
double s = ((data[k++] & 0xff) | (data[k++] << 8));
double sa = Math.abs(s);
if (sa > maxAmpl) {
maxAmpl = sa;
}
signal[offset++] = s;
}
// if dtmf buffer full check signal
if (offset == N) {
System.out.println("buffer full maxAmpl = " + maxAmpl);
offset = 0;
// and if max amplitude of signal is greater theshold
// try to detect tone.
if (maxAmpl >= threshold) {
maxAmpl = 0;
getPower(freqFilters, signal, 0, p);
if (isDetected()) {
notifySignal();
}
}
}
}
}
private void notifySignal() {
sendEvent(event);
this.stop();
}
private boolean isDetected() {
for (double P : p) {
System.out.println("POWER =" + P);
if (P <= POWER) {
return false;
}
}
return true;
}
private void getPower(GoertzelFilter[] filters, double[] data, int offset, double[] power) {
for (int i = 0; i < filters.length; i++) {
power[i] = filters[i].getPower(data, offset);
}
}
/**
* (Non Java-doc.)
*
* @see org.mobicents.media.MediaSink.isAcceptable(Format).
*/
public boolean isAcceptable(Format fmt) {
return fmt.matches(Codec.LINEAR_AUDIO);
}
public Format[] getFormats() {
return FORMATS;
}
public FrequencyBean getFreqBean() {
return freqBean;
}
public void setFreqBean(FrequencyBean freqBean) {
this.freqBean = freqBean;
this.signal = new double[N];
freqFilters = new GoertzelFilter[2];
p = new double[2];
freqFilters[0] = new GoertzelFilter(freqBean.getLowFreq(), N, scale);
freqFilters[1] = new GoertzelFilter(freqBean.getHighFreq(), N, scale);
}
public int getVolume() {
return level;
}
public void setVolume(int level) {
this.level = level;
threshold = Math.pow(Math.pow(10, level), 0.1) * Short.MAX_VALUE;
}
}