1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.apis.media; 18 19 import com.example.android.apis.R; 20 21 import android.app.Activity; 22 import android.content.Context; 23 import android.content.res.AssetFileDescriptor; 24 import android.graphics.Canvas; 25 import android.graphics.Color; 26 import android.graphics.Paint; 27 import android.graphics.Rect; 28 import android.media.AudioManager; 29 import android.media.MediaPlayer; 30 import android.media.audiofx.Equalizer; 31 import android.media.audiofx.Visualizer; 32 import android.net.Uri; 33 import android.os.Bundle; 34 import android.util.Log; 35 import android.view.Gravity; 36 import android.view.View; 37 import android.view.ViewGroup; 38 import android.widget.LinearLayout; 39 import android.widget.SeekBar; 40 import android.widget.TextView; 41 42 import java.io.IOException; 43 44 public class AudioFxDemo extends Activity { 45 private static final String TAG = "AudioFxDemo"; 46 47 private static final float VISUALIZER_HEIGHT_DIP = 50f; 48 49 private MediaPlayer mMediaPlayer; 50 private Visualizer mVisualizer; 51 private Equalizer mEqualizer; 52 53 private LinearLayout mLinearLayout; 54 private VisualizerView mVisualizerView; 55 private TextView mStatusTextView; 56 57 @Override 58 public void onCreate(Bundle icicle) { 59 super.onCreate(icicle); 60 61 setVolumeControlStream(AudioManager.STREAM_MUSIC); 62 63 mStatusTextView = new TextView(this); 64 65 mLinearLayout = new LinearLayout(this); 66 mLinearLayout.setOrientation(LinearLayout.VERTICAL); 67 mLinearLayout.addView(mStatusTextView); 68 69 setContentView(mLinearLayout); 70 71 // Create the MediaPlayer 72 mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr); 73 Log.d(TAG, "MediaPlayer audio session ID: " + mMediaPlayer.getAudioSessionId()); 74 75 setupVisualizerFxAndUI(); 76 setupEqualizerFxAndUI(); 77 78 // Make sure the visualizer is enabled only when you actually want to receive data, and 79 // when it makes sense to receive data. 80 mVisualizer.setEnabled(true); 81 82 // When the stream ends, we don't need to collect any more data. We don't do this in 83 // setupVisualizerFxAndUI because we likely want to have more, non-Visualizer related code 84 // in this callback. 85 mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 86 public void onCompletion(MediaPlayer mediaPlayer) { 87 mVisualizer.setEnabled(false); 88 } 89 }); 90 91 mMediaPlayer.start(); 92 mStatusTextView.setText("Playing audio..."); 93 } 94 95 private void setupEqualizerFxAndUI() { 96 // Create the Equalizer object (an AudioEffect subclass) and attach it to our media player, 97 // with a default priority (0). 98 mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId()); 99 mEqualizer.setEnabled(true); 100 101 TextView eqTextView = new TextView(this); 102 eqTextView.setText("Equalizer:"); 103 mLinearLayout.addView(eqTextView); 104 105 short bands = mEqualizer.getNumberOfBands(); 106 107 final short minEQLevel = mEqualizer.getBandLevelRange()[0]; 108 final short maxEQLevel = mEqualizer.getBandLevelRange()[1]; 109 110 for (short i = 0; i < bands; i++) { 111 final short band = i; 112 113 TextView freqTextView = new TextView(this); 114 freqTextView.setLayoutParams(new ViewGroup.LayoutParams( 115 ViewGroup.LayoutParams.FILL_PARENT, 116 ViewGroup.LayoutParams.WRAP_CONTENT)); 117 freqTextView.setGravity(Gravity.CENTER_HORIZONTAL); 118 freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz"); 119 mLinearLayout.addView(freqTextView); 120 121 LinearLayout row = new LinearLayout(this); 122 row.setOrientation(LinearLayout.HORIZONTAL); 123 124 TextView minDbTextView = new TextView(this); 125 minDbTextView.setLayoutParams(new ViewGroup.LayoutParams( 126 ViewGroup.LayoutParams.WRAP_CONTENT, 127 ViewGroup.LayoutParams.WRAP_CONTENT)); 128 minDbTextView.setText((minEQLevel / 100) + " dB"); 129 130 TextView maxDbTextView = new TextView(this); 131 maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams( 132 ViewGroup.LayoutParams.WRAP_CONTENT, 133 ViewGroup.LayoutParams.WRAP_CONTENT)); 134 maxDbTextView.setText((maxEQLevel / 100) + " dB"); 135 136 LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( 137 ViewGroup.LayoutParams.FILL_PARENT, 138 ViewGroup.LayoutParams.WRAP_CONTENT); 139 layoutParams.weight = 1; 140 SeekBar bar = new SeekBar(this); 141 bar.setLayoutParams(layoutParams); 142 bar.setMax(maxEQLevel - minEQLevel); 143 bar.setProgress(mEqualizer.getBandLevel(band)); 144 145 bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 146 public void onProgressChanged(SeekBar seekBar, int progress, 147 boolean fromUser) { 148 mEqualizer.setBandLevel(band, (short) (progress + minEQLevel)); 149 } 150 151 public void onStartTrackingTouch(SeekBar seekBar) {} 152 public void onStopTrackingTouch(SeekBar seekBar) {} 153 }); 154 155 row.addView(minDbTextView); 156 row.addView(bar); 157 row.addView(maxDbTextView); 158 159 mLinearLayout.addView(row); 160 } 161 } 162 163 private void setupVisualizerFxAndUI() { 164 // Create a VisualizerView (defined below), which will render the simplified audio 165 // wave form to a Canvas. 166 mVisualizerView = new VisualizerView(this); 167 mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams( 168 ViewGroup.LayoutParams.FILL_PARENT, 169 (int)(VISUALIZER_HEIGHT_DIP * getResources().getDisplayMetrics().density))); 170 mLinearLayout.addView(mVisualizerView); 171 172 // Create the Visualizer object and attach it to our media player. 173 mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId()); 174 mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]); 175 mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() { 176 public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes, 177 int samplingRate) { 178 mVisualizerView.updateVisualizer(bytes); 179 } 180 181 public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {} 182 }, Visualizer.getMaxCaptureRate() / 2, true, false); 183 } 184 185 @Override 186 protected void onPause() { 187 super.onPause(); 188 189 if (isFinishing() && mMediaPlayer != null) { 190 mVisualizer.release(); 191 mEqualizer.release(); 192 mMediaPlayer.release(); 193 mMediaPlayer = null; 194 } 195 } 196 } 197 198 /** 199 * A simple class that draws waveform data received from a 200 * {@link Visualizer.OnDataCaptureListener#onWaveFormDataCapture } 201 */ 202 class VisualizerView extends View { 203 private byte[] mBytes; 204 private float[] mPoints; 205 private Rect mRect = new Rect(); 206 207 private Paint mForePaint = new Paint(); 208 209 public VisualizerView(Context context) { 210 super(context); 211 init(); 212 } 213 214 private void init() { 215 mBytes = null; 216 217 mForePaint.setStrokeWidth(1f); 218 mForePaint.setAntiAlias(true); 219 mForePaint.setColor(Color.rgb(0, 128, 255)); 220 } 221 222 public void updateVisualizer(byte[] bytes) { 223 mBytes = bytes; 224 invalidate(); 225 } 226 227 @Override 228 protected void onDraw(Canvas canvas) { 229 super.onDraw(canvas); 230 231 if (mBytes == null) { 232 return; 233 } 234 235 if (mPoints == null || mPoints.length < mBytes.length * 4) { 236 mPoints = new float[mBytes.length * 4]; 237 } 238 239 mRect.set(0, 0, getWidth(), getHeight()); 240 241 for (int i = 0; i < mBytes.length - 1; i++) { 242 mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1); 243 mPoints[i * 4 + 1] = mRect.height() / 2 244 + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128; 245 mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1); 246 mPoints[i * 4 + 3] = mRect.height() / 2 247 + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128; 248 } 249 250 canvas.drawLines(mPoints, mForePaint); 251 } 252 } 253