2017-08-04 76 views
0

我試圖構建一個簡單的音樂可視化應用程序,只需調整一個圓圈。因此,如果當前正在播放的音樂部分響亮,則應該變大,否則應該變小。帶圓圈的簡單音樂可視化

可視化圓我剛剛創建了一個自定義的視圖類,它在onDraw方法中繪製圓。

要從當前音頻中獲取信息,我找到了Android的Visualizer Class,並且還使用了setDataCaptureListener

mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId()); 
mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[0]); 
mVisualizer.setDataCaptureListener(
    new Visualizer.OnDataCaptureListener() { 
      public void onWaveFormDataCapture(Visualizer visualizer,byte[] bytes, int samplingRate) { 
         mVisualizerView.updateVisualizer(bytes); 
        } 

        public void onFftDataCapture(Visualizer visualizer,byte[] bytes, int samplingRate) { 

        } 
       }, (int)(Visualizer.getMaxCaptureRate()/1.5), true, false); 

但我的問題是,我真的不知道我該如何使用它還給字節數組,找出一般的音樂變化(有大聲或不?)。

我只是試圖得到數組的平均值,但這給了我完全不好的結果。這個圓圈像毒品一樣改變了他的大小。所以我想也許陣列有太多的輪廓/極端值(這是真的),所以我計算了陣列的中位數。這給我更好的結果,但仍然不是我想要的。它不是很流暢,而且很複雜。我總是必須對那些效率不高的數組進行排序。我在想什麼錯了?

我真的是這個AudioFX部分的初學者,我完全抱歉如果這是一個愚蠢的問題和我的企圖。

謝謝你的幫助!

編輯:

private float schwelle = 5000; 
private float last = 0; 
... 

    float summe = 0; 

    for (Byte currentByte: mBytes) 
     summe += currentByte; 

    if (summe > schwelle && summe > last) 
    { 
     last = summe; //make it bigger 
    } 
    else { 
     last -= 100; //make circle smaller 
    } 

    canvas.drawCircle(getWidth()/2,getHeight()/2,last/100,mForePaint); 

回答

0

一個真正好的Git項目是https://github.com/felixpalmer/android-visualizer。 我自己想出了這個:(它比git解決方案簡單很多)

您可以使用數組的值使用三角法在圓的輪廓上繪製波形,並將起始半徑圈如果大數組的總和大於一定treshhold更大:

class StarWaveformRenderer implements Renderer { 
private Paint p = new Paint(); 

private static final int BOOST_TRASH_HOLD = 10000; 


private float stretchFade = 1; //circle fades after a prominent beat 

@Override 
public void render(Canvas canvas, byte[] data) { 
    if (data == null || data.length == 0) 
     return; 

    int centerX = canvas.getWidth()/2; 
    int centerY = canvas.getHeight()/2; 
    float stretch = stretchFade; 

    int sum = RenderUtils.sum(data); 
    p.setColor((p.getColor() + sum/2)); //change color of circle 
    if (sum > BOOST_TRASH_HOLD) {//prominent beat 

     stretch = (float) Math.min(canvas.getWidth(), canvas.getHeight())/Byte.MAX_VALUE/3; //maximum 

     stretchFade = stretch; 
    } 

    double radDif = 2 * Math.PI/data.length; //the angle between each element of the array 
    double radPos = 0; 

    float lX = (float) Math.cos(radPos) * data[0] + centerX; 
    float lY = (float) Math.sin(radPos) * data[0] + centerY; 
    float cX; 
    float cY; 


    for (byte b : data) { 
     cX = (float) Math.cos(radPos) * b * stretch + centerX; 
     cY = (float) Math.sin(radPos) * b * stretch + centerY;//calculate position of outline, stretch indicates promince of the beat 

     canvas.drawLine(lX, lY, cX, cY, p); 

     lX = cX; 
     lY = cY; 
     radPos += radDif; 

    } 


    stretchFade = Math.max(1, stretchFade/1.2f);//beat fades out 

} 

}

您可以PROGRAMM自己renderes並讓用戶選擇他想要使用哪一個。只需將數組從onWaveformDataCapture傳遞給onRender方法即可。

utils的分析波形(振幅存儲很怪):

class RenderUtils { 
private static final byte SHIFT = Byte.MAX_VALUE; 


static int sum(byte[] data) { 
    int sum = 0; 
    for (byte b : data) 
     sum += b; 
    return sum; 
} 


static int toAmplitude(byte b) { 
    return b > 0 ? b + SHIFT : -b;//+127=high positive;+1=low positive;-127=low negative;-1=high negative 
} 

static float toAmplitude(float f) { 
    return f > 0 ? f + SHIFT : -f;//+127=high positive;+1=low positive;-127=low negative;-1=high negative 
} 

}

+0

嗯......謝謝你的幫助,我只是想與和做出來,這是trashhold princip,但它仍然不是我想要的。它看起來不像一個同步的圓。 (我沒有添加圈子周圍的花哨線:-))。我用我試過的代碼更新了我的帖子。 –