轉載請標明出處:http://blog.csdn.net/sctu_vroy/article/details/45871823
功能:加載本地SD卡中moveDsp文件夾中的音頻文件(包括錄音獲取文件和MP3文件),播放實時FFT,繪制出信號的時域和頻域波形。
設計步驟:
第一步:頁面布局,編寫錄音工具類URecorder(設置錄音屬性)和接口IVoiceManager
- public class URecorder implements IVoiceManager{
- private static final String TAG = "URecorder";
- private Context context = null;
- private String path = null;
- private MediaRecorder mRecorder = null;
- public URecorder(Context context, String path) {
- this.context = context;
- this.path = path;
- mRecorder = new MediaRecorder();
- }
- @Override
- public boolean start() {
- //設置音源為Micphone
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- //設置封裝格式
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setOutputFile(path);
- //設置編碼格式
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- try {
- mRecorder.prepare();
- } catch (IOException e) {
- Log.e(TAG, "prepare() failed");
- }
- //錄音
- mRecorder.start();
- return false;
- }
- @Override
- public boolean stop() {
- mRecorder.stop();
- mRecorder.release();
- mRecorder = null;
- return false;
- }
- }
- public interface IVoiceManager {
- public boolean start();
- public boolean stop();
- }
時域波形顯示類:
- public class VisualizerView extends View {
- private byte[] mBytes;
- private float[] mPoints;
- private Rect mRect = new Rect();
- private Paint mForePaint = new Paint();
- public VisualizerView(Context context) {
- super(context);
- init();
- }
- /**
- * 初始化
- */
- private void init() {
- mBytes = null;
- mForePaint.setStrokeWidth(1f);
- mForePaint.setAntiAlias(true);
- mForePaint.setColor(Color.GREEN);
- }
- public void updateVisualizer(byte[] waveForm)
- {
- mBytes = waveForm;
- invalidate();
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mBytes == null)
- {
- return;
- }
- if (mPoints == null || mPoints.length < mBytes.length * 4)
- {
- mPoints = new float[mBytes.length * 4];
- }
- mRect.set(0, 0, getWidth(), getHeight());
- //繪制波形
- for (int i = 0; i < mBytes.length - 1; i++) {
- mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
- mPoints[i * 4 + 1] = mRect.height() / 2
- + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;
- mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);
- mPoints[i * 4 + 3] = mRect.height() / 2
- + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128;
- }
- canvas.drawLines(mPoints, mForePaint);
- }
- }
- public class VisualizerFFTView extends View {
- private byte[] mBytes;
- private float[] mPoints;
- private Rect mRect = new Rect();
- private Paint mForePaint = new Paint();
- private int mSpectrumNum = 48;
- public VisualizerFFTView(Context context) {
- super(context);
- init();
- }
- /**
- * 初始化
- */
- private void init() {
- mBytes = null;
- mForePaint.setStrokeWidth(8f);
- mForePaint.setAntiAlias(true);
- mForePaint.setColor(Color.rgb(0, 128, 255));
- }
- public void updateVisualizer(byte[] fft)
- {
- byte[] model = new byte[fft.length / 2 + 1];
- model[0] = (byte) Math.abs(fft[0]);
- for (int i = 2, j = 1; j < mSpectrumNum;)
- {
- model[j] = (byte) Math.hypot(fft[i], fft[i + 1]);
- i += 2;
- j++;
- }
- mBytes = model;
- invalidate();
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mBytes == null)
- {
- return;
- }
- if (mPoints == null || mPoints.length < mBytes.length * 4)
- {
- mPoints = new float[mBytes.length * 4];
- }
- mRect.set(0, 0, getWidth(), getHeight());
- //繪制頻譜
- final int baseX = mRect.width()/mSpectrumNum;
- final int height = mRect.height();
- for (int i = 0; i < mSpectrumNum ; i++)
- {
- if (mBytes[i] < 0)
- {
- mBytes[i] = 127;
- }
- final int xi = baseX*i + baseX/2;
- mPoints[i * 4] = xi;
- mPoints[i * 4 + 1] = height;
- mPoints[i * 4 + 2] = xi;
- mPoints[i * 4 + 3] = height - mBytes[i];
- }
- canvas.drawLines(mPoints, mForePaint);
- }
- }
- //uri = Uri.parse(AudioPath); // 解析錄音文件路徑到uri
- uri = Uri.parse(Mp3Path); // 解析MP3文件路徑到uri
- mMedia = MediaPlayer.create(this, uri); // 實例化mMedia對象,並通過uri將資源文件加載到該對象
調用Android SDK 2.3以上版本中一個工具包android.media.audiofx.Visualizer,程序需要做的就是實例化一個Visualizer對象,通過獲得一個實例化的音頻媒體類對象的SessionId,並設置該對象的需要轉換的音樂內容長度和采樣率。最后為visualizer設置監聽器setDataCaptureListener(OnDataCaptureListener listener, rate, iswave, isfft),當采樣得到的數據長度達到之前設置的內容長度后,將會觸發兩個函數,在這兩個函數中即可分別得到音頻信號的時域信號數據以及經過快速傅里葉變換(FFT)處理的頻域信號數據,均為字節數組形式(即:byte[])。
- mWaveView = new VisualizerView(this); // 創建VisualizerView對象
- mFFtView = new VisualizerFFTView(this); // 創建VisualizerFFTView對象
- final int maxCR = Visualizer.getMaxCaptureRate(); // 獲取最大采樣率
- mVisualizer = new Visualizer(mMedia.getAudioSessionId()); // 實例化mVisualizer
- mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]); // 設置內容長度為1024
- mVisualizer.setDataCaptureListener(
- new Visualizer.OnDataCaptureListener()
- {
- public void onWaveFormDataCapture(Visualizer visualizer,
- byte[] waveform, int samplingRate)
- {
- mWaveView.updateVisualizer(waveform); // 更新時域波形數據
- }
- public void onFftDataCapture(Visualizer visualizer,
- byte[] fft, int samplingRate)
- {
- mFFtView.updateVisualizer(fft); // 更新頻域波形數據
- }
- }, maxCR / 2, true, true); // 采樣速率為512MHz,設置同時獲取時域、頻域波形數據
音頻信號FFT效果圖:

源碼下載鏈接: