简洁明了的插值音频重采样算法例子 (附完整C代码)

时间:2021-09-07 09:47:29

近一段时间在图像算法以及音频算法之间来回游走。

经常有一些需求,需要将音频进行采样转码处理。

现有的知名开源库,诸如: webrtc , sox等,

代码阅读起来实在闹心。

而音频重采样其实也就是插值算法。

与图像方面的插值算法没有太大的区别。

基于双线性插值的思路。

博主简单实现一个简洁的重采样算法,

用在对采样音质要求不高的情况下,也是够用了。

编解码库采用dr_wav

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

近期有点强迫症,纯c实现。

贴上完整代码:

#ifdef __cplusplus
extern "C" {
#endif

#define  _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解码
#define DR_WAV_IMPLEMENTATION
#include "dr_wav.h"
void resampler(char *in_file, char *out_file);

//写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 = ;
    format.sampleRate = (drwav_uint32) sampleRate;
    format.bitsPerSample = ;
    drwav *pWav = drwav_open_file_write(filename, &format);
    if (pWav) {
        drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer);
        drwav_uninit(pWav);
        if (samplesWritten != totalSampleCount) {
            fprintf(stderr, "ERROR\n");
            exit();
        }
    }
}
//读取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文件失败.");
    }
    //仅仅处理单通道音频
    ) {
        drwav_free(buffer);
        buffer = NULL;
        *sampleRate = ;
        *totalSampleCount = ;
    }
    return buffer;
}

//分割路径函数
void splitpath(const char *path, char *drv, char *dir, char *name, char *ext) {
    const char *end;
    const char *p;
    const char *s;
    ] && path[] == ':') {
        if (drv) {
            *drv++ = *path++;
            *drv++ = *path++;
            *drv = '\0';
        }
    } else if (drv)
        *drv = '\0';
    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 = '\0';
    }
    if (dir) {
        for (s = path; s < p;)
            *dir++ = *s++;
        *dir = '\0';
    }
}

void resampleData(const int16_t *sourceData, int32_t sampleRate, uint32_t srcSize, int16_t *destinationData,
                  int32_t newSampleRate) {
    if (sampleRate == newSampleRate) {
        memcpy(destinationData, sourceData, srcSize * sizeof(int16_t));
        return;
    }
    uint32_t last_pos = srcSize - ;
    uint32_t dstSize = (uint32_t) (srcSize * ((float) newSampleRate / sampleRate));
    ; idx < dstSize; idx++) {
        float index = ((float) idx * sampleRate) / (newSampleRate);
        uint32_t p1 = (uint32_t) index;
        float coef = index - p1;
        uint32_t p2 = (p1 == last_pos) ? last_pos : p1 + ;
        destinationData[idx] = (int16_t) ((1.0f - coef) * sourceData[p1] + coef * sourceData[p2]);
    }
}

void resampler(char *in_file, char *out_file) {
    //音频采样率
    uint32_t sampleRate = ;
    //总音频采样数
    uint64_t totalSampleCount = ;
    int16_t *data_in = wavRead_int16(in_file, &sampleRate, &totalSampleCount);
    int16_t *data_out = (int16_t *)  * sizeof(int16_t));
    //如果加载成功
    if (data_in != NULL && data_out != NULL) {
        resampleData(data_in, sampleRate, (uint32_t) totalSampleCount, data_out, sampleRate * );
        wavWrite_int16(out_file, data_out,sampleRate * , (uint32_t) totalSampleCount * );
        free(data_in);
        free(data_out);
    }
    else{
        if(data_in) free(data_in);
          if(data_out) free(data_out);
    }
}

int main(int argc, char *argv[]) {
    printf("Audio Processing\n");
    printf("博客:http://tntmonks.cnblogs.com/\n");
    printf("音频插值重采样\n");
     )
         ;

    ];
    ];
    ];
    ];
    ];
    ];
    splitpath(in_file, drive, dir, fname, ext);
    sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext);
    resampler(in_file, out_file);
    getchar();
    printf("按任意键退出程序 \n");
    ;
}

#ifdef __cplusplus
}
#endif

不多注释,代码比较简单,一看就明了。

示例具体流程为:

加载wav(拖放wav文件到可执行文件上)->重采样为原采样的2倍->保存wav

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

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

