车载音频开发(二):对音频数据作音量调节

通过前一个章节打下的基础车载音频开发(一):从看懂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头部信息的结构体

cpp 复制代码
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
};

其次,我们创建一个预定义函数

cpp 复制代码
#define volume_(x) pow(10, (x / 20))

接下来,我们用用一个函数将所有采样点数据进行提取并调整音量

cpp 复制代码
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;
}
相关推荐
allnlei8 小时前
Opus In-Band FEC 详解:原理、实现与开源方案
ffmpeg·音视频·gstreamer
爱吃提升9 小时前
文生视频模型发展趋势(2026)
人工智能·音视频
可乐鸡翅yeah_10 小时前
新手梳理:M3U8 线上问题,哪些是前端锅,哪些是后端锅
前端·ios·音视频·实时音视频·m3u8·音视频在线播放
apple_6926588511 小时前
最新ComfyUI 0.37.1使用教程:画图、3D、音频都有改动 ComfyUI升级到0.37.1啦,新增或改进五大功能
音视频
VidDown17 小时前
从视频画面里提取文字:OCR、文字检测与结构化输出
python·网络协议·ocr·音视频·视频编解码·视频
音视频牛哥18 小时前
一帧视频的底层工程:像素格式、内存带宽、GPU 与 AI
音视频·像素格式·yuv rgb·nv12 nv21·rgb565·rtsp yuv·rtmp rgb
VidDown18 小时前
文件没问题但网页播不了:播放器接入实战与那些“环境问题
python·网络协议·音视频·视频编解码·视频
the3clipse19 小时前
视频编码技术如何赋能游戏性能优化:从硬件隔离到AI驱动的带宽革命
游戏·性能优化·音视频·视频编码·硬件加速·ai编码·自适应编码
I Am a robert girl19 小时前
打破音频生态壁垒:用 WinAirCast 把 Windows 声音塞进 HomePod
windows·音视频·跨平台开发·音频串流·airplay 2·homepod
揽秀亭长19 小时前
视频转脚本有哪些技术路线?三种常见方案对比分析
人工智能·音视频