Bad Spectrum с выхода FFT-выхода Android (Visualiser)?

У меня есть какой-то вопрос о FFT (на самом деле я считаю, что это больше о FFT-выходе Androids от Visualizer.getFFT ()).

Я создал Музыкальный плеер с собственной библиотечной функцией для Android, включая лот Stuff (например, жанры, динамические плейлисты и визуализации). В настоящее время у меня есть некоторые проблемы с Visualisations, которые я создаю, когда речь заходит о предоставлении Спектрума текущего AudioStream.

Я уже прочитал следующие вопросы (и ответы), чтобы получить идею андроидов БПФ:

Какую выходную информацию я должен видеть из getFft?

Android 2.3 Visualizer – понимание проблем getFft ()

Теперь к моей проблеме: Спектр, который я получаю от коэффициентов getFFTs, кажется несколько «странным». Я замечаю, что спектр, который я оказываю, кажется, отображает много «шума» при воспроизведении песни, поэтому я попытался использовать некоторые тестовые звуки. Один из них – простой звук 8 кГц, который должен приводить к одному пику на графике. К сожалению, результат выглядит следующим образом:

http://img4.imageshack.us/img4/4181/spectrum8khz.png

Шум, появляющийся внизу, мерцает по всей ширине графика. Высокие бары остаются в положении, слегка мерцающем по величине.

Когда я использую тестовый звук, медленно двигающийся от 1 кГц до 20 кГц, он выглядит следующим образом (примерно на 2-3 кГц):

http://img846.imageshack.us/img846/7373/spectrum3khz1khz20khz.png

Пики движутся слева направо, и каждый из них немного быстрее, поэтому со временем расстояние между вершинами растет. Не видно, что пики возвращаются и идут справа налево, когда они покидают экран справа (но с меньшей величиной). Также все пики присоединяются к одному большому пику на чуть больше 0,5 экрана.

Вот код, который я использую для извлечения данных:

for (int i = 1; i < n / 2; i++) { byte rfk = mRawSpecData[2*i]; byte ifk = mRawSpecData[2*i+1]; float magnitude = (float)Math.sqrt(rfk * rfk + ifk * ifk); mFormattedSpecData[i-1] = magnitude / 128f; } 

В приведенном выше коде mRawSpecData является результатом функции visualisers getFFT (). Длина захваченных данных равна 1024. В настоящее время наклон начинается с 1, потому что mRawSpecData [0] содержит DC и mRawSpecData [1] содержит n / 2.

Чтобы решить мою проблему, я также попытался объединиться с DC и фазой бункера. Думал, что мне пришлось применить некоторые вычисления по величинам, чтобы «очистить» график. Но мне это не удалось (может быть, потому, что я не понял, что вообще происходит с DC / фазой!).

Я провел две недели в поисках Google по вечерам и пробовал разные вычисления, но ничего не помогло.

Так в чем заключена сделка? Я что-то делаю неправильно или что-то выхожу? После этого другой вопрос, который беспокоит меня, – это правильно масштабировать величины. Моя цель – получить значения между 0f и 1f.

большое спасибо

буйство

PS: Скриншоты, снятые через eclipse с телефона под управлением Android 2.3.

PPS: Я также проверял звуки с различными другими игроками (например, winamp), и там я вижу правильное поведение спектра.

У меня есть хороший результат, используя следующие вычисления, для получения визуализатора, подобного этому изображению. Я использую почти 19 изображений для отображения, подобных этому. Они отвечают на вход метода getFFT (). И обязательно включайте как эквалайзер, так и визуализатор. В противном случае он дает высокие значения, а значения fft отвечают на объем устройства. Фактически я не могу Дать объяснение кода из-за моего english.so в прошлом коде здесь.

VisualizerView:

 public class VisualizerView extends View { private byte[] mBytes; private float[] mPoints; Paint mForePaint = new Paint(); // private int width;// height; private Paint mPaint; Bitmap mBmpArray[]; int wTilesize; int hTilesize; int no_of_colomuns; private Bitmap peakBitmap; private float changeFromTop, changeFromLeft; private int images_drawn_starting_point ; int magnitudePoints[]; int max[] = new int[34]; int temp[]=new int[32]; private final int[][] images = { { R.drawable.blue_fade_1, R.drawable.blue_fade_2, R.drawable.blue_fade_3, R.drawable.blue_fade_4, R.drawable.blue_fade_5, R.drawable.blue_fade_6, R.drawable.blue_fade_7, R.drawable.blue_fade_8, R.drawable.blue_fade_9, R.drawable.blue_fade_10, R.drawable.blue_fade_11, R.drawable.blue_fade_12, R.drawable.blue_fade_13, R.drawable.blue_fade_14, R.drawable.blue_fade_15, R.drawable.blue_fade_16, R.drawable.blue_fade_17, R.drawable.blue_fade_18, R.drawable.blue_fade_19 }}; private final int IMAGES_LENTH = 19; public VisualizerView(Context context) { super(context); mBmpArray = new Bitmap[20]; init(); } public VisualizerView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public VisualizerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); images_drawn_starting_point = h; int temp; wTilesize = w / 34; // hTilesize = h / 30; temp = h - ((IMAGES_LENTH - 1) ); hTilesize = temp / (IMAGES_LENTH ); no_of_colomuns = ( w / (wTilesize)); magnitudePoints = new int[no_of_colomuns]; changeFromLeft = wTilesize + 3f;//For spacing left changeFromTop = hTilesize + 2.5f;//For spacing Right } public void init() { mPaint = new Paint(); mPaint.setColor(Color.BLACK); mPaint.setStrokeWidth(5f); } @Override public void draw(Canvas canvas) { super.draw(canvas); int h = canvas.getHeight(); int w = canvas.getWidth(); canvas.drawRect(new Rect(0, 0, w, h), mPaint); if (mBytes == null) { return; } if (mPoints == null || mPoints.length < mBytes.length * 4) { mPoints = new float[mBytes.length * 4]; } double magnitude; //VisualizerActivity.THEME_COLOR=0 for (int j = 0; j < IMAGES_LENTH; j++) loadTile(j,getResources().getDrawable(images[VisualizerActivity.THEME_COLOR][j])); for (int i = 0; i < no_of_colomuns; i++) { byte rfk = mBytes[2 * i]; byte ifk = mBytes[2 * i + 1]; magnitude = ((rfk * rfk + ifk * ifk)); int dbValue = (int) (10 * Math.log10(magnitude)); magnitude = Math.round(dbValue * 8); try { magnitudePoints[i] = (int) magnitude; } catch (Exception e) { e.printStackTrace(); } } int left; int top; int index; try { index = 0; left = 0; int m = 1; if (VisualizerActivity.THEME_STYLE == 0) { // common for (int i = 0; i < no_of_colomuns; i++) { top = images_drawn_starting_point; index = 18; for (int j = 0; j < IMAGES_LENTH; j++) { if (j > magnitudePoints[m] / IMAGES_LENTH) { canvas.drawBitmap(mBmpArray[0], left, top, mPaint); index++; } else { canvas.drawBitmap(mBmpArray[index--], left, top, mPaint); } top -= changeFromTop;// hTilesize+1.5; } m++; left += changeFromLeft;// wTilesize+2.5; } } } catch (Exception e) { e.getMessage(); } } public void loadTile(int key, Drawable tile) { try { Bitmap bitmap = Bitmap.createBitmap(wTilesize, hTilesize, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); tile.setBounds(0, 0, wTilesize, hTilesize); tile.draw(canvas); mBmpArray[key] = bitmap; } catch (Exception e) { e.printStackTrace(); } } public void updateVisualizerWithFft(byte[] bytes) { if (AudioPlayer.player != null) { if (AudioPlayer.player.isPlaying()) { mBytes = bytes; } } invalidate(); } } 

В VisualizerActivity.java:

 AudioPlayer.mVisualizer.setCaptureSize(Visualizer .getCaptureSizeRange()[1]); AudioPlayer.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) { mVisualizerView.updateVisualizerWithFft(bytes); } }, Visualizer.getMaxCaptureRate() / 2, false, true);