相关文章推荐
越狱的鼠标  ·  eslint - ...·  4 月前    · 
强悍的大蒜  ·  Prevent Cross-Site ...·  6 月前    · 
健身的苦瓜  ·  VLC核显编解码简介 + ...·  9 月前    · 
坐怀不乱的大葱  ·  React项目 fetch ...·  1 年前    · 

https://blog.csdn.net/aiynmimi/article/details/53189076 (Android音频进阶 Equalizer,Visualizer,BassBoost,PresetReverb,EnvironmentalReverb)

https://www.cnblogs.com/sage-blog/p/3885802.html (JNI实例1---扫描SD卡中mp3文件 JNI实例2---扫描SD卡中mp3文件,native层调用Java自定义的类 JNI实例3---扫描SD卡中mp3文件,native层调用Java自定义的类)

做了个音乐播放器 就一直想做个加一个音乐频谱的展示界面

觉的这是一个好玩的东西,可以将耳边动听的声音形象化,仿佛眼前可以看到声音一样。

但是我在文档的开发者指南里没有讲任何有关音乐频谱的东西,最后还是在google的源码示例中找到了。

你可以直接去参看源代码更原滋原味 以下只是个人对着源码的重构和理解

所有以下所讲的功能,均需要在2.3以上的sdk中才能实现。

音频频谱的获取

首先音频的频谱相关的类叫做 android.media.audiofx.Visualizer;

需要权限 所以要做的第一件事 是初始化一个visualizer出来

//使用音乐的sessionId来实例化这个类

mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());

//设置每次捕获频谱的大小,音乐在播放中的时候采集的数据的大小或者说是采集的精度吧,我的理解,而且getCaptureSizeRange()所返回的数组里面就两个值 .文档里说数组[0]是最小值(128),数组[1]是最大值(1024)。

mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);

//接下来就好理解了设置一个监听器来监听不断而来的所采集的数据。一共有4个参数,第一个是监听者,第二个单位是毫赫兹,表示的是采集的频率,第三个是是否采集波形,第四个是是否采集频率

mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {

//这个回调应该采集的是波形数据

[@Override](https://my.oschina.net/u/1162528)

public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform,

int samplingRate) {

//waveformView 是一个自定义的view用来按照波形来画图 一会后面再讲

waveformView.updateVisualizer(waveform);

//这个回调应该采集的是快速傅里叶变换有关的数据,没试过,回头有空了再试试

[@Override](https://my.oschina.net/u/1162528)

public void onFftDataCapture(Visualizer visualizer, byte[] fft,

int samplingRate) {

// TODO Auto-generated method stub

}, Visualizer.getMaxCaptureRate() / 2, true, false);

以上波形的数据采集就完成了,需要注意的一个点是mVisualizer.setEnabled(true);

这个方法的主要作用是为了控制何时去采集频谱数据,你应该只是愿意采集你所关心的音乐数据,而不关心声音输出器中任何的声音。而且对mVisualizer的许多设置必须在setEnable之前完成。并且结束功能后,要记得setEnable(false)

如果你见到了以下这个错误,那基本上就是因为没有及时setEnable(false),导致setCaptureSize()这个方法出错。

E/AndroidRuntime(22259): Caused by: java.lang.IllegalStateException: setCaptureSize() called in wrong state: 2

顺带再说一个bug 如果你得到的错误代码是 -1 那么基本上的原因是你忘记了声明权限

音频频谱的展示

你在上一节已经通过监听器获得了波形数据,那么如何展示?这仅仅是一个自定义view的问题,简单废话一下:重点提一下view中的onDraw()方法

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);

//mBytes就是采集来的数据 这里是个大小为1024的数组,里面的数据都是byts类型,所以大小为-127到128

if (mBytes == null) {

return;

if (mPoints == null || mPoints.length < mBytes.length * 4) {

//mPoints主要用来存储要画直线的4个坐标(每个点两个坐标,所以一条直线需要两个点,也就是4个坐标) mPoints = new float[mBytes.length * 4]; }

mRect.set(0, 0, getWidth(), getHeight());

//xOrdinate是x轴的总刻度,因为一次会传输过来1024个数据,每两个数据要画成一条直线,所以x轴我们分成1023段。你要是觉的太多了,也可以像我一样除以2,看自己需求了。

int xOrdinate = (mBytes.length - 1)/2;

//以下的for循环将利用mBytes[i] mBytes[i+1] 这两个数据去生成4个坐标值,从而在刻画成两个坐标,来画线条 for (int i = 0; i

//第i个点在总横轴上的坐标,

mPoints[i * 4] = mRect.width() * i / xOrdinate;

//第i个点的在总纵轴上的坐标。他在画线上以总纵轴的1/2为基准线(mRect.height() / 2),所有的点或正或负以此线为基础标记。

//((byte) (mBytes[i] + 128))这个一直没有理解,如果+128是为了将数据全部换算为正整数,那么强转为byte后不又变回-127到128了么??要是谁知道原因可以留言告诉我.....

//(mRect.height() / 2) / 128就是将二分之一的总长度换算成128个刻度,因为我们的数据是byte类型,所以刻画成128个刻度正好 mPoints[i * 4 + 1] = mRect.height() / 2+ ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;

//以下就是刻画第i+1个数据了,原理和刻画第i个一样 mPoints[i * 4 + 2] = mRect.width() * (i + 1) / xOrdinate; mPoints[i * 4 + 3] = mRect.height() / 2 + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128; }

//循环结束后,就得到了这一次波形的所有刻画坐标,直接画在画布上就好了

canvas.drawLines(mPoints, mForePaint);

做的音乐软件 纯粹好玩 就放在了国内的market上

给定原始的 音频 信号,通过melspectrogram()函数提取梅尔 频谱 ,然后通过DCT离散余弦变换得到梅尔倒谱系数。Mel滤波器对应了频率提高之后人耳会迟钝的客观规律,所以Mel滤波器在人声的信号处理上有着广泛的使用,但是如果应用到非人声上,就会丢失很多高频信息。输入语音信号->预加重->分针->加窗->FFT(傅里叶变换)->Mel滤波器->对数运算->DCT(离散预先变换)->MFCC。这是MFCC(梅尔倒谱)的提取过程,而梅尔 频谱 则是经过Mel滤波器就直接输出的一个结果。.............. ** SpectrumFor Android ** 这是一个 Android 平台的 音乐 频谱 合集,把 音频 能量用canvas画出来,至于 频谱 数据的 获取 或者傅里叶转换之类的不在本篇范畴,网上教程一大把 有需要的童鞋可以拿来一看 No picture u say a j8! 少啰嗦,先看效果 个人兴趣,本项目会持续更新 By SSS 开发用 Eclipse,检验用 Eclipse 和 MATLAB。本次项目位于项目文件夹 FFT2_backup,一个类一个 Java 文件,所有类在 priv.Zhanghao.FFT 包,Bignumber 类:验证 Java 计算存在的误差以及解决方法;Complex 类:实现了复数及其加减乘除运算;Demo 类:主类,实现了调用其他类,开启线程等;DFT 类:实现了 DFT 运算;FFT 类:实现了 FFT 运算的两种方法、倒叙、返回一个数是 2 的几次幂; 第一步先判断是不是第一个矩形,如果是第一个,那么第一个矩形的左边距就等于=0或者你需要设置的左边距即可,右边距就等于=左边距+矩形的宽度+2个矩形的间距。第二步判断非0个矩形,name左边距就等于上一一个的右边距+2个矩形之间的间距代码如上。先说下这个自定义view也不难很简单,就是绘制矩形,唯一的难点在于计算矩形的坐标。上面代码是针对图2的,如果需要看图一的完整代码我提供一份都在一个项目中。高度好说动态设置就好,top直接设置动态,bottom直接是固定的值。看下SurfaceView完整代码吧。.... 喜欢听 音乐 的朋友想必都知道,有很多 音乐 播放软件(如:千千静听),里面都会有一个能够伴随着 音乐 的节奏在不断变化的 频谱 。由于之前我也在开发一个 音乐 播放器,也有在琢磨这个功能的实现,然后我就自己写了一个自定义组件,随机生成 频谱 ,虽说是随机生成可能对不上 音乐 的节奏,但是播放器中有没有这个组件的差别完全是天差地别啊。下面我就将我的想法分享给大家。 Android 音频 开发 目录一、演示image二、实现实现流程:使用MediaPlayer播放传入的 音乐 ,并拿到mediaPlayerId使用Visualizer类拿到拿到MediaPlayer播放中的 音频 数据(wave/fft)将数据用自定义控件展现出来三、准备工作使用Visualizer需要录音的动态权限, 如果播放sd卡 音频 需要STORAGE权限private static final ... 在做 音乐 播放器、 音频 编辑软件,录音软件、 音频 相关其他软件时,经常有显示 音频 频谱 这种需求;通过 音频 频谱 图可以很直观的显示 音乐 里声音的高低情况。 接下来会连续通过几篇文章来介绍各种需求下的 频谱 图实现方式。 package com.goobird.common.basic.utils.audio; import java .io.BufferedWriter; import java .io.File; import java .io.FileWriter; import java .io.FileOutputStream; import java .i... 使用librosa和matplot,我们可以用10行代码完整地 展示 整个 频谱 : import matplotlib.pyplot as plt import librosa.display 音乐 文件载入 audio_path = ‘Fenn.mp3’ music, sr = librosa.load(audio_path) 宽高比为14:5的图 plt.figure(figsize=(14, 5)) librosa.display.waveplot(music, sr=sr) 觉的这是一个好玩的东西,可以将耳边动听的声音形象化,仿佛眼前可以看到声音一样。 但是我在文档的开发者指南里没有讲任何有关 音乐 频谱 的东西,最后还是在google的源码示例中找到了。 你可以直接去参看源代码更原滋原味  以下只是个人对着源码的重构和理解 所有以下所讲的功能,均需要在2.3以上的sdk中才能实现。