android獲取和展現音樂的頻譜

還有一些帖子: https://blog.csdn.net/Qzhongwenze/article/details/52851297html

http://blog.sina.com.cn/s/blog_67d95f40010113ec.htmljava

https://blog.csdn.net/caryee89/article/details/6935237android

https://blog.csdn.net/qq2582494/article/details/74393315git

https://blog.csdn.net/java173842219/article/details/54096598 (不少音樂播放器類的Android項目源碼)github

https://blog.csdn.net/SCTU_vroy/article/details/45871823 (Android平臺音頻信號FFT的實現 源碼,還有各類濾波算法:https://github.com/vroy007/MoveDSP)算法

https://www.jianshu.com/p/cdd09b840500 (Android:音樂特效控制 有回聲,噪音刪除,波形)canvas

http://www.javashuo.com/article/p-vklhojgg-gy.html (Android 音頻FFT提取分析 )數組

http://www.javashuo.com/article/p-cgorruls-gm.html (Android音頻進階 Equalizer,Visualizer,BassBoost,PresetReverb,EnvironmentalReverb)session

https://www.cnblogs.com/Free-Thinker/p/5027830.html (Android提升第十一篇之模擬信號示波器)ide

https://www.cnblogs.com/sage-blog/p/3885802.html (JNI實例1---掃描SD卡中mp3文件 JNI實例2---掃描SD卡中mp3文件,native層調用Java自定義的類 JNI實例3---掃描SD卡中mp3文件,native層調用Java自定義的類)

針對onFftDataCapture拿到的數據全爲0的狀況,這一篇帖子中有更祥細的變量說明: https://blog.csdn.net/suwenlie/article/details/45070883

作了個音樂播放器 就一直想作個加一個音樂頻譜的展現界面

覺的這是一個好玩的東西,能夠將耳邊動聽的聲音形象化,彷彿眼前能夠看到聲音同樣。

可是我在文檔的開發者指南里沒有講任何有關音樂頻譜的東西,最後仍是在google的源碼示例中找到了。

你能夠直接去參看源代碼更原滋原味 如下只是我的對着源碼的重構和理解

全部如下所講的功能,均須要在2.3以上的sdk中才能實現。

音頻頻譜的獲取

首先音頻的頻譜相關的類叫作 android.media.audiofx.Visualizer;

須要權限 <uses-permission android:name="android.permission.RECORD_AUDIO"/> 因此要作的第一件事 是初始化一個visualizer出來

//使用音樂的sessionId來實例化這個類

        mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
        //設置每次捕獲頻譜的大小,音樂在播放中的時候採集的數據的大小或者說是採集的精度吧,個人理解,並且getCaptureSizeRange()所返回的數組裏面就兩個值 .文檔裏說數組[0]是最小值(128),數組[1]是最大值(1024)。

        mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);



       //接下來就好理解了設置一個監聽器來監聽不斷而來的所採集的數據。一共有4個參數,第一個是監聽者,第二個單位是毫赫茲,表示的是採集的頻率,第三個是是否採集波形,第四個是是否採集頻率
        mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
           

       //這個回調應該採集的是波形數據
            [@Override](https://my.oschina.net/u/1162528)
            public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform,
                    int samplingRate) {

            //waveformView 是一個自定義的view用來按照波形來畫圖 一會後面再講
                waveformView.updateVisualizer(waveform);
            }
           

     //這個回調應該採集的是快速傅里葉變換有關的數據,沒試過,回頭有空了再試試
            [@Override](https://my.oschina.net/u/1162528)
            public void onFftDataCapture(Visualizer visualizer, byte[] fft,
                    int samplingRate) {
                // TODO Auto-generated method stub
               
            }
        }, Visualizer.getMaxCaptureRate() / 2, true, false);

以上波形的數據採集就完成了,須要注意的一個點是mVisualizer.setEnabled(true);

這個方法的主要做用是爲了控制什麼時候去採集頻譜數據,你應該只是願意採集你所關心的音樂數據,而不關心聲音輸出器中任何的聲音。並且對mVisualizer的許多設置必須在setEnable以前完成。而且結束功能後,要記得setEnable(false)

若是你見到了如下這個錯誤,那基本上就是由於沒有及時setEnable(false),致使setCaptureSize()這個方法出錯。

E/AndroidRuntime(22259): Caused by: java.lang.IllegalStateException: setCaptureSize() called in wrong state: 2

順帶再說一個bug 若是你獲得的錯誤代碼是 -1 那麼基本上的緣由是你忘記了聲明權限

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

音頻頻譜的展現

你在上一節已經經過監聽器得到了波形數據,那麼如何展現?這僅僅是一個自定義view的問題,簡單廢話一下:重點提一下view中的onDraw()方法

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);

//mBytes就是採集來的數據 這裏是個大小爲1024的數組,裏面的數據都是byts類型,因此大小爲-127到128

if (mBytes == null) {
        return;
    }

    if (mPoints == null || mPoints.length < mBytes.length * 4) {

//mPoints主要用來存儲要畫直線的4個座標(每一個點兩個座標,因此一條直線須要兩個點,也就是4個座標) mPoints = new float[mBytes.length * 4]; }

mRect.set(0, 0, getWidth(), getHeight());

//xOrdinate是x軸的總刻度,由於一次會傳輸過來1024個數據,每兩個數據要畫成一條直線,因此x軸咱們分紅1023段。你要是覺的太多了,也能夠像我同樣除以2,看本身需求了。

int xOrdinate = (mBytes.length - 1)/2;

//如下的for循環將利用mBytes[i] mBytes[i+1] 這兩個數據去生成4個座標值,從而在刻畫成兩個座標,來畫線條 for (int i = 0; i <xOrdinate ; i++) {

//第i個點在總橫軸上的座標,

        mPoints[i * 4] = mRect.width() * i / xOrdinate;

//第i個點的在總縱軸上的座標。他在畫線上以總縱軸的1/2爲基準線(mRect.height() / 2),全部的點或正或負以此線爲基礎標記。

//((byte) (mBytes[i] + 128))這個一直沒有理解,若是+128是爲了將數據所有換算爲正整數,那麼強轉爲byte後不又變回-127到128了麼??要是誰知道緣由能夠留言告訴我.....

//(mRect.height() / 2) / 128就是將二分之一的總長度換算成128個刻度,由於咱們的數據是byte類型,因此刻畫成128個刻度正好 mPoints[i * 4 + 1] = mRect.height() / 2+ ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;

//如下就是刻畫第i+1個數據了,原理和刻畫第i個同樣 mPoints[i * 4 + 2] = mRect.width() * (i + 1) / xOrdinate; mPoints[i * 4 + 3] = mRect.height() / 2 + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128; }

//循環結束後,就獲得了這一次波形的全部刻畫座標,直接畫在畫布上就行了

canvas.drawLines(mPoints, mForePaint);
}

作的音樂軟件 純粹好玩 就放在了國內的market上

http://market.nduoa.com/apk/detail/412136

相關文章
相關標籤/搜索