examples.be.tarsos.dsp.example.Spectrogram 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.example;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import be.tarsos.dsp.AudioDispatcher;
import be.tarsos.dsp.AudioEvent;
import be.tarsos.dsp.AudioProcessor;
import be.tarsos.dsp.io.jvm.AudioDispatcherFactory;
import be.tarsos.dsp.io.jvm.AudioPlayer;
import be.tarsos.dsp.io.jvm.JVMAudioInputStream;
import be.tarsos.dsp.pitch.PitchDetectionHandler;
import be.tarsos.dsp.pitch.PitchDetectionResult;
import be.tarsos.dsp.pitch.PitchProcessor;
import be.tarsos.dsp.pitch.PitchProcessor.PitchEstimationAlgorithm;
import be.tarsos.dsp.util.fft.FFT;
public class Spectrogram extends JFrame implements PitchDetectionHandler {
/**
*
*/
private static final long serialVersionUID = 1383896180290138076L;
private final SpectrogramPanel panel;
private AudioDispatcher dispatcher;
private Mixer currentMixer;
private PitchEstimationAlgorithm algo;
private double pitch;
private float sampleRate = 44100;
private int bufferSize = 1024 * 4;
private int overlap = 768 * 4 ;
private String fileName;
private ActionListener algoChangeListener = new ActionListener(){
@Override
public void actionPerformed(final ActionEvent e) {
String name = e.getActionCommand();
PitchEstimationAlgorithm newAlgo = PitchEstimationAlgorithm.valueOf(name);
algo = newAlgo;
try {
setNewMixer(currentMixer);
} catch (LineUnavailableException e1) {
e1.printStackTrace();
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
}
}};
public Spectrogram(String fileName){
this.setLayout(new BorderLayout());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Spectrogram");
panel = new SpectrogramPanel();
algo = PitchEstimationAlgorithm.DYNAMIC_WAVELET;
this.fileName = fileName;
JPanel pitchDetectionPanel = new PitchDetectionPanel(algoChangeListener);
JPanel inputPanel = new InputPanel();
inputPanel.addPropertyChangeListener("mixer",
new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent arg0) {
try {
setNewMixer((Mixer) arg0.getNewValue());
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
JPanel containerPanel = new JPanel(new GridLayout(1,0));
containerPanel.add(inputPanel);
containerPanel.add(pitchDetectionPanel);
this.add(containerPanel,BorderLayout.NORTH);
JPanel otherContainer = new JPanel(new BorderLayout());
otherContainer.add(panel,BorderLayout.CENTER);
otherContainer.setBorder(new TitledBorder("3. Utter a sound (whistling works best)"));
this.add(otherContainer,BorderLayout.CENTER);
}
private void setNewMixer(Mixer mixer) throws LineUnavailableException, UnsupportedAudioFileException {
if(dispatcher!= null){
dispatcher.stop();
}
if(fileName == null){
final AudioFormat format = new AudioFormat(sampleRate, 16, 1, true,
false);
final DataLine.Info dataLineInfo = new DataLine.Info(
TargetDataLine.class, format);
TargetDataLine line;
line = (TargetDataLine) mixer.getLine(dataLineInfo);
final int numberOfSamples = bufferSize;
line.open(format, numberOfSamples);
line.start();
final AudioInputStream stream = new AudioInputStream(line);
JVMAudioInputStream audioStream = new JVMAudioInputStream(stream);
// create a new dispatcher
dispatcher = new AudioDispatcher(audioStream, bufferSize,
overlap);
} else {
try {
File audioFile = new File(fileName);
dispatcher = AudioDispatcherFactory.fromFile(audioFile, bufferSize, overlap);
AudioFormat format = AudioSystem.getAudioFileFormat(audioFile).getFormat();
dispatcher.addAudioProcessor(new AudioPlayer(format));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
currentMixer = mixer;
// add a processor, handle pitch event.
dispatcher.addAudioProcessor(new PitchProcessor(algo, sampleRate, bufferSize, this));
dispatcher.addAudioProcessor(fftProcessor);
// run the dispatcher (on a new thread).
new Thread(dispatcher,"Audio dispatching").start();
}
AudioProcessor fftProcessor = new AudioProcessor(){
FFT fft = new FFT(bufferSize);
float[] amplitudes = new float[bufferSize/2];
@Override
public void processingFinished() {
// TODO Auto-generated method stub
}
@Override
public boolean process(AudioEvent audioEvent) {
float[] audioFloatBuffer = audioEvent.getFloatBuffer();
float[] transformbuffer = new float[bufferSize*2];
System.arraycopy(audioFloatBuffer, 0, transformbuffer, 0, audioFloatBuffer.length);
fft.forwardTransform(transformbuffer);
fft.modulus(transformbuffer, amplitudes);
panel.drawFFT(pitch, amplitudes,fft);
panel.repaint();
return true;
}
};
@Override
public void handlePitch(PitchDetectionResult pitchDetectionResult,AudioEvent audioEvent) {
if(pitchDetectionResult.isPitched()){
pitch = pitchDetectionResult.getPitch();
} else {
pitch = -1;
}
}
public static void main(final String... strings) throws InterruptedException,
InvocationTargetException {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager
.getSystemLookAndFeelClassName());
} catch (Exception e) {
// ignore failure to set default look en feel;
}
JFrame frame = strings.length == 0 ? new Spectrogram(null) : new Spectrogram(strings[0]) ;
frame.pack();
frame.setSize(640, 480);
frame.setVisible(true);
}
});
}
}