Пример #1
0
        // Add more buffers to the playback queue - keep it full
        private void RefillPlayBuffers()
        {
            while (m_qBuffers.Count < MaxBuffers)
            {
                int    cb   = (int)(BufferLen * m_format.SamplesPerSec * m_format.Channels);
                byte[] data = new byte[cb];

                for (int i = 0; i < m_streamArray.Count; i++)
                {
                    if (m_streamArray[i] != null)
                    {
                        cb = ((Stream)m_streamArray[i]).Read(data, 0, cb);
                        break;
                    }
                }

                if (cb == 0)
                {
                    break;
                }

                WaveHeader hdr = new WaveHeader(data);
                Monitor.Enter(m_HandleMap.SyncRoot);
                m_HandleMap.Add(hdr.Pointer.ToInt32(), hdr);
                Monitor.Exit(m_HandleMap.SyncRoot);

                // prepare the header
                CheckWaveError(NativeMethods.waveOutPrepareHeader(m_hWaveOut, hdr.Pointer, hdr.HeaderLength));
                Monitor.Enter(m_qBuffers);
                m_qBuffers.Enqueue(hdr);
                Monitor.Exit(m_qBuffers);
            }
        }
Пример #2
0
        /// <summary>
        /// Creates a recording buffer
        /// </summary>
        /// <param name="dwBufferSize"></param>
        /// <returns>new buffer as WaveHeader</returns>
        private WaveHeader GetNewRecordBuffer(int dwBufferSize)
        {
            WaveHeader hdr = new WaveHeader(dwBufferSize);

            Monitor.Enter(m_HandleMap.SyncRoot);
            m_HandleMap.Add(hdr.Pointer.ToInt32(), hdr);
            Monitor.Exit(m_HandleMap.SyncRoot);
            // prepare the header
            CheckWaveError(NativeMethods.waveInPrepareHeader(m_hWaveIn, hdr.Pointer, hdr.HeaderLength));
            return(hdr);
        }
Пример #3
0
        private void m_recmw_WaveDoneMessage(object sender, IntPtr wParam, IntPtr lParam)
        {
            Debug.WriteLine("received WaveDone");
#if !NDOC
            // Retrieve Waveheader object by the lpHeader pointer
            Monitor.Enter(m_HandleMap.SyncRoot);
            WaveHeader hdr = m_HandleMap[lParam.ToInt32()] as WaveHeader;

            m_HandleMap.Remove(hdr.Pointer.ToInt32());
            Monitor.Exit(m_HandleMap.SyncRoot);

            // unprepare the header
            CheckWaveError(NativeMethods.waveInUnprepareHeader(m_hWaveIn, hdr.Pointer, hdr.HeaderLength));
            //      hdr.RetrieveHeader();
            m_qBuffers.Enqueue(hdr);

            if (recordingFinished) // last chunk
            {
                DumpRecordBuffers();
                CheckWaveError(NativeMethods.waveInClose(m_hWaveIn));
                m_streamRecord.Flush();
                m_streamRecord.Close();
                mw_WaveCloseMessage(this);
                // clean up the messageWindow
                m_recmw.Dispose();

                // reset the global flag
                recording = false;
                // set our event
                if (DoneRecording != null)
                {
                    DoneRecording();
                }

                foreach (WaveHeader whdr in m_HandleMap.Values)
                {
                    whdr.Dispose();
                }
                m_HandleMap.Clear();
            }
            else
            {
                hdr = GetNewRecordBuffer(m_recBufferSize);
                CheckWaveError(NativeMethods.waveInAddBuffer(m_hWaveIn, hdr.Pointer, hdr.HeaderLength));
                DumpRecordBuffers();
            }

            if (PositionChanged != null)
            {
                PositionChanged(this, EventArgs.Empty);
            }
#endif
        }
Пример #4
0
        private void DumpRecordBuffers()
        {
            while (m_qBuffers.Count > 0)
            {
                Monitor.Enter(m_qBuffers);
                WaveHeader hdr = (WaveHeader)m_qBuffers.Dequeue();
                Monitor.Exit(m_qBuffers);


                try
                {
                    m_streamRecord.Write(hdr.BufferData, 0, hdr.BytesRecorded);
                    //          m_streamRecord.Write(hdr.GetData(), 0, hdr.BytesRecorded);
                }
                catch (Exception ex)
                {
                    Debug.Write("Exception in stream.Write: " + ex.ToString());
                }
                hdr.Dispose();
            }
        }
