www.pudn.com > d4j.zip > TargetVoiceLine.java


package local.dialogic; 
import javax.sound.sampled.*; 
import java.io.*; 
import java.util.*; 
 
public class TargetVoiceLine extends OutputStream implements TargetDataLine 
{ 
    // Default buffer size, can be reset via open(format, bufferSize) 
    int bufferSize = 8096; 
    byte buffer[] = null; 
    boolean active = false; 
    int pos = 0; 
    // Available bytes 
    int cap = 0;  
    // Next incoming byte 
    int at = 0; 
    // Should be linked to Voice constants, may be command Voice from here ? 
    // Can be reset via open(format) or open(format, bufferSize) 
    AudioFormat format = new AudioFormat( 
                            AudioFormat.Encoding.ULAW,  // Encoding 
                            8000,     // Sample rate 
                            8,        // bits per sample 
                            1,        // channels 
                            1,        // frame size 
                            8000,     // frame rate 
                            true);    // big endian 
    //My listeners 
    Vector listeners = new Vector(); 
 
    // OutputStream 
     
    /** 
     *  
     */ 
    public synchronized void write(byte[] b, int off, int len) throws IOException { 
        if (!active)  
            return; 
        if (off != 0) 
            throw new IOException("Offset not supported!"); 
        for (int i = 0; i < len; i++) { 
            buffer[at++] = b[i]; 
            if (at >= bufferSize) at = 0; 
        } 
        cap += len; 
        if (cap > bufferSize) cap = bufferSize; 
        //System.out.println("TargetVoiceLine write " + len + " at " + at + " cap " + cap); 
        notifyAll(); 
    } 
     
    /** 
     * Write one byte 
     */ 
    public synchronized void write(int b) throws IOException { 
        buffer[at++] = (byte)b; 
        if (at >= bufferSize) at = 0; 
        if (cap < bufferSize) cap++;  
        notifyAll(); 
    } 
     
    // Line methods 
     
    /** 
     * Adds a listener to this line. 
     */ 
    public void addLineListener (LineListener listener) { 
        synchronized(listeners) { 
            listeners.add(listener); 
        } 
    } 
     
    /** 
     *  Closes the line, indicating that any system resources in use by the line can be released. 
     */ 
    public synchronized void close() { 
        buffer = null; 
        active = false; 
        pos = 0; 
        at = 0; 
        cap = 0; 
    } 
     
    /** 
     * Obtains a control of the specified type, if there is any. 
     */ 
    public Control getControl (Control.Type control) throws IllegalArgumentException { 
        throw new IllegalArgumentException(); 
    } 
     
    /** 
     * Obtains the set of controls associated with this line. 
     */ 
    public Control[] getControls () { 
        return new Control[0]; 
    } 
     
    /** 
     * Obtains the Line.Info object describing this line. 
     */ 
    public Line.Info getLineInfo () { 
        return new Line.Info(TargetVoiceLine.class); 
    } 
     
    /** 
     *  Indicates whether the line supports a control of the specified type. 
     */ 
    public boolean isControlSupported (Control.Type control) { 
        return false; 
    } 
     
    /** 
     * Indicates whether the line is open, meaning that it has reserved system  
     * resources and is operational, although it might not currently be playing 
     * or capturing sound. 
     */ 
    public boolean isOpen () { 
        return (buffer != null); 
    } 
     
    /** 
     * Opens the line, indicating that it should acquire any required system  
     * resources and become operational. 
     */ 
    public synchronized void open () { 
        buffer = new byte[bufferSize]; 
        pos = 0; 
        at = 0; 
        cap = 0; 
    } 
     
    /** 
     * Removes the specified listener from this line's list of listeners. 
     */ 
    public void removeLineListener(LineListener listener) { 
        synchronized(listeners) { 
            listeners.remove(listener); 
        } 
    } 
     
    // DataLine methods 
    /** 
     * Obtains the number of bytes of data currently available to the application  
     * for processing in the data line's internal buffer. 
     */ 
    public int available() { 
        return cap; 
    } 
     
    /** 
     * Drains queued data from the line by continuing data I/O until the data  
     * line's internal buffer has been emptied. 
     */ 
    public synchronized void drain() { 
        while(cap > 0) { 
            try { 
                wait(); 
            } catch (InterruptedException ie) {}; 
        } 
    } 
     
    /** 
     * Flushes queued data from the line. 
     */ 
    public synchronized void flush() { 
        at = cap = 0; 
        notifyAll(); 
    } 
     
    /** 
     * Obtains the maximum number of bytes of data that will fit in the data  
     * line's internal buffer. 
     */ 
    public int getBufferSize() { 
        return bufferSize; 
    } 
     
    /** 
     * Obtains the current format (encoding, sample rate, number of channels, etc.)  
     * of the data line's audio data. 
     */ 
    public AudioFormat getFormat() { 
        return format; 
    } 
     
    /** 
     * Obtains the current position in the audio data, in sample frames. 
     */ 
    public int getFramePosition() { 
        return pos; 
    } 
     
    /** 
     * Obtains the current volume level for the line 
     */ 
    public float getLevel() { 
        return (float)AudioSystem.NOT_SPECIFIED; 
    } 
     
    /** 
     * Obtains the current position in the audio data, in microseconds. 
     */ 
    public long getMicrosecondPosition() { 
        return (long)pos * 1000L / (long)format.getFrameRate(); 
    } 
     
    /** 
     * Indicates whether the line is engaging in active I/O (such as playback or capture). 
     */ 
    public boolean isActive() { 
        return active; 
    } 
     
    /** 
     * Indicates whether the line is running. 
     */ 
    public boolean isRunning() { 
        return true; 
    } 
     
    /** 
     * Allows a line to engage in data I/O. 
     */ 
    public synchronized void start() { 
        if (isOpen()) 
            active = true; 
        // XXX Should inform listeners... 
    } 
     
    /** 
     * Stops the line. 
     */ 
    public synchronized void stop() { 
        active = false; 
        notifyAll(); 
        // XXX Should inform listeners... 
    } 
     
    // TargetDataLine methods 
 
    /** 
     * Opens the line with the specified format, causing the line to acquire  
     * any required system resources and become operational. 
     */ 
    public synchronized void open(AudioFormat format) { 
        this.format = format; 
        open(); 
    } 
     
    /** 
     * Opens the line with the specified format and requested buffer size,  
     * causing the line to acquire any required system resources and 
     * become operational. 
     */ 
    public void open(AudioFormat format, int bufferSize) { 
        this.bufferSize = bufferSize; 
        open(format); 
    } 
     
    /** 
     *  Reads audio data from the data line's input buffer. 
     */ 
    public synchronized int read(byte[] b, int off, int len) { 
        while (active && (cap < len)) { 
            try { 
                wait(); 
            } catch (InterruptedException ie) {}; 
        } 
        int i, ato = at - cap; 
        if (ato < 0) ato += bufferSize; 
        for (i = 0; (i < len) && (i < cap); i++) { 
            b[i+off] = buffer[ato++]; 
            if (ato >= bufferSize) ato = 0; 
        } 
        cap -= i; 
        return i; 
    } 
}