android 实现跳动频谱 DEMO
- package com.terry.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.MediaPlayer.OnCompletionListener;
- import android.media.audiofx.Equalizer;
- import android.media.audiofx.Visualizer;
- import android.media.audiofx.Visualizer.OnDataCaptureListener;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.LinearLayout;
- import android.widget.SeekBar;
- import android.widget.TextView;
- import android.widget.SeekBar.OnSeekBarChangeListener;
- public class AudioFxActivity extends Activity {
- private static final String TAG = "AudioFxActivity";
- private static final float VISUALIZER_HEIGHT_DIP = 50f;
- private MediaPlayer mMediaPlayer;
- private Visualizer mVisualizer;
- private Equalizer mEqualizer; // 均衡器
- private LinearLayout mLayout;
- VisualizerView mVisualizerView;
- private TextView mStatusTextView;
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
- mStatusTextView = new TextView(this);
- mLayout = new LinearLayout(this);
- mLayout.setOrientation(LinearLayout.VERTICAL);
- mLayout.addView(mStatusTextView);
- setContentView(mLayout);
- mMediaPlayer = MediaPlayer.create(this, R.raw.z8806c);
- 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("播放中。。。");
- }
- /**
- * 通过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);
- }
- @Override
- protected void onPause() {
- // TODO Auto-generated method stub
- super.onPause();
- if (isFinishing() && mMediaPlayer != null) {
- mVisualizer.release();
- mMediaPlayer.release();
- mEqualizer.release();
- mMediaPlayer = null;
- }
- }
- 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);
- }
- }
- }
android 实现跳动频谱 DEMO的更多相关文章
- 解决Android微信支付官方demo运行失败
Android微信支付官方demo运行失败,在此简单记录一下解决步骤 1.httpclient错误 官方给的demo是eclipse的,打开之后提示httpclient的错误,我知道在as下解决htt ...
- Android JNI学习(五)——Demo演示
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- Android之ViewPager循环Demo
ViewPager是谷歌官方提供的兼容低版本安卓设备的软件包,里面包含了只有在安卓3.0以上可以使用的api.Viewpager现在也算是标配了,如果一个App没有用到ViewPager感觉还是比较罕 ...
- Android studio百度地图demo出现230错误,key校验失败
转自daoxiaomianzi原文 Android studio 百度地图demo出现230错误,key校验失败 使用AndroidStudio导入Baidu地图的as版的demo,引入后,发现没有k ...
- Android第一代壳demo编写
Android第一代壳Demo编写 前言 这篇文章是对姜维大佬的这篇文章[Android中的Apk的加固(加壳)原理解析和实现]的补充.建议先看一编姜维大佬的这篇文章再看. 姜维大佬写那篇文章的时间距 ...
- Android -- 自定义View小Demo,动态画圆(一)
1,转载:(http://blog.csdn.NET/lmj623565791/article/details/24500107),现在如下图的效果: 由上面的效果图可以看到其实是一个在一个圆上换不同 ...
- 转:android surface简单使用Demo
转: http://blog.csdn.net/listening_music/article/details/6860786 通过之前介绍的如何自定义View, 我们知道使用它可以做一些简单的动画效 ...
- 转:android 录制视频的Demo
转:http://blog.csdn.net/peijiangping1989/article/details/7049991 在这里给出自己的一个测试DEMO,里面注释很详细.简单的视频录制功能. ...
- android Popupwindow 的一个demo源码
一直想用一下PopupWindow,就是苦于没有demo,自己去研究有太懒,刚好最近研究推送,下载了一个腾讯信鸽的demo,里面用到了一个PopupWindow,效果还不错,弄下来记录一下: 1.核心 ...
随机推荐
- 驱动: 中断【1】linux中断流程
通常情况下,当一个给定的中断处理程序正在执行时,所有其他的中断都是打开的,所以这些不同中断线上的其他中断都能被处理,但当前中断总是被禁止的. 将中断处理切为两个部分或两半.中断处理程序上半部(top ...
- FileDescriptor
FileDescriptor 在java中的java.io包下面 public final class FileDescriptor { ... } 官方的解释: 文件描述符类的实例用作与基础机器有关 ...
- Week8(10月31日):并发
Part I:提问 =========================== 1. 更新关联.删除关联数据,需要注意哪些问题?以Instructor类为例说明. 2. 已知某请假系统,请实现以下界面的 ...
- larbin是一种开源的网络爬虫/网络蜘
larbin是一种开源的网络爬虫/网络蜘蛛,由法国的年轻人 Sébastien Ailleret独立开发.larbin目的是能够跟踪页面的url进行扩展的抓取,最后为搜索引擎提供广泛的数据来源.Lar ...
- HTML5实现IP Camera网页输出
HTML5实现IP Camera网页输出 这两天做OA项目.有一个要通过IP Camera将视频流输出到浏览器端的模块.尽管如今买到的摄像头都会提供浏览器和client的实现,可是一般来说都是仅仅支持 ...
- vector的成员函数解析
vector是线性容器,它的元素严格的依照线性序列排序,和动态数组非常相似,和数组一样,它的元素存储在一块连续的存储空间中,这也意味着我们不仅能够使用迭代器(iterator)訪问元素,还能够使用指针 ...
- PHP - session编码和解码
<?php //session编码 session_start(); $_SESSION['name'] = 'Jack'; $_SESSION['sex'] = 'men'; $envar = ...
- BZOJ 3477: [Usaco2014 Mar]Sabotage( 二分答案 )
先二分答案m, 然后对于原序列 A[i] = A[i] - m, 然后O(n)找最大连续子序列和, 那么此时序列由 L + mx + R组成. L + mx + R = sum - n * m, s ...
- QTabWidget 实现类似QQ聊天窗口(拖动分离出新的窗口)
新版本的QQ聊天窗口可以实现拖动,分离出新的窗口.浏览器等软件也可以实现类似操作.所以心血来潮想用Qt实现类似的功能.想用QTabWidget直接实现是很难的,仔细阅读源码,发现QTabWidget内 ...
- PHP - 遍历文件夹下的所有文件名
/** * * 函数名:myreaddir($dir) * 作用:读取目录所有的文件名 * 参数:$dir 目录地址 * 返回值:文件名数组 * * */ function myreaddir($di ...