Android編程之播放器MediaPlayer實(shí)現(xiàn)均衡器效果示例
本文實(shí)例講述了Android播放器MediaPlayer實(shí)現(xiàn)均衡器效果。分享給大家供大家參考,具體如下:
這幾天在系統(tǒng)學(xué)習(xí)Android官方API Demos,看到實(shí)現(xiàn)均衡器效果,就把官方API中代碼copy下來(lái),根據(jù)網(wǎng)上前輩的指引略有修改,添加了注釋。
public class AudioFxDemo extends Activity { private static final String TAG = "AudioFxDemo"; private static final float VISUALIZER_HEIGHT_DIP = 50f; // 定義播放器 private MediaPlayer mMediaPlayer; // 定義系統(tǒng)的頻譜 private Visualizer mVisualizer; // 定義系統(tǒng)的均衡器 private Equalizer mEqualizer; private LinearLayout mLinearLayout; private VisualizerView mVisualizerView; private TextView mStatusTextView; @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); // 音量控制 setVolumeControlStream(AudioManager.STREAM_MUSIC); mStatusTextView = new TextView(this); mLinearLayout = new LinearLayout(this); mLinearLayout.setOrientation(LinearLayout.VERTICAL); mLinearLayout.addView(mStatusTextView); setContentView(mLinearLayout); // 創(chuàng)建MediaPlayer對(duì)象 mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr); Log.d(TAG, "MediaPlayer audio session ID: " + mMediaPlayer.getAudioSessionId()); // 設(shè)置頻譜顯示 setupVisualizerFxAndUI(); // 設(shè)置示波器顯示 setupEqualizerFxAndUI(); // Make sure the visualizer is enabled only when you actually want to // receive data, and // when it makes sense to receive data. mVisualizer.setEnabled(true); // When the stream ends, we don't need to collect any more data. We // don't do this in // setupVisualizerFxAndUI because we likely want to have more, // non-Visualizer related code // in this callback. mMediaPlayer .setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mediaPlayer) { mVisualizer.setEnabled(false); mStatusTextView.setText("播放結(jié)束"); } }); mMediaPlayer.start(); mStatusTextView.setText("正在播放中"); } private void setupEqualizerFxAndUI() { // Create the Equalizer object (an AudioEffect subclass) and attach it // to our media player, // with a default priority (0). mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId()); mEqualizer.setEnabled(true); TextView eqTextView = new TextView(this); eqTextView.setText("Equalizer:"); mLinearLayout.addView(eqTextView); short bands = mEqualizer.getNumberOfBands(); final short minEQLevel = mEqualizer.getBandLevelRange()[0]; final short maxEQLevel = mEqualizer.getBandLevelRange()[1]; for (short i = 0; i < bands; i++) { final short band = i; TextView freqTextView = new TextView(this); freqTextView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); freqTextView.setGravity(Gravity.CENTER_HORIZONTAL); freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz"); mLinearLayout.addView(freqTextView); LinearLayout row = new LinearLayout(this); row.setOrientation(LinearLayout.HORIZONTAL); TextView minDbTextView = new TextView(this); minDbTextView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); minDbTextView.setText((minEQLevel / 100) + " dB"); TextView maxDbTextView = new TextView(this); maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); maxDbTextView.setText((maxEQLevel / 100) + " dB"); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.weight = 1; SeekBar bar = new SeekBar(this); bar.setLayoutParams(layoutParams); bar.setMax(maxEQLevel - minEQLevel); bar.setProgress(mEqualizer.getBandLevel(band)); bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mEqualizer.setBandLevel(band, (short) (progress + minEQLevel)); } public void onStartTrackingTouch(SeekBar seekBar) { } public void onStopTrackingTouch(SeekBar seekBar) { } }); row.addView(minDbTextView); row.addView(bar); row.addView(maxDbTextView); mLinearLayout.addView(row); } } private void setupVisualizerFxAndUI() { // Create a VisualizerView (defined below), which will render the // simplified audio // wave form to a Canvas. mVisualizerView = new VisualizerView(this); mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, (int) (VISUALIZER_HEIGHT_DIP * getResources() .getDisplayMetrics().density))); mLinearLayout.addView(mVisualizerView); // Create the Visualizer object and attach it to our media player. mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId()); mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]); 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) { } }, Visualizer.getMaxCaptureRate() / 2, true, false); } @Override protected void onPause() { super.onPause(); if (isFinishing() && mMediaPlayer != null) { mVisualizer.release(); mEqualizer.release(); mMediaPlayer.release(); mMediaPlayer = null; } } } /** * 繪制波狀View * * @description: * @author ldm * @date 2016-4-20 上午9:11:49 */ class VisualizerView extends View { // 數(shù)組保存了波形抽樣點(diǎn)的值 private byte[] bytes; private float[] points; // 定義畫(huà)筆 private Paint paint = new Paint(); // 矩形區(qū)域 private Rect rect = new Rect(); private byte type = 0; public VisualizerView(Context context) { super(context); bytes = null; // 設(shè)置畫(huà)筆的屬性 paint.setStrokeWidth(1f);// 設(shè)置空心線寬 paint.setAntiAlias(true);// 抗鋸齒 paint.setColor(Color.BLUE);// 畫(huà)筆顏色 paint.setStyle(Style.STROKE);// 非填充模式 } public void updateVisualizer(byte[] ftt) { bytes = ftt; // 通知組件重繪 invalidate(); } @Override public boolean onTouchEvent(MotionEvent me) { // 當(dāng)用戶(hù)觸碰該組件時(shí),切換波形類(lèi)型 if (me.getAction() != MotionEvent.ACTION_DOWN) { return false; } type++; if (type >= 3) { type = 0; } return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (bytes == null) { return; } // 繪制黑色背景 canvas.drawColor(Color.BLACK); // 使用rect對(duì)象記錄該組件的寬度和高度 rect.set(0, 0, getWidth(), getHeight()); switch (type) { // 繪制塊狀的波形圖 case 0: for (int i = 0; i < bytes.length - 1; i++) { float left = getWidth() * i / (bytes.length - 1); // 根據(jù)波形值計(jì)算該矩形的高度 float top = rect.height() - (byte) (bytes[i + 1] + 128) * rect.height() / 128; float right = left + 1; float bottom = rect.height(); canvas.drawRect(left, top, right, bottom, paint); } break; // 繪制柱狀的波形圖(每隔18個(gè)抽樣點(diǎn)繪制一個(gè)矩形) case 1: for (int i = 0; i < bytes.length - 1; i += 18) { float left = rect.width() * i / (bytes.length - 1); // 根據(jù)波形值計(jì)算該矩形的高度 float top = rect.height() - (byte) (bytes[i + 1] + 128) * rect.height() / 128; float right = left + 6; float bottom = rect.height(); canvas.drawRect(left, top, right, bottom, paint); } break; // -繪制曲線波形圖 case 2: // 如果point數(shù)組還未初始化 if (points == null || points.length < bytes.length * 4) { points = new float[bytes.length * 4]; } for (int i = 0; i < bytes.length - 1; i++) { // 計(jì)算第i個(gè)點(diǎn)的x坐標(biāo) points[i * 4] = rect.width() * i / (bytes.length - 1); // 根據(jù)bytes[i]的值(波形點(diǎn)的值)計(jì)算第i個(gè)點(diǎn)的y坐標(biāo) points[i * 4 + 1] = (rect.height() / 2) + ((byte) (bytes[i] + 128)) * 128 / (rect.height() / 2); // 計(jì)算第i+1個(gè)點(diǎn)的x坐標(biāo) points[i * 4 + 2] = rect.width() * (i + 1) / (bytes.length - 1); // 根據(jù)bytes[i+1]的值(波形點(diǎn)的值)計(jì)算第i+1個(gè)點(diǎn)的y坐標(biāo) points[i * 4 + 3] = (rect.height() / 2) + ((byte) (bytes[i + 1] + 128)) * 128 / (rect.height() / 2); } // 繪制波形曲線 canvas.drawLines(points, paint); break; } } }
自己新建 項(xiàng)目時(shí),記得在res/raw下添加一個(gè)名為test_cbr的mp3格式文件。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Android多媒體操作技巧匯總(音頻,視頻,錄音等)》、《Android開(kāi)發(fā)入門(mén)與進(jìn)階教程》、《Android視圖View技巧總結(jié)》、《Android編程之a(chǎn)ctivity操作技巧總結(jié)》、《Android文件操作技巧匯總》、《Android資源操作技巧匯總》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android音視頻開(kāi)發(fā)之MediaPlayer使用教程
- Android MediaPlayer 音頻倍速播放 調(diào)整播放速度問(wèn)題
- Android MediaPlayer 播放音頻的方式
- Android多媒體應(yīng)用使用MediaPlayer播放音頻
- Android開(kāi)發(fā)之MediaPlayer多媒體(音頻,視頻)播放工具類(lèi)
- Android編程視頻播放API之MediaPlayer用法示例
- Android實(shí)現(xiàn)簡(jiǎn)單音樂(lè)播放器(MediaPlayer)
- Android MediaPlayer音頻播放器封裝示例淺析
相關(guān)文章
Android?Gradle?插件自定義Plugin實(shí)現(xiàn)注意事項(xiàng)
這篇文章主要介紹了Android?Gradle?插件自定義Plugin實(shí)現(xiàn)注意事項(xiàng),文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-06-06android開(kāi)發(fā)教程之a(chǎn)ndroid的handler使用方法
這篇文章主要介紹了android的handler使用方法,大家參考使用吧2014-01-01Android StickyListHeaders實(shí)現(xiàn)電話(huà)本列表效果
這篇文章主要為大家詳細(xì)介紹了Android StickyListHeaders實(shí)現(xiàn)電話(huà)本列表效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05Android獲取分享應(yīng)用列表詳解及實(shí)例
這篇文章主要介紹了Android獲取分享應(yīng)用列表詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-04-04HttpURLConnection和okHttp兩種獲取網(wǎng)絡(luò)數(shù)據(jù)的實(shí)現(xiàn)方法
下面小編就為大家分享一篇HttpURLConnection和okHttp兩種獲取網(wǎng)絡(luò)數(shù)據(jù)的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01淺析Android中build.gradle的實(shí)用技巧
這篇文章主要介紹了淺析Android中build.gradle的實(shí)用技巧,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03