一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

7.2 Audio系統(tǒng)和上層接口 - 《Android系統(tǒng)原理及開發(fā)要點詳解》 - 免費試...

 xrzs 2010-02-25
Audio系統(tǒng)和上層接口   

在Android中,Audio系統(tǒng)自上而下由Java的Audio類、Audio本地框架類、AudioFlinger和Audio的硬件抽象層幾個部分組成。

è 7.2.1  Audio系統(tǒng)的各個層次

Audio系統(tǒng)的各層次情況如下所示。

   Audio本地框架類是libmedia.so的一個部分,這些Audio接口對上層提供接口,由下層的本地代碼去實現(xiàn)。

   AudioFlinger繼承l(wèi)ibmeida中的接口,提供實現(xiàn)庫libaudiofilnger.so。這部分內(nèi)容沒有自己的對外頭文件,上層調(diào)用的只是libmedia本部分的接口,但實際調(diào)用的內(nèi)容是libaudioflinger.so。

  Audio使用JNI和Java對上層提供接口,JNI部分通過調(diào)用libmedia庫提供的接口來實現(xiàn)。

   Audio的硬件抽象層提供到硬件的接口,供AudioFlinger調(diào)用。Audio的硬件抽象層實際上是各個平臺開發(fā)過程中需要主要關(guān)注和獨立完成的部分。

 提示:Android的Audio系統(tǒng)不涉及編解碼環(huán)節(jié),只是負(fù)責(zé)上層系統(tǒng)和底層Audio硬件的交互,一般以PCM作為輸入/輸出格式。

在Android的Audio系統(tǒng)中,無論上層還是下層,都使用一個管理類和輸出輸入兩個類來表示整個Audio系統(tǒng),輸出輸入兩個類負(fù)責(zé)數(shù)據(jù)通道。在各個層次之間具有對應(yīng)關(guān)系,如表7-1所示所示。

表7-1  Android各個層次的對應(yīng)關(guān)系

Audio管理環(huán)節(jié)

Audio輸出

Audio輸入

Java層

android.media.AudioSystem

android.media.AudioTrack

android.media.AudioRecorder

本地框架層

AudioSystem

AudioTrack

AudioRecorder

AudioFlinger

IAudioFlinger

IAudioTrack

IAudioRecorder

硬件抽象層

AudioHardwareInterface

AudioStreamOut

AudioStreamIn

è 7.2.2  media庫中的Audio框架部分

Android的Audio系統(tǒng)的核心框架在media庫中提供,對上面主要實現(xiàn)AudioSystem、AudioTrack和AudioRecorder三個類。

提供了IAudioFlinger類接口,在這個類中,可以獲得IAudioTrack和IAudioRecorder兩個接口,分別用于聲音的播放和錄制。AudioTrack和AudioRecorder分別通過調(diào)用IAudioTrack和IAudioRecorder來實現(xiàn)。

Audio系統(tǒng)的頭文件在frameworks/base/include/media/目錄中,主要的頭文件如下:

n  AudioSystem.h:media庫的Audio部分對上層的總管接口;

n  IAudioFlinger.h:需要下層實現(xiàn)的總管接口;

n  AudioTrack.h:放音部分對上接口;

n  IAudioTrack.h:放音部分需要下層實現(xiàn)的接口;

n  AudioRecorder.h:錄音部分對上接口;

n  IAudioRecorder.h:錄音部分需要下層實現(xiàn)的接口。

IaudioFlinger.h、IAudioTrack.h和IAudioRecorder.h這三個接口通過下層的繼承來實現(xiàn)(即AudioFlinger)。AudioFlinger.h、AudioTrack.h和AudioRecorder.h是對上層提供的接口,它們既供本地程序調(diào)用(例如聲音的播放器、錄制器等),也可以通過JNI向Java層提供接口。

meida庫中Audio部分的結(jié)構(gòu)如圖7-2所示。

圖7-2  meida庫中Audio部分的結(jié)構(gòu)

從功能上看,AudioSystem負(fù)責(zé)的是Audio系統(tǒng)的綜合管理功能,而AudioTrack和AudioRecorder分別負(fù)責(zé)音頻數(shù)據(jù)的輸出和輸入,即播放和錄制。

AudioSystem.h中主要定義了一些枚舉值和set/get等一系列接口,如下所示:

class AudioSystem

{

public:

    enum stream_type {                        // Audio 流的類型

        SYSTEM          = 1,

        RING            = 2,

        MUSIC           = 3,

        ALARM           = 4,

        NOTIFICATION    = 5,

        BLUETOOTH_SCO   = 6,

        ENFORCED_AUDIBLE = 7,

        NUM_STREAM_TYPES

    };

    enum audio_output_type {           // Audio數(shù)據(jù)輸出類型

        // …… 省略部分內(nèi)容   };

    enum audio_format {                   // Audio數(shù)據(jù)格式

        FORMAT_DEFAULT = 0,

        PCM_16_BIT,

        PCM_8_BIT,

        INVALID_FORMAT

    };

    enum audio_mode {                    // Audio模式

        // …… 省略部分內(nèi)容   };

    enum audio_routes {                   // Audio 路徑類型

        ROUTE_EARPIECE         = (1 << 0),

        ROUTE_SPEAKER          = (1 << 1),

        ROUTE_BLUETOOTH_SCO  = (1 << 2),

        ROUTE_HEADSET           = (1 << 3),

        ROUTE_BLUETOOTH_A2DP  = (1 << 4),

        ROUTE_ALL                 = -1UL,

    };

    // …… 省略部分內(nèi)容

    static status_t setMasterVolume(float value);

    static status_t setMasterMute(bool mute);

    static status_t getMasterVolume(float* volume);

    static status_t getMasterMute(bool* mute);

    static status_t setStreamVolume(int stream, float value);

    static status_t setStreamMute(int stream, bool mute);

    static status_t getStreamVolume(int stream, float* volume);

    static status_t getStreamMute(int stream, bool* mute);

    static status_t setMode(int mode);

    static status_t getMode(int* mode);

    static status_t setRouting(int mode, uint32_t routes, uint32_t mask);

    static status_t getRouting(int mode, uint32_t* routes);

    // …… 省略部分內(nèi)容

};

在Audio系統(tǒng)的幾個枚舉值中,audio_routes是由單獨的位來表示的,而不是由順序的枚舉值表示,因此這個值在使用過程中可以使用“或”的方式。例如,表示聲音可以既從耳機(EARPIECE)輸出,也從揚聲器(SPEAKER)輸出,這樣是否能實現(xiàn),由下層提供支持。在這個類中,set/get等接口控制的也是相關(guān)的內(nèi)容,例如Audio聲音的大小、Audio的模式、路徑等。

AudioTrack是Audio輸出環(huán)節(jié)的類,其中最重要的接口是write(),主要的函數(shù)如下所示。

class AudioTrack

{

    typedef void (*callback_t)(int event, void* user, void *info);

    AudioTrack( int streamType,

                uint32_t sampleRate  = 0,    // 音頻的采樣律

                int format           = 0,        // 音頻的格式(例如8位或者16位的PCM)

                int channelCount     = 0,      // 音頻的通道數(shù)

                int frameCount       = 0,       // 音頻的幀數(shù)

                uint32_t flags       = 0,

                callback_t cbf       = 0,

                void* user           = 0,

                int notificationFrames = 0);

    void        start();

    void        stop();

    void        flush();

    void        pause();

    void        mute(bool);

    ssize_t     write(const void* buffer, size_t size);

// …… 省略部分內(nèi)容

}

AudioRecord是Audio輸入環(huán)節(jié)的類,其中最重要的接口為read(),主要的函數(shù)如下所示。

class AudioRecord

{

public:

    AudioRecord(int streamType,

                uint32_t sampleRate  = 0,        // 音頻的采樣律

                int format           = 0,       // 音頻的格式(例如8位或者16位的PCM)

                int channelCount     = 0,     // 音頻的通道數(shù)

                int frameCount       = 0,      // 音頻的幀數(shù)

                uint32_t flags      = 0,

                callback_t cbf = 0,

                void* user = 0,

                int notificationFrames = 0);

    status_t    start();

    status_t    stop();

    ssize_t     read(void* buffer, size_t size);

// …… 省略部分內(nèi)容

}

AudioTrack和AudioRecord的read/write函數(shù)的參數(shù)都是內(nèi)存的指針及其大小,內(nèi)存中的內(nèi)容一般表示的是Audio的原始數(shù)據(jù)(PCM數(shù)據(jù))。這兩個類還涉及Auido數(shù)據(jù)格式、通道數(shù)、幀數(shù)目等參數(shù),可以在建立時指定,也可以在建立之后使用set()函數(shù)進行設(shè)置。

在libmedia庫中提供的只是一個Audio系統(tǒng)框架,AudioSystem、AudioTrack和AudioRecord分別調(diào)用下層的IAudioFlinger、IAudioTrack和IAudioRecord來實現(xiàn)。另外的一個接口是IAudioFlingerClient,它作為向IAudioFlinger中注冊的監(jiān)聽器,相當(dāng)于使用回調(diào)函數(shù)獲取IAudioFlinger運行時信息。

è 7.2.3  AudioFlinger本地代碼

AudioFlinger是Audio系統(tǒng)的中間層,在系統(tǒng)中起到服務(wù)作用,它主要作為libmedia提供的Audio部分接口的實現(xiàn),其代碼路徑為:

frameworks/base/libs/audioflinger

AudioFlinger的核心文件是AudioFlinger.h和AudioFlinger.cpp,提供了類AudioFlinger,這個類是一個IAudioFlinger的實現(xiàn),其主要接口如下所示:

class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient

{

public:

                                            // …… 省略部分內(nèi)容

    virtual sp<IAudioTrack> createTrack(           // 獲得音頻輸出接口(Track)

                                pid_t pid,

                                int streamType,

                                uint32_t sampleRate,

                                int format,

                                int channelCount,

                                int frameCount,

                                uint32_t flags,

                                const sp<IMemory>& sharedBuffer,

                                status_t *status);

    // …… 省略部分內(nèi)容

    virtual     status_t    setMasterVolume(float value);

    virtual     status_t    setMasterMute(bool muted);

    virtual     status_t    setStreamVolume(int stream, float value);

    virtual     status_t    setStreamMute(int stream, bool muted);

    virtual     status_t    setRouting(int mode, uint32_t routes, uint32_t mask);

    virtual     uint32_t    getRouting(int mode) const;

    virtual     status_t    setMode(int mode);

    virtual     int         getMode() const;

    virtual sp<IAudioRecord> openRecord(           // 獲得音頻輸出接口(Record)

                                pid_t pid,

                                int streamType,

                                uint32_t sampleRate,

                                int format,

                                int channelCount,

                                int frameCount,

                                uint32_t flags,

                                status_t *status);

}

AudioFlinger主要提供createTrack()創(chuàng)建音頻的輸出設(shè)備IAudioTrack,openRecord()創(chuàng)建音頻的輸入設(shè)備IAudioRecord。另外包含的就是一個get/set接口,用于控制。

AudioFlinger構(gòu)造函數(shù)片段如下所示:

AudioFlinger::AudioFlinger()

{

    mHardwareStatus = AUDIO_HW_IDLE;

    mAudioHardware = AudioHardwareInterface::create();

    mHardwareStatus = AUDIO_HW_INIT;

    if (mAudioHardware->initCheck() == NO_ERROR) {

        mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;

        status_t status;

        AudioStreamOut *hwOutput =

            mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);

        mHardwareStatus = AUDIO_HW_IDLE;

        if (hwOutput) {

            mHardwareMixerThread =

            new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE);

        } else {

            LOGE("Failed to initialize hardware output stream, status: %d", status);

        }

    // …… 省略部分內(nèi)容

        mAudioRecordThread = new AudioRecordThread(mAudioHardware, this);

        if (mAudioRecordThread != 0) {

            mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);           

        }

     } else {

        LOGE("Couldn't even initialize the stubbed audio hardware!");

    }

}

從工作的角度看,AudioFlinger在初始化之后,首先獲得放音設(shè)備,然后為混音器(Mixer)建立線程,接著建立放音設(shè)備線程,在線程中獲得放音設(shè)備。

在AudioFlinger的AudioResampler.h中定義了一個音頻重取樣器工具類,如下所示:

class AudioResampler {

public:

    enum src_quality {

        DEFAULT=0,

        LOW_QUALITY=1,              // 線性差值算法

        MED_QUALITY=2,              // 立方差值算法

        HIGH_QUALITY=3              // fixed multi-tap FIR算法

    };

    static AudioResampler* create(int bitDepth, int inChannelCount,  // 靜態(tài)地創(chuàng)建函數(shù)

            int32_t sampleRate, int quality=DEFAULT);

    virtual ~AudioResampler();

    virtual void init() = 0;

    virtual void setSampleRate(int32_t inSampleRate);                  // 設(shè)置重采樣率

    virtual void setVolume(int16_t left, int16_t right);            // 設(shè)置音量

    virtual void resample(int32_t* out, size_t outFrameCount,

                       AudioBufferProvider* provider) = 0;

};

這個音頻重取樣工具包含3種質(zhì)量:低等質(zhì)量(LOW_QUALITY)將使用線性差值算法實現(xiàn);中等質(zhì)量(MED_QUALITY)將使用立方差值算法實現(xiàn);高等質(zhì)量(HIGH_ QUALITY)將使用FIR(有限階濾波器)實現(xiàn)。AudioResampler中的AudioResamplerOrder1是線性實現(xiàn),AudioResamplerCubic.*文件提供立方實現(xiàn)方式,AudioResamplerSinc.*提供FIR實現(xiàn)。

AudioMixer.h和AudioMixer.cpp中實現(xiàn)的是一個Audio系統(tǒng)混音器,它被AudioFlinger調(diào)用,一般用于在聲音輸出之前的處理,提供多通道處理、聲音縮放、重取樣。AudioMixer調(diào)用了AudioResampler。

 提示: AudioFlinger本身的實現(xiàn)通過調(diào)用下層的Audio硬件抽象層的接口來實現(xiàn)具體的功能,各個接口之間具有對應(yīng)關(guān)系。

è 7.2.4  Audio系統(tǒng)的JNI代碼

Android的Audio部分通過JNI向Java層提供接口,在Java層可以通過JNI接口完成Audio系統(tǒng)的大部分操作。

Audio JNI部分的代碼路徑為:frameworks/base/core/jni。

其中,主要實現(xiàn)的3個文件為:android_media_AudioSystem.cpp、android_media_Audio Track.cpp和android_media_AudioRecord.cpp,它們分別對應(yīng)了Android Java框架中的3個類的支持:

n  android.media.AudioSystem:負(fù)責(zé)Audio系統(tǒng)的總體控制;

n  android.media.AudioTrack:負(fù)責(zé)Audio系統(tǒng)的輸出環(huán)節(jié);

n  android.media.AudioRecorder:負(fù)責(zé)Audio系統(tǒng)的輸入環(huán)節(jié)。

在Android的Java層中,可以對Audio系統(tǒng)進行控制和數(shù)據(jù)流操作,對于控制操作,和底層的處理基本一致;但是對于數(shù)據(jù)流操作,由于Java不支持指針,因此接口被封裝成了另外的形式。

例如,對于音頻輸出,android_media_AudioTrack.cpp提供的是寫字節(jié)和寫短整型的接口類型。

static jint android_media_AudioTrack_native_write(JNIEnv *env,  jobject thiz,

                                             jbyteArray javaAudioData,

                                             jint offsetInBytes, jint sizeInBytes,

                                             jint javaAudioFormat) {

    jbyte* cAudioData = NULL;

    AudioTrack *lpTrack = NULL;

    lpTrack = (AudioTrack *)env->GetIntField(

                 thiz, javaAudioTrackFields. Native TrackInJavaObj);

    // …… 省略部分內(nèi)容

    ssize_t written = 0;

    if (lpTrack->sharedBuffer() == 0) {

    //進行寫操作

        written = lpTrack->write(cAudioData + offsetInBytes, sizeInBytes);

    } else {

        if (javaAudioFormat == javaAudioTrackFields.PCM16) {

            memcpy(lpTrack->sharedBuffer()->pointer(),

                    cAudioData+offsetInBytes, sizeInBytes);

            written = sizeInBytes;

        } else if (javaAudioFormat == javaAudioTrackFields.PCM8) {

            int count = sizeInBytes;

            int16_t *dst = (int16_t *)lpTrack->sharedBuffer()->pointer();

            const int8_t *src = (const int8_t *)(cAudioData + offsetInBytes);           

            while(count--) {

                *dst++ = (int16_t)(*src++^0x80) << 8;

            }

            written = sizeInBytes;

        }

    }

    // …… 省略部分內(nèi)容

    env->ReleasePrimitiveArrayCritical(javaAudioData, cAudioData, 0);

    return (int)written;

}

所定義的JNI接口native_write_byte和native_write_short如下所示:

    {"native_write_byte",    "([BIII]I", (void *)android_media_AudioTrack_native_write),

    {"native_write_short",   "([SIII]I", (void *)android_media_AudioTrack_native_ write_short),

向Java提供native_write_byte和native_write_short接口,它們一般是通過調(diào)用AudioTrack的write()函數(shù)來完成的,只是在Java的數(shù)據(jù)類型和C++的指針中做了一步    轉(zhuǎn)換。

è 7.2.5  Audio系統(tǒng)的Java代碼

Android的Audio系統(tǒng)的相關(guān)類在android.media 包中,Java部分的代碼路徑為:

frameworks/base/media/java/android/media

Audio系統(tǒng)主要實現(xiàn)了以下幾個類:android.media.AudioSystem、android.media. Audio Track、android.media.AudioRecorder、android.media.AudioFormat。前面的3個類和本地代碼是對應(yīng)的,AudioFormat提供了一些Audio相關(guān)類型的枚舉值。

 注意:在Audio系統(tǒng)的Java代碼中,雖然可以通過AudioTrack和AudioRecorder的write()和read()接口,在Java層對Audio的數(shù)據(jù)流進行操作。但是,更多的時候并不需要這樣做,而是在本地代碼中直接調(diào)用接口進行數(shù)據(jù)流的輸入/輸出,而Java層只進行控制類操作,不處理數(shù)據(jù)流。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产成人精品资源在线观看| 黄片免费观看一区二区| 中国日韩一级黄色大片| 成人免费高清在线一区二区| 久久中文字人妻熟女小妇| 国产欧美高清精品一区| 中文字幕一区久久综合| 亚洲综合色婷婷七月丁香| 91亚洲国产—区=区a| 亚洲精品一区二区三区免| 乱女午夜精品一区二区三区| 69老司机精品视频在线观看| 久久精品国产一区久久久| 色婷婷成人精品综合一区| 国产福利一区二区久久| 国产一级二级三级观看| 免费福利午夜在线观看| 国产精品一区二区日韩新区| 欧美一区二区三区十区| 日韩精品中文字幕亚洲| 国产精品免费精品一区二区 | 国产一区二区久久综合| 免费一区二区三区少妇| 亚洲精品欧美精品日韩精品| 国产熟女高清一区二区| 一区二区三区日韩在线| 丁香六月婷婷基地伊人| 青草草在线视频免费视频| 不卡免费成人日韩精品| 日韩夫妻午夜性生活视频| 中国美女草逼一级黄片视频| 清纯少妇被捅到高潮免费观看| 日本免费一区二区三女| 超薄肉色丝袜脚一区二区| 日韩一本不卡在线观看| 欧美人与动牲交a精品| 乱女午夜精品一区二区三区| 国产精品白丝久久av| 日韩一区二区三区18| 国产精品尹人香蕉综合网| 国内精品美女福利av在线|