资讯详情

基于C语言实现PCM音频流或音频文件重采样(48K到16K)

基于C语言实现PCM音频流或音频文件重采样(48K到16K)

由于云厂商SDK所需的音频采样率为16K的,而SFU回调的流量是48K因此,我们仍然需要正确的PCM采样处理音频数据。

转换的原理比较简单,从48KHz降到16KHz,下降3倍,即同时在单位范围内,48KHz采样3点,16点KHz只采样了一个点,即从48KHz的 PCM流中每读取三个数据,就要根据这三个数据计算一个数据,对应16个数据KHz PCM流中的数据。

重采样

从三个数据中获取一个数据的方法有很多,如取平均值、取样点等:

(1). 取平均值:

取3点,加后求平均值。这种效果不好,转换后会有噪音。这是因为转换成16kHz根据奈奎斯特采样定律,当采样频率fs.max大于信号中最高频率fmax的2倍时(fs.max>2fmax),,根据这些抽样值,原始信号可以完全恢复,因此可以转换为16kHz采样率不能有8K上述频率。对于三点的平均值,有可能存在8khz上述频段,所以效果不好。

(2). 取特征点:

取三个采样点中固定位置的一个点,如固定三个点中的第一个点,然后合并成一个新的数据流。这种效果,测量相对清晰,虽然有可能失去一些声音细节,但整体仍能满足语音识别。

综上所述,我们采用了第一个特征点的方法。

具体实现如下

C语言实现

处理pcm流:

/** PCM frame. */ typedef struct {     uint8_t        *buf;     int             len;     int             sample_rate;     int             sample_depth; } pcm_frame_t;  void pcm_resample_16k(const pcm_frame_t *frame_in, pcm_frame_t *frame_out) {     int i;     int magnification = frame_in->sample_rate / 16000;      frame_out->buf = frame_in->buf;     frame_out->len = frame_in->len / magnification;     frame_out->sample_rate = 16000;     frame_out->sample_depth = frame_in->sample_depth;       for (i = 0; i < frame_out->len; i  ) {         frame_out->buf[i] = frame_in->buf[i*magnification]; /* 取第一个特征值 */     }       /* 如果按照16bit来 */ //     for (i = 0; i < len / 3; i  ) { //         if (0 == (i % 2)) { //             buf[i] = buf[i*3 2]; //         } else { //             buf[i] = buf[i*3]; //         } //     } } 

处理pcm文件:

void pcm_resample(void) {     short read_buf = 0;     int size = 0;     int cnt = 0;      FILE *fp = fopen("in.pcm", "rb ");     FILE *fp_out = fopen("out.pcm", "wb ");      while (!feof(fp)) {         size = fread(&read_buf, 2, 1, fp); // 16bit,所以你需要一次读两个字节         if (size > 0) {             cnt  ;             if (cnt == 3) { //每采集3个点                 cnt = 0; // 重置计数                 fwrite(&read_buf, 2, 1, fp_out); ///写入数据             }         }     }      fclose(fp);     fclose(fp_out); } 

标签: p48k5s圆形连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台