java音频频谱_Android 音乐频谱实现
最近由于需要實(shí)現(xiàn)音樂頻譜,所以今天就為大家普及一下。關(guān)于音樂頻譜你需要了解數(shù)字信號(hào)處理的知識(shí),尤其是FFT的知識(shí)。簡單說就是把時(shí)域上連續(xù)的信號(hào)(波形)強(qiáng)度轉(zhuǎn)換成離散的頻域信號(hào)(頻譜)。我理解波形就是信號(hào)的強(qiáng)度,或者說音響設(shè)備的輸出的功率,功率高,音量就大。但是歌曲的曲調(diào)是不會(huì)變的,因?yàn)轭l譜是不會(huì)變的。
頻譜反映的是這個(gè)這個(gè)音樂在某個(gè)連續(xù)時(shí)間段內(nèi),聲音的震動(dòng)頻率。不知道理解的對(duì)不對(duì)。
本文的音樂頻譜實(shí)現(xiàn)是仿照Android Api Demo 里的一個(gè)例子實(shí)現(xiàn)的,需要Android 2.3及以上系統(tǒng),因?yàn)橐玫絍isualizer 類,這個(gè)類只在Android 2.3以上的API才支持。
首先實(shí)例化Visualizer,參數(shù)SessionId可以通過MediaPlayer的對(duì)象獲得
visualizer?=?new?Visualizer(mPlayerInstance.getAudioSessionId());
接著設(shè)置需要轉(zhuǎn)換的音樂內(nèi)容長度,專業(yè)的說這就是采樣,該采樣值一般為2的指數(shù)倍,如64,128,256,512,1024。這里我設(shè)置了128,原因是長度越長,FFT算法運(yùn)行時(shí)間更長。
visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[0]);
然后為visualizer設(shè)置監(jiān)聽器,這樣當(dāng)Capture一段數(shù)據(jù)后,就會(huì)觸發(fā)兩個(gè)函數(shù)進(jìn)行處理。設(shè)置監(jiān)聽函數(shù)為
setDataCaptureListener(OnDataCaptureListener?listener,?rata,iswave,isfft?)
參數(shù)解釋:
rate, 表示采樣的周期,即隔多久采樣一次,聯(lián)系前文就是隔多久采樣128個(gè)數(shù)據(jù),本文設(shè)置為512mHz更新一次
iswave,是波形信號(hào)
isfft,是FFT信號(hào),表示是獲取波形信號(hào)還是頻域信號(hào)
OnDataCaptureListener,表監(jiān)聽函數(shù),匿名內(nèi)部類實(shí)現(xiàn)該接口,該接口需要實(shí)現(xiàn)兩個(gè)函數(shù)
onWaveFormDataCapture(Visualizer?visualizer,byte[]?waveform,?int?samplingRate)
和
public?void?onFftDataCapture(Visualizer?visualizer,byte[]?fft,?int?samplingRate)
samplingRate是采樣速率,即上文的rate值,512mHz。
其中兩個(gè)byte[] waveform和byte[] fft數(shù)組,分別是獲得波形數(shù)據(jù)和FFT的數(shù)據(jù),該byte數(shù)組的大小即為之前設(shè)置的采樣值大小128,獲得數(shù)據(jù)如下圖所示。
其中n為采樣值,index 0 表示直流分量,Rf表示FFT計(jì)算后的實(shí)部,If表示FFT計(jì)算后的虛部。
如何計(jì)算出該頻率,就是將FFT的實(shí)部和對(duì)應(yīng)的虛部先各自平方再相加然后開方,簡單說就是平方取模。
具體計(jì)算請(qǐng)看如下的代碼。
visualizer.setDataCaptureListener(
new?Visualizer.OnDataCaptureListener()?{
@Override
public?void?onWaveFormDataCapture(Visualizer?visualizer,
byte[]?waveform,?int?samplingRate)?{
//?這里添加獲得數(shù)據(jù)的處理?byte[]?數(shù)組?更新出去,并畫圖。這里可以把這個(gè)
//?數(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: *