Android之Audio初探

ALSA

Gentoo Linux ALSA 指南

ALSA Main Page

Linux音频驱动之二:声卡的创建

Android之Audio

Android深入浅出之Audio 第一部分 AudioTrack分析

Android深入浅出之Audio 第二部分 AudioFlinger分析

Android深入浅出之Audio第三部分Audio Policy[1]

audio系统主要分为以下几个层次:

                1.media库提供的Audio系统本地部分接口

                2.AudioFlinger作为Audio系统的中间层

                3.Audio的硬件抽象层提供底层支持

                4.Audio通过JNI和java框架提供给上层

以上各个层次抽象成:放音(Track)和录音(Recorder)两个部分。

                Java Audio Class(java 框架层) -> Audio JNI(Audio 本地API) -> libmedia -->libaudioflinger.so -->AudioHardwareInterface? --> libaudio.so --> alsa以上的Audio 各个层次都使用一个管理类,和输入输出两个类来表示整个系统。各个层次的目录为:

                1 Java 层:frameworks/base/media/java/android/media

                2 JNI部分:frameworks/base/core/jni

                3 libmedia:frameworks/base/media/libmedia                

                4 AudioFlinger:frameworks/base/libs/audioflinger

                5 AudioHardwareInterface(硬件接口层):hardware/alsa_sound

                6 底层:ALSA

在Android中,使用ALSA的api编写了libaudio.so

intelmid.c文件分析

                简介 A card record is the headquarters of the soundcard.这个结构体管理包括PCM、MIDI、mixers、synthesizer在内的声卡设备,并且保存有声卡的ID、声卡的名字(strings)、proc文件、PM以及热插拔管理。

                1、 在文件intelmid.c中,下半部分是一个SPI总线的初始化部分,注册一个名为DRIVER_NAME("pmic_audio"@intelmid.h),结构体为snd_intelmad_driver的SPI设备。

                2、 然后,通过snd_intelmad_driver中的probe函数。

                                1> 初始化指向snd_intelmad结构体的指针intelmaddata;

                                2> 并创建了一个声卡设备:snd_card_create(card_index, card_id, THIS_MODULE, 0, &card);------struct snd_card *card;

                                3> snd_intelmad_sst_register(intelmaddata);注册一个sst_card,时期能够调用SST的API;                 

                                4> 初始化PCM实例、mixer和jack;

                                5> INIT_WORK(&intelmaddata->mad_jack_msg.wq,sst_process_mad_jack_detection);intelmaddata->mad_jack_wq = create_workqueue("sst_mad_jack_wq");

                                6> snd_intelmad_register_irq(intelmaddata);

                                7> snd_intelmad_create(intelmaddata, card);------snd_device_new(card, SNDRV_DEV_LOWLEVEL, intelmaddata, &ops);(attach the components (devices) to the card instance.)

                                8> 关联与注册声卡设备nd_card_set_dev(card, &spi->dev);snd_card_register(card);

程序说明:

  
  ALSA driver for Intel MID sound card chipset 


    #include "intelmid_snd_control.h"
    #include "intelmid.h"
    #include "intelmid_ctrl.h"
    module_param : card_index,card_id

    int     sst_card_vendor_id;


结构体:
    struct snd_pcm_hardware snd_intelmad_stream:info:interleaved PCM格式,双声道,支持PAUSE,RESUME,MMAP,两个OSS参数,PCM子流支持同步
                                                .formats  .rates  .rate_min  .rate_max  .channels_min  .channels_max(单声道或者双声道)
                                                .buffer_bytes_max (MAX_BUFFER 128*1024)
                                                .periodxxxx
//The “period” is a term that corresponds to a fragment in the OSS world. The period defines the size at which a PCM interrupt is generated.
//This size strongly depends on the hardware. Generally, the smaller period size will give you more interrupts, that is, more controls. 
//In the case of capture, this size defines the input latency. On the other hand, the whole buffer size defines the output latency for the playback direction.

    struct snd_pcm_ops snd_intelmad_playback_ops  与  snd_intelmad_capture_ops  
        当创建PCM实例后(snd_pcm_new(),一般使用一个函数来调用这个),要将PCM子流与其对应的操作关联起来,上面这两个结构体就是做这个用的。



本程序结构:
    本程序是一个SPI结构:
static struct spi_driver snd_intelmad_driver = { 
        .driver = {
                .name = DRIVER_NAME,           
                .bus = &spi_bus_type,          
                .owner = THIS_MODULE,  
        },
        .probe = snd_intelmad_probe,   
        .remove = __devexit_p(snd_intelmad_remove),
};

/*This function is called when the device is initialized(在注册的时候就调用了)*/
snd_intelmad_probe->snd_card_create
                    填充intelmaddata结构体
                    snd_intelmad_sst_register
                    snd_intelmad_pcm
                    snd_intelmad_jack
                    snd_intelmad_mixer
                    INIT_WORK
                    snd_intelmad_register_irq
                    snd_intelmad_create
                    snd_card_set_dev:
    1、snd_intelmad_sst_register:
        从芯片读vendor_id,
        处理intelmaddata->sstdrv_ops(module_name, vendor_id, scard_ops),通过各个函数初始化sstdrv_ops所有成员
            scard_ops:这个结构体与实际的vendor_id对应的数据结构相连:intelmaddata->sstdrv_ops->scard_ops = intelmad_vendor_ops[sst_card_vendor_id];
            假如vendor_id为2则通过intelmid_ctrl.c的结构体intelmad_vendor_ops映射到intelmid_v2_control.c上文件最后的结构体snd_pmic_ops_nc中。
        /* registering with SST driver to get access to SST APIs to use */
        intelmaddata->pmic_status为未初始化状态
    2、snd_intelmad_pcm: set up pcm params and functions
        snd_pcm_new(card, name, i, PLAYBACK_COUNT, CAPTURE_COUNT, &pcm):PCM实例的构造函数:第一个参数指定将要构造的实例,第二个参数是ID字符串,第三个参数是PCM的index
                                    第四个和第五个参数是playback和capture的个数, 第六个参数是&pcm
            /* setup the ops for playback and capture streams */
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_intelmad_playback_ops);固定形式,将pcm和后面的结构体相关联,该结构体执行相对的操作
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_intelmad_capture_ops);
            /* setup private data which can be retrieved when required */ 
            /* allocate dma pages for ALSA stream operations */
    3、snd_intelmad_jack:to setup jack settings of the card[Google: ALSA JACK]
    4、snd_intelmad_mixer
        ret_val = snd_ctl_add(card, snd_ctl_new1(&snd_intelmad_controls[idx], intelmaddata));创建一个声卡控制接口
   
        


工作队列:
    本驱动程序结构使用到了linux中的中断上半部和下半部的应用,使用了工作队列:
        snd_intelmad_probe-->INIT_WORK(&intelmaddata->mad_jack_msg.wq, sst_process_mad_jack_detection);
                             intelmaddata->mad_jack_wq = create_workqueue("sst_mad_jack_wq");创建自己的工作队列
        snd_intelmad_intr_handler-->queue_work(intelmaddata->mad_jack_wq, &intelmaddata->mad_jack_msg.wq);
    工作队列通过vendor_id来调用相应的工作的函数:这里是sst_mad_jackdetection_nec(intsts,intelmaddata);根据当前工作状态的标记intsts进行相应的操作。 然后载调用函数sst_mad_send_jack_report(struct snd_jack *jack, int buttonpressevent , int status) 


ALSA:
    snd_intelmad_pcm_trigger:This function is called whenever an a stream activity is invoked


ipc_mrst.c文件分析

Driver for Langwell IPC1

总结

部分audio寄存器自己尝试使用默认与auto配置就好

你可能感兴趣的:(Android-Linux,Driver,android,playback,audio,stream,struct,module)