目錄
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。