zoukankan      html  css  js  c++  java
  • 分享用于学习C++音频处理的代码示例

    与《分享用于学习C++图像处理的代码示例》为姊妹篇。

    为了便于学习C++音频处理并研究音频算法,

    俺写了一个适合初学者学习的小小框架。

    麻雀虽小五脏俱全,仅仅考虑单通道处理。

    采用Decoder and Encoder:dr_wav

    https://github.com/mackron/dr_libs/blob/master/dr_wav.h 

    关于wav格式的解析移步至:

    http://soundfile.sapp.org/doc/WaveFormat/

    个人习惯,采用int16的处理方式,也可以通过简单的修改,改为float类型。

     wav音频样本可以从维基百科上(https://en.wikipedia.org/wiki/WAV)下载。

    注:少数wav格式不支持

    FormatBitrate (kbit/s)1 minute (KiB)Sample
    11,025 Hz 16 bit PCM 176.4 1292 11k16bitpcm.wav
    8,000 Hz 16 bit PCM 128 938 8k16bitpcm.wav
    11,025 Hz 8 bit PCM 88.2 646 11k8bitpcm.wav
    11,025 Hz µ-Law 88.2 646 11kulaw.wav
    8,000 Hz 8 bit PCM 64 469 8k8bitpcm.wav
    8,000 Hz µ-Law 64 469 8kulaw.wav
    11,025 Hz 4 bit ADPCM 44.1 323 11kadpcm.wav
    8,000 Hz 4 bit ADPCM 32 234 8kadpcm.wav
    11,025 Hz GSM 06.10 18 132 11kgsm.wav
    8,000 Hz MP3 16 kbit/s 16 117 8kmp316.wav
    8,000 Hz GSM 06.10 13 103 8kgsm.wav
    8,000 Hz Lernout & Hauspie SBC 12 kbit/s 12 88 8ksbc12.wav
    8,000 Hz DSP Group Truespeech 9 66 8ktruespeech.wav
    8,000 Hz MP3 8 kbit/s 8 60 8kmp38.wav
    8,000 Hz Lernout & Hauspie CELP 4.8 35 8kcelp.wav

    附带处理耗时计算,示例演示了一个简单的将音频前面一半静音处理,并简单注释了一下部分逻辑。

    完整代码:

    #include <stdio.h>
    #include <stdlib.h>    
    #include <stdint.h>    
    #include <time.h> 
    #include <iostream> 
    //采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解码
    #define DR_WAV_IMPLEMENTATION
    #include "dr_wav.h"
    
    auto const epoch = clock();
    static double now()
    {
        return  (clock() - epoch);
    };
    
    template <typename FN>
    static double bench(const FN &fn)
    {
        auto took = -now();
        return (fn(), took + now()) / 1000;
    }
    
    //写wav文件
    void wavWrite_int16(char* filename, int16_t* buffer, int sampleRate, uint32_t totalSampleCount) {
        drwav_data_format format;
        format.container = drwav_container_riff;     // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
        format.format = DR_WAVE_FORMAT_PCM;          // <-- Any of the DR_WAVE_FORMAT_* codes.
        format.channels = 1;
        format.sampleRate = sampleRate;
        format.bitsPerSample = 16;
        drwav* pWav = drwav_open_file_write(filename, &format); 
        if (pWav)
        {
            drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer);
            drwav_uninit(pWav);
        } 
    }
    //读取wav文件
    int16_t* wavRead_int16(char* filename, uint32_t* sampleRate, uint64_t    *totalSampleCount) {
    
        unsigned int channels;
        int16_t* buffer = drwav_open_and_read_file_s16(filename, &channels, sampleRate, totalSampleCount);
        if (buffer == NULL) {
            printf("读取wav文件失败.");
        }
        //仅仅处理单通道音频
        if (channels != 1)
        {
            drwav_free(buffer);
            buffer = NULL;
            *sampleRate = 0;
            *totalSampleCount = 0;
        }
        return buffer;
    }
    
    //分割路径函数
    void splitpath(const char* path, char* drv, char* dir, char* name, char* ext)
    {
        const char* end;
        const char* p;
        const char* s;
        if (path[0] && path[1] == ':') {
            if (drv) {
                *drv++ = *path++;
                *drv++ = *path++;
                *drv = '';
            }
        }
        else if (drv)
            *drv = '';
        for (end = path; *end && *end != ':';)
            end++;
        for (p = end; p > path && *--p != '\' && *p != '/';)
            if (*p == '.') {
                end = p;
                break;
            }
        if (ext)
            for (s = end; (*ext = *s++);)
                ext++;
        for (p = end; p > path;)
            if (*--p == '\' || *p == '/') {
                p++;
                break;
            }
        if (name) {
            for (s = p; s < end;)
                *name++ = *s++;
            *name = '';
        }
        if (dir) {
            for (s = path; s < p;)
                *dir++ = *s++;
            *dir = '';
        }
    }
    
    int main(int argc, char* argv[])
    {
        std::cout << "Audio Processing " << std::endl;
        std::cout << "博客:http://cpuimage.cnblogs.com/" << std::endl;
        std::cout << "支持解析单通道wav格式." << std::endl;
    
        if (argc < 2) return -1;
        char* in_file = argv[1];
    
        //音频采样率
        uint32_t sampleRate = 0;
        //总音频采样数
        uint64_t totalSampleCount = 0;
        int16_t* wavBuffer = NULL;
        double nLoadTime = bench([&]
        {
            wavBuffer = wavRead_int16(in_file, &sampleRate, &totalSampleCount);
        });
        std::cout << " 加载耗时: " << int(nLoadTime * 1000) << " 毫秒" << std::endl;
    
        //如果加载成功
        if (wavBuffer != NULL)
        {
            //将前面一般进行静音处理,直接置零即可
            for (uint64_t i = 0; i < totalSampleCount / 2; i++)
            {
                wavBuffer[i] = 0;
            }
        }
        //保存结果
        double nSaveTime = bench([&]
        {
            char drive[3];
            char dir[256];
            char fname[256];
            char ext[256];
            char out_file[1024];
            splitpath(in_file, drive, dir, fname, ext);
            sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext);
            wavWrite_int16(out_file, wavBuffer, sampleRate, totalSampleCount);
        });
        std::cout << " 保存耗时: " << int(nSaveTime * 1000) << " 毫秒" << std::endl;
        if (wavBuffer)
        {
            free(wavBuffer);
        }
        getchar();
        std::cout << "按任意键退出程序 
    " << std::endl;
        return 0;
    }

    示例具体流程为:

    加载wav(拖放wav文件到可执行文件上)->简单静音处理->保存wav

    并对 加载,保存 这2个环节都进行了耗时计算并输出。

      

    若有其他相关问题或者需求也可以邮件联系俺探讨。

    邮箱地址是: 
    gaozhihan@vip.qq.com

    若此博文能帮到您,欢迎扫码小额赞助。

    微信:  

     

    支付宝: 

  • 相关阅读:
    Running ASP.NET Applications in Debian and Ubuntu using XSP and Mono
    .net extjs 封装
    ext direct spring
    install ubuntu tweak on ubuntu lts 10.04,this software is created by zhouding
    redis cookbook
    aptana eclipse plugin install on sts
    ubuntu open folderpath on terminal
    ubuntu install pae for the 32bit system 4g limited issue
    EXT Designer 正式版延长使用脚本
    用 Vagrant 快速建立開發環境
  • 原文地址:https://www.cnblogs.com/cpuimage/p/8278451.html
Copyright © 2011-2022 走看看