All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tests.be.tarsos.dsp.test.GoertzelTest Maven / Gradle / Ivy

The newest version!
/*
*      _______                       _____   _____ _____  
*     |__   __|                     |  __ \ / ____|  __ \ 
*        | | __ _ _ __ ___  ___  ___| |  | | (___ | |__) |
*        | |/ _` | '__/ __|/ _ \/ __| |  | |\___ \|  ___/ 
*        | | (_| | |  \__ \ (_) \__ \ |__| |____) | |     
*        |_|\__,_|_|  |___/\___/|___/_____/|_____/|_|     
*                                                         
* -------------------------------------------------------------
*
* TarsosDSP is developed by Joren Six at IPEM, University Ghent
*  
* -------------------------------------------------------------
*
*  Info: http://0110.be/tag/TarsosDSP
*  Github: https://github.com/JorenSix/TarsosDSP
*  Releases: http://0110.be/releases/TarsosDSP/
*  
*  TarsosDSP includes modified source code by various authors,
*  for credits and info, see README.
* 
*/


package be.tarsos.dsp.test;

import static org.junit.Assert.assertEquals;

import java.io.ByteArrayInputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

import org.junit.Test;

import be.tarsos.dsp.AudioDispatcher;
import be.tarsos.dsp.io.TarsosDSPAudioFloatConverter;
import be.tarsos.dsp.io.TarsosDSPAudioFormat;
import be.tarsos.dsp.io.jvm.JVMAudioInputStream;
import be.tarsos.dsp.pitch.DTMF;
import be.tarsos.dsp.pitch.Goertzel;
import be.tarsos.dsp.pitch.Goertzel.FrequenciesDetectedHandler;

public class GoertzelTest {
	
	/**
	 * Generate a buffer with one sine wave.
	 * 
	 * @param f0
	 *            the frequency of the sine wave;
	 * @param size
	 *            the size of the buffer in samples.
	 * @return a buffer (float array) with audio information for the sine wave.
	 */
	public static float[] testAudioBufferSine(final double f0, int size) {
		final double sampleRate = 44100.0;
		final double amplitudeF0 = 1.0;
		final float[] buffer = new float[size];
		for (int sample = 0; sample < buffer.length; sample++) {
			final double time = sample / sampleRate;
			buffer[sample] = (float) (amplitudeF0 * Math.sin(2 * Math.PI * f0
					* time));
		}
		return buffer;
	}

	/**
	 * Append float buffers to form one big float buffer.
	 * 
	 * @param floatBuffers
	 *            The float buffers to append.
	 * @return An appended float buffer with all the information in the array of
	 *         buffers.
	 */
	public static float[] appendBuffers(final float[]...floatBuffers){
		int size = 0;
		for(int i = 0 ; i < floatBuffers.length ; i ++){
			size += floatBuffers[i].length;
		}
		final float[] floatBuffer = new float[size];
		int index = 0;
		for(int i = 0 ; i < floatBuffers.length; i ++){			
			for(int j = 0 ; j < floatBuffers[i].length ; j++){
				floatBuffer[index] = floatBuffers[i][j];
				index++;
			}
		}
		return floatBuffer;
	}
	
	
	/**
	 * Test detection of a simple sine wave (one frequency).
	 * @throws LineUnavailableException
	 * @throws UnsupportedAudioFileException
	 */
	@Test
	public void testDetection() throws LineUnavailableException, UnsupportedAudioFileException{
		
		final float[][] floatSinBuffers = {testAudioBufferSine(6000,10240),testAudioBufferSine(2000,10240),testAudioBufferSine(4000,10240)};
		final float[] floatBuffer = appendBuffers(floatSinBuffers);
		final TarsosDSPAudioFormat format = new TarsosDSPAudioFormat(44100, 16, 1, true, false);
		final TarsosDSPAudioFloatConverter converter = TarsosDSPAudioFloatConverter.getConverter(format);
		final byte[] byteBuffer = new byte[floatBuffer.length * format.getFrameSize()];
		assertEquals("Specified 16 bits so framesize should be 2.", 2, format.getFrameSize());
		converter.toByteArray(floatBuffer, byteBuffer);
		final ByteArrayInputStream bais = new ByteArrayInputStream(byteBuffer);
		final AudioInputStream inputStream = new AudioInputStream(bais, JVMAudioInputStream.toAudioFormat(format),floatBuffer.length);
		JVMAudioInputStream stream = new JVMAudioInputStream(inputStream);
		final AudioDispatcher dispatcher = new AudioDispatcher(stream, 1024, 0);
		
		double[] frequencies = {6000,3000,5000,5800,6500};
		
        dispatcher.addAudioProcessor(new Goertzel(44100,1024,frequencies,new FrequenciesDetectedHandler() {
			@Override
			public void handleDetectedFrequencies(double time,final double[] frequencies, final double[] powers, final double[] allFrequencies, final double allPowers[]) {
				assertEquals("Should only detect 6000 Hz",(int)frequencies[0],6000);
			}
		}));
        //dispatcher.addAudioProcessor(new BlockingAudioPlayer(format,1024, 0));
        dispatcher.run();
	}
	