简洁明了的插值音频重采样算法例子 (附完整C代码)的更多相关文章

  1. 一种简单高效的音频降噪算法示例&lpar;附完整C代码&rpar;

    近期比较忙, 抽空出来5.1开源献礼. 但凡学习音频降噪算法的朋友,肯定看过一个算法. <<语音增强-理论与实践>> 中提及到基于对数的最小均方误差的降噪算法,也就是LogMM ...

  2. 基于傅里叶变换的音频重采样算法 &lpar;附完整c代码&rpar;

    前面有提到音频采样算法: WebRTC 音频采样算法 附完整C++示例代码 简洁明了的插值音频重采样算法例子 (附完整C代码) 近段时间有不少朋友给我写过邮件,说了一些他们使用的情况和问题. 坦白讲, ...

  3. 基于RNN的音频降噪算法 &lpar;附完整C代码&rpar;

    前几天无意间看到一个项目rnnoise. 项目地址: https://github.com/xiph/rnnoise 基于RNN的音频降噪算法. 采用的是 GRU/LSTM 模型. 阅读下训练代码,可 ...

  4. 音频降噪算法 附完整C代码

    降噪是音频图像算法中的必不可少的. 目的肯定是让图片或语音 更加自然平滑,简而言之,美化. 图像算法和音频算法 都有其共通点. 图像是偏向 空间 处理,例如图片中的某个区域. 图像很多时候是以二维数据 ...

  5. 音频自动增益 与 静音检测 算法 附完整C代码

    前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用于评估一定长度音频的音量强度, 而分析之后,很多类似的需求,肯定是做音频增益,提高音量诸如此类做法. ...

  6. 音频自动增益 与 静音检测 算法 附完整C代码【转】

    转自:https://www.cnblogs.com/cpuimage/p/8908551.html 前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用 ...

  7. 音频算法之小黄人变声 附完整C代码

    前面提及到<大话音频变声原理 附简单示例代码>与<声音变调算法PitchShift(模拟汤姆猫) 附完整C++算法实现代码> 都稍微讲过变声的原理和具体实现. 大家都知道,算法 ...

  8. 经典傅里叶算法小集合 附完整c代码

    前面写过关于傅里叶算法的应用例子. <基于傅里叶变换的音频重采样算法 (附完整c代码)> 当然也就是举个例子,主要是学习傅里叶变换. 这个重采样思路还有点瑕疵, 稍微改一下,就可以支持多通 ...

  9. 自动曝光修复算法 附完整C代码

    众所周知, 图像方面的3A算法有: AF自动对焦(Automatic Focus)自动对焦即调节摄像头焦距自动得到清晰的图像的过程 AE自动曝光(Automatic Exposure)自动曝光的是为了 ...

随机推荐

  1. 《CSS权威指南》基础复习&plus;查漏补缺

    前几天被朋友问到几个CSS问题,讲道理么,接触CSS是从大一开始的,也算有3年半了,总是觉得自己对css算是熟悉的了.然而还是被几个问题弄的"一脸懵逼"... 然后又是刚入职新公司 ...

  2. jsgen 搭建

    1,mongodb 2,redis  http://www.cnblogs.com/lxx/archive/2013/06/04/3116985.html http://blog.csdn.net/w ...

  3. C&plus;&plus;&colon; getline函数

    转自http://blog.sina.com.cn/s/blog_60263c1c0101ck25.html 学习C++的同学可能都会遇到一个getline()函数,譬如在C++premer中,标准s ...

  4. Leetcode 解题 Longest Substring without repeating charcater python

    原题: Given a string, find the length of the longest substring without repeating character For example ...

  5. button 自动刷新当前页面

    button请始终为按钮规定 type 属性.Internet Explorer 的默认类型是 "button",而其他浏览器中(包括 W3C 规范)的默认值是 "sub ...

  6. HDU 1054 Strategic Game &lpar;最小点覆盖&rpar;【二分图匹配】

    <题目链接> 题目大意:鲍勃喜欢玩电脑游戏,特别是战略游戏,但有时他无法找到解决方案,速度不够快,那么他很伤心.现在,他有以下的问题.他必须捍卫一个中世纪的城市,形成了树的道路.他把战士的 ...

  7. docker第一章:docker核心概念及centos6下安装

    Docker三大核心概念 镜像 容器 仓库 镜像 docker镜像类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统. 容器 1.容器是从镜像创建的应用运行实例,容器和 ...

  8. 【jQuery源码】DOM Ready

    一直以来,各种JS最佳实践都会告诉我们,将JS放在HTML的最后,即</body>之前,理由就是:JS会阻塞下载,而且,在JS中很有可能有对DOM的操作,放在HTML的最后,可以尽可能的保 ...

  9. C&plus;&plus;运行时动态类型

    RTTI 运行时类型识别(RTTI)的引入有三个作用: 配合typeid操作符的实现: 实现异常处理中catch的匹配过程: 实现动态类型转换dynamic_cast typeid操作符的实现 静态类 ...

  10. 利用 Python 分析微信好友性别和位置

    今天用到一个非常有意思的库——itchat,它已经完成了 wechat 的个人账号API接口,使爬取个人微信信息更加方便.  下载 爬取微信好友信息 这样就将你所有微信好友的信息都返回了,我们并不需要 ...