2014年9月7日 星期日

[Matlab/Ocyave] Spectrogram overlap 需要多少? 一個解決out of memory的方法

處理聲音訊號時,若要繪製聲紋圖,最煩的就是遇到out of menory這件事情。以前我使用32bit的版本,只要是20秒以上的聲音訊號,我都沒有辦法畫出聲紋來,非常困擾。當時查到一些資料說32位元記憶體使用量太少,可以使用64為原版本以避免記憶體不足,於是我就換成64位元的了。最近因為有一些需求,需要繪製超過100秒的聲音聲紋圖,但...我以前的畫法就只能允許我畫約60秒而已,我又再次的頭大了。再次探討如何不要發生out of memory這件事情。
今天來看看我為何會一直發生記憶體不足的事情吧!!

先跑一下500秒的音訊圖看看。(上為Matlab,下為Octave,因為忘記存出音訊讓cotave讀,就刪掉變數了,所以圖就不一樣啦,且錄音錄8分多鐘太久了...所以我隨便錄25秒,然後將矩陣加到300秒XD)










Octave 竟然跑500會睡著= =,根本沒有在動,所以畫300秒就好,還滿快的









spectrogram(X,WINDOW,NOVERLAP,F,Fs)
X→音訊的矩陣,矩陣越大越容易記憶體不足
WINDOW→我通常使用1024
NOVERLAP→覆蓋率越高圖越漂亮,平時都使用1000
F→平時使用[]
Fs→我的音訊檔都是48000

這樣的程式碼看起來記憶體爆表主因就是你的聲音檔案,但我現在沒有辦法更動X來達到記憶體足夠的情況。但我看別人的程式碼卻都可以畫出100秒的聲紋圖,為何我辦不到呢?在他的程式碼中我來來回回找了幾次都沒有發現原因何在,但今天卻發現了一件事情,就是NOVERLAP我的覆蓋率是97%,而他使用的只有55%,這是最主要的癥結點。

來看一下聲紋圖overlap不同時,資料量的差別到底有多少

fs=48000;
x=wavrecord(5*fs,fs); %錄製五秒的聲音,取樣頻率為48000,請盡情地大叫,會幫你錄音
[s1000]=spectrogram(x,1024,1000,[],fs);
[s512]=spectrogram(x,1024,512,[],fs);
[s128]=spectrogram(x,1024,128,[],fs);

>> whos
  Name            Size                 Bytes  Class     Attributes
  fs              1x1                      8  double            
  s1000         513x9958            81735264  double    complex
  s128          513x267              2191536  double    complex
  s512          513x467              3833136  double    complex
  x          240000x1                1920000  double              

這邊可以發現聲音訊號的資料量在spectrogram中,差異可以達到37倍之多(s1000與s128相較)

subplot(311),spectrogram(x,1024,1000,[],fs,'yaxis');
subplot(312),spectrogram(x,1024,512,[],fs,'yaxis');
subplot(313),spectrogram(x,1024,128,[],fs,'yaxis');





















我稍微調一下xlim ylim後呈現的結果

現在我們可以發現做圖時,這些設定對於5秒的音訊而言,其聲紋圖的影響並非嚴重,但1000的overpal還是看起來較舒服,再來看看0.5秒區間的差別吧。



















此時終於清楚的發現128的overlap是如此的不堪,但今天我們畫不出來、會out of memory的不是0.5秒的音訊,而是500秒的音訊,而不同的overlap只有時間維度有差別,音訊當時間很長時,這樣的差別我們卻看不出來,那麼,為何我們需要用到97%的音訊重複率呢?

於是我重新更正了程式碼,以避免記憶體爆表的事情

fs=48000;
x=wavrecord(500*fs,fs); %這次來個500秒挑戰看看吧,請唱一下情歌吧
t=(0:length(x)-1)/fs;

if max(t)>225
    overlap=1024*0.25; %實際上不用這樣寫,這裡只是強調覆蓋率是25%
elseif max(t)>12
    overlap=floor(1024*(1-max(t)/300)); %計算覆蓋率,使音訊長度越長覆蓋率越低,反之越高
else
    overlap=floor(1024*0.97);% 97%覆蓋率,floor為無條件捨去至整數
end

spectrogram(x,1024,overlap,[],fs,'yaxis');

成果就是網誌的第一張圖囉~
執行後記憶體使用狀態如下,並未爆表
>> memory
Maximum possible array:        7064 MB (7.407e+09 bytes) *
Memory available for all arrays:        7064 MB (7.407e+09 bytes) *
Memory used by MATLAB:        2648 MB (2.777e+09 bytes)
Physical Memory (RAM):        7650 MB (8.022e+09 bytes)
這樣可以看到覆蓋率對應圖如下,相信這樣的方式畫300秒聲紋圖將不會是問題,秒數再多也會密到看不到要看的資訊了吧!!(如前兩張圖根本沒有甚麼好看的,資料太密了...)

沒有留言:

張貼留言

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