我是靠谱客的博主 粗暴荷花,最近开发中收集的这篇文章主要介绍音频相关概念,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.音频硬件设备

也称为module,定义在services/audiopolicy/config/audio_policy_configuration.xml:

分别有primary,a2dp,usb,r_submix;

配置文件中的每一个module都被描述为HwModule,保存在mHwModules中;

2.output

可以理解成是输出端设备,常用的输出端设备有:

prmary_out,low_latency,deep_buffer,compress_offload,mutil_channel等;

定义在services/audiopolicy/config/audio_policy_configuration.xml;

每个输出设备上都有声卡,蓝牙设备,HDMI接口等;

声卡上面有一个喇叭,也就是speaker,以及一个耳机/麦克插孔用来连接耳机;

蓝牙设备用来连接蓝牙耳机;

把一个设备上具有相同参数的一组device称为output:

①output是多个device的组合;

②这些devcie属于同一硬件上的不同端口;

③这些device支持相同的参数,如:采样率,通道等;

也就是说,output是具有相同特性的device的组合;

配置文件中的每一个output都被描述为OutputProfile,保存在module->mOutputProfiles中;

3.SwAudioOutputDescriptor

Output的描述符,真正的output对象,以output为句柄,保存在AudioPolicyManager的mOutputs中;

可以通过flag,device,stream去获取;

4.PlaybackThread

回放线程。

output在创建同时,会创建一个与之一一对应的PlaybackThread,句柄为output,保存在AudioFlinger的mPlaybackThreads中;

PlaybackThread的类型与配置文件中output的flag有关。

PlaybackThread与output一一对应,一旦确定了output,也就确定了PlaybackThread;

5.AudioPolicyManager中的mpClientInterface

其实是AudioPolicyClientInterface *mpClientInterface,

定义在frameworksavservicesaudiopolicyserviceaudioPolicyClientImpl.cpp中;

6.stream与stage

流类型很多,需要为将他们分类,将具有相同行为的stream分成一组,它们共用一个Strategy:

具有相同行为的Stream:播放的设备一样,device相同,播放优先级相同。

7.stream,strategy,device,output,flag以及playbackthread之间的关系?

①解析配置文件时:

创建output

-->根据flag创建playbackthread

-->以output为句柄保存playbackthread;

②播放声音时:

app指定声音类型stream type

-->将stream进行分类,属于哪一strategy

-->根据strategy确定播放的设备device

-->根据device,flag确定output

-->根据output确定playbackthread

-->把声音数据传给这个thread

8.AudioPolicyService启动过程

①读取解析配置文件

②根据配置文件调用AudioFlinger的服务,打开output,创建线程;

void AudioPolicyService::onFirstRef()
    // start tone playback thread
    mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
    // start audio commands thread
    mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
    // start output activity command thread
    mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
    /*
    AudioPolicyService要使用AudioFlinger提供的服务,mAudioPolicyClient 就是AudioFlinger的客户        端,可以通过AudioPolicyClient使用AudioFlinger提供的服务访问硬件。
    AudioPolicyClient是在AudioPolicyClientImpl.cpp文件中实现的
     */
	mAudioPolicyClient = new AudioPolicyClient(this);
	mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);

createAudioPolicyManager(mAudioPolicyClient)主要就是构建AudioPolicyManager,在AudioPolicyManager里面解析配置文件。

AudioPolicyService启动过程分析:
a. 对于配置文件里的每一个module项, new HwModule(name), 放入mHwModules数组;
   对于module里的每一个output, new IOProfile, 放入module的mOutputProfiles;
   对于module里的每一个input, new IOProfile, 放入module的mInputProfiles;
b. 根据module的name加载厂家提供的so文件 (通过AudioFlinger来加载)
c. 打开对应的output                     (通过AudioFlinger来open output)

9.AudioTrack的创建过程:

①使用AudioTrack的属性, 根据AudioPolicy找到对应的output、playbackThread
②在playbackThread中创建对应的track
③APP的AudioTrack 和 playbackThread的mTracks中的track之间建立共享内存

10.output选择的优先级:

output的选择发生在AudioTrack.set()中,最终会走到AudioPolicyManager::getOutputForDevice()中;

选择output的逻辑优先级是:

flags > Format > primary > outputs[0](即outputs中的第一个output)。

11.应用程序的AudioTrack与播放线程之中的Track之间是怎么传递数据的?

应用的AudioTrack提供数据有两种方式:

①MODE_STATIC:一次性提供,比如简单的提示音,可以把所有的数据一次性提供给播放线程;

②MODE_STREAM:边播边提供,比如播放音乐;

在每个playbackThread中,有一个mTracks数组,其中肯定有一项,与我们的应用程序的AudioTrack对应起来,应用程序往track中写入数据时,playbackThread就能从对应的track中取出数据,然后混音播放。

所以APP与PlaybackThread声音数据的传递是使用共享内存(即APP与PlaybackThread可以访问同一块内存)。

共享内存是由谁来创建的,是由APP还是由PlaybackThread呢?

①如果APP提供AudioTrack的数据是一次性提供(MODE_STATIC:一次性,提前提供数据),那么显然这个buffer当然是由应用程序提供。因为应用程序才知道这个buffer有多大。
②如果应用程序是一边播放,一边提供数据(MODE_STREAM),那么就由PlaybackThread创建共享内存,因为这样省事(为了简单应用程序的编程)。
 

应用程序APP与PlaybackThread如何同步数据呢?

①如果APP提供AudioTrack的数据是一次性提供(MODE_STATIC:一次性,提前提供数据),APP先构造,PlaybackThread再消费,则无需进行同步。
②如果应用程序,是一边播放一边提供数据(MODE_STREAM),使用环形缓冲区进行同步。

AudioFlinger::PlaybackThread::Track::Track(
	if (sharedBuffer == 0) {
         //如果应用程序没有创建sharedBuffer,那么气会创建一个AudioTrackServerProxy用来管理Buffer
        mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize, !isExternalTrack(), sampleRate);
    } else {
        //如果提供了sharedBuffer,则会创建StaticAudioTrackServerProxy,用来管理者一个buffer
        mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize);
    }
    mServerProxy = mAudioTrackServerProxy;
status_t AudioTrack::set(
	status_t status = createTrack_l();
	/*使用audioFlinger的服务创建Track,会导致播放线程中创建Track*/
	sp<IAudioTrack> track = audioFlinger->createTrack()
	/*如果没有提供buffer,指向PlaybackThread提供的buffer*/
    if (mSharedBuffer == 0) {
        buffers = cblk + 1;
    } else {
    	/*否则指向自己提供的buffer*/
        buffers = mSharedBuffer->pointer();
        if (buffers == NULL) {
            ALOGE("Could not get buffer pointer");
            return NO_INIT;
        }
    }                                                  
	
	/*管理共享内存*/
    // update proxy
    if (mSharedBuffer == 0) {
        //如果应用程序没有创建sharedBuffer,那么气会创建一个AudioTrackClientProxy用来管理Buffer
        mStaticProxy.clear();
        mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
    } else {
        //如果提供了sharedBuffer,则会创建StaticAudioTrackClientProxy用来管理一个buffer
        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
        mProxy = mStaticProxy;
    }

AudioTrackClientProxy对应AudioTrackServerProxy,StaticAudioTrackClientProxy对应StaticAudioTrackServerProxy,都是对buffer以及共享内存的管理。

最后

以上就是粗暴荷花为你收集整理的音频相关概念的全部内容,希望文章能够帮你解决音频相关概念所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部