Пример #5
0
        private void BufferWriteThreadProc(object header)
        {
            WaveHeader hdr = header as WaveHeader;

            Interlocked.Increment(ref m_workers);

            Debug.WriteLine(string.Format("Queued Worker Thread on header {0} - Flags == {1} [{2} running]", hdr.Pointer.ToString(), hdr.Flags.ToString(), m_workers));

            int ret = NativeMethods.waveOutWrite(m_hWaveOut, hdr.Pointer, hdr.HeaderLength);

            while ((hdr.Flags & WHDR_FLAGS.DONE) == 0)
            {
                Thread.Sleep(1);
            }

            Interlocked.Decrement(ref m_workers);

            Debug.WriteLine(string.Format("Worker Thread on header {0} Completed [{1} remain]", hdr.Pointer.ToString(), m_workers));

            CheckWaveError(NativeMethods.waveOutUnprepareHeader(m_hWaveOut, hdr.Pointer, hdr.HeaderLength));
            hdr.Dispose();
        }
Пример #6
0
        /// <summary>
        /// Record sound data for specified number of seconds using given wave format
        /// The stream will be a properly formatted RIFF file
        /// </summary>
        /// <param name="st">Stream into which recorded samples are written</param>
        /// <param name="Seconds">Seconds of data to record</param>
        /// <param name="format">Sound format to record in.</param>
        public RiffStream RecordFor(Stream st, short Seconds, WaveFormat2 format)
        {
            // only allow 1 recording session at a time
            if (recording)
            {
                throw new InvalidOperationException("Already recording");
            }

            m_hWaveIn = IntPtr.Zero;

            // set our global flag
            recording = true;

            if (m_qBuffers == null)
            {
                m_qBuffers = new Queue <WaveHeader>(MaxBuffers);
            }
            if (m_HandleMap == null)
            {
                m_HandleMap = new System.Collections.Hashtable(MaxBuffers);
            }

            m_recformat = new WaveFormat2();
#if !NDOC
            // create the callback message window
            m_recmw = new SoundMessageWindow();
            m_recmw.WaveDoneMessage  += new WaveDoneHandler(m_recmw_WaveDoneMessage);
            m_recmw.WaveCloseMessage += new WaveCloseHandler(mw_WaveCloseMessage);
            m_recmw.WaveOpenMessage  += new WaveOpenHandler(mw_WaveOpenMessage);
#endif
            bool append = st.Length >= 42;
            if (format.FormatTag == FormatTag.PCM)
            {
                m_recformat = format;
                if (append)
                {
                    m_streamRecord = RiffStream.Append(st);
                }
                else
                {
                    m_streamRecord = RiffStream.OpenWrite(st, m_recformat);
                }
            }
            else
            {
                m_recformat = WaveFormat2.GetPCMWaveFormat(SoundFormats.Mono8bit11kHz);
                if (append)
                {
                    m_streamRecord = ACMStream.Append(st, m_recformat);
                }
                else
                {
                    m_streamRecord = ACMStream.OpenWrite(st, m_recformat, format);
                }
            }
#if !NDOC
            // check for support of selected format
            CheckWaveError(NativeMethods.waveInOpen(out m_hWaveIn, WAVE_MAPPER, m_recformat.GetBytes(), IntPtr.Zero, 0, WAVE_FORMAT_QUERY));

            // open wave device
            CheckWaveError(NativeMethods.waveInOpen(out m_hWaveIn, (uint)m_deviceID, m_recformat.GetBytes(), m_recmw.Hwnd, 0, CALLBACK_WINDOW));

            m_recBufferSize = (int)(Math.Min((int)Seconds, BufferLen) * m_recformat.AvgBytesPerSec);

            for (int i = 0; i < 2; i++)
            {
                WaveHeader hdr = GetNewRecordBuffer(m_recBufferSize);

                // send the buffer to the device
                CheckWaveError(NativeMethods.waveInAddBuffer(m_hWaveIn, hdr.Pointer, hdr.HeaderLength));
            }

            // begin recording
            CheckWaveError(NativeMethods.waveInStart(m_hWaveIn));
            recordingFinished = false;
            m_recTimer        = new Timer(new TimerCallback(RecTimerCallback), this, Seconds * 1000, Timeout.Infinite);
#endif
            return(m_streamRecord);
        }
