实时录制/转换AUDIO数据到WAV

时间:2015-01-30 05:33:42

标签: c++ audio wav recording

在音频信号处理方面,我是新手。

目前我已将设备连接到我的PC,该设备向我发送麦克风/播放曲目的音频数据。我已经创建了使用Steinberg ASIO SDK 2.3的主机应用程序,它连接到设备并重复回调返回原始数据。信号是24位,频率可以选择任何我喜欢的,比如44100 hZ,2pan,单通道。我已将此信号转换为双倍< -1.0,1.0>因为我正在做一些信号处理。

我现在要做的是向主机添加录制功能。例如,在按钮单击时,传入的数据将被连续转换为WAV文件,当我单击其他按钮时,它将停止并保存。

我已经阅读过关于WAV文件,文件格式,比特流格式(RIFF)的内容,并且以某种方式全面了解WAV文件的外观。我还检查了很多论坛帖子,stackoverflow的线程或代码项目帖子以及我发现与主题相关的所有内容但我无法知道如何实时进行持续录制。我发现的很多代码都是在对数据进行修改后将数据转换为WAV。我想进行持续转换并使WAV文件追加/扩展,直到我告诉它停止。

例如我可以以某种方式修改它吗?

#include <fstream>

template <typename T>
void write(std::ofstream& stream, const T& t) {
  stream.write((const char*)&t, sizeof(T));
}

template <typename T>
void writeFormat(std::ofstream& stream) {
  write<short>(stream, 1);
}

template <>
void writeFormat<float>(std::ofstream& stream) {
  write<short>(stream, 3);
}

template <typename SampleType>
void writeWAVData(
  char const* outFile,
  SampleType* buf,
  size_t bufSize,
  int sampleRate,
  short channels)
{
  std::ofstream stream(outFile, std::ios::binary);
  stream.write("RIFF", 4);
  write<int>(stream, 36 + bufSize);
  stream.write("WAVE", 4);
  stream.write("fmt ", 4);
  write<int>(stream, 16);
  writeFormat<SampleType>(stream);                                // Format
  write<short>(stream, channels);                                 // Channels
  write<int>(stream, sampleRate);                                 // Sample Rate
  write<int>(stream, sampleRate * channels * sizeof(SampleType)); // Byterate
  write<short>(stream, channels * sizeof(SampleType));            // Frame size
  write<short>(stream, 8 * sizeof(SampleType));                   // Bits per sample
  stream.write("data", 4);
  stream.write((const char*)&bufSize, 4);
  stream.write((const char*)buf, bufSize);
}

以某种方式回调:

writeWAVData("mySound.wav", mySampleBuffer, mySampleBufferSize, 44100, 1);

我很感激任何提示/链接/建议/形式的帮助。

1 个答案:

答案 0 :(得分:3)

您的使用案例与您在线上看到的代码之间的区别在于,在您的使用案例中,您事先并不知道该文件最终会持续多长时间,因为您不会#39;知道用户何时按下停止按钮。

处理这个问题的方法是像往常一样写出WAV标题,但现在不要担心你为特定文件大小的字段写的值(即#34之后的字段) ; RIFF&#34;以及&#34;数据&#34;)之后的字段。您现在可以将这些字段设置为零。

然后在收到音频样本时将其写出来,即将它们附加到文件的末尾。

最后,在用户按下停止并且您即将关闭文件后,您需要返回并使用正确的值覆盖这两个标头字段。你现在可以这样做,因为此时你知道你写入文件的音频数据的字节数。完成后,文件应该是格式良好且可用的。你可以用例如ofstream::seekp(fieldOffset, ios_base::beg)从文件顶部寻找适合您需要修改的字段的偏移量。