Android 实时获取麦克风输入音量的代码

来源:互联网 发布:json encode 不转义 编辑:程序博客网 时间:2024/06/08 03:11

http://www.mikespook.com/index.php/archives/762

Android 上有一些很有趣的应用,例如《吹裙子》、《吹气球》之类的。利用的是实时获取麦克风输入音量,然后进行相应的处理。网上也不少人问如何处理这个事情,也有一些解答,不过都没有实际的代码。简单摸索了一下,写了个小 Demo 试了试,果然可以。给大家共享一下。
不解释代码了,大家看注释。

package com.xxiyy.spl;

 

import android.media.AudioFormat;

import android.media.AudioRecord;

import android.media.MediaRecorder;

import android.util.Log;

 

public class RecordThread extends Thread {

    private AudioRecord ar;

    private int bs;

    private static int SAMPLE_RATE_IN_HZ = 8000;

    private boolean isRun = false;

 

    public RecordThread() {

        super();

        bs = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,

                AudioFormat.CHANNEL_CONFIGURATION_MONO,

                AudioFormat.ENCODING_PCM_16BIT);

        ar = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE_IN_HZ,

                AudioFormat.CHANNEL_CONFIGURATION_MONO,

                AudioFormat.ENCODING_PCM_16BIT, bs);

    }

 

    public void run() {

        super.run();

        ar.startRecording();

                // 用于读取的 buffer

        byte[] buffer = new byte[bs];

        isRun = true;

        while (isRun) {

            int r = ar.read(buffer, 0, bs);

            int v = 0;

                        // 将 buffer 内容取出,进行平方和运算

            for (int i = 0; i < buffer.length; i++) {

                // 这里没有做运算的优化,为了更加清晰的展示代码

                v += buffer[i] * buffer[i];

            }

            // 平方和除以数据总长度,得到音量大小。可以获取白噪声值,然后对实际采样进行标准化。

            // 如果想利用这个数值进行操作,建议用 sendMessage 将其抛出,在 Handler 里进行处理。

            Log.d("spl", String.valueOf(v / (float) r));

        }

        ar.stop();

    }

 

    public void pause() {

                // 在调用本线程的 Activity 的 onPause 里调用,以便 Activity 暂停时释放麦克风

        isRun = false;

    }

 

    public void start() {

                // 在调用本线程的 Activity 的 onResume 里调用,以便 Activity 恢复后继续获取麦克风输入音量

        if (!isRun) {

            super.start();

        }

    }

}

This entry was posted on Monday, November 8th, 2010 at 20:02 and is filed under android. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhjp4295216/archive/2010/11/09/5996735.aspx





Android AudioManager控制系统声音的流程


http://shazhuzhu1.iteye.com/blog/967229

首先上层java调用

XXXPlayer

AudioManager audiomanage = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

audiomanager就是我们定义的控制系统声音的对象,(如果context报错,可将其改成XXXPlayer.this)

audiomanager.SetStreamVolume(AA,BB,CC),是我们可以直接使用的AudioManager的成员函数,3个参数表示的意思:AA:有内置的常量,可以在AudioManager里面查到相关的定义,我们在此用 AudioManager.STREAM_MUSIC, BB:自己设置音量的值,CC:也是一些标示量,我在此设置为0;

 

1.AudioManager.java

public void setStreamVolume(int streamType, int index, int flags);上层接口

       1)调用IAudioService service = getService(); 当程序开启时会获得service,调用此来获得

2.执行ServiceManager.java 
public static IBinder getService(String name)获取audio服务

3.AudioService.java 
public void setStreamVolume(int streamType, int index, int flags)//服务接口
   1) private void setStreamVolumeInt(int streamType, int index, boolean force, boolean lastAudible)//服务函数
   2)调用以下函数  
sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0,streamState, 0) 
       //Post message to set system volume (it in turn will post a message
                  // to persist)
3)AudioHandler::setSystemVolume(VolumeStreamState streamState);//sendmsg(...)后执行函数
   4)调用AudioHandler::setStreamVolumeIndex(int stream, int index)
    5)AudioSystem.setStreamVolumeIndex(stream,index);//audioSystem接口

static int android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, jobject thiz, jint stream, jint index)
1)调用AudioSystem::setStreamVolumeIndex

6.status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index)(处理到这时,也可以直接走AudioFlinger路线,不经过策略) 
1)获得服务 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
2)调用aps->setStreamVolumeIndex(stream, index)

7.status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
1)调用mpPolicyManager->setStreamVolumeIndex(stream, index)
status_t AudioPolicyManager::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
1)记录音量index: mStreams[stream].mIndexCur = index
2)compute and apply stream volume on all outputs:
checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device())

8.status_t AudioPolicyManager::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)
1)计算音量:float volume = computeVolume(stream, index, output, device);
2)调用:mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);

9.status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
调用mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);

10.status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
调用insertCommand_l(command, delayMs);

 

补充1)在条用getService();获取服务的时候 ,实际调用的是ServiceManager.getService(context);

系统服务都是由serviceManager来管理的,要添加服务,可以调用serviceManager.AddService(context,service);

每添加一个service,都会有对应的唯一context, 当getService的时候就会根据context获得相应的服务,

可查看ServiceManager.java, ServiceManager.h/cpp

补充2) AudioService 的接口在 IaudioService.aidl中定义。添加自定义功能时( 我们创建控制接口比如创建个音效处理的接口SetEffectVolume(XXX),可以参照SetStreamVolume(a,b,c))别忘了修改此处,否则,AudioManager 会出现cannot find symbol..错误!!!

 

补充3)编译的时候可能会在Audiomanager.java中调用自己写的接口时出错,此时先将该文件中的调用注释掉,执行 make update-api

执行完成后,将注释去掉,然后从新编译。。。