示例#1
0
        /// <summary>
        /// Fills recording buffers.
        /// </summary>
        private void EnsureBuffers()
        {
            // We keep 3 x buffer.
            lock (m_pBuffers){
                while (m_pBuffers.Count < 3)
                {
                    byte[]   data       = new byte[m_BufferSize];
                    GCHandle dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);

                    WAVEHDR wavHeader = new WAVEHDR();
                    wavHeader.lpData          = dataHandle.AddrOfPinnedObject();
                    wavHeader.dwBufferLength  = (uint)data.Length;
                    wavHeader.dwBytesRecorded = 0;
                    wavHeader.dwUser          = IntPtr.Zero;
                    wavHeader.dwFlags         = 0;
                    wavHeader.dwLoops         = 0;
                    wavHeader.lpNext          = IntPtr.Zero;
                    wavHeader.reserved        = 0;
                    GCHandle headerHandle = GCHandle.Alloc(wavHeader, GCHandleType.Pinned);
                    int      result       = 0;
                    result = WavMethods.waveInPrepareHeader(m_pWavDevHandle, headerHandle.AddrOfPinnedObject(), Marshal.SizeOf(wavHeader));
                    if (result == MMSYSERR.NOERROR)
                    {
                        m_pBuffers.Add(new BufferItem(ref headerHandle, ref dataHandle, m_BufferSize));

                        result = WavMethods.waveInAddBuffer(m_pWavDevHandle, headerHandle.AddrOfPinnedObject(), Marshal.SizeOf(wavHeader));
                        if (result != MMSYSERR.NOERROR)
                        {
                            throw new Exception("Error adding wave in buffer, error: " + result + ".");
                        }
                    }
                }
            }
        }
示例#2
0
 // Initialize a new WAVEHDR with an allocated memory buffer
 private void InitBuffer(ref WAVEHDR buffer, uint frames)
 {
     /*
      * Audio buffers must remain in place within memory while playing,
      * which occurs between WaveOut API calls. In order to prevent the
      * garbage collector from relocating things, memory is allocated to
      * the process heap.
      *
      * lpData is a pointer to the sample data to be played as output,
      * and is allocated on the heap.
      *
      * dwUser is available for application use. In this situation, a
      * WAVEHDR-sized buffer is allocated on the heap, which is used to
      * store a copy of the struct when used in API calls.
      *
      * dwLoops is intended for repeating the buffer multiple times
      * before finishing, but is being used in this class to indicate
      * that the buffer was the last one in the audio stream. The
      * looping feature is disabled and unused because the
      * WHDR_BEGINLOOP and WHDR_ENDLOOP flags are never set in dwFlags.
      */
     buffer.lpData          = Marshal.AllocHGlobal((int)frames * 4);
     buffer.dwBufferLength  = frames * 4;
     buffer.dwBytesRecorded = 0;
     buffer.dwUser          = Marshal.AllocHGlobal((int)WAVEHDR_SIZE);
     buffer.dwFlags         = 0;
     buffer.dwLoops         = 0;
     buffer.lpNext          = IntPtr.Zero;
     buffer.reserved        = IntPtr.Zero;
 }
示例#3
0
文件: WaveIn.cs 项目: otac0n/winmm
        /// <summary>
        /// Processes data and frees buffers that have been used by the application.
        /// </summary>
        private void ProcessDone()
        {
            IntPtr header;

            // Pull the header data back out of unmanaged memory
            lock (this.bufferingLock)
            {
                header = this.bufferReleaseQueue.Dequeue();
                Monitor.Pulse(this.bufferingLock);
            }

            WAVEHDR pwh = (WAVEHDR)Marshal.PtrToStructure(header, typeof(WAVEHDR));

            // Find and copy the buffer data
            IntPtr data = pwh.lpData;

            // Copy the data and fire the DataReady event if necessary
            if (pwh.dwBytesRecorded > 0 && this.DataReady != null)
            {
                byte[] newData = new byte[pwh.dwBytesRecorded];
                Marshal.Copy(data, newData, 0, (int)pwh.dwBytesRecorded);
                this.DataReady(this, new DataReadyEventArgs(newData));
            }

            // Unprepare the header
            NativeMethods.Throw(
                NativeMethods.waveInUnprepareHeader(this.handle, header, Marshal.SizeOf(typeof(WAVEHDR))),
                NativeMethods.ErrorSource.WaveIn);

            // Free the unmanaged memory
            Marshal.FreeHGlobal(data);
            Marshal.FreeHGlobal(header);
        }
示例#4
0
文件: WaveIn.cs 项目: otac0n/winmm
        /// <summary>
        /// Adds a buffer to the queue.
        /// </summary>
        private void AddBuffer()
        {
            // Allocate unmanaged memory for the buffer
            int    bufferLength = this.bufferSize * this.recordingFormat.BlockAlign;
            IntPtr mem          = Marshal.AllocHGlobal(bufferLength);

            // Initialize the buffer header, including a reference to the buffer memory
            WAVEHDR pwh = new WAVEHDR();

            pwh.dwBufferLength = bufferLength;
            pwh.dwFlags        = 0;
            pwh.lpData         = mem;
            pwh.dwUser         = new IntPtr(12345);

            // Copy the header into unmanaged memory
            IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(pwh));

            Marshal.StructureToPtr(pwh, header, false);

            // Prepare the header
            NativeMethods.Throw(
                NativeMethods.waveInPrepareHeader(this.handle, header, Marshal.SizeOf(typeof(WAVEHDR))),
                NativeMethods.ErrorSource.WaveOut);

            // Add the buffer to the device
            NativeMethods.Throw(
                NativeMethods.waveInAddBuffer(this.handle, header, Marshal.SizeOf(typeof(WAVEHDR))),
                NativeMethods.ErrorSource.WaveOut);

            lock (this.bufferingLock)
            {
                this.bufferQueueCount++;
                Monitor.Pulse(this.bufferingLock);
            }
        }
示例#5
0
        private void Prepare()
        {
            System.Diagnostics.Debug.Write("call waveOutPrepareHeader");

            Thread.Sleep(100); // これがないとなぜか落ちる

            for (int i = 0; i < WAVEHDR_NUM_; ++i)
            {
                wave_hdr_list_[i] = new WAVEHDR();

                wave_hdr_list_[i].lpData          = Marshal.AllocHGlobal(buffer_length_);
                wave_hdr_list_[i].dwBufferLength  = (uint)buffer_length_;
                wave_hdr_list_[i].dwBytesRecorded = 0;
                wave_hdr_list_[i].dwUser          = (uint)i;
                wave_hdr_list_[i].dwFlags         = 0;
                wave_hdr_list_[i].dwLoops         = 1;
                wave_hdr_list_[i].lpNext          = (IntPtr)0;
                wave_hdr_list_[i].reserved        = 0;

                // アンマネージドオブジェクト(WAVEHDR)を確保
                p_wave_hdr_list_[i] = Marshal.AllocHGlobal(WAVEHDR_STRUCT_SIZE_);
                Marshal.StructureToPtr(wave_hdr_list_[i], p_wave_hdr_list_[i], false);

                uint error_code = waveOutPrepareHeader(h_wave_out_, p_wave_hdr_list_[i], WAVEHDR_STRUCT_SIZE_);
                if (error_code != 0)
                {
                    throw new WaveOutApiException("waveOutPrepareHeader " + h_wave_out_.ToInt32().ToString(), error_code);
                }
            }

            state_ = StateKind.Prepared;
        }
示例#6
0
        private void WaveCallbackProc(IntPtr h_wave_out, uint message, uint instance, uint param1, uint param2)
        {
            System.Diagnostics.Debug.Write("called WaveCallbackProc : " + message + ", " + param1 + ", " + param2);

            switch (message)
            {
            case MM_WOM_OPEN:
                // waveOutPrepareHeader をこのスレッドで呼んではいけないので、
                // 別スレッドを作って呼び出す。
                Thread t = new Thread(new ThreadStart(Prepare));
                t.IsBackground = true;
                t.Start();
                break;

            case MM_WOM_CLOSE:
                for (int i = 0; i < WAVEHDR_NUM_; ++i)
                {
                    waveOutUnprepareHeader(h_wave_out_, p_wave_hdr_list_[i], WAVEHDR_STRUCT_SIZE_);
                    Marshal.FreeHGlobal(p_wave_hdr_list_[i]);
                }
                close_event_.Set();     // 後処理完了を通知
                break;

            case MM_WOM_DONE:
                IntPtr  ptr      = new IntPtr(param1);
                WAVEHDR wave_hdr = (WAVEHDR)Marshal.PtrToStructure(ptr, typeof(WAVEHDR));
                int     index    = (int)wave_hdr.dwUser; // 何番目の WAVEHDR 構造体かを取得
                waiting_manager_.Set(index);             // 再生完了のシグナル
                break;
            }
        }
示例#7
0
        /// コールバック関数
        void wave_callback(IntPtr hwo, uint uMsg, uint dwInstance, uint dwParam1, uint dwParam2)
        {
#if DEBUG
            Console.WriteLine("WavePlay.wave_callback; uMsg=" + uMsg);
#endif
            if (uMsg == win32.MM_WOM_DONE)
            {
                int     index_done = 0;
                WAVEHDR whdr       = (WAVEHDR)Marshal.PtrToStructure(new IntPtr(dwParam1), typeof(WAVEHDR));
                int     dwuser     = whdr.dwUser.ToInt32();
                if (dwuser >= _NUM_BUF)
                {
                    index_done = dwuser - _NUM_BUF;
                }
                else
                {
                    index_done = dwuser;
                }
                if (0 <= index_done && index_done < _NUM_BUF)
                {
                    s_done[index_done] = true;
                    if (s_last_buffer == index_done)
                    {
                        s_playing = false;
                    }
                    if (dwuser >= _NUM_BUF)
                    {
                        s_wave_header[index_done].dwUser = new IntPtr(index_done);
                    }
                }
            }
        }
示例#8
0
文件: WaveOut.cs 项目: otac0n/winmm
        /// <summary>
        /// Writes a block of data (in the current forma, set during Open) to the device.
        /// </summary>
        /// <param name="bufferData">The data to send to the device.</param>
        public void Write(byte[] bufferData)
        {
            lock (this.startStopLock)
            {
                IntPtr mem = Marshal.AllocHGlobal(bufferData.Length);
                Marshal.Copy(bufferData, 0, mem, bufferData.Length);

                WAVEHDR pwh = new WAVEHDR();
                pwh.dwBufferLength = bufferData.Length;
                pwh.dwFlags        = 0;
                pwh.lpData         = mem;
                pwh.dwUser         = new IntPtr(12345);

                IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(pwh));
                Marshal.StructureToPtr(pwh, header, false);

                NativeMethods.Throw(
                    NativeMethods.waveOutPrepareHeader(this.handle, header, Marshal.SizeOf(typeof(WAVEHDR))),
                    NativeMethods.ErrorSource.WaveOut);

                NativeMethods.Throw(
                    NativeMethods.waveOutWrite(this.handle, header, Marshal.SizeOf(typeof(WAVEHDR))),
                    NativeMethods.ErrorSource.WaveOut);

                lock (this.bufferingLock)
                {
                    this.bufferQueueCount++;
                    Monitor.Pulse(this.bufferingLock);
                }
            }
        }
示例#9
0
        /*  SetupBuffer
         *
         *  Setups header and buffer used for recording
         *
         *  Return void
         */
        private void setupBuffer()
        {
            pWaveHdr1                 = new WAVEHDR();
            pWaveHdr1.lpData          = bufferPin.AddrOfPinnedObject();
            pWaveHdr1.dwBufferLength  = INP_BUFFER_SIZE;
            pWaveHdr1.dwBytesRecorded = 0;
            pWaveHdr1.dwUser          = IntPtr.Zero;
            pWaveHdr1.dwFlags         = 0;
            pWaveHdr1.dwLoops         = 1;
            pWaveHdr1.lpNext          = IntPtr.Zero;
            pWaveHdr1.reserved        = (System.IntPtr)null;

            int i = waveInPrepareHeader(handle, ref pWaveHdr1, Convert.ToUInt32(Marshal.SizeOf(pWaveHdr1)));

            if (i != 0)
            {
                this.Text = "Error: waveInPrepare " + i.ToString();
                return;
            }

            i = waveInAddBuffer(handle, ref pWaveHdr1, Convert.ToUInt32(Marshal.SizeOf(pWaveHdr1)));
            if (i != 0)
            {
                this.Text = "Error: waveInAddrBuffer";
                return;
            }
        }
示例#10
0
        public MediaSample(int bufferSize)
        {
            // Create the header
            fHeader = new WAVEHDR(bufferSize);

            // Get a pinned handle on the header
            fHeaderHandle = GCHandle.Alloc(fHeader, GCHandleType.Pinned);
        }
示例#11
0
        public RecordingBuffer(int iSize, IntPtr ipHandle)
        {
            m_Head   = new WAVEHDR(iSize);
            m_Handle = GCHandle.Alloc(m_Head, GCHandleType.Pinned);

            int mmr = waveIn.PrepareHeader(ipHandle, m_Head, Marshal.SizeOf(m_Head));

            waveIn.ThrowExceptionForError(mmr);
        }
示例#12
0
文件: __WaveOut__.cs 项目: daisy/obi
        private static void PrepareHeader(IntPtr waveOutHandle, ref WAVEHDR waveOutHeader, uint size)
        {
            uint err = waveOutPrepareHeader(waveOutHandle, ref waveOutHeader, size);

            if (err != 0)
            {
                throw new Exception("Error preparing header: " + GetErrorText(err) + ".");
            }
        }
示例#13
0
        /// <summary>
        /// Write a sample to the file
        /// </summary>
        /// <param name="wh"></param>
        private void WriteSample(WAVEHDR wh)
        {
            int iBytes = MMIO.Write(m_OutputFile, wh.lpData, wh.dwBytesRecorded);

            if (iBytes < 0)
            {
                throw new Exception("Write Failed");
            }
            m_AudioLength += iBytes;
        }
示例#14
0
      ///
      /// Opens the audio system, enqueues buffers, and otherwise
      /// gets us ready to play.
      ///
      public void Open()
      {
         lock (_mainLock)
         {
            if (_isOpen)
               throw new ApplicationExcption( "Open while already open" );
            
            WAVEFORMATEX wfx = new WAVEFORMATEX();
            wfx.wFormatTag = WAVE_FORMAT_PCM;
            wfx.nChannels = 2;     // stereo
            wfx.nSamplesPerSec = 44100;
            wfx.nBlockAlign = 4;   // four bytes per frame, see?
            wfx.wBitsPerSample = 16;
            wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
            wfx.cbSize = 0; // no extra info

            int status = waveOutOpen( out _waveOutHandle,
                                      WAVE_MAPPER, 
                                      wfx, 
                                      _playEvent.SafeWaitHandle,
                                      CALLBACK_EVENT,
                                      0
                                      );
            
            if (status != MMSYSERR_NOERROR) 
            {
               throw new ApplicationException(
                  "unable to open the default WAVE device" );
            }

            _isOpen = true;
            
            // Create audio buffers, including unmanaged data buffers
            for (int i = 0; i < N_WAVE_HEADERS; i++)
            {
               WAVEHDR header = new WAVEHDR();

               IntPtr data = Marshal.AllocHGlobal( size );
               
               header.lpData = data;     // pointer to the data buffer
               header.dwBufferLength = 0; // set on each call
               header.dwBytesRecorded = 0;
               header.dwUser = size; // hide the real buffer size here
               header.dwFlags = WHDR_DONE; // so it'll get enqueued
               header.dwLoops = 0;
               header.lpNext = 0;  // we don't mess with this pointer
               header.reserved;    // or this int

               // Yeah, this sucker's gonna be pinned for the duration.
               // This is probably bad. It is better if we unpin it on
               // each buffer switch? Probably not.
               _waveHdr[i] = GCHandle.Alloc( header, GCHandldType.Pinned );
            }
         }
      }
示例#15
0
 private void Timer_Elapsed(object sender, ElapsedEventArgs e)
 {
     if ((data.Flags & WaveHdrFlags.WHDR_DONE) == 0) // still running
     {
         // updated managed data
         data = (WAVEHDR)Marshal.PtrToStructure(dataPointer, typeof(WAVEHDR));
     }
     else // finished
     {
         Close();
     }
 }
示例#16
0
 internal static void WaveOutProc(IntPtr hdrvr, int uMsg, int dwUser, ref WAVEHDR wavhdr, int dwParam2)
 {
     if (uMsg == WaveNative.MM_WOM_DONE)
     {
         try
         {
             GCHandle      h   = (GCHandle)wavhdr.dwUser;
             WaveOutBuffer buf = (WaveOutBuffer)h.Target;
             buf.OnCompleted();
         }
         catch
         { }
     }
 }
示例#17
0
 // System-invoked callback for audio output events
 private void waveOutProc(IntPtr hwo, uint uMsg, IntPtr dwInstance,
                          ref WAVEHDR buffer, IntPtr dwParam2)
 {
     /*
      * Inform the main thread that the buffer has finished. The reason
      * this is done with a concurrent collection is because system
      * function calls are not permitted by the thread that calls
      * waveOutProc(). This mechanism essentially transfers control of
      * the event handler to the thread created in Play().
      */
     if (uMsg == MM_WOM_DONE)
     {
         BuffersDone.Add(buffer);
     }
 }
示例#18
0
        public async Task PlayWave(RiffCodec riff)
        {
            uint   WAVE_MAPPER   = uint.MaxValue;
            int    CALLBACK_NULL = 0;
            IntPtr handle        = IntPtr.Zero;

            var header   = riff.FormatHeader as WaveFormatHeader;
            int duration = Convert.ToInt32(header.AvgBytesPerSec / header.SampleRate);

            var waveFormat = new WAVEFORMAT
            {
                wFormatTag      = header.FormatTag,
                nChannels       = header.ChannelsCount,
                nSamplesPerSec  = header.SampleRate,
                nAvgBytesPerSec = header.AvgBytesPerSec,
                nBlockAlign     = header.BlockAlign,
                wBitsPerSample  = header.BitsPerSample,
                cbSize          = header.ExtraInfoSize
            };

            var waveHdr = new WAVEHDR
            {
                dwBufferLength  = riff.DataSize,
                dwBytesRecorded = riff.DataSize,
                dwUser          = 0,
                dwFlags         = 0,
                dwLoops         = 0
            };

            using var buffer = new UnamanagedMemory((int)riff.DataSize);
            Marshal.Copy(riff.Data, 0, buffer.Pointer, riff.Data.Length);
            waveHdr.lpData = buffer.Pointer;

            uint res = uint.MaxValue;

            res = WindowsMultimedia.waveOutOpen(ref handle, WAVE_MAPPER, ref waveFormat, 0, 0, CALLBACK_NULL);
            CheckMethodResult(nameof(WindowsMultimedia.waveOutOpen), res);

            res = WindowsMultimedia.waveOutPrepareHeader(handle, ref waveHdr, Marshal.SizeOf(waveHdr));
            CheckMethodResult(nameof(WindowsMultimedia.waveOutPrepareHeader), res);

            res = WindowsMultimedia.waveOutWrite(handle, ref waveHdr, Marshal.SizeOf(waveHdr));
            CheckMethodResult(nameof(WindowsMultimedia.waveOutWrite), res);
            await Task.Delay(duration * 1000);

            res = WindowsMultimedia.waveOutClose(handle);
            CheckMethodResult(nameof(WindowsMultimedia.waveOutClose), res);
        }
示例#19
0
        public INSBuf(IntPtr waveHandle, int iMaxBuf)
        {
            m_MaxLen = iMaxBuf;
            m_Head   = new WAVEHDR(iMaxBuf);
            m_Head.dwBytesRecorded = 0;

            // Since waveOutWrite will continue to the buffer after the call
            // returns, the buffer must be fixed in place.
            m_Handle = GCHandle.Alloc(m_Head, GCHandleType.Pinned);

            int mmr = waveOut.PrepareHeader(waveHandle, m_Head, Marshal.SizeOf(typeof(WAVEHDR)));

            waveOut.ThrowExceptionForError(mmr);

            // Make it easier for IsBufferFree() to determine when buffers are free
            m_Head.dwFlags |= WAVEHDR.WHDR.Done;
        }
示例#20
0
        /// <summary>
        /// wavInヘッダをひとつ準備します。
        /// 使用前にWAVEHDR構造体のlpData,dwBufferLength,dwFlagsを初期化してください。
        /// dwFlags = 0にしてください。
        /// </summary>
        public void WaveInPrepareHeader(ref WAVEHDR whdr)
        {
            //初期化
            whdr.dwBytesRecorded = 0;
            whdr.dwFlags         = 0;

            //ヘッダの中身をポインタに写す。写す前にアンマネージ領域
            Marshal.StructureToPtr(whdr, this.WaveHeaderPtr, true);


            //エラーが発生したら例外を投げる
            MMRESULT result = waveInPrepareHeader(this.WaveInHandle, this.WaveHeaderPtr, (uint)Marshal.SizeOf(whdr));

            if (result != MMRESULT.MMSYSERR_NOERROR)
            {
                Exception e = new Exception("WaveInPrepareHeader:" + result + "\r\nエラーが発生しました。");
            }
        }
示例#21
0
文件: __WaveOut__.cs 项目: daisy/obi
        private static void WaveFeed(IntPtr handle, uint message, uint user, ref WAVEHDR header, uint param2)
        {
            switch (message)
            {
            case MM_WOM_OPEN:
                Console.WriteLine("!!! OPEN !!!");
                break;

            case MM_WOM_CLOSE:
                Console.WriteLine("!!! CLOSE !!!");
                break;

            case MM_WOM_DONE:
                Console.WriteLine("!!! DONE !!!");
                break;

            default:
                Console.WriteLine("??? {0}", message);
                break;
            }
        }
示例#22
0
文件: WaveOut.cs 项目: otac0n/winmm
        /// <summary>
        /// Frees buffers that have been used by the application.
        /// </summary>
        private void ProcessDone()
        {
            IntPtr header;

            // Pull the header data back out of unmanaged memory
            lock (this.bufferingLock)
            {
                header = this.bufferReleaseQueue.Dequeue();
                Monitor.Pulse(this.bufferingLock);
            }

            WAVEHDR pwh  = (WAVEHDR)Marshal.PtrToStructure(header, typeof(WAVEHDR));
            IntPtr  data = pwh.lpData;

            NativeMethods.Throw(
                NativeMethods.waveOutUnprepareHeader(this.handle, header, Marshal.SizeOf(typeof(WAVEHDR))),
                NativeMethods.ErrorSource.WaveOut);

            Marshal.FreeHGlobal(data);
            Marshal.FreeHGlobal(header);
        }
示例#23
0
		public void QueueDataBlock(Stream stream)
		{
			// Reset the stream position and keep track of the previous position.
			// The former position tells how much data we need to copy.
			stream.Flush();
			int l = (int)stream.Position;

			// Allocate unmanaged memory to store samples from stream
			var ptrData = Marshal.AllocHGlobal(l);

			// Populate a WAVEHDR with samples
			WAVEHDR hdr;
			using (var ums = new UnmanagedMemoryStream((byte*)ptrData.ToPointer(), l, l, FileAccess.ReadWrite))
			{
				stream.SetLength(l);
				stream.Position = 0;
				stream.CopyTo(ums, l);
				stream.Position = 0;
				ums.Position = 0;
				hdr = new WAVEHDR
				{
					BufferLength = (uint)l,
					Data = new IntPtr(ums.PositionPointer)
				};
			}

			// Copy WAVEHDR instance to unmanaged space
			var ptrHdr = Marshal.AllocHGlobal(sizeof(WAVEHDR));
			Marshal.StructureToPtr(hdr, ptrHdr, false);

			// Prepare the header and queue it
			MMRESULT result;
			if ((result = waveOutPrepareHeader(_ptrOutputDevice, ptrHdr, sizeof(WAVEHDR))) != MMRESULT.MMSYSERR_NOERROR)
				throw new ExternalException($"Function 'waveOutPrepareHeader' returned error code {result}");
			if ((result = waveOutWrite(_ptrOutputDevice, ptrHdr, sizeof(WAVEHDR))) != MMRESULT.MMSYSERR_NOERROR)
				throw new ExternalException($"Function 'waveOutWrite' returned error code {result}");

			// Increment queue size
			_queueSize++;
		}
示例#24
0
        // Fill and play the next audio buffer
        // Returns true if the buffer was skipped
        private bool FillAndPlay(ref WAVEHDR buffer)
        {
            // Error checking
            if (Finished)
            {
                return(true);
            }

            // Request samples from the application
            uint frames = OnNext(SamplesF, 0, (uint)SamplesF.Length / 2);

            // If zero samples were given, assume end of stream
            if (frames == 0)
            {
                Finish();
                return(true);
            }

            // Process samples into output format
            for (uint x = 0; x < frames * 2; x++)
            {
                float sample = Math.Min(Math.Max(SamplesF[x], -1.0f), 1.0f);
                SamplesS[x] = (short)Math.Round(sample * 32767.0f);
            }

            // Configure the buffer and make a copy of it in process memory
            buffer.dwBufferLength = frames * 4;
            buffer.dwFlags        = 0;
            buffer.dwLoops        = (uint)(Finished ? 1 : 0);
            Marshal.StructureToPtr(buffer, buffer.dwUser, true);

            // Send the buffer to the audio output stream
            Marshal.Copy(SamplesS, 0, buffer.lpData, (int)frames * 2);
            waveOutPrepareHeader(WaveHandle, buffer.dwUser, WAVEHDR_SIZE);
            waveOutWrite(WaveHandle, buffer.dwUser, WAVEHDR_SIZE);

            // The buffer was not skipped
            return(false);
        }
示例#25
0
            /// <summary>
            /// Default constructor.
            /// </summary>
            /// <param name="wavDevHandle">Wave in device handle.</param>
            /// <param name="dataSize">Data buffer size in bytes.</param>
            public BufferItem(IntPtr wavDevHandle, int dataSize)
            {
                m_WavDevHandle = wavDevHandle;

                m_ThisHandle = GCHandle.Alloc(this);

                m_pBuffer    = new byte[dataSize];
                m_DataHandle = GCHandle.Alloc(m_pBuffer, GCHandleType.Pinned);

                m_Header                 = new WAVEHDR();
                m_Header.lpData          = m_DataHandle.AddrOfPinnedObject();
                m_Header.dwBufferLength  = (uint)dataSize;
                m_Header.dwBytesRecorded = 0;
                m_Header.dwUser          = (IntPtr)m_ThisHandle;
                m_Header.dwFlags         = 0;
                m_Header.dwLoops         = 0;
                m_Header.lpNext          = IntPtr.Zero;
                m_Header.reserved        = 0;

                m_HeaderHandle = GCHandle.Alloc(m_Header, GCHandleType.Pinned);

                m_pEventArgs = new EventArgs <byte[]>(m_pBuffer);
            }
示例#26
0
                public Wave(IntPtr handle, short[] data)
                {
                    timer.Interval  = 20;
                    timer.AutoReset = true;
                    timer.Elapsed  += Timer_Elapsed;

                    this.handle = handle;
                    dataPointer = Marshal.AllocHGlobal(Marshal.SizeOf(this.data));

                    this.data.Data = Marshal.AllocHGlobal(data.Length * 2);
                    Marshal.Copy(data, 0, this.data.Data, data.Length);
                    this.data.BufferLength = (uint)data.Length * 2;
                    this.data.Flags        = 0;

                    Marshal.StructureToPtr(this.data, dataPointer, true);

                    if (waveOutPrepareHeader(handle, dataPointer, Marshal.SizeOf(this.data)) != 0)
                    {
                        throw new ExceptionAudio("Unable to play wave.");
                    }

                    this.data = (WAVEHDR)Marshal.PtrToStructure(dataPointer, typeof(WAVEHDR));
                }
