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

examples.be.tarsos.dsp.example.spectrum.FFTZoomGeneralizedGoertzel Maven / Gradle / Ivy

The newest version!
package be.tarsos.dsp.example.spectrum;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import be.tarsos.dsp.AudioEvent;
import be.tarsos.dsp.AudioProcessor;
import be.tarsos.dsp.example.constantq.Player;
import be.tarsos.dsp.example.constantq.Player.PlayerState;
import be.tarsos.dsp.ui.Axis;
import be.tarsos.dsp.ui.AxisUnit;
import be.tarsos.dsp.ui.CoordinateSystem;
import be.tarsos.dsp.ui.LinkedPanel;
import be.tarsos.dsp.ui.ViewPort;
import be.tarsos.dsp.ui.ViewPort.ViewPortChangedListener;
import be.tarsos.dsp.ui.layers.AmplitudeAxisLayer;
import be.tarsos.dsp.ui.layers.BackgroundLayer;
import be.tarsos.dsp.ui.layers.DragMouseListenerLayer;
import be.tarsos.dsp.ui.layers.LegendLayer;
import be.tarsos.dsp.ui.layers.MouseCursorLayer;
import be.tarsos.dsp.ui.layers.PitchContourLayer;
import be.tarsos.dsp.ui.layers.Scalogram;
import be.tarsos.dsp.ui.layers.SelectionLayer;
import be.tarsos.dsp.ui.layers.TimeAxisLayer;
import be.tarsos.dsp.ui.layers.TooltipLayer;
import be.tarsos.dsp.ui.layers.VerticalFrequencyAxisLayer;
import be.tarsos.dsp.ui.layers.WaveFormLayer;
import be.tarsos.dsp.ui.layers.ZoomMouseListenerLayer;

public class FFTZoomGeneralizedGoertzel extends JPanel{
	/**
	 * 
	 */
	private static final long serialVersionUID = 5689356875546643126L;
	
	JLabel progressLabel;
	JLabel totalLabel;
	
	//position value in the slider
	private int newPositionValue;
	
	JSlider positionSlider;
	
	final Player player;
	
	private LinkedPanel waveForm;
	private LinkedPanel timeFrequencyPane;
	private CoordinateSystem waveFormCS;
	private CoordinateSystem timeFrequencyPaneCS;
	

	final AudioProcessor processor = new AudioProcessor() {
		
		@Override
		public boolean process(AudioEvent audioEvent) {
			double timeStamp =  audioEvent.getTimeStamp();
			if(!positionSlider.getValueIsAdjusting()){
				newPositionValue = (int) (audioEvent.getProgress() * 1000);
				positionSlider.setValue(newPositionValue);
				setProgressLabelText(timeStamp,player.getDurationInSeconds());
			}
			return true;
		}
		
		@Override
		public void processingFinished() {
			
		}
	};

	
	public FFTZoomGeneralizedGoertzel(){
		this.setLayout(new BorderLayout());
		
	
		player = new Player(processor,1024,0);
		
		JPanel subPanel = new JPanel(new GridLayout(0,1));
		subPanel.add(createButtonPanel());
		subPanel.add(createProgressPanel());
		subPanel.add(createGainPanel());
		
		JComponent featurePanel =  createFeaturePanel();
		
		JComponent splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, subPanel,featurePanel);
		
		
		player.addPropertyChangeListener(new PropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent arg0) {
				if(arg0.getPropertyName()=="state"){
					PlayerState newState = (PlayerState) arg0.getNewValue();
					reactToPlayerState(newState);
				}
			}
		});
		reactToPlayerState(player.getState());
		
		this.add(splitPane);
	}
	
	private void reactToPlayerState(PlayerState newState){
		positionSlider.setEnabled(newState != PlayerState.NO_FILE_LOADED);
		if(newState == PlayerState.STOPPED || newState == PlayerState.FILE_LOADED){
			newPositionValue = 0;
			positionSlider.setValue(0);
			setProgressLabelText(0, player.getDurationInSeconds());
		}
		if(newState == PlayerState.FILE_LOADED){
	
			
			waveForm.removeLayers();
			waveForm.addLayer(new BackgroundLayer(waveFormCS));
			waveForm.addLayer(new AmplitudeAxisLayer(waveFormCS));
			waveForm.addLayer(new TimeAxisLayer(waveFormCS));
			waveForm.addLayer(new WaveFormLayer(waveFormCS, player.getLoadedFile()));
			waveForm.addLayer(new ZoomMouseListenerLayer());
			waveForm.addLayer(new DragMouseListenerLayer(waveFormCS));
			
			
			final MouseCursorLayer waveFormCursor = new MouseCursorLayer(waveFormCS);
			waveForm.addLayer(waveFormCursor);
			
			LegendLayer legend = new LegendLayer(waveFormCS,50);
			waveForm.addLayer(legend);
			legend.addEntry("Wave",Color.BLACK);
			
			timeFrequencyPane.removeLayers();
			timeFrequencyPane.addLayer(new BackgroundLayer(timeFrequencyPaneCS));
		//	timeFrequencyPane.addLayer(new GeneralizedGoertzelLayer(timeFrequencyPaneCS,player.getLoadedFile(),20));
			
			Scalogram fftLayer = new Scalogram(timeFrequencyPaneCS,player.getLoadedFile().getAbsolutePath());
			timeFrequencyPane.addLayer(fftLayer);
			MouseCursorLayer cl = new MouseCursorLayer(timeFrequencyPaneCS);
			timeFrequencyPane.addLayer(cl);
			
			
			timeFrequencyPane.addLayer(new PitchContourLayer(timeFrequencyPaneCS,player.getLoadedFile(),Color.red,2048,0));
			timeFrequencyPane.addLayer(new VerticalFrequencyAxisLayer(timeFrequencyPaneCS));
			timeFrequencyPane.addLayer(new ZoomMouseListenerLayer());
			timeFrequencyPane.addLayer(new DragMouseListenerLayer(timeFrequencyPaneCS));
			timeFrequencyPane.addLayer(new SelectionLayer(timeFrequencyPaneCS));
			timeFrequencyPane.addLayer(new TimeAxisLayer(timeFrequencyPaneCS));
			timeFrequencyPane.addLayer(new TooltipLayer(timeFrequencyPaneCS,fftLayer));
			
			legend = new LegendLayer(timeFrequencyPaneCS,110);
			timeFrequencyPane.addLayer(legend);
			legend.addEntry("ConstantQ",Color.BLACK);
			legend.addEntry("Pitch estimations",Color.RED);
			
			cl.addPropertyChangeListener(new PropertyChangeListener() {
				
				@Override
				public void propertyChange(PropertyChangeEvent evt) {
					if(evt.getPropertyName()=="cursor"){
						Point newPoint = (Point) evt.getNewValue();
						waveFormCursor.setPoint(newPoint);
					}
					
				}
			});
		}
	}
	
	private CoordinateSystem getCoordinateSystem(AxisUnit yUnits) {
		float minValue = -1000;
		float maxValue = 1000;
		if(yUnits == AxisUnit.FREQUENCY){
			minValue = 200;
			maxValue = 8000;
		}
		return new CoordinateSystem(yUnits, minValue, maxValue);
	}
	
	
	private JComponent createFeaturePanel() {
		JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
		
		waveFormCS = getCoordinateSystem(AxisUnit.AMPLITUDE);
		waveForm = new LinkedPanel(waveFormCS);
		waveForm.addLayer(new BackgroundLayer(waveFormCS));
		waveForm.addLayer(new AmplitudeAxisLayer(waveFormCS));
		waveForm.addLayer(new TimeAxisLayer(waveFormCS));
		waveForm.addLayer(new ZoomMouseListenerLayer());
		waveForm.addLayer(new DragMouseListenerLayer(waveFormCS));
		LegendLayer legend = new LegendLayer(waveFormCS,50);
		waveForm.addLayer(legend);
		legend.addEntry("Wave",Color.BLACK);
		
		splitPane.add(waveForm, JSplitPane.TOP);
		
		timeFrequencyPaneCS = getCoordinateSystem(AxisUnit.FREQUENCY);
		timeFrequencyPane = new LinkedPanel(timeFrequencyPaneCS);
		timeFrequencyPane.addLayer(new BackgroundLayer(timeFrequencyPaneCS));
		timeFrequencyPane.addLayer(new VerticalFrequencyAxisLayer(timeFrequencyPaneCS));
		timeFrequencyPane.addLayer(new TimeAxisLayer(timeFrequencyPaneCS));
		timeFrequencyPane.addLayer(new ZoomMouseListenerLayer());
		timeFrequencyPane.addLayer(new DragMouseListenerLayer(timeFrequencyPaneCS));
		timeFrequencyPane.addLayer(new SelectionLayer(timeFrequencyPaneCS));
		
		legend = new LegendLayer(timeFrequencyPaneCS,110);
		timeFrequencyPane.addLayer(legend);
		
		legend.addEntry("Spectrogram",Color.BLACK);
		legend.addEntry("Pitch estimations",Color.RED);
		
		splitPane.add(timeFrequencyPane, JSplitPane.BOTTOM);
		splitPane.setDividerLocation(150);
		
		ViewPortChangedListener listener = new ViewPortChangedListener() {
			@Override
			public void viewPortChanged(ViewPort newViewPort) {
				waveForm.repaint();
				timeFrequencyPane.repaint();
			}
		};
		waveForm.getViewPort().addViewPortChangedListener(new ViewPortChangedListener() {
			@Override
			public void viewPortChanged(ViewPort newViewPort) {
				timeFrequencyPaneCS.setMin(Axis.X,waveFormCS.getMin(Axis.X));
				timeFrequencyPaneCS.setMax(Axis.X,waveFormCS.getMax(Axis.X));
			}
		});
		
		
		
		waveForm.getViewPort().addViewPortChangedListener(listener);
		
		timeFrequencyPane.getViewPort().addViewPortChangedListener(new ViewPortChangedListener() {
			@Override
			public void viewPortChanged(ViewPort newViewPort) {
				waveFormCS.setMin(Axis.X,timeFrequencyPaneCS.getMin(Axis.X));
				waveFormCS.setMax(Axis.X,timeFrequencyPaneCS.getMax(Axis.X));
			}
		});
		timeFrequencyPane.getViewPort().addViewPortChangedListener(listener);
		return splitPane;
	}

	private JComponent createProgressPanel(){
	    positionSlider = new JSlider(0,1000);
		positionSlider.setValue(0);
		positionSlider.setPaintLabels(false);
		positionSlider.setPaintTicks(false);
		positionSlider.setEnabled(false);
		positionSlider.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent arg0) {
				if (newPositionValue != positionSlider.getValue()) {
					double promille = positionSlider.getValue() / 1000.0;
					double currentPosition = player.getDurationInSeconds() * promille;
					if (positionSlider.getValueIsAdjusting()) {
						setProgressLabelText(currentPosition, player.getDurationInSeconds());
					} else {
						double secondsToSkip = currentPosition;
						PlayerState currentState = player.getState();
						
						player.pauze(secondsToSkip);
						if(currentState == PlayerState.PLAYING){
							player.play();							
						} 
					}
				}
			}
		});
		
		progressLabel = new JLabel();
		totalLabel = new JLabel();
		setProgressLabelText(0, 0);
		
		JPanel subPanel = new JPanel(new BorderLayout());
		subPanel.add(progressLabel,BorderLayout.WEST);
		subPanel.add(positionSlider,BorderLayout.CENTER);
		subPanel.add(totalLabel,BorderLayout.EAST);
		
		JPanel panel = new JPanel(new BorderLayout());
		JLabel label = new JLabel("Progress (in %°)");
		label.setToolTipText("Progress in promille.");
		panel.add(label,BorderLayout.NORTH);
		panel.add(subPanel,BorderLayout.CENTER);
		panel.setBorder(new TitledBorder("Progress control"));

		return panel;
	}
	
	private void setProgressLabelText(double current, double max){
		progressLabel.setText(formattedToString(current));
		totalLabel.setText(formattedToString(max));
	}
	
	public String formattedToString(double seconds) {
		int minutes = (int) (seconds / 60);
		int completeSeconds = (int) seconds - (minutes * 60);
		int hundred =  (int) ((seconds - (int) seconds) * 100);
		return String.format(Locale.US, "%02d:%02d:%02d", minutes , completeSeconds, hundred);
	}
	
	private JComponent createButtonPanel(){
		JPanel fileChooserPanel = new JPanel(new GridLayout(1,0));
		fileChooserPanel.setBorder(new TitledBorder("Actions"));
		
		final JFileChooser fileChooser = new JFileChooser();
		
		final JButton chooseFileButton = new JButton("Open...");
		chooseFileButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				int returnVal = fileChooser.showOpenDialog(FFTZoomGeneralizedGoertzel.this);
	            if (returnVal == JFileChooser.APPROVE_OPTION) {
	                File file = fileChooser.getSelectedFile();	                
	                PlayerState currentState = player.getState();
	                player.load(file);
	                if(currentState == PlayerState.NO_FILE_LOADED || currentState == PlayerState.PLAYING){
	                	player.play();
	                }
	            } else {
	                //canceled
	            }
			}			
		});
		fileChooserPanel.add(chooseFileButton);
		
		final JButton stopButton = new JButton("Stop");
		stopButton.setEnabled(false);
		fileChooserPanel.add(stopButton);
		stopButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				player.stop();
			}
		});
		
		
		final JButton playButton = new JButton("Play");
		playButton.setEnabled(false);
		playButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				player.play();
			}
		});
		fileChooserPanel.add(playButton);		
		
		final JButton pauzeButton = new JButton("Pauze");
		pauzeButton.setEnabled(false);
		pauzeButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				player.pauze();
			}
		});
		fileChooserPanel.add(pauzeButton);
		
		player.addPropertyChangeListener(new PropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				if(evt.getPropertyName()=="state"){
					PlayerState newState = (PlayerState) evt.getNewValue();
					playButton.setEnabled(newState != PlayerState.PLAYING && newState != PlayerState.NO_FILE_LOADED);
					pauzeButton.setEnabled(newState == PlayerState.PLAYING && newState != PlayerState.NO_FILE_LOADED );
					stopButton.setEnabled((newState == PlayerState.PLAYING || newState == PlayerState.PAUZED) && newState != PlayerState.NO_FILE_LOADED);
				}
			}
		});
		
		return fileChooserPanel;
	}
	
	
	private JComponent createGainPanel(){
		JSlider gainSlider;
		gainSlider = new JSlider(0,200);
		gainSlider.setValue(100);
		gainSlider.setPaintLabels(true);
		gainSlider.setPaintTicks(true);
		final JLabel label = new JLabel("Gain: 100%");
		gainSlider.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent arg0) {
				JSlider gainSlider = ((JSlider)arg0.getSource());
				double gainValue = gainSlider.getValue() / 100.0;
				label.setText(String.format("Gain: %3d", gainSlider.getValue())+"%");
				player.setGain(gainValue);
			}
		});
		
		JPanel gainPanel = new JPanel(new BorderLayout());
		label.setToolTipText("Volume in % (100 is no change).");
		gainPanel.add(label,BorderLayout.NORTH);
		gainPanel.add(gainSlider,BorderLayout.CENTER);
		gainPanel.setBorder(new TitledBorder("Volume control"));
		return gainPanel;
	}
	
	public static void main(String... args) throws InterruptedException, InvocationTargetException {
		SwingUtilities.invokeAndWait(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new JFrame();
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setTitle("FFT Zoom with Generalized Goertzel");
				frame.add(new FFTZoomGeneralizedGoertzel());
				frame.pack();
				frame.setSize(450,650);
				frame.setVisible(true);
			}
		});
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy