My Android advanced tour ------> Android implements music oscilloscope, balancer, bass and audio field functions, and android advanced
This example is from the crazy Android handout. To implement specific functions, you need to understand the following APIs:
- MediaPlayer Media Player
- Visualizer Spectrum
- Equalizer
- BassBoost bass Controller
- PresetReverb preset sound field controller
- Painting
The following figure shows the effect.
Portrait Waveform
Block Waveform
Curve Waveform
Adjust the balancer and bass
Select audio field
The specific implementation code MediaPlayerTest. java is as follows:
Package com. oyp. media; import java. util. arrayList; import java. util. list; import android. app. activity; import android. content. context; import android. graphics. canvas; import android. graphics. color; import android. graphics. paint; import android. graphics. paint. style; import android. graphics. rect; import android. media. audioManager; import android. media. mediaPlayer; import android. media. audiofx. bassBoost; import Droid. media. audiofx. equalizer; import android. media. audiofx. presetReverb; import android. media. audiofx. visualizer; import android. OS. bundle; import android. view. gravity; import android. view. motionEvent; import android. view. view; import android. view. viewGroup; import android. widget. adapterView; import android. widget. arrayAdapter; import android. widget. linearLayout; import android. widget. seekBar; import android. Widget. spinner; import android. widget. textView; public class MediaPlayerTest extends Activity {// MediaPlayerprivate MediaPlayer mPlayer that defines the playing sound; // defines the system's spectrum private Visualizer mVisualizer; // defines the system's balancer private Equalizer mEqualizer; // define the system's bass controller private BassBoost mBass; // define the system's preset sound field controller private PresetReverb mPresetReverb; private LinearLayout layout; private List <Short> reverbNames = new ArrayList <Short> (); priv Ate List <String> reverbVals = new ArrayList <String> (); @ Overridepublic void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); // sets the audio stream-STREAM_MUSIC: media playback volume setVolumeControlStream (AudioManager. STREAM_MUSIC); layout = new LinearLayout (this); // code creation layout. setOrientation (LinearLayout. VERTICAL); // set to linear layout-Up and down setContentView (layout); // Add the layout to Activity // create a MediaPlayer object and add the audio // audio path Res/raw/beautifulw.mplayer = MediaPlayer. create (this, R. raw. beautiful); // initialize the oscilloscope setupVisualizer (); // initialize the balance controller setupEqualizer (); // initialize the bass controller setupBassBoost (); // initialize the preset sound field controller setupPresetReverb (); // develop and play music mPlayer. start ();}/*** initialize spectrum */private void setupVisualizer () {// create the MyVisualizerView component to display the waveform map final MyVisualizerView mVisualizerView = new MyVisualizerView (this ); mVisualizerView. setLayoutParams (new ViewG Roup. layoutParams (ViewGroup. layoutParams. MATCH_PARENT, (int) (120f * getResources (). getDisplayMetrics (). density); // Add the MyVisualizerView component to the layout container. addView (mVisualizerView); // create a Visualizer with the AudioSessionId of the MediaPlayer. // It is equivalent to setting the Visualizer to display the audio data of the MediaPlayer. mVisualizer = new Visualizer (mPlayer. getAudioSessionId (); // set the length of the music content to be converted. Specifically, this is sampling. The sample value is usually an exponential multiple of 2, for example, 64,128,256,512,102 4. MVisualizer. setCaptureSize (Visualizer. getCaptureSizeRange () [1]); // set the listener for mVisualizer/** Visualizer. setDataCaptureListener (OnDataCaptureListener listener, int rate, boolean waveform, boolean fft ** listener, table listening function. Anonymous internal class implements this interface. This interface requires two function rates, it indicates the sampling period, that is, the interval of sampling once. In the previous article, it is the interval of sampling 128 data iswave, which is the waveform signal isfft and the FFT signal, indicates whether to obtain the waveform signal or frequency-domain signal */mVisualizer. setDataCaptureListener (new Visualizer. onDataCaptureListener () {// This callback should The collected data is the data related to the Fast Fourier transformation @ Overridepublic void onFftDataCapture (Visualizer visualizer, byte [] fft, int samplingRate) {} // The callback should collect the waveform data @ Overridepublic void transform (Visualizer visualizer, byte [] waveform, int samplingRate) {// use the waveform data to update the mVisualizerView component mVisualizerView. updateVisualizer (waveform) ;}, Visualizer. getMaxCaptureRate ()/2, true, false); mVisualizer. setEnabled (true);}/*** initialize the balancing Controller */Private void setupEqualizer () {// create Equalizer with the AudioSessionId of the MediaPlayer // It is equivalent to setting Equalizer to control the MediaPlayermEqualizer = new Equalizer (0, mPlayer. getAudioSessionId (); // enable the balance control effect mEqualizer. setEnabled (true); TextView eqTitle = new TextView (this); eqTitle. setText ("balancer:"); layout. addView (eqTitle); // obtain the minimum and maximum values supported by the balance controller. final short minEQLevel = mEqualizer. getBandLevelRange () [0]; // The short maxEQLevel with the lowest subscript = MEqualizer. getBandLevelRange () [1]; // The second subscript is the maximum limit range // obtain all the frequencies supported by the balancing controller. short brands = mEqualizer. getNumberOfBands (); for (short I = 0; I <brands; I ++) {TextView eqTextView = new TextView (this); // create a TextView for display frequency eqTextView. setLayoutParams (new ViewGroup. layoutParams (ViewGroup. layoutParams. MATCH_PARENT, ViewGroup. layoutParams. WRAP_CONTENT); eqTextView. setGravity (Gravity. CENTER_HORIZONTAL); // sets the balance control. EqTextView. setText (mEqualizer. getCenterFreq (I)/1000) + "Hz"); layout. addView (eqTextView); // create a horizontal arrangement component named LinearLayoutLinearLayout tmpLayout = new LinearLayout (this); tmpLayout. setOrientation (LinearLayout. HORIZONTAL); // create TextViewTextView minDbTextView = new TextView (this); minDbTextView. setLayoutParams (new ViewGroup. layoutParams (ViewGroup. layoutParams. WRAP_CONTENT, ViewGroup. layoutPar Ams. WRAP_CONTENT); // display the minimum value of the balance controller minDbTextView. setText (minEQLevel/100) + "dB"); // create TextViewTextView maxDbTextView = new TextView (this); maxDbTextView. setLayoutParams (new ViewGroup. layoutParams (ViewGroup. layoutParams. WRAP_CONTENT, ViewGroup. layoutParams. WRAP_CONTENT); // display the maximum value of the balance controller maxDbTextView. setText (maxEQLevel/100) + "dB"); LinearLayout. layoutParams layoutParams = new LinearLay Out. layoutParams (ViewGroup. layoutParams. MATCH_PARENT, ViewGroup. layoutParams. WRAP_CONTENT); layoutParams. weight = 1; // defines SeekBar as the adjustment tool SeekBar bar = new SeekBar (this); bar. setLayoutParams (layoutParams); bar. setMax (maxEQLevel-minEQLevel); bar. setProgress (mEqualizer. getBandLevel (I); final short brand = I; // set the event listener bar for the drag event of SeekBar. setOnSeekBarChangeListener (new SeekBar. onSeekBarChangeListener () {@ Overrid Epublic void onProgressChanged (SeekBar seekBar, int progress, boolean fromUser) {// you can specify mEqualizer for the specified frequency. setBandLevel (brand, (short) (progress + minEQLevel) ;}@ Overridepublic void onStartTrackingTouch (SeekBar seekBar) {}@ Overridepublic void onStopTrackingTouch (SeekBar seekBar ){}}); // use the horizontal arrangement component LinearLayout to "Dress up" the three components tmpLayout. addView (minDbTextView); tmpLayout. addView (bar); tmpLayout. addView (maxDbTextView );// Add the LinearLayout of the horizontal arrangement component to the myLayout container. addView (tmpLayout) ;}}/*** initialize the bass controller */private void setupBassBoost () {// use MediaPlayer's AudioSessionId to create BassBoost // It is equivalent to setting BassBoost to control MediaPlayermBass = new BassBoost (0, mPlayer. getAudioSessionId (); // set to enable the bass effect mBass. setEnabled (true); TextView bbTitle = new TextView (this); bbTitle. setText ("Bass:"); layout. addView (bbTitle); // use SeekBar as the tuning tool for the bass. SeekBar bar = new SeekBar (this); // the range of the bass is 0 ~ 1000bar. setMax (1, 1000); bar. setProgress (0); // set the event listener bar for the drag event of SeekBar. setOnSeekBarChangeListener (new SeekBar. onSeekBarChangeListener () {@ Overridepublic void onProgressChanged (SeekBar seekBar, int progress, boolean fromUser) {// set the intensity of the Bass mBass. setStrength (short) progress) ;}@ Overridepublic void onStartTrackingTouch (SeekBar seekBar) {}@ Overridepublic void onStopTrackingTouch (SeekBar seekBar) {}}); layout. addV Iew (bar);}/*** initialize the preset sound field controller */private void setupPresetReverb () {// use MediaPlayer's AudioSessionId to create PresetReverb // It is equivalent to setting PresetReverb to control the MediaPlayermPresetReverb = new PresetReverb (0, mPlayer. getAudioSessionId (); // set to enable the preset audio field control mPresetReverb. setEnabled (true); TextView prTitle = new TextView (this); prTitle. setText ("audio field"); layout. addView (prTitle); // obtain all preset Sound Fields supported by the system for (short I = 0; I <mEqualizer. getNumberOfPreset S (); I ++) {reverbNames. add (I); reverbVals. add (mEqualizer. getPresetName (I);} // use the Spinner as the audio field selection tool. setAdapter (new ArrayAdapter <String> (MediaPlayerTest. this, android. r. layout. simple_spinner_item, reverbVals); // sets the listener sp for the selected event in the list item of the Spinner. setOnItemSelectedListener (new Spinner. onItemSelectedListener () {@ Overridepublic void onItemSelected (AdapterView <?> Arg0, View arg1, int arg2, long arg3) {// set the audio field mPresetReverb. setPreset (reverbNames. get (arg2);} @ Overridepublic void onNothingSelected (AdapterView <?> Arg0) {}}); layout. addView (sp) ;}@ Overrideprotected void onPause () {super. onPause (); if (isFinishing () & mPlayer! = Null) {// release all objects mVisualizer. release (); mEqualizer. release (); mPresetReverb. release (); mBass. release (); mPlayer. release (); mPlayer = null;}/*** dynamically draws the waveform based on the data transmitted by Visualizer, respectively: * block waveform, columnar waveform, curve waveform */private static class MyVisualizerView extends View {// bytes array saves the value of the waveform sampling point private byte [] bytes; private float [] points; private Paint paint = new Paint (); private Rect rect = new Rect (); private byte type = 0; public M YVisualizerView (Context context) {super (context); bytes = null; // you can specify the paint attribute. setStrokeWidth (1f); paint. setAntiAlias (true); // anti-sawtooth paint. setColor (Color. YELLOW); // paint color. setStyle (Style. FILL);} public void updateVisualizer (byte [] ftt) {bytes = ftt; // notify the component to repaint itself. Invalidate () ;}@ Overridepublic boolean onTouchEvent (MotionEvent me) {// if (me. getAction ()! = MotionEvent. ACTION_DOWN) {return false;} type ++; if (type >=3) {type = 0;} return true ;}@ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); if (bytes = null) {return;} // draw a canvas with a white background. drawColor (Color. WHITE); // use a rect object to record the width and height of the component. set (0, 0, getWidth (), getHeight (); switch (type) {// ------- draw a block waveform ------- case 0: for (int I = 0; I <bytes. length-1; I ++) {float left = getWidth () * I/(bytes. length-1); // calculate the height float top = rect of the rectangle Based on the waveform value. 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; // ------- draw a bar waveform (draw a rectangle at every 18 sampling points) ------- case 1: for (int I = 0; I <bytes. length-1; I + = 18) {float left = rect. width () * I/(bytes. length-1); // calculate the height float top = rect of the rectangle Based on the waveform value. 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; // ------- plot the curve waveform ------- case 2: // if the point array has not been initialized if (points = null | points. length <bytes. length * 4) {points = new float [bytes. length * 4];} for (int I = 0; I <bytes. length-1; I ++) {// calculate the x coordinate points of point I [I * 4] = rect. width () * I/(bytes. length-1); // calculate the y coordinate points [I * 4 + 1] = (rect. height ()/2) + (byte) (bytes [I] + 128) * 128/(rect. height ()/2); // calculate the x coordinate points of point I + 1 [I * 4 + 2] = rect. width () * (I + 1)/(bytes. length-1); // Based on the bytes [I + 1] value (waveform point value) calculate the y coordinate points [I * 4 + 3] = (rect. height ()/2) + (byte) (bytes [I + 1] + 128) * 128/(rect. height ()/2);} // draw the waveform curve canvas. drawLines (points, paint); break ;}}}}
AndroidManifest. xml
<? Xml version = "1.0" encoding = "UTF-8"?> <Manifestxmlns: android = "http://schemas.android.com/apk/res/android" package = "com. oyp. media "android: versionCode =" 1 "android: versionName =" 1.0 "> <uses-sdk android: minSdkVersion =" 10 "android: targetSdkVersion =" 17 "/> <! -- Permissions required to use the sound field effect --> <uses-permission android: name = "android. permission. RECORD_AUDIO "/> <uses-permission android: 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> <action android: name =" android. intent. action. MAIN "/> <category android: name =" android. intent. category. LAUNCHER "/> </intent-filter> </activity> </application> </manifest>
PS: run this program in the real machine environment. If it is run in the simulator, an error may be reported:
java.lang.RuntimeException: Cannot initialize Visualizer engine, error: -4
========================================================== ========================================================== ============================
Author: Ouyang Peng: Welcome to repost. sharing with others is the source of progress!
Reprinted Please retain the original address: http://blog.csdn.net/ouyang_peng
========================================================== ========================================================== ============================
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.