我已经使用SharpDX.XAudio2了几天,虽然事情在很大程度上是积极的(到处都是奇怪的软件怪癖),但以下问题却使我完全陷入困境:
我正在使用VS2015在C#.NET中工作。
我正在尝试同时播放多种声音。
为此,我做了:
-Test.cs:包含主要方法
-cSoundEngine.cs:包含XAudio2,MasteringVoice和声音管理方法。
-VoiceChannel.cs:保存SourceVoice,以及将来的所有sfx /相关数据。
cSoundEngine:
List<VoiceChannel> sourceVoices;
XAudio2 engine;
MasteringVoice master;
public cSoundEngine()
{
engine = new XAudio2();
master = new MasteringVoice(engine);
sourceVoices = new List<VoiceChannel>();
}
public VoiceChannel AddAndPlaySFX(string filepath, double vol, float pan)
{
/**
* Set up and start SourceVoice
*/
NativeFileStream fileStream = new NativeFileStream(filepath, NativeFileMode.Open, NativeFileAccess.Read);
SoundStream soundStream = new SoundStream(fileStream);
SourceVoice source = new SourceVoice(engine, soundStream.Format);
AudioBuffer audioBuffer = new AudioBuffer()
{
Stream = soundStream.ToDataStream(),
AudioBytes = (int)soundStream.Length,
Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
};
//Make voice wrapper
VoiceChannel voice = new VoiceChannel(source);
sourceVoices.Add(voice);
//Volume
source.SetVolume((float)vol);
//Play sound
source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
source.Start();
return voice;
}
Test.cs:
cSoundEngine engine = new cSoundEngine();
total = 6;
for (int i = 0; i < total; i++)
{
string filepath = System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.FullName + @"\Assets\Planet.wav";
VoiceChannel sfx = engine.AddAndPlaySFX(filepath, 0.1, 0);
}
Console.Read(); //Input anything to end play.
目前在VoiceChannel.cs中没有值得显示的内容-它包含“SourceVoice源”,这是在构造函数中发送的一个参数!
一切都很好,并且运行良好,最多有5种声音(总计= 5)。您所听到的只是Planet.wav的幸福无人机。高于5的值将导致控制台冻结约5秒钟,然后关闭(可能是调试器无法处理的C++错误)。遗憾的是,没有错误消息供我们查看或其他内容。
从测试:
-只要您运行的音源不超过5个,就不会崩溃。
-更改采样率似乎无济于事。
-将主对象的inputChannels设置为其他数字没有区别。
-MasteringVoice似乎说最大输入语音数是64。
-使每个sfx从不同的wav文件播放都没有区别。
-设置原始声音和/或主声音的音量没有区别。
在XAudio2 API Documentation中,我找到了这句话:'XAudio2取消了多声道声音的6声道限制,并在任何具有多声道功能的声卡上支持多声道音频。该卡不需要硬件加速。 。这是我最近发现有关此问题的内容。
我对sfx编程经验不足,其中的很多对我来说都是很新的,因此请在适当的时候随意称呼我为白痴,但请尝试以外行的方式进行解释。
请,如果您有任何想法或答案,将不胜感激!
-乔什
最佳答案
正如Chuck所建议的那样,我创建了一个数据库来保存.wav数据,并且我只引用了每个缓冲区的单个数据存储。这样可以将声音限制提高到20级-但这并不能解决整个问题,可能是因为我没有正确实现这一点。
实现方式:
class SoundDataBank
{
/**
* Holds a single byte array for each sound
*/
Dictionary<eSFX, Byte[]> bank;
string curdir => Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
public SoundDataBank()
{
bank = new Dictionary<eSFX, byte[]>();
bank.Add(eSFX.planet, NativeFile.ReadAllBytes(curdir + @"\Assets\Planet.wav"));
bank.Add(eSFX.base1, NativeFile.ReadAllBytes(curdir + @"\Assets\Base.wav"));
}
public Byte[] GetSoundData(eSFX sfx)
{
byte[] output = bank[sfx];
return output;
}
}
在SoundEngine中,我们创建一个SoundBank对象(在SoundEngine构造函数中初始化):
SoundDataBank soundBank;
public VoiceChannel AddAndPlaySFXFromStore(eSFX sfx, double vol)
{
/**
* sourcevoice will be automatically added to MasteringVoice and engine in the constructor.
*/
byte[] buffer = soundBank.GetSoundData(sfx);
MemoryStream memoryStream = new MemoryStream(buffer);
SoundStream soundStream = new SoundStream(memoryStream);
SourceVoice source = new SourceVoice(engine, soundStream.Format);
AudioBuffer audioBuffer = new AudioBuffer()
{
Stream = soundStream.ToDataStream(),
AudioBytes = (int)soundStream.Length,
Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
};
//Make voice wrapper
VoiceChannel voice = new VoiceChannel(source, engine, MakeOutputMatrix());
//Volume
source.SetVolume((float)vol);
//Play sound
source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
source.Start();
sourceVoices.Add(voice);
return voice;
}
现在,执行此实现后,我可以播放多达20种声音效果-但不是因为我们正在从音库中播放。实际上,即使运行声音效果的旧方法,现在也可以达到20个sfx实例。
由于我们已经在SoundBank的构造函数中完成了NativeFile.ReadAllBytes(curdir + @“\ Assets \ Base.wav”),因此最多可以改进20个。
我怀疑NativeFile正在保存已加载文件数据的存储,因此无论您是运行原始的SoundEngine.AddAndPlaySFX()还是SoundEngine.AddAndPlaySFXFromStore(),它们都从内存运行?
无论哪种方式,这都使限制达到了以前的三倍,因此这是非常有用的-但需要做进一步的工作。
关于c# - SharpDX XAudio2:6 SourceVoice限制,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53582583/