2

ビジュアライザーを使用して、再生中のサウンド ファイルのビジュアライゼーションを描画しています。音波が表示されていますが、フレームレートに影響するため、詳細を減らしたいと思います。これに関するドキュメントは非常に限られています。だから私は次のことを試みました:

mVisualizer.setCaptureSize(2);

キャプチャ レートを非常に低い値に設定します。ただし、線は同じ量の詳細で描かれているように見えます。ドキュメントで次のことを読みました。

Sets the capture size, i.e. the number of bytes returned by getWaveForm(byte[]) and getFft(byte[]) methods.

私が抱えているもう1つの問題は、再生中のサウンドファイルでエネルギーレベルの高いサウンドを検出して、それらを画面上で視覚的に表現できるようにしたいということです。例: 画面がベースラインと共に点滅します。これが私がこれまでに持っているものです:

public static void setupVisualizer() {
    mVisualizer = new Visualizer(mpSong.getAudioSessionId());
    mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
    mVisualizer.setDataCaptureListener(
            new Visualizer.OnDataCaptureListener() {
                public void onWaveFormDataCapture(Visualizer visualizer,
                        byte[] bytes, int samplingRate) {
                    Game.updateVisualizer(bytes);
                }

                public void onFftDataCapture(Visualizer visualizer,
                        byte[] bytes, int samplingRate) {
                }
            }, Visualizer.getMaxCaptureRate() / 2, true, false);
}

このリスナー内の特定の音を検出することは可能ですか? または、代替手段は何ですか?私の悪い英語でごめんなさい。お時間いただきまして誠にありがとうございました。

4

1 に答える 1

6

数時間のテストと調査の後、解決策を見つけました。あまり正確ではないかもしれませんが、私が思いついた唯一の選択肢です。BeatDetector というクラスを作成しました。

public class BeatDetectorByFrequency {
private static final String TAG = "TEST";

private Visualizer mVisualizer = null;

private double mRunningSoundAvg[];
private double mCurrentAvgEnergyOneSec[];
private int mNumberOfSamplesInOneSec;
private long mSystemTimeStartSec;
// FREQS
private static final int LOW_FREQUENCY = 300;
private static final int MID_FREQUENCY = 2500;
private static final int HIGH_FREQUENCY = 10000;
private OnBeatDetectedListener onBeatDetectedListener = null;

public BeatDetectorByFrequency() {
    init();
}

private void init() {
    mRunningSoundAvg = new double[3];
    mCurrentAvgEnergyOneSec = new double[3];
    mCurrentAvgEnergyOneSec[0] = -1;
    mCurrentAvgEnergyOneSec[1] = -1;
    mCurrentAvgEnergyOneSec[2] = -1;
}

public void link(MediaPlayer player) {
    if (player == null) {
        throw new NullPointerException("Cannot link to null MediaPlayer");
    }
    mVisualizer = new Visualizer(player.getAudioSessionId());
    mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);

    Visualizer.OnDataCaptureListener captureListener = new Visualizer.OnDataCaptureListener() {
        @Override
        public void onWaveFormDataCapture(Visualizer visualizer,
                byte[] bytes, int samplingRate) {
            // DO NOTHING
        }

        @Override
        public void onFftDataCapture(Visualizer visualizer, byte[] bytes,
                int samplingRate) {
            updateVisualizerFFT(bytes);
        }
    };

    mVisualizer.setDataCaptureListener(captureListener,
            Visualizer.getMaxCaptureRate() / 2, false, true);
    mVisualizer.setEnabled(true);
    player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            mVisualizer.setEnabled(false);
        }
    });
    mSystemTimeStartSec = System.currentTimeMillis();
}

public void release() {
    if (mVisualizer != null) {
        mVisualizer.setEnabled(false);
        mVisualizer.release();
    }
}

public void pause() {
    if (mVisualizer != null) {
        mVisualizer.setEnabled(false);
    }
}

public void resume() {
    if (mVisualizer != null) {
        mVisualizer.setEnabled(true);
    }
}

