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

examples.be.tarsos.dsp.example.constantq.ConstantQAudioPlayer 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.constantq;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
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.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.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.ConstantQLayer;
import be.tarsos.dsp.ui.layers.DragMouseListenerLayer;
import be.tarsos.dsp.ui.layers.LegendLayer;
import be.tarsos.dsp.ui.layers.PitchContourLayer;
import be.tarsos.dsp.ui.layers.SelectionLayer;
import be.tarsos.dsp.ui.layers.TimeAxisLayer;
import be.tarsos.dsp.ui.layers.VerticalFrequencyAxisLayer;
import be.tarsos.dsp.ui.layers.WaveFormLayer;
import be.tarsos.dsp.ui.layers.ZoomMouseListenerLayer;

public class ConstantQAudioPlayer extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = -4000269621209901229L;
	
	private JSlider gainSlider;
	private JSlider positionSlider;
	
	private JButton playButton;
	private JButton stopButton;
	private JButton pauzeButton;
	private JLabel progressLabel;
	private JLabel totalLabel;
	
	private LinkedPanel waveForm;
	private LinkedPanel constantQ;
	private CoordinateSystem waveFormCS;
	private CoordinateSystem constantQCS;
	
	private JFileChooser fileChooser;
	
	//position value in the slider
	private int newPositionValue;
	
	final Player player;
	
	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 ConstantQAudioPlayer(){
		this.setLayout(new BorderLayout());
		
		JPanel subPanel = new JPanel(new GridLayout(0,1));
		
		subPanel.add(createGainPanel());
		subPanel.add(createProgressPanel());
		subPanel.add(createButtonPanel());
		
		this.add(new JSplitPane(JSplitPane.VERTICAL_SPLIT, subPanel, createConstantQ()));
		
		player = new Player(processor,1024,0);
		player.addPropertyChangeListener(new PropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent arg0) {
				if(arg0.getPropertyName()=="state"){
					PlayerState newState = (PlayerState) arg0.getNewValue();
					reactToPlayerState(newState);
				}
			}
		});
		reactToPlayerState(player.getState());
	}
	
	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 Component createConstantQ() {
		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);
		
		constantQCS = getCoordinateSystem(AxisUnit.FREQUENCY);
		constantQ = new LinkedPanel(constantQCS);
		constantQ.addLayer(new BackgroundLayer(constantQCS));
		constantQ.addLayer(new VerticalFrequencyAxisLayer(constantQCS));
		constantQ.addLayer(new TimeAxisLayer(constantQCS));
		constantQ.addLayer(new ZoomMouseListenerLayer());
		constantQ.addLayer(new DragMouseListenerLayer(constantQCS));
		constantQ.addLayer(new SelectionLayer(constantQCS));
		
		legend = new LegendLayer(constantQCS,110);
		constantQ.addLayer(legend);
		
		legend.addEntry("ConstantQ",Color.BLACK);
		legend.addEntry("Pitch estimations",Color.RED);
		
		splitPane.add(constantQ, JSplitPane.BOTTOM);
		splitPane.setDividerLocation(150);
		
		ViewPortChangedListener listener = new ViewPortChangedListener() {
			@Override
			public void viewPortChanged(ViewPort newViewPort) {
				waveForm.repaint();
				constantQ.repaint();
			}
		};
		waveForm.getViewPort().addViewPortChangedListener(new ViewPortChangedListener() {
			@Override
			public void viewPortChanged(ViewPort newViewPort) {
				constantQCS.setMin(Axis.X,waveFormCS.getMin(Axis.X));
				constantQCS.setMax(Axis.X,waveFormCS.getMax(Axis.X));
			}
		});		
		waveForm.getViewPort().addViewPortChangedListener(listener);
		
		constantQ.getViewPort().addViewPortChangedListener(new ViewPortChangedListener() {
			@Override
			public void viewPortChanged(ViewPort newViewPort) {
				waveFormCS.setMin(Axis.X,constantQCS.getMin(Axis.X));
				waveFormCS.setMax(Axis.X,constantQCS.getMax(Axis.X));
			}
		});
		constantQ.getViewPort().addViewPortChangedListener(listener);
		
		return splitPane;
	}

	private void reactToPlayerState(PlayerState newState){
		positionSlider.setEnabled(newState != PlayerState.NO_FILE_LOADED);
		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);
		
		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));
			
			
			LegendLayer legend = new LegendLayer(waveFormCS,50);
			waveForm.addLayer(legend);
			legend.addEntry("Wave",Color.BLACK);
			
			constantQ.removeLayers();
			constantQ.addLayer(new BackgroundLayer(constantQCS));
			constantQ.addLayer(new ConstantQLayer(constantQCS,player.getLoadedFile(),2048,3600,10800,12));
			constantQ.addLayer(new PitchContourLayer(constantQCS,player.getLoadedFile(),Color.red,2048,0));
			constantQ.addLayer(new VerticalFrequencyAxisLayer(constantQCS));
			constantQ.addLayer(new ZoomMouseListenerLayer());
			constantQ.addLayer(new DragMouseListenerLayer(constantQCS));
			constantQ.addLayer(new SelectionLayer(constantQCS));
			constantQ.addLayer(new TimeAxisLayer(constantQCS));
			
			legend = new LegendLayer(constantQCS,110);
			constantQ.addLayer(legend);
			legend.addEntry("ConstantQ",Color.BLACK);
			legend.addEntry("Pitch estimations",Color.RED);
		}
	}
	
	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 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 JComponent createButtonPanel(){
		JPanel fileChooserPanel = new JPanel(new GridLayout(1,0));
		fileChooserPanel.setBorder(new TitledBorder("Actions"));
		
		fileChooser = new JFileChooser();
		
		final JButton chooseFileButton = new JButton("Open...");
		chooseFileButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				int returnVal = fileChooser.showOpenDialog(ConstantQAudioPlayer.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);
		
		stopButton = new JButton("Stop");
		fileChooserPanel.add(stopButton);
		stopButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				player.stop();
			}
		});
		
		playButton = new JButton("Play");
		playButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				player.play();
			}
		});
		fileChooserPanel.add(playButton);		
		
		pauzeButton = new JButton("Pauze");
		pauzeButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				player.pauze();
			}
		});
		fileChooserPanel.add(pauzeButton);
		
		return fileChooserPanel;
	}
	
	private void setProgressLabelText(double current, double max){
		progressLabel.setText(formattedToString(current));
		totalLabel.setText(formattedToString(max));
	}
	
	private JComponent createGainPanel(){
		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) {
				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("Constant Q Audio Player");
				frame.add(new ConstantQAudioPlayer());
				frame.pack();
				frame.setSize(450,650);
				frame.setVisible(true);
			}
		});
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy