2014-12-22 16 views
2

저는 Visualizer를 사용하여 내가 연주하고있는 사운드 파일의 시각화를 그려 왔습니다. 음파가 표시되지만 내 프레임 속도에 영향을 미치므로 덜 자세하게 만들고 싶습니다. 이에 대한 문서는 매우 제한적입니다. 그래서 나는 다음을 시도했습니다 :Android Visualizer Detect Beat? 그리고 Visualizer.setCaptureSize()가 작동하지 않습니까? 대안?

mVisualizer.setCaptureSize(2); 

캡처 속도를 매우 낮게 설정하려면 다음을 수행하십시오. 그러나 선이 같은 양의 세부 묘사로 그려지고있는 것으로 보입니다.

Sets the capture size, i.e. the number of bytes returned by getWaveForm(byte[]) and getFft(byte[]) methods. 
은 내가,이 내가 연주하고 사운드 파일에서 높은 에너지 레벨로 소리를 감지하고 싶다고 또 다른 문제는 그래서 시각적으로 그들을 표시 할 수

: 나는 그 문서에 읽고 화면. 예 : 화면이 기준선과 함께 깜박입니다. 다음은 지금까지 내가 가지고있는 것입니다 :

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); 
} 

이 청취자 내부의 특정 소리를 감지 할 수 있습니까? 또는 대안은 무엇입니까? 나쁜 영어로 죄송합니다. 당신의 시간 친구를 위해 대단히 당신을 감사하십시오.

답변

3

몇 시간의 테스트 및 리서치 후 나는 해결책을 찾았습니다. 그것은 정확하지 않을 수도 있지만, 내가 생각해 낼 수있는 유일한 대안입니다. 나는 BeatDetector라는 클래스했다 : 그것은 매개 변수로 MediaPlayer를 객체를 사용

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(); 
} 
} 

를 다음 바이트 데이터의 EnergySum을 바탕으로 세 가지 서로 다른 주파수를 계산합니다. 원하는만큼 여러 번 주파수를 분할 할 수 있습니다. 나는 각각의 리스너가있는 주파수 배열 만들기를 고려하고있었습니다.

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

희망 나는이 문제에 다른 사람을 도울 수 있습니다.