Example #1
0
        public PlayAudio(VoiceService voices, int frameSize, RemoteVoice user)
        {
            Voices = voices;
            User   = user;

            CallbackHandler = new WinMM.WaveDelegate(WaveCallback);

            FrameSize = frameSize;
            int sampleRate = 0;

            // if 20ms, at high quality (16khz) is 320 samples at 2 bytes each
            if (FrameSize == 320)
            {
                sampleRate = 16000;
                BufferSize = 320 * 2 * 2; // 2 bytes each frame, 2 channels
                SpeexMode  = Speex.SPEEX_MODEID_WB;
            }
            else if (FrameSize == 160)
            {
                sampleRate = 8000;
                BufferSize = 160 * 2 * 2;
                SpeexMode  = Speex.SPEEX_MODEID_NB;
            }
            else
            {
                Dispose();
                return;
            }


            try
            {
                // init speex
                Speex.speex_bits_init(ref DecodeBits);
                IntPtr modePtr = Speex.speex_lib_get_mode(SpeexMode);
                SpeexDecoder = Speex.speex_decoder_init(modePtr);

                int tmp = 1;
                Speex.speex_decoder_ctl(SpeexDecoder, Speex.SPEEX_SET_ENH, ref tmp);

                // init wave
                Format = new WinMM.WaveFormat(sampleRate, 16, 2);
                WinMM.ErrorCheck(WinMM.waveOutOpen(out WaveHandle, Voices.PlaybackDevice, Format, CallbackHandler, 0, WinMM.CALLBACK_FUNCTION));

                for (int i = 0; i < BufferCount; i++)
                {
                    Buffers[i] = new PlayBuffer(i, WaveHandle, BufferSize);
                }
            }
            catch (Exception ex)
            {
                Dispose();
                Voices.Core.Network.UpdateLog("Voice", "Error starting playing: " + ex.Message);
            }
        }
Example #2
0
        public void Dispose()
        {
            if (HeaderHandle.IsAllocated)
            {
                WinMM.ErrorCheck(WinMM.waveOutUnprepareHeader(WaveHandle, ref Header, Marshal.SizeOf(Header)));

                HeaderHandle.Free();
            }

            if (DataHandle.IsAllocated)
            {
                DataHandle.Free();
            }
        }
Example #3
0
        public PlayBuffer(int index, IntPtr handle, int size)
        {
            WaveHandle = handle;

            HeaderHandle = GCHandle.Alloc(Header, GCHandleType.Pinned);

            Data       = new byte[size];
            DataHandle = GCHandle.Alloc(Data, GCHandleType.Pinned);
            DataPtr    = DataHandle.AddrOfPinnedObject();

            //Header.dwUser = new IntPtr(index); //(IntPtr)GCHandle.Alloc(this);
            Header.lpData         = DataHandle.AddrOfPinnedObject();
            Header.dwBufferLength = size;

            WinMM.ErrorCheck(WinMM.waveOutPrepareHeader(WaveHandle, ref Header, Marshal.SizeOf(Header)));
        }
Example #4
0
        //public IntPtr EchoState;


        public RecordAudio(VoiceService voices)
        {
            Voices = voices;

            CallbackHandler = new WinMM.WaveDelegate(WaveCallback);


            // if 20ms, at high quality (16khz) is 320 samples at 2 bytes each
            if (HighQuality)
            {
                SampleRate = 16000;
                BufferSize = 320 * 2;
                SpeexMode  = Speex.SPEEX_MODEID_WB;
            }
            else
            {
                SampleRate = 8000;
                BufferSize = 160 * 2;
                SpeexMode  = Speex.SPEEX_MODEID_NB;
            }

            //LastBuffer = new byte[BufferSize];

            try
            {
                InitSpeexEncoder();

                Format = new WinMM.WaveFormat(SampleRate, 16, 1);
                WinMM.ErrorCheck(WinMM.waveInOpen(out WaveHandle, Voices.RecordingDevice, Format, CallbackHandler, 0, WinMM.CALLBACK_FUNCTION));

                for (int i = 0; i < BufferCount; i++)
                {
                    Buffers[i] = new RecordBuffer(i, WaveHandle, BufferSize);
                }

                WinMM.ErrorCheck(WinMM.waveInStart(WaveHandle));
            }
            catch (Exception ex)
            {
                Dispose();
                Voices.Core.Network.UpdateLog("Voice", "Error starting recording: " + ex.Message);
            }
        }
