Implement application specific behavior of an Audio Device Class (ADC) USB Device.
More...
Implement application specific behavior of an Audio Device Class (ADC) USB Device.
Use the following class specific functions to customize the functionality of an Audio Device Class (ADC) Device. Adapt these functions in the file USBD_User_ADC_Audio_n.c.
The USB Component allows multiple instances of the ADC class. This feature is used to create USB Composite Devices. Each ADC class instance has a separate files and interface functions:
The following source code can be used to implement the application specific behavior of an USB ADC Device with Audio Interface.
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "rl_usb.h"
#include "USBD_Config_ADC_n.h"
#include "Board_Audio.h"
#define PLAYBACK_AVAILABLE (USBD_ADCn_EP_ISO_OUT_EN != 0U)
#define PLAYBACK_CHANNELS (USBD_ADCn_OUT_CH_NUM)
#define PLAYBACK_FREQ (USBD_ADCn_OUT_TSAM_FREQ)
#define PLAYBACK_RESOLUTION (USBD_ADCn_OUT_BBITRESOLUTION)
#if (USBD_ADCn_OUT_BSUBFRAMESIZE >= 3U)
#define PLAYBACK_SAMPLE_SIZE (4U)
#else
#define PLAYBACK_SAMPLE_SIZE (USBD_ADCn_OUT_BSUBFRAMESIZE)
#endif
#if (PLAYBACK_CHANNELS > 1U)
#define PLAYBACK_FORMAT (PLAYBACK_SAMPLE_SIZE | ((PLAYBACK_CHANNELS - 1U) << 7))
#else
#define PLAYBACK_FORMAT (PLAYBACK_SAMPLE_SIZE)
#endif
#define PLAYBACK_USB_BUFFER_SAMPLES (USBD_ADCn_OUT_BUF_SIZE)
#define PLAYBACK_AUDIO_BUFFER_SAMPLES (PLAYBACK_USB_BUFFER_SAMPLES / 8U)
#define PLAYBACK_AUDIO_BUFFER_SIZE ((PLAYBACK_AUDIO_BUFFER_SAMPLES + PLAYBACK_CHANNELS) * PLAYBACK_SAMPLE_SIZE)
#define RECORD_AVAILABLE (USBD_ADCn_EP_ISO_IN_EN != 0U)
#define RECORD_CHANNELS (USBD_ADCn_IN_CH_NUM)
#define RECORD_FREQ (USBD_ADCn_IN_TSAM_FREQ)
#if (USBD_ADCn_IN_BSUBFRAMESIZE >= 3U)
#define RECORD_SAMPLE_SIZE (4U)
#else
#define RECORD_SAMPLE_SIZE (USBD_ADCn_IN_BSUBFRAMESIZE)
#endif
#if (RECORD_CHANNELS > 1U)
#define RECORD_FORMAT (RECORD_SAMPLE_SIZE | ((RECORD_CHANNELS - 1U) << 7))
#else
#define RECORD_FORMAT (RECORD_SAMPLE_SIZE)
#endif
#define RECORD_USB_BUFFER_SAMPLES (USBD_ADCn_IN_BUF_SIZE)
#define RECORD_AUDIO_BUFFER_SAMPLES (RECORD_USB_BUFFER_SAMPLES / 8U)
#define RECORD_AUDIO_BUFFER_SIZE ((RECORD_AUDIO_BUFFER_SAMPLES + RECORD_CHANNELS) * RECORD_SAMPLE_SIZE)
#if (PLAYBACK_AVAILABLE)
#if ((PLAYBACK_CHANNELS == 0U) || (PLAYBACK_CHANNELS > 2U))
#error Playback channel configuration mono or stereo supported!
#endif
#endif
#if (RECORD_AVAILABLE)
#if ((RECORD_CHANNELS == 0U) || (RECORD_CHANNELS > 2U))
#error Recording channel configuration mono or stereo supported!
#endif
#endif
#if (PLAYBACK_AVAILABLE)
static uint8_t play_idx = 0U;
static uint32_t play_num = 0U;
static uint8_t play_buf [2][PLAYBACK_AUDIO_BUFFER_SIZE] __attribute__((aligned(4U)));
#endif
#if (RECORD_AVAILABLE)
static uint8_t rec_idx = 0U;
static uint32_t rec_num = 0U;
static uint8_t rec_buf [2][RECORD_AUDIO_BUFFER_SIZE] __attribute__((aligned(4U)));
#endif
#if ((PLAYBACK_AVAILABLE) && (PLAYBACK_RESOLUTION == 24U))
static void Repack_shl_8 (uint8_t *ptr, uint32_t num) {
uint32_t i;
for (i = 0; i < num; i ++) {
*(__packed uint32_t *)ptr = ((*(__packed uint32_t *)ptr) << 8U) & 0xFFFFFF00U;
ptr += 4U;
}
}
#endif
static void AudioCallback (uint32_t event) {
uint32_t samples_available;
#if (PLAYBACK_AVAILABLE)
int32_t num;
#endif
#if (RECORD_AVAILABLE)
if (event & AUDIO_EVENT_RECEIVE_COMPLETE) {
(void)Audio_ReceiveData ((void *)(&rec_buf[rec_idx ^ 1U][0U]), RECORD_AUDIO_BUFFER_SAMPLES);
}
#endif
#if (PLAYBACK_AVAILABLE)
if ((event & AUDIO_EVENT_SEND_COMPLETE) && (play_num != 0U)) {
(void)Audio_SendData ((void *)(&play_buf[play_idx][0U]), (uint32_t)(play_num));
play_idx ^= 1U;
}
#endif
#if (RECORD_AVAILABLE)
if (event & AUDIO_EVENT_RECEIVE_COMPLETE) {
rec_num = RECORD_AUDIO_BUFFER_SAMPLES;
if (samples_available <= (2U * RECORD_AUDIO_BUFFER_SAMPLES)) {
memcpy((void *)(&rec_buf[rec_idx][ RECORD_AUDIO_BUFFER_SAMPLES * RECORD_SAMPLE_SIZE]),
(void *)(&rec_buf[rec_idx][(RECORD_AUDIO_BUFFER_SAMPLES - RECORD_CHANNELS) * RECORD_SAMPLE_SIZE]),
RECORD_CHANNELS * RECORD_SAMPLE_SIZE);
rec_num += RECORD_CHANNELS;
} else if (samples_available >= (RECORD_USB_BUFFER_SAMPLES - (2U * RECORD_AUDIO_BUFFER_SAMPLES))) {
rec_num -= RECORD_CHANNELS;
}
rec_idx ^= 1U;
}
#endif
#if (PLAYBACK_AVAILABLE)
if ((event & AUDIO_EVENT_SEND_COMPLETE) && (play_num != 0U)) {
if (num > 0) {
play_num = (uint32_t)(num);
} else {
play_num = 0U;
}
#if (PLAYBACK_RESOLUTION == 24U)
Repack_shl_8 (&play_buf[play_idx][0U], play_num);
#endif
if (samples_available == 0U) {
(void)Audio_Stop (AUDIO_STREAM_OUT);
} else if (samples_available <= (2U * PLAYBACK_AUDIO_BUFFER_SAMPLES)) {
memcpy((void *)(&play_buf[play_idx][ play_num * PLAYBACK_SAMPLE_SIZE]),
(void *)(&play_buf[play_idx][(play_num - PLAYBACK_CHANNELS) * PLAYBACK_SAMPLE_SIZE]),
PLAYBACK_CHANNELS * PLAYBACK_SAMPLE_SIZE);
play_num += PLAYBACK_CHANNELS;
} else if (samples_available >= (PLAYBACK_USB_BUFFER_SAMPLES - (2U * PLAYBACK_AUDIO_BUFFER_SAMPLES))) {
play_num -= PLAYBACK_CHANNELS;
}
}
#endif
}
#if (PLAYBACK_AVAILABLE)
int32_t num;
if (num > 0) {
play_num = (uint32_t)(num);
} else {
play_num = 0U;
}
#if (PLAYBACK_RESOLUTION == 24U)
Repack_shl_8 (&play_buf[0U][0U], play_num);
#endif
(void)Audio_SendData ((void *)(&play_buf[0U][0U]), play_num);
(void)Audio_Start (AUDIO_STREAM_OUT);
play_idx = 1U;
if (num > 0) {
play_num = (uint32_t)(num);
} else {
play_num = 0U;
}
#if (PLAYBACK_RESOLUTION == 24U)
Repack_shl_8 (&play_buf[1U][0U], play_num);
#endif
}
#endif
(void)Audio_Initialize (AudioCallback);
#if (PLAYBACK_AVAILABLE)
(void)USBD_ADC_SpeakerSetVolumeRange (nU, 0U, 0U, 100U, 1U, 50U);
(void)Audio_SetDataFormat (AUDIO_STREAM_OUT, PLAYBACK_FORMAT);
(void)Audio_SetFrequency (AUDIO_STREAM_OUT, PLAYBACK_FREQ);
(void)Audio_SetMute (AUDIO_STREAM_OUT, AUDIO_CHANNEL_MASTER, (bool)false);
(void)Audio_SetVolume (AUDIO_STREAM_OUT, AUDIO_CHANNEL_MASTER, 50U);
#endif
#if (RECORD_AVAILABLE)
(void)USBD_ADC_MicrophoneSetVolumeRange (nU, 0U, 0U, 100U, 1U, 50U);
(void)Audio_SetDataFormat (AUDIO_STREAM_IN, RECORD_FORMAT);
(void)Audio_SetFrequency (AUDIO_STREAM_IN, RECORD_FREQ);
(void)Audio_SetMute (AUDIO_STREAM_IN, AUDIO_CHANNEL_MASTER, (bool)false);
(void)Audio_SetVolume (AUDIO_STREAM_IN, AUDIO_CHANNEL_MASTER, 50U);
#endif
}
(void)Audio_Uninitialize ();
}
#if (PLAYBACK_AVAILABLE)
(void)Audio_Stop (AUDIO_STREAM_OUT);
}
(void)Audio_SetMute (AUDIO_STREAM_OUT, ch, on);
}
(void)Audio_SetVolume (AUDIO_STREAM_OUT, ch, (uint8_t)(vol));
}
#endif
#if (RECORD_AVAILABLE)
rec_idx = 0U;
rec_num = RECORD_AUDIO_BUFFER_SAMPLES;
(void)Audio_ReceiveData (&rec_buf[0U][0U], RECORD_AUDIO_BUFFER_SAMPLES);
(void)Audio_Start (AUDIO_STREAM_IN);
}
(void)Audio_Stop (AUDIO_STREAM_IN);
}
(void)Audio_SetMute (AUDIO_STREAM_IN, ch, on);
}
(void)Audio_SetVolume (AUDIO_STREAM_IN, ch, (uint8_t)(vol));
}
#endif