打从生成缓冲区声音Windows 8应用 [英] Playing a sound from a generated buffer in a Windows 8 app

查看:200
本文介绍了打从生成缓冲区声音Windows 8应用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我移植一些C#的Windows Phone 7应用到Windows 8中。



的手机应用程序使用的XNA的 SoundEffect中从缓冲区玩任意声音。在最简单的情况下,我只希望创建所需的持续时间和频率的正弦波。无论是持续时间和频率可以相差很大,所以我宁愿不依赖于MediaElements(除非有好歹基本文件的频率漂移,但是这只会帮助我的单频代)。



什么是XNA SoundEffectInstance在WinRT中的相同呢?



我想我需要要使用DirectX这一点,但我不知道如何去了解这个从否则C#/ XAML应用程序。我有一个看看 SharpDX ,但它似乎并不具备的DirectSound,SecondaryBuffer,SecondaryBuffer类,我假设我需要使用。



我做了上述的一些假设。这可能是我找错了班或有从Windows 8应用产生任意的声音一个完全独立的方式。






我发现的使用XAudio2从SharpDX通过AudioBuffer 播放WAV文件的例子。这似乎是有前途的,我只需要替换本地文件流我生成的音频缓冲。




PM>安装封装SharpDX



PM>安装封装SharpDX.XAudio2




 公共无效PlaySound()
{
XAudio2 xaudio;
MasteringVoice masteringVoice;

xaudio =新XAudio2();
masteringVoice =新MasteringVoice(xaudio);

变种nativefilestream =新NativeFileStream(
@Assets\SpeechOn.wav,
NativeFileMode.Open,
NativeFileAccess.Read,
NativeFileShare。读);

变种SOUNDSTREAM =新SOUNDSTREAM(nativefilestream);


VAR WAVEFORMAT = soundstream.Format;
变种缓冲=新AudioBuffer
{
=流soundstream.ToDataStream(),
AudioBytes =(INT)soundstream.Length,
标志= BufferFlags.EndOfStream
};

变种sourceVoice =新SourceVoice(xaudio,WAVEFORMAT,真正的);

//还为转移的频率支持。
sourceVoice.SetFrequencyRatio(0.5F);

sourceVoice.SubmitSourceBuffer(缓冲液,soundstream.DecodedPacketsInfo);

sourceVoice.Start();
}


解决方案

只有这样,才能生成动态在声音是Win8RT使用XAudio2,所以你应该能够SharpDX.XAudio2做到这一点。



而不是使用NativeFileStream的,只是实例化数据流直接给你管理的缓冲区(或者你可以使用一个非托管的缓冲区,或者让的数据流中实例化一个给你)。该代码将是这样的:

  //初始化阶段,保持这个缓冲你的应用程序
的生命周期内/在16位立体声信号
变种myBufferOfSamples的44.1 / 10秒分配=新的短[44100 * 10 * 2];

//创建固定管理缓冲
VAR数据流= DataStream.Create(myBufferOfSamples,真实,真实的)数据流;

变种缓冲=新AudioBuffer
{
=流数据流,
AudioBytes =(INT)dataStream.Length,
标志= BufferFlags.EndOfStream
};

// ...
//填写myBufferOfSamples
// ...

// PCM立体声44.1kHz的16位格式
VAR WAVEFORMAT =新WAVEFORMAT();

XAudio2 xaudio =新XAudio2();
MasteringVoice masteringVoice =新MasteringVoice(xaudio);
变种sourceVoice =新SourceVoice(xaudio,WAVEFORMAT,真正的);

//提交缓冲
sourceVoice.SubmitSourceBuffer(缓冲液,空);



采样方法来填充正弦波缓冲区:

 私人无效FillBuffer(短[]缓冲区,诠释采样率,双频率)
{
双TOTALTIME = 0;

的for(int i = 0; I< buffer.Length - 1; I + = 2)
{
双倍时间=(双)TOTALTIME /(双)采样率;
短currentSample =(短)(Math.Sin(2 * Math.PI *频率*时间)*(双)short.MaxValue);

缓冲区[i] = currentSample; //(短)(currentSample&安培; 0xFF的);
缓冲液第[i + 1] = currentSample; //(短)(currentSample>→8);

TOTALTIME + = 2;
}

}


I'm porting some C# Windows Phone 7 apps over to Windows 8.

The phone apps used an XNA SoundEffect to play arbitrary sounds from a buffer. In the simplest cases I'd just create a sine wave of the required duration and frequency. Both the duration and frequency can vary greatly, so I'd prefer not to rely on MediaElements (unless there is someway to shift the frequency of a base file, but that will only help me with the single frequency generation).

What is the equivalent of an XNA SoundEffectInstance in WinRT?

I assume I'll need to use DirectX for this, but I'm not sure how to go about this from an otherwise C#/XAML app. I've had a look at SharpDX, but it didn't seem to have the DirectSound, SecondaryBuffer, SecondaryBuffer classes that I assume I'd need to use.

I've made a number of assumptions above. It may be I'm looking for the wrong classes or there is an entirely separate way to generate arbitrary sound from a Windows 8 app.


I found an example using XAudio2 from SharpDX to play a wav file via an AudioBuffer. This seems promising, I'd just need to substitute my generated audio buffer for the native file stream.

PM> Install-Package 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();
    }

解决方案

The only way to generate dynamic sound in Win8RT is to use XAudio2, so you should be able to do this with SharpDX.XAudio2.

Instead of using NativeFileStream, just instantiate a DataStream directly giving your managed buffer (or you can use an unmanaged buffer or let DataStream instantiate one for you). The code would be like this:

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

Sample method to fill the buffer with a Sine wave:

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

    }

这篇关于打从生成缓冲区声音Windows 8应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