实时从数据创建WAV文件-需要帮助吗 我对音频处理很陌生,我的C++编程技巧也在基础层面上。我必须创建记录函数,并以回调的形式从设备接收数据信号。我想有人来帮助我的基本理论,我应该如何管理WAV内存,因为我迷路了。目前,我的代码如下所示:

实时从数据创建WAV文件-需要帮助吗 我对音频处理很陌生,我的C++编程技巧也在基础层面上。我必须创建记录函数,并以回调的形式从设备接收数据信号。我想有人来帮助我的基本理论,我应该如何管理WAV内存,因为我迷路了。目前,我的代码如下所示:,c++,ios,audio,wav,C++,Ios,Audio,Wav,我当前使用的功能: 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 <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|ios::app|ios::ate);

  stream.write("RIFF", 4);                                        // Start writting RIFF
  write<int>(stream, 0);                                          // (file-size)-8 - FOR NOW IGNORED
  stream.write("WAVE", 4);                                        // File type

  stream.write("fmt ", 4);                                        // Start Writting format chunk "fmt"
  write<int>(stream, 16);                                         // Chunk Data Size 16 + extra format bytes
  writeFormat<SampleType>(stream);                                // Format (compression code)
  write<short>(stream, channels);                                 // Channels
  write<int>(stream, sampleRate);                                 // Sample Rate
  write<int>(stream, sampleRate * channels * sizeof(SampleType)); // Byterate (byte/per sec)
  write<short>(stream, channels * sizeof(SampleType));            // Frame size (block align)
  write<short>(stream, 8 * sizeof(SampleType));                   // Bits per sample 

  stream.write("data", 4);                                        // Start writting chunk for extra format bytes
  stream.write((const char*)&bufSize, 0);                         //  - FOR NOW IGNORED
  stream.write((const char*)buf, 0);                              //  - FOR NOW IGNORED
}
模板
无效写入(流和流的标准::常数T&T){
stream.write((const char*)&t,sizeof(t));
}
模板
void writeFormat(流和流的标准::){
写入(流,1);
}
模板
void writeFormat(流和流的标准::){
写入(流,3);
}
模板
无效写入数据(
字符常量*输出文件,
样本类型*buf,
大小,
int采样器,
短频道)
{
流流的std::of(outFile,std::ios::binary | ios::app | ios::ate);
stream.write(“RIFF”,4);//开始写RIFF
写入(流,0);/(文件大小)-8-暂时忽略
stream.write(“WAVE”,4);//文件类型
stream.write(“fmt”,4);//开始写入格式块“fmt”
写入(流,16);//块数据大小16+额外的格式字节
writeFormat(流);//格式(压缩代码)
写入(流,通道);//通道
写入(流、采样器);//采样率
写入(流,采样器*通道*sizeof(SampleType));//字节数(字节/秒)
写入(流,通道*sizeof(SampleType));//帧大小(块对齐)
写入(流,8*sizeof(SampleType));//每个样本位
stream.write(“data”,4);//开始为额外的格式字节写入数据块
stream.write((const char*)&bufSize,0);//-现在被忽略
stream.write((const char*)buf,0);//-现在被忽略
}
总的来说,我想做的是:

  • 创建*.wav文件
  • 写入头块
  • 只要用户不停止,就在文件末尾添加新数据
  • 当用户单击“停止”时,返回“RIFF”和“data”块下的标题内存和编辑字段,并使用正确的值
  • 第一个问题:我有一个存储256个样本的缓冲区,所以在循环中,每256个样本我都会尝试用新数据将缓冲区写入文件,如下面的代码所示。在阅读了*.wav文档之后,我了解到*.wav文件应该在每个块的开头有RIFF头。但若我写了256个样本的缓冲区,并将RIFF块放在它前面,若我改为输入512个样本又有什么区别呢?是否每个样本都需要RIFF块

    for (int j = 0 ; j < 256 ; j++)
    {
        if (j == 255) 
            writeWAVData("mySound0.wav", (int*)bufferInfos[0].buffers[doubleBufferIndex], buffSize, 44100, 1);
    }
    
    for(int j=0;j<256;j++)
    {
    如果(j==255)
    writeWAVData(“mySound0.wav”,(int*)bufferInfos[0]。buffers[doubleBufferIndex],buffSize,44100,1);
    }
    
    其中:

    • bufferInfos[]-保存各种缓冲区的表,但我现在只想保存其中一个缓冲区的数据
    • bufferInfos[0]。buffers[doubleBufferIndex]-是指向第一个缓冲区数据块的指针
    • doubleBufferIndex—pan的索引,取值为0-1、左、右、左、右等
    第二个问题:是关于通道参数的,因为它有点混乱。我的信号由依次接收的值组成:左平移、右平移、左平移、右平移。。。那就意味着我有两个频道-左和右


    第三个问题:我的设备信号是24位。。。那么,我不应该只写每个样本24的位,或者它应该如何包含这些信息。

    RIFF头在每个文件的开头显示一次。您试图包含多个

    按照惯例,
    WAVE
    头在每次记录中出现一次。.WAV格式允许多个,但这类似于相册

    很明显,你确实有两个频道

    是的,如果每个样本有24位,那么必须将其放入,每个样本精确写入3个字节。就是说,

    template <typename T>
    void write(std::ofstream& stream, const T& t) {
      stream.write((const char*)&t, sizeof(T));
    }
    
    模板
    无效写入(流和流的标准::常数T&T){
    stream.write((const char*)&t,sizeof(t));
    }
    

    不太可能做到这一点。而且
    sizeof(SampleType)
    可能也不是3。

    你读过你前面问题的答案了吗?在我看来,这个问题有很多重叠之处。具体地说,我们告诉过您,在录制完成之前,您不能将文件大小放入标题中。希望以不同的方式形成问题。最后一个问题的回答是正确的,但我仍然不确定一些事情,所以我想再添加一个。它连接到同一个主题,可能有点重叠。对不起。非常感谢。在使用您的建议后,我现在可以创建.wav文件,该文件将打开,我可以听到一些录制的语音,但速度太快-时间是真实语音的0.1。我想这是因为我写的数据不够,这是由你所说的->常量字符引起的。这应该是大一点的,对吗?我很难说我的信号是24还是32。这是因为ASIO SDK返回用于处理32位和24位信号的ASIOSTInt32LSB。在我的设备规范中,有这样一句话:无论I/O格式如何,系统都使用24位信号路径传输所有数据。但是sizeof(样本)是4…谢谢。你已经回答了我所有的问题。我已经将信号从24位转换为16位,所以我可以使用这种方法。现在我可以理解一些单词,但当我使用1个通道时,记录时间为0.5实时,采样率为44100,因此快了2倍。如果我使用2个通道,那么录制是0.25实时。。。仍然有问题,但我需要继续尝试。听起来好像你在某处混合了“每秒字节数”和“每秒采样数”。是的,我写了2个字节,但在添加额外数据时没有乘以bufferSize x2。现在它起作用了。