首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 聲音波形/音量即時顯示:MediaRecorder + Visualizer 實現 QQ 按住說話效果

     編輯:程式設計綜合問答

兩種主流方案

方案適用場景優點缺點
MediaRecorder.getMaxAmplitude()錄音/語音輸入時即時音量條API 簡單、無權限顧慮 (已有 RECORD_AUDIO)需輪詢、數值範圍 0~32767 需自行映射
Visualizer (API 9+)播放音樂/系統聲音波形、FFT 頻譜提供波形 (byte[]) 與 FFT (float[])、高效原生需 `MODIFY_AUDIO_SETTINGS` 權限、僅能掛載播放 Session

方案一:MediaRecorder 即時音量 (適合「按住說話」)


public class VoiceLevelMeter {
    private MediaRecorder recorder;
    private Runnable pollTask;
    private Handler handler = new Handler(Looper.getMainLooper());
    private OnLevelListener listener;

    public interface OnLevelListener {
        void onLevel(float level); // 0.0f ~ 1.0f
    }

    public void start(OnLevelListener listener) {
        this.listener = listener;
        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        recorder.setOutputFile("/dev/null"); // 不存檔
        try {
            recorder.prepare();
            recorder.start();
        } catch (IOException e) { e.printStackTrace(); return; }

        pollTask = new Runnable() {
            @Override public void run() {
                if (recorder != null) {
                    int amp = recorder.getMaxAmplitude(); // 0~32767
                    float level = Math.min(amp / 32767f, 1f);
                    listener.onLevel(level);
                    handler.postDelayed(this, 50); // 20fps
                }
            }
        };
        handler.post(pollTask);
    }

    public void stop() {
        handler.removeCallbacks(pollTask);
        if (recorder != null) {
            recorder.stop();
            recorder.release();
            recorder = null;
        }
    }
}

使用方式 (按住說話按鈕)


VoiceLevelMeter meter = new VoiceLevelMeter();

btnSpeak.setOnTouchListener((v, event) -> {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            meter.start(level -> {
                // 更新 UI: 波形圖、音量條、圖片縮放等
                waveView.setLevel(level);
            });
            return true;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            meter.stop();
            // 送出語音辨識/上傳
            return true;
    }
    return false;
});

開源專案參考

  • VoiceCurve - 完整波形繪製、貝塞爾曲線平滑、錄音整合。
  • VoiceRecorderView - Material 風格錄音按鈕、波形動畫。

關鍵提醒

  1. **權限**:`RECORD_AUDIO` (危險權限,**運行時請求**)。
  2. **生命週期**:`onPause/onStop` 必須呼叫 `meter.stop()` 釋放 `MediaRecorder`,否則下次啟動失敗。
  3. **數值平滑**:原始振幅波動大,建議用 **EMA (指數移動平均)** 平滑:`smooth = 0.3 * current + 0.7 * prev`。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved