/*
* Mobicents, Communications Middleware
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party
* contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
*
* Boston, MA 02110-1301 USA
*/
package org.mobicents.media.server.impl.resource.test;
import java.io.IOException;
import org.mobicents.media.Buffer;
import org.mobicents.media.Format;
import org.mobicents.media.server.impl.AbstractSink;
import org.mobicents.media.server.spi.dsp.Codec;
/**
*
* @author kulikov
*/
public class MeanderDetector extends AbstractSink {
private final static Format[] FORMATS = new Format[]{Codec.LINEAR_AUDIO};
private int sampleRate;
private double T;
private short A;
private short[] localBuffer;
private int size;
private int offset;
private int count;
private long seq;
public MeanderDetector(String name) {
super(name);
sampleRate = (int)Codec.LINEAR_AUDIO.getSampleRate();
}
public void setPeriod(double T) {
this.T = T/2;
//preparing local buffer
//we have to hold at least 3-4 periods of data for analysis
size = (int)(sampleRate * this.T);
localBuffer = new short[4*size];
}
public void setAmplitude(short A) {
this.A = A;
}
public Format[] getFormats() {
return FORMATS;
}
public boolean isAcceptable(Format format) {
return format.matches(Codec.LINEAR_AUDIO);
}
@Override
public void start() {
seq = 0;
super.start();
}
private boolean checkShock(short a, short b) {
if (a == 0) {
return b == A;
} else if (a == A) {
return b == 0;
}
return false;
}
private void analysis() {
int p1 = 0;
for (int i = 0; i < localBuffer.length - 1; i++) {
if (localBuffer[i] != localBuffer[i+1]) {
int delta = i - p1;
p1 = i;
if (Math.abs(delta - size ) < 2) {
count++;
if (count == 3 && checkShock(localBuffer[i], localBuffer[i+1])) {
count = 0;
sendEvent(new MeanderEvent(this, MeanderEvent.EVENT_MEANDER));
break;
}
}
}
}
}
public void onMediaTransfer(Buffer buffer) throws IOException {
//checking sequence number
if (seq != 0 && (buffer.getSequenceNumber() - seq) != 1) {
sendEvent(new MeanderEvent(this, MeanderEvent.EVENT_OUT_OF_SEQUENCE));
}
seq = buffer.getSequenceNumber();
if (!buffer.getFormat().matches(Codec.LINEAR_AUDIO)) {
sendEvent(new MeanderEvent(this, MeanderEvent.EVENT_FORMAT_MISSMATCH));
}
//checking data
byte[] data = (byte[]) buffer.getData();
for (int i = 0; i < buffer.getLength() - 1; i += 2) {
if (offset < localBuffer.length) {
localBuffer[offset++] = (short)((data[i] & 0xff) | (data[i+1] << 8));
} else {
analysis();
offset = 0;
}
}
}
}