Пример #7
0
        private void mw_WaveDoneMessage(object sender, IntPtr wParam, IntPtr lParam)
        {
            Monitor.Enter(m_syncRoot);
            try
            {
                if (m_hWaveOut == IntPtr.Zero)
                {
                    return;
                }

                // Are there any pending buffers?
                if (m_qBuffers.Count == 0)
                {
                    try
                    {
                        // No more buffers - wait for all workers to end
                        while (m_workers > 0)
                        {
                            Thread.Sleep(10);
                        }

                        // Close the device
                        CheckWaveError(NativeMethods.waveOutClose(m_hWaveOut));
                        m_playing  = false;
                        m_qBuffers = null;
                        m_hWaveOut = IntPtr.Zero;

                        // Notify clients
                        if (DonePlaying != null)
                        {
                            // On a separate thread in case the app calls Play in the Done handler.
                            ThreadPool.QueueUserWorkItem(RaiseDonePlaying, new Message {
                                LParam = lParam, WParam = wParam
                            });
                        }
                    }
                    catch (Exception e)
                    {
                        if (!e.Message.Equals("Sound still playing"))
                        {
                            throw e;
                        }
                    }
                }
                else
                {
                    //Get next buffer (already prepared)
                    Monitor.Enter(m_qBuffers);
                    WaveHeader hdr = m_qBuffers.Dequeue() as WaveHeader;
                    Monitor.Exit(m_qBuffers);

                    // play the file
                    ThreadPool.QueueUserWorkItem(BufferWriteThreadProc, hdr);

                    // Add more buffers
                    RefillPlayBuffers();
                }

                if (PositionChanged != null)
                {
                    PositionChanged(this, EventArgs.Empty);
                }
            }
            finally
            {
                Monitor.Exit(m_syncRoot);
            }
        }
Пример #8
0
        /// <summary>
        /// Plays waveform contained in the given stream. Stream is exepcted to contain full riff header
        /// </summary>
        /// <param name="playStream">Stream with the waveform</param>
        public void Play(Stream playStream)
        {
            Monitor.Enter(m_syncRoot);
            try
            {
                if (m_playing)
                {
                    return;
                }

                if (playStream == null)
                {
                    throw new Exception("No valid WAV file has been opened");
                }

#if !NDOC
                if (m_qBuffers == null)
                {
                    m_qBuffers = new Queue <WaveHeader>(MaxBuffers);
                }
                if (m_HandleMap == null)
                {
                    m_HandleMap = new System.Collections.Hashtable(MaxBuffers);
                }

                // create a window to catch waveOutxxx messages
                SoundMessageWindow mw = new SoundMessageWindow();

                // wire in events
                mw.WaveOpenMessage  += new WaveOpenHandler(mw_WaveOpenMessage);
                mw.WaveCloseMessage += new WaveCloseHandler(mw_WaveCloseMessage);
                mw.WaveDoneMessage  += new WaveDoneHandler(mw_WaveDoneMessage);

                // add it to the global array
                m_mwArray.Add(mw);
                int i = m_mwArray.Count - 1;
                if (playStream is ACMStream)
                {
                    m_streamArray.Add(playStream as ACMStream);
                }
                else if (playStream is RiffStream)
                {
                    m_streamArray.Add(playStream as RiffStream);
                }
                else
                {
                    m_streamArray.Add(ACMStream.OpenRead(playStream));
                }
                m_format = (m_streamArray[m_streamArray.Count - 1] as RiffStream).Format;

                // open the waveOut device and register the callback
                CheckWaveError(NativeMethods.waveOutOpen(out m_hWaveOut, m_deviceID, m_format.GetBytes(), m_mwArray[i].Hwnd, 0, CALLBACK_WINDOW));

                // see if we need to adjust playback rate
                if ((PlaybackRate < 0.9f) || (PlaybackRate > 1.1f))
                {
                    SetPlaybackRate(PlaybackRate);
                }

                RefillPlayBuffers();

                while (m_qBuffers.Count > 0)
                {
                    Monitor.Enter(m_qBuffers);
                    WaveHeader hdr = m_qBuffers.Dequeue();
                    Monitor.Exit(m_qBuffers);

                    // play the file
                    ThreadPool.QueueUserWorkItem(BufferWriteThreadProc, hdr);

                    m_playing = true;

                    if (m_qBuffers.Count <= 1)
                    {
                        RefillPlayBuffers();
                    }
                }
#endif
            }
            finally
            {
                Monitor.Exit(m_syncRoot);
            }
        }