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;
}
}
