コード例 #1
0
        /// <summary>
        /// Gets the current position in bytes from the wave output device.
        /// (n.b. this is not the same thing as the position within your reader
        /// stream - it calls directly into waveOutGetPosition)
        /// </summary>
        /// <returns>Position in bytes</returns>
        public long GetPosition()
        {
            lock (WaveOutLock)
            {
                var time = new MmTime()
                {
                    Type = MmTime.TIME_BYTES
                };

                MmException.Try(WaveInterop.NativeMethods.waveOutGetPosition(DeviceHandle, out time, Marshal.SizeOf(time)), nameof(WaveInterop.NativeMethods.waveOutGetPosition));

                if (time.Type != MmTime.TIME_BYTES)
                {
                    throw new Exception(string.Format($"{nameof(WaveInterop.NativeMethods.waveOutGetPosition)}: wType -> Expected {0}, Received {1}", MmTime.TIME_BYTES, time.Type));
                }

                return(time.CB);
            }
        }
コード例 #2
0
        /// <summary>
        /// Initializes the specified wave provider.
        /// </summary>
        /// <param name="waveProvider">The wave provider.</param>
        /// <exception cref="System.InvalidOperationException">Can't re-initialize during playback</exception>
        public void Init(IWaveProvider waveProvider)
        {
            if (m_PlaybackState != PlaybackState.Stopped)
            {
                throw new InvalidOperationException("Can't re-initialize during playback");
            }

            if (DeviceHandle != IntPtr.Zero)
            {
                // normally we don't allow calling Init twice, but as experiment, see if we can clean up and go again
                // try to allow reuse of this waveOut device
                // n.b. risky if Playback thread has not exited
                DisposeBuffers();
                CloseWaveOut();
            }

            CallbackEvent = new AutoResetEvent(false);

            WaveStream = waveProvider;
            var bufferSize = waveProvider.WaveFormat.ConvertLatencyToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers);

            MmResult result;

            lock (WaveOutLock)
            {
                result = WaveInterop.NativeMethods.waveOutOpenWindow(
                    out DeviceHandle,
                    DeviceNumber,
                    WaveStream.WaveFormat,
                    CallbackEvent.SafeWaitHandle.DangerousGetHandle(),
                    IntPtr.Zero,
                    WaveInterop.WaveInOutOpenFlags.CallbackEvent);
            }

            MmException.Try(result, nameof(WaveInterop.NativeMethods.waveOutOpen));

            Buffers         = new WaveOutBuffer[NumberOfBuffers];
            m_PlaybackState = PlaybackState.Stopped;
            for (var n = 0; n < NumberOfBuffers; n++)
            {
                Buffers[n] = new WaveOutBuffer(DeviceHandle, bufferSize, WaveStream, WaveOutLock);
            }
        }
コード例 #3
0
        private GCHandle callbackHandle; // for the user callback

        /// <summary>
        /// Initializes a new instance of the <see cref="WaveOutBuffer"/> class.
        /// </summary>
        /// <param name="hWaveOut">WaveOut device to write to</param>
        /// <param name="bufferSize">Buffer size in bytes</param>
        /// <param name="bufferFillStream">Stream to provide more data</param>
        /// <param name="waveOutLock">Lock to protect WaveOut API's from being called on &gt;1 thread</param>
        public WaveOutBuffer(IntPtr hWaveOut, Int32 bufferSize, IWaveProvider bufferFillStream, object waveOutLock)
        {
            this.bufferSize  = bufferSize;
            buffer           = new byte[bufferSize];
            bufferHandle     = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            this.waveOutPtr  = hWaveOut;
            waveStream       = bufferFillStream;
            this.waveOutLock = waveOutLock;

            header              = new WaveHeader();
            headerHandle        = GCHandle.Alloc(header, GCHandleType.Pinned);
            header.DataBuffer   = bufferHandle.AddrOfPinnedObject();
            header.BufferLength = bufferSize;
            header.Loops        = 1;
            callbackHandle      = GCHandle.Alloc(this);
            header.UserData     = (IntPtr)callbackHandle;
            lock (waveOutLock)
            {
                MmException.Try(WaveInterop.NativeMethods.waveOutPrepareHeader(hWaveOut, header, Marshal.SizeOf(header)), "waveOutPrepareHeader");
            }
        }