Matlab 生成任意波形wav文件

1、背景

  測試DAC/功放的性能指標的時候,常需要 1KHz 的波形來分析,主要測試參數有輸出幅度,相移、失真度、頻響曲線、信噪比(SNR)等常用的手段來評估設備的好壞程度,測試儀器一般選用AG,粗略測試也可以使用稍微好一點的示波器。
  曾經一開始接觸這部分調試的時候,從網上找了些音頻文件,發現怎麼測參數都不對,後來從別人那裏考來了一份常用的1K文件,才得出像樣點的結果,由於此文件需要的精度高,而網上下載的文件質量參差不齊,而且沒有所需要的各種格式,比如各採樣率、位深、時常、特殊幅值、任意頻率等的參數,所以乾脆自己寫一個程序來生成,所有內部的波形都能夠看得出來,會比較放心地拿來測試。
  對音頻這塊比較專業的軟件有 Adobe Audition 這一款,很適合音頻錄製、編輯和混合,但是作爲程序員,還是喜歡通過用代碼來生成想要的內容,因此選擇使用 Matlab,Matlab 在信號處理上,也可以說是老大了,各種處理的算法基本都是有對應的函數庫,就算有些沒有,編寫起來也很容易,包含了衆多科學/工程領域的包及仿真工具。當然,對於本文這種比較小的需求,雖說有種牛刀殺雞的感覺,但是未嘗不是一個學習的過程,再不用一下,在學校裏學的就得忘光了。

2、實現

  本文是該分欄的第一篇文章,上述廢話多了點哈,後面的代碼都儘量保證代碼的註釋多點,也歡迎大家來指正錯誤一起學習哦,現在開始來實現吧~~

2.1 參數定義

可以自由設置的參數如下,同學們可以根據需要來修改想要的參數,然後運行一下來生成wav文件。
在這裏插入圖片描述
代碼片段(csdn 的 markdown 貌似對 m 文件的支持不太好,沒有高亮 - -。):

 %%  參數定義  %%%%%%%%%%%
fs = 96000;             % 採樣頻率
bps = 16;               % 位深 bit
Tfile = 60;             % 聲音片段的總時長,單位s
vol = 0;                % 聲音片段的音量 0db
sinewave1_fs = 1000;    % 左聲道頻率,單位Hz
sinewave2_fs = 1000;    % 右聲道頻率
stereo = 1;             % 0:單聲道,1:立體聲
filename = ('96000_16b_1KHz_60s_stereo_gen_by_Matlab.wav'); %輸出文件名稱(自己定義,後綴是.wav)

2.2 生成時間序列

生成一個時間序列,序列裏每一個點對應一個採樣點。
在這裏插入圖片描述

代碼片段:

%% 生成時間序列
Df = 1;                 % 頻率間隔,默認1
T = 1/fs;               % 採樣週期
N = fs/Df;              % 序列點數
time = Tfile*(N-1)*T;   % 文件總時長
t = 0:T:time;           % 生成每一個採樣點對應的時間序列

2.3 生成左右聲道波形

調用正弦函數來生成波形,參數爲 2.1 定義的參數,照葫蘆畫瓢,可以將 sin 函數 替換成其他函數,生成各種你想要的波形。
在這裏插入圖片描述
代碼片段:

%% 生成左右聲道波形
y1 = sin(2*pi*sinewave1_fs*t)*(db2mag(vol));    % 生成第一個聲音片段,注意需要用db2mag()函數把dB轉換成magnitude。
y2 = sin(2*pi*sinewave2_fs*t)*(db2mag(vol));    % 生成第二個聲音片段,若需不同賦值,可以在參數定義中增加一個 vol_2 來控制第二段的賦值。 
if stereo == 0                                  % 選擇單聲道輸出
        y = y1';                                %   輸出的 y 只使用 y1, 左聲道(單聲道)
        y2 = 0*sin(2*pi*sinewave2_fs*t);        %   令 y2 爲 0
else                                            % 選擇立體聲輸出
        y = [y1',y2'];                          %   合成立體聲
end

2.4 播放生成的波形

生成的波形文件可以通過 sound() 函數來播放。
在這裏插入圖片描述

代碼片段:

%% 通過電腦音頻輸出口,播放生成的波形
whos y              % 命令行打印 y 的信息
if fs < 192000      % 電腦不能支持大於 192K 的聲音輸出,但是可以正常生成。
    sound(y,fs)     % 可以播放聲音的函數 sound()
end

2.5 描繪波形圖像

這部分比較簡單,關鍵點是要順便寫一下驗錯的流程,直接上圖看註釋。
在這裏插入圖片描述
代碼片段:

%% 描繪波形圖像
if stereo == 0              % 如果選擇單聲道輸出 
    subplot(2,1,1);         %     選中第一個圖片位置
    plot(t,y1);             %     描繪左聲道生成波形
    title('左聲道生成波形'); 
    subplot(2,1,2);         %     選中第二個圖片位置
    plot(y1(1:200));        %     打印左聲道 1~200的值,如果下面讀取成功,此值會被覆蓋
    title('左聲道讀取失敗'); %     若後面讀取正常,該值會被覆蓋(即讀取成功的話,將看不到這句話,用於驗錯)

else                        % 如果選擇立體聲輸出 
    subplot(4,1,1);         %     選中第一個圖片位置
    plot(t,y1);             %     描繪左聲道生成波形
    title('左聲道生成波形');
    subplot(4,1,2);         %     選中第二個圖片位置
    plot(t,y2);             %     描繪右聲道生成波形
    title('右聲道生成波形');
    subplot(4,1,3);         %     選中第三個圖片位置
    plot(y1(1:200))         %     打印左聲道 1~200的值,如果下面讀取成功,此值會被覆蓋
    title('左聲道讀取失敗'); %     若後面讀取正常,該值會被覆蓋(即讀取成功的話,將看不到這句話,用於驗錯)
    subplot(4,1,4);         %     選中第四個圖片位置
    plot(y2(1:200))         %     打印右聲道 1~200的值,如果下面讀取成功,此值會被覆蓋
    title('右聲道讀取失敗'); %     若後面讀取正常,該值會被覆蓋(即讀取成功的話,將看不到這句話,用於驗錯)
end

2.6 寫入 .wav文件

在這裏插入圖片描述
代碼片段:

%% 寫入文件
audiowrite(filename,y,fs,'BitsPerSample',bps);  % 存儲.wav音頻文件,文件名在參數定義裏設置
AudioInfo = audioinfo(filename)                 % 這裏不用加分號,可以順便在命令窗口看看寫入文件的打印信息

2.7 讀取生成的 wav 文件進行,並描繪波形

讀取波形文件,若讀取失敗,則無法打印正確的波形,此時需要檢查是否生成的參數設置有誤
在這裏插入圖片描述
代碼片段:

%%   讀取剛纔生成的 wav 文件進行,並描繪波形
[y_read,FS]=audioread(filename);    % 將 WAV 文件轉換成變量
whos y_r                            % 打印一下 y_read 信息
if stereo == 0                      % 如果選擇單聲道 
    y_read1 = y_read(:,1);          %	提取聲道
    subplot(2,1,2);                 %	選中第二個圖片位置
    plot(t,y_read1);                %   描繪左聲道讀取波形,覆蓋上一步驟的驗錯內容
    title('左聲道讀取波形');
else                                % 如果選擇立體聲 
    y_read1 = y_read(:,1);          %	提取左聲道
    subplot(4,1,3);                 %   選中第三個圖片位置
    plot(t,y_read1);                %   描繪左聲道讀取波形,覆蓋上一步驟的驗錯內容
    title('左聲道讀取波形');
    y_read2 = y_read(:,2);          %	提取右聲道
    subplot(4,1,4);                 %   選中第四個圖片位置
    plot(t,y_read2);                %   描繪右聲道讀取波形,覆蓋上一步驟的驗錯內容
    title('右聲道讀取波形');
end

OK ,到這裏功能已經實現了,第一個 Matlab 分享代碼註釋寫的算是較爲詳細了,方便自己也方便大家,學習的路上共勉。

3、完整代碼

代碼比較簡單,不需要其他配置,直接複製到Matlab上即可成功運行,各位有需要用到的可以試試哦。

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   功能:生成任意正弦波形文件(單聲道 or 立體聲) % 
%   作者:Mr-Ma Technology(馬健維)             %
%   時間:2019.08.31                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

clear; 
close all; 
clc;
 %%  參數定義  %%%%%%%%%%%
fs = 96000;             % 採樣頻率
bps = 16;               % 位深 bit
Tfile = 60;             % 聲音片段的總時長,單位s
vol = 0;                % 聲音片段的音量 0db
sinewave1_fs = 1000;    % 左聲道頻率,單位Hz
sinewave2_fs = 1000;    % 右聲道頻率
stereo = 1;             % 0:單聲道,1:立體聲
filename = ('96000_16b_1KHz_60s_stereo_gen_by_Matlab.wav'); %輸出文件名稱(自己定義,後綴是.wav)

