Android实现播放音频时的跳动频谱,并实现可以调节的均衡器。
Main.java
- packagecom.wjq.audiofx;
- importandroid.app.Activity;
- importandroid.media.AudioManager;
- importandroid.media.MediaPlayer;
- importandroid.media.audiofx.Equalizer;
- importandroid.media.audiofx.Visualizer;
- importandroid.os.Bundle;
- importandroid.util.Log;
- importandroid.view.Gravity;
- importandroid.view.ViewGroup;
- importandroid.widget.LinearLayout;
- importandroid.widget.SeekBar;
- importandroid.widget.TextView;
- publicclassMainextendsActivity{
- privatestaticfinalStringTAG="AudioFxDemo";
- privatestaticfinalfloatVISUALIZER_HEIGHT_DIP=50f;
- privateMediaPlayermMediaPlayer;
- privateVisualizermVisualizer;
- privateEqualizermEqualizer;//均横器
- privateLinearLayoutmLinearLayout;
- VisualizerViewmVisualizerView;
- privateTextViewmStatusTextView;
- @Override
- publicvoidonCreate(Bundleicicle){
- super.onCreate(icicle);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
- mStatusTextView=newTextView(this);
- mLinearLayout=newLinearLayout(this);
- mLinearLayout.setOrientation(LinearLayout.VERTICAL);
- mLinearLayout.addView(mStatusTextView);
- setContentView(mLinearLayout);
- //CreatetheMediaPlayer
- mMediaPlayer=MediaPlayer.create(this,R.raw.test_cbr);
- if(null==mMediaPlayer)
- return;
- Log.d(TAG,"MediaPlayeraudiosessionID:"+mMediaPlayer.getAudioSessionId());
- setupVisualizerFxAndUI();
- setupEqualizerFxAndUI();
- //Makesurethevisualizerisenabledonlywhenyouactuallywanttoreceivedata,and
- //whenitmakessensetoreceivedata.
- mVisualizer.setEnabled(true);
- //Whenthestreamends,wedon'tneedtocollectanymoredata.Wedon'tdothisin
- //setupVisualizerFxAndUIbecausewelikelywanttohavemore,non-Visualizerrelatedcode
- //inthiscallback.
- mMediaPlayer.setOnCompletionListener(newMediaPlayer.OnCompletionListener(){
- publicvoidonCompletion(MediaPlayermediaPlayer){
- mVisualizer.setEnabled(false);
- }
- });
- mMediaPlayer.start();
- mStatusTextView.setText("播放音频...");
- }
- /**
- *通过mMediaPlayer返回的AudioSessionId创建一个优先级为0均衡器对象,并且通过频谱生成相应的UI和对应的事件
- */
- privatevoidsetupEqualizerFxAndUI(){
- mEqualizer=newEqualizer(0,mMediaPlayer.getAudioSessionId());
- //启用均衡器
- mEqualizer.setEnabled(true);
- TextVieweqTextView=newTextView(this);
- eqTextView.setText("均横器:");
- mLinearLayout.addView(eqTextView);
- //通过均衡器得到其支持的频谱引擎
- shortbands=mEqualizer.getNumberOfBands();
- //getBandLevelRange是一个数组,返回一组频谱等级数组,返回一组频谱等级数组
- //第一个下标为最低的限度范围,第二个下标为最高的限度范围
- //依次取出
- finalshortminEQLevel=mEqualizer.getBandLevelRange()[0];
- finalshortmaxEQLevel=mEqualizer.getBandLevelRange()[1];
- for(shorti=0;i<bands;i++){
- finalshortband=i;
- TextViewfreqTextView=newTextView(this);
- freqTextView.setLayoutParams(newViewGroup.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
- freqTextView.setText((mEqualizer.getCenterFreq(band)/1000)+"Hz");
- mLinearLayout.addView(freqTextView);
- LinearLayoutrow=newLinearLayout(this);
- row.setOrientation(LinearLayout.HORIZONTAL);
- TextViewminDbTextView=newTextView(this);
- minDbTextView.setLayoutParams(newViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- minDbTextView.setText((minEQLevel/100)+"dB");
- TextViewmaxDbTextView=newTextView(this);
- maxDbTextView.setLayoutParams(newViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- maxDbTextView.setText((maxEQLevel/100)+"dB");
- LinearLayout.LayoutParamslayoutParams=newLinearLayout.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- layoutParams.weight=1;
- SeekBarbar=newSeekBar(this);
- bar.setLayoutParams(layoutParams);
- bar.setMax(maxEQLevel-minEQLevel);
- bar.setProgress(mEqualizer.getBandLevel(band));
- bar.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener(){
- publicvoidonStopTrackingTouch(SeekBarseekBar){}
- publicvoidonStartTrackingTouch(SeekBarseekBar){}
- publicvoidonProgressChanged(SeekBarseekBar,intprogress,
- booleanfromUser){
- mEqualizer.setBandLevel(band,(short)(progress+minEQLevel));
- }
- });
- row.addView(minDbTextView);
- row.addView(bar);
- row.addView(maxDbTextView);
- mLinearLayout.addView(row);
- }
- }
- /**
- *生成一个VisualizerView对象,使音频频谱的波段能够反映到VisualizerView上
- */
- privatevoidsetupVisualizerFxAndUI(){
- mVisualizerView=newVisualizerView(this);
- mVisualizerView.setLayoutParams(newViewGroup.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- (int)(VISUALIZER_HEIGHT_DIP*getResources().getDisplayMetrics().density)));
- mLinearLayout.addView(mVisualizerView);
- intsessId=mMediaPlayer.getAudioSessionId();
- mVisualizer=newVisualizer(sessId);
- //参数必须是2的位数
- mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
- //设置允许波形表示,并且捕获它
- mVisualizer.setDataCaptureListener(newVisualizer.OnDataCaptureListener(){
- publicvoidonWaveFormDataCapture(Visualizervisualizer,byte[]bytes,
- intsamplingRate){
- mVisualizerView.updateVisualizer(bytes);
- }
- publicvoidonFftDataCapture(Visualizervisualizer,byte[]bytes,intsamplingRate){}
- },Visualizer.getMaxCaptureRate()/2,true,false);
- }
- @Override
- protectedvoidonPause(){
- super.onPause();
- if(isFinishing()&&mMediaPlayer!=null){
- mVisualizer.release();
- mEqualizer.release();
- mMediaPlayer.release();
- mMediaPlayer=null;
- }
- }
- }
VisualizerView.java
- packagecom.wjq.audiofx;
- importandroid.content.Context;
- importandroid.graphics.Canvas;
- importandroid.graphics.Color;
- importandroid.graphics.Paint;
- importandroid.graphics.Rect;
- importandroid.view.View;
- publicclassVisualizerViewextendsView{
- privatebyte[]mBytes;
- privatefloat[]mPoints;
- //矩形区域
- privateRectmRect=newRect();
- //画笔
- privatePaintmForePaint=newPaint();
- //初始化画笔
- privatevoidinit(){
- mBytes=null;
- mForePaint.setStrokeWidth(1f);
- mForePaint.setAntiAlias(true);
- mForePaint.setColor(Color.GREEN);
- }
- publicVisualizerView(Contextcontext){
- super(context);
- init();
- }
- publicvoidupdateVisualizer(byte[]bytes){
- mBytes=bytes;
- invalidate();
- }
- @Override
- protectedvoidonDraw(Canvascanvas){
- super.onDraw(canvas);
- if(mBytes==null){
- return;
- }
- if(mPoints==null||mPoints.length<mBytes.length*4){
- mPoints=newfloat[mBytes.length*4];
- }
- mRect.set(0,0,getWidth(),getHeight());
- for(inti=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);
- }
- }