	/**
	 * Test detection of multiple frequencies.
	 * @throws LineUnavailableException
	 * @throws UnsupportedAudioFileException
	 */
	@Test
	public void testDTMF() throws LineUnavailableException, UnsupportedAudioFileException{
		
		final float[][] floatSinBuffers = {DTMF.generateDTMFTone('1'),DTMF.generateDTMFTone('2'),DTMF.generateDTMFTone('3'),DTMF.generateDTMFTone('4'),DTMF.generateDTMFTone('5'),DTMF.generateDTMFTone('6'),DTMF.generateDTMFTone('7'),DTMF.generateDTMFTone('8'),DTMF.generateDTMFTone('9')};
		final float[] floatBuffer = appendBuffers(floatSinBuffers);
		final int stepSize = 512;
		final AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
		final TarsosDSPAudioFloatConverter converter = TarsosDSPAudioFloatConverter.getConverter(JVMAudioInputStream.toTarsosDSPFormat(format));
		final byte[] byteBuffer = new byte[floatBuffer.length * format.getFrameSize()];
		assertEquals("Specified 16 bits so framesize should be 2.", 2, format.getFrameSize());
		converter.toByteArray(floatBuffer, byteBuffer);
		final ByteArrayInputStream bais = new ByteArrayInputStream(byteBuffer);
		final AudioInputStream inputStream = new AudioInputStream(bais, format,floatBuffer.length);
		JVMAudioInputStream stream = new JVMAudioInputStream(inputStream);
		final AudioDispatcher dispatcher = new AudioDispatcher(stream, stepSize, 0);
		final StringBuilder data = new StringBuilder();
		dispatcher.addAudioProcessor(new Goertzel(44100, stepSize,
				DTMF.DTMF_FREQUENCIES, new FrequenciesDetectedHandler() {
					
					@Override
					public void handleDetectedFrequencies(double time,
							final double[] frequencies, final double[] powers, final double[] allFrequencies, final double allPowers[]) {
						// assertEquals("Should detect 2 frequencies.",2,frequencies.length);
						assertEquals(
								"Number of frequencies should be the same as the number of powers.",
								frequencies.length, powers.length);
						if (frequencies.length == 2) {
							int rowIndex = -1;
							int colIndex = -1;
							for (int i = 0; i < 4; i++) {
								if (frequencies[0] == DTMF.DTMF_FREQUENCIES[i] || frequencies[1] == DTMF.DTMF_FREQUENCIES[i])
									rowIndex = i;
							}
							for (int i = 4; i < DTMF.DTMF_FREQUENCIES.length; i++) {
								if (frequencies[0] == DTMF.DTMF_FREQUENCIES[i] || frequencies[1] == DTMF.DTMF_FREQUENCIES[i])
									colIndex = i-4;
							}
							if(rowIndex>=0 && colIndex>=0){
								char character = DTMF.DTMF_CHARACTERS[rowIndex][colIndex];
								if(data.length()==0 || character != data.charAt(data.length()-1)){
									data.append(character);
								}
							}
						}
					}
				}));
		//dispatcher.addAudioProcessor(new BlockingAudioPlayer(format, stepSize, 0));
		dispatcher.run();
		assertEquals("Decoded string should be 123456789", "123456789", data.toString());
		assertEquals("Length should be 9", 9, data.length());
		
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy