/*
* 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.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import org.mobicents.media.MediaSink;
import org.mobicents.media.MediaSource;
import org.mobicents.media.server.impl.resource.fft.SpectraAnalyzer;
import org.mobicents.media.server.impl.resource.fft.SpectrumEvent;
import org.mobicents.media.server.spi.NotificationListener;
import org.mobicents.media.server.spi.Timer;
import org.mobicents.media.server.spi.events.FailureEvent;
import org.mobicents.media.server.spi.events.NotifyEvent;
/**
* This class is used for testing transmission.
* The carrier signal is a single frequency sine.
*
* @author kulikov
*/
public class TransmissionTester2 implements NotificationListener {
private final static int TEST_DURATION = 10;
private int MAX_ERRORS = 1;
private final static int FREQ_ERROR = 5;
private final static short A = 1000;
private final static int f = 150;
private SineGenerator gen;
private SpectraAnalyzer det;
private MediaSink sink;
private MediaSource source;
private ArrayList<double[]> s = new ArrayList();
private boolean isPassed = false;
private String msg = "Not started yet";
private Semaphore semaphore = new Semaphore(0);
public TransmissionTester2(Timer timer) {
gen = new SineGenerator("sine.generator", timer);
gen.setAmplitude(A);
gen.setFrequency(f);
det = new SpectraAnalyzer("spectra.analyzer");
det.addListener(this);
gen.addListener(this);
}
public SineGenerator getGenerator() {
return gen;
}
public SpectraAnalyzer getDetector() {
return det;
}
public void connect(MediaSink sink) {
this.sink = sink;
gen.connect(sink);
}
public void connect(MediaSource source) {
this.source = source;
det.connect(source);
}
@SuppressWarnings("static-access")
public void start() {
s.clear();
det.start();
gen.start();
isPassed = true;
try {
semaphore.tryAcquire(TEST_DURATION, TimeUnit.SECONDS);
} catch (InterruptedException e) {
msg = "Test interrupted";
return;
}
gen.stop();
det.stop();
if (sink != null) {
gen.disconnect(sink);
}
if (source != null) {
det.disconnect(source);
}
try {
Thread.currentThread().sleep(1000);
} catch (Exception e) {
}
if (!isPassed) {
return;
}
isPassed = verify(s, new int[]{f});
}
private boolean verify(ArrayList<double[]> spectra, int[] F) {
int errorCount = 0;
if (spectra.size() == 0) {
msg = "Data not received";
return false;
}
for (double[] ss : spectra) {
int[] ext = getFreq(ss);
if (ext.length == 0) {
msg = "Received silence [" + spectra.size() + " seconds]";
return false;
}
boolean r = checkFreq(ext, F, FREQ_ERROR);
if (!r) {
errorCount++;
}
}
return (errorCount <= MAX_ERRORS);
}
public boolean checkFreq(int[] ext, int[] F, int error) {
for (int i = 0; i < F.length; i++) {
if (Math.abs(ext[i] - F[i]) > error) {
msg = "Expected " + F[i] + " but found " + ext[i];
return false;
}
}
return true;
}
public int[] getFreq(double[] s) {
double max = findMax(s);
int len = s.length / 2;
double ss[] = new double[len];
for (int i = 0; i < len; i++) {
ss[i] = s[i] / max;
ss[i] = ss[i] < 0.7 ? 0 : ss[i];
}
double[] diff = diff(ss);
int[] ext = findExtremums(diff);
return ext;
}
private double[] diff(double[] f) {
double[] diff = new double[f.length];
for (int i = 0; i < f.length - 1; i++) {
diff[i] = f[i + 1] - f[i];
}
return diff;
}
private double findMax(double[] f) {
double max = f[0];
for (int i = 1; i < f.length; i++) {
max = Math.max(max, f[i]);
}
return max;
}
private int[] findExtremums(double[] f) {
List<Integer> ext = new ArrayList();
for (int i = 0; i < f.length - 1; i++) {
if (f[i] > 0 && f[i + 1] < 0) {
ext.add(i);
}
}
int[] res = new int[ext.size()];
for (int i = 0; i < res.length; i++) {
res[i] = ext.get(i);
}
return res;
}
public boolean isPassed() {
return isPassed;
}
public String getMessage() {
return msg;
}
public void update(NotifyEvent event) {
if (event.getEventID() == SpectrumEvent.SPECTRA) {
SpectrumEvent evt = (SpectrumEvent) event;
s.add(evt.getSpectra());
} else if (event.getEventID() == NotifyEvent.TX_FAILED) {
isPassed = false;
msg = "Transmission error: " + ((FailureEvent)event).getSource();
((FailureEvent)event).getException().printStackTrace();
semaphore.release();
}
}
}