USB Libraries Help > USB Host Libraries > USB Audio v1.0 Host Client Driver Library > Using the Library > How the Library Works > Obtaining an Audio Stream
MPLAB Harmony USB Stack
Obtaining an Audio Stream

Once application has identified which audio stream to use, application must open that audio stream by using USB_HOST_AUDIO_V1_0_StreamOpen function. This function takes audio stream object USB_HOST_AUDIO_V1_0_STREAM_OBJ as an argument which obtained by USB_HOST_AUDIO_V1_0_StreamGetFirst and USB_HOST_AUDIO_V1_0_StreamGetNext functions and returns audio stream handle USB_HOST_AUDIO_V1_0_STREAM_HANDLE. If the open function fails, it returns an invalid handle (USB_HOST_AUDIO_V1_0_STREAM_HANDLE _INVALID). Once opened successfully, a valid handle tracks the relationship between the client and the Audio Stream. This handle should be used with other Audio Stream functions. 

An audio stream can be opened multiple times by different application clients. In an RTOS based application each client could running its own thread. Multiple clients can read write data to the one Audio stream. In such a case, the read and write requests are queued. The following code shows an example of how an Audio Stream is opened.

/* This code shows an example of opening an audio stream */

/* 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;
USB_HOST_AUDIO_V1_0_OBJ audioDeviceObj;

/*************************************************************/
/* 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;
                }
            }
            break;

        default:
            break;
    }
}