新超声音采集卡NET2406T存WAV格式文件

发布日期:
2024-11-06

浏览次数:

一、预备知识:

PCMPulse Code Modulation,脉冲编码调制)是一种将模拟信号转换为数字信号的编码方式。在音频处理中,PCM是最常用的格式之一,用来表示原始的未压缩数字音频数据。PCM将连续的模拟音频波形信号采样并量化成一系列的数字值,通常是通过以下几个参数定义的:

1采样率(Sample Rate:每秒采样的次数,通常用赫兹(Hz)表示,比如常见的44100 HzCD质量)或48000 Hz(视频音频标准)。

2量化位深(Bit Depth:每个采样的位数,比如8位、16位、24位等。位深越高,音频的动态范围和精度越高。常见的位深是16位。

3声道数(Channels:例如单声道(Mono)或立体声(Stereo),单声道数据有一个音频通道,而立体声则有左右两个通道。

 

二、PCM音频数据的存储形式

PCM格式中,每个采样点直接保存了音频波形的数值(对应特定时间点的音量)。对于16位的PCM音频数据,每个采样点用2个字节存储,常见的存储方式是Little Endian(低位字节在前)。

PCM数据本身不带有文件头或元数据信息,只是纯音频样本数据。因此在保存到文件时通常会包装成WAV等带文件头的格式,以便保存采样率、位深和通道数等信息,从而使播放器可以正确解码音频数据。

 

如果采集到的是 double 类型的电压数据数组则需要先将这些数据转换为合适的整数格式(例如 int16_t  int32_t)以符合 WAV 文件的要求。WAV 文件的 PCM 数据通常使用整数表示(例如 16 位或 24 位),而不是浮点数。因此,需要将 double 类型的电压值进行缩放和量化,以适配整数范围

以下是步骤和实现代码:

2.1、将 double 型电压转换为 PCM 整数数据

假设电压数据的值范围在 -1.0 1.0 之间,可以将它们缩放到 16 PCM 的范围(-32768 32767)。如果电压值范围不同,需要先将其归一化或缩放到 [-1.0, 1.0] 之间。

 

如果使用新超仁达的NET-2406T采集到的电压数据范围在 -5.0V  5.0V 之间,那么在将这些电压值转换为 PCM 格式之前,需要先对其进行缩放,使其适配 24 PCM 数据的范围(-8388608 8388607)。下面是处理这个过程的步骤详细请联系新超仁达科技,网址:www.xckz.com

新超声音采集卡NET2406T存WAV格式文件 

处理步骤

1)、缩放电压数据

将电压数据从 -5.0 5.0 的范围转换到 -1.0 1.0 的范围。通过归一化来实现。这样,-5.0 变为 -1.05.0 变为 1.0

2)、转换为 24 位 PCM 数据

将缩放后的值乘以 8388607(即 2^23 −1),得到合适的整数值范围。

 

2.2、编写代码转换并保存为 WAV 文件部分代码,详细联系新超仁达科技网址:www.xckz.com

#include

#include

#include

#include

 

// WAV文件头结构

struct WAVHeader {

    char chunkID[4];        // "RIFF"

    uint32_t chunkSize;     // 文件大小 - 8字节

    char format[4];         // "WAVE"

    char subchunk1ID[4];    // "fmt "

    uint32_t subchunk1Size; // PCM = 16

    uint16_t audioFormat;   // PCM = 1

    uint16_t numChannels;   // 声道数

    uint32_t sampleRate;    // 采样率

    uint32_t byteRate;      // byteRate = SampleRate * NumChannels * BitsPerSample / 8

    uint16_t blockAlign;    // blockAlign = NumChannels * BitsPerSample / 8

    uint16_t bitsPerSample; // 位深

    char subchunk2ID[4];    // "data"

    uint32_t subchunk2Size; // data size = NumSamples * NumChannels * BitsPerSample / 8

};

 

void writeWAV(const std::string& filename, const std::vector& audioData,

              int sampleRate, int numChannels, int bitsPerSample) {

    // 创建WAV文件头

// 省略核心代码

//

// 省略核心代码

}

 

}

 

三、立体声

对于音频应用,如果需要更高的音频质量,使用立体声(2 个通道)或更多通道可能会带来更丰富的音频体验。在使用多个传感器进行数据采集,需要确保所有传感器的信号能够有效同步。这对于正确处理多通道音频信号非常重要。

WAV 文件中,如果使用两个通道(例如立体声),PCM 数据的存储格式会有所不同。每个音频样本将包含两个通道的数据,通常以交替的方式存储,即左声道和右声道的样本交替出现。

立体声PCM 数据的存储格式

假设每个样本是 16 位 PCM(即每个样本使用 2 字节),那么对于两个通道的 PCM 数据,存储格式将如下所示:

样本 1:左声道(L1) 右声道(R1

样本 2:左声道(L2) 右声道(R2

样本 3:左声道(L3) 右声道(R3

// 假设你有两个通道的 PCM 数据

std::vector leftChannel = {1000, 2000};  // 左声道数据

std::vector rightChannel = {-1000, -2000}; // 右声道数据

std::vector pcmData;

 

// PCM 数据交替存放到 pcmData

for (size_t i = 0; i < leftChannel.size(); ++i) {

    // 将左声道数据添加到 pcmData

    pcmData.push_back(static_cast((leftChannel[i] >> 0) & 0xFF));   // 低位

    pcmData.push_back(static_cast((leftChannel[i] >> 8) & 0xFF));   // 高位

 

    // 将右声道数据添加到 pcmData

    pcmData.push_back(static_cast((rightChannel[i] >> 0) & 0xFF));  // 低位

    pcmData.push_back(static_cast((rightChannel[i] >> 8) & 0xFF));  // 高位

}

 

重要的注意事项

1交替存储:确保左声道和右声道的样本交替存储,这是处理立体声音频的标准格式。

2字节顺序:根据你的平台,确保字节顺序(大端或小端)正确。例如,通常在 x86 系统中采用小端字节序。

3位深:上述示例假设为 16 位样本。如果你的数据是 24 位或其他位深,需要相应地调整数据存储方式(例如,24 位样本需要 3 字节)。

4采样率和其他头信息:在写入文件之前,确保在 WAV 文件头中正确设置采样率、位深和通道数。

总结

对于两个通道的 PCM 数据,将左声道和右声道的样本交替存储是处理立体声音频的标准方法。在将数据写入 WAV 文件时,确保数据格式正确,以保证音频的播放和处理效果。