通过前一个章节打下的基础车载音频开发(一):从看懂wav开始https://blog.csdn.net/Hellomino_/article/details/140873133?fromshare=blogdetail&sharetype=blogdetail&sharerId=140873133&sharerefer=PC&sharesource=Hellomino_&sharefrom=from_link 我们已经对音频文件wav有了初步的了解
接下来我们可以将音频的每个采样点的数据提取出来,对数据进行处理,简单的,我们可以将数据减小或增大来升高或减低整体的音量。
一般的,音频的数据采样点分为定点和浮点
定点常见的有16bit,24bit,和32bit
浮点一般用float (32bit)
然后,我们必须要指导采样点数值与分贝值(dB)之间的关系
data : 每个采样点存储的数值(以浮点值为例)
db : 每个采样点转化的dB值
dB = 20 * log10f(abs( data))
接下来就是代码时间
1.首先还是创建读取wav头部信息的结构体
struct WavHeader {
char chunkId[4]; //"RIFF"
uint32_t chunkSize; //totalsize - 8
char format[4]; //"WAVE"
char subchunk1Id[4]; //"fmt"
uint32_t subchunk1Size; //16:Normal; 18:Non_PCM; 40:Extensible;
};
struct type40_header {
uint16_t audioFormat; //wav 格式 1;int型 3:float型 65534:未知
uint16_t numChannels; //声道数
uint32_t sampleRate; //采样率
uint32_t byteRate; //比特率:采样率 * 采样位宽
uint16_t blockAlign; //采样深度:
uint16_t bitsPerSample; //采样位宽:采样深度 * 8
uint16_t cbSize;
uint16_t wValidBitsPerSample;
uint32_t dwChannelMask;
char SubFormat[4];
char ckID[4];
uint32_t cksize;
uint32_t dwSampleLength;
};
struct data_header {
char subchunk2Id[4]; //"data"
uint32_t subchunk2Size; //datasize
};
其次,我们创建一个预定义函数
#define volume_(x) pow(10, (x / 20))
接下来,我们用用一个函数将所有采样点数据进行提取并调整音量
int volume_contral(const char* filename,float gain)
{
WavHeader header = {};
type40_header headera = {};
data_header headerb = {};
ifstream inputFile(filename, ios::binary);
if (!inputFile.is_open()) {
cerr << "无法打开文件" << endl;
return -1;
}
// 读取WAV文件头部信息并写入
ofstream output("output.wav", ios::binary);
if (!output.is_open()) {
cerr << "无法打开文件" << endl;
return -1;
}
inputFile.read(reinterpret_cast<char*>(&header), sizeof(header));
inputFile.read(reinterpret_cast<char*>(&headera), header.subchunk1Size);
inputFile.read(reinterpret_cast<char*>(&headerb), sizeof(headerb));
output.write(reinterpret_cast<char*>(&header), sizeof(header));
output.write(reinterpret_cast<char*>(&headera), header.subchunk1Size);
output.write(reinterpret_cast<char*>(&headerb), sizeof(headerb));
const size_t dataSize = headerb.subchunk2Size;
vector<char> buffer(dataSize);
inputFile.read(buffer.data(), dataSize);
uint32_t rearsize = header.chunkSize - (uint32_t)dataSize - header.subchunk1Size - sizeof(headerb) - 12;
vector<char> rear(rearsize);
inputFile.read(rear.data(), rearsize);
inputFile.close();
uint16_t perdatasize = headera.bitsPerSample / 8;
float wavdata;
int32_t WavData = 0;
int16_t WavData16 = 0;
for (size_t i = 0; i < dataSize / perdatasize; i++) {
if (16 == headera.bitsPerSample)
{
memcpy(&WavData16, buffer.data() + i * perdatasize, perdatasize);
printf(" %10d , %.2f db ,", WavData16, 20 * log10f(abs((float)WavData16) / 32768));
WavData16 = (int16_t)WavData16 * volume_(gain);
memcpy(buffer.data() + i * perdatasize, &WavData16, perdatasize);
printf("\t %10d , %.2f db ,", WavData16, 20 * log10f(abs((float)WavData16) / 32768));
}
else if (24 == headera.bitsPerSample)
{
memcpy(&WavData, buffer.data() + i * perdatasize, perdatasize);
printf(" %10d , %.2f db ,", (WavData << 8) / 256, 20 * log10f(abs((float)(WavData << 8)) / 256 / 8388608));
WavData = (int32_t)((WavData << 8) * volume_(gain));
WavData >>= 8;
memcpy(buffer.data() + i * perdatasize, &WavData, perdatasize);
printf("\t %10d , %.2f db ,", (WavData << 8) / 256, 20 * log10f(abs((float)(WavData << 8)) / 256 / 8388608));
}
else if (32 == headera.bitsPerSample)
{
if (3 == headera.audioFormat || (65534 == headera.audioFormat && 0x01 != headera.SubFormat[0])) {
memcpy(&wavdata, buffer.data() + i * perdatasize, perdatasize);
printf(" %.6f , %.2f db ,", wavdata, 20 * log10f(abs(wavdata)));
wavdata = wavdata * volume_(gain);
memcpy(buffer.data() + i * perdatasize, &wavdata, perdatasize);
printf("\t %.6f , %.2f db ,", wavdata, 20 * log10f(abs(wavdata)));
}
else {
memcpy(&WavData, buffer.data() + i * perdatasize, perdatasize);
printf(" %16d , %.2f db ,", WavData, 20 * log10f(abs((float)WavData) / 2147483648));
WavData = (int32_t)WavData * volume_(gain);
memcpy(buffer.data() + i * perdatasize, &WavData, perdatasize);
printf("\t %16d , %.2f db ,", WavData, 20 * log10f(abs((float)WavData) / 2147483648));
}
}
cout << endl;
}
output.write(buffer.data(), buffer.size());
output.write(rear.data(), rearsize);
buffer.clear();
output.close();
return 0;
}