注意android2.3以后才可用,主要用到这个类Visualizer,这个源码其实是apiDemos中一个例子,但例子中实现的是两种中的波形显示,而不是频谱显示,
原文博主实现了另一种频谱显示,并分享出来,精神可嘉。我做了些修改,使稍微好看了些,继续分享。
官方文档解释:
public int getFft (byte[] fft)
Returns a frequency capture of currently playing audio content.
This method must be called when the Visualizer is enabled.
The capture is an 8-bit magnitude FFT, the frequency range covered being 0 (DC) to half of the sampling rate returned by getSamplingRate()
. The capture returns the real and imaginary parts of a number of frequency points equal to half of the capture size plus one.
Note: only the real part is returned for the first point (DC) and the last point (sampling frequency / 2).
The layout in the returned byte array is as follows:
- n is the capture size returned by getCaptureSize()
- Rfk, Ifk are respectively the real and imaginary parts of the kth frequency component
- If Fs is the sampling frequency retuned by getSamplingRate() the kth frequency is: (k*Fs)/(n/2)
Index |
0 |
1 |
2 |
3 |
4 |
5 |
... |
n - 2 |
n - 1 |
Data |
Rf0 |
Rf(n/2) |
Rf1 |
If1 |
Rf2 |
If2 |
... |
Rf(n-1)/2 |
If(n-1)/2 |
Parameters
fft |
array of bytes where the FFT should be returned |
Returns
SUCCESS
in case of success, ERROR_NO_MEMORY
, ERROR_INVALID_OPERATION
or ERROR_DEAD_OBJECT
in case of failure.
实部和虚部的平方和就是振幅的平方,因为是byte类型,所以最大值是127。
对原文的代码做了一些修改,使更好看一些,代码中用到的歌曲谁要用到,自己重新放一首就行,代码如下:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- package com.AudioFx;
-
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.media.AudioManager;
- import android.media.MediaPlayer;
- import android.media.audiofx.Equalizer;
- import android.media.audiofx.Visualizer;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.WindowManager;
- import android.widget.LinearLayout;
- import android.widget.SeekBar;
- import android.widget.TextView;
-
- public class AudioFxActivity extends Activity
- {
- private static final String TAG = "AudioFxActivity";
-
- private static final float VISUALIZER_HEIGHT_DIP = 160f;
-
- private MediaPlayer mMediaPlayer;
- private Visualizer mVisualizer;
- private Equalizer mEqualizer;
-
- private LinearLayout mLinearLayout;
- private VisualizerView mVisualizerView;
- private TextView mStatusTextView;
- private TextView mInfoView;
-
- @Override
- public void onCreate(Bundle icicle)
- {
- super.onCreate(icicle);
-
- mStatusTextView = new TextView(this);
-
- mLinearLayout = new LinearLayout(this);
- mLinearLayout.setOrientation(LinearLayout.VERTICAL);
- mLinearLayout.addView(mStatusTextView);
-
- setContentView(mLinearLayout);
-
-
- mMediaPlayer = MediaPlayer.create(this, R.raw.my_life);
- Log.d(TAG,
- "MediaPlayer audio session ID: "
- + mMediaPlayer.getAudioSessionId());
-
- setupVisualizerFxAndUI();
- setupEqualizerFxAndUI();
-
-
-
-
- mVisualizer.setEnabled(true);
-
-
-
-
-
-
- mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
- {
- public void onCompletion(MediaPlayer mediaPlayer)
- {
- mVisualizer.setEnabled(false);
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- setVolumeControlStream(AudioManager.STREAM_SYSTEM);
- mStatusTextView.setText("音乐播放完毕");
- }
- });
-
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
- mMediaPlayer.start();
- mStatusTextView.setText("播放音乐中....");
- }
-
- private void setupEqualizerFxAndUI()
- {
-
-
-
- mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
- mEqualizer.setEnabled(true);
-
- TextView eqTextView = new TextView(this);
- eqTextView.setText("均衡器:");
- mLinearLayout.addView(eqTextView);
-
- short bands = mEqualizer.getNumberOfBands();
-
- final short minEQLevel = mEqualizer.getBandLevelRange()[0];
- final short maxEQLevel = 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");
- mLinearLayout.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((minEQLevel / 100) + " dB");
-
- TextView maxDbTextView = new TextView(this);
- maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- maxDbTextView.setText((maxEQLevel / 100) + " dB");
-
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- layoutParams.weight = 1;
- SeekBar bar = new SeekBar(this);
- bar.setLayoutParams(layoutParams);
- bar.setMax(maxEQLevel - minEQLevel);
- bar.setProgress(mEqualizer.getBandLevel(band));
-
- bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
- {
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser)
- {
- mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));
- }
-
- public void onStartTrackingTouch(SeekBar seekBar)
- {
- }
-
- public void onStopTrackingTouch(SeekBar seekBar)
- {
- }
- });
-
- row.addView(minDbTextView);
- row.addView(bar);
- row.addView(maxDbTextView);
-
- mLinearLayout.addView(row);
- }
- }
-
- private void setupVisualizerFxAndUI()
- {
- mVisualizerView = new VisualizerView(this);
- mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- (int) (VISUALIZER_HEIGHT_DIP * getResources()
- .getDisplayMetrics().density)));
- mLinearLayout.addView(mVisualizerView);
-
- mInfoView = new TextView(this);
- String infoStr = "";
-
- int[] csr = Visualizer.getCaptureSizeRange();
- if(csr != null)
- {
- String csrStr = "CaptureSizeRange: ";
- for(int i = 0; i < csr.length; i ++)
- {
- csrStr += csr[i];
- csrStr +=" ";
- }
- infoStr += csrStr;
- }
-
- final int maxCR = Visualizer.getMaxCaptureRate();
-
- infoStr = infoStr + "\nMaxCaptureRate: " + maxCR;
-
- mInfoView.setText(infoStr);
- mLinearLayout.addView(mInfoView);
-
- mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
- mVisualizer.setCaptureSize(256);
- mVisualizer.setDataCaptureListener(
- new Visualizer.OnDataCaptureListener()
- {
- public void onWaveFormDataCapture(Visualizer visualizer,
- byte[] bytes, int samplingRate)
- {
- mVisualizerView.updateVisualizer(bytes);
- }
-
- public void onFftDataCapture(Visualizer visualizer,
- byte[] fft, int samplingRate)
- {
- mVisualizerView.updateVisualizer(fft);
- }
- }, maxCR / 2, false, true);
- }
-
- @Override
- protected void onPause()
- {
- super.onPause();
-
- if (isFinishing() && mMediaPlayer != null)
- {
- mVisualizer.release();
- mEqualizer.release();
- mMediaPlayer.release();
- mMediaPlayer = null;
- }
- }
-
-
-
-
-
- class VisualizerView extends View
- {
- private byte[] mBytes;
- private float[] mPoints;
- private Rect mRect = new Rect();
-
- private Paint mForePaint = new Paint();
- private int mSpectrumNum = 48;
- private boolean mFirst = true;
-
- public VisualizerView(Context context)
- {
- super(context);
- init();
- }
-
- private void init()
- {
- mBytes = null;
-
- mForePaint.setStrokeWidth(8f);
- mForePaint.setAntiAlias(true);
- mForePaint.setColor(Color.rgb(0, 128, 255));
- }
-
- public void updateVisualizer(byte[] fft)
- {
- if(mFirst )
- {
- mInfoView.setText(mInfoView.getText().toString() + "\nCaptureSize: " + fft.length);
- mFirst = false;
- }
-
-
- byte[] model = new byte[fft.length / 2 + 1];
-
- model[0] = (byte) Math.abs(fft[0]);
- for (int i = 2, j = 1; j < mSpectrumNum;)
- {
- model[j] = (byte) Math.hypot(fft[i], fft[i + 1]);
- i += 2;
- j++;
- }
- mBytes = model;
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas)
- {
- 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());
-
-
-
-
-
-
-
-
-
-
-
-
- final int baseX = mRect.width()/mSpectrumNum;
- final int height = mRect.height();
-
- for (int i = 0; i < mSpectrumNum ; i++)
- {
- if (mBytes[i] < 0)
- {
- mBytes[i] = 127;
- }
-
- final int xi = baseX*i + baseX/2;
-
- mPoints[i * 4] = xi;
- mPoints[i * 4 + 1] = height;
-
- mPoints[i * 4 + 2] = xi;
- mPoints[i * 4 + 3] = height - mBytes[i];
- }
-
- canvas.drawLines(mPoints, mForePaint);
- }
- }
- }
运行效果如下:
跟上一篇一样,完全参考自google源码,如果可以自己去看是最好的
否则你就要看我的个人理解了
EQ应该就是频率均衡器,适当的调整和控制可以设置重低音,古典,摇滚之类的感觉
主要的类就是android.media.audiofx.Equalizer;
//many application can control equalizer ,so we need priotiry
//首先初始化这个类,需要两个参数,第一个是优先级,默认是0.所谓优先级就是说当有多个应用同时去控制EQ的时候,就靠优先级来判断了。第二个参数是音乐的sessionId.
mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
mEqualizer.setEnabled(true);
//可以得到当前Equalizer 引擎所支持的控制频率的标签数目。
short bands = mEqualizer.getNumberOfBands();
//可以得到的最小频率(我这是-15dB)
short minEQLevel = mEqualizer.getBandLevelRange()[0];
//可以得到的最大频率(我这是15dB)
short maxEQLevel = mEqualizer.getBandLevelRange()[1];
for (short i = 0; i < bands; i++) {
final short band = i;
//通过标签可以顺次的获得所有你所支持的频率的名字比如 60Hz 230Hz
freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz");
......
//接下来就是最重要的方法 设置频率的值了,需要提供标签号,和设置的大小data。这个data要记住其最小值是上面得到的minEQLevel,最大值是maxEQLevel.
mEqualizer.setBandLevel(band, (short) data);
}
以上就可以搞定了。
如果你不知道 自己手上那些频率都代表什么效果 我就顺手转载网上的知识吧
均衡器分段后的每个部分的作用:
1. 20Hz--60Hz部分
这一段提升能给音乐强有力的感觉,给人很响的感觉,如雷声。是音乐中强劲有力的感觉。如果提升过高,则又会混浊不清,造成清晰度不佳,特别是低频响应差和低频过重的音响设备。
2. 60Hz--250Hz部分
这段是音乐的低频结构,它们包含了节奏部分的基础音,包括基音、节奏音的主音。它和高中音的比例构成了音色结构的平衡特性。提升这一段可使声音丰满,过度提升会发出隆隆声。衰减这两段会使声音单薄。
3. 250Hz--2KHz部分
这段包含了大多数乐器的低频谐波,如果提升过多会使声音像电话里的声音。如把600Hz和1kHz过度提升会使声音像喇叭的声音。如把3kHz提升过多会掩蔽说话的识别音,即口齿不清,并使唇音“mbv”难以分辨。如把1kHz和3kHz过分提升会使声音具有金属感。由于人耳对这一频段比较敏感,通常不调节这一段,过分提升这一段会使听觉疲劳。
4. 2KHz--4kHz部分
这段频率属中频,如果提升得过高会掩盖说话的识别音,尤其是3kHz提升过高,会引起听觉疲劳。
5. 4kHz--5KHz部分
这是具有临场感的频段,它影响语言和乐器等声音的清晰度。提升这一频段,使人感觉声源与听者的距离显得稍近了一些;衰减5kHz,就会使声音的距离感变远;如果在5kHz左右提出升6dB,则会使整个混合声音的声功率提升3dB。
6. 6kHz--16kHz部分
这一频段控制着音色的明亮度,宏亮度和清晰度。一般来说提升这几段使声音宏亮,但不清晰,不可能会引起齿音过重,衰减时声音变得清晰,但声音不宏亮。