AudioTrack创建流程分析

android audio从应用到中间层再到HAL层,涉及很多,比如音频链路的选择,共享内存的分配及音频数据的传输、平台音频配置文件的加载等等,内容很多又很复杂,每块可以单独拉出来讨论,今天先简单说下应用是怎么从AudioTrack一步步到AudioFlinger服务。

AudioTrack和Track的创建流程

首先我们先从应用使用开始:frameworks\base\media\tests\MediaFrameworkTest\src\com\android\mediaframeworktest\functional\audio\MediaAudioTrackTest.java
这个文件是针对AudioTrack向应用提供的一些接口,实现的测试程序,这里就随便取一个函数开涮:

//Test case 1: setStereoVolume() with max volume returns SUCCESS
    @LargeTest
    public void testSetStereoVolumeMax() throws Exception {
     //测试立体声的最大值
        // constants for test
        final String TEST_NAME = "testSetStereoVolumeMax";
        final int TEST_SR = 22050;
        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO; //通道数
        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; //位深
        final int TEST_MODE = AudioTrack.MODE_STREAM;  //音频数据传输模式
        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;//音频类型,音乐
        
        //-------- initialization --------------
        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);//重要,得到需要分配的共享内存大小
        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
                minBuffSize, TEST_MODE); //陷入AudioTrack.java --重点
        byte data[] = new byte[minBuffSize/2];
        //--------    test        --------------
        track.write(data, 0, data.length);//写入音频数据
        track.write(data, 0, data.length);
        track.play();//播放控制
        float maxVol = AudioTrack.getMaxVolume();//得到最大音量
        assertTrue(TEST_NAME, track.setStereoVolume(maxVol, maxVol) == AudioTrack.SUCCESS);//设置最大音量
        //-------- tear down      --------------
        track.release();//释放资源,使用完成后要释放所占用的资源,如:音频服务、音频通道...
    }

以上函数,设置音频格式、音频数据传输模式、然后获取最小的共享内存大小(分配内存,详细分析见文末),创建AudioTrack对象,获取对应的接口实现功能。

AudioTrack.java

接着分析AudioTrack对象的创建都实现了些啥?

public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
            int bufferSizeInBytes, int mode, int sessionId)
    throws IllegalArgumentException {
   
        // mState already == STATE_UNINITIALIZED

        // remember which looper is associated with the AudioTrack instantiation
        Looper looper;
        if ((looper = Looper.myLooper()) == null) {
   
            looper = Looper.getMainLooper();//获取主循环
        }
        //Looper associated with the thread that creates the AudioTrack instance.
        mInitializationLooper = looper;

        audioParamCheck(streamType, sampleRateInHz, channelConfig, audioFormat, mode);//参数合法性检查

        audioBuffSizeCheck(bufferSizeInBytes);//buf大小的检查

        if (sessionId < 0) {
    //回话id不能为0
            throw new IllegalArgumentException("Invalid audio session ID: "+sessionId);
        }

        int[] session = new int[1];
        session[0] = sessionId;
        // native initialization
        int initResult = native_setup(new WeakReference<AudioTrack>(this),
                mStreamType, mSampleRate, mChannels, mAudioFormat,
                mNativeBufferSizeInBytes, mDataLoadMode, session);//重要,这里调用jni层的native方法实现,此处只是一个包装
        if (initResult != SUCCESS) {
   
            loge("Error code "+initResult+" when initializing AudioTrack.");
            return; // with mState == STATE_UNINITIALIZED
        }

        mSessionId = session[0];

        if (mDataLoadMode == MODE_STATIC) {
    //设置音频数据传输模式
            mState = STATE_NO_STATIC_DATA;
        } else {
   
            mState = STATE_INITIALIZED;
        }
    }

可以看出,在AudioTrack.java的构造函数中只是进行一些参数的检查,然后调用native_setup进入jni层的具体实现。
通过搜索我们发现,native_setup是jni层注册的一个方法,具体如下:
所在文件frameworks\base\core\jni\android_media_AudioTrack.cpp

cpp

android_media_AudioTrack.cpp

static JNINativeMethod gMethods[] = {
   
    // name,              signature,     funcPtr
    {
   "native_start",         "()V",      (void *)android_media_AudioTrack_start},
    {
   "native_stop",          "()V",      (void *)android_media_AudioTrack_stop},
    ...
    {
   "native_setup",         "(Ljava/lang/Object;IIIIII[I)I",
                                         (void *)android_media_AudioTrack_native_setup},//
    ...

来看看这个函数做了些什么,因内容太长,我们只列举部分比较重要和主题相关的内容:

  // check the stream type
    audio_stream_type_t atStreamType;
    switch (streamType) {
   
    ...
   // check the format.
   ...
   // compute the frame count
    int bytesPerSample = audioFormat == ENCODING_PCM_16BIT ? 2 : 1;
    audio_format_t format =</
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值