
你是获取手机内存里面的音乐吗?如果是你应该先获取音乐文件的路径,你在服务中通过mediaplayersetdatasource(currentMusicgetpath)来获取当前avtivity发送过来的当前音乐对象,在music类中用mediaStroseAdeiomedia来获取音乐文件的歌名,歌手和歌曲存放的路径。
小米手机播放音乐时锁屏页面可以设置音频可视化效果,这是用OpenGL绘制出来的,我们来实现一下。
首先简单分析一下原理:
图形的每一行代表一个声音片段,它就是一个一维数组,按照数值大小绘制不同的高度,就形成了一条“山脉”;获取到下一个声音片段后,将它绘制到下面一行,然后画面整体向上滚动就可以了。整体类似于绘制一张游戏里常见的3D地形图。
创建一个MediaPlayer,它可以直接读取res/raw里面的音频文件,start()开始播放
Visualizer是Android SDK里面提供的音频分析工具,它可以直接获取播放的音频的波形和频谱。onWaveFormDataCapture回调方法里返回的是原始的PCM波形数组,onFftDataCapture回调方法里返回的是经过快速傅里叶方法转换后的声音频谱数组,数组的第一位是直流分量,后面是不同频率的数值。
每次获取到的是一组声音数据,将它传给Render绘制。
首先确定图形的长宽,宽度w其实是由每组音频的数组长度决定,可以由VisualizergetCaptureSizeRange()[0]获取,这里获取的是最小的数组,也可以用VisualizergetCaptureSizeRange()[1]获取最大的数组;长度h可以自己设置想展示多长。
绘制地形图也就是绘制w h 2个三角形,创建vao、vbo和ebo,由于顶点的位置都是固定的,可以在顶点着色器中用gl_VertexID获取,所以vbo里面不用传顶点数据,直接传声音数组。
由于图形是不断刷新最后一行并向上滚动的,那么需要使用一个队列,为了每一帧数据改变最小,不至于进行大量的数组复制和移动。我们 用ByteBuffer vertexBuffer模拟一个循环队列,使用一个行号int lineNum来标记队列的头部。每添加一行数据后,lineNum会加上w,这样ByteBuffer分成了两部分:lineNum w之后的是新旧数据,之前的是旧数据 。
现在我们需要将数据从主内存(vertexBuffer)复制到GPU显存(vbo)。vertexBuffer里是一个循环队列,而vbo里面只能顺序保存(因为ebo序号是顺序的,vbo不是顺序图形就会错乱),更新vbo数据缓存的glBufferSubData方法支持设置偏移位置部分更新。那么我们 先将vertexBuffer定位到lineNum w,将它后面的旧数据复制到vbo的前面;然后将vertexBuffer定位到0,将剩下的新数据复制到vbo的后面 。这样就保证了绘制时从上到下,从旧到新。
为了让颜色更丰富,这里用了地形图中常用的热度渐变色数组。
理论上音频数值是unsigned byte格式的,但是着色器不支持byte格式,我直接用int vPosition接收数据,然而数值范围不再是0~255了,这有点奇怪,我没有深入研究。简单测试了一下,发现取int的前8位,再进行一点比例缩放,用它去渐变色数组里取颜色,会取得较好的显示效果。
顶点着色器
shader_audio_vglsl
将颜色传给片段着色器显示
shader_audio_fglsl
最终效果如下图,录屏设置的码率比较低,实际上是很清晰的。
完整项目在 SurfacePaint 项目下的 opengles3 模块里的audio。
最近需要在Android的客户端中使用PCM声音播放和录制,简单学习了一下。有不正确的地方还请指出。
首先有几个概念需要了解一下:采样频率、声道数、采样位数。
采样频率一般是sample rate, 代表的是数字化音频时每秒采样的次数。常见的有441KHz(CD品质)、48KHz等。
这个很好理解,单声道Mono就是声音从一个方向传出来;双声道Stereo也叫立体声,声音是从两个方向传来。通常的流行音乐中,仔细听能发现每个声道可能侧重不同的乐曲声部,比如左声道吉他,右声道钢琴,人声似乎两个声道都有,听起来就像站在中间一样。(这里没有考证,随便举例)
每一个采样都是一个数据点,采样位数是指这个数据点使用了几位来记录。AudioTrack类只支持8位和16位的PCM音频。8位就是2的8次方,即256个值;而16位则是2的16次方,有65536个值。
这个在音频的编解码中还是比较常用的。在PCM格式中,1秒钟音频的数据大小是SampleRate×Channel×Bit/8,单位是byte字节。由于PCM本身没有音频帧的概念,所以通过这个公式就能计算出任意时长音频的大小,或者得到任意大小音频的时长。如果规定1个音频帧是“每个声道256个采样”,双声道下就是512个采样,那么1帧的数据量就是256×Channel×Bit/8,同理可以推断出1秒钟有多少音频帧等等。音频帧的概念在各种编解码中各有不同,但计算公式大同小异,这里不展开。
Android中音频的播放使用的是AudioTrack类,具体用法非常简单。
首先设置buffer大小。AudioTrack播放时需要先写入buffer,如果这个buffer没有写满,那么这部分是不会播放的。所以buffer不能设置太小,这样会导致播放不连贯;而buffer也不能设置太小,这样不间断写入会消耗许多CPU资源。AudioTrack自带了getMinBufferSize方法可以给出一个最小buffer,一般用这个值就可以。getMinBufferSize方法三个参数分别是sample rate、channel和bit。
设置完buffer size就可以实例化一个AudioTrack。其中第一个参数streamType是指不同的音频流类型,包括STREAM_MUSIC、STREAM_ALARM、STREAM_VOICE_CALL、STREAM_RING等,是Android对不同音频的分类。中间三个参数很好理解,第四个是buffer size,刚刚计算出来了。最后一个参数mode有两种:MODE_STREAM和MODE_STATIC。前者是以流形式播放,后者则是一次性全部写入然后播放。
调用实例的play()方法就可以开始播放了。不过播放得要有数据吧?要填写数据就要用到write()方法。write方法中第一个参数是一个byte[]类型,是要写入的数据源,可以是从文件流中读取出来的;第二个参数offset是初始位移,即从source的哪个位置开始;第三个参数则是输入长度。
当write方法写满一个AudioTrack的buffer时,就会有声音播放出来了。
当播放完成后记得要把AudioTrack停止并释放。
MediaMetadataRetriever是Android原生提供的获取音视频文件信息的一个类,我们可以通过这个类的相关方法获取一些基本信息,如视频时长、宽高、帧率、方向、某一帧的等。
我们可以通过MediaMetadataRetriever的extractMetadata(int keyCode)的方法获取一些视频的基本信息,以下列出一些常用的:
可以通过getFrameAtTime(long timeUs)获取某一时刻附近的帧;API>=28,可以准确获取帧,相关方法getFrameAtIndex();获取帧图可以应用在 视频封面图 、 视频裁剪的缩略图 等。
MediaMetadataRetriever还是比较常用的,以上只是简略的列出了MediaMetadataRetriever的一些用法,具体可自行查阅源文件。
以上就是关于android开发如何获得歌曲信息全部的内容,包括:android开发如何获得歌曲信息、Android OpenGLES3绘图 - 音频可视化(模仿MIUI系统效果)、Android音频播放等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)