示例#27
0
        /// <summary>
        /// Thread to process samples when the recording device is done with them
        /// </summary>
        private void ProcSample()
        {
            int iCount      = 0;
            int iNextSample = 0;

            // Notify that thread is started
            m_ProcReady.Set();

            do
            {
                // Notify that we are ready to process samples
                m_ProcReady.Set();

                //  Wait for the callback to receive a sample
                m_Sample.WaitOne();

                if (!m_Closing)
                {
                    WAVEHDR wh = m_Buffers[iNextSample].GetHdr();

                    WriteSample(wh);

                    // Send the buffer back to the recording device for re-use
                    int mmr = waveIn.AddBuffer(m_hDevice, m_Buffers[iNextSample].GetPtr(), Marshal.SizeOf(typeof(WAVEHDR)));
                    waveIn.ThrowExceptionForError(mmr);
                }
                else
                {
                    iCount++;
                }
                // Loop around
                iNextSample = (iNextSample + 1) % RECORDINGBUFFERS;
            } while (iCount < RECORDINGBUFFERS);

            Debug.WriteLine("Thread Exiting");
            m_ProcReady.Set();
        }
        public static extern int waveOutPrepareHeader(
		int hWaveOut,
		ref   WAVEHDR lpWaveOutHdr,
		int uSize
		);
示例#29
0
 public void Write(WAVEHDR pwh)
 {
     MmException.Try(winmm.waveOutWrite(DeviceHandle, pwh, (int)Marshal.SizeOf(typeof(WAVEHDR))), "waveOutWrite");
 }
示例#30
0
        //public void AddBuffer(IntPtr pwh)
        //{
        //    EnsureOpen();

        //    PrepareHeader(pwh);
        //    MmException.Try(winmm.waveInAddBuffer(DeviceHandle, pwh, (int)Marshal.SizeOf(typeof(WAVEHDR))), "waveInAddBuffer");
        //}

        //public int AddBuffer(ref WAVEHDR pwh)
        //{

        //    int result = AddBuffer(ref pwh, (int)Marshal.SizeOf(typeof(WAVEHDR)));

        //    return result;
        //}

        //protected int AddBuffer(ref WAVEHDR pwh, int cbwh)
        //{
        //    EnsureOpen();
        //    PrepareHeader(pwh);
        //    int result = winmm.waveInAddBuffer(DeviceHandle, ref pwh, cbwh);

        //    return result;
        //}

        //public void PrepareHeader(IntPtr pwh)
        //{
        //    EnsureOpen();

        //    MmException.Try(winmm.waveInPrepareHeader(DeviceHandle, pwh, (int)Marshal.SizeOf(typeof(WAVEHDR))), "waveInPrepareHeader");
        //}

        //public int PrepareHeader(WAVEHDR pwh)
        //{
        //    int result = PrepareHeader(pwh, (int)Marshal.SizeOf(typeof(WAVEHDR)));

        //    return result;
        //}

        //protected int PrepareHeader(WAVEHDR pwh, int cbwh)
        //{
        //    EnsureOpen();

        //    int result = winmm.waveInPrepareHeader(DeviceHandle, ref pwh, cbwh);

        //    return result;
        //}

        //public void UnprepareHeader(IntPtr pwh)
        //{
        //    EnsureOpen();

        //    MmException.Try(winmm.waveInUnprepareHeader(DeviceHandle, pwh, (int)Marshal.SizeOf(typeof(WAVEHDR))), "waveInUnprepareHeader");
        //}

        public int UnprepareHeader(WAVEHDR pwh)
        {
            EnsureOpen();

            int result = winmm.waveInUnprepareHeader(DeviceHandle, pwh, (int)Marshal.SizeOf(pwh));

            return result;
        }
        public static extern int waveOutWrite(
		int hWaveOut,
		ref   WAVEHDR lpWaveOutHdr,
		int uSize
		);
示例#32
0
 public void ReturnSample(WAVEHDR aSample)
 {
     fAvailableSamples.Enqueue(aSample);
 }
 public static extern int waveInAddBuffer(int hWaveIn, ref   WAVEHDR lpWaveInHdr, int uSize);
 public static extern int waveInUnprepareHeader(int hWaveIn, ref   WAVEHDR lpWaveInHdr, int uSize);
示例#35
0
            /// <summary>
            /// Plays specified audio data bytes. If player is currently playing, data will be queued for playing.
            /// </summary>
            /// <param name="audioData">Audio data. Data boundary must n * BlockSize.</param>
            /// <param name="offset">Offset in the buffer.</param>
            /// <param name="count">Number of bytes to play form the specified offset.</param>
            /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and this method is accessed.</exception>
            /// <exception cref="ArgumentNullException">Is raised when <b>audioData</b> is null.</exception>
            /// <exception cref="ArgumentException">Is raised when <b>audioData</b> is with invalid length.</exception>
            public void Play(byte[] audioData,int offset,int count)
            {
                if(m_IsDisposed){
                    throw new ObjectDisposedException("WaveOut");
                }
                if(audioData == null){
                    throw new ArgumentNullException("audioData");
                }
                if((count % m_BlockSize) != 0){
                    throw new ArgumentException("Audio data is not n * BlockSize.");
                }

                //--- Queue specified audio block for play. --------------------------------------------------------
                byte[]   data       = new byte[count];
                Array.Copy(audioData,offset,data,0,count);
                GCHandle dataHandle = GCHandle.Alloc(data,GCHandleType.Pinned);

                WAVEHDR wavHeader = new WAVEHDR();
                wavHeader.lpData          = dataHandle.AddrOfPinnedObject();
                wavHeader.dwBufferLength  = (uint)data.Length;
                wavHeader.dwBytesRecorded = 0;
                wavHeader.dwUser          = IntPtr.Zero;
                wavHeader.dwFlags         = 0;
                wavHeader.dwLoops         = 0;
                wavHeader.lpNext          = IntPtr.Zero;
                wavHeader.reserved        = 0;
                GCHandle headerHandle = GCHandle.Alloc(wavHeader,GCHandleType.Pinned);
                int result = 0;        
                result = WavMethods.waveOutPrepareHeader(m_pWavDevHandle,headerHandle.AddrOfPinnedObject(),Marshal.SizeOf(wavHeader));
                if(result == MMSYSERR.NOERROR){
                    PlayItem item = new PlayItem(ref headerHandle,ref dataHandle,data.Length);
                    m_pPlayItems.Add(item);

                    // We ran out of minimum buffer, we must pause playing while min buffer filled.
                    if(m_BytesBuffered < 1000){
                        if(!m_IsPaused){
                            WavMethods.waveOutPause(m_pWavDevHandle);
                            m_IsPaused = true;
                        }
                    }
                    // Buffering completed,we may resume playing.
                    else if(m_IsPaused && m_BytesBuffered > m_MinBuffer){
                        WavMethods.waveOutRestart(m_pWavDevHandle);
                        m_IsPaused = false;
                    }

                    m_BytesBuffered += data.Length;

                    result = WavMethods.waveOutWrite(m_pWavDevHandle,headerHandle.AddrOfPinnedObject(),Marshal.SizeOf(wavHeader));
                }
                else{
                    dataHandle.Free();
                    headerHandle.Free();
                }
                //--------------------------------------------------------------------------------------------------
            }
 static extern uint waveOutUnprepareHeader(IntPtr hwo, WAVEHDR* wh, uint cbwh);
示例#37
0
文件: AudioIn.cs 项目: dioptre/nkd
            /// <summary>
            /// Fills recording buffers.
            /// </summary>
            private void CreateBuffers()
            {               
                while(m_pBuffers.Count < 10){
                    byte[]   data       = new byte[m_BufferSize];
                    GCHandle dataHandle = GCHandle.Alloc(data,GCHandleType.Pinned);

                    WAVEHDR wavHeader = new WAVEHDR();
                    wavHeader.lpData          = dataHandle.AddrOfPinnedObject();
                    wavHeader.dwBufferLength  = (uint)data.Length;
                    wavHeader.dwBytesRecorded = 0;
                    wavHeader.dwUser          = IntPtr.Zero;
                    wavHeader.dwFlags         = 0;
                    wavHeader.dwLoops         = 0;
                    wavHeader.lpNext          = IntPtr.Zero;
                    wavHeader.reserved        = 0;
                    GCHandle headerHandle = GCHandle.Alloc(wavHeader,GCHandleType.Pinned);
                    int result = 0;        
                    result = waveInPrepareHeader(m_pWavDevHandle,headerHandle.AddrOfPinnedObject(),Marshal.SizeOf(wavHeader));                    
                    if(result != MMSYSERR.NOERROR){
                        throw new Exception("Error preparing wave in buffer, error: " + result + ".");
                    }
                    else{
                        m_pBuffers.Add(new BufferItem(ref headerHandle,ref dataHandle,m_BufferSize));

                        result = waveInAddBuffer(m_pWavDevHandle,headerHandle.AddrOfPinnedObject(),Marshal.SizeOf(wavHeader));
                        if(result != MMSYSERR.NOERROR){
                            throw new Exception("Error adding wave in buffer, error: " + result + ".");
                        }
                    }
                } 
               
                m_pCurrentBuffer = m_pBuffers[0];
            }
 public static extern int waveOutPrepareHeader(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, int uSize);
示例#39
0
 private static extern uint waveOutWrite(IntPtr phwi, ref WAVEHDR pwh, uint cbwh);
示例#40
0
 private static extern uint waveInAddBuffer(IntPtr phwi, ref WAVEHDR pwh, uint cbwh);
示例#41
0
 int waveOutWrite( IntPtr waveOutHandle,
                   ref WAVEHDR waveHeader,
                   int size );
示例#42
0
 public void PrepareHeader(WAVEHDR pwh)
 {
     MmException.Try(winmm.waveOutPrepareHeader(DeviceHandle, pwh, (int)Marshal.SizeOf(pwh)), "waveOutPrepareHeader");
 }
示例#43
0
 private static extern uint waveOutUnprepareHeader(IntPtr phwi, ref WAVEHDR pwh, uint cbwh);
 static extern uint waveOutWrite(IntPtr hwo, WAVEHDR* wh, uint cbwh);
