从Windows 8应用程序中生成的缓冲区播放声音

我正在将一些C#Windows Phone 7应用移植到Windows 8。

手机应用程序使用XNA SoundEffect从缓冲区播放任意声音。 在最简单的情况下,我只需创建所需持续时间和频率的正弦波。 持续时间和频率都可能有很大差异,所以我宁愿不依赖MediaElements(除非有一些方法可以改变基本文件的频率,但这只会帮助我生成单一频率)。

WinRT中的XNA SoundEffectInstance相当于什么?

我假设我需要使用DirectX,但我不确定如何从其他C#/ XAML应用程序中进行此操作。 我已经看过SharpDX ,但它似乎没有我认为我需要使用的DirectSound,SecondaryBuffer,SecondaryBuffer类。

我上面做了一些假设。 可能是我正在寻找错误的类,或者有一种完全独立的方式从Windows 8应用程序生成任意声音。


我找到了一个使用SharpDX的XAudio2通过AudioBuffer播放wav文件的例子 。 这看起来很有希望,我只需要将生成的音频缓冲区替换为本机文件流。

PM>安装包装SharpDX

PM> Install-Package SharpDX.XAudio2

public void PlaySound() { XAudio2 xaudio; MasteringVoice masteringVoice; xaudio = new XAudio2(); masteringVoice = new MasteringVoice(xaudio); var nativefilestream = new NativeFileStream( @"Assets\SpeechOn.wav", NativeFileMode.Open, NativeFileAccess.Read, NativeFileShare.Read); var soundstream = new SoundStream(nativefilestream); var waveFormat = soundstream.Format; var buffer = new AudioBuffer { Stream = soundstream.ToDataStream(), AudioBytes = (int)soundstream.Length, Flags = BufferFlags.EndOfStream }; var sourceVoice = new SourceVoice(xaudio, waveFormat, true); // There is also support for shifting the frequency. sourceVoice.SetFrequencyRatio(0.5f); sourceVoice.SubmitSourceBuffer(buffer, soundstream.DecodedPacketsInfo); sourceVoice.Start(); } 

在Win8RT中生成动态声音的唯一方法是使用XAudio2,因此您应该能够使用SharpDX.XAudio2执行此操作。

而不是使用NativeFileStream,只需实例化一个直接给出托管缓冲区的DataStream(或者您可以使用非托管缓冲区或让DataStream为您实例化一个)。 代码如下:

 // Initialization phase, keep this buffer during the life of your application // Allocate 10s at 44.1Khz of stereo 16bit signals var myBufferOfSamples = new short[44100 * 10 * 2]; // Create a DataStream with pinned managed buffer var dataStream = DataStream.Create(myBufferOfSamples, true, true); var buffer = new AudioBuffer { Stream = dataStream, AudioBytes = (int)dataStream.Length, Flags = BufferFlags.EndOfStream }; //... // Fill myBufferOfSamples //... // PCM 44.1Khz stereo 16 bit format var waveFormat = new WaveFormat(); XAudio2 xaudio = new XAudio2(); MasteringVoice masteringVoice = new MasteringVoice(xaudio); var sourceVoice = new SourceVoice(xaudio, waveFormat, true); // Submit the buffer sourceVoice.SubmitSourceBuffer(buffer, null); // Start playing sourceVoice.Start(); 

使用正弦波填充缓冲区的示例方法:

  private void FillBuffer(short[] buffer, int sampleRate, double frequency) { double totalTime = 0; for (int i = 0; i < buffer.Length - 1; i += 2) { double time = (double)totalTime / (double)sampleRate; short currentSample = (short)(Math.Sin(2 * Math.PI * frequency * time) * (double)short.MaxValue); buffer[i] = currentSample; //(short)(currentSample & 0xFF); buffer[i + 1] = currentSample; //(short)(currentSample >> 8); totalTime += 2; } } 

您还可以使用WASAPI在WinRT中播放动态生成的声音缓冲区。 (xaudio2不是唯一的解决方案)。

我在这里用VB编写了示例代码(C#基本相同): http : //www.codeproject.com/Articles/460145/Recording-and-playing-PCM-audio-on-Windows-8-VB

我相信NAudio家伙正计划将我的示例代码翻译成NAudio,以获得Win8支持的版本,这样就更容易使用了。