/* * _______ _____ _____ _____ * |__ __| | __ \ / ____| __ \ * | | __ _ _ __ ___ ___ ___| | | | (___ | |__) | * | |/ _` | '__/ __|/ _ \/ __| | | |\___ \| ___/ * | | (_| | | \__ \ (_) \__ \ |__| |____) | | * |_|\__,_|_| |___/\___/|___/_____/|_____/|_| * * ------------------------------------------------------------- * * 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.KeyEventPostProcessor; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import be.tarsos.dsp.AudioDispatcher; import be.tarsos.dsp.StopAudioProcessor; import be.tarsos.dsp.WaveformSimilarityBasedOverlapAdd; import be.tarsos.dsp.WaveformSimilarityBasedOverlapAdd.Parameters; 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.io.jvm.WaveformWriter; import be.tarsos.dsp.resample.RateTransposer; public class SampleExtractor extends JFrame { /** * */ private static final long serialVersionUID = -8749523013657700525L; private final JFileChooser fileChooser; private final JSpinner startSelectionSpinner; private final JSpinner endSelectionSpinner; private final JSpinner[] centsSpinner; private final JSpinner[] durationSpinner; private final JLabel[] sampleLabel; private final JButton playSelection; private final JCheckBox[] saveSampleCheckboxes; private File file; private final char[] codes = {'e','r','t','y','u','i','o','p'}; private double currentDuration = 0; private ChangeListener selectionChangedListener = new ChangeListener() { @Override public void stateChanged(ChangeEvent event) { double endValue = (Double) endSelectionSpinner.getValue(); double startValue = (Double) startSelectionSpinner.getValue(); if(endValue < startValue){ startSelectionSpinner.removeChangeListener(this); startSelectionSpinner.setValue(endValue); startSelectionSpinner.addChangeListener(this); } for(int i = 0 ; i < durationSpinner.length;i++){ double duration = (Double) durationSpinner[i].getValue(); if(duration == 0 || duration == currentDuration){ durationSpinner[i].setValue(selectionDuration()); } } currentDuration = selectionDuration(); } }; public SampleExtractor(){ this.setLayout(new BorderLayout()); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setTitle("Sample Exctractor: Extract & Modify Samples"); fileChooser = new JFileChooser(); startSelectionSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000, 0.1)); startSelectionSpinner.setEnabled(false); startSelectionSpinner.addChangeListener(selectionChangedListener); endSelectionSpinner = new JSpinner(new SpinnerNumberModel(0,0,10000,0.1)); endSelectionSpinner.setEnabled(false); endSelectionSpinner.addChangeListener(selectionChangedListener); centsSpinner = new JSpinner[codes.length]; durationSpinner = new JSpinner[codes.length]; sampleLabel = new JLabel[codes.length]; saveSampleCheckboxes = new JCheckBox[codes.length]; playSelection = new JButton("Play"); playSelection.setEnabled(false); playSelection.addActionListener(new ActionListener() { AudioDispatcher dispatcher = null; @Override public void actionPerformed(ActionEvent arg0) { if(((Double)startSelectionSpinner.getValue())<((Double)endSelectionSpinner.getValue())){ try { dispatcher = AudioDispatcherFactory.fromFile(file, 1024, 0); dispatcher.skip((Double)startSelectionSpinner.getValue()); dispatcher.addAudioProcessor(new StopAudioProcessor((Double)endSelectionSpinner.getValue())); dispatcher.addAudioProcessor(new AudioPlayer(JVMAudioInputStream.toAudioFormat(dispatcher.getFormat()))); } catch (UnsupportedAudioFileException e1) { } catch (IOException e1) { } catch (LineUnavailableException e) { } new Thread(dispatcher).start(); } } }); JPanel fileChooserPanel = new JPanel(new GridLayout(2,4)); fileChooserPanel.setBorder(new TitledBorder("1. Choose your audio to extract samples from (wav mono)")); JButton chooseFileButton = new JButton("Load a file..."); chooseFileButton.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { int returnVal = fileChooser.showOpenDialog(SampleExtractor.this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); setFile(file); } else { //canceled } } }); fileChooserPanel.add(new JLabel("Load a file")); fileChooserPanel.add(new JLabel("Start (s)")); fileChooserPanel.add(new JLabel("End (s)")); fileChooserPanel.add(new JLabel("Play Selection")); fileChooserPanel.add(chooseFileButton); fileChooserPanel.add(startSelectionSpinner); fileChooserPanel.add(endSelectionSpinner); fileChooserPanel.add(playSelection); this.add(fileChooserPanel,BorderLayout.NORTH); JPanel samplePanel = new JPanel(new GridLayout(0,1)); JPanel sampleSubPanel = new JPanel(new GridLayout(1,0)); sampleSubPanel.add(new JLabel("Key")); sampleSubPanel.add(new JLabel("Cents")); sampleSubPanel.add(new JLabel("Duration")); samplePanel.add(sampleSubPanel); samplePanel.add(sampleSubPanel); final KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); for(int i = 0;i<centsSpinner.length;i++){ sampleSubPanel = new JPanel(new GridLayout(1,0)); centsSpinner[i] = new JSpinner(new SpinnerNumberModel(i*100,-1200,1200,1)); centsSpinner[i].setEnabled(false); durationSpinner[i] = new JSpinner(new SpinnerNumberModel(0,0,1200,0.1)); durationSpinner[i].setEnabled(false); sampleLabel[i] = new JLabel("Press " + codes[i] + " to play."); saveSampleCheckboxes[i] = new JCheckBox("Save?"); saveSampleCheckboxes[i].setEnabled(false); sampleSubPanel.add(sampleLabel[i]); sampleSubPanel.add(centsSpinner[i]); sampleSubPanel.add(durationSpinner[i]); sampleSubPanel.add(durationSpinner[i]); sampleSubPanel.add(saveSampleCheckboxes[i]); samplePanel.add(sampleSubPanel); final Integer index = i; manager.addKeyEventPostProcessor(new KeyEventPostProcessor() { @Override public boolean postProcessKeyEvent(KeyEvent e) { boolean consumed = false; if(e.getKeyChar()== codes[index] && e.getID() == KeyEvent.KEY_TYPED && file != null){ try{ int cents = (Integer) centsSpinner[index].getValue(); double duration = (Double) durationSpinner[index].getValue(); double originalDuration = selectionDuration(); double pitchFactor = PitchShiftingExample.centToFactor(cents); double durationFactor = originalDuration/duration * pitchFactor; boolean saveWav = saveSampleCheckboxes[index].isSelected(); AudioFormat format = AudioSystem.getAudioFileFormat(file).getFormat(); double sampleRate = format.getSampleRate(); double endValue = (Double) endSelectionSpinner.getValue(); double startValue = (Double) startSelectionSpinner.getValue(); WaveformSimilarityBasedOverlapAdd wsola; AudioPlayer audioPlayer; RateTransposer rateTransposer; rateTransposer = new RateTransposer(pitchFactor); wsola = new WaveformSimilarityBasedOverlapAdd(Parameters.musicDefaults(durationFactor,sampleRate)); AudioDispatcher dispatcher = AudioDispatcherFactory.fromFile(file,wsola.getInputBufferSize(), wsola.getOverlap()); audioPlayer = new AudioPlayer(format); wsola.setDispatcher(dispatcher); dispatcher.skip(startValue); dispatcher.addAudioProcessor(new StopAudioProcessor(endValue)); dispatcher.addAudioProcessor(wsola); dispatcher.addAudioProcessor(rateTransposer); if(saveWav){ String filename = String.format("%s_%.2fs-%.2fs_modified_%dcents_%.2fs.wav", file.getName(),startValue,endValue,cents,duration); WaveformWriter wfw = new WaveformWriter(format,filename); dispatcher.addAudioProcessor(wfw); System.out.println("Saving to " + filename); }else{ dispatcher.addAudioProcessor(audioPlayer); } Thread t = new Thread(dispatcher); t.start(); consumed = true; } catch (Exception ex) { ex.printStackTrace(); } } return consumed; } }); } samplePanel.setBorder(new TitledBorder("2. Adapt and play the samples.")); samplePanel.setFocusable(true); this.add(samplePanel,BorderLayout.CENTER); try{ final String tempDir = System.getProperty("java.io.tmpdir"); String path = new File(tempDir,"flute_sample.wav").getAbsolutePath(); String resource = "/be/tarsos/dsp/example/resources/flute_sample.wav"; copyFileFromJar(resource,path); setFile(new File(path)); }catch (Exception e){ e.printStackTrace(); } } /** * Copy a file from a jar. * * @param source * The path to read e.g. /package/name/here/help.html * @param target * The target to save the file to. */ private void copyFileFromJar(final String source, final String target) { try { final InputStream inputStream = this.getClass().getResourceAsStream(source); OutputStream out; out = new FileOutputStream(target); final byte[] buffer = new byte[4096]; int len = inputStream.read(buffer); while (len != -1) { out.write(buffer, 0, len); len = inputStream.read(buffer); } out.close(); inputStream.close(); } catch (final FileNotFoundException e) { } catch (final IOException e) { } } private double selectionDuration(){ return (Double) endSelectionSpinner.getValue() - (Double) startSelectionSpinner.getValue(); } private void setFile(File file) { this.file=file; endSelectionSpinner.setEnabled(true); startSelectionSpinner.setEnabled(true); playSelection.setEnabled(true); for(int i = 0;i<centsSpinner.length;i++){ centsSpinner[i].setEnabled(true); durationSpinner[i].setEnabled(true); saveSampleCheckboxes[i].setEnabled(true); } try { AudioDispatcher dispatcher = AudioDispatcherFactory.fromFile(file, 1024, 0); dispatcher.run(); endSelectionSpinner.setValue((double) dispatcher.secondsProcessed()); } catch (UnsupportedAudioFileException e) { } catch (IOException e) { } } public static void main(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 and feel; } JFrame frame = new SampleExtractor(); frame.pack(); frame.setSize(450,400); frame.setVisible(true); } }); } }