我正在使用 OpenTK,更准确地说是 OpenAL。我能够从麦克风捕获声音,但随后我想将数据保存到 WAVE 文件中。
我找到了一个如何编写波形文件的示例,结果几乎可以工作。
我相信我的文件头是正确的,但我对将缓冲区数据写入文件的正确方法有些怀疑。
我第一次尝试使用此设置进行录制:
播放文件只是一些噪音
我更改为单声道设置(1 通道)。 这次我能够再现音频,但播放速度快了 2 倍
我是否应该先转换 ALC.CaptureSamples 中的数据,然后再将其直接写入流?
要添加一些代码,首先我有捕获样本,我认为它可以正常工作(我从 OpenAL 存储库的 TestUnit 中获得):
int totalSamples = 0;
while (totalSamples < buffer.Length && !_cancellationToken.IsCancellationRequested)
{
int samplesAvailable = ALC.GetInteger(_captureDevice, AlcGetInteger.CaptureSamples);
if (samplesAvailable < 512) continue;
int samplesToRead = Math.Min(samplesAvailable, buffer.Length - totalSamples);
ALC.CaptureSamples(_captureDevice, ref buffer[totalSamples], samplesToRead);
totalSamples += samplesToRead;
spinWait.SpinOnce();
}
然后我简单地写入流:
// headers writing...
// ...
sw.Write(buffer, 0, totalSamples);
我没有找到任何有关 OpenAL 和文件写入的示例...
一切都正确吗?
我错过了一些步骤吗?
好的@fdcpp 给了我一个提示,但没有编写完整的示例。因此,为了使其正常工作,对于单声道 16 位声音,缓冲区应该是
ushort
而不是 byte
类型。
缺少一些关于声音音频规格的知识😔
所以代码的具体部分是:
// Capture the device
_captureDevice = ALC.CaptureOpenDevice(null, 44100, ALFormat.Mono16, 1024);
...
// Start recording
var buffer = new ushort[44100 * 16];
...
// Writing data
ushort bytePerBloc = 1 * (16 / 8);
using (MemoryStream memoryStream = new())
using (BinaryWriter sw = new(memoryStream))
{
sw.Write(['R', 'I', 'F', 'F']);
sw.Write(totalSamples * bytePerBloc + 36);
...
sw.Write(['d', 'a', 't', 'a']);
sw.Write(totalSamples * bytePerBloc); // size of buffer
for (int i = 0; i < totalSamples; i++)
{
sw.Write(buffer[i]);
}
...
}
现在它正在工作。
下一步尝试使用立体声 16 位进行相同的操作 😅