Example #5
0
        public void Dispose()
        {
            try
            {
                WinMM.ErrorCheck(WinMM.waveOutReset(WaveHandle));

                // free buffers
                foreach (PlayBuffer buffer in Buffers)
                {
                    buffer.Dispose();
                }
                Buffers = null;

                // free speex
                Speex.speex_bits_destroy(ref DecodeBits);
                Speex.speex_decoder_destroy(SpeexDecoder);

                WinMM.ErrorCheck(WinMM.waveOutClose(WaveHandle));
            }
            catch (Exception ex)
            {
                Voices.Core.Network.UpdateLog("Voice", "Error Disposing Player: " + ex.Message);
            }

            // remove wave out stream from user structure
            foreach (ulong routing in User.Streams.Keys)
            {
                if (User.Streams[routing] == this)
                {
                    User.Streams.Remove(routing);
                    break;
                }
            }

            Voices.Players.SafeRemove(this);
        }
Example #6
0
        public void ProcessBuffers()
        {
            try
            {
                while (FilledBuffers < BufferCount)
                {
                    byte[] data = null;
                    lock (AudioQueue) // either gets called from core, or system thread
                    {
                        if (AudioQueue.Count == 0)
                        {
                            return;
                        }

                        data = AudioQueue.Dequeue();
                    }

                    // keep a log of received audio that user can back track through
                    lock (History)
                    {
                        History.Enqueue(data);

                        while (History.Count > HistoryLength)
                        {
                            History.Dequeue();
                        }
                    }

                    // decode
                    Speex.speex_bits_reset(ref DecodeBits);

                    Speex.speex_bits_read_from(ref DecodeBits, data, data.Length);

                    byte[] mono    = new byte[FrameSize * 2];
                    int    success = Speex.speex_decode_int(SpeexDecoder, ref DecodeBits, mono);

                    if (success != 0)
                    {
                        continue;
                    }

                    // cancel echo
                    //if (Voices.Recorder != null && FrameSize == Voices.Recorder.FrameSize)
                    //   Speex.speex_echo_playback(Voices.Recorder.EchoState, mono);

                    // get volume
                    short maxVolume = 0;
                    for (int i = 0; i < mono.Length / 2; i++)
                    {
                        short val = BitConverter.ToInt16(mono, i * 2);
                        if (val > maxVolume)
                        {
                            maxVolume = val;
                        }
                    }

                    if (maxVolume > User.VolumeIn)
                    {
                        User.VolumeIn = maxVolume;
                    }


                    // find out where audio should come out from, if at all
                    // return down here so that even if user not listening, window shows volume bar
                    AudioDirection direction = User.GetDirection();

                    if (direction == AudioDirection.None)
                    {
                        continue;
                    }


                    // shifting to one side
                    PlayBuffer buffer = Buffers[NextBuffer];

                    for (int i = 0; i < mono.Length / 2; i++)
                    {
                        switch (direction)
                        {
                        case AudioDirection.Both:
                            Buffer.BlockCopy(mono, i * 2, buffer.Data, i * 4, 2);     // left
                            Buffer.BlockCopy(mono, i * 2, buffer.Data, i * 4 + 2, 2); // right
                            break;

                        case AudioDirection.Left:
                            Buffer.BlockCopy(mono, i * 2, buffer.Data, i * 4, 2);     // left
                            break;

                        case AudioDirection.Right:
                            Buffer.BlockCopy(mono, i * 2, buffer.Data, i * 4 + 2, 2);     // right
                            break;
                        }
                    }


                    WinMM.ErrorCheck(WinMM.waveOutWrite(WaveHandle, ref buffer.Header, Marshal.SizeOf(buffer.Header)));

                    FilledBuffers++;

                    NextBuffer++;
                    if (NextBuffer >= BufferCount)
                    {
                        NextBuffer = 0;
                    }
                }
            }
            catch (Exception ex)
            {
                Voices.Core.RunInCoreAsync(() =>
                {
                    Dispose();
                    Voices.Core.Network.UpdateLog("Voice", "Error filling buffers: " + ex.Message);
                });
            }
        }
Example #7
0
        public void ProcessBuffers()
        {
            try
            {
                while (AddedBuffers < BufferCount)
                {
                    RecordBuffer buffer = Buffers[NextBuffer];

                    if (buffer.Added)
                    {
                        EncodeAudio(buffer);
                    }

                    /*if (!EncodeAudio(buffer) && LastBufferSet)
                     * {
                     *  // no data sent - send last buffer so that audio doesnt snap, but fades out
                     *  // reverse - so waves match up
                     *  byte[] frame = new byte[2];
                     *  int backpos = 0;
                     *  for (int i = 0; i < FrameSize / 2; i++)
                     *  {
                     *      backpos = LastBuffer.Length - 2 - i * 2;
                     *      Buffer.BlockCopy(LastBuffer, i * 2, frame, 0, 2); // front to temp
                     *      Buffer.BlockCopy(LastBuffer, backpos, LastBuffer, i * 2, 2); // back to front
                     *      Buffer.BlockCopy(frame, 0, LastBuffer, backpos, 2); // temp to back
                     *  }
                     *
                     *  // fade so no sharp end to the sound
                     *  for (int i = 0; i < FrameSize; i++)
                     *  {
                     *      short value = BitConverter.ToInt16(LastBuffer, i * 2);
                     *      value = (short) (value * (FrameSize - i) / FrameSize);
                     *      BitConverter.GetBytes(value).CopyTo(LastBuffer, i * 2);
                     *  }
                     *
                     *  LastBuffer.CopyTo(buffer.Data, 0);
                     *
                     *  int tmp = 0;
                     *  Speex.speex_encoder_ctl(SpeexEncoder, Speex.SPEEX_SET_VAD, ref tmp);
                     *  Speex.speex_encoder_ctl(SpeexEncoder, Speex.SPEEX_SET_DTX, ref tmp);
                     *
                     *  //EncodeAudio(buffer);
                     *
                     *  tmp = 1;
                     *  Speex.speex_encoder_ctl(SpeexEncoder, Speex.SPEEX_SET_VAD, ref tmp);
                     *  Speex.speex_encoder_ctl(SpeexEncoder, Speex.SPEEX_SET_DTX, ref tmp);
                     *
                     *
                     *  LastBufferSet = false;
                     * }*/

                    WinMM.ErrorCheck(WinMM.waveInAddBuffer(WaveHandle, ref buffer.Header, Marshal.SizeOf(buffer.Header)));
                    buffer.Added = true;

                    NextBuffer++;
                    if (NextBuffer >= BufferCount)
                    {
                        NextBuffer = 0;
                    }

                    AddedBuffers++;
                }
            }
            catch (Exception ex)
            {
                Debug.Assert(false);

                Voices.Core.RunInCoreAsync(() =>
                {
                    Voices.Core.Network.UpdateLog("Voice", "Error in record thread: " + ex.Message);
                    Dispose();
                });
            }
        }
Example #8
0
        public void WaveCallback(IntPtr hdrvr, int uMsg, int dwUser, ref WinMM.WaveHdr wavhdr, int dwParam2)
        {
            if (uMsg == WinMM.MM_WIM_DATA)
            {
                // use dwUser parameter of header to keep buffers in sync?
                // doesnt seem like buffers are getting out of sync at all

                AddedBuffers--;

                Voices.AudioEvent.Set();
            }
        }
Example #9
0
        public void WaveCallback(IntPtr hdrvr, int uMsg, int dwUser, ref WinMM.WaveHdr wavhdr, int dwParam2)
        {
            if (uMsg == WinMM.MM_WOM_DONE)
            {
                FilledBuffers--;

                Voices.AudioEvent.Set();
            }
        }