2014年10月24日 星期五

[Matlab/Octave] 音訊給個比例尺

在一些時候我們或許會想把聲音訊號的波型圖以較輕鬆的方式作呈現,不想要有時間軸也不想要有振幅值,就單純的一個波形就好,最多再加個聲音長度的比例尺。但是正規的畫圖就是會有XY軸,而有告知時間的X軸也不需要比例尺了,看起來真的很不輕鬆。這兩天,我有點無聊,想說能玩玩什麼,於是就想一下要如何畫出這樣的圖片,打發時間。

image

首先,先簡單說明繪圖概念,這種繪圖其實不脫離plot指令,但經過設定之後使得XY軸不出現於繪圖區中,而比例尺也是畫一條線而已,非常簡單。下面就來看看程式碼吧!!


程式碼

%%參數設定區

col='b'; %波形圖色彩設定'b' 'k' 'g' 'r' 'm'...請使用預設顏色代碼
fix_bar=0; %若要固定時間比例尺請輸入1,若要程式決定請輸入0
bar_sec=1; %設定時間軸比例尺的長度,單位秒。若fix_bar=0,此設定將失效
bar_width=5; %設定比例尺寬度
bar_position=1; %設定時間比例尺位置,0置於前方,1置於後方
width_high=[900 300]; %設定欲畫的圖形大小

%%程式執行區

fs=48000; %紅色部分為自寫的隨機數字充當音訊,若需要請自行讀入聲音訊號
x=rand(floor(rand*10*fs),1);
t=(0:length(x)-1)/fs;
for i=1:length(x)
    x(i)=sin(t(i))^3*x(i);
end
for i=1:2:length(x)
    x(i)=-1*x(i);
end

x=x/max(abs(x));
if fix_bar==0 %判斷時間比例尺是否為程式決定
    if max(t)>300
        bar_sec=60; %大於300秒的訊號一律用60秒為比例尺
    elseif max(t)>100
        bar_sec=30; %100-300秒的聲音訊號,使用30秒為比例尺
    elseif max(t)>30
        bar_sec=20; %30-100秒的聲音訊號,使用20秒為比例尺
    elseif max(t)>15
        bar_sec=5; %15-30秒的聲音訊號,使用5秒為比例尺          
    elseif max(t)>7
        bar_sec=3; %7-15秒的聲音訊號,使用3秒為比例尺
    elseif max(t)>2
        bar_sec=1; %2-7秒的聲音訊號,使用1秒為比例尺
    elseif max(t)>0.7
        bar_sec=0.5; %0.7-2秒的聲音訊號,使用0.5秒為比例尺
    else
        bar_sec=0.1; %小於0.7秒的聲音訊號,使用0.1秒為比例尺
        if max(t)<0.1 %聲音訊號小於0.1秒必須插入一些空值避免繪圖錯誤
            if bar_position==0
                x(length(x)+1:0.1*fs)=nan; %比例尺放前面,空值加於聲音訊號後方
            else
                x=[repmat(nan,fs*bar_sec-length(x),1);x]; %比例尺放後面,空值加於聲音訊號前方
            end
        end
    end
end
words=[num2str(bar_sec) ' s']; %製作比例尺說明文字
if max(t) < bar_sec %程式決定比例尺時有避免訊號短於比例尺的錯誤(上面的if fix_bar==0),這邊需再設定一次(程式碼還可以簡化,懶得改了XD)
    if bar_position==0
        x(length(x)+1:bar_sec*fs)=nan;
    else
        x=[repmat(nan,fs*bar_sec-length(x),1);x];
    end
end
t=(0:length(x)-1)/fs; %x可能長度有變,重新設定時間
if bar_position==0; %判斷比例尺放置位置
    barline=[0 bar_sec];
elseif bar_position==1;
    barline=[max(t)-bar_sec max(t)];
else
    fprintf('reset bar_position\n');
end
xb=[-1.1 -1.1];
set(figure,'Position',[1 1 width_high(1) width_high(2)]) %設定繪圖區位置大小
set(gca,'position',[0 0 1 1]) %使XY軸貼緊下方與左方
plot(t,x,col) %畫上波形圖
box off;
hold on;
plot(barline,xb,'k','linewidth',bar_width) %畫上時間比例尺,並設定線寬
text(barline(1)+bar_sec/50,-1.2,words,'FontSize',14,'FontName','Times New Roman') %幫比例尺上文字
ylim([-1.3 1.1]) %設定Y軸最大值,-1.3~-1空間留給比例尺繪圖
xlim([0 max(t)])
set(gca,'xcolor',[1 1 1],'ycolor',[1 1 1],'ytick',[],'xtick',[]) %把tick刪除,XY軸設為白色


成果區

將比例尺至於後方,時間比例尺長度程式決定

imageimage

比例尺放於前方,時間比例尺程式決定,更改其他參數→fs=100,x=rand(floor(rand*fs*300),1);

image

比例尺放於後方,比例尺長度手動決定,訊號長度短於比例尺的情況

image

比例尺放前方,比例尺長度手動決定,訊號長度短於比例尺的情況

image


程式碼最前方有一些可以更動的設定,之後程式碼會透過if判斷,得到所需的繪圖情況。做出圖片之後就可以隨心所欲地使用,像是應用於PPT中,或是用於海報上,也可以將多個圖一起排版做比較,都會較為美觀。

沒有留言:

張貼留言

有任何問題可以詢問,我們會盡量回答