源代码一共包括两个文件MyVisualizerView.java 和MainActivity.java
MyVisualizerView用于可视化音乐波形,MainActivity调控各种音乐效果。注意:该程序只在android4.4运行通过,在android4.0则无法创建Visualizer
源代码下载:http://pan.baidu.com/s/1o60758m
MyVisualizerView.java
package com.example.audioeffecttest;
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.view.MotionEvent;
import android.view.View;
public class MyVisualizerView extends View {
private byte[] bytes;
private float[] points;
private Paint paint = new Paint();
private Rect rect = new Rect();
private byte type = 0;
public MyVisualizerView(Context context) {
super(context);
bytes = null;
paint.setStrokeWidth(1f);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Style.FILL);
}
public void updateVisualizer(byte[] ftt) {
bytes = ftt;
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
type++;
if (type >= 3) {
type = 0;
}
return true;
}
@Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
super.draw(canvas);
if (bytes == null) {
return;
}
canvas.drawColor(Color.WHITE);
rect.set(0, 0, this.getWidth(), this.getHeight());
switch (type) {
case 0://绘制块状波形图
for (int i = 0; i < bytes.length-1; i++) {
float left = this.getWidth() * i / (bytes.length-1);
float top = rect.height() - (byte)(bytes[i+1]+128) * rect.height() / 128;//这里加上128后再取byte用来截断超出范围值
float right = left + 1;
float bottom = rect.height();
//System.out.println("left:"+left+"top:"+top+"right:"+right+"bottom:"+bottom);
canvas.drawRect(left, top, right, bottom, paint);
}
break;
case 1://绘制柱状波形图(每隔18抽样点绘制一个矩形)
for (int i = 0; i < bytes.length-1; i += 18) {
float left = rect.width() * i / (bytes.length-1);
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:
if (points == null || points.length < bytes.length * 4) {
points = new float[bytes.length*4];
for (int i = 0; i < bytes.length - 1; i++) {
points[i*4] = rect.width() * i / (bytes.length - 1);
points[i*4+1] = (rect.height()/2) + ((byte)(bytes[i]+128))*128/(rect.height()/2);
points[i*4+2] = rect.width() * (i+1) / (bytes.length-1);
points[i*4+3] = (rect.height()/2)+((byte)(bytes[i+1]+128))*128/(rect.height()/2);
}//for
}//if
canvas.drawLines(points, paint);
break;
}
}
}
MainActivity.java
package com.example.audioeffecttest;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.audiofx.BassBoost;
import android.media.audiofx.Equalizer;
import android.media.audiofx.PresetReverb;
import android.media.audiofx.Visualizer;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
public class MainActivity extends Activity {
private MediaPlayer mediaPlayer;
private Visualizer visualizer;
private Equalizer equalizer;
private BassBoost bassBoost;
private PresetReverb presetReverb;
private LinearLayout layout;
private ScrollView scrollView;
private List<Short> reverbNames = new ArrayList<Short>();
private List<String> reverbVals = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
//layout = new LinearLayout(this);
layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
scrollView = new ScrollView(this);
scrollView.addView(layout);
setContentView(scrollView);
mediaPlayer = MediaPlayer.create(this, R.raw.hometown);
//初始化滤波器
setupVisualizer();
//初始化均衡控制器
setupEqualizer();
//初始化重低音控制器
setupBassBoost();
//初始化预设音场控制器
setupPresetReverb();
mediaPlayer.start();
}
public void setupPresetReverb() {
presetReverb = new PresetReverb(0, mediaPlayer.getAudioSessionId());
presetReverb.setEnabled(true);
TextView prTitle = new TextView(this);
prTitle.setText("音场");
layout.addView(prTitle);
for (short i = 0; i < equalizer.getNumberOfPresets(); i++) {
reverbNames.add(i);
reverbVals.add(equalizer.getPresetName(i));
}
Spinner sp = new Spinner(this);
sp.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_item, reverbVals));
sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
presetReverb.setPreset(reverbNames.get(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
});
layout.addView(sp);
}
public void setupBassBoost() {
bassBoost = new BassBoost(0, mediaPlayer.getAudioSessionId());
bassBoost.setEnabled(true);
TextView bbTitle = new TextView(this);
bbTitle.setText("重低音:");
layout.addView(bbTitle);
SeekBar bar = new SeekBar(this);
//重低音范围为0-1000
bar.setMax(1000);
bar.setProgress(0);
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
bassBoost.setStrength((short)progress);
}
});
layout.addView(bar);
}
public void setupEqualizer() {
equalizer = new Equalizer(0, mediaPlayer.getAudioSessionId());
equalizer.setEnabled(true);
TextView eqTitle = new TextView(this);
eqTitle.setText("均衡器:");
layout.addView(eqTitle);
//获取均衡器控制器支持最小值和最大值
final short minEQLevel = equalizer.getBandLevelRange()[0];
short maxEQLevel = equalizer.getBandLevelRange()[1];
//获取均衡器控制器支持的所有频率
short brands = equalizer.getNumberOfBands();
for (short i = 0; i < brands; i++) {
TextView eqTextView = new TextView(this);
eqTextView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
eqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
eqTextView.setText((equalizer.getCenterFreq(i)/1000)+"Hz");
layout.addView(eqTextView);
LinearLayout tmpLayout = new LinearLayout(this);
tmpLayout.setOrientation(LinearLayout.HORIZONTAL);
TextView minDbTextView = new TextView(this);
minDbTextView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
minDbTextView.setText((minEQLevel/100)+"dB");
TextView maxDbTextView = new TextView(this);
maxDbTextView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
maxDbTextView.setText((maxEQLevel/100)+"dB");
SeekBar bar = new SeekBar(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
layoutParams.weight = 1;
bar.setLayoutParams(layoutParams);
bar.setMax(maxEQLevel-minEQLevel);
bar.setProgress(equalizer.getBandLevel(i));
final short brand = i;
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
equalizer.setBandLevel(brand, (short)(progress+minEQLevel));
}
});
//使用水平排列组件的LinearLayout盛装三个组件
tmpLayout.addView(minDbTextView);
tmpLayout.addView(bar);
tmpLayout.addView(maxDbTextView);
layout.addView(tmpLayout);
}
}
public void setupVisualizer() {
final MyVisualizerView myVisualizerView = new MyVisualizerView(this);
myVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,
(int)(120f*getResources().getDisplayMetrics().density)));
layout.addView(myVisualizerView);
visualizer = new Visualizer(mediaPlayer.getAudioSessionId());
visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
visualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
@Override
public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform,
int samplingRate) {
// TODO Auto-generated method stub
//String str = new String(waveform, 0, waveform.length);
System.out.println("capture->" + waveform.length);
/*
for (byte b: waveform) {
System.out.println(b);
}*/
myVisualizerView.updateVisualizer(waveform);
}
@Override
public void onFftDataCapture(Visualizer visualizer, byte[] fft,
int samplingRate) {
// TODO Auto-generated method stub
}
}, Visualizer.getMaxCaptureRate()/2, true, false);
visualizer.setEnabled(true);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
if (isFinishing() && mediaPlayer != null) {
visualizer.release();
equalizer.release();
presetReverb.release();
bassBoost.release();
mediaPlayer.release();
mediaPlayer = null;
}
super.onPause();
}
}