免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1306 | 回复: 0
打印 上一主题 下一主题

A Tutorial on Using the ALSA Audio API [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-29 13:47 |只看该作者 |倒序浏览

                A Tutorial on Using the ALSA Audio APIThis document attempts to provide an introduction to theALSA Audio API. It is not a complete reference manual forthe API, and it does not cover many specific issues thatmore complex software will need to address. However, it doestry to provide enough background and information for areasonably skilled programmer but who is new to ALSA towrite a simple program that uses the API.
All code in the document is licensed under the GNU PublicLicense. If you plan to write software using ALSA under some otherlicense, then I suggest you find some other documentation.
ContentsUnderstanding Audio InterfacesLet us first review the basic design of an audio interface.  As anapplication developer, you don't need to worry about this level ofoperation - its all taken care of by the device driver (which is oneof the components that ALSA provides). But you do need to understandwhat is going at a conceptual level if you want to write efficient andflexible software.
An audio interface is a device that allows a computer to receive andto send audio data from/to the outside world. Inside of the computer,audio data is represented a stream of bits, just like any other kindof data. However, the audio interface may send and receive audio aseither an analog signal (a time-varying voltage) or as a digitalsignal (some stream of bits). In either case, the set of bits that thecomputer uses to represent a particular sound will need to betransformed before it is delivered to the outside world, and likewise,the external signal received by the interface will need to betransformed before it is useful to the computer. These twotransformations are the raison d'etre of the audio interface.
Within the audio interface is an area referred to as the "hardwarebuffer". As an audio signal arrives from the outside world, theinterface converts it into a stream of bits usable by the computer andstores it in the part hardware buffer used to send data to thecomputer. When it has collected enough data in the hardware buffer,the interface interrupts the computer to tell it that it has dataready for it. A similar process happens in reverse for data being sentfrom the computer to the outside world. The interface interrupts thecomputer to tell it that there is space in the hardware buffer, andthe computer proceeds to store data there. The interface laterconverts these bits into whatever form is needed to deliver it to theoutside world, and delivers it. It is very important to understandthat the interface uses this buffer as a "circular buffer". When itgets to the end of the buffer, it continues by wrapping around to thestart.
For this process to work correctly, there are a number of variablesthat need to be configured. They include:
  • what format should the interface use when converting between     the bitstream used by the computer and the signal used     in the outside world?
  • at what rate should samples be moved between the interface     and the computer?
  • how much data (and/or space) should there be before the device     interrupts the computer?
  • how big should the hardware buffer be?
The first two questions are fundamental in governing thequality of the audio data. The second two questions affectthe "latency" of the audio signal. This term refers to thedelay between
  • data arriving at the audio interface from the outside world,       and it being available to the computer ("input latency")
  • data being delivered by the computer, and it being        delivered to the outside world ("output latency")Both of these are very important for many kinds of audio software,though some programs do not need be concerned with such matters.What a typical audio application doesA typical audio application has this rough structure:      open_the_device();
          set_the_parameters_of_the_device();
          while (!done) {
               /* one or both of these */
               receive_audio_data_from_the_device();
               deliver_audio_data_to_the_device();
          }
          close the device
         A Minimal Playback ProgramThis program opens an audio interface for playback,configures it for stereo, 16 bit, 44.1kHz, interleavedconventional read/write access. Then its delivers a chunk ofrandom data to it, and exits. It represents about thesimplest possible use of the ALSA Audio API, and isn't meantto be a real program.#include
            #include
            #include
                 
            main (int argc, char *argv[])
            {
                    int i;
                    int err;
                    short buf[128];
                    snd_pcm_t *playback_handle;
                    snd_pcm_hw_params_t *hw_params;
           
                    if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) A Minimal Capture ProgramThis program opens an audio interface for capture,configures it for stereo, 16 bit, 44.1kHz, interleavedconventional read/write access. Then its reads a chunk ofrandom data from it, and exits. It isn't meant to be a realprogram.        #include
            #include
            #include
                 
            main (int argc, char *argv[])
            {
                    int i;
                    int err;
                    short buf[128];
                    snd_pcm_t *capture_handle;
                    snd_pcm_hw_params_t *hw_params;
           
                    if ((err = snd_pcm_open (&capture_handle, argv[1], SND_PCM_STREAM_CAPTURE, 0)) A Minimal Interrupt-Driven ProgramThis program opens an audio interface for playback,configures it for stereo, 16 bit, 44.1kHz, interleavedconventional read/write access. It then waits till theinterface is ready for playback data, and delivers randomdata to it at that time.  This design allows your program tobe easily ported to systems that rely on a callback-drivenmechanism, such as JACK, LADSPA, CoreAudio, VST andmany others.        #include
            #include
            #include
            #include
            #include &ltalsa/asoundlib.h>
                 
            snd_pcm_t *playback_handle;
            short buf[4096];
           
            int
            playback_callback (snd_pcm_sframes_t nframes)
            {
                    int err;
           
                    printf ("playback callback called with %u frames\n", nframes);
           
                    /* ... fill buf with data ... */
           
                    if ((err = snd_pcm_writei (playback_handle, buf, nframes))  4096 ? 4096 : frames_to_deliver;
           
                            /* deliver the data */
           
                            if (playback_callback (frames_to_deliver) != frames_to_deliver) {
                                    fprintf (stderr, "playback callback failed\n");
                                    break;
                            }
                    }
           
                    snd_pcm_close (playback_handle);
                    exit (0);
            }
    A Minimal Full-Duplex ProgramFull duplex can be implemented by combining the playback and capturedesigns show above.  Although many existing Linux audio applicationsuse this kind of design, in this author's opinion, it is deeplyflawed. The
    the interrupt-driven
    examplerepresents a fundamentally better design for many situations. It is,however, rather complex to extend to full duplex. This is why Isuggest you
    forget about all of this.
    TerminologycaptureReceiving data from the outside world (different     from "recording" which implies storing that data     somewhere, and is not part of ALSA's API)
    playbackDelivering data to the outside world, presumably,    though not necessarily, so that it can be heard.
    duplexA situation where capture and playback are occuring    on the same interface at the same time.
    xrunOnce the audio interface starts running, it continues    to do until told to stop. It will be generating data    for computer to use and/or sending data from the    computer to the outside world. For various reasons,    your program may not keep up with it. For playback,     this can lead to a situation where the interface    needs new data from the computer, but it isn't there,    forcing it use old data left in the hardware    buffer. This is called an "underrun". For capture, the    interface may have data to deliver to the computer,    but nowhere to store it, so it has to overwrite part    of the hardware buffer that contains data the computer    has not received. This is called an "overrun". For    simplicity, we use the generic term "xrun" to refer    to either of these conditions
    PCMPulse Code Modulation. This phrase (and acronym) describes    one method of representing an analog signal in digital form.     Its the method used by almost computer audio interfaces, and    it is used in the ALSA API as a shorthand for "audio".
    channel
    frameA sample is a single value    that describes the amplitude of the audio signal at a single    point in time, on a single channel. When we talk    about working with digital audio, we often want to    talk about the data that represents all channels at a single    point in time. This is a collection of samples, one per channel,    and is generally called a "frame". When we talk about the passage    of time in terms of frames, its roughly equivalent to what people    when they measure in terms of samples, but is more accurate; more    importantly, when we're talking about the amount of data needed    to represent all the channels at a point in time, its the only    unit that makes sense. Almost every ALSA Audio API function uses frames    as its unit of measurement for data quantities.
    interleaveda data layout arrangement where the samples of each channel    that will be played at the same time follow each other    sequentially. See "non-interleaved"
    non-interleaveda data layout where the samples for a single channel     follow each other sequentially; samples for another    channel are either in another buffer or another    part of this buffer. Contrast with "interleaved"
    sample clocka timing source that is used to mark the times at which    a sample should be delivered and/or received to/from    the outside world. Some audio interfaces allow    you to use an external sample clock, either a "word clock"    signal (typically used in many studios), or "autosync"    which uses a clock signal present in incoming digital data.     All audio interfaces have at least one sample clock    source that is present on the interface itself, typically    a small crystal clock. Some interfaces do not allow    the rate of the clock to be varied, and some have clocks    that do not actually run at precisely the rates you    would expect (44.1kHz, etc). No two sample clocks    can ever be expected to run at precisely the same rate - if    you need two sample streams to remain synchronized    with each other, they MUST be run from    the same sample clock.
    How to do it ...Opening the deviceALSA separates capture and playback ....Setting parametersWe mentioned above that there are numberof parameters that need to be set in order for an audio interface todo its job. However, because your program will not actually beinteracting with the hardware directly, but instead with a devicedriver that controls the hardware, there are really two distinct setsof parameters:Hardware ParametersThese are parameters that directly affect the hardware of the audiointerface.
    Sample rateThis controls the rate at which either A/D/D/A    conversion is done, if the interface has analog I/O. For    fully digital interfaces, it controls the speed of    the clock used to move digital audio data to/from the    outside world. On some interfaces, other device-specific    configuration may mean that your program cannot    control this value (for example, when the interface has    been told to use an external word clock source to    determine the sample rate).
    Sample formatThis controls the sample format used to transfer data to    and from the interface. It may or may not correspond    with a format directly supported by the hardware.
    Number of channelsHopefully, this is fairly self-explanatory.
    Data access and layoutThis controls the way that the program will    deliver/receive data from the interface. There are two    parameters controlled by 4 possible settings. One    parameter is whether or not a "read/write" model    will be used, in which explicit function calls    are used to transfer data. The other option here    is to use "mmap mode" in which data is transferred    by copying between areas of memory, and API calls    are only necessary to note when it has started    and finished.
        The other parameter is whether the data layout    will be interleaved or non-interleaved.   
    Interrupt intervalThis determines how many interrupts the interface will    generate per complete traversal of its hardware    buffer. It can be set either by specifying a number of    periods, of the size of a period. Since this determines    the number of frames of space/data that have to    accumulate before the interface will interrupt the    computer. It is central in controlling latency.
    Buffer sizeThis determines how large the hardware buffer is. It    can be specified in units of time or frames.
    Software ParametersThese are parameters that control the operation of the device driverrather than the hardware itself. Most programs that use theALSA Audio API will not need to set any of these; a few willneed set a subset of them.
    When to start the deviceWhen you open the audio interface, ALSA ensures that it    is not active - no data is being moved to or from    its external connectors. Presumably, at some point    you want this data transfer to begin. There are several    options for how to make this happen.
        The control point here the start threshold, which defines the    number of frames of space/data necessary to start the device    automatically. If set to some value other than zero for playback,    it is necessary to prefill the playback buffer before the device    will start. If set to zero, the first data written to the device    (or first attempt to read from a capture stream) will start the    device.
            You can also start the device explicitly using snd_pcm_start,    but this requires buffer prefilling in the case of the playback    stream. If you attempt to start the stream without doing this,    you will get -EPIPE as a return code, indicating that there    is no data waiting to deliver to the playback hardware buffer.
             What to do about xrunsIf an xrun occurs, the device    driver may, if requested, take certain steps to     handle it. Options include stopping the device,    or silencing all or part of the hardware buffer    used for playback.
            the stop threshold    if the number of frames of data/space available        meets or exceeds this value, the driver will stop        the interface.      the silence threshold    if the number of frames of space available        for a playback stream meets or exceeds this         value, the driver will fill part of the        playback hardware buffer with silence.     silence size     when the silence threshold level is met,         this determines how many frames of silence         are written into the playback hardware buffer                       
    Available minimum space/data for wakeupPrograms that use poll(2) or    select(2) to determine when    audio data may be transferred to/from the interface    may set this to control at what point    relative to the state of the hardware buffer,    they wish to be woken up.
    Transfer chunk sizethis determines the number of frames used when    transferring data to/from the device hardware buffer.
    There are a couple of other software parameters but theyneed not concern us here.Receiving and delivering dataNOT YET WRITTENWhy you might want to forget about all of this
    In a word:
    JACK
    .
    This document is Copyright (C) 2002 Paul Davis
    All source code in the document is licensed under the GNU PublicLicense (GPL), which may be read
    here
    .
                   
                   
                   
                   
                   

    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/87597/showart_2134288.html
  • 您需要登录后才可以回帖 登录 | 注册

    本版积分规则 发表回复

      

    北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
    未成年举报专区
    中国互联网协会会员  联系我们:huangweiwei@itpub.net
    感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP