Audio Statistics

During the development of your audio function, you may be interested in knowing what is happening during stream communication. The audio class offers a few statistics per AudioStreaming interface. The configuration constant USBD_AUDIO_CFG_STAT_EN allows you to activate the audio stream statistics. You need to set it to DEF_ENABLED.

You will have to use the structure USBD_AUDIO_STAT in your audio application to get statistics. This structure collects long-term statistics for a given AudioStreaming interface, that is each time the corresponding stream is opened and used by the host. The statistics are not reset when the stream is closed. Audio Statistics#Listing - Getting Audio Statistics in the Application shows how to retrieve audio statistics from your application.

#if (USBD_AUDIO_CFG_STAT_EN == DEF_ENABLED)                     (1)
USBD_AUDIO_STAT  *App_SpeakerStatPtr;                           (2)
USBD_AUDIO_STAT  *App_MicStatPtr;
#endif
                                                                (3)
static  void  App_USBD_Audio_Conn (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)
{
    ...
                                                                
    audio_nbr = USBD_Audio_Add(APP_CFG_USBD_AUDIO_NBR_ENTITY,
                              &USBD_Audio_DrvCommonAPI_Simulation,
                              &App_USBD_Audio_EventFncts,       (4)
                              &err);
    if (err != USBD_ERR_NONE) {
        /* $$$$ Handle the error. */
    }
    ...
    return (DEF_OK);
}
                                                                (5)
static void  App_USBD_Audio_Conn(CPU_INT08U            dev_nbr, 
                                 CPU_INT08U            cfg_nbr,
                                 CPU_INT08U            terminal_id,
                                 USBD_AUDIO_AS_HANDLE  as_handle)
{
    (void)&dev_nbr;
    (void)&cfg_nbr;
#if (USBD_AUDIO_CFG_STAT_EN == DEF_ENABLED)
    if (terminal_id == Mic_OT_USB_IN_ID) {                      (6)
        App_MicStatPtr = USBD_Audio_AS_IF_StatGet(as_handle);
    } else if (terminal_id == Speaker_IT_USB_OUT_ID) {
        App_SpeakerStatPtr = USBD_Audio_AS_IF_StatGet(as_handle);
    }
#else
    (void)&terminal_id;
    (void)&p_as_if_arg;
#endif
}

(1) Your debug code for audio statistics could be surrounded by some preprocessor directives testing USBD_AUDIO_CFG_STAT_EN.

(2) Declare a pointer to an USBD_AUDIO_STAT structure. You can have one pointer per stream you want to follow. In the example, the pointers App_SpeakerStatPtr and App_MicStatPtr allows respectively to monitor the speaker and record streams.

(3) Declare a connection event function that will be called by the audio class when the device configuration is selected by the host. In this example, the function named App_USBD_Audio_Conn() will allow you to retrieve references to the speaker and record stream statistics structures. This function will initialize a function pointer from the audio event structure USBD_AUDIO_EVENT_FNCTS.

(4) When creating an audio class instance with USBD_Audio_Add(), the third argument will be a reference to the structure containing the connection event function.

(5) The audio class will call App_USBD_Audio_Conn() for each AudioStreaming interface.

(6) Call the function USBD_Audio_AS_IF_StatGet()to get statistics about the microphone in the example. The audio class will return a reference to the USBD_AUDIO_STAT structure assigned to the microphone stream. This reference is kept by the pointer App_MicStatPtr . You may have to check the terminal ID if you have several audio streams statistics to retrieve. For each stream, call again USBD_Audio_AS_IF_StatGet() . The audio statistics structure can be consulted during debug operations in a watch window for instance.

Table - USBD_AUDIO_STAT Structure Fields Description gives more details about the fields of USBD_AUDIO_STAT structure. The fields are basically counters that are incremented to follow a certain statistic. Counters are placed strategically inside the audio class to monitor the stream communication.The column "Description" will refer to the stream data flow. Refer to Audio Class Stream Data Flow  as a complement to fully understand counters.

Table - USBD_AUDIO_STAT Structure Fields Description
FieldDescriptionDescription
Related to Playback
AudioProc_Playback_NbrIsocRxSubmitSuccessTotal number of isochronous OUT transfers successfully submitted to the USB device driver. The sum of AudioProc_Playback_NbrIsocRxSubmitPlaybackTask with AudioProc_Playback_NbrIsocRxSubmitCoreTask should be equal to this counter when a stream is closed.Total number of isochronous OUT transfers successfully submitted to the USB device driver. The sum of AudioProc_Playback_NbrIsocRxSubmitPlaybackTask with AudioProc_Playback_NbrIsocRxSubmitCoreTask should be equal to this counter when a stream is closed.
AudioProc_Playback_NbrIsocRxSubmitErrNumber of isochronous OUT transfers  submitted to the USB device driver with an error.Number of isochronous OUT transfers  submitted to the USB device driver with an error.
AudioProc_Playback_NbrIsocRxSubmitPlaybackTaskNumber of isochronous OUT transfers successfully submitted by the Playback task.Number of isochronous OUT transfers successfully submitted by the Playback task.
AudioProc_Playback_NbrIsocRxSubmitCoreTaskNumber of isochronous OUT transfers successfully submitted by the Core task.Number of isochronous OUT transfers successfully submitted by the Core task.
AudioProc_Playback_NbrIsocRxCmpl

Number of isochronous OUT transfers completed with or without error. That is USBD_Audio_PlaybackIsocCmpl() has been called by the Core task.

Number of isochronous OUT transfers completed with or without error. That is USBD_Audio_PlaybackIsocCmpl() has been called by the Core task.

AudioProc_Playback_NbrIsocRxCmplErrOther

Number of isochronous OUT transfers completed with an error different from USBD_ERR_EP_ABORT. That is USBD_Audio_ Playback IsocCmpl() has been called by the Core task.

Number of isochronous OUT transfers completed with an error different from USBD_ERR_EP_ABORT. That is USBD_Audio_ Playback IsocCmpl() has been called by the Core task.

AudioProc_Playback_NbrIsocRxCmplErrAbortNumber of isochronous OUT transfers completed with the error code USBD_ERR_EP_ABORT . When a stream closes, a few isochronous transfers may be pending in the USB device driver, the Core task aborts all pending transfers by calling USBD_Audio_ Playback IsocCmpl() with the error code USBD_ERR_EP_ABORT . This error code is a normal error.Number of isochronous OUT transfers completed with the error code USBD_ERR_EP_ABORT . When a stream closes, a few isochronous transfers may be pending in the USB device driver, the Core task aborts all pending transfers by calling USBD_Audio_ Playback IsocCmpl() with the error code USBD_ERR_EP_ABORT . This error code is a normal error.
AudioProc_Playback_NbrIsocRxBufNotAvail

Number of times no buffer available for Playback and Core tasks while preparing a new isochronous transfer.

Number of times no buffer available for Playback and Core tasks while preparing a new isochronous transfer.

AudioProc_Playback_NbrReqPostPlaybackTaskNumber of requests submitted to the Playback task. A request is a stream handle sent when opening the playback stream and each time an audio transfer is finished. At the stream closing, this counter should be equal to AudioProc_Playback_NbrReqPendPlaybackTask.Number of requests submitted to the Playback task. A request is a stream handle sent when opening the playback stream and each time an audio transfer is finished. At the stream closing, this counter should be equal to AudioProc_Playback_NbrReqPendPlaybackTask.
AudioProc_Playback_NbrReqPendPlaybackTaskNumber of requests retrieved by the Playback task. Each time the Playback task wakes up, this counter is incremented.Number of requests retrieved by the Playback task. Each time the Playback task wakes up, this counter is incremented.
AudioProc_Playback_NbrIsocRxOngoingCnt

Current number of isochronous OUT transfers in progress. That is transfers have been submitted to the USB device driver but are not yet finished. A transfer is being processed or transfers are waiting to be processed by the USB device controller.

Current number of isochronous OUT transfers in progress. That is transfers have been submitted to the USB device driver but are not yet finished. A transfer is being processed or transfers are waiting to be processed by the USB device controller.

Related to Playback Feedback: all these counters are available only if USBD_AUDIO_CFG_PLAYBACK_FEEDBACK_EN is set to DEF_ENABLED .
AudioProc_Playback_SynchNbrBufGet

Number of feedback buffers obtained each time a new feedback value must be sent to the host. There is one and unique feedback buffer per stream. If a new feedback value is to be sent and the single buffer is already in use, this feedback value is lost. The counter AudioProc_Playback_SynchNbrBufNotAvail indicates the feedback values lost.

Number of feedback buffers obtained each time a new feedback value must be sent to the host. There is one and unique feedback buffer per stream. If a new feedback value is to be sent and the single buffer is already in use, this feedback value is lost. The counter AudioProc_Playback_SynchNbrBufNotAvail indicates the feedback values lost.

AudioProc_Playback_SynchNbrBufFree Number of feedback buffers made available again. The unique feedback buffer is made available each time an isochronous IN transfer completes or in case of error when submitting an isochronous transfer with the function USBD_IsocTxAsync().Number of feedback buffers made available again. The unique feedback buffer is made available each time an isochronous IN transfer completes or in case of error when submitting an isochronous transfer with the function USBD_IsocTxAsync().
AudioProc_Playback_SynchNbrBufNotAvail Number of times the unique feedback buffer is not available because already in use. In that case, the feedback value is lost.Number of times the unique feedback buffer is not available because already in use. In that case, the feedback value is lost.
AudioProc_Playback_SynchNbrSafeZone Number of normal situations without feedback correction. Number of normal situations without feedback correction. 
AudioProc_Playback_SynchNbrOverrun

Number of overrun situations requiring feedback correction.

Number of overrun situations requiring feedback correction.

AudioProc_Playback_SynchNbrLightOverrun Number of light overrun situations. Refer to section Playback Feedback Correction for more details about a light overrun.Number of light overrun situations. Refer to section Playback Feedback Correction for more details about a light overrun.
AudioProc_Playback_SynchNbrHeavyOverrun Number of heavy overrun situations. Refer to section Playback Feedback Correction  for more details about a heavy overrun.Number of heavy overrun situations. Refer to section Playback Feedback Correction  for more details about a heavy overrun.
AudioProc_Playback_SynchNbrUnderrun Number of underrun situations requiring feedback correction. Number of underrun situations requiring feedback correction. 
AudioProc_Playback_SynchNbrLightUnderrun Number of light underrun situations. Refer to section Playback Feedback Correction  for more details about a light underrun.Number of light underrun situations. Refer to section Playback Feedback Correction  for more details about a light underrun.
AudioProc_Playback_SynchNbrHeavyUnderrun Number of heavy underrun situations. Refer to section Playback Feedback Correction for more details about a heavy underrun.Number of heavy underrun situations. Refer to section Playback Feedback Correction for more details about a heavy underrun.
AudioProc_Playback_SynchNbrRefreshPeriodReached Number of times the refresh period has been reached, The audio device reports a feedback value every bRefresh period. This bRefresh period is defined in the feedback Endpoint descriptor retrieved by the host during the enumeration. The audio class evaluates the feedback correction each time a playback buffer is received from host. When the number of frames elapsed matches the bRefresh period, a feedback value is sent. Refer to section Playback Feedback Correction  for more details.Number of times the refresh period has been reached, The audio device reports a feedback value every bRefresh period. This bRefresh period is defined in the feedback Endpoint descriptor retrieved by the host during the enumeration. The audio class evaluates the feedback correction each time a playback buffer is received from host. When the number of frames elapsed matches the bRefresh period, a feedback value is sent. Refer to section Playback Feedback Correction  for more details.
AudioProc_Playback_SynchNbrIsocTxSubmitted Number of isochronous IN transfers successfully submitted to the USB device driver. Number of isochronous IN transfers successfully submitted to the USB device driver. 
AudioProc_Playback_SynchNbrIsocTxCmpl Number of isochronous IN transfers completed with or without an error. That is USBD_Audio_IsocPlaybackSynchCmpl () has been called by the Core task.Number of isochronous IN transfers completed with or without an error. That is USBD_Audio_IsocPlaybackSynchCmpl () has been called by the Core task.
Related to Record
AudioProc_Record_NbrIsocTxSubmitSuccessTotal number of isochronous IN transfers successfully submitted to the USB device driver. The sum of AudioProc_Record_NbrIsocTxSubmitRecordTask   with AudioProc_Record_NbrIsocTxSubmitCoreTask should be equal to this counter when a stream is closed.Total number of isochronous IN transfers successfully submitted to the USB device driver. The sum of AudioProc_Record_NbrIsocTxSubmitRecordTask   with AudioProc_Record_NbrIsocTxSubmitCoreTask should be equal to this counter when a stream is closed.
AudioProc_Record_NbrIsocTxSubmitErrNumber of isochronous IN transfers  submitted to the USB device driver with an error.Number of isochronous IN transfers  submitted to the USB device driver with an error.
AudioProc_Record_NbrIsocTxSubmitRecordTaskNumber of isochronous IN transfers successfully submitted by the Record task.Number of isochronous IN transfers successfully submitted by the Record task.
AudioProc_Record_NbrIsocTxSubmitCoreTaskNumber of isochronous IN transfers successfully submitted by the Core task.Number of isochronous IN transfers successfully submitted by the Core task.
AudioProc_Record_NbrIsocTxCmplNumber of isochronous IN transfers completed with or without an error. That is USBD_Audio_RecordIsocCmpl () has been called by the Core task.Number of isochronous IN transfers completed with or without an error. That is USBD_Audio_RecordIsocCmpl () has been called by the Core task.
AudioProc_Record_NbrIsocTxCmplErrOtherNumber of isochronous IN transfers completed with an error different from  USBD_ERR_EP_ABORT .  That is USBD_Audio_RecordIsocCmpl()  has been called by the Core task.Number of isochronous IN transfers completed with an error different from  USBD_ERR_EP_ABORT .  That is USBD_Audio_RecordIsocCmpl()  has been called by the Core task.
AudioProc_Record_NbrIsocTxCmplErrAbortNumber of isochronous IN transfers completed with the error code  USBD_ERR_EP_ABORT . When a stream closes, a few isochronous transfers may be pending in the USB device driver, the Core task aborts all pending transfers by calling USBD_Audio_RecordIsocCmpl() with the error code USBD_ERR_EP_ABORT. This error code is a normal error.Number of isochronous IN transfers completed with the error code  USBD_ERR_EP_ABORT . When a stream closes, a few isochronous transfers may be pending in the USB device driver, the Core task aborts all pending transfers by calling USBD_Audio_RecordIsocCmpl() with the error code USBD_ERR_EP_ABORT. This error code is a normal error.
AudioProc_Record_NbrIsocTxBufNotAvailNumber of times no buffer available for Record and Core tasks while preparing a new isochronous transfer.Number of times no buffer available for Record and Core tasks while preparing a new isochronous transfer.
AudioProc_Record_NbrReqPostRecordTaskNumber of requests submitted to the Record task. A request is a stream handle sent each time a record buffer ready to be sent to the host is signaled to the Record task by the Audio Peripheral Driver. When the stream is closed, this counter should be equal to AudioProc_Record_NbrReqPendRecordTask.Number of requests submitted to the Record task. A request is a stream handle sent each time a record buffer ready to be sent to the host is signaled to the Record task by the Audio Peripheral Driver. When the stream is closed, this counter should be equal to AudioProc_Record_NbrReqPendRecordTask.
AudioProc_Record_NbrReqPendRecordTask

Number of requests retrieved by the Record task. Each time the Record task wakes up, this counter is incremented.

Number of requests retrieved by the Record task. Each time the Record task wakes up, this counter is incremented.

Related to Playback and Record
AudioProc_RingBufQ_NbrProducerStartIxCatchUpNumber of times the index ProducerStart has caught up the index ConsumerEnd and/or ProducerEnd.Number of times the index ProducerStart has caught up the index ConsumerEnd and/or ProducerEnd.
AudioProc_RingBufQ_NbrProducerEndIxCatchUpNumber of times the index ProducerEnd has caught up the index ProducerStart and/or ConsumerStart .Number of times the index ProducerEnd has caught up the index ProducerStart and/or ConsumerStart .
AudioProc_RingBufQ_NbrConsumerStartIxCatchUpNumber of times the index ConsumerStart has caught up the index ProducerEnd and/or ConsumerEnd.Number of times the index ConsumerStart has caught up the index ProducerEnd and/or ConsumerEnd.
AudioProc_RingBufQ_NbrConsumerEndIxCatchUpNumber of times the index ConsumerEnd has caught up the index ConsumerStart and/or ProducerStart.Number of times the index ConsumerEnd has caught up the index ConsumerStart and/or ProducerStart.
AudioProc_RingBufQ_NbrProducerStartIxWrapAroundNumber of wrap-around for the index ProducerStart of the ring buffer queue.Number of wrap-around for the index ProducerStart of the ring buffer queue.
AudioProc_RingBufQ_NbrProducerEndIxWrapAroundNumber of wrap-around for the index ProducerEnd of the ring buffer queue.Number of wrap-around for the index ProducerEnd of the ring buffer queue.
AudioProc_RingBufQ_NbrConsumerStartIxWrapAroundNumber of wrap-around for the index Consumer Start of the ring buffer queue.Number of wrap-around for the index Consumer Start of the ring buffer queue.
AudioProc_RingBufQ_NbrConsumerEndIxWrapAroundNumber of wrap-around for the index ConsumerEnd of the ring buffer queue.Number of wrap-around for the index ConsumerEnd of the ring buffer queue.
AudioProc_RingBufQ_NbrBufDescInUseNumber of buffer descriptors in use by playback or record streams. Buffer descriptors are used internally by the audio class, in particular to support multi-streaming. It allows the Playback or Record task to manage buffers from different AudioStreaming interfaces.Number of buffer descriptors in use by playback or record streams. Buffer descriptors are used internally by the audio class, in particular to support multi-streaming. It allows the Playback or Record task to manage buffers from different AudioStreaming interfaces.
AudioProc_RingBufQ_NbrErrNumber of times there was an error getting a buffer from the ring buffer queue.Number of times there was an error getting a buffer from the ring buffer queue.
AudioProc_NbrStreamOpenNumber of times the stream has been open by the host. This counter is incremented when the host sends a SET_INTERFACE request to the device with a non-null alternate setting.Number of times the stream has been open by the host. This counter is incremented when the host sends a SET_INTERFACE request to the device with a non-null alternate setting.
AudioProc_NbrStreamClosedNumber of times the stream has been closed. This counter is incremented when the host sends a SET_INTERFACE request to the device with a null alternate setting and when an internal error within the audio class occurs requiring to mark the stream as closed. When a stream is closed and no error occurs internally, this counter should be equal to AudioProc_NbrStreamOpen.Number of times the stream has been closed. This counter is incremented when the host sends a SET_INTERFACE request to the device with a null alternate setting and when an internal error within the audio class occurs requiring to mark the stream as closed. When a stream is closed and no error occurs internally, this counter should be equal to AudioProc_NbrStreamOpen.
AudioProc_CorrNbrUnderrunNumber of underrun situations requiring built-in playback or record correction. Number of underrun situations requiring built-in playback or record correction. 
AudioProc_CorrNbrOverrunNumber of overrun situations requiring built-in playback or record correction. Number of overrun situations requiring built-in playback or record correction. 
AudioProc_CorrNbrSafeZoneNumber of normal situations without built-in playback or record correction. Number of normal situations without built-in playback or record correction. 
Related to Playback and Record from Audio Peripheral Driver
AudioDrv_Playback_DMA_NbrXferCmplNumber of playback buffers consumed by the Audio Peripheral Driver. By default, audio statistics are not available in the Audio Peripheral Driver. Since the Audio Peripheral Driver is written by you, you can use the macro AUDIO_DRV_STAT_INC() to increment this counter. Refer to Statistics for more details about where to use this macro.Number of playback buffers consumed by the Audio Peripheral Driver. By default, audio statistics are not available in the Audio Peripheral Driver. Since the Audio Peripheral Driver is written by you, you can use the macro AUDIO_DRV_STAT_INC() to increment this counter. Refer to Statistics for more details about where to use this macro.
AudioDrv_Playback_DMA_NbrSilenceBufNumber of silence buffers consumed by the Audio Peripheral Driver. If there are no playback buffers ready to play by the codec, the driver should simply send silence buffers. This counter can be incremented with the macro AUDIO_DRV_STAT_INC() .Number of silence buffers consumed by the Audio Peripheral Driver. If there are no playback buffers ready to play by the codec, the driver should simply send silence buffers. This counter can be incremented with the macro AUDIO_DRV_STAT_INC() .
AudioDrv_Record_DMA_NbrXferCmplNumber of record buffers produced by the Audio Peripheral Driver. You can use the macro AUDIO_DRV_STAT_INC() to increment this counter.Number of record buffers produced by the Audio Peripheral Driver. You can use the macro AUDIO_DRV_STAT_INC() to increment this counter.
AudioDrv_Record_DMA_NbrDummyBufNumber of dummy buffers used by the Audio Peripheral Driver because no empty record buffers are available. If there are no record buffers available, the driver may need to falsely consume some record data while waiting for some record buffers to be free. This counter can be incremented with the macro AUDIO_DRV_STAT_INC().Number of dummy buffers used by the Audio Peripheral Driver because no empty record buffers are available. If there are no record buffers available, the driver may need to falsely consume some record data while waiting for some record buffers to be free. This counter can be incremented with the macro AUDIO_DRV_STAT_INC().