最近由于需要实现音乐频谱,所以今天就为大家普及一下。
关于音乐频谱你需要了解数字信号处理的知识,尤其是FFT的知识。
简单说就是把时域上连续的信号(波形)强度转换成离散的频域信号(频谱)。
我理解波形就是信号的强度,或者说音响设备的输出的功率,功率高,音量就大。
但是歌曲的曲调是不会变的,因为频谱是不会变的。
频谱反映的是这个这个音乐在某个连续时间段内,声音的震动频率。
不知道理解的对不对。
本文的音乐频谱实现是仿照Android Api Demo 里的一个例子实现的,需要
Android 2.3及以上系统,因为要用到Visualizer 类,这个类只在Android 2.3以上的API才支持。
首先实例化Visualizer,参数SessionId可以通过MediaPlayer的对象获得
rate, 表示采样的周期,即隔多久采样一次,联系前文就是隔多久采样128个数据,本文设置为512mHz更新一次
iswave,是波形信号
isfft,是FFT信号,表示是获取波形信号还是频域信号
OnDataCaptureListener,表监听函数,匿名内部类实现该接口,该接口需要实现两个函数
-
public
void
onFftDataCapture(Visualizer visualizer,
byte
[] fft,
int
samplingRate)
samplingRate是采样速率,即上文的rate值,512mHz。
其中两个byte[] waveform和byte[] fft数组,分别是获得波形数据和FFT的数据,该byte数组的大小即为之前设置的采样值大小128,获得数据如下图所示。
其中n为采样值,index 0 表示直流分量,Rf表示FFT计算后的实部,If表示FFT计算后的虚部。
如何计算出该频率,就是将FFT的实部和对应的虚部先各自平方再相加然后开方,简单说就是平方取模。
具体计算请看如下的代码。
-
visualizer.setDataCaptureListener(
-
new
Visualizer.OnDataCaptureListener() {
-
-
@Override
-
public
void
onWaveFormDataCapture(Visualizer visualizer,
-
byte
[] waveform,
int
samplingRate) {
-
-
-
-
-
-
}
-
-
@Override
-
public
void
onFftDataCapture(Visualizer visualizer,
-
byte
[] fft,
int
samplingRate) {
-
byte
[] model =
new
byte
[fft.length /
2
+
1
];
-
model[
0
] = (
byte
) Math.abs(fft[
1
]);
-
int
j =
1
;
-
-
for
(
int
i =
2
; i <
18
;) {
-
model[j] = (
byte
) Math.hypot(fft[i], fft[i +
1
]);
-
i +=
2
;
-
j++;
-
}
-
-
visualView.updateVisualizer(model);
-
-
}
-
}, Visualizer.getMaxCaptureRate() /
2
,
false
,
true
);
-
-
}
-
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() -
50
);
-
-
for
(
int
i =
0
; i <
9
; i++) {
-
-
if
(mBytes[i] <
0
)
-
mBytes[i] =
127
;
-
-
mPoints[i *
4
] = mRect.width() * i /
9
;
-
mPoints[i *
4
+
1
] = mRect.height() /
2
;
-
mPoints[i *
4
+
2
] = mRect.width() * i /
9
;
-
mPoints[i *
4
+
3
] =
2
+ mRect.height() /
2
+ mBytes[i];
-
}
-
canvas.drawLines(mPoints, mForePaint);
-
}
-
-
}
最近由于需要实现音乐频谱,所以今天就为大家普及一下。关于音乐频谱你需要了解数字信号处理的知识,尤其是FFT的知识。简单说就是把时域上连续的信号(波形)强度转换成离散的频域信号(频谱)。我理解波形就是信号的强度,或者说音响设备的输出的功率,功率高,音量就大。但是歌曲的曲调是不会变的,因为频谱是不会变的。频谱反映的是这个这个音乐在某个连续时间段内,声音的震动频率。不知道理解的对不对。本
import
android
.app.Activity;
import
android
.content.Context;
import
android
.graphics.Canvas;
import
android
.graphics.Color;
import
android
.graphics.Paint;
import a...
Library is available in jcenter repository
How to use
Refer to the sample project on how to use visualizer or refer to WIKI docs.
Visualizers
LineVisualizer
BarVisualizer
CircleVisualizer
Circle Bar Visualizer
Line Bar Visualizer
License
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance
觉的这是一个好玩的东西,可以将耳边动听的声音形象化,仿佛眼前可以看到声音一样。
但是我在文档的开发者指南里没有讲任何有关
音乐频谱
的东西,最后还是在google的源码示例中找到了。
你可以直接去参看源代码更原滋原味 以下只是个人对着源码的重构和理解
所有以下所讲的功能,均需要在2.3以上的sdk中才能
实现
。
前一段实习,本来打算做c++,到了公司发现没啥项目,于是乎转行做了
android
,写的第一个程序竟然要我
处理
信号,咱可是一心搞计算机的,没接触过信号的东西,什么都没接触过,于是乎, 找各种朋友,各种熟人,现在想想,专注语言是不对的,语言就是一工具,关键还是业务,算法。好了,废话不多说,上程序,注释都很详细,应该能看懂。
分析声音,其实很简单,就是运用傅里叶变换,将声音信号由时域转...
android
:layout_width="320dp"
android
:layout_height="300dp"
android
:layout_gravity="center"
app:color_center="@color/r
如果你想在
Android
应用程序中
实现
音乐频谱
,可以使用
Android
的Media Player类来获取音频
数据
。然后,你可以使用FFT(快速傅里叶变换)算法将音频
数据
转换为频谱
数据
。最后,你可以使用Canvas和Paint类在屏幕上绘制频谱图。
以下是一个简单的
实现
方法:
1. 在你的
Android
应用程序中,创建一个MediaPlayer对象并设置音频资源:
```java
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.song);
2. 创建一个Visualizer对象,并将其连接到MediaPlayer对象:
```java
Visualizer visualizer = new Visualizer(mediaPlayer.getAudioSessionId());
visualizer.set
Capture
Size(Visualizer.get
Capture
SizeRange()[1]);
visualizer.set
Data
Capture
Listener(new Visualizer.On
Data
Capture
Listener() {
@Override
public void on
Wav
e
Form
Data
Capture
(Visualizer visualizer, byte[]
wav
e
form
, int samplingRate) {
//
处理
波形
数据
@Override
public void onFft
Data
Capture
(Visualizer visualizer, byte[] fft, int samplingRate) {
//
处理
FFT
数据
}, Visualizer.getMax
Capture
Rate() / 2, true, true);
visualizer.setEnabled(true);
3. 在onFft
Data
Capture
回调方法中,将FFT
数据
转换为频谱
数据
,然后绘制频谱图。以下是一个简单的FFT转换方法:
```java
private void trans
form
FFT(byte[] fft) {
int[] buffer = new int[fft.length / 2];
for (int i = 0, j = 0; i < fft.length; i += 2, j++) {
buffer[j] = (fft[i] & 0xFF) | (fft[i + 1] & 0xFF) << 8;
DoubleFFT_1D fftTrans
form
= new DoubleFFT_1D(buffer.length);
double[] fft
Data
= new double[buffer.length * 2];
for (int i = 0; i < buffer.length; i++) {
fft
Data
[i * 2] = buffer[i];
fftTrans
form
.realForwardFull(fft
Data
);
//
处理
FFT
数据
4. 在
处理
FFT
数据
后,可以使用Canvas和Paint绘制频谱图。以下是一个简单的绘图方法:
```java
private void drawSpectrum(Canvas canvas, Paint paint, float[] spectrum) {
float barWidth = (float) getWidth() / spectrum.length;
float barHeight;
float x = 0;
for (int i = 0; i < spectrum.length; i++) {
barHeight = (spectrum[i] + 128) * 2;
canvas.drawRect(x, getHeight() - barHeight, x + barWidth, getHeight(), paint);
x += barWidth + 1;
以上是一个简单的
实现
方法,你可以根据实际需要进行调整和优化。