Доступ к мультимедийному streamу Android для аудиовизуализации
В принципе, я хочу сделать аудио визуализатор. Я знаю, что это возможно, потому что в моем телефоне появилось несколько живых обоев, которые это делают. Проблема в том, что я не могу понять, как это сделать с Android API.
Мое приложение подхватит текущий воспроизводимый медиа-stream, а затем в зависимости от того, что воспроизводится в то время, оно отображает больше или меньше баров на экране.
Как я могу это сделать? Похоже, я могу сделать что-то подобное с помощью микрофона, но я хочу, чтобы это можно было сделать для музыки, подкастов и т. Д.
- Ошибка CreateProcess = 740. Запрошенная операция требует повышения
- Переопределение Object.equals VS Перегрузка
- Как объект будет вызывать метод toString неявно?
- Сохранять широковещательный приемник после закрытия приложения
- Как вернуть массив из JNI в Java?
- Как удалить файл на Google Диске с помощью Google Диска Android API
- RecyclerView - просмотр в определенном положении
- Импорт android.support не может быть разрешен
- Что-то вроде «содержит любые» для набора Java?
- Импортирование двух classов с одинаковым именем. Как обращаться?
- Странное поведение java с приведениями к примитивным типам
- Строковый постоянный пул
- В чем разница между == vs equals () в Java?
Источник обоев MusicVisualization доступен на AOSP . В основном это связано с вызовом MediaPlayer.snoop()
, недокументированного метода, добавленного в Eclair.
Похоже, что в 2.3 здесь изменились, теперь есть разрешения
И есть вспомогательный class AudioCapture в aosp, чтобы помочь живым обоям сделать это правильно. 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, он, по-видимому, возвращает stream звука с низким разрешением, но не достаточно хорош для записи.
В основном то, что сказал roskit, за исключением незначительной модификации возвращаемого значения из
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; } }
Немного быстрее 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; } } }
Вот как я это сделал из своего приложения:
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; } }
Посмотрите на http://code.google.com/p/moonblink/wiki/Tricorder для примера.