示例#45
0
    internal static void DSP_Play(byte[] data)
    {
        uint       len;
        int        freq;
        MMSYSERROR res;
        var        dataPointer = 0;

        DSP_Stop();

        dataPointer += Read_LE_UInt16(data.AsSpan(20));

        if (data[dataPointer] != 1)
        {
            return;
        }

        len = (Read_LE_UInt32(data.AsSpan(dataPointer)) >> 8) - 2;

        if (s_dataLen < len)
        {
            Array.Resize(ref s_data, (int)len); //s_data = realloc(s_data, len);
            s_dataLen = len;
        }

        Array.Copy(data, dataPointer + 6, s_data, 0, len); //memcpy(s_data, data + 6, len);

        freq = 1000000 / (256 - data[dataPointer + 4]);

        var waveFormat = new WAVEFORMATEX
        {
            wFormatTag      = (short)WaveFormatTag.Pcm, //WAVE_FORMAT_PCM;
            nChannels       = 1,
            nSamplesPerSec  = freq,
            nAvgBytesPerSec = freq,
            nBlockAlign     = 1,
            wBitsPerSample  = 8,
            cbSize          = 0 //sizeof(WAVEFORMATEX);
        };

        res = waveOutOpen(ref s_waveOut, WaveOutMapperDeviceId /*WAVE_MAPPER*/, ref waveFormat, DSP_Callback_Del, IntPtr.Zero, WaveOpenFlags.CALLBACK_FUNCTION /*CALLBACK_FUNCTION*/);
        if (res != MMSYSERROR.MMSYSERR_NOERROR)
        {
            Trace.WriteLine($"ERROR: waveOutOpen failed ({res})");
            s_waveOut = IntPtr.Zero;
            return;
        }

        s_dataAddr = Marshal.AllocHGlobal(s_data.Length);

        unsafe { fixed(sbyte *first = s_data) Unsafe.CopyBlock(s_dataAddr.ToPointer(), first, (uint)s_data.Length); }

        var s_waveHdr = new WAVEHDR
        {
            lpData         = s_dataAddr, //s_data
            dwBufferLength = (int)len,
            dwFlags        = 0,
            dwLoops        = 0
        };

        s_waveHdrAddr = Marshal.AllocHGlobal(Marshal.SizeOf(s_waveHdr));
        Marshal.StructureToPtr(s_waveHdr, s_waveHdrAddr, false);

        res = waveOutPrepareHeader(s_waveOut, s_waveHdrAddr, Marshal.SizeOf(typeof(WAVEHDR)));
        if (res != MMSYSERROR.MMSYSERR_NOERROR)
        {
            Trace.WriteLine($"ERROR: waveOutPrepareHeader failed ({res})");
            return;
        }

        res = waveOutWrite(s_waveOut, s_waveHdrAddr, Marshal.SizeOf(typeof(WAVEHDR)));
        if (res != MMSYSERROR.MMSYSERR_NOERROR)
        {
            Trace.WriteLine($"ERROR: waveOutWrite failed ({res})");
            return;
        }

        s_playing = true;
    }
示例#46
0
        public void UnprepareHeader(WAVEHDR pwh)
        {
            EnsureOpen();

            MmException.Try(winmm.waveOutUnprepareHeader(DeviceHandle, pwh, Marshal.SizeOf(pwh)), "waveOutUnprepareHeader");
        }
示例#47
0
            /// <summary>
            /// Default constructor.
            /// </summary>
            /// <param name="wavDevHandle">Wave in device handle.</param>
            /// <param name="dataSize">Data buffer size in bytes.</param>
            public BufferItem(IntPtr wavDevHandle,int dataSize)
            {
                m_WavDevHandle = wavDevHandle;

                m_ThisHandle = GCHandle.Alloc(this);

                m_pBuffer = new byte[dataSize];
                m_DataHandle = GCHandle.Alloc(m_pBuffer,GCHandleType.Pinned);

                m_Header = new WAVEHDR();
                m_Header.lpData          = m_DataHandle.AddrOfPinnedObject();
                m_Header.dwBufferLength  = (uint)dataSize;
                m_Header.dwBytesRecorded = 0;
                m_Header.dwUser          = (IntPtr)m_ThisHandle;
                m_Header.dwFlags         = 0;
                m_Header.dwLoops         = 0;
                m_Header.lpNext          = IntPtr.Zero;
                m_Header.reserved        = 0;

                m_HeaderHandle = GCHandle.Alloc(m_Header,GCHandleType.Pinned);

                m_pEventArgs = new EventArgs<byte[]>(m_pBuffer);
            }
示例#48
0
      ///
      /// Returns the next header we should write to, or blocks until
      /// one is available. The returned header is done and prepared.
      ///
      void _GetFreeHeader( out GCHandle nextIntPtr,
                           out WAVEHDR nextAsHeader )
      {
         while (true)
         {
            // Clear the wave event before checking "done" to 
            // reduce the race condition between checking and 
            // waiting on the event. (it's manual reset...)
            _playEvent.Reset();

            // Note that the header memory fields will be updated
            // by the wave engine at the same time. Oooh, scary!
            // OK, so we're just checking one bit in an int, it's not
            // really dangerous.

            nextFree = _waveHdr[_nextFreeHeader];
            nextAsHeader = (WAVEHDR)nextFree.Target;
            nextIntPtr = nextIntPtr.ToIntPtr();

            if (nextAsHeader.dwFlags & WHDR_DONE)
            {
               if (nextAsHeader.dwFlags & WHDR_PREPARED)
               {
                  int status = waveOutUnprepareHeader
                     ( _waveOutHandle,
                       nextIntPtr,
                       Marshal.sizeof(typeof(WAVEHDR)) );
                  
                  if (status != MMSYSERR_NOERROR)
                  {
                     // Ugh? Still playing? But WHDR_DONE is set!
                     throw new ApplicationException( 
                        String.Format( "Error '{0}' unpreparing wave header",
                                       status ) 
                        );
                  }
               }

               // Switch buffers. Whee.
               _nextFreeHeader = _nextFreeHeader ^ 0x01;
               return;
            }

            // The next buffer is not done. Wait for it to be done.
            // Note there is a race condition here. :(
            _playEvent.WaitOne( 500, false );

            // Could check here to avoid non-buffer-done type events,
            // but really it doesn't matter.
         }
      }
 public static extern int waveOutWrite(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, int uSize);
示例#50
0
 int waveOutUnprepareHeader( IntPtr waveOutHandle,
                             ref WAVEHDR waveHeader,
                             int size );