我正在将一些C#Windows Phone 7应用移植到Windows 8。
手机应用使用XNA SoundEffect播放来自缓冲区的任意声音。在最简单的情况下,我只需要创建所需持续时间和频率的正弦波。持续时间和频率都可能有很大差异,所以我宁愿不依赖MediaElements(除非有一些方法可以改变基本文件的频率,但这只会帮助我生成单一频率)。
WinRT中XNA SoundEffectInstance的等价物是什么?
我认为我需要使用DirectX,但我不确定如何从其他C#/ XAML应用程序中解决这个问题。我看过SharpDX,但它似乎没有我认为我需要使用的DirectSound,SecondaryBuffer,SecondaryBuffer类。
我做了一些上面的假设。可能是我正在寻找错误的类,或者有一种完全独立的方式从Windows 8应用程序生成任意声音。
我找到了an example using XAudio2 from SharpDX to play a wav file via an AudioBuffer。这看起来很有希望,我只需要将生成的音频缓冲区替换为本机文件流。
PM>安装包SharpDX
PM>安装包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();
}
答案 0 :(得分:9)
在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;
}
}
答案 1 :(得分:3)
您还可以使用WASAPI在WinRT中播放动态生成的声音缓冲区。 (xaudio2不是唯一的解决方案)。
我在这里用VB编写了示例代码(C#基本相同): http://www.codeproject.com/Articles/460145/Recording-and-playing-PCM-audio-on-Windows-8-VB
我相信NAudio家伙正计划将我的示例代码翻译成NAudio,以获得Win8支持的版本,以便更容易使用。