目录
一、API简介
二、实验
1. matlab
2. C语言
一、API简介
链接如下:
读取音频文件 - MATLAB audioread- MathWorks 中国
也可以浏览最新的英文版API说明:
简单说明如下:
1. 读取wav格式的文件,会自动跳过44个字节的文件头
2. audioread()使用来代替wavread()的,新版本的Matlab已经不再支持wavread();所以在使用的时候需要注意返回的参数:wavread()返回三个参数,而audioread()只返回两个参数,少了“位深度”这个信息。
3. audioread()读出来的音频数据流有“归一化”操作,默认是除以32768归一化每个样本点,之后用double类型空间进行存储。
例如:假设对于一个音频文件,每个样本点都是用16位来量化而得到的数字信号,一般是用short类型进行存储,用audioread()读出来后,每个样本点其实都做了归一化, 比如对于数值为-417的样本点, 读出来的值是-417/(32768.0)=0.012725830078125,约为0.01273。
4. 如果不希望归一化,则第二个参数可设置为’native’,调用形式为:
[x,fs] = audioread('input.wav', ‘native’); |
二、实验
假设音频源来自一个音频文件,采样率是8KHz,16bit的单声道数据。
1. matlab
[x,fs] = audioread('input.wav'); %自动跳过44个字节的文件头
fprintf('fs:%d\n', fs)
fprintf('row:%d\n', size(x, 1))%矩阵的行数
fprintf('col:%d\n', size(x, 2))%矩阵的列数
len=256;
noise_mean = zeros(len,1);
j=1;
noise_mean = x(j:j+len-1); %读取前面256个样本点
audiowrite('outFile.wav', x, fs);
noise_mean这个矩阵的值如下:
假设不进行归一化操作:
[x,fs] = audioread('input.wav', 'native'); %自动跳过44个字节的文件头
fprintf('len(x):%d\n', size(x))%28019
len=256
noise_mean = zeros(len,1);
j=1;
noise_mean = x(j:j+len-1) %读取前面256个样本点
audiowrite('outFile.wav', x, fs);
noise_mean这个矩阵的值如下:
注:
(1) 这就是最原始的音频数据,可以手动验算该API的“归一化数值”操作。
(2)可以直接用C语言读出,进行对比。
2. C语言
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int i;
int count=0;
FILE *fpin = fopen("input.wav", "rb");
if (fpin == NULL) {
printf("input data read fail\n");
return 0;
}
fseek(fpin, 0, SEEK_END);
long inputdata_length = ftell(fpin);
//偏移,跳过文件头
inputdata_length = inputdata_length - 44;
inputdata_length /= 2;
printf("input_file_len:% ld\n", inputdata_length);
rewind(fpin);
short* x = (short*)calloc(inputdata_length, sizeof(short));
//偏移,跳过文件头
fseek(fpin, 44, SEEK_SET);
count = fread(x, sizeof(short), inputdata_length, fpin);
printf("count:% d\n", count);
for (i = 0; i < 256; i++) {
printf("x_tmp[%d]=%d\n", i, x[i]);
}
return 0;
}
打印如下:
input_file_len: 28019 count: 28019 x[0]=-417 x[1]=-14 x[2]=-17 x[3]=-112 x[4]=1319 x[5]=1512 x[6]=-987 x[7]=-1046 x[8]=550 x[9]=342 x[10]=212 x[11]=-182 x[12]=192 x[13]=175 x[14]=-1268 x[15]=-952 x[16]=-786 x[17]=-759 x[18]=473 x[19]=950 x[20]=603 .................................................... |
实际算法开发,为防止计算过程中,数据过大,一般也会做归一化操作。注意,读取实际音频数据长度,以及读出实际音频数据之前,都要先跨过文件头(如果是PCM格式,就不需要)。
完整示例代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int i;
int count=0;
FILE *fpin = fopen("input.wav", "rb");
if (fpin == NULL) {
printf("input data read fail\n");
return 0;
}
FILE *fpout = fopen("output.wav", "wb");
if (fpin == NULL) {
printf("open output file fail\n");
return 0;
}
fseek(fpin, 0, SEEK_END);
long inputdata_length = ftell(fpin);
//偏移,跳过文件头
inputdata_length = inputdata_length - 44;
inputdata_length /= 2;
printf("input_file_len:% ld\n", inputdata_length);
rewind(fpin);
short* x = (short*)calloc(inputdata_length, sizeof(short));
//偏移,跳过文件头
fseek(fpin, 44, SEEK_SET);
count = fread(x, sizeof(short), inputdata_length, fpin);
printf("count:% d\n", count);
// for (i = 0; i < 256; i++) {
// printf("x[%d]=%d\n", i, x[i]);
// }
#if 0 /* 无数值归一化操作 */
fwrite(x, sizeof(short), inputdata_length, fpout);
free(x);
fclose(fpin);
fclose(fpout);
#else /* 进行数值归一化操作 */
float* x_in = (float*)calloc(inputdata_length, sizeof(float));
short* x_out = (short*)calloc(inputdata_length, sizeof(short));
//输入
for(i=0; i<inputdata_length; i++) {
x_in[i]=x[i]/32768.0;
}
//处理
//输出
for(i=0; i<inputdata_length; i++) {
x_out[i]=(short)(x_in[i]*32768.0);
}
fwrite(x_out, sizeof(short), inputdata_length, fpout);
free(x);
free(x_in);
free(x_out);
fclose(fpin);
fclose(fpout);
#endif
return 0;
}
输出的音频文件和源文件一致: