Beispiel #1
0
        /// <summary>
        /// Create & initialize the Notifier object and notification positions in the
        /// streaming SecondaryBuffer.  These fill positions persist through multiple
        /// Play/Pause events; however, they are replaced by the single endPosition
        /// at end of data, and are reloaded by Play() if Stopped (position == 0).
        /// </summary>
        /// <param name="numberOfSectors">number of equal-sized sectors in the buffer</param>
        private void SetFillNotifications(int numberOfSectors)
        {
            // Set up the fill-notification positions at last byte of each sector.
            // All use the same event, in contrast to recipe in DX9.0 SDK Aug 2005 titled
            // "DirectSound Buffers | Using Streaming Buffers"
            for (int i = 0; i < numberOfSectors; i++)
            {
                NotificationPositionArray[i].Offset = (i + 1) * SectorSize - 1;
                NotificationPositionArray[i].Event  = NotificationEvent;
            }

            // set the buffer to fire events at the notification positions
            buffer.SetNotificationPositions(NotificationPositionArray);
        }
Beispiel #2
0
        /// <summary>
        /// Initializes a media player with the given file
        /// </summary>
        /// <param name="fileName">the file to play</param>
        /// <returns>true if successful</returns>
        private bool _setupSoundPlayer(string filename)
        {
            bool retval = false;

            soundPlayer = null;

            if ((filename.Length != 0))
            {
                try
                {
                    fileName    = filename;
                    soundPlayer = DirectSoundWrapper.CreateSoundBufferFromWave(fileName);
                    SlimDX.Multimedia.WaveStream waveFile = new SlimDX.Multimedia.WaveStream(fileName);

                    List <NotificationPosition> pos = new List <NotificationPosition>();
                    notificationPosition.Offset = (int)waveFile.Length - 1;
                    notificationPosition.Event  = new AutoResetEvent(false);

                    pos.Add(notificationPosition);
                    soundPlayer.SetNotificationPositions(pos.ToArray());
                }
                catch (Exception ex)
                {
                    logger.Error("[SoundPlayer] Error creating soundplayer: " + ex.Message);
                }

                _updateVolume(volume);

                retval = true;
            }

            return(retval);
        }
Beispiel #3
0
        public DirectSound(
            Form form,
            int sampleRate,
            int bufferCount)
        {
            if ((sampleRate % 50) != 0)
            {
                throw new ArgumentOutOfRangeException("sampleRate", "Sample rate must be a multiple of 50!");
            }
            _sampleRate = sampleRate;
            var bufferSize = sampleRate / 50;

            for (int i = 0; i < bufferCount; i++)
            {
                _fillQueue.Enqueue(new uint[bufferSize]);
            }
            _bufferSize  = bufferSize;
            _bufferCount = bufferCount;
            _zeroValue   = 0;

            var hWnd = form != null ? form.Handle : IntPtr.Zero;

            _device = new DirectSound8();
            _device.SetCooperativeLevel(hWnd, DSSCL.PRIORITY);

            // we always use 16 bit stereo (uint per sample)
            const short channels      = 2;
            const short bitsPerSample = 16;
            const int   sampleSize    = 4; // channels * (bitsPerSample / 8);
            var         wf            = new WaveFormat(_sampleRate, bitsPerSample, channels);

            // Create a buffer
            var bufferDesc = new DSBUFFERDESC();

            bufferDesc.dwBufferBytes = _bufferSize * sampleSize * _bufferCount;
            bufferDesc.dwFlags       =
                DSBCAPS_FLAGS.CTRLVOLUME |
                DSBCAPS_FLAGS.CTRLPOSITIONNOTIFY |
                DSBCAPS_FLAGS.GLOBALFOCUS |
                DSBCAPS_FLAGS.GETCURRENTPOSITION2;
            bufferDesc.Format = wf;
            _soundBuffer      = new SecondarySoundBuffer(_device, bufferDesc);

            var posNotify = new DSBPOSITIONNOTIFY[_bufferCount];

            for (int i = 0; i < posNotify.Length; i++)
            {
                posNotify[i]            = new DSBPOSITIONNOTIFY();
                posNotify[i].dwOffset   = i * _bufferSize * sampleSize;
                posNotify[i].WaitHandle = _fillEvent;
            }
            _soundBuffer.SetNotificationPositions(posNotify);

            _wavePlayThread = new Thread(WavePlayThreadProc);
            _wavePlayThread.IsBackground = true;
            _wavePlayThread.Name         = "WavePlay";
            _wavePlayThread.Priority     = ThreadPriority.Highest;
            _wavePlayThread.Start();
        }
Beispiel #4
0
        public void run()
        {
            directSound = new DirectSound();


            IntPtr hwnd = GetDesktopWindow();

            // Set Cooperative Level to PRIORITY (priority level can call the SetFormat and Compact methods)
            directSound.SetCooperativeLevel(hwnd, CooperativeLevel.Priority);

            // Create PrimarySoundBuffer
            var primaryBufferDesc = new SoundBufferDescription();

            primaryBufferDesc.Flags          = BufferFlags.PrimaryBuffer;
            primaryBufferDesc.AlgorithmFor3D = Guid.Empty;

            primarySoundBuffer = new PrimarySoundBuffer(directSound, primaryBufferDesc);


            // Create SecondarySoundBuffer
            int soundLatencyInMilliseconds = 100;

            var secondaryBufferDesc = new SoundBufferDescription();

            secondaryBufferDesc.BufferBytes = soundStreamer.waveFormat.ConvertLatencyToByteSize(soundLatencyInMilliseconds);
            secondaryBufferDesc.Format      = soundStreamer.waveFormat;
            secondaryBufferDesc.Flags       = BufferFlags.GetCurrentPosition2 | BufferFlags.ControlPositionNotify | BufferFlags.GlobalFocus |
                                              BufferFlags.ControlVolume | BufferFlags.StickyFocus | BufferFlags.Trueplayposition;
            secondaryBufferDesc.AlgorithmFor3D = Guid.Empty;



            secondarySoundBuffer = new SecondarySoundBuffer(directSound, secondaryBufferDesc);



            NotificationPosition n = new NotificationPosition();

            n.Offset     = (secondaryBufferDesc.BufferBytes / 4) * 1;
            n.WaitHandle = soundStreamer.wait;

            NotificationPosition n2 = new NotificationPosition();

            n2.Offset     = (secondaryBufferDesc.BufferBytes / 4) * 3;
            n2.WaitHandle = soundStreamer.wait;

            secondarySoundBuffer.SetNotificationPositions(new NotificationPosition[] { n, n2 });

            soundStreamerThread = new Thread(soundStreamer.loop);
            soundStreamer.secondarySoundBuffer = secondarySoundBuffer;
            soundStreamerThread.Start();


            // play the sound
            secondarySoundBuffer.Play(0, PlayFlags.Looping);
        }
