3.3.2.3.8 Audio Data Streaming

The application can use the USB_HOST_AUDIO_V1_0_StreamRead and USB_HOST_AUDIO_V1_0_StreamWrite functions to transfer data to an Audio Stream. While calling these functions, the stream handle specifies the target Audio stream and the event handler function to which the events should be sent. It is possible for multiple clients to open the same audio stream and transfer data to the stream.

Calling the USB_HOST_AUDIO_V1_0_StreamRead and USB_HOST_AUDIO_V1_0_StreamWrite functions while a read/write transfer is already in progress will cause the transfer result to be queued. If the transfer was successfully queued or scheduled, the USB_HOST_AUDIO_V1_0_StreamRead and USB_HOST_AUDIO_V1_0_StreamWrite functions will return a valid transfer handle. This transfer handle identifies the transfer request. The application clients can use the transfer handles to keep track of multiple queued transfers. When a transfer completes, the Audio stream handler generates an event. The following table shows the event and the event data associated with the event.

Table 1: Read

Function USB_HOST_AUDIO_V1_0_StreamRead
Event USB_HOST_AUDIO_V1_0_STREAM_EVENT_READ_COMPLETE
Event Data Type USB_HOST_AUDIO_V1_0_STREAM_EVENT_READ_COMPLETE _DATA

Table 2: Write

Function USB_HOST_AUDIO_V1_0_StreamWrite
Event USB_HOST_AUDIO_V1_0_STREAM_EVENT_WRITE_COMPLETE
Event Data Type USB_HOST_AUDIO_V1_0_STREAM_EVENT_WRITE_COMPLETE _DATA

The event data contains information on the amount of data transferred, completion status and the transfer handle of the transfer. The following code shows an example of reading and writing data.

/* This code  shows an example of audio data streaming */
/* PCM16 samples for 1Khz Sine Wave at 48 kHz Sample Rate */
uint16_t audioSamples[96] =  {
    0x0000, 0x0000,  //Sample 1
    0x10B4, 0x10B4,  //Sample 2
    0x2120, 0x2120,  //Sample 3
    0x30FB, 0x30FB,  //Sample 4
    0x3FFF, 0x3FFF,  //Sample 5
    0x4DEB, 0x4DEB,  //Sample 6
    0x5A81, 0x5A81,  //Sample 7
    0x658B, 0x658B,  //Sample 8
    0x6ED9, 0x6ED9,  //Sample 9
    0x7640, 0x7640,  //Sample 10
    0x7BA2, 0x7BA2,  //Sample 11
    0x7EE6, 0x7EE6,  //Sample 12
    0x7FFF, 0x7FFF,  //Sample 13
    0x7FE6, 0x7FE6,  //Sample 14
    0x7BA2, 0x7BA2,  //Sample 15
    0x7640, 0x7640,  //Sample 16
    0x6ED9, 0x6ED9,  //Sample 17
    0x658B, 0x658B,  //Sample 18
    0x5A81, 0x5A81,  //Sample 19
    0x4DEB, 0x4DEB,  //Sample 20
    0x3FFF, 0x3FFF,  //Sample 21
    0x30FB, 0x30FB,  //Sample 22
    0x2120, 0x2120,  //Sample 23
    0x10B4, 0x10B4,  //Sample 24
    0x0000, 0x0000,  //Sample 25
    0xEF4C, 0xEF4C,  //Sample 26
    0xDEE0, 0xDEE0,  //Sample 27
    0xCF05, 0xCF05,  //Sample 28
    0xC001, 0xC001,  //Sample 29
    0xB215, 0xB215,  //Sample 30
    0xA57F, 0xA57F,  //Sample 31
    0x9A75, 0x9A75,  //Sample 32
    0x9127, 0x9127,  //Sample 33
    0x89C0, 0x89C0,  //Sample 34
    0x845E, 0x845E,  //Sample 35
    0x811A, 0x811A,  //Sample 36
    0x8001, 0x8001,  //Sample 37
    0x811A, 0x811A,  //Sample 38
    0x845E, 0x845E,  //Sample 39
    0x89C0, 0x89C0,  //Sample 40
    0x9127, 0x9127,  //Sample 41
    0x9A75, 0x9A75,  //Sample 42
    0xA57F, 0xA57F,  //Sample 43
    0xB215, 0xB215,  //Sample 44
    0xC001, 0xC001,  //Sample 45
    0xCF05, 0xCF05,  //Sample 46
    0xDEE0, 0xDEE0,  //Sample 47
    0xFF4C, 0xFF4C,  //Sample 48
};

/* Specify the Audio Stream format details that this application supports */
const APP_USB_HOST_AUDIO_STREAM_FORTMAT audioSpeakerStreamFormat =
{

    .streamDirection = USB_HOST_AUDIO_V1_0_DIRECTION_OUT,
    .format = USB_AUDIO_FORMAT_PCM,
    .nChannels = 2,
    .bitResolution = 16,
    .subFrameSize = 2,
    .samplingRate = 48000
};

bool isAudioDeviceAttached = false;
bool isStreamEnabled = false;
bool isAudioWriteCompleted = false;
USB_HOST_AUDIO_V1_0_OBJ audioDeviceObj;
USB_HOST_AUDIO_V1_0_STREAM_TRANSFER_HANDLE transferHandleAudioWrite;



/*************************************************************
 * Audio Stream Event Handler function.
 ************************************************************/

USB_HOST_AUDIO_V1_0_STREAM_EVENT_RESPONSE APP_USBHostAudioStreamEventHandler
(
    USB_HOST_AUDIO_V1_0_STREAM_HANDLE streamHandle,
    USB_HOST_AUDIO_V1_0_STREAM_EVENT event,
    void * eventData,
    uintptr_t context
)
{
    USB_HOST_AUDIO_V1_0_STREAM_EVENT_WRITE_COMPLETE_DATA * writeCompleteEventData;
    switch(event)
    {
        case USB_HOST_AUDIO_V1_0_STREAM_EVENT_DISABLE_COMPLETE:

            break;

        case USB_HOST_AUDIO_V1_0_STREAM_EVENT_ENABLE_COMPLETE:
            /* Check eventData result member to know if stream enable is complete */
                isStreamEnabled = true;

            break;
        case USB_HOST_AUDIO_V1_0_STREAM_EVENT_WRITE_COMPLETE:

             /* This means the Write request completed. We can
             * find out if the request was successful. */
            writeCompleteEventData =
                (USB_HOST_AUDIO_V1_0_STREAM_EVENT_WRITE_COMPLETE_DATA*)eventData;
            if(transferHandleAudioWrite == writeCompleteEventData->transferHandle)
            {
                isAudioWriteCompleted = true;
            }
            break;
        default:
            break;
    }
    return USB_HOST_AUDIO_V1_0_STREAM_EVENT_RESPONSE_NONE;
}
/*************************************************************/
/* Function to search for a specific Audio Stream */
/************************************************************/
USB_HOST_AUDIO_V1_0_STREAM_OBJ App_USBHostAudioSpeakerStreamFind
(
    USB_HOST_AUDIO_V1_0_OBJ audioDeviceObj,
    APP_USB_HOST_AUDIO_STREAM_FORTMAT audioStream,
    uint8_t* numberofStreamGroups
)
{
    USB_HOST_AUDIO_V1_0_RESULT result;
    USB_HOST_AUDIO_V1_0_STREAM_INFO streamInfo;

    /* Get Number of Stream Groups */
    *numberofStreamGroups = USB_HOST_AUDIO_V1_0_NumberOfStreamGroupsGet(audioDeviceObj);
    if (*numberofStreamGroups == 0)
    {
        return (USB_HOST_AUDIO_V1_0_STREAM_OBJ)0;
    }
    /* Get the First Stream Information in the Stream Group */
    result = USB_HOST_AUDIO_V1_0_StreamGetFirst(appData.audioDeviceObj, 0, &streamInfo);
    if (result == USB_HOST_AUDIO_V1_0_RESULT_SUCCESS)
    {
         /* Compare Audio Stream info */
        if ((streamInfo.format == audioStream.format)
            && (streamInfo.streamDirection == audioStream.streamDirection)
                    && (streamInfo.nChannels == audioStream.nChannels)
                    && (streamInfo.bitResolution == audioStream.bitResolution)
                    && (streamInfo.subFrameSize == audioStream.subFrameSize))
        {
            return streamInfo.streamObj;
        }
    }
    return (USB_HOST_AUDIO_V1_0_STREAM_OBJ)0;
}

/*************************************************************/
/* Audio attach event listener function */
/************************************************************/
void APP_USBHostAudioAttachEventListener
(
    USB_HOST_AUDIO_V1_0_OBJ audioObj,
    USB_HOST_AUDIO_V1_0_EVENT event,
    uintptr_t context
)
{
    /* This function gets called when the Audio v1.0 device is attached/detached. In this
     * example we let the application know that a device is attached and we
     * store the Audio v1.0 device object. This object will be required to open the
     * device. */
    switch (event)
    {
        case USB_HOST_AUDIO_V1_0_EVENT_ATTACH:
            if (isAudioDeviceAttached == false)
            {
                isAudioDeviceAttached = true;
                audioDeviceObj = audioObj;
            }
            else
            {
                /* This application supports only one Audio Device . Handle Error Here.*/
            }
        break;
        case USB_HOST_AUDIO_V1_0_EVENT_DETACH:
            if (isAudioDeviceAttached == true)
            {
                /* This means the device was detached. There is no event data
                 * associated with this event.*/
                isAudioDeviceAttached = false;
                break;
            }
        break;
    }
}

