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