public void updateVisualizerFFT(byte[] audioBytes) {
    int energySum = 0;
    energySum += Math.abs(audioBytes[0]);
    int k = 2;
    double captureSize = mVisualizer.getCaptureSize() / 2;
    int sampleRate = mVisualizer.getSamplingRate() / 2000;
    double nextFrequency = ((k / 2) * sampleRate) / (captureSize);
    while (nextFrequency < LOW_FREQUENCY) {
        energySum += Math.sqrt((audioBytes[k] * audioBytes[k])
                * (audioBytes[k + 1] * audioBytes[k + 1]));
        k += 2;
        nextFrequency = ((k / 2) * sampleRate) / (captureSize);
    }
    double sampleAvgAudioEnergy = (double) energySum
            / (double) ((k * 1.0) / 2.0);

    mRunningSoundAvg[0] += sampleAvgAudioEnergy;
    if ((sampleAvgAudioEnergy > mCurrentAvgEnergyOneSec[0])
            && (mCurrentAvgEnergyOneSec[0] > 0)) {
        fireBeatDetectedLowEvent(sampleAvgAudioEnergy);
    }
    energySum = 0;
    while (nextFrequency < MID_FREQUENCY) {
        energySum += Math.sqrt((audioBytes[k] * audioBytes[k])
                * (audioBytes[k + 1] * audioBytes[k + 1]));
        k += 2;
        nextFrequency = ((k / 2) * sampleRate) / (captureSize);
    }

    sampleAvgAudioEnergy = (double) energySum / (double) ((k * 1.0) / 2.0);
    mRunningSoundAvg[1] += sampleAvgAudioEnergy;
    if ((sampleAvgAudioEnergy > mCurrentAvgEnergyOneSec[1])
            && (mCurrentAvgEnergyOneSec[1] > 0)) {
        fireBeatDetectedMidEvent(sampleAvgAudioEnergy);
    }
    energySum = Math.abs(audioBytes[1]);

    while ((nextFrequency < HIGH_FREQUENCY) && (k < audioBytes.length)) {
        energySum += Math.sqrt((audioBytes[k] * audioBytes[k])
                * (audioBytes[k + 1] * audioBytes[k + 1]));
        k += 2;
        nextFrequency = ((k / 2) * sampleRate) / (captureSize);
    }

    sampleAvgAudioEnergy = (double) energySum / (double) ((k * 1.0) / 2.0);
    mRunningSoundAvg[2] += sampleAvgAudioEnergy;
    if ((sampleAvgAudioEnergy > mCurrentAvgEnergyOneSec[2])
            && (mCurrentAvgEnergyOneSec[2] > 0)) {
        fireBeatDetectedHighEvent(sampleAvgAudioEnergy);
    }

    mNumberOfSamplesInOneSec++;
    if ((System.currentTimeMillis() - mSystemTimeStartSec) > 1000) {
        mCurrentAvgEnergyOneSec[0] = mRunningSoundAvg[0]
                / mNumberOfSamplesInOneSec;
        mCurrentAvgEnergyOneSec[1] = mRunningSoundAvg[1]
                / mNumberOfSamplesInOneSec;
        mCurrentAvgEnergyOneSec[2] = mRunningSoundAvg[2]
                / mNumberOfSamplesInOneSec;
        mNumberOfSamplesInOneSec = 0;
        mRunningSoundAvg[0] = 0.0;
        mRunningSoundAvg[1] = 0.0;
        mRunningSoundAvg[2] = 0.0;
        mSystemTimeStartSec = System.currentTimeMillis();
    }
}

// USE INTERFACES IN NEXT UPDATE:
private void fireBeatDetectedLowEvent(double power) {
    // Utility.log("LOW BEAT DETECTED!");
    Game.lowBeat(power);
    if (onBeatDetectedListener != null) {
        onBeatDetectedListener.onBeatDetectedLow();
    }
}

private void fireBeatDetectedMidEvent(double power) {
    // Utility.log("MEDIUM BEAT DETECTED!");
    Game.mediumBeat(power);
    if (onBeatDetectedListener != null) {
        onBeatDetectedListener.onBeatDetectedMid();
    }
}

private void fireBeatDetectedHighEvent(double power) {
    // Utility.log("HIGH BEAT DETECTED!");
    Game.highBeat(power);
    if (onBeatDetectedListener != null) {
        onBeatDetectedListener.onBeatDetectedHigh();
    }
}

public void setOnBeatDetectedListener(OnBeatDetectedListener listener) {
    onBeatDetectedListener = listener;
}

public interface OnBeatDetectedListener {
    public abstract void onBeatDetectedLow();

    public abstract void onBeatDetectedMid();

    public abstract void onBeatDetectedHigh();
}
}

MediaPlayer オブジェクトをパラメーターとして受け取り、バイト データの EnergySum に基づいて 3 つの異なる周波数を計算します。周波数を何度でも分割できます。それぞれがリスナーを持つ周波数の配列を作成することを検討していました。次に、以下を使用して長方形を描画しました。

public static void highBeat(double power) {
    HIGH_FREQUENCY += (power * 1000); // ORIGINAL: * 1000
    if (HIGH_FREQUENCY > GameValues.FREQ_MAX) {
        HIGH_FREQUENCY = GameValues.FREQ_MAX;
    }
    updateHighFreq();
}

public static void updateHighFreq() {
    prcnt = HIGH_FREQUENCY * 100 / GameValues.FREQ_MAX;
    if (prcnt < 0)
        prcnt = 0;
    HIGH_F_HEIGHT = (int) (GameValues.FREQ_MAX_HEIGHT * (prcnt / 100));
}

これは、バーの最大電力と最大高さに基づいてパーセンテージを計算することにより、長方形の高さを計算します。あまり正確ではありませんが、私が思いついた最高のものです。繰り返しますが、これは好きなだけ多くの周波数に対して行うことができます。ここに私を助けたいくつかのリンクがあります:

https://android.googlesource.com/platform/cts/+/master/tests/tests/media/src/android/media/cts/VisualizerTest.java

https://www.codota.com/android/scenarios/518916b8da0af8330dfa9398/android.media.audiofx.Visualizer?tag=out_2013_05_05_07_19_34

これらの問題で他の誰かを助けることができることを願っています。

于 2014-12-22T22:42:55.263 に答える