FMOD CreateSound与用户创建的流
本文关键字:创建 用户 CreateSound FMOD | 更新日期: 2023-09-27 18:36:01
给定一个应该在 C# 中播放 SNES SPC 文件和 FMOD 的 DLL,为什么对 system.createSound
的调用失败?
var ret = system.init(32, FMOD.INITFLAGS.NORMAL, (IntPtr)null);
var soundEx = new FMOD.CREATESOUNDEXINFO()
{
cbsize = Marshal.SizeOf(soundEx),
fileoffset = 0,
length = ~0U,
numchannels = 2,
defaultfrequency = 32000,
format = FMOD.SOUND_FORMAT.PCM16,
pcmreadcallback = pcmreadcallback,
pcmsetposcallback = pcmsetposcallback,
dlsname = null,
};
var mode = FMOD.MODE.DEFAULT | FMOD.MODE.OPENUSER
| FMOD.MODE.LOOP_NORMAL | FMOD.MODE.CREATESTREAM;
ret = system.createSound((string)null, mode, ref soundEx, ref sound);
//^-- ERR_INVALID_PARAM
ret = system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel);
将其与 FMOD 附带的usercreatedsound
示例进行比较:
FMOD.MODE mode = (FMOD.MODE._2D | FMOD.MODE.DEFAULT
| FMOD.MODE.OPENUSER | FMOD.MODE.LOOP_NORMAL
| FMOD.MODE.HARDWARE);
//snip
createsoundexinfo.cbsize = Marshal.SizeOf(createsoundexinfo);
createsoundexinfo.fileoffset = 0;
createsoundexinfo.length = frequency * channels * 2 * 2;
createsoundexinfo.numchannels = (int)channels;
createsoundexinfo.defaultfrequency = (int)frequency;
createsoundexinfo.format = FMOD.SOUND_FORMAT.PCM16;
createsoundexinfo.pcmreadcallback = pcmreadcallback;
createsoundexinfo.pcmsetposcallback = pcmsetposcallback;
createsoundexinfo.dlsname = null;
//snop
result = system.createSound(
(string)null,
(mode | FMOD.MODE.CREATESTREAM),
ref createsoundexinfo,
ref sound);
长度,频率...无所谓。
编辑:我已经确认SPC播放器可以工作,至少就初始化而言,并且FMOD附带的示例构建和运行良好。除了调整设置以尝试使其运行之外,唯一特别有意义的更改是以 4.0 风格编写它。
任意采样率的播放不一定在所有声卡上都可用。 32Khz 不是"常见"速率,例如 44.1、48、96 等......
- 你试过FMOD吗?模式。软件?
- 您可以使用ASIO4ALL使用仲裁采样率,但您需要切换到 ASIO。
你和 FMOD 有联系吗?如果没有,那么请考虑 BASS.NET,您将比在 FMOD 中拥有更多的控制权来做这些事情。
使用 BASSMix 的示例:请参阅下面的备注
using System;
using Un4seen.Bass;
using Un4seen.Bass.AddOn.Mix;
namespace XXX
{
public class Resampler : IDisposable
{
private readonly int _channels;
private readonly string _filename;
private readonly int _samplerate;
public Resampler(string filename, int samplerate, int channels)
{
if (filename == null) throw new ArgumentNullException("filename");
if (samplerate <= 0) throw new ArgumentNullException("samplerate");
if (channels <= 0) throw new ArgumentNullException("channels");
#region Initialize BASS stuff
#endregion
_filename = filename;
_samplerate = samplerate;
_channels = channels;
}
#region IDisposable Members
public void Dispose()
{
throw new NotImplementedException();
}
#endregion
public void Resample(string filename)
{
if (filename == null) throw new ArgumentNullException("filename");
Exceptions.ThrowIfPathInvalid(filename);
#region Create stream and mixer
int channel = Bass.BASS_StreamCreateFile(filename, 0, 0,
BASSFlag.BASS_STREAM_PRESCAN | BASSFlag.BASS_STREAM_DECODE |
BASSFlag.BASS_SAMPLE_FLOAT);
if (channel == 0)
throw new BassException("Couldn't create stream.");
var mixer = BassMix.BASS_Mixer_StreamCreate(22050, 1, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
if (mixer == 0)
throw new BassException("Couldn't create mixer stream.");
if (!BassMix.BASS_Mixer_StreamAddChannel(mixer, channel,
BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_MIXER_FILTER |
BASSFlag.BASS_MIXER_NORAMPIN))
throw new BassException("Couldn't add stream channel to mixer.");
#endregion
int sr = 22050;
int secs = 20;
int samples0 = sr * secs;
var buffer = new float[samples0];
int length = sizeof(float) * buffer.Length;
var getData = Bass.BASS_ChannelGetData(mixer, buffer, length | (int)BASSData.BASS_DATA_FLOAT);
if (getData != length)
{
throw new BassException("");
}
var bassMixerChannelRemove = BassMix.BASS_Mixer_ChannelRemove(channel);
var streamFree = Bass.BASS_StreamFree(channel);
var bassStreamFree = Bass.BASS_StreamFree(mixer);
}
}
}
(在VS2010中使用最新的低音工作)
一些额外的提示:
你必须打电话给巴斯。首先Bass_Init,
不要忘记复制低音.dll和贝斯混音.dll在你的EXE旁边,
我个人会坚持BASS_SAMPLE_FLOAT即使您的来源不是,最大的好处是你不会用这种格式进行剪辑,我告诉你这个是因为我为 NES emu 制作了一个音频包装器,APU 的输出非常"动态",事实证明它是有帮助的。此外,这使事情更简单,质量最好。
在您的情况下,您希望使用推送流并用您的SNES输出馈送它:Bass..::.。BASS_StreamCreatePush
创建一个"标准"混音器流(不是解码流),插入推送流,播放混音器
在示例中,它是一个解码流,因为我需要处理数据,而不是播放数据。
BassException只是我自己创建的东西,把它改成你想要的任何东西
您最好的朋友将是CHM帮助文件,也是他们的论坛。
我建议你用这段代码开始一些事情,然后在你有任何问题时发布你的新代码。
我不得不说,BASS一开始很难掌握,但最终是非常有益的。我最近在学习OpenGL 3.X时也有完全相同的感觉;起初这很不可理解,但现在我可以做很多事情。我会说BASS与OpenGL和3D相当。
抱歉,自上次以来我病得很重,大部分时间都没有使用PC,但是我看到了您的消息,并希望快速回复,以便您可以继续前进。如果有人从SO抱怨我的答案的布局:我稍后会修复它。