/// <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); }
/// <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); }
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(); }
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); }
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(); }
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); }
/// <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; }