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). The host then sets the sampling frequency for a certain isochronous IN endpoint by sending 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 an ADC (Analog-to-Digital Converter) clock in the codec.

(2) When processing the SET_CUR(sampling frequency) request, the audio class will also start the record stream on the codec side by calling StreamStart() . In this function, a DMA transfer will be prepared to get the first record buffer from the codec. The initial receive buffer will be obtained by calling USBD_Audio_RecordBufGet() . This step is not entirely represented in the figure. The audio class ensures that the record stream is started on the codec side after setting the sampling frequency as a codec needs the correct clock settings before getting record data.

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.

(3) Once the first DMA transfer has completed, the audio peripheral driver will obtain the next receive buffer from the ring buffer queue by calling USBD_Audio_RecordBufGet() . This This function provides also to the audio peripheral driver the number of bytes to get from the codec.

(4) The buffer will be filled with audio samples given by one or more ADCs (one ADC per logical channel). The buffer will contain 1 ms worth of audio samples. This 1 ms of audio samples should be encoded, either directly by the codec (hardware) or by the audio peripheral driver (software). Most of the time, the codec will provide the chunk of audio stream already encoded. The driver signals the end of an audio transfer to the record task by calling the function USBD_Audio_RecordRxCmpl() . The signal represents an AudioStreaming interface handle.

(5) The record task wakes up and retrieves the ready buffer from the audio peripheral driver by calling the audio peripheral driver function StreamRecordRx() . The buffer is stored in the ring buffer queue.

(6) To prime the audio stream, the record task waits for a certain number of buffers to be ready. The pre-bufferring threshold is always equal to (MaxBufNbr / 2). The field  MaxBufNbr is part of the structure USBD_AUDIO_STREAM_CFG . Once the pre-buffering is done, the record task submits the initial isochronous IN transfer to the USB device driver via USBD_IsocTxAsync() . During the stream communication, the record task does not submit other isochronous transfers. Other USB transfers submission is done by the core task.

There is a special situation where the record task can submit a new transfer. When the stream communication loop is broken, that is there are no more ongoing isochronous transfers in the USB device driver, the record task restarts the stream with a new USB transfer.

(7) The USB device driver will send isochronous audio data to the host during a specific frame.

(8) Upon completion of the isochronous IN transfer, the core task will call the callback USBD_Audio_RecordIsocCmpl() provided by the Audio Processing as an argument of USBD_IsocTxAsync() . This callback will free the buffer by returning it in the ring buffer queue. Before the buffer return int the ring buffer queue, a stream correction may happen for the next record buffer to fill by the codec. The record stream correction is explained in section  Record Stream Correction.  

Info
titleError Handling

If a transfer has completed with an error, the associated buffer is freed by USBD_Audio_RecordIsocCmpl().

(9) The core task submits all the ready buffers it can to the USB device driver by calling USBD_IsocTxAsync()  several times. The core task is thus responsible to maintain alive the stream communication by repeating the steps 7 and 8.

Info
titleError Handling

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

(10) Once the audio stream is initiated, the steps 3 to 8 will repeat over and over again until the host stops recording 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 StreamRecordStop() . Basically, any record DMA transfer will be aborted. All empty buffers being processed and all ready buffers not yet retrieved by the record task are implicitly freed by the ring buffer queue reset. On the USB side, all the record buffers unconsumed will be freed automatically by the core by calling USBD_Audio_IsocRecordCmpl() for each aborted isochronous transfers.

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. 

...