/*************************************************************/
/* Audio Tasks function */
/************************************************************/
void APP_Tasks ( void )
{
    USB_HOST_AUDIO_V1_0_RESULT audioResult;
    USB_HOST_AUDIO_V1_0_STREAM_RESULT streamResult;

    /* Check the application's current state. */
    switch ( appData.state )
    {
        case APP_STATE_BUS_ENABLE:

            /* Register a callback for Audio Device Attach. */
            audioResult = USB_HOST_AUDIO_V1_0_AttachEventHandlerSet
                          (
                              &APP_USBHostAudioAttachEventListener,
                              (uintptr_t)0
                          );

            if (audioResult == USB_HOST_AUDIO_V1_0_RESULT_SUCCESS )
            {
                /* Set Host Event Handler */
                USB_HOST_EventHandlerSet(APP_USBHostEventHandler, 0);
                USB_HOST_BusEnable(0);
                /* Advance application state */
                appData.state = APP_STATE_WAIT_FOR_BUS_ENABLE_COMPLETE;
            }
            break;

        case APP_STATE_WAIT_FOR_BUS_ENABLE_COMPLETE:
            if(USB_HOST_BusIsEnabled(0))
            {
                appData.state = APP_STATE_WAIT_FOR_DEVICE_ATTACH;
            }
            break;

        case APP_STATE_WAIT_FOR_DEVICE_ATTACH:
            /* Check if an Audio Device has been attached  */
            if(appData.isAudioDeviceAttached == true)
            {
                appData.nAudioStreamGroups = 0;
                /* Find an Audio Stream matching to our requirement */
                appData.ouStreamObj = App_USBHostAudioSpeakerStreamFind
                                      (
                                          appData.audioDeviceObj,
                                          audioSpeakerStreamFormat,
                                          &appData.nAudioStreamGroups
                                      );
                if (appData.nAudioStreamGroups == 0)
                {
                    appData.state = APP_STATE_ERROR;
                    break;
                }

                /* Open Audio Stream */
                appData.outStreamHandle = USB_HOST_AUDIO_V1_0_StreamOpen
                                          (
                                              appData.ouStreamObj
                                          );

                if (appData.outStreamHandle == USB_HOST_AUDIO_V1_0_STREAM_HANDLE_INVALID)
                {
                    appData.state = APP_STATE_ERROR;
                    break;
                }

                /* Set Stream Event Handler  */
                streamResult = USB_HOST_AUDIO_V1_0_StreamEventHandlerSet
                               (
                                   appData.outStreamHandle,
                                   APP_USBHostAudioStreamEventHandler,
                                   (uintptr_t)appData.ouStreamObj
                               );

                if (streamResult != USB_HOST_AUDIO_V1_0_STREAM_SUCCESS)
                {
                    appData.state = APP_STATE_ERROR;
                    break;
                }
                appData.state = APP_STATE_ENABLE_AUDIO_STREAM;
            }
            break;

      case  APP_STATE_ENABLE_AUDIO_STREAM:
                isStreamEnableComplete = false;
                 /* Set default interface setting of the streaming interface */
                streamResult = USB_HOST_AUDIO_V1_0_StreamEnable
                               (
                                   appData.outStreamHandle,
                                   &appData.requestHandle
                               );
                if (streamResult != USB_HOST_AUDIO_V1_0_STREAM_SUCCESS)
                {
                    appData.state = APP_STATE_ERROR;
                    break;
                }
                appData.state = APP_STATE_WAIT_FOR_ENABLE_AUDIO_STREAM;
            break;
        case  APP_STATE_WAIT_FOR_ENABLE_AUDIO_STREAM:
            if (isStreamEnabled == true)
            {
                appData.state = APP_STATE_START_STREAM_DATA;
            }
            break;
       case APP_STATE_START_STREAM_DATA:
            isAudioWriteCompleted = false;
            appData.state = APP_SATE_WAIT_FOR_WRITE_COMPLETE;
            USB_HOST_AUDIO_V1_0_StreamWrite
            (
                appData.outStreamHandle,
                &transferHandleAudioWrite,
                (void*)&audioSamples,
                192
            );
            break;

        case APP_SATE_WAIT_FOR_WRITE_COMPLETE:
            if (appData.isAudioWriteCompleted)
            {
                isAudioWriteCompleted = false;
                USB_HOST_AUDIO_V1_0_StreamWrite
                (
                    appData.outStreamHandle,
                    &transferHandleAudioWrite,
                    (void*)&audioSamples,
                    192
                );
            }
            break;

        default:
            break;
    }
}