失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android实现音乐示波器 均衡器 重低音和音场功能

Android实现音乐示波器 均衡器 重低音和音场功能

时间:2023-04-28 01:45:25

相关推荐

Android实现音乐示波器 均衡器 重低音和音场功能

本实例来自于《疯狂Android讲义》,要实现具体的功能,需要了解以下API: MediaPlayer 媒体播放器Visualizer 频谱Equalizer 均衡器BassBoost 重低音控制器PresetReverb 预设音场控制器Paint 绘图

来看下效果示意图,如下所示

竖状波形图

块状波形图

曲线波形图

调节均衡器、重低音

选择音场

下面来看具体的实现代码MediaPlayerTest.java

[java]view plain copy print ? packagecom.oyp.media;importjava.util.ArrayList;importjava.util.List;importandroid.app.Activity;importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.Color;importandroid.graphics.Paint;importandroid.graphics.Paint.Style;importandroid.graphics.Rect;importandroid.media.AudioManager;importandroid.media.MediaPlayer;importandroid.media.audiofx.BassBoost;importandroid.media.audiofx.Equalizer;importandroid.media.audiofx.PresetReverb;importandroid.media.audiofx.Visualizer;importandroid.os.Bundle;importandroid.view.Gravity;importandroid.view.MotionEvent;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.AdapterView;importandroid.widget.ArrayAdapter;importandroid.widget.LinearLayout;importandroid.widget.SeekBar;importandroid.widget.Spinner;importandroid.widget.TextView;publicclassMediaPlayerTestextendsActivity{//定义播放声音的MediaPlayerprivateMediaPlayermPlayer;//定义系统的频谱privateVisualizermVisualizer;//定义系统的均衡器privateEqualizermEqualizer;//定义系统的重低音控制器privateBassBoostmBass;//定义系统的预设音场控制器privatePresetReverbmPresetReverb;privateLinearLayoutlayout;privateList<Short>reverbNames=newArrayList<Short>();privateList<String>reverbVals=newArrayList<String>();@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);//设置音频流-STREAM_MUSIC:音乐回放即媒体音量setVolumeControlStream(AudioManager.STREAM_MUSIC);layout=newLinearLayout(this);//代码创建布局layout.setOrientation(LinearLayout.VERTICAL);//设置为线性布局-上下排列setContentView(layout);//将布局添加到Activity//创建MediaPlayer对象,并添加音频//音频路径为res/raw/beautiful.mp3mPlayer=MediaPlayer.create(this,R.raw.beautiful);//初始化示波器setupVisualizer();//初始化均衡控制器setupEqualizer();//初始化重低音控制器setupBassBoost();//初始化预设音场控制器setupPresetReverb();//开发播放音乐mPlayer.start();}/***初始化频谱*/privatevoidsetupVisualizer(){//创建MyVisualizerView组件,用于显示波形图finalMyVisualizerViewmVisualizerView=newMyVisualizerView(this);mVisualizerView.setLayoutParams(newViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int)(120f*getResources().getDisplayMetrics().density)));//将MyVisualizerView组件添加到layout容器中layout.addView(mVisualizerView);//以MediaPlayer的AudioSessionId创建Visualizer//相当于设置Visualizer负责显示该MediaPlayer的音频数据mVisualizer=newVisualizer(mPlayer.getAudioSessionId());//设置需要转换的音乐内容长度,专业的说这就是采样,该采样值一般为2的指数倍,如64,128,256,512,1024。mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);//为mVisualizer设置监听器/**Visualizer.setDataCaptureListener(OnDataCaptureListenerlistener,intrate,booleanwaveform,booleanfft**listener,表监听函数,匿名内部类实现该接口,该接口需要实现两个函数rate,表示采样的周期,即隔多久采样一次,联系前文就是隔多久采样128个数据iswave,是波形信号isfft,是FFT信号,表示是获取波形信号还是频域信号*/mVisualizer.setDataCaptureListener(newVisualizer.OnDataCaptureListener(){//这个回调应该采集的是快速傅里叶变换有关的数据@OverridepublicvoidonFftDataCapture(Visualizervisualizer,byte[]fft,intsamplingRate){}//这个回调应该采集的是波形数据@OverridepublicvoidonWaveFormDataCapture(Visualizervisualizer,byte[]waveform,intsamplingRate){//用waveform波形数据更新mVisualizerView组件mVisualizerView.updateVisualizer(waveform);}},Visualizer.getMaxCaptureRate()/2,true,false);mVisualizer.setEnabled(true);}/***初始化均衡控制器*/privatevoidsetupEqualizer(){//以MediaPlayer的AudioSessionId创建Equalizer//相当于设置Equalizer负责控制该MediaPlayermEqualizer=newEqualizer(0,mPlayer.getAudioSessionId());//启用均衡控制效果mEqualizer.setEnabled(true);TextVieweqTitle=newTextView(this);eqTitle.setText(”均衡器:”);layout.addView(eqTitle);//获取均衡控制器支持最小值和最大值finalshortminEQLevel=mEqualizer.getBandLevelRange()[0];//第一个下标为最低的限度范围shortmaxEQLevel=mEqualizer.getBandLevelRange()[1];//第二个下标为最高的限度范围//获取均衡控制器支持的所有频率shortbrands=mEqualizer.getNumberOfBands();for(shorti=0;i<brands;i++){TextVieweqTextView=newTextView(this);//创建一个TextView,用于显示频率eqTextView.setLayoutParams(newViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));eqTextView.setGravity(Gravity.CENTER_HORIZONTAL);//设置该均衡控制器的频率eqTextView.setText((mEqualizer.getCenterFreq(i)/1000)+”Hz”);layout.addView(eqTextView);//创建一个水平排列组件的LinearLayoutLinearLayouttmpLayout=newLinearLayout(this);tmpLayout.setOrientation(LinearLayout.HORIZONTAL);//创建显示均衡控制器最小值的TextViewTextViewminDbTextView=newTextView(this);minDbTextView.setLayoutParams(newViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT));//显示均衡控制器的最小值minDbTextView.setText((minEQLevel/100)+“dB”);//创建显示均衡控制器最大值的TextViewTextViewmaxDbTextView=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.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);layoutParams.weight=1;//定义SeekBar做为调整工具SeekBarbar=newSeekBar(this);bar.setLayoutParams(layoutParams);bar.setMax(maxEQLevel-minEQLevel);bar.setProgress(mEqualizer.getBandLevel(i));finalshortbrand=i;//为SeekBar的拖动事件设置事件监听器bar.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener(){@OverridepublicvoidonProgressChanged(SeekBarseekBar,intprogress,booleanfromUser){//设置该频率的均衡值mEqualizer.setBandLevel(brand,(short)(progress+minEQLevel));}@OverridepublicvoidonStartTrackingTouch(SeekBarseekBar){}@OverridepublicvoidonStopTrackingTouch(SeekBarseekBar){}});//使用水平排列组件的LinearLayout“盛装”3个组件tmpLayout.addView(minDbTextView);tmpLayout.addView(bar);tmpLayout.addView(maxDbTextView);//将水平排列组件的LinearLayout添加到myLayout容器中layout.addView(tmpLayout);}}/***初始化重低音控制器*/privatevoidsetupBassBoost(){//以MediaPlayer的AudioSessionId创建BassBoost//相当于设置BassBoost负责控制该MediaPlayermBass=newBassBoost(0,mPlayer.getAudioSessionId());//设置启用重低音效果mBass.setEnabled(true);TextViewbbTitle=newTextView(this);bbTitle.setText(”重低音:”);layout.addView(bbTitle);//使用SeekBar做为重低音的调整工具SeekBarbar=newSeekBar(this);//重低音的范围为0~1000bar.setMax(1000);bar.setProgress(0);//为SeekBar的拖动事件设置事件监听器bar.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener(){@OverridepublicvoidonProgressChanged(SeekBarseekBar,intprogress,booleanfromUser){//设置重低音的强度mBass.setStrength((short)progress);}@OverridepublicvoidonStartTrackingTouch(SeekBarseekBar){}@OverridepublicvoidonStopTrackingTouch(SeekBarseekBar){}});layout.addView(bar);}/***初始化预设音场控制器*/privatevoidsetupPresetReverb(){//以MediaPlayer的AudioSessionId创建PresetReverb//相当于设置PresetReverb负责控制该MediaPlayermPresetReverb=newPresetReverb(0,mPlayer.getAudioSessionId());//设置启用预设音场控制mPresetReverb.setEnabled(true);TextViewprTitle=newTextView(this);prTitle.setText(”音场”);layout.addView(prTitle);//获取系统支持的所有预设音场for(shorti=0;i<mEqualizer.getNumberOfPresets();i++){reverbNames.add(i);reverbVals.add(mEqualizer.getPresetName(i));}//使用Spinner做为音场选择工具Spinnersp=newSpinner(this);sp.setAdapter(newArrayAdapter<String>(MediaPlayerTest.this,android.R.layout.simple_spinner_item,reverbVals));//为Spinner的列表项选中事件设置监听器sp.setOnItemSelectedListener(newSpinner.OnItemSelectedListener(){@OverridepublicvoidonItemSelected(AdapterView<?>arg0,Viewarg1,intarg2,longarg3){//设定音场mPresetReverb.setPreset(reverbNames.get(arg2));}@OverridepublicvoidonNothingSelected(AdapterView<?>arg0){}});layout.addView(sp);}@OverrideprotectedvoidonPause(){super.onPause();if(isFinishing()&&mPlayer!=null){//释放所有对象mVisualizer.release();mEqualizer.release();mPresetReverb.release();mBass.release();mPlayer.release();mPlayer=null;}}/***根据Visualizer传来的数据动态绘制波形效果,分别为:*块状波形、柱状波形、曲线波形*/privatestaticclassMyVisualizerViewextendsView{//bytes数组保存了波形抽样点的值privatebyte[]bytes;privatefloat[]points;privatePaintpaint=newPaint();privateRectrect=newRect();privatebytetype=0;publicMyVisualizerView(Contextcontext){super(context);bytes=null;//设置画笔的属性paint.setStrokeWidth(1f);paint.setAntiAlias(true);//抗锯齿paint.setColor(Color.YELLOW);//画笔颜色paint.setStyle(Style.FILL);}publicvoidupdateVisualizer(byte[]ftt){bytes=ftt;//通知该组件重绘自己。invalidate();}@OverridepublicbooleanonTouchEvent(MotionEventme){//当用户触碰该组件时,切换波形类型if(me.getAction()!=MotionEvent.ACTION_DOWN){returnfalse;}type++;if(type>=3){type=0;}returntrue;}@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);if(bytes==null){return;}//绘制白色背景canvas.drawColor(Color.WHITE);//使用rect对象记录该组件的宽度和高度rect.set(0,0,getWidth(),getHeight());switch(type){//——-绘制块状的波形图——-case0:for(inti=0;i<bytes.length-1;i++){floatleft=getWidth()*i/(bytes.length-1);//根据波形值计算该矩形的高度floattop=rect.height()-(byte)(bytes[i+1]+128)*rect.height()/128;floatright=left+1;floatbottom=rect.height();canvas.drawRect(left,top,right,bottom,paint);}break;//——-绘制柱状的波形图(每隔18个抽样点绘制一个矩形)——-case1:for(inti=0;i<bytes.length-1;i+=18){floatleft=rect.width()*i/(bytes.length-1);//根据波形值计算该矩形的高度floattop=rect.height()-(byte)(bytes[i+1]+128)*rect.height()/128;floatright=left+6;floatbottom=rect.height();canvas.drawRect(left,top,right,bottom,paint);}break;//——-绘制曲线波形图——-case2://如果point数组还未初始化if(points==null||points.length<bytes.length*4){points=newfloat[bytes.length*4];}for(inti=0;i<bytes.length-1;i++){//计算第i个点的x坐标points[i*4]=rect.width()*i/(bytes.length-1);//根据bytes[i]的值(波形点的值)计算第i个点的y坐标points[i*4+1]=(rect.height()/2)+((byte)(bytes[i]+128))*128/(rect.height()/2);//计算第i+1个点的x坐标points[i*4+2]=rect.width()*(i+1)/(bytes.length-1);//根据bytes[i+1]的值(波形点的值)计算第i+1个点的y坐标points[i*4+3]=(rect.height()/2)+((byte)(bytes[i+1]+128))*128/(rect.height()/2);}//绘制波形曲线canvas.drawLines(points,paint);break;}}}}

AndroidManifest.xml

[html]view plain copy print ? <?xmlversion=“1.0”encoding=“utf-8”?><manifestxmlns:android=“/apk/res/android”package=“com.oyp.media”android:versionCode=“1”android:versionName=“1.0”><uses-sdkandroid:minSdkVersion=“10”android:targetSdkVersion=“17”/><!–使用音场效果必要的权限–><uses-permissionandroid:name=“android.permission.RECORD_AUDIO”/><uses-permissionandroid:name=“android.permission.MODIFY_AUDIO_SETTINGS”/><applicationandroid:icon=“@drawable/ic_launcher”android:label=“@string/app_name”><activityandroid:name=“.MediaPlayerTest”android:label=“@string/app_name”><intent-filter><actionandroid:name=“android.intent.action.MAIN”/><categoryandroid:name=“android.intent.category.LAUNCHER”/></intent-filter></activity></application></manifest>

PS:请在真机环境下运行此程序,如果在模拟器下运行,可能会报错:

[java]view plain copy print ? java.lang.RuntimeException:CannotinitializeVisualizerengine,error:-4

转载自:/ouyang_peng/article/details/46841893

如果觉得《Android实现音乐示波器 均衡器 重低音和音场功能》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。