001: /*
002: * Lucane - a collaborative platform
003: * Copyright (C) 2004 Vincent Fiack <vfiack@mail15.com>
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019: package org.lucane.applications.audioconf.audio;
020:
021: import java.util.*;
022:
023: import javax.sound.sampled.*;
024:
025: import org.xiph.speex.SpeexEncoder;
026:
027: /**
028: * Audio recorder that encodes directly in Speex
029: */
030: public class AudioRecorder implements Runnable {
031: //-- attributes
032: private TargetDataLine dataLine;
033: private AudioFormat audioFormat;
034: private AudioConfig audioConfig;
035:
036: private ArrayList listeners;
037:
038: /**
039: * Constructor
040: *
041: * @param config the audio configuration to use to encode
042: */
043: public AudioRecorder(AudioConfig config) {
044: this .listeners = new ArrayList();
045:
046: this .audioConfig = config;
047: this .audioFormat = config
048: .createAudioFormat(AudioFormat.Encoding.PCM_SIGNED);
049: DataLine.Info info = new DataLine.Info(TargetDataLine.class,
050: audioFormat);
051: try {
052: dataLine = (TargetDataLine) AudioSystem.getLine(info);
053: } catch (LineUnavailableException lue) {
054: lue.printStackTrace();
055: }
056: }
057:
058: /**
059: * Add a listener that will be notified of recording status
060: *
061: * @param listener the listener to add
062: */
063: public void addAudioListener(AudioRecorderListener listener) {
064: this .listeners.add(listener);
065: }
066:
067: /**
068: * Remove a listener
069: *
070: * @param listener the listener to remove
071: */
072: public void removeAudioListener(AudioRecorderListener listener) {
073: this .listeners.remove(listener);
074: }
075:
076: /**
077: * Stop recording
078: */
079: public void stop() {
080: dataLine.stop();
081: dataLine.close();
082:
083: //notify listeners
084: Iterator listeners = this .listeners.iterator();
085: while (listeners.hasNext())
086: ((AudioRecorderListener) listeners.next())
087: .audioRecordingEnded();
088: }
089:
090: /**
091: * Run recording as a thread
092: */
093: public void run() {
094: try {
095: dataLine.open();
096: dataLine.start();
097: } catch (LineUnavailableException lue) {
098: lue.printStackTrace();
099: return;
100: }
101:
102: //notify listeners
103: Iterator listeners = this .listeners.iterator();
104: while (listeners.hasNext())
105: ((AudioRecorderListener) listeners.next())
106: .audioRecordingStarted(audioConfig);
107:
108: //do the real recording
109: byte[] pcm = new byte[audioConfig.getPcmBufferSize()];
110: byte[] speex = new byte[audioConfig.getSpeexBufferSize()];
111: SpeexEncoder encoder = audioConfig.createEncoder();
112:
113: while (dataLine.isOpen()) {
114: int length = dataLine.read(pcm, 0, pcm.length);
115: encoder.processData(pcm, 0, pcm.length);
116: length = encoder.getProcessedDataByteSize();
117: encoder.getProcessedData(speex, 0);
118:
119: if (length > 0) {
120: listeners = this .listeners.iterator();
121: while (listeners.hasNext())
122: ((AudioRecorderListener) listeners.next())
123: .audioRecorded(speex, length);
124: }
125: }
126: }
127: }
|