/* * JBoss, Home of Professional Open Source * Copyright 2011, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.restcomm.media.component.audio; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import org.restcomm.media.ComponentType; import org.restcomm.media.component.AbstractSink; import org.restcomm.media.scheduler.PriorityQueueScheduler; import org.restcomm.media.spi.format.AudioFormat; import org.restcomm.media.spi.format.FormatFactory; import org.restcomm.media.spi.format.Formats; import org.restcomm.media.spi.memory.Frame; /** * * @author yulian oifa */ public class SpectraAnalyzer extends AbstractSink { private static final long serialVersionUID = 1646539542777368667L; private final static int tolerance = 5; private final static AudioFormat LINEAR_AUDIO = FormatFactory.createAudioFormat("LINEAR", 8000, 16, 1); private final static Formats formats = new Formats(); //more then 10 seconds private double[] buffer = new double[81920]; private volatile int len; private double pow[]; private FFT fft = new FFT(); private Resampler resampler = new Resampler(8000, 8192); static { formats.add(LINEAR_AUDIO); } private AudioOutput output; public SpectraAnalyzer(String name,PriorityQueueScheduler scheduler) { super(name); output=new AudioOutput(scheduler,ComponentType.SPECTRA_ANALYZER.getType()); output.join(this); } public AudioOutput getAudioOutput() { return this.output; } public void activate() { this.len = 0; System.out.println("start, len=" + len); output.start(); } public void deactivate() { output.stop(); } private double[] mod(Complex[] x) { double[] res = new double[x.length]; for (int i = 0; i < res.length; i++) { res[i] = Math.sqrt(x[i].re() * x[i].re() + x[i].im() * x[i].im()); } return res; } public void onMediaTransfer(Frame frame) throws IOException { byte[] data = frame.getData(); int j = 0; for (int i = 0; i < (frame.getLength() / 2) && len < buffer.length; i++) { buffer[len++] = (data[j++] & 0xff) | (data[j++] << 8); // System.out.println(buffer[len-1]); } } private double[] derivative(double[] spectra) { double[] res = new double[spectra.length / 2 - 1]; for (int i = 0; i < res.length; i++) { res[i] = spectra[i + 1] - spectra[i]; } return res; } private int[] findPeaks(double[] data) { ArrayList<Integer> peaks = new ArrayList<Integer>(); for (int i = 0; i < data.length; i++) { if (data[i] > 10000000) peaks.add(i); } int[] res = new int[peaks.size()]; for (int i = 0; i < res.length; i++) { res[i] = peaks.get(i); } return res; } private void append(ArrayList<Integer> list, int v) { boolean found = false; for (int i : list) { if (Math.abs(i - v) <= tolerance) { found = true; break; } } if (!found) list.add(v); } public int[] getSpectra() { ArrayList<Integer> frequency = new ArrayList<Integer>(); System.out.println("len=" + len); int count = len / 8000; for (int i = 0; i < count; i++) { double[] data = new double[8000]; System.arraycopy(buffer, 8000 * i, data, 0, 8000); double s[] = resampler.perform(data, 8000); Complex[] signal = new Complex[8192]; for (int j = 0; j < 8192; j++) { signal[j] = new Complex(s[j], 0); } Complex[] sp = fft.fft(signal); pow = mod(sp); double[] dif = this.derivative(pow); int[] freqs = this.findPeaks(dif); for (int k = 0; k < freqs.length; k++) { append(frequency, freqs[k]); } } int[] res = new int[frequency.size()]; for (int i = 0; i < res.length; i++) { res[i] = frequency.get(i); } return res; } public void print(String fileName) throws FileNotFoundException, IOException { FileOutputStream fout = new FileOutputStream(fileName, false); for (int i = 0; i < len; i++) { fout.write((i + " " + buffer[i] + "\n").getBytes()); } fout.flush(); fout.close(); } public Formats getNativeFormats() { return formats; } }