2010-08-26 50 views
20

基本上,我想製作一個音頻可視化器。我知道這是可能的,因爲我的手機附帶了幾個動態壁紙。問題是,我似乎無法弄清楚如何使用Android API來做到這一點。訪問Android媒體流以進行音頻可視化

我的應用程序會選取當前正在播放的媒體流,然後根據當時正在播放的音量,它會在屏幕上顯示更多或更少的條。

我該怎麼做?它看起來像我可以用麥克風做這樣的事情,但我希望能夠做到這一點,音樂,播客等。

+0

從一個應用程序獲取來自其他應用程序的音頻(例如,可能存在嚴重的隱私問題)。,VOIP)。 – CommonsWare 2010-09-09 18:45:05

+1

請參閱我的回答,2.3通過低分辨率的音頻嗅探器API以安全的方式解決此問題。 snoop()將無法在2.3設備上工作,找不到功能。 – HaMMeReD 2011-01-10 20:15:23

回答

5

MusicVisualization wallpaper source可在AOSP處獲得。它基本上似乎涉及呼籲MediaPlayer.snoop(),Eclair中添加一個未公開的方法。

+0

謝謝!在賞金到期之前,我沒有時間去測試,但這似乎正是我所期待的。 – HenryAdamsJr 2010-10-20 14:30:57

+0

謝謝,請在此發佈一個鏈接到您的結果! – adietrich 2010-10-21 07:17:29

+0

該鏈接不再工作 – 2013-10-31 09:47:31

2

這是我從我的應用程序做到了:

protected short [] mAudioData = new short[1024]; 

然後在循環:

int res = snoop(mAudioData, 0); 

,這裏是本身的功能:

public static int snoop(short [] outData, int kind){  
    try { 
     Class c = MediaPlayer.class; 
     Method m = c.getMethod("snoop", outData.getClass(), Integer.TYPE); 
     m.setAccessible(true); 
     m.invoke(c, outData, kind); 
     return 0; 
    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     return 1; 
    } 
} 
3

基本上什麼roskit說除了從

01次要返回值修改
return 0; 

return Integer.parseInt((m.invoke(c, outData, kind)).toString()); 

換句話說:

public static int snoop(short [] outData, int kind){  
       try { 
        Class c = MediaPlayer.class; 
        Method m = c.getMethod("snoop", outData.getClass(), Integer.TYPE); 
        m.setAccessible(true); 
        return Integer.parseInt((m.invoke(c, outData, kind)).toString()); 
       } catch (Exception e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       return 1; 
      } 
    } 
2

稍快snoop()將調用Class.getMethod()一次,然後使用一個自定義parseInt()而不是Integer.parseInt() ...

private static Method mSnoop; 

//..(http://nadeausoftware.com/node/97).. 
private static int customParseInt(final String s) 
{ 
    // Check for a sign. 
    int num = 0; 
    int sign = -1; 
    final int len = s.length(); 
    final char ch = s.charAt(0); 
    if (ch == '-') 
     sign = 1; 
    else 
     num = '0' - ch; 

    // Build the number. 
    int i = 1; 
    while (i < len) 
     num = num*10 + '0' - s.charAt(i++); 

    return sign * num; 
} 

private static int snoop(short [] outData, int kind) 
{  
    if (mSnoop != null) 
    { 
     try 
     { 
      return customParseInt((mSnoop.invoke(MediaPlayer.class , outData, kind)).toString()); 
     } 
     catch (Exception e) 
     { 
      Log.e(TAG, "Failed to MediaPlayer.snoop()!", e); 
      return 1; 
     } 
    } 
    else 
    { 
     try { 
      Class c = MediaPlayer.class; 
      Method m = c.getMethod("snoop", outData.getClass(), Integer.TYPE); 
      m.setAccessible(true); 
      mSnoop = m; 
      return customParseInt((m.invoke(c, outData, kind)).toString()); 
     } 
     catch (Exception e) 
     { 
      Log.e(TAG, "Failed to MediaPlayer.snoop()!", e); 
      return 1; 
     } 
    } 
} 
6

它看起來像在2.3事情已經改變了這裏,有權限現在

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

而且還有在AOSP一個AudioCapture輔助類來幫助動態壁紙做正確。 https://android.googlesource.com/platform/packages/wallpapers/MusicVisualization/+/gingerbread-release/src/com/android/musicvis/AudioCapture.java

編輯:

一位在AOSP的進口量不匹配的公共API。
import android.media.audiofx.Visualizer;


import android.media.Visualizer;

如果它給出了一個頭痛確保切換。這都是2.3 api,它顯然會返回一個低分辨率的音頻流,但對於錄製而言還不夠好。

+2

對於2.3+,這是要走的路。看到這裏的示例實現:https://github.com/felixpalmer/android-visualizer – pheelicks 2011-12-07 21:26:38