Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents
maxLevel3
minLevel2
indent20px

...

A playback stream carries audio data over an isochronous OUT endpoint. There is a one-to-one relation between an isochronous OUT endpoint, an AudioStreaming interface and a Terminal. 101482827 presents the audio data flow implemented inside the Audio Processing module. The playback path relies on a ring buffer queue to synchronize the playback task, the core task and the codec ISR.

...

Panel
bgColor#f0f0f0

(1) The host activates the AudioStreaming interface #X by selecting the operational interface (request SET_INTERFACE sent for alternate setting 1). This marks the opening of the playback. The core task will call the function USBD_Audio_AS_IF_Start(). The first isochronous OUT transfer is submitted to the USB device driver to prime the stream. An empty audio buffer is taken from the ring buffer queue.

(2) The host then sets the sampling frequency for a certain isochronous OUT endpoint by sending a SET_CUR request. The function USBD_Audio_DrvAS_SamplingFreqManage() (not indicated in the figure) is called from the core task's context. This function is implemented by the audio peripheral driver and will set a DAC (Digital-to-Analog Converter) clock in the codec.

(3) The USB Device Controller fills the buffer with the isochronous audio data that have been sent by the host. The buffer is retrieved by the core task. As soon as one isochronous transfer is completed, the core task will call the callback USBD_Audio_PlaybackIsocCmpl() passed as a parameter of USBD_IsocRxAsync() . This callback notifies the audio class that a buffer with audio samples is ready for the audio codec.

Info
titleError Handling

If the isochronous transfer has completed with an error, USBD_Audio_PlaybackIsocCmpl() will free the buffer associated to the transfer.

(4) The received buffer is then added to the ring buffer queue.

(5) The core task will submit all the buffers it can to the USB device driver to feed the stream communication by calling USBD_IsocRxAsync()  several times.

(5a) Once a certain number of buffers (pre-buffering threshold) have been accumulated , the playback stream is started on the codec side by calling the function StreamStart() . The pre-buffering threshold is always equal to (MaxBufNbr / 2). The field MaxBufNbr is part of the structure USBD_AUDIO_STREAM_CFG . Within Drv_API_Ptr->PlaybackStart() , the audio peripheral driver should signal the playback task N times by calling via the function USBD_Audio_PlaybackTxCmpl() . N corresponds to the number of buffers it can queue. The driver should at least support the double-buffering and thus queue two buffers.

(6) Signalling the playback task consists in posting an AudioStreaming (AS) interface handle in a queue. The playback task wakes up and processes the handle. It submits a ready buffer taken from the ring buffer queue to the audio peripheral driver by calling the function StreamPlaybackTx() . Before being submitted to the audio peripheral driver, the received audio data may go through a correction in case of underrun or overrun situation of ring buffer queue. The playback stream correction is explained in section Playback Stream Correction . The audio peripheral driver should accumulate the ready buffer. After at least two buffers accumulated, the driver should send the first buffer to the codec usually by preparing a DMA transfer.

Tip
titleDMA in Audio Peripheral Driver

The use of DMA transfers is assumed to communicate with the audio codec. It allows to offload the CPU and to optimize performances.


Info
titleError Handling

If the ring buffer queue is empty, the playback task waits 1 ms and signals itself to re-submit another ready buffer to the audio peripheral driver. At least one ready buffer should have been inserted in the waiting list during the delay.

(7) In the same way as the core task in USBD_Audio_PlaybackIsocCmpl() , the playback task submits all buffers it can to the USB device driver by calling USBD_IsocRxAsync() several times.

Info
titleError Handling

If the submission with USBD_IsocRxAsync() fails by returning an error code, the buffer is freed back to the ring buffer queue.

(8) The buffer contains a chunk (1 ms of audio data) of audio stream. This audio chunk is encoded following a certain format. The audio peripheral driver might have to decode the audio chunk in order to correctly present the audio samples to the codec.

(9) Each time a playback buffer is consumed by the codec, the audio peripheral driver ISR signals to the playback task the end of an audio transfer by calling the function USBD_Audio_PlaybackTxCmpl() . This function posts a AS interface handle and free the consumed buffer back to the ring buffer queue.

(10) Afterwards, steps 3 to 9 are repeated over and over again until the host stops the playback by selecting the default AudioStreaming Interface (request SET_INTERFACE sent for alternate setting 0). At this time, the Audio Processing will stop the streaming on the codec side by calling the audio peripheral driver function StreamStop() . Basically, any playback DMA transfer is aborted. All the playback buffers attached to pending isochronous transfers will be freed automatically by the core which calls USBD_Audio_IsocPlaybackCmpl() for each aborted isochronous transfer.

Info

Refer to page Audio Peripheral Driver Guide for more details about the audio peripheral driver processing.


...

Panel
borderWidth0
titleFigure - Playback Ring Buffers Queue Monitoring


Figure - Adding a Sample in Case of Underrun illustrates the algorithm to add an audio sample in case of underrun situation. 

...

Warning

This stream correction is convenient for low-cost audio design. It will give good results as long as the incoming USB audio sampling frequency is very close to the DAC input clock frequency. However, if the difference between the two frequencies is important, this will add audio distortion.

Figure - Removing a Sample in Case of Overrun illustrates the algorithm to remove an audio sample in case of overrun situation. 

...

The playback stream correction offers the possibility to apply your own correction algorithm. If an underrun or overrun situation is detected, an application callback is called. Listing - Example of Playback Correction Callback Provided by the Application shows an example of playback correction callback prototype and definition provided by the application. 

...