Matlab 音频格式转换(wav,ogg,flac,au,aiff,aif,aifc,mp3,m4a,mp4 互转)

Shaine ·
更新时间:2024-11-10
· 728 次阅读

欢迎转载,但请一定要给出原文链接,标注出处,支持原创! 谢谢~
https://blog.csdn.net/qq_29225913/article/details/105445028

目录1、目标及关键函数及其介绍1.1 读音频 audioread1.2 写音频audiowrite1.3 FFT 离散傅立叶变换的快速算法2、实现2.1 参数定义2.2 原始音频文件读取2.3 打印输入波形图像2.4 输出参数设置2.5 生成输出音频并转码2.6 输出音频文件读取2.7 打印输出波形图像3、运行图片3.1 例:.m4a 转 ogg3.2 例:.flac转 wav4、完整代码 1、目标及关键函数及其介绍

  在本文,有两个核心的函数需要掌握,方可实现功能,具体可以在命令行 help 查看,或者点击链接进入中文帮助中心。

1.1 读音频 audioread

audioread
语法:
  [y,Fs] = audioread(filename);   从名为 filename 的文件中读取数据,并返回样本数据 y 以及该数据的采样率 Fs。

  [y,Fs] = audioread(filename,samples);   读取文件中所选范围的音频样本,其中 samples 是 [start,finish] 格式的向量。

  [y,Fs] = audioread(___,dataType) ;   返回数据范围内与 dataType(‘native’ 或 ‘double’)对应的采样数据,可以包含先前语法中的任何输入参数。

1.2 写音频audiowrite

audiowrite
语法:
  audiowrite(filename,y,Fs);  以采样率 Fs 将音频数据矩阵 y 写入名为 filename 的文件。filename 输入还指定了输出文件格式。输出数据类型取决于音频数据 y 的输出文件格式和数据类型。

  audiowrite(filename,y,Fs,Name,Value) ;  使用一个或多个 Name,Value 对组参数指定的其他选项。

1.3 FFT 离散傅立叶变换的快速算法

FFT 的详细使用参考我的另一篇单独分析 FFT 的博文 Matlab 计算 FFT 的方法及幅值问题
截取部分关键内容在这里(此处 FFT 只用作绘制频谱图像进行分析,并不对音频格式转换有直接的影响,因此属于扩展阅读内容):
  N个采样点,经过FFT之后,就可以得到N个点的FFT结果。为了方便进行FFT运算,通常N取2的整数次方,但是这里直接取读取出来的样本数作为N。

FFT 计算公式如下:
在这里插入图片描述 Xk 长度与 N 相同。 根据奈科斯特定律,只有 f=fs/2 范围内的信号才是被采样到的有效信号,因此得到的频谱肯定是关于 N/2 对称的(就是只看前一半的波形就好)。 第k点的实际频率的计算为 f(k) = k * (fs / n) — — (横轴的频率范围为 :f = n * fs / N;) X[0] 为直流分量 ,幅值 = 模值(X[0]) / N X[k] 为个点的频率分量(除X[0]外),幅值 = 模值(X[k]) / (N / 2) 2、实现

备注:在本文发布后,对绘图部分有小部分修改,暂时没时间对本章的图片及内容进行修改,本章节的内容已经过验证,能够实现 音频格式转换 功能,因此也可以使用本章节的代码,第四章-完整代码 已做了更新。

2.1 参数定义 能够修改的参数,放在这个部分来定义。
在这里插入图片描述 代码片段:%% 参数定义 %%%%%%%%%%% % 音频文件参数 % source_FS = 16000; %原采样率(该值弃用,从文件读取) dest_FS = 8000; %目标采样率 bps = 16; %位深 (查看帮助文档可以获取支持的 bps) Tfile = 0; %声音片段的总时长s (0为不修改) % 音频通道 stereo = 'mono'; % 输出音频通道 'mono':单声道,'stereo':立体声 audio_ch = 'left'; % 立体声输入,单声道输出时,选用哪一通道? 'left','right','both' Left_channel_ratio = 0.5; % 左声道占比 % 文件 inputfile = ('connected_CN.mp3'); % 输入文件名 outputfile = [inputfile,'.wav']; % 输出文件名 AudioInfo = audioinfo(inputfile) % 打印输入音频文件的信息(不加分号) %播放设置 isplay = 1; % 0:播放原音频 1:播放生成音频 2.2 原始音频文件读取 读入原始音频,记得修改对应的文件名,带后缀。如果选择播放原音频,那么读取完源文件后,会从电脑喇叭播放声音。
在这里插入图片描述 代码片段:%% 原始音频文件读取 %%%%%%%%%%% [y_input,source_FS]=audioread(inputfile); % 将 WAV 文件转换成变量 fs_str = ['(Fs:',num2str(source_FS/1000),'KHz)']; % fs 的字符串,在图上显示文件 fs whos y_input % 打印y的信息 if isplay == 0 % 如果选择播放原音频 if source_FS < 192000 % 电脑小于 192K 采样率才能播放 sound(y_input,source_FS) % 调用可以播放声音的函数 sound() end end 2.3 打印输入波形图像 这一步将 audioread 读取出来的原音频数据,通过图像展示出来,原音频文件解码后,会得到一个列表,根据源文件的通道数n来区分,常用的通道是双通道,即2声道立体声,还有有其他的如:2.1声道、4声道、5.1声道、7.1声道等,对应的n会不同,此处我只对2声道的立体声做处理,有需要其他声道的,可以在此基础上,增加不同 n 值处理的方法。
在这里插入图片描述 代码片段%% 打印输入波形图像 %%%%%%%%%%% figure('Name','输入文件波形','NumberTitle','off'); [m,n] = size(y_input); % 计算文件的长度与声道数量 if n==1 % 单声道 y1 = y_input(:,1); % 提取声道数据 subplot(2,1,1); plot(y1); % 描绘左声道图像 title(['单声道原始波形 ',fs_str]); legend(fs_str); % 显示图例 subplot(2,1,2); Y_fft = fft(y1,4096); % 计算 FFT plot(abs(Y_fft)); % 描绘 FFT 图像 title('单声道原始波形频谱') else % 立体声 y1 = y_input(:,1); % 提取左声道数据 y2 = y_input(:,2); % 提取右声道数据 subplot(2,2,1); plot(y1); % 描绘左声道图像 title(['左声道原始波形 ',fs_str]); legend(fs_str); % 显示图例 subplot(2,2,2); plot(y2); % 描绘右声道图像 title(['右声道原始波形 ',fs_str]); legend(fs_str); % 显示图例 subplot(2,2,3); Y_fft1 = fft(y1,4096); % 左声道 FFT 计算 plot(abs(Y_fft1)); % 描绘左声道 FFT 图像 title('左声道原始波形频谱') subplot(2,2,4); Y_fft2 = fft(y2,4096); % 右声道 FFT 计算 plot(abs(Y_fft2)); % 描绘右声道 FFT 图像 title('右声道原始波形频谱') end 2.4 输出参数设置 这一个步骤是根据 2.1 设置的参数来去对读取出来的声道列表进行计算,可以根据需求来这里增加对音频序列的操作,但是本文的目标是转码,不做音频处理,因此,此处不对音频数据进行过多的处理。
在这里插入图片描述- 代码片段:%% 输出参数设置 %%%%%%%%%%% if strcmp(stereo,'mono') % 输出选项为单声道 if n == 1 % 如果输入文件是单声道文件 y_ratio = y1; % 那么输出文件的数据与输入文件的数据一致 else % 如果输入是立体声文件 if strcmp(audio_ch,'left') % 输出通道选择 左声道 y_ratio = y1; % 将左声道的数据作为输出数据 elseif strcmp(audio_ch,'right') % 输出通道选择 右声道 y_ratio = y2; % 将右声道的数据作为输出数据 else % 输出通道选择其他选项(both) y_ratio = y1*Left_channel_ratio + y2*(1-Left_channel_ratio); % 就将左声道数据与右声道数据,按照设定的比例来混合。 end end else % 如果输出选项为立体声 if n == 1 % 输入文件是单声道 y_ratio(:,1) = y1; % 那么左右声道都用输入的数据 y_ratio(:,2) = y1; else % 输入文件是立体声 y_ratio = y_input; % 那么输出文件的数据与输入文件的数据一致 end end 2.5 生成输出音频并转码 这一步是本文的关键步骤,转码的核心就是调用 audiowrite() ,也是需要去学习使用的函数。
在这里插入图片描述- 代码片段:%% 生成输出音频并转码 %%%%%%%%%%% y_out = resample(y_ratio,dest_FS,source_FS); % 对即将输出的数据,进行重采样到设定的采样率 audiowrite(outputfile,y_out,dest_FS,'BitsPerSample',bps); % 将输出数据存储为音频文件。 2.6 输出音频文件读取 这一步将刚才生成的音频文件再重新读入进来,用于检查格式转换后的效果。如果选择播放生成音频,那么读取完源文件后,会从电脑喇叭播放声音。
在这里插入图片描述 代码片段:%% 输出音频文件读取 %%%%%%%%%%% figure('Name','输出文件波形','NumberTitle','off'); % 打开第2个figure [y_output,dest_FS]=audioread(outputfile); % 将上一步生成的文件读取出来保存为变量 fs_str = ['(Fs:',num2str(dest_FS/1000),'KHz)']; % 采样率字符串 if isplay == 1 % 如果选择播放生成音频 if dest_FS < 192000 % 电脑小于 192K 采样率才能播放 sound(y_output,dest_FS) % 调用可以播放声音的函数 sound() end end 2.7 打印输出波形图像 这一步将 audioread 读取出来的转码后的音频数据,通过图像展示出来,操作方式与原文件的读取并打印波形类似。
在这里插入图片描述 代码片段:%% 打印输出波形图像 (跟打印输入波形图像类似,由于后续复用性较低,就不单独编写函数了) %%%%%%%%%%% [m,n] = size(y_output); % 计算文件的长度与声道数量 if n==1 % 单声道 y1 = y_output(:,1); % 提取声道数据 subplot(2,1,1); plot(y1); % 描绘左声道图像 title(['单声道生成波形 ',fs_str]); legend(fs_str); % 显示图例 subplot(2,1,2); Y_fft = fft(y1,4096); % 计算 FFT plot(abs(Y_fft)); % 描绘 FFT 图像 title('单声道生成波形频谱'); else %立体声 y1 = y_output(:,1); % 提取左声道数据 y2 = y_output(:,2); % 提取右声道数据 subplot(2,2,1); plot(y1); % 描绘左声道图像 title(['左声道生成波形 ',fs_str]); legend(fs_str); % 显示图例 subplot(2,2,2); plot(y2); % 描绘右声道图像 title(['右声道生成波形 ',fs_str]); legend(fs_str); % 显示图例 subplot(2,2,3); Y_fft1 = fft(y1,4096); % 左声道 FFT 计算 plot(abs(Y_fft1)); % 描绘左声道 FFT 图像 title('左声道生成波形频谱') subplot(2,2,4); Y_fft2 = fft(y2,4096); % 右声道 FFT 计算 plot(abs(Y_fft2)); % 描绘右声道 FFT 图像 title('右声道生成波形频谱') end 3、运行图片

先准备两首歌,用于测试。分别将 .m4a 转成 .ogg,将 .flac 转成 .wav。
在这里插入图片描述

3.1 例:.m4a 转 ogg

“萨克斯 - 莫斯科郊外的晚上 - 纯音乐.m4a” 转 .ogg,且将44.1KHz 采样率转为 48KHz采样率。
  由于上述代码中,是按照 wav 的格式来输出,audiowrite 中的 name-value 键值对对 ogg 无效,因此修改一下 audiowrite 函数的 name-value 键值对,按照帮助文档提供的设置,可以选择以下选项:
在这里插入图片描述因此修改一下 audiowrite 为:

audiowrite(outputfile,y_out,dest_FS,'Quality',100); % 将输出数据存储为音频文件。

同时修改 inputfile 与 outputfile。
运行程序后,生成下面文件在这里插入图片描述
在这里插入图片描述

3.2 例:.flac转 wav

按照老方法,修改一下 audiowrite 函数的 name-value 键值对,选用bps参数。
在这里插入图片描述
在这里插入图片描述
运行代码,
同样也生成了“张国荣-沉默是金.flac.wav”文件,显示区间显示,有需要可以通过这个地方来设置在这里插入图片描述
在这里插入图片描述

4、完整代码 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 功能:音频格式转换(任意格式互转) % % 作者:Mr-Ma Technology(马健维) % % 时间:2020.04.09 % % 转载请注明出处 % % https://blog.csdn.net/qq_29225913/article/details/105445028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 支持的转换格式 %%%%%%%%%%% % |-----------------------------------------------------| % | 格式 | 输入 | 输出 | % |-----------------------------------------------------| % |WAVE (.wav) | 支持 | 支持 | % |OGG (.ogg) | 支持 | 支持 | % |FLAC (.flac) | 支持 | 支持 | % |AU (.au) | 支持 | 不支持 | % |AIFF(.aiff/.aif) | 支持 | 不支持 | % |AIFC (.aifc) | 支持 | 不支持 | % |MP3 (.mp3) (注意电脑版本) | 支持 | 不支持 | % |MPEG-4 AAC(.m4a/.mp4)(注意电脑版本) | 支持 | 支持 | % |-----------------------------------------------------| % 更多详细信息,请参考 Matlab 相关描述(通道数、比特率、位深) % audioread :https://ww2.mathworks.cn/help/matlab/ref/audioread.html % audiowrite :https://ww2.mathworks.cn/help/matlab/ref/audiowrite.html?ue&s_tid=gn_loc_dropp %% 清空内存里的变量 %%%%%%%%%%% clear; close all; clc; %% 参数定义 %%%%%%%%%%% % 音频文件参数 % source_FS = 16000; %原采样率(该值弃用,从文件读取) dest_FS = 48000; % 目标采样率 bps = 16; % 位深 -audiowrite 参数(适用于输出 .wav/.flac 文件) qlt = 80; % Quality -audiowrite 参数(适用于输出 .ogg 文件) br = 0; % BitRate -audiowrite 参数(适用于输出 .m4a/.mp4 文件) % Tfile = 0; % 声音片段的总时长s (0为不修改) 暂时没用这个参数 % 音频通道 stereo = 'stereo'; % 输出音频通道 'mono':单声道,'stereo':立体声 audio_ch = 'left'; % 立体声输入,单声道输出时,选用哪一通道? 'left','right','both' Left_channel_ratio = 0.5; % 左声道占比 % 文件 inputfile = ('张国荣-沉默是金.flac'); % 输入文件名 outputfile = [inputfile,'.wav']; % 输出文件名 AudioInfo = audioinfo(inputfile) % 打印输入音频文件的信息(不加分号) %播放设置 isplay = 1; % 0:播放原音频 1:播放生成音频 % 绘图 isdraw = 1; % 1:打开绘图, 0:关闭绘图, 计算 FFT 需要消耗时间 t_axis = [-1 1]; % 时域图显示区域(纵坐标),按实际来改 f_axis = [0 20000 0 0.002]; % 频域图显示区域,按实际来改 %% 原始音频文件读取 %%%%%%%%%%% [y_input,source_FS]=audioread(inputfile); % 将 WAV 文件转换成变量 fs_str = ['(Fs:',num2str(source_FS/1000),'KHz)']; % fs 的字符串,在图上显示文件 fs whos y_input % 打印y的信息 if isplay == 0 % 如果选择播放原音频 if source_FS < 192000 % 电脑小于 192K 采样率才能播放 sound(y_input,source_FS) % 调用可以播放声音的函数 sound() end end %% 打印输入波形图像 %%%%%%%%%%% if isdraw == 1 figure('Name','输入文件波形','NumberTitle','off'); [N,n] = size(y_input); % 计算文件的长度与声道数量 if n==1 % 单声道 y1 = y_input(:,1); % 提取声道数据 subplot(2,1,1); plot(y1); % 描绘左声道图像 axis([0 N t_axis]); % 根据实际情况,限制可显示区间 xlabel('采样点');ylabel('幅度'); title(['单声道原始波形 ',fs_str]); subplot(2,1,2); NFFT = source_FS * floor(N / source_FS); % FFT 点数取 fs 的倍数 Y_fft = abs(fft(y1,NFFT)); % 左声道 FFT 计算 A_FFT1 = Y_fft * 2 / NFFT; % 转换为幅值 A_FFT1(1) = 0; % 忽略直流分量的影响 f = (0:(NFFT/2)) * source_FS / NFFT; % 频率范围,横坐标(半边谱) plot(f ,A_FFT1(1:NFFT/2 +1)); % 描绘 FFT 图像 axis(f_axis); % 根据实际情况,限制可显示区间 xlabel('频率/Hz');ylabel('振幅'); title('单声道原始波形频谱') else % 立体声 y1 = y_input(:,1); % 提取左声道数据 y2 = y_input(:,2); % 提取右声道数据 subplot(2,2,1); plot(y1); % 描绘左声道图像 axis([0 N t_axis]); % 根据实际情况,限制可显示区间 xlabel('采样点');ylabel('幅度'); title(['左声道原始波形 ',fs_str]); subplot(2,2,2); plot(y2); % 描绘右声道图像 axis([0 N t_axis]); % 根据实际情况,限制可显示区间 xlabel('采样点');ylabel('幅度'); title(['右声道原始波形 ',fs_str]); subplot(2,2,3); NFFT = source_FS * floor(N / source_FS); % FFT 点数取 fs 的倍数 Y_fft1 = abs(fft(y1,NFFT)); % 左声道 FFT 计算 A_FFT1 = Y_fft1 * 2 / NFFT; % 转换为幅值 A_FFT1(1) = 0; % 忽略直流分量的影响 f = (0:(NFFT/2)) * source_FS / NFFT; % 频率范围,横坐标(半边谱) plot(f ,A_FFT1(1:NFFT/2 +1)); % 描绘 FFT 图像 axis(f_axis); % 根据实际情况,限制可显示区间 xlabel('频率/Hz');ylabel('振幅'); title('左声道原始波形频谱') subplot(2,2,4); NFFT = source_FS * floor(N / source_FS); % FFT 点数取 fs 的倍数 Y_fft2 = abs(fft(y2,NFFT)); % 左声道 FFT 计算 A_FFT2 = Y_fft2 * 2 / NFFT; % 转换为幅值 A_FFT2(1) = 0; % 忽略直流分量的影响 f = (0:(NFFT/2)) * source_FS / NFFT; % 频率范围,横坐标(半边谱) plot(f ,A_FFT2(1:NFFT/2 +1)); % 描绘 FFT 图像 axis(f_axis); % 根据实际情况,限制可显示区间 xlabel('频率/Hz');ylabel('振幅'); title('右声道原始波形频谱') end end %% 输出参数设置 %%%%%%%%%%% if strcmp(stereo,'mono') % 输出选项为单声道 if n == 1 % 如果输入文件是单声道文件 y_ratio = y1; % 那么输出文件的数据与输入文件的数据一致 else % 如果输入是立体声文件 if strcmp(audio_ch,'left') % 输出通道选择 左声道 y_ratio = y1; % 将左声道的数据作为输出数据 elseif strcmp(audio_ch,'right') % 输出通道选择 右声道 y_ratio = y2; % 将右声道的数据作为输出数据 else % 输出通道选择其他选项(both) y_ratio = y1*Left_channel_ratio + y2*(1-Left_channel_ratio); % 就将左声道数据与右声道数据,按照设定的比例来混合。 end end else % 如果输出选项为立体声 if n == 1 % 输入文件是单声道 y_ratio(:,1) = y1; % 那么左右声道都用输入的数据 y_ratio(:,2) = y1; else % 输入文件是立体声 y_ratio = y_input; % 那么输出文件的数据与输入文件的数据一致 end end %% 生成输出音频并转码 %%%%%%%%%%% y_out = resample(y_ratio,dest_FS,source_FS); % 对即将输出的数据,进行重采样到设定的采样率 audiowrite(outputfile,y_out,dest_FS,'BitsPerSample',bps); % 将输出数据存储为音频文件。 %audiowrite(outputfile,y_out,dest_FS,'Quality',qlt); % 将输出数据存储为音频文件。 %% 输出音频文件读取 %%%%%%%%%%% [y_output,dest_FS]=audioread(outputfile); % 将上一步生成的文件读取出来保存为变量 fs_str = ['(Fs:',num2str(dest_FS/1000),'KHz)']; % 采样率字符串 if isplay == 1 % 如果选择播放生成音频 if dest_FS < 192000 % 电脑小于 192K 采样率才能播放 sound(y_output,dest_FS) % 调用可以播放声音的函数 sound() end end %% 打印输出波形图像 (跟打印输入波形图像类似,由于后续复用性较低,就不单独编写函数了) %%%%%%%%%%% if isdraw == 1 figure('Name','输出文件波形','NumberTitle','off'); % 打开第2个figure [N,n] = size(y_output); % 计算文件的长度与声道数量 if n==1 % 单声道 y1 = y_output(:,1); % 提取声道数据 subplot(2,1,1); plot(y1); % 描绘左声道图像 axis([0 N t_axis]); % 根据实际情况,限制可显示区间 xlabel('采样点');ylabel('幅度'); title(['单声道生成波形 ',fs_str]); subplot(2,1,2); NFFT = dest_FS * floor(N / dest_FS); % FFT 点数取 fs 的倍数 Y_fft = abs(fft(y1,NFFT)); % 左声道 FFT 计算 A_FFT1 = Y_fft * 2 / NFFT; % 转换为幅值 A_FFT1(1) = 0; % 忽略直流分量的影响 f = (0:(NFFT/2)) * dest_FS / NFFT; % 频率范围,横坐标(半边谱) plot(f ,A_FFT1(1:NFFT/2 +1)); % 描绘 FFT 图像 axis(f_axis); % 根据实际情况,限制可显示区间 xlabel('频率/Hz');ylabel('振幅'); title('单声道生成波形频谱'); else % 立体声 y1 = y_output(:,1); % 提取左声道数据 y2 = y_output(:,2); % 提取右声道数据 subplot(2,2,1); plot(y1); % 描绘左声道图像 axis([0 N t_axis]); % 根据实际情况,限制可显示区间 xlabel('采样点');ylabel('幅度'); title(['左声道生成波形 ',fs_str]); subplot(2,2,2); plot(y2); % 描绘右声道图像 axis([0 N t_axis]); % 根据实际情况,限制可显示区间 xlabel('采样点');ylabel('幅度'); title(['右声道生成波形 ',fs_str]); subplot(2,2,3); NFFT = dest_FS * floor(N / dest_FS); % FFT 点数取 fs 的倍数 Y_fft1 = abs(fft(y1,NFFT)); % 左声道 FFT 计算 A_FFT1 = Y_fft1 * 2 / NFFT; % 转换为幅值 A_FFT1(1) = 0; % 忽略直流分量的影响 f = (0:(NFFT/2)) * dest_FS / NFFT; % 频率范围,横坐标(半边谱) plot(f ,A_FFT1(1:NFFT/2 +1)); % 描绘 FFT 图像 axis(f_axis); % 根据实际情况,限制可显示区间 xlabel('频率/Hz');ylabel('振幅'); title('左声道生成波形频谱') subplot(2,2,4); NFFT = dest_FS * floor(N / dest_FS); % FFT 点数取 fs 的倍数 Y_fft2 = abs(fft(y2,NFFT)); % 左声道 FFT 计算 A_FFT2 = Y_fft2 * 2 / NFFT; % 转换为幅值 A_FFT2(1) = 0; % 忽略直流分量的影响 f = (0:(NFFT/2)) * dest_FS / NFFT; % 频率范围,横坐标(半边谱) plot(f ,A_FFT2(1:NFFT/2 +1)); % 描绘 FFT 图像 axis(f_axis); % 根据实际情况,限制可显示区间 xlabel('频率/Hz');ylabel('振幅'); title('右声道生成波形频谱') end end
作者:Mr-Ma Technology



flac 音频格式转换 mp4 m4a mp mp3 matlab

需要 登录 后方可回复, 如果你还没有账号请 注册新账号