从PCM数据创建.wav文件

从PCM数据创建.wav文件,c,audio,wav,binary-data,pcm,C,Audio,Wav,Binary Data,Pcm,我正在尝试从SPH0645LM4H-B读取数据 并将其转换为.wav格式,以便验证传感器是否正常工作。 到目前为止,我已经设法接口传感器和读取数据样本通过i2s dma传输 此外,我发现大多数主流的计算机声音文件格式都由一个头文件(包含长度等)和16位的two's-complete PCM 对于将PCM数据转换为波形格式,我已参考 现在,传感器数据格式是I2S,24位,2的补充,MSB优先。数据精度为18位;未使用的位是零。 我已将传感器数据转换为32位(MSB是符号位) 我使用了以下链接(以及

我正在尝试从SPH0645LM4H-B读取数据 并将其转换为.wav格式,以便验证传感器是否正常工作。 到目前为止,我已经设法接口传感器和读取数据样本通过i2s dma传输

此外,我发现大多数主流的计算机声音文件格式都由一个头文件(包含长度等)和16位的two's-complete PCM

对于将PCM数据转换为波形格式,我已参考

现在,传感器数据格式是I2S,24位,2的补充,MSB优先。数据精度为18位;未使用的位是零。 我已将传感器数据转换为32位(MSB是符号位)

我使用了以下链接(以及其中提到的链接)中的代码来创建.wav文件:-

//.wav文件头数据

struct wavfile
{
char            id[4];          // should always contain "RIFF"
int             totallength;    // total file length minus 8
char            wavefmt[8];     // should be "WAVEfmt "
int             format;         // 16 for PCM format
short           pcm;            // WAVE_FORMAT_IEEE_FLOAT (3).
short           channels;       // channels
int             frequency;      // sampling frequency, 16000 in this case
int             bytes_per_second;
short           bytes_by_capture;
short           bits_per_sample;
char            data[4];        // should always contain "data"
int             bytes_in_data;
};
//将标头写入输出.wav文件

void write_wav_header(char* name, int samples, int channels)
{
struct wavfile filler;
FILE *pFile;
strcpy(filler.id, "RIFF");
filler.totallength = (samples * channels) + sizeof(struct wavfile) - 8;
strcpy(filler.wavefmt, "WAVEfmt ");
filler.format = 16;
filler.pcm = 3; // WAVE_FORMAT_IEEE_FLOAT (3).
filler.channels = channels;
filler.frequency = 32000;
filler.bits_per_sample = 32;
filler.bytes_per_second = filler.channels * filler.frequency * filler.bits_per_sample/8;
filler.bytes_by_capture = filler.channels*filler.bits_per_sample/8;
filler.bytes_in_data = samples * filler.channels * filler.bits_per_sample/8;
strcpy(filler.data, "data");
pFile = fopen(name, "wb");
fwrite(&filler, 1, sizeof(filler), pFile);
fclose(pFile);
}
void write_pcm_data_to_file(char* inFile, char* outFile)
{
char buffer[SAMPLE_SIZE];
size_t n;
FILE *fin,*fout;
fin = fopen(inFile,"r");
fout = fopen(outFile,"a");
while((n = fread(buffer, 1, sizeof(buffer), fin)) > 0)
{
    if(n != fwrite(buffer, 1, n, fout))
    {
        perror("fwrite");
        exit(1);
    }
}
fclose(fin);
fclose(fout);
}
//将音频传感器数据附加到此.wav文件

void write_wav_header(char* name, int samples, int channels)
{
struct wavfile filler;
FILE *pFile;
strcpy(filler.id, "RIFF");
filler.totallength = (samples * channels) + sizeof(struct wavfile) - 8;
strcpy(filler.wavefmt, "WAVEfmt ");
filler.format = 16;
filler.pcm = 3; // WAVE_FORMAT_IEEE_FLOAT (3).
filler.channels = channels;
filler.frequency = 32000;
filler.bits_per_sample = 32;
filler.bytes_per_second = filler.channels * filler.frequency * filler.bits_per_sample/8;
filler.bytes_by_capture = filler.channels*filler.bits_per_sample/8;
filler.bytes_in_data = samples * filler.channels * filler.bits_per_sample/8;
strcpy(filler.data, "data");
pFile = fopen(name, "wb");
fwrite(&filler, 1, sizeof(filler), pFile);
fclose(pFile);
}
void write_pcm_data_to_file(char* inFile, char* outFile)
{
char buffer[SAMPLE_SIZE];
size_t n;
FILE *fin,*fout;
fin = fopen(inFile,"r");
fout = fopen(outFile,"a");
while((n = fread(buffer, 1, sizeof(buffer), fin)) > 0)
{
    if(n != fwrite(buffer, 1, n, fout))
    {
        perror("fwrite");
        exit(1);
    }
}
fclose(fin);
fclose(fout);
}
以下是生成的.wav文件在十六进制编辑器中的外观:- 我可以看到wav标题值设置正确,随后是来自音频传感器的PCM数据

但是,当我播放.wav文件时,我无法播放输入音频。相反,我听到了一个不变的音调。 我尝试更改输入音频(播放不同的音乐、歌曲),但生成的.wav文件播放相同的恒定音调

为了将麦克风播放的输入音乐重新创建为wav文件,我应该做哪些修改

提前谢谢

编辑:-

根据Soffith的回答,为了将示例转换为十六进制,我使用了以下代码:-

hexValue = strtoll(sample, NULL, 16);
我转换了缓冲区中的每个值,然后将其写入.wav文件。现在我的.wav文件看起来像

但是,即使这个wav文件也不会播放音频。 有没有进一步的建议将麦克风播放的输入音乐重新创建为wav文件


非常感谢您的帮助

对于初学者,您将PCM数据存储在文件中作为ascii十六进制。我希望这有帮助

这是一个“黑客”你可以使用

char c[2];
while((n = fread(&c[0], 2, 1, fin)) > 0)
 { 
    if (c[0] > 0x39) c[0] -= 7;
    c[0] &= 0x0F;
    if (c[1] > 0x39) c[1] -= 7;
    c[1] &= 0x0F;
    c[1] |= c[0] << 4;
    if(1 != fwrite(&c[1], 1, 1, fout))
charc[2];
而((n=fread(&c[0],2,1,fin))>0)
{ 
如果(c[0]>0x39)c[0]=7;
c[0]&=0x0F;
如果(c[1]>0x39)c[1]=7;
c[1]&=0x0F;

c[1]|=c[0]对于初学者,您将PCM数据存储在文件中作为ascii十六进制。我希望这会有所帮助

这是一个“黑客”你可以使用

char c[2];
while((n = fread(&c[0], 2, 1, fin)) > 0)
 { 
    if (c[0] > 0x39) c[0] -= 7;
    c[0] &= 0x0F;
    if (c[1] > 0x39) c[1] -= 7;
    c[1] &= 0x0F;
    c[1] |= c[0] << 4;
    if(1 != fwrite(&c[1], 1, 1, fout))
charc[2];
而((n=fread(&c[0],2,1,fin))>0)
{ 
如果(c[0]>0x39)c[0]=7;
c[0]&=0x0F;
如果(c[1]>0x39)c[1]=7;
c[1]&=0x0F;

c[1]|=c[0]Hi@42Leapsofith。我一直在玩我的数据,试图转换它(strtoll(),atoi()等)。但是,我仍然无法理解你的意思。你能详细说明一下在将数据复制到.wav文件之前,我应该如何修改数据吗?答案在你的.wav文件中的十六进制编辑器中。”图像。您的填充文件中的数据格式错误-它是ascii十六进制格式(字符串)。在使用它之前,您需要将其转换回十六进制(int)(即“A5”>0xA5)。或者,首先以正确的格式存储在填充文件中…我希望这会有所帮助。char c[1];while((n=fread(&c[0],2,1,fin))>0{if(c[0]>0x39)c[0]-=7;c[0]&=0x0F;如果(c[1]>0x39)c[1]-=7;c[1]&=0x0F;c[0]|=c[1]为什么“filler.pcm=3;//WAVE_FORMAT_IEEE_FLOAT(3)”,当你在写INT时。你的通道数和位数都不清楚……你知道数据的尾数吗?嗨@42Leapsofith。我一直在玩我的数据,试图转换它(strtoll()、atoi()等)。但是,我仍然无法理解您的意思。请您详细说明一下,在将数据复制到.wav文件之前,我应该如何修改数据?答案在您的“十六进制编辑器中的.wav文件”图像中。填充文件中的数据格式错误-它是ascii十六进制格式(字符串)。在使用它之前,您需要将其转换回十六进制(int)(即“A5”>0xA5)。或者,首先以正确的格式将其存储在填充中…我希望这会有所帮助。char c[1];而((n=fread(&c[0],2,1,fin))>0){if(c[0]>0x39)c[0]=7;c[0]&=0x0F;if(c[1]>0x39)c[1]-=7;c[1]&=0x0F;c[0]&c[1]为什么“filler.pcm=3;//WAVE\u FORMAT\u IEEE\u FLOAT(3)。”当您写入INT时,通道数和位数不清楚……您知道数据的尾数吗?