%% 生成時間序列
Df = 1;                 % 頻率間隔,默認1
T = 1/fs;               % 採樣週期
N = fs/Df;              % 序列點數
time = Tfile*(N-1)*T;   % 文件總時長
t = 0:T:time;           % 生成每一個採樣點對應的時間序列

%% 生成左右聲道波形
y1 = sin(2*pi*sinewave1_fs*t)*(db2mag(vol));    % 生成第一個聲音片段,注意需要用db2mag()函數把dB轉換成magnitude。
y2 = sin(2*pi*sinewave2_fs*t)*(db2mag(vol));    % 生成第二個聲音片段,若需不同賦值,可以在參數定義中增加一個 vol_2 來控制第二段的賦值。 
if stereo == 0                                  % 選擇單聲道輸出
        y = y1';                                %   輸出的 y 只使用 y1, 左聲道(單聲道)
        y2 = 0*sin(2*pi*sinewave2_fs*t);        %   令 y2 爲 0
else                                            % 選擇立體聲輸出
        y = [y1',y2'];                          %   合成立體聲
end

%% 通過電腦音頻輸出口,播放生成的波形
whos y              % 命令行打印 y 的信息
if fs < 192000      % 電腦不能支持大於 192K 的聲音輸出,但是可以正常生成。
    sound(y,fs)     % 可以播放聲音的函數 sound()
end

%% 描繪波形圖像
if stereo == 0              % 如果選擇單聲道輸出 
    subplot(2,1,1);         %     選中第一個圖片位置
    plot(t,y1);             %     描繪左聲道生成波形
    title('左聲道生成波形'); 
    subplot(2,1,2);         %     選中第二個圖片位置
    plot(y1(1:200));        %     打印左聲道 1~200的值,如果下面讀取成功,此值會被覆蓋
    title('左聲道讀取失敗'); %     若後面讀取正常,該值會被覆蓋(即讀取成功的話,將看不到這句話,用於驗錯)

else                        % 如果選擇立體聲輸出 
    subplot(4,1,1);         %     選中第一個圖片位置
    plot(t,y1);             %     描繪左聲道生成波形
    title('左聲道生成波形');
    subplot(4,1,2);         %     選中第二個圖片位置
    plot(t,y2);             %     描繪右聲道生成波形
    title('右聲道生成波形');
    subplot(4,1,3);         %     選中第三個圖片位置
    plot(y1(1:200))         %     打印左聲道 1~200的值,如果下面讀取成功,此值會被覆蓋
    title('左聲道讀取失敗'); %     若後面讀取正常,該值會被覆蓋(即讀取成功的話,將看不到這句話,用於驗錯)
    subplot(4,1,4);         %     選中第四個圖片位置
    plot(y2(1:200))         %     打印右聲道 1~200的值,如果下面讀取成功,此值會被覆蓋
    title('右聲道讀取失敗'); %     若後面讀取正常,該值會被覆蓋(即讀取成功的話,將看不到這句話,用於驗錯)
end

%% 寫入文件
audiowrite(filename,y,fs,'BitsPerSample',bps);  % 存儲.wav音頻文件,文件名在參數定義裏設置
AudioInfo = audioinfo(filename)                 % 這裏不用加分號,可以順便在命令窗口看看寫入文件的打印信息

%%   讀取剛纔生成的 wav 文件進行,並描繪波形
[y_read,FS]=audioread(filename);    % 將 WAV 文件轉換成變量
whos y_r                            % 打印一下 y_read 信息
if stereo == 0                      % 如果選擇單聲道 
    y_read1 = y_read(:,1);          %	提取聲道
    subplot(2,1,2);                 %	選中第二個圖片位置
    plot(t,y_read1);                %   描繪左聲道讀取波形,覆蓋上一步驟的驗錯內容
    title('左聲道讀取波形');
else                                % 如果選擇立體聲 
    y_read1 = y_read(:,1);          %	提取左聲道
    subplot(4,1,3);                 %   選中第三個圖片位置
    plot(t,y_read1);                %   描繪左聲道讀取波形,覆蓋上一步驟的驗錯內容
    title('左聲道讀取波形');
    y_read2 = y_read(:,2);          %	提取右聲道
    subplot(4,1,4);                 %   選中第四個圖片位置
    plot(t,y_read2);                %   描繪右聲道讀取波形,覆蓋上一步驟的驗錯內容
    title('右聲道讀取波形');
end

4、運行圖片

爲了讓圖片看出正弦波形,修改文件時長爲 0.1s。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章