f@0: /* f@0: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool f@0: f@0: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) f@0: f@0: This program is free software: you can redistribute it and/or modify f@0: it under the terms of the GNU General Public License as published by f@0: the Free Software Foundation, either version 3 of the License, or f@0: (at your option) any later version. f@0: f@0: This program is distributed in the hope that it will be useful, f@0: but WITHOUT ANY WARRANTY; without even the implied warranty of f@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the f@0: GNU General Public License for more details. f@0: f@0: You should have received a copy of the GNU General Public License f@0: along with this program. If not, see . f@0: */ f@0: f@0: package uk.ac.qmul.eecs.ccmi.speech; f@0: f@0: import java.io.ByteArrayInputStream; f@0: import java.io.ByteArrayOutputStream; f@0: import java.io.IOException; f@0: f@0: import javax.sound.sampled.AudioFileFormat; f@0: import javax.sound.sampled.AudioFormat; f@0: import javax.sound.sampled.AudioInputStream; f@0: import javax.sound.sampled.AudioSystem; f@0: import javax.sound.sampled.UnsupportedAudioFileException; f@0: f@0: f@0: import net.beadsproject.beads.core.AudioContext; f@0: import net.beadsproject.beads.core.Bead; f@0: import net.beadsproject.beads.data.Sample; f@0: import net.beadsproject.beads.ugens.Gain; f@0: import net.beadsproject.beads.ugens.Panner; f@0: import net.beadsproject.beads.ugens.SamplePlayer; f@0: f@0: import com.sun.speech.freetts.audio.AudioPlayer; f@0: f@0: /** f@0: * An implementation of {@code AudioPlayer} using the {@code Beads} f@0: * library. f@0: */ f@0: public class BeadsAudioPlayer implements AudioPlayer { f@0: public BeadsAudioPlayer(){ f@0: format = new AudioFormat(8000f, 16, 1, true, true); f@0: ac = new AudioContext(format); f@0: volume = 1.0f; f@0: monitor = new Object(); f@0: } f@0: f@0: public BeadsAudioPlayer(float vol, float pan){ f@0: this(); f@0: volume = vol; f@0: this.pan = pan; f@0: } f@0: f@0: f@0: @Override f@0: public void begin(int size) { f@0: buffer = new byte[size]; f@0: bufferPosition = 0; f@0: ac = new AudioContext(); f@0: } f@0: f@0: @Override f@0: public void cancel() { f@0: f@0: } f@0: f@0: @Override f@0: public void close() { f@0: ac.stop(); f@0: } f@0: f@0: @Override f@0: public boolean drain() { f@0: synchronized(monitor){ f@0: if(!finished) f@0: try { f@0: monitor.wait(); f@0: } catch (InterruptedException e) { f@0: throw new RuntimeException(e); f@0: } f@0: finished = false; f@0: } f@0: return false; f@0: } f@0: f@0: @Override f@0: public boolean end() { f@0: ByteArrayInputStream stream = new ByteArrayInputStream(buffer); f@0: AudioInputStream audioStream = new AudioInputStream(stream, format, bufferPosition/format.getFrameSize()); f@0: ByteArrayOutputStream out = new ByteArrayOutputStream(); f@0: Sample sample = null; f@0: try { f@0: AudioSystem.write(audioStream, AudioFileFormat.Type.WAVE,out); f@0: sample = new Sample(new ByteArrayInputStream(out.toByteArray())); f@0: } catch (IOException e) { f@0: e.printStackTrace(); f@0: return false; f@0: } catch (UnsupportedAudioFileException e) { f@0: e.printStackTrace(); f@0: return false; f@0: } f@0: f@0: SamplePlayer player = new SamplePlayer(ac,sample); f@0: player.setKillOnEnd(true); f@0: Gain g = new Gain(ac,1,volume); f@0: g.addInput(player); f@0: final Panner panner = new Panner(ac,pan); f@0: panner.addInput(g); f@0: player.setKillListener(new Bead(){ f@0: @Override f@0: protected void messageReceived(Bead message){ f@0: panner.kill(); f@0: synchronized(monitor){ f@0: finished = true; f@0: monitor.notify(); f@0: } f@0: } f@0: }); f@0: f@0: /* starts playing the sample */ f@0: ac.out.addInput(panner); f@0: ac.start(); f@0: return true; f@0: } f@0: f@0: @Override f@0: public AudioFormat getAudioFormat() { f@0: return format; f@0: } f@0: f@0: @Override f@0: public long getTime() { f@0: return -1L; f@0: } f@0: f@0: @Override f@0: public float getVolume() { f@0: return volume; f@0: } f@0: f@0: @Override f@0: public void pause() { f@0: f@0: } f@0: f@0: @Override f@0: public void reset() { f@0: f@0: } f@0: f@0: @Override f@0: public void resetTime() { f@0: f@0: } f@0: f@0: @Override f@0: public void resume() { f@0: f@0: } f@0: f@0: @Override f@0: public void setAudioFormat(AudioFormat format) { f@0: this.format = format; f@0: ac.setInputAudioFormat(format); f@0: } f@0: f@0: @Override f@0: public void setVolume(float vol) { f@0: volume = vol; f@0: } f@0: f@0: public void setPan(float pan){ f@0: this.pan = pan; f@0: } f@0: f@0: public float getPan(){ f@0: return pan; f@0: } f@0: f@0: @Override f@0: public void showMetrics() { f@0: f@0: } f@0: f@0: @Override f@0: public void startFirstSampleTimer() { f@0: f@0: } f@0: f@0: @Override f@0: public boolean write(byte[] audioData) { f@0: return write(audioData,0,audioData.length); f@0: } f@0: f@0: @Override f@0: public boolean write(byte[] audioData, int offset, int size) { f@0: System.arraycopy(audioData, offset, buffer, bufferPosition, size); f@0: bufferPosition += size; f@0: return true; f@0: } f@0: f@0: private byte[] buffer; f@0: private int bufferPosition; f@0: private AudioFormat format; f@0: private float volume; f@0: private float pan; f@0: private Object monitor; f@0: private boolean finished; f@0: private AudioContext ac; f@0: f@0: }