⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 voicemicrophoneinput.java

📁 用jxse开发的一个p2p通讯软件 有聊天 文件共享 视频3大功能
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * Created on Oct 17, 2004 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */package net.jxta.myjxta.plugins.vojxta;import net.jxta.endpoint.ByteArrayMessageElement;import net.jxta.endpoint.StringMessageElement;import net.jxta.logging.Logging;import net.jxta.myjxta.dialog.Dialog;import net.jxta.myjxta.dialog.DialogMessage;import javax.sound.sampled.*;import java.util.logging.Level;import java.util.logging.Logger;/** * @author Ravi * @author jamoore * @modified 2005-03-05 jamoore add producer/consumer threads, line state * @modified 2005-03-05 jamoore audio encoding is now dynamic based on quality * @modified 2005-03-10 jamoore rework encoding to fit dynamic block sizes * @modified 2005-03-12 jamoore add statistical accessors * @modified 2005-03-18 jamoore refactor * @modified 2005-03-18 jamoore add in/out buffer size/capacity accessor/stats *  */public final class VoiceMicrophoneInput extends Thread implements AudioResource{        static final Logger LOG = Logger.getLogger (VoiceMicrophoneInput.class.getName());        /** default number of speex encoded chunks to place in each message*/    private static final int DEFAULT_MESSAGE_SIZE_MULTIPLIER = 10;        /** default number of speex encoded chunks the out going buffer will hold*/    private static final int DEFAULT_BUFFER_SIZE_MULTIPLIER = 50;        /** these represetn the logical state of the hardware to the call control*/    private static final int STATE_ON = 20;        private static final int STATE_OFF = 10;        private static final int STATE_PAUSE = 30;        /** represents the current state of the audio targetline */    private int micState = STATE_PAUSE;        /** type of audio we want from the target line */    private final AudioFileFormat.Type targetType = null;    /** data line to microphone*/    private TargetDataLine targetLine = null;;        /** wrapper to the speex encoder */    private Encoder encoder = null;;        /** call control object - performs protocol navigation */    private VoJxtaCallControl vojxtaCallControl = null;        /** outgoing buffer that holds que'd up speex audio blocks */    private VoiceDataBuffer sendBuffer = null;        /** wait lock to pause the target line from reading*/    private Object pauseLock = null;        /** wait lock till the buffer recovers from starvation*/    private Object messageThreadLock = null;        /** dialog that we dispatch messages to*/    public Dialog vojxtaDialog = null;        // debugging    boolean firstSentMessage = true;    byte[] firstSentBytes = null;        /** statistic*/    private long sentMessages = 0;    /** statistic*/    private long sentBytes = 0;        /** true if message thread is waiting for the buffer to fill up*/    private boolean messageThreadWaiting = false;        /** size of audio chucks speex can encode at the current sample rate*/    private final int rawChunkSize = BLOCK_SIZE; // basically at the sample rate this is 640 bytes        /** size of the speex encoded audio. this depends on the quality setting*/    private int speexChunkSize = 0;;        /** the size in bytes each outgoing message contains*/    private int speexMessageSize = 0;        /** size in bytes of the outgoing buffer holding speex encoded bytes*/    private int speexBufferSize = 0;        /** target line buffer size*/    private final int rawBufferSize = rawChunkSize * 10;        /** size in bytes of buffer read from target Line */    private final int audioReadChunkSize = rawChunkSize * 5;        /** default mixer on target line */    private Mixer micMixer = null;        /** default gain control on target line*/    private FloatControl gainControl = null;        /** statistic */    private int averageEncodeTime = 0;        /** speex quality level */    private int encodeQuality = 0;        /** consumer thread, dispatches messages to dialog*/    private Thread messageThread = null;        /**     *      */    public VoiceMicrophoneInput (VoJxtaCallControl vojxtaCallControl) {                LOG.setLevel (Level.INFO);        //LOG.setLevel (Level.SEVERE);        pauseLock = new Object ();                messageThreadLock = new Object ();                this.vojxtaCallControl = vojxtaCallControl;                this.vojxtaDialog = this.vojxtaCallControl.getDialog ();                /** This thread dispatches messages to the vojxta dialog and           *  blocks on outgoing buffer starvation */        messageThread = new Thread (new Runnable () {                        public void run () {                    while(true) {                    if(getMicState () == STATE_OFF) {                                                //we should send any remaining data in buffer first                        break;                    }                                        if (sendBuffer.size () >= speexMessageSize) {                                                dispatchVoiceData (sendBuffer.get (speexMessageSize));                    }else {                                                try {                                                        synchronized(messageThreadLock) {                                                                messageThreadWaiting = true;                                                                messageThreadLock.wait ();                            }                        }catch(InterruptedException ix) {                                                        ix.printStackTrace ();                        }                    }                }                }        });    }//constructor        /**     *  Retain the mic line from the audiosubsystem. Try for a gain control too.     *  For some raeson target lines do not have available controls. we might have     * to add some amplitude to the line oourselve.     */    public void obtainHardware () {                AudioFormat  audioFormat = new AudioFormat (AudioFormat.Encoding.PCM_SIGNED, 16000.0F, 16, 1, 2, 16000.0F, false);                DataLine.Info info = new DataLine.Info (TargetDataLine.class, audioFormat);                try {                        targetLine = (TargetDataLine) AudioSystem.getLine (info);                        targetLine.open (audioFormat, rawBufferSize );                    } catch (LineUnavailableException e) {            // TODO Auto-generated catch block            e.printStackTrace ();                    }                AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE;                if(targetLine.isControlSupported (FloatControl.Type.MASTER_GAIN)) {                        gainControl = (FloatControl)targetLine.getControl (FloatControl.Type.MASTER_GAIN);        }            }            /**     * Return block size of encoded audio bytes     */    public int getEncodedBlockSize () {                return speexChunkSize;    }        /**     *  Return the size in byte of voice data in a message     */    public int getEncodedMessageSize () {                return speexMessageSize;            }        /**     *  Set the size in bytes of voice data in a message     */    public void setEncodedMessageSize (int encodedMessageSize) {                this.speexMessageSize = encodedMessageSize;    }        /**     *  Returns the size in bytes of the buffer holding outgoing encoded voice     *  bytes     */    public int getEncodedBufferSize () {                return speexBufferSize;    }        /**     *  Sets the size in bytes of the buffer that holds encoded voice bytes.      *  The current buffer impl does not allow dynamic resizing     */    public void setEncodedBufferSize (int encodedBufferSize) {                this.speexBufferSize = encodedBufferSize;            }        /*      *  producer thread. read from target line blocks till buffer size can be      *  filled. data is encoded then added to the outgoing buffer.     */    public void run () {                /** start the message dispatch thread*/        messageThread.start ();                /** local buff to read raw audio into */        byte[] buff = new byte[audioReadChunkSize];        /** bytes read from targetline... if zero after read that mean the line            has been stopped */        int bytesRead = 0;                try {                        while((bytesRead =                         this.targetLine.read (buff,0,buff.length)) != -1) {                                if(getMicState () == this.STATE_PAUSE) {                                        synchronized(pauseLock) {                                                pauseLock.wait ();                    }                }                                if(getMicState () == this.STATE_OFF) {                                        //we should send any remaining data in buffer first                    break;                }                if(bytesRead > 0) {                                        encodeAndStore (buff);                                        if (messageThreadWaiting && sendBuffer.size () >= speexMessageSize) {                                                messageThreadWaiting = false;                        synchronized(messageThreadLock) {                                                        messageThreadLock.notify ();                        }                    }                }else{                    /** if bytes read is zero something is wrong.. break */                   if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {                                               this.printMicState ();                                                if(!targetLine.isOpen ()) {                            LOG.info("targetline != open");                        }                                                LOG.info("ZERO Bytes READ");                                                break;                    }                }            }//while        }catch (InterruptedException ix ) {                        setMicState (this.STATE_OFF);                        if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {                LOG.info("run : interuptedexception");            }                        ix.printStackTrace ();                    }            }//run            /**     *  encodes the raw pcm audio from target line then stores it in the      *  outgoing buffer. at the current sample rate speex encodes 640byte     *  blocks. we break the buff up into 640byte chunks -> encode -> store     */    private void encodeAndStore (byte[] buff) {                        int chunks = buff.length / rawChunkSize;                int[] startPos = new int[chunks];                for(int j = 0; j < chunks; j++) {                        startPos[j] = j * rawChunkSize;        }                for(int i = 0 ; i < chunks ; i++) {                        byte[] preEncodeBuff = new byte[rawChunkSize];                        System.arraycopy (buff,startPos[i], preEncodeBuff, 0, rawChunkSize );                        long in = System.currentTimeMillis ();                        byte[] postEncodeBuff = encoder.encode (preEncodeBuff);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -