Audio Class Configuration Guidelines

In order to optimize the usage of the audio class, there are a few places to pay attention to when configuring the audio class:

  • Memory segment size: parameter size of Mem_SegCreate() or µC/LIB heap size: LIB_MEM_CFG_HEAP_SIZE
  • µC/USB-Device general configuration for extra URBs (USB Request Block): USBD_CFG_MAX_NBR_URB_EXTRA
  • Buffers allocated to each AudioStreaming interface: field MaxBufNbr of structure USBD_AUDIO_STREAM_CFG passed as argument to USBD_Audio_AS_IF_Cfg

The recommendations for these places are:

  1. Buffers allocated for each AudioStreaming interface composing your audio function are allocated either from a dedicated memory segment created with Mem_SegCreate() or from the heap region defined by µC/LIB. Consequently, the parameter size of Mem_SegCreate() or the configuration constant LIB_MEM_CFG_HEAP_SIZE defining the heap region size must be set large enough to hold all playback and record buffers.
  2. USBD_CFG_MAX_NBR_URB_EXTRA is used by the core layer to assign an URB to each isochronous transfer submitted to the core and that could be queued in a USB device driver. Certain USB device drivers implement a queuing mechanism allowing to queue several isochronous transfers for a given endpoint. If a USB device driver is capable of queuing transfers and in order to take advantage of audio streaming, the total number of allocated buffers for all AudioStreaming interfaces should be equal to USBD_CFG_MAX_NBR_URB_EXTRA. It will allow the playback and record tasks to queue each time all isochronous transfers they can. They will spend less time trying to re-submit an isochronous transfer if this one could not be queued. If the USB device driver can only accept one transfer at a time, it is not necessary that the total number of allocated buffers be equal to USBD_CFG_MAX_NBR_URB_EXTRA. In that case, you can specify the total number of buffers you want. The result is that playback and record tasks will attempt more often to retry isochronous transfers that cannot be queued.
  3. The field MaxBufNbr of structure USBD_AUDIO_STREAM_CFG should be set accordingly following the two previous recommendations. Moreover, 

Table - Audio Class Configuration Guidelines presents some examples according to the type of audio application.

Table - Audio Class Configuration Guidelines
ConstantValueNote
Playback only application (2 channels, 16 bit resolution, 48 kHz)
APP_CFG_USBD_AUDIO_PLAYBACK_NBR_BUF16uApplication constant that can be passed to the field MaxBufNbr of structure USBD_AUDIO_STREAM_CFG
USBD_CFG_MAX_NBR_URB_EXTRA16uThe USB device driver is able to queue isochronous transfers.
parameter size of Mem_SegCreate()

LIB_MEM_CFG_HEAP_SIZE
-With 2 channels, 16 bit resolution, 48 kHz, each playback buffer is 192 bytes which gives a total of 192 * 20 = 3072 bytes. The memory segment or heap should be set accordingly to accommodate the 3072 bytes required.
Record only application (1 channel, 16 bit resolution, 48 kHz)
APP_CFG_USBD_AUDIO_RECORD_NBR_BUF16uApplication constant that can be passed to the field MaxBufNbr of structure  USBD_AUDIO_STREAM_CFG
USBD_CFG_MAX_NBR_URB_EXTRA0u

The USB device driver is not able to queue isochronous transfers.

USBD_CFG_MAX_NBR_URB_EXTRA set to 0 should be avoided. The record and/or the playback tasks can spend more time re-submitting isochronous transfers that cannot be queued. The stream may be altered by some zero-packet length isochoronous transfers provoking some audible audio artifacts. The USB device driver should support at least double-buffering when dealing with audio and isochronous transfers.

parameter size of Mem_SegCreate()

LIB_MEM_CFG_HEAP_SIZE
-With 1 channel, 16 bit resolution, 48 kHz, each record buffer is 96 bytes which gives a total of 96 * 16 = 1536 bytes. The memory segment or heap should be set accordingly to accommodate the 1536 bytes required.
Playback and record application (playback: 2 channels, 16 bit resolution, 48 kHz; record: 1 channel, 16 bit resolution, 48 kHz)
APP_CFG_USBD_AUDIO_PLAYBACK_NBR_BUF16uApplication constant that can be passed to the field MaxBufNbr of structure USBD_AUDIO_STREAM_CFG
APP_CFG_USBD_AUDIO_RECORD_NBR_BUF16uApplication constant that can be passed to the field MaxBufNbr of structure USBD_AUDIO_STREAM_CFG.
USBD_CFG_MAX_NBR_URB_EXTRA32uThe USB device driver is able to queue isochronous transfers.
parameter size of Mem_SegCreate()

LIB_MEM_CFG_HEAP_SIZE
 -Each playback buffer is 192 bytes which gives a total of 192 * 16 = 3072 bytes and each record buffer is 96 bytes which gives a total of 96 * 16 = 1536 bytes. At least, 5760 bytes must be available from the memory segment or the heap for all audio buffers. More heap space can be necessary for all software resources needed by the USB device stack and other Micrium products used in your application.

Heap Size

µC/USB-Device uses the heap to allocate some software resources such as internal buffers. The core, classes and certain drivers allocate resources on the heap. Moreover, you must take into account that other Micrium products also allocate from the heap. Thus, its size must be set accordingly.

Another recommendation relates to the configuration of the maximum number of interfaces (constant  USBD_CFG_MAX_NBR_IF ) and alternate interfaces (constant  USBD_CFG_MAX_NBR_IF_ALT ) needed for your audio function. Assuming that the audio class is the only class used, these formula can be used to determine the maximum number of interfaces and alternates interfaces for the audio class:

USBD_CFG_MAX_NBR_IF = sum of [(1 AudioControl interface + N AudioStreaming interface)] from 1 to X times Audio Interface Collection (AIC)

USBD_CFG_MAX_NBR_IF_ALT = sum of [(1 AudioControl interface + N AudioStreaming interface * M alternate settings)] from 1 to X times Audio Interface Collection (AIC)

where N is in the range [1, 255] and M in the range [2, 255]

When using the built-in playback or record correction, you should pay attention to the value of the MaxBufNbr field  of the structure  USBD_AUDIO_STREAM_CFG. The size of the safe zone depends on t he number of streams buffers, set in the field  MaxBufNbr . If you allocate more buffers for a given stream, the safe zone will be larger. Since the pre-buffering threshold for a stream is always ( MaxBufNbr / 2), if the safe zone is large, any slight clock drift between the USB and codec clocks will be easily absorbed and the risk of reaching the under-run or overrun situation is reduced (cf. Figure - Playback Ring Buffers Queue Monitoring).

If you activate any stream correction (built-in or feedback), you should set the number of buffers, the field MaxBufNbr, to a multiple of 6. This will optimize the stream correction processing. You can set the field  MaxBufNbr to one of these pre-defined constants:

  • USBD_AUDIO_STREAM_NBR_BUF_6
  • USBD_AUDIO_STREAM_NBR_BUF_12
  • USBD_AUDIO_STREAM_NBR_BUF_18
  • USBD_AUDIO_STREAM_NBR_BUF_24
  • USBD_AUDIO_STREAM_NBR_BUF_30
  • USBD_AUDIO_STREAM_NBR_BUF_36
  • USBD_AUDIO_STREAM_NBR_BUF_42

Furthermore, if you have a playback stream, you should favor the feedback correction. Indeed, the feedback correction allows a correction more progressive as the host is doing the audio samples adjustment based on the device feedback for a given stream. It makes the correction smoother and prevent the device from trying to compensate on its side a possible USB and codec clocks drifting by software that could impact the correction performance.