Beispiel #5
0
        public DXWavePlayer(int device, int BufferByteSize, DataRequestDelegate fillProc)
        {
            if (BufferByteSize < 1000)
            {
                throw new ArgumentOutOfRangeException("BufferByteSize", "minimal size of buffer is 1000 bytes");
            }

            _buffersize  = BufferByteSize;
            _requestproc = fillProc;
            var devices = DirectSound.GetDevices();

            if (device <= 0 || device >= devices.Count)
            {
                device = 0;
            }

            _outputDevice = new DirectSound(devices[device].DriverGuid);


            System.Windows.Interop.WindowInteropHelper wh = new System.Windows.Interop.WindowInteropHelper(Application.Current.MainWindow);
            _outputDevice.SetCooperativeLevel(wh.Handle, CooperativeLevel.Priority);

            _buffDescription             = new SoundBufferDescription();
            _buffDescription.Flags       = BufferFlags.ControlPositionNotify | BufferFlags.ControlFrequency | BufferFlags.ControlEffects | BufferFlags.GlobalFocus | BufferFlags.GetCurrentPosition2;
            _buffDescription.BufferBytes = BufferByteSize * InternalBufferSizeMultiplier;

            WaveFormat format = new WaveFormat(16000, 16, 1);

            _buffDescription.Format = format;

            _soundBuffer  = new SecondarySoundBuffer(_outputDevice, _buffDescription);
            _synchronizer = new AutoResetEvent(false);

            NotificationPosition[] nots = new NotificationPosition[InternalBufferSizeMultiplier];

            NotificationPosition not;
            int bytepos = 800;

            for (int i = 0; i < InternalBufferSizeMultiplier; i++)
            {
                not            = new NotificationPosition();
                not.Offset     = bytepos;
                not.WaitHandle = _synchronizer;
                nots[i]        = not;
                bytepos       += BufferByteSize;
            }

            _soundBuffer.SetNotificationPositions(nots);


            _waitThread = new Thread(new ThreadStart(DataRequestThread))
            {
                Name = "MyWavePlayer.DataRequestThread"
            };
            _waitThread.Start();
        }
Beispiel #6
0
        public DxPlaySound(int frequency)
        {
            device = new DirectSound();                                              //音频设备对象

            IntPtr hwnd = new WindowInteropHelper(DisPlayWindow.HMainWindow).Handle; //设置窗口句柄

            device.SetCooperativeLevel(hwnd, CooperativeLevel.Priority);

            //设置Wav音频文件对象属性
            WaveFormat waveformat = SetWaveFormat(frequency);

            //设置通知对象
            mNotifySize = waveformat.AverageBytesPerSecond / 5;        //0.2S数据
            int mainBufferSize = waveformat.AverageBytesPerSecond * 2; //  2s数据长度

            cNotifyNum = mainBufferSize / mNotifySize;                 //通知个数 10 == 2s/0.2s

            //设置主缓存区
            SoundBufferDescription sndBufferDesc = new SoundBufferDescription
            {
                SizeInBytes = mainBufferSize,
                Format      = waveformat,
                Flags       = BufferFlags.ControlPositionNotify | BufferFlags.ControlFrequency | BufferFlags.GlobalFocus | BufferFlags.GetCurrentPosition2
            };

            scdBuffer = new SecondarySoundBuffer(device, sndBufferDesc); //为声音建立二级缓存

            if (scdBuffer != null)
            {
                mNotificationEvent = new AutoResetEvent(false);
                isRunning          = true;
                Task.Factory.StartNew(NotifyThread);
                NotificationPosition[] positionNotify = new NotificationPosition[cNotifyNum]; //通知数组
                for (int i = 0; i < cNotifyNum; i++)
                {
                    positionNotify[i].Offset = mNotifySize * (i + 1) - 1;
                    positionNotify[i].Event  = mNotificationEvent;
                }
                scdBuffer.SetNotificationPositions(positionNotify);
            }
        }
        /// <summary>
        ///   Constructs a new Audio Output Device.
        /// </summary>
        ///
        /// <param name="device">Global identifier of the audio output device.</param>
        /// <param name="owner">The owner window handle.</param>
        /// <param name="samplingRate">The sampling rate of the device.</param>
        /// <param name="channels">The number of channels of the device.</param>
        ///
        public AudioOutputDevice(Guid device, IntPtr owner, int samplingRate, int channels)
        {
            this.owner        = owner;
            this.samplingRate = samplingRate;
            this.channels     = channels;
            this.device       = device;

            DirectSound ds = new DirectSound(device);

            ds.SetCooperativeLevel(owner, CooperativeLevel.Priority);


            // Set the output format
            WaveFormat waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(samplingRate, channels);

            bufferSize = 8 * waveFormat.AverageBytesPerSecond;


            // Setup the secondary buffer
            SoundBufferDescription desc2 = new SoundBufferDescription();

            desc2.Flags =
                BufferFlags.GlobalFocus |
                BufferFlags.ControlPositionNotify |
                BufferFlags.GetCurrentPosition2;
            desc2.BufferBytes = bufferSize;
            desc2.Format      = waveFormat;

            buffer = new SecondarySoundBuffer(ds, desc2);


            var list = new List <NotificationPosition>();
            int numberOfPositions = 32;

            // Set notification for buffer percentiles
            for (int i = 0; i < numberOfPositions; i++)
            {
                list.Add(new NotificationPosition()
                {
                    WaitHandle = new AutoResetEvent(false),
                    Offset     = i * bufferSize / numberOfPositions + 1,
                });
            }

            // Set notification for end of buffer
            list.Add(new NotificationPosition()
            {
                Offset     = bufferSize - 1,
                WaitHandle = new AutoResetEvent(false)
            });

            firstHalfBufferIndex  = numberOfPositions / 2;
            secondHalfBufferIndex = numberOfPositions;

            notifications = list.ToArray();

            Accord.Diagnostics.Debug.Assert(notifications[firstHalfBufferIndex].Offset == bufferSize / 2 + 1);
            Accord.Diagnostics.Debug.Assert(notifications[secondHalfBufferIndex].Offset == bufferSize - 1);

            // Make a copy of the wait handles
            waitHandles = new WaitHandle[notifications.Length];
            for (int i = 0; i < notifications.Length; i++)
            {
                waitHandles[i] = notifications[i].WaitHandle;
            }

            // Store all notification positions
            buffer.SetNotificationPositions(notifications);
        }
Beispiel #8
0
        /// <summary>
        ///   Constructs a new Audio Output Device.
        /// </summary>
        /// 
        /// <param name="device">Global identifier of the audio output device.</param>
        /// <param name="owner">The owner window handle.</param>
        /// <param name="samplingRate">The sampling rate of the device.</param>
        /// <param name="channels">The number of channels of the device.</param>
        /// 
        public AudioOutputDevice(Guid device, IntPtr owner, int samplingRate, int channels)
        {
            this.owner = owner;
            this.samplingRate = samplingRate;
            this.channels = channels;
            this.device = device;

            DirectSound ds = new DirectSound(device);
            ds.SetCooperativeLevel(owner, CooperativeLevel.Priority);


            // Set the output format
            WaveFormat waveFormat = new WaveFormat();
            waveFormat.FormatTag = WaveFormatTag.IeeeFloat;
            waveFormat.BitsPerSample = 32;
            waveFormat.BlockAlignment = (short)(waveFormat.BitsPerSample * channels / 8);
            waveFormat.Channels = (short)channels;
            waveFormat.SamplesPerSecond = samplingRate;
            waveFormat.AverageBytesPerSecond = waveFormat.SamplesPerSecond * waveFormat.BlockAlignment;

            bufferSize = 8 * waveFormat.AverageBytesPerSecond;


            // Setup the secondary buffer
            SoundBufferDescription desc2 = new SoundBufferDescription();
            desc2.Flags =
                BufferFlags.GlobalFocus |
                BufferFlags.ControlPositionNotify |
                BufferFlags.GetCurrentPosition2;
            desc2.SizeInBytes = bufferSize;
            desc2.Format = waveFormat;

            buffer = new SecondarySoundBuffer(ds, desc2);


            var list = new List<NotificationPosition>();
            int numberOfPositions = 32;

            // Set notification for buffer percentiles
            for (int i = 0; i < numberOfPositions; i++)
            {
                list.Add(new NotificationPosition()
                {
                    Event = new AutoResetEvent(false),
                    Offset = i * bufferSize / numberOfPositions + 1,
                });
            }

            // Set notification for end of buffer
            list.Add(new NotificationPosition()
            {
                Offset = bufferSize - 1,
                Event = new AutoResetEvent(false)
            });

            firstHalfBufferIndex = numberOfPositions / 2;
            secondHalfBufferIndex = numberOfPositions;

            notifications = list.ToArray();

            System.Diagnostics.Debug.Assert(notifications[firstHalfBufferIndex].Offset == bufferSize / 2 + 1);
            System.Diagnostics.Debug.Assert(notifications[secondHalfBufferIndex].Offset == bufferSize - 1);

            // Make a copy of the wait handles
            waitHandles = new WaitHandle[notifications.Length];
            for (int i = 0; i < notifications.Length; i++)
                waitHandles[i] = notifications[i].Event;

            // Store all notification positions
            buffer.SetNotificationPositions(notifications);
        }
        private void process(bool initializeNextTrack)
        {
            preparing = true;
            SecondarySoundBuffer sBuff = null;
            int p = playPointer;

            if (initializeNextTrack)
            {
                p++;                 // Point to the next track which we will initialize.
            }
            MemoryStream PcmStream = null;
            PlayFlags    f         = PlayFlags.None;

            if (p > soundBuffers.Count - 1)
            {
                SoundBufferDescription desc = new SoundBufferDescription();
                desc.Flags = BufferFlags.ControlPositionNotify | BufferFlags.ControlVolume | BufferFlags.GetCurrentPosition2 | BufferFlags.GlobalFocus;
                byte[] outBuffer = new Byte[4096];
                oggFile   = new OggVorbisFileStream(fileNames[p]);
                PcmStream = new MemoryStream();
                int        PcmBytes   = -1;
                WaveFormat waveFormat = new WaveFormat();
                // Decode the Ogg Vorbis data into its PCM data
                while (PcmBytes != 0)
                {
                    PcmBytes = oggFile.Read(outBuffer, 0, outBuffer.Length);
                    PcmStream.Write(outBuffer, 0, PcmBytes);
                }
                VorbisInfo info = oggFile.Info;
                waveFormat       = new WaveFormat(info.Rate, bitsPerSample, info.Channels);
                desc.Format      = waveFormat;
                desc.BufferBytes = (int)PcmStream.Length;
                lock (lockObject)                 // So we don't lose a simultaneous volume change.
                    soundBuffers.Add(sBuff = new SecondarySoundBuffer(device, desc));
                sBuff.Write(PcmStream.ToArray(), 0, LockFlags.EntireBuffer);
                // In a multi-wave playback, only loop the last track. The preceeding tracks are intros.
                // Next, if we have a multi-file situation, we need to wait for the current file to stop playing before starting the next one.
                // This handler will also fire when a sound is done playing by default so we can explicitly dispose of the soundBuffer.
                stoppedSignal = new AutoResetEvent(false);
                NotificationPosition[] n = { new NotificationPosition()
                                             {
                                                 Offset = (int)PcmStream.Length - 1, WaitHandle = new AutoResetEvent(false)
                                             } };
                stoppedSignal = (AutoResetEvent)(n[0].WaitHandle);
                sBuff.SetNotificationPositions(n);
            }
            else                  // If this buffer has already been initialized ahead of time
            {
                sBuff = soundBuffers[p];
            }
            if (!initializeNextTrack)
            {
                Thread t = new Thread(stopEventHandler);
                t.Start();
                sBuff.Volume = m_volume;
                f            = (loop && p == fileNames.Length - 1) ? PlayFlags.Looping : PlayFlags.None;
                sBuff.Play(0, f);
            }
            if (PcmStream != null)
            {
                oggFile.Close();
                oggFile.Dispose();
                PcmStream.Close();
                PcmStream.Dispose();
            }
            if (!initializeNextTrack && playPointer < fileNames.Length - 1)             // Prepare the next track.
            {
                process(true);
            }
            preparing = false;
        }