2.3之后,Google 为Mediaplayer 类添加了EQ支持,如果你需要使用这个EQ功能,有两点需要注意,分别为如下:
- 在配置文件中设置最小的SDK版本为9
- 添加权限android.permission.RECORD_AUDIO 即可使用,具体的使用方法,下文会介绍
为了使应用程序能够支持波段变化,我们需要重新定义一个VIEW对象,在onDraw 方法画频谱,代码如下:
class
VisualizerView extends View {
private
byte
[] mBytes;
private
float
[] mPoints;
//
矩形区域
private
Rect mRect
=
new
Rect();
//
画笔
private
Paint mPaint
=
new
Paint();
//
初始化画笔
private
void
init() {
mBytes
=
null
;
mPaint.setStrokeWidth(1f);
mPaint.setAntiAlias(
true
);
mPaint.setColor(Color.BLUE);
}
public
VisualizerView(Context context) {
super(context);
init();
}
public
void
updateVisualizer(
byte
[] mbyte) {
mBytes
=
mbyte;
invalidate();
}
@Override
protected
void
onDraw(Canvas canvas) {
//
TODO Auto-generated method stub
super.onDraw(canvas);
if
(mBytes
==
null
) {
return
;
}
if
(mPoints
==
null
||
mPoints.length
<
mBytes.length
*
4
) {
mPoints
=
new
float
[mBytes.length
*
4
];
}
mRect.
set
(
0
,
0
, getWidth(), getHeight());
for
(
int
i
=
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, mPaint);
}
}
另外,为了使用EQ和频谱可视化,我们必须了解以下两个类:
- Visualizer
此类能使应用程序获取当前有效的一部分音频可视化的目的。使用此类必须添加上面提到的权限。
- Equalizer
一个均衡器的类,使用此类可以轻松的操纵音频的频段,和输出的混合 。
具体使用代码和注释见下面:
/*
*
* 通过mMediaPlayer返回的AudioSessionId创建一个优先级为0均衡器对象 并且通过频谱生成相应的UI和对应的事件
*/
private
void
setupEqualizeFxAndUi() {
mEqualizer
=
new
Equalizer(
0
, mMediaPlayer.getAudioSessionId());
mEqualizer.setEnabled(
true
);
//
启用均衡器
TextView eqTextView
=
new
TextView(
this
);
eqTextView.setText(
"
均衡器:
"
);
mLayout.addView(eqTextView);
//
通过均衡器得到其支持的频谱引擎
short
bands
=
mEqualizer.getNumberOfBands();
//
getBandLevelRange 是一个数组,返回一组频谱等级数组,
//
第一个下标为最低的限度范围
//
第二个下标为最大的上限,依次取出
final
short
minEqualizer
=
mEqualizer.getBandLevelRange()[
0
];
final
short
maxEqualizer
=
mEqualizer.getBandLevelRange()[
1
];
for
(
short
i
=
0
; i
<
bands; i
++
) {
final
short
band
=
i;
TextView freqTextView
=
new
TextView(
this
);
freqTextView.setLayoutParams(
new
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
//
取出中心频率
freqTextView
.setText((mEqualizer.getCenterFreq(band)
/
1000
)
+
"
HZ
"
);
mLayout.addView(freqTextView);
LinearLayout row
=
new
LinearLayout(
this
);
row.setOrientation(LinearLayout.HORIZONTAL);
TextView minDbTextView
=
new
TextView(
this
);
minDbTextView.setLayoutParams(
new
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
minDbTextView.setText((minEqualizer
/
100
)
+
"
dB
"
);
TextView maxDbTextView
=
new
TextView(
this
);
maxDbTextView.setLayoutParams(
new
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
maxDbTextView.setText((maxEqualizer
/
100
)
+
"
dB
"
);
LinearLayout.LayoutParams layoutParams
=
new
LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.weight
=
1
;
SeekBar seekbar
=
new
SeekBar(
this
);
seekbar.setLayoutParams(layoutParams);
seekbar.setMax(maxEqualizer
-
minEqualizer);
seekbar.setProgress(mEqualizer.getBandLevel(band));
seekbar.setOnSeekBarChangeListener(
new
OnSeekBarChangeListener() {
@Override
public
void
onStopTrackingTouch(SeekBar seekBar) {
}
@Override
public
void
onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public
void
onProgressChanged(SeekBar seekBar,
int
progress,
boolean fromUser) {
//
TODO Auto-generated method stub
mEqualizer.setBandLevel(band,
(
short
) (progress
+
minEqualizer));
}
});
row.addView(minDbTextView);
row.addView(seekbar);
row.addView(maxDbTextView);
mLayout.addView(row);
}
}
/*
*
* 生成一个VisualizerView对象,使音频频谱的波段能够反映到 VisualizerView上
*/
private
void
setupVisualizerFxAndUi() {
mVisualizerView
=
new
VisualizerView(
this
);
mVisualizerView.setLayoutParams(
new
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
(
int
) (VISUALIZER_HEIGHT_DIP
*
getResources()
.getDisplayMetrics().density)));
mLayout.addView(mVisualizerView);
mVisualizer
=
new
Visualizer(mMediaPlayer.getAudioSessionId());
//
参数内必须是2的位数
mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[
1
]);
//
设置允许波形表示,并且捕获它
mVisualizer.setDataCaptureListener(
new
OnDataCaptureListener() {
@Override
public
void
onWaveFormDataCapture(Visualizer visualizer,
byte
[] waveform,
int
samplingRate) {
//
TODO Auto-generated method stub
mVisualizerView.updateVisualizer(waveform);
}
@Override
public
void
onFftDataCapture(Visualizer visualizer,
byte
[] fft,
int
samplingRate) {
//
TODO Auto-generated method stub
}
}, Visualizer.getMaxCaptureRate()
/
2
,
true
,
false
);
}
进入程序后,在程序入口加载如下代码:
mStatusTextView
=
new
TextView(
this
);
mLayout
=
new
LinearLayout(
this
);
mLayout.setOrientation(LinearLayout.VERTICAL);
mLayout.addView(mStatusTextView);
setContentView(mLayout);
mMediaPlayer
=
MediaPlayer.create(
this
, R.raw.eason);
setupVisualizerFxAndUi();
setupEqualizeFxAndUi();
mVisualizer.setEnabled(
true
);
mMediaPlayer.setOnCompletionListener(
new
OnCompletionListener() {
@Override
public
void
onCompletion(MediaPlayer mp) {
//
TODO Auto-generated method stub
mVisualizer.setEnabled(
false
);
}
});
mMediaPlayer.start();
mStatusTextView.setText(
"
播放中。。。
"
);
完整运行效果:
![]()
试试改变一下拖动条,听一下音频有什么变化。
源码下载:
音频频谱操作
注:源码内没有包含音频文件,测试的话自行添加一个MP3文件即可。
本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/475113,如需转载请自行联系原作者