Audio Class Instance Configuration
Before starting the communication phase, your application needs to initialize and configure the class to suit your needs. Table - Audio Class Initialization API Summary summarizes the initialization functions provided by the audio class. For more details about the functions parameters, refer to the Audio API.
Function Name | Operation |
---|---|
USBD_Audio_Init()
| Initializes audio class internal structures, variables and the OS layer. |
USBD_Audio_Add()
| Creates a new instance of audio class. |
USBD_Audio_CfgAdd()
| Adds an existing audio instance to the specified device configuration. |
USBD_Audio_IT_Add()
| Adds an Input Terminal to the specified audio instance. |
USBD_Audio_OT_Add()
| Adds an Output Terminal to the specified audio instance. |
USBD_Audio_FU_Add()
| Adds a Feature Unit to the specified audio instance. |
USBD_Audio_MU_Add()
| Adds a Mixer Unit to the specified audio instance. |
USBD_Audio_SU_Add()
| Adds a Selector Unit to the specified audio instance. |
USBD_Audio_IT_Assoc
| Associates an Output Terminal to the Input Terminal. |
USBD_Audio_OT_Assoc
| Specifies the entity ID (terminal or unit) connected to the specified Output Terminal and associates an Input Terminal to it. |
USBD_Audio_FU_Assoc
| Specifies the entity ID (terminal or unit) connected to the specified Feature Unit. |
USBD_Audio_MU_Assoc
| Specifies the entities ID (terminal, unit) connected to the specified Mixer Unit. |
USBD_Audio_SU_Assoc
| Specifies the entities ID (terminal, unit) connected to the specified Selector Unit. |
USBD_Audio_MU_MixingCtrlSet
| Sets the mixing controls. |
USBD_Audio_AS_IF_Cfg(
)
| Configures the stream characteristics. |
USBD_Audio_AS_IF_Add()
| Add an AudioStreaming interface to the specified audio instance. |
You need to call these functions in the order shown below to successfully initialize the audio class:
- Call
USBD_Audio_Init()
This is the first function you should call and you should do it only once even if you use multiple class instances. This function initializes all internal structures and variables that the class needs. - Call
USBD_Audio_Add()
This function allocates an audio class instance. The audio instance represents an Audio Interface Collection (AIC). This function allows you to specify the Audio Peripheral Driver API. - Call
USBD_Audio_CfgAdd()
Once the audio class instance has been created, you must add it to a specific configuration. - Call
USBD_Audio_IT_Add()
This function adds an Input Terminal with its configuration to a specific AIC. An audio function will always have at least one Input Terminal. Hence, this function should be called at least once. - Call
USBD_Audio_OT_Add()
This function adds an Output Terminal with its configuration to a specific AIC. An audio function will always have at least one Output Terminal. Hence, this function should be called at least once. - Call
USBD_Audio_FU_Add()
This function adds a Feature Unit with its configuration to a specific AIC. Most of the time, an audio function will have at least one Feature Unit to control the stream (for example mute, volume). - Call
USBD_Audio_MU_Add()
This function adds a Mixer Unit with its configuration to a specific AIC. An audio function may have a Mixer Unit. In general, basics audio devices don't need a Mixer Unit (for instance microphone, speaker, headset). Hence, calling this function is optional. - Call
USBD_Audio_SU_Add()
This function adds a Selector Unit with its configuration to a specific AIC. An audio function may have a Selector Unit. In general, basics audio devices don't need a Selector Unit (for instance microphone, speaker, headset). Hence, calling this function is optional. - Call
USBD_Audio_IT_Assoc
This function associates an Output to the Input Terminal. The function is required if your audio device contains a bi-directional terminal. This terminal type describes an Input and an Output Terminal for voice communication that are closely related. If your device does not have a bi-directional terminal, calling this function is optional. - Call
USBD_Audio_OT_Assoc()
This function Specifies the entity ID (terminal or unit) connected to the specified Output Terminal and associates an Input Terminal to it. - Call
USBD_Audio_FU_Assoc()
This function specifies the terminal or unit connected to the Feature Unit. - Call
USBD_Audio_MU_Assoc()
This function specifies the terminals and/or units connected to the Mixer Unit. If your audio function does not have a Mixer Unit, calling this function is optional. - Call
USBD_Audio_SU_Assoc()
This function specifies the terminals and/or units connected to the Selector Unit. If your audio function does not have a Selector Unit, calling this function is optional. - Call
USBD_Audio_MU_MixingCtrlSet
This function configures the programmable mixing controls. - Call
USBD_Audio_AS_IF_Cfg()
This function configures a given stream according to some specified characteristics. - Call
USBD_Audio_AS_IF_Add()
This function adds an AudioStreaming interface with its configuration to a specific AIC. You can specify a name for the AudioStreaming interface.
Listing - Audio Class Initialization Example illustrates the use of the previous functions for initializing an audio class. Note that the error handling has been omitted for clarity.
The listing does not show an example of usage of the functions
USBD_Audio_MU_Assoc
,
USBD_Audio_SU_Assoc()
and
USBD_Audio_MU_MixingCtrlSet()
to avoid overloading the code snippet. Refer to the associated function page documentation for an example.
#define APP_CFG_USBD_AUDIO_TASKS_Q_LEN 20u #define APP_CFG_USBD_AUDIO_NBR_ENTITY 6u CPU_INT08U Speaker_IT_USB_OUT_ID; (1) CPU_INT08U Speaker_OT_ID; CPU_INT08U Speaker_FU_ID; static void App_USBD_Audio_Conn (CPU_INT08U dev_nbr, CPU_INT08U cfg_nbr, CPU_INT08U terminal_id, USBD_AUDIO_AS_HANDLE as_handle); static void App_USBD_Audio_Disconn(CPU_INT08U dev_nbr, CPU_INT08U cfg_nbr, CPU_INT08U terminal_id, USBD_AUDIO_AS_HANDLE as_handle); const USBD_AUDIO_EVENT_FNCTS App_USBD_Audio_EventFncts = { App_USBD_Audio_Conn, App_USBD_Audio_Disconn }; CPU_BOOLEAN App_USBD_Audio_Init (CPU_INT08U dev_nbr, CPU_INT08U cfg_hs, CPU_INT08U cfg_fs) { USBD_ERR err; CPU_INT08U audio_nbr; USBD_AUDIO_AS_IF_HANDLE speaker_playback_as_if_handle; /* Init Audio class. */ USBD_Audio_Init(APP_CFG_USBD_AUDIO_TASKS_Q_LEN, (2) &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } /* Create an audio class instance. */ audio_nbr = USBD_Audio_Add(APP_CFG_USBD_AUDIO_NBR_ENTITY, (3) &USBD_Audio_DrvCommonAPI_Simulation, &App_USBD_Audio_EventFncts, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } if (cfg_hs != USBD_CFG_NBR_NONE) { /* --------------- ADD HS CONFIGURATION --------------- */ USBD_Audio_CfgAdd(audio_nbr, (4) dev_nbr, cfg_hs, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } } if (cfg_fs != USBD_CFG_NBR_NONE) { /* --------------- ADD FS CONFIGURATION --------------- */ USBD_Audio_CfgAdd(audio_nbr, (5) dev_nbr, cfg_fs, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } } /* ----------- BUILD AUDIO FUNCTION TOPOLOGY ---------- */ /* Add terminals and units. */ Speaker_IT_USB_OUT_ID = USBD_Audio_IT_Add(audio_nbr, (6) &USBD_IT_USB_OUT_Cfg, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } Speaker_OT_ID = USBD_Audio_OT_Add(audio_nbr, &USBD_OT_SPEAKER_Cfg, DEF_NULL, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } Speaker_FU_ID = USBD_Audio_FU_Add(audio_nbr, &USBD_FU_SPEAKER_Cfg, &USBD_Audio_DrvFU_API_Simulation, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } /* Bind terminals and units. */ USBD_Audio_IT_Assoc(audio_nbr, (7) Speaker_IT_USB_OUT_ID, USBD_AUDIO_TERMINAL_NO_ASSOCIATION, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } USBD_Audio_OT_Assoc(audio_nbr, Speaker_OT_ID, Speaker_FU_ID, USBD_AUDIO_TERMINAL_NO_ASSOCIATION, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } USBD_Audio_FU_Assoc(audio_nbr, Speaker_FU_ID, Speaker_IT_USB_OUT_ID, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } /* ----------- CONFIGURE AUDIO STREAMING IF ----------- */ (8) speaker_playback_as_if_handle = USBD_Audio_AS_IF_Cfg(&USBD_SpeakerStreamCfg, &USBD_AS_IF1_SpeakerCfg, &USBD_Audio_DrvAS_API_Simulation, &App_USBD_Audio_MemSegInfo, Speaker_IT_USB_OUT_ID, DEF_NULL, &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } if (cfg_hs != USBD_CFG_NBR_NONE) { /* -------------- ADD AUDIO STREAMING IF -------------- */ USBD_Audio_AS_IF_Add(audio_nbr, (9) cfg_hs, speaker_playback_as_if_handle, &USBD_AS_IF1_SpeakerCfg, "Speaker AudioStreaming IF", &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } } if (cfg_fs != USBD_CFG_NBR_NONE) { /* -------------- ADD AUDIO STREAMING IF -------------- */ USBD_Audio_AS_IF_Add(audio_nbr, (10) cfg_fs, speaker_playback_as_if_handle, &USBD_AS_IF1_SpeakerCfg, "Speaker AudioStreaming IF", &err); if (err != USBD_ERR_NONE) { /* $$$$ Handle the error. */ } } return (DEF_OK); }
(1) These global variables will contain the terminal and unit IDs assigned by the audio class. These global variables can then be accessed by the Audio Peripheral Driver when processing class requests and streaming data.
(2) Initialize audio class internal structures, variables and OS layer. The queue size for the playback and record tasks is passed to the function. In this example, the constant APP_CFG_USBD_AUDIO_TASKS_Q_LEN
indicates that each task queue can contain up to 20 messages.
(3) Create a new audio class instance. USBD_Audio_DrvCommonAPI_Simulation
represents the Audio Peripheral Driver API. The API structure will be used by the Audio Processing module to execute a certain action associated to a class request. Refer to Audio Peripheral Driver Guide for more details about the Audio Peripheral Driver API. The structure App_USBD_Audio_EventFncts
contains class event callbacks called by the class during specific moments. The callback App_USBD_Audio_Conn()
is called when the host selects a device configuration. This callback is called for each AudioStreaming interface. You may retrieve some audio statistics from this callback (cf. page Audio Statistics). The callback App_USBD_Audio_Disconn()
is called once when the host selects a new device configuration, resets the device configuration or the USB device stack is stopped internally by the embedded application.
(4) Check if the high-speed configuration is active and proceed to add the audio instance previously created to this configuration.
(5) Check if the full-speed configuration is active and proceed to add the audio instance to this configuration.
(6) Build the audio function topology by adding all the required terminals and units. In this example, a speaker topology is built by adding an Input Terminal of type USB OUT, an Output Terminal of type Speaker and a Feature Unit to control the mute and volume controls of the speaker stream. This topology corresponds to the one shown in Figure - usbd_audio_dev_cfg.c - Typical Topologies Example. The audio class assigned a unique ID to each terminal and unit. Each ID can be stored in a global variable accessible by the Audio Peripheral Driver for class requests and stream data processing. The associated terminal or unit configuration structure is passed to the function USBD_Audio_XX_Add()
. Information contained in these structures will be stored internally in the audio class. Refer to Audio Topology Configuration page for more details about terminal and unit configuration structure. USBD_IT_USB_OUT_Cfg, USBD_OT_SPEAKER_Cfg
and USBD_FU_SPEAKER_Cfg
are declared in the file usbd_audio_dev_cfg.c
located in \ Micrium\Software\uC-USB-Device-V4\Cfg\Template\. Output Terminal, Feature, Mixer and Selector units Add() functions can receive an associated API provided by the Audio Peripheral Driver. In this example, the Output Terminal has no API associated, DEF_NULL
is passed. Whereas the Feature Unit has the API USBD_Audio_DrvFU_API_Simulation
.
(7) Build the connection between terminals and units using the ID assigned by the audio class. The terminals and units connection is based on the input pin(s). An Input Terminal has no input pin. Thus no entity source ID is passed as argument of USBD_Audio_IT_Assoc()
. In this example, a speaker is built. The speaker does not use a bi-directional terminal (that is an Input and Output Terminals working together). So the constant USBD_AUDIO_TERMINAL_NO_ASSOCIATION
is passed as argument to
USBD_Audio_IT_Assoc()
and
USBD_Audio_OT_Assoc()
. The call to the function USBD_Audio_IT_Assoc()
is not mandatory if there is no bi-directional terminal within the audio function.
(8) Configure the AudioStreaming interface with all the information passed as argument. In the example, the AudioStreaming interface is a speaker stream. The general speaker stream configuration structure, USBD_SpeakerStreamCfg
, and the AudioStreaming interface configuration structure, USBD_AS_IF1_SpeakerCfg,
are passed. Refer to section Streams for more details about these structures. Internally, the audio class will perform some checks and store any relevant information for the stream communication. The function will allocate buffers for the given stream taken into account the alignment requirement indicated by
USBD_AUDIO_CFG_BUF_ALIGN_OCTETS
. Buffers can be allocated from a general purpose heap or from the a specific memory segment. In the example, buffers will be allocated from the heap because a DEF_NULL
pointer is passed. Refer to the page
USBD_Audio_AS_IF_Cfg
for an example of buffers allocated from a memory segment. The terminal ID associated to this stream is also passed to the function. The 6th argument is a DEF_NULL
pointer, that is you don't provide an application playback stream correction callback. The audio class has a built-in stream correction enabled by USBD_AUDIO_CFG_PLAYBACK_CORR_EN
or USBD_AUDIO_CFG_RECORD_CORR_EN
configuration constants. If USBD_AUDIO_CFG_PLAYBACK_CORR_EN
is set to DEF_ENABLED
and the stream is a playback stream, you have the possibility to provide a callback that will implement your own playback stream correction in case of overrun and underrun situations. Listing - Example of Playback Correction Callback Provided by the Application gives an example of an application playback stream correction callback declaration. Refer to Stream Correction for more details about the built-in stream correction.
At the end, the function returns an handle identifying the stream.
(9) Add to the high-speed configuration an AudioStreaming interface. In the example, the stream handle returned by USBD_Audio_AS_IF_Cfg()
and the AudioStreaming interface structure, USBD_AS_IF1_SpeakerCfg
, are passed to the function.
(10) Add to the full-speed configuration an AudioStreaming interface. The different parameters passed to the function are the same as the one described in (8).