Example #1
0
        internal static AcmFormatInfo FromFormatTagDetails(ACMFORMATTAGDETAILS details, IntPtr hDriver, int driverId)
        {
            if (driverId == 0)
            {
                AcmNativeMethods.acmDriverID(hDriver, out driverId, 0);
            }
            AcmFormatInfo info = new AcmFormatInfo();

            info.DriverId = driverId;
            //info.Format = new WaveFormat2(
            info.FormatName = details.szFormatTag;
            info.FormatTag  = (FormatTag)details.dwFormatTag;

            for (int i = 0; i < details.cStandardFormats; i++)
            {
                ACMFORMATDETAILS fd = new ACMFORMATDETAILS();
                fd.cbStruct = Marshal.SizeOf(fd);
                fd.cbwfx    = details.cbFormatSize;
                WaveFormat2 fmt = new WaveFormat2(new byte[fd.cbwfx]);
                fmt.FormatTag = (FormatTag)details.dwFormatTag;
                fmt.Size      = (short)(fd.cbwfx == 16 ? 0 : fd.cbwfx - 18);
                fmt.Extra     = new byte[fmt.Size];
                fd.pwfx       = Marshal.AllocHGlobal(fd.cbwfx);
                Marshal.Copy(fmt.GetBytes(), 0, fd.pwfx, fd.cbwfx);
                fd.dwFormatIndex = i;
                fd.dwFormatTag   = (int)info.FormatTag;
                /*MMResult mmr = */
                int    mmr     = AcmNativeMethods.acmFormatDetails(hDriver, ref fd, AcmFormatDetailsFlags.INDEX);
                byte[] fmtData = new byte[fd.cbwfx];
                Marshal.Copy(fd.pwfx, fmtData, 0, fd.cbwfx);
                info.Format = new WaveFormat2(fmtData);
                Marshal.FreeHGlobal(fd.pwfx);
            }
            return(info);
        }
Example #2
0
        /// <summary>
        /// Set the volume for the default waveOut device (device ID = 0)
        /// </summary>
        /// <param name="Volume"></param>
        public void SetVolume(int Volume)
        {
            WaveFormat2 format   = new WaveFormat2();
            IntPtr      hWaveOut = IntPtr.Zero;

            NativeMethods.waveOutOpen(out hWaveOut, 0, format.GetBytes(), IntPtr.Zero, 0, 0);
            NativeMethods.waveOutSetVolume(hWaveOut, Volume);
            NativeMethods.waveOutClose(hWaveOut);
        }
Example #3
0
        /// <summary>
        /// Get the current volume setting for the default waveOut device (device ID = 0)
        /// </summary>
        /// <returns></returns>
        public int GetVolume()
        {
            WaveFormat2 format   = new WaveFormat2();
            IntPtr      hWaveOut = IntPtr.Zero;
            int         volume   = 0;

            NativeMethods.waveOutOpen(out hWaveOut, 0, format.GetBytes(), IntPtr.Zero, 0, 0);
            NativeMethods.waveOutGetVolume(hWaveOut, ref volume);
            NativeMethods.waveOutClose(hWaveOut);

            return(volume);
        }
Example #4
0
        protected override void LoadHeader()
        {
            base.LoadHeader();

            byte[] fmtIn = _fmt.GetBytes();
            if (_fmt2 == null)
            {
                _fmt2 = WaveFormat2.GetPCMWaveFormat(_fmt.SamplesPerSec, _fmt.Channels, _fmt.BitsPerSample != 0 ? _fmt.BitsPerSample : (short)16);
            }
            byte[]   fmtOut = _fmt2.GetBytes();
            MMResult mmr;

            _fmt2         = new WaveFormat2(fmtOut);
            mmr           = AcmNativeMethods.acmStreamOpen(out hStreamComp, IntPtr.Zero, fmtIn, fmtOut, IntPtr.Zero, 0, 0, AcmStreamOpenFlags.CALLBACK_NULL);
            hdr1          = new ACMSTREAMHEADER();
            hdr1.cbStruct = Marshal.SizeOf(hdr1);
            hdr2          = new ACMSTREAMHEADER();
            hdr2.cbStruct = Marshal.SizeOf(hdr2);

            int cbIn = (_fmt.AvgBytesPerSec * DefaultBufferSizeInSeconds / _fmt.BlockAlign + 1) * _fmt.BlockAlign;

            inBuffer1 = new byte[cbIn];
            inBuffer2 = new byte[cbIn];
            int cbOut = _fmt2.BlockAlign * _fmt2.AvgBytesPerSec * DefaultBufferSizeInSeconds;

            mmr         = AcmNativeMethods.acmStreamSize(hStreamComp, cbIn, out cbOut, AcmStreamSizeFlags.SOURCE);
            outBuffer1  = new byte[cbOut];
            outBuffer2  = new byte[cbOut];
            hinBuffer1  = GCHandle.Alloc(inBuffer1, GCHandleType.Pinned);
            houtBuffer1 = GCHandle.Alloc(outBuffer1, GCHandleType.Pinned);
            hinBuffer2  = GCHandle.Alloc(inBuffer2, GCHandleType.Pinned);
            houtBuffer2 = GCHandle.Alloc(outBuffer2, GCHandleType.Pinned);

            hdr1.pbSrc       = hinBuffer1.AddrOfPinnedObject();
            hdr1.pbDst       = houtBuffer1.AddrOfPinnedObject();
            hdr1.cbSrcLength = cbIn;
            hdr1.cbDstLength = cbOut;

            hdr2.pbSrc       = hinBuffer2.AddrOfPinnedObject();
            hdr2.pbDst       = houtBuffer2.AddrOfPinnedObject();
            hdr2.cbSrcLength = cbIn;
            hdr2.cbDstLength = cbOut;

            ptrBuffer1 = ptrBuffer1 = 0;

            bufferRead = new SlidingBuffer(cbOut);
            firstBlock = true;

            bufferRead.BufferStarving = (BufferStarvingHandler) delegate(SlidingBuffer obj, int spaceAvailable)
            {
                if (hdr1.cbDstLengthUsed == ptrBuffer1)
                {
                    int cb = ReadInternal(inBuffer1, 0, inBuffer1.Length);
                    if (cb == 0)
                    {
                        return(0);
                    }
                    ptrBuffer1 = 0;
                    AcmStreamConvertFlags flags;
                    if (firstBlock)
                    {
                        flags      = AcmStreamConvertFlags.START;
                        firstBlock = false;
                    }
                    else if (cb == inBuffer1.Length)
                    {
                        flags = AcmStreamConvertFlags.BLOCKALIGN;
                    }
                    else
                    {
                        flags = AcmStreamConvertFlags.END;
                    }

                    hdr1.cbSrcLength = cb;
                    MMResult res = AcmNativeMethods.acmStreamConvert(hStreamComp, ref hdr1, flags);
                    return(cb);
                }

                int written = obj.Append(outBuffer1, ptrBuffer1, hdr1.cbDstLengthUsed - ptrBuffer1);
                ptrBuffer1 += written;
                return(written);
            };

            mmr = AcmNativeMethods.acmStreamPrepareHeader(hStreamComp, ref hdr1, 0);
            mmr = AcmNativeMethods.acmStreamPrepareHeader(hStreamComp, ref hdr2, 0);
        }
Example #5
0
        protected override bool InitializeForWriting(Stream underlyingStream, WaveFormat2 wfIn, WaveFormat2 wfOut, bool fAppend)
        {
            base.InitializeForWriting(underlyingStream, wfIn, wfOut, fAppend);
            MMResult mmr;

            int driverId = 0;

            foreach (AcmDriverInfo drvInfo in ACMSupport.SupportedDrivers)
            {
                foreach (AcmFormatInfo fmtInfo in drvInfo.Formats)
                {
                    if (fmtInfo.Format == wfOut)
                    {
                        driverId = fmtInfo.DriverId;
                        break;
                    }
                }
            }

            foreach (AcmDriverInfo drvInfo in ACMSupport.SupportedDrivers)
            {
                foreach (AcmFormatInfo fmtInfo in drvInfo.Formats)
                {
                    if (fmtInfo.DriverId == driverId && fmtInfo.Format.FormatTag == wfIn.FormatTag)
                    {
                        wfIn.CopyFrom(fmtInfo.Format);
                        break;
                    }
                }
            }

            byte[] fmtIn  = wfIn.GetBytes();
            byte[] fmtOut = wfOut.GetBytes();

            IntPtr hDrv = IntPtr.Zero;

            if (driverId != 0)
            {
                AcmNativeMethods.acmDriverOpen(out hDrv, driverId, 0);
            }
            mmr           = AcmNativeMethods.acmStreamOpen(out hStreamComp, hDrv, fmtIn, fmtOut, IntPtr.Zero, 0, 0, AcmStreamOpenFlags.CALLBACK_NULL | AcmStreamOpenFlags.NONREALTIME);
            hdr1          = new ACMSTREAMHEADER();
            hdr1.cbStruct = Marshal.SizeOf(hdr1);
            hdr2          = new ACMSTREAMHEADER();
            hdr2.cbStruct = Marshal.SizeOf(hdr2);

            int cbIn = (wfIn.AvgBytesPerSec * DefaultBufferSizeInSeconds / wfIn.BlockAlign + 1) * wfIn.BlockAlign;

            inBuffer1 = new byte[cbIn];
            inBuffer2 = new byte[cbIn];
            int cbOut = wfOut.BlockAlign * wfOut.AvgBytesPerSec * DefaultBufferSizeInSeconds;

            mmr         = AcmNativeMethods.acmStreamSize(hStreamComp, cbIn, out cbOut, AcmStreamSizeFlags.DESTINATION);
            outBuffer1  = new byte[cbOut];
            outBuffer2  = new byte[cbOut];
            hinBuffer1  = GCHandle.Alloc(inBuffer1, GCHandleType.Pinned);
            houtBuffer1 = GCHandle.Alloc(outBuffer1, GCHandleType.Pinned);
            hinBuffer2  = GCHandle.Alloc(inBuffer2, GCHandleType.Pinned);
            houtBuffer2 = GCHandle.Alloc(outBuffer2, GCHandleType.Pinned);

            hdr1.pbSrc       = hinBuffer1.AddrOfPinnedObject();
            hdr1.pbDst       = houtBuffer1.AddrOfPinnedObject();
            hdr1.cbSrcLength = cbIn;
            hdr1.cbDstLength = cbOut;

            hdr2.pbSrc       = hinBuffer2.AddrOfPinnedObject();
            hdr2.pbDst       = houtBuffer2.AddrOfPinnedObject();
            hdr2.cbSrcLength = cbIn;
            hdr2.cbDstLength = cbOut;

            ptrBuffer1 = ptrBuffer1 = 0;

            firstBlock = true;

            mmr = AcmNativeMethods.acmStreamPrepareHeader(hStreamComp, ref hdr1, 0);
            mmr = AcmNativeMethods.acmStreamPrepareHeader(hStreamComp, ref hdr2, 0);

            return(true);
        }
Example #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);
        }
Example #7
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);
            }
        }