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

C# 在Windows 8应用程序中从生成的缓冲区播放声音,c#,directx,windows-runtime,winrt-xaml,sharpdx,C#,Directx,Windows Runtime,Winrt Xaml,Sharpdx,我正在将一些C#Windows Phone 7应用程序移植到Windows 8 手机应用程序使用XNA从缓冲区播放任意声音。在最简单的情况下,我只需要创建一个所需持续时间和频率的正弦波。持续时间和频率可能会有很大的不同,因此我不希望依赖MediaElements(除非有某种方法可以改变基本文件的频率,但这只能帮助我生成单个频率) WinRT中XNA SoundEffectInstance的等价物是什么? 我想我需要使用DirectX来实现这一点,但我不确定如何从其他C#/XAML应用程序中实现这

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

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

WinRT中XNA SoundEffectInstance的等价物是什么?

我想我需要使用DirectX来实现这一点,但我不确定如何从其他C#/XAML应用程序中实现这一点。我已经看过了,但它似乎没有我认为需要使用的DirectSound、SecondaryBuffer和SecondaryBuffer类

我在上面做了一些假设。这可能是我在寻找错误的类,或者有一种完全不同的方法从Windows8应用程序生成任意声音


我找到了。这似乎很有希望,我只需要将生成的音频缓冲区替换为本机文件流

PM>安装软件包SharpDX

PM>安装软件包SharpDX.XAudio2


在Win8RT中生成动态声音的唯一方法是使用XAudio2,因此您应该能够使用SharpDX.XAudio2实现这一点

不使用NativeFileStream,只需直接实例化一个数据流,并提供托管缓冲区(或者您可以使用非托管缓冲区,或者让数据流为您实例化一个)。代码如下所示:

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

    }
private void FillBuffer(短[]buffer,int sampleRate,双频)
{
双倍总时间=0;
对于(int i=0;i>8);
总时间+=2;
}
}

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

我在这里用VB为其编写了示例代码(C#基本相同):


我相信NAudio的家伙正计划将我的示例代码翻译并合并到NAudio中,以获得支持Win8的版本,这样会更易于使用。

太好了,谢谢。我通过创建XAudio2实例扩展了您的示例。我现在从缓冲器中发出声音。目前看来有点扭曲。我需要再次检查我的FillBuffer方法,我也将其添加到了您的答案中,供其他人使用。我在XNA中工作时,FillBuffer方法用于填充字节[]。删除按位&和向右移位>>运算符修复了此问题。我现在得到了一个清晰的音调。这有一个错误:
totalTime+=2
意味着它产生的频率是原来的两倍。它应该是
totalTime++
。(我自己测试过!)@DanielBallinger,如果可以,你能分享你的例子吗?我一直想学习如何做你在这里做的事情。我是WinRT和声音生成的新手。我想尝试编写一个简单的钢琴应用程序,让我的孩子们玩。@Jim,答案涵盖了生成基本正弦波所需的大部分内容。您还想介绍什么?我正在寻找一种解决方案,可以直接从windows phone 8中的缓冲音频包播放音频?你能重定向到一个工作示例吗。
    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;
        }

    }