java音频频谱_Android 音乐频谱实现
最近由于需要實現(xiàn)音樂頻譜,所以今天就為大家普及一下。關(guān)于音樂頻譜你需要了解數(shù)字信號處理的知識,尤其是FFT的知識。簡單說就是把時域上連續(xù)的信號(波形)強度轉(zhuǎn)換成離散的頻域信號(頻譜)。我理解波形就是信號的強度,或者說音響設(shè)備的輸出的功率,功率高,音量就大。但是歌曲的曲調(diào)是不會變的,因為頻譜是不會變的。
頻譜反映的是這個這個音樂在某個連續(xù)時間段內(nèi),聲音的震動頻率。不知道理解的對不對。
本文的音樂頻譜實現(xiàn)是仿照Android Api Demo 里的一個例子實現(xiàn)的,需要Android 2.3及以上系統(tǒng),因為要用到Visualizer 類,這個類只在Android 2.3以上的API才支持。
首先實例化Visualizer,參數(shù)SessionId可以通過MediaPlayer的對象獲得
visualizer?=?new?Visualizer(mPlayerInstance.getAudioSessionId());
接著設(shè)置需要轉(zhuǎn)換的音樂內(nèi)容長度,專業(yè)的說這就是采樣,該采樣值一般為2的指數(shù)倍,如64,128,256,512,1024。這里我設(shè)置了128,原因是長度越長,FFT算法運行時間更長。
visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[0]);
然后為visualizer設(shè)置監(jiān)聽器,這樣當(dāng)Capture一段數(shù)據(jù)后,就會觸發(fā)兩個函數(shù)進行處理。設(shè)置監(jiān)聽函數(shù)為
setDataCaptureListener(OnDataCaptureListener?listener,?rata,iswave,isfft?)
參數(shù)解釋:
rate, 表示采樣的周期,即隔多久采樣一次,聯(lián)系前文就是隔多久采樣128個數(shù)據(jù),本文設(shè)置為512mHz更新一次
iswave,是波形信號
isfft,是FFT信號,表示是獲取波形信號還是頻域信號
OnDataCaptureListener,表監(jiān)聽函數(shù),匿名內(nèi)部類實現(xiàn)該接口,該接口需要實現(xiàn)兩個函數(shù)
onWaveFormDataCapture(Visualizer?visualizer,byte[]?waveform,?int?samplingRate)
和
public?void?onFftDataCapture(Visualizer?visualizer,byte[]?fft,?int?samplingRate)
samplingRate是采樣速率,即上文的rate值,512mHz。
其中兩個byte[] waveform和byte[] fft數(shù)組,分別是獲得波形數(shù)據(jù)和FFT的數(shù)據(jù),該byte數(shù)組的大小即為之前設(shè)置的采樣值大小128,獲得數(shù)據(jù)如下圖所示。
其中n為采樣值,index 0 表示直流分量,Rf表示FFT計算后的實部,If表示FFT計算后的虛部。
如何計算出該頻率,就是將FFT的實部和對應(yīng)的虛部先各自平方再相加然后開方,簡單說就是平方取模。
具體計算請看如下的代碼。
visualizer.setDataCaptureListener(
new?Visualizer.OnDataCaptureListener()?{
@Override
public?void?onWaveFormDataCapture(Visualizer?visualizer,
byte[]?waveform,?int?samplingRate)?{
//?這里添加獲得數(shù)據(jù)的處理?byte[]?數(shù)組?更新出去,并畫圖。這里可以把這個
//?數(shù)組傳到RunOnMusic里去
//?visualView.updateVisualizer(waveform);
}
@Override
public?void?onFftDataCapture(Visualizer?visualizer,
byte[]?fft,?int?samplingRate)?{
byte[]?model?=?new?byte[fft.length?/?2?+?1];
model[0]?=?(byte)?Math.abs(fft[1]);
int?j?=?1;
for?(int?i?=?2;?i?
model[j]?=?(byte)?Math.hypot(fft[i],?fft[i?+?1]);
i?+=?2;
j++;
}
visualView.updateVisualizer(model);
}
},?Visualizer.getMaxCaptureRate()?/?2,?false,?true);
}
其中visualView是顯示程序,updateVisulizer是將model獲取的頻譜值更新到要顯示的view。
protected?void?onDraw(Canvas?canvas)?{
super.onDraw(canvas);
if?(mBytes?==?null)?{
return;
}
if?(mPoints?==?null?||?mPoints.length?
mPoints?=?new?float[mBytes.length?*?4];
mRect.set(0,?0,?getWidth(),?getHeight()?-?50);
for?(int?i?=?0;?i?
if?(mBytes[i]?
mBytes[i]?=?127;
mPoints[i?*?4]?=?mRect.width()?*?i?/?9;
mPoints[i?*?4?+?1]?=?mRect.height()?/?2;
mPoints[i?*?4?+?2]?=?mRect.width()?*?i?/?9;
mPoints[i?*?4?+?3]?=?2?+?mRect.height()?/?2?+?mBytes[i];
}
canvas.drawLines(mPoints,?mForePaint);
}
}
總結(jié)
以上是生活随笔為你收集整理的java音频频谱_Android 音乐频谱实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2016TI杯智能电子秤的设计
- 下一篇: 打包Android编译出错make: *