/*
 * Copyright 2018-2025 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */


#include "usb_device_config.h"
#include "usb.h"
#include "usb_device.h"

#include "usb_device_class.h"
#include "usb_device_audio.h"

#include "usb_device_ch9.h"
#include "usb_device_descriptor.h"

#include "Main.h"

#include "fsl_device_registers.h"
#include "fsl_mu.h"
#include "fsl_sema42.h"
#include "clock_config.h"
#include "board.h"
#include <stdio.h>
#include <stdlib.h>

#include "GlobalDef.h"
#include "SubFunc.h"
#include "CircularBufManagement.h"
#include "CircularBuf.h"
#include "AudioIoInit.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

#define USB_AUDIO_ENTER_CRITICAL() \
                                   \
    OSA_SR_ALLOC();            \
                                   \
    OSA_ENTER_CRITICAL()

#define USB_AUDIO_EXIT_CRITICAL() OSA_EXIT_CRITICAL()
/*******************************************************************************
 * Prototypes
 ******************************************************************************/

#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
extern void SCTIMER_CaptureInit(void);
#endif
/*******************************************************************************
 * Variables
 ******************************************************************************/
//USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
//uint8_t audioPlayDataBuff[AUDIO_SPEAKER_DATA_WHOLE_BUFFER_LENGTH * FS_ISO_OUT_ENDP_PACKET_SIZE];

#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
uint8_t UacRxPacketBuf[FS_ISO_OUT_ENDP_PACKET_SIZE];
#else
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
uint8_t UacRxPacketBuf[(FS_ISO_OUT_ENDP_PACKET_SIZE + AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE)];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
uint8_t audioFeedBackBuffer[4];
#endif


extern unsigned int CycCnt1,CycCnt2;

int UsbDnS32BufL[AUDIO_OUT_SAMPLING_RATE_KHZ];
int UsbDnS32BufR[AUDIO_OUT_SAMPLING_RATE_KHZ];

usb_device_composite_struct_t *g_deviceAudioComposite;
extern usb_device_composite_struct_t g_composite;
//extern uint8_t s_wavBuff[];
/*******************************************************************************
 * Code
 ******************************************************************************/



/*!
 * @brief Audio class specific request function.
 *
 * This function handles the Audio class specific requests.
 *
 * @param handle           The USB device handle.
 * @param event            The USB device event type.
 * @param param            The parameter of the device specific request.
 *
 * @return A USB error code or kStatus_USB_Success.
 */
usb_status_t USB_DeviceAudioRequest(class_handle_t handle, uint32_t event, void *param)
{
    usb_device_control_request_struct_t *request = (usb_device_control_request_struct_t *)param;
    usb_status_t error                           = kStatus_USB_Success;
    uint16_t volume;
#if USB_DEVICE_CONFIG_AUDIO_CLASS_2_0
    uint8_t entityId;
#endif

    switch (event)
    {
        case USB_DEVICE_AUDIO_GET_CUR_MUTE_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.curMute;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curMute);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_VOLUME_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.curVolume;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curVolume);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_BASS_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.curBass;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curBass);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_MID_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.curMid;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curMid);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_TREBLE_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.curTreble;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curTreble);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_AUTOMATIC_GAIN_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.curAutomaticGain;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curAutomaticGain);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_DELAY_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.curDelay;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curDelay);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_SAMPLING_FREQ_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.curSamplingFrequency;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curSamplingFrequency);
            break;
        case USB_DEVICE_AUDIO_GET_MIN_VOLUME_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.minVolume;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.minVolume);
            break;
        case USB_DEVICE_AUDIO_GET_MIN_BASS_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.minBass;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.minBass);
            break;
        case USB_DEVICE_AUDIO_GET_MIN_MID_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.minMid;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.minMid);
            break;
        case USB_DEVICE_AUDIO_GET_MIN_TREBLE_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.minTreble;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.minTreble);
            break;
        case USB_DEVICE_AUDIO_GET_MIN_DELAY_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.minDelay;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.minDelay);
            break;
        case USB_DEVICE_AUDIO_GET_MIN_SAMPLING_FREQ_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.minSamplingFrequency;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.minSamplingFrequency);
            break;
        case USB_DEVICE_AUDIO_GET_MAX_VOLUME_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.maxVolume;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.maxVolume);
            break;
        case USB_DEVICE_AUDIO_GET_MAX_BASS_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.maxBass;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.maxBass);
            break;
        case USB_DEVICE_AUDIO_GET_MAX_MID_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.maxMid;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.maxMid);
            break;
        case USB_DEVICE_AUDIO_GET_MAX_TREBLE_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.maxTreble;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.maxTreble);
            break;
        case USB_DEVICE_AUDIO_GET_MAX_DELAY_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.maxDelay;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.maxDelay);
            break;
        case USB_DEVICE_AUDIO_GET_MAX_SAMPLING_FREQ_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.maxSamplingFrequency;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.maxSamplingFrequency);
            break;
        case USB_DEVICE_AUDIO_GET_RES_VOLUME_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.resVolume;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.resVolume);
            break;
        case USB_DEVICE_AUDIO_GET_RES_BASS_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.resBass;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.resBass);
            break;
        case USB_DEVICE_AUDIO_GET_RES_MID_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.resMid;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.resMid);
            break;
        case USB_DEVICE_AUDIO_GET_RES_TREBLE_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.resTreble;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.resTreble);
            break;
        case USB_DEVICE_AUDIO_GET_RES_DELAY_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.resDelay;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.resDelay);
            break;
        case USB_DEVICE_AUDIO_GET_RES_SAMPLING_FREQ_CONTROL:
            request->buffer = g_deviceAudioComposite->audioUnified.resSamplingFrequency;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.resSamplingFrequency);
            break;
#if USB_DEVICE_CONFIG_AUDIO_CLASS_2_0
        case USB_DEVICE_AUDIO_GET_CUR_SAM_FREQ_CONTROL:
            entityId = (uint8_t)(request->setup->wIndex >> 0x08);
            if (entityId == USB_AUDIO_RECORDER_CONTROL_CLOCK_SOURCE_ID)
            {
                request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.curRecorderSampleFrequency;
                ;
                request->length = sizeof(g_deviceAudioComposite->audioUnified.curRecorderSampleFrequency);
            }
            else if (entityId == USB_AUDIO_SPEAKER_CONTROL_CLOCK_SOURCE_ID)
            {
                request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.curSpeakerSampleFrequency;
                ;
                request->length = sizeof(g_deviceAudioComposite->audioUnified.curSpeakerSampleFrequency);
            }
            else
            {
                /* no action */
            }
            break;
        case USB_DEVICE_AUDIO_GET_RANGE_SAM_FREQ_CONTROL:
            entityId = (uint8_t)(request->setup->wIndex >> 0x08);
            if (entityId == USB_AUDIO_RECORDER_CONTROL_CLOCK_SOURCE_ID)
            {
                request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.freqRecorderControlRange;
                request->length = sizeof(g_deviceAudioComposite->audioUnified.freqRecorderControlRange);
            }
            else if (entityId == USB_AUDIO_SPEAKER_CONTROL_CLOCK_SOURCE_ID)
            {
                request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.freqSpeakerControlRange;
                request->length = sizeof(g_deviceAudioComposite->audioUnified.freqSpeakerControlRange);
            }
            else
            {
            }
            break;
        case USB_DEVICE_AUDIO_GET_CUR_CLOCK_VALID_CONTROL:
            request->buffer = &g_deviceAudioComposite->audioUnified.curClockValid;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curClockValid);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_MUTE_CONTROL_AUDIO20:
            request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.curMute20;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curMute20);
            break;
        case USB_DEVICE_AUDIO_GET_CUR_VOLUME_CONTROL_AUDIO20:
            request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.curVolume20;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.curVolume20);
            break;
        case USB_DEVICE_AUDIO_GET_RANGE_VOLUME_CONTROL_AUDIO20:
            request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.volumeControlRange;
            request->length = sizeof(g_deviceAudioComposite->audioUnified.volumeControlRange);
            break;
#endif
        case USB_DEVICE_AUDIO_SET_CUR_VOLUME_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.curVolume;
            }
            else
            {
                volume = (uint16_t)((uint16_t)g_deviceAudioComposite->audioUnified.curVolume[1] << 8U);
                volume |= (uint8_t)(g_deviceAudioComposite->audioUnified.curVolume[0]);
                g_deviceAudioComposite->audioUnified.codecTask |= VOLUME_CHANGE_TASK;
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_MUTE_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.curMute;
            }
            else
            {
                if (g_deviceAudioComposite->audioUnified.curMute)
                {
                    g_deviceAudioComposite->audioUnified.codecTask |= MUTE_CODEC_TASK;
                }
                else
                {
                    g_deviceAudioComposite->audioUnified.codecTask |= UNMUTE_CODEC_TASK;
                }
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_BASS_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.curBass;
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_MID_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.curMid;
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_TREBLE_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.curTreble;
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_AUTOMATIC_GAIN_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.curAutomaticGain;
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_DELAY_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.curDelay;
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_SAMPLING_FREQ_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.curSamplingFrequency;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MIN_VOLUME_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.minVolume;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MIN_BASS_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.minBass;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MIN_MID_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.minMid;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MIN_TREBLE_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.minTreble;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MIN_DELAY_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.minDelay;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MIN_SAMPLING_FREQ_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.minSamplingFrequency;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MAX_VOLUME_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.maxVolume;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MAX_BASS_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.maxBass;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MAX_MID_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.maxMid;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MAX_TREBLE_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.maxTreble;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MAX_DELAY_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.maxDelay;
            }
            break;
        case USB_DEVICE_AUDIO_SET_MAX_SAMPLING_FREQ_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.maxSamplingFrequency;
            }
            break;
        case USB_DEVICE_AUDIO_SET_RES_VOLUME_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.resVolume;
            }
            break;
        case USB_DEVICE_AUDIO_SET_RES_BASS_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.resBass;
            }
            break;
        case USB_DEVICE_AUDIO_SET_RES_MID_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.resMid;
            }
            break;
        case USB_DEVICE_AUDIO_SET_RES_TREBLE_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.resTreble;
            }
            break;
        case USB_DEVICE_AUDIO_SET_RES_DELAY_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.resDelay;
            }
            break;
        case USB_DEVICE_AUDIO_SET_RES_SAMPLING_FREQ_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.resSamplingFrequency;
            }
            break;
#if USB_DEVICE_CONFIG_AUDIO_CLASS_2_0
        case USB_DEVICE_AUDIO_SET_CUR_SAM_FREQ_CONTROL:
            if (request->isSetup == 1U)
            {
                entityId = (uint8_t)(request->setup->wIndex >> 0x08);
                if (entityId == USB_AUDIO_RECORDER_CONTROL_CLOCK_SOURCE_ID)
                {
                    request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.curRecorderSampleFrequency;
                }
                else if (entityId == USB_AUDIO_SPEAKER_CONTROL_CLOCK_SOURCE_ID)
                {
                    request->buffer = (uint8_t *)&g_deviceAudioComposite->audioUnified.curSpeakerSampleFrequency;
                }
                else
                {
                    /* no action */
                }
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_CLOCK_VALID_CONTROL:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.curClockValid;
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_MUTE_CONTROL_AUDIO20:
            if (request->isSetup == 1U)
            {
                request->buffer = &g_deviceAudioComposite->audioUnified.curMute20;
            }
            else
            {
                if (g_deviceAudioComposite->audioUnified.curMute20)
                {
                    g_deviceAudioComposite->audioUnified.codecTask |= MUTE_CODEC_TASK;
                }
                else
                {
                    g_deviceAudioComposite->audioUnified.codecTask |= UNMUTE_CODEC_TASK;
                }
            }
            break;
        case USB_DEVICE_AUDIO_SET_CUR_VOLUME_CONTROL_AUDIO20:
            if (request->isSetup == 1U)
            {
                request->buffer = g_deviceAudioComposite->audioUnified.curVolume20;
            }
            else
            {
                g_deviceAudioComposite->audioUnified.codecTask |= VOLUME_CHANGE_TASK;
            }
            break;
#endif
        default:
            error = kStatus_USB_InvalidRequest;
            break;
    }
    return error;
}


#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
#else
/* The USB_AudioFeedbackDataUpdate() function calculates the feedback data */
void USB_AudioFeedbackDataUpdate()
{
    static int32_t audioSpeakerUsedDiff = 0x0, audioSpeakerDiffThres = 0x0;
    static uint32_t feedbackValue = 0x0, originFeedbackValue = 0x0, audioSpeakerUsedSpace = 0x0,
                    audioSpeakerLastUsedSpace = 0x0;

    if (g_deviceAudioComposite->audioUnified.speakerIntervalCount != AUDIO_CALCULATE_Ff_INTERVAL)
    {
        g_deviceAudioComposite->audioUnified.speakerIntervalCount++;
        return;
    }
    g_deviceAudioComposite->audioUnified.speakerIntervalCount = 1;

    g_deviceAudioComposite->audioUnified.timesFeedbackCalculate++;
    if (g_deviceAudioComposite->audioUnified.timesFeedbackCalculate == 2)
    {
        originFeedbackValue = ((g_deviceAudioComposite->audioUnified.audioSendCount -
                                g_deviceAudioComposite->audioUnified.lastAudioSendCount)) /
                              (AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE);
        originFeedbackValue *= (1024U / AUDIO_CALCULATE_Ff_INTERVAL);
        feedbackValue = originFeedbackValue;
        AUDIO_UPDATE_FEEDBACK_DATA(audioFeedBackBuffer, originFeedbackValue);
        audioSpeakerUsedSpace     = USB_AudioSpeakerBufferSpaceUsed();
        audioSpeakerLastUsedSpace = audioSpeakerUsedSpace;
    }
    else if (g_deviceAudioComposite->audioUnified.timesFeedbackCalculate > 2)
    {
        audioSpeakerUsedSpace = USB_AudioSpeakerBufferSpaceUsed();
        audioSpeakerUsedDiff += (audioSpeakerUsedSpace - audioSpeakerLastUsedSpace);
        audioSpeakerLastUsedSpace = audioSpeakerUsedSpace;

        if ((audioSpeakerUsedDiff > -AUDIO_OUT_SAMPLING_RATE_KHZ) &&  (audioSpeakerUsedDiff < AUDIO_OUT_SAMPLING_RATE_KHZ))
        {
            audioSpeakerDiffThres = 4 * AUDIO_OUT_SAMPLING_RATE_KHZ;
        }
        if (audioSpeakerUsedDiff <= -audioSpeakerDiffThres)
        {
            audioSpeakerDiffThres += 4 * AUDIO_OUT_SAMPLING_RATE_KHZ;
#if defined(USB_DEVICE_CONFIG_AUDIO_CLASS_2_0) && (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0 > 0U)
            feedbackValue += (AUDIO_ADJUST_MIN_STEP);
#else
            feedbackValue += (AUDIO_OUT_SAMPLING_RATE_KHZ / AUDIO_SAMPLING_RATE_16KHZ) * (AUDIO_ADJUST_MIN_STEP);
#endif
        }
        if (audioSpeakerUsedDiff >= audioSpeakerDiffThres)
        {
            audioSpeakerDiffThres += 4 * AUDIO_OUT_SAMPLING_RATE_KHZ;
#if defined(USB_DEVICE_CONFIG_AUDIO_CLASS_2_0) && (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0 > 0U)
            feedbackValue -= (AUDIO_ADJUST_MIN_STEP);
#else
            feedbackValue -= (AUDIO_OUT_SAMPLING_RATE_KHZ / AUDIO_SAMPLING_RATE_16KHZ) * (AUDIO_ADJUST_MIN_STEP);
#endif
        }
        AUDIO_UPDATE_FEEDBACK_DATA(audioFeedBackBuffer, feedbackValue);
    }
    else
    {
    }
    g_deviceAudioComposite->audioUnified.lastAudioSendCount = g_deviceAudioComposite->audioUnified.audioSendCount;
}
#endif


uint32_t USB_UsbAudioUpStreamDataRateControl_AdjustPacketLength(T_CircularAudioBuf_S32 *CirBufPtr)
{
    unsigned short int AvailableSamplesInCirBuf;
    unsigned int PacketSize;
	uint16_t HiLimitInSample, LoLimitInSample;

	if(CirBufPtr->LengthInSamples < AUDIO_IN_SAMPLING_RATE_KHZ * 16 )
	{	//buffer length is shorter than 16ms  --- assume 12ms
		HiLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 8;
		LoLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 4;
	}
	else if(CirBufPtr->LengthInSamples < AUDIO_IN_SAMPLING_RATE_KHZ * 32 )
	{	//buffer length is 16ms ~ 32ms        --- assume 16ms
		HiLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 12;
		LoLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 4;
	}
	else if(CirBufPtr->LengthInSamples < AUDIO_IN_SAMPLING_RATE_KHZ * 64 )
	{	//buffer length is 32ms ~ 64ms        --- assume 32ms
		HiLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 28;
		LoLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 4;
	}
	else if(CirBufPtr->LengthInSamples < AUDIO_IN_SAMPLING_RATE_KHZ * 128 )
	{	//buffer length is 64ms ~ 128ms       --- assume 64ms
		HiLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 50;
		LoLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 4;
	}
	else
	{	//buffer length is longer than 128ms  --- assume 128ms
		HiLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 100;
		LoLimitInSample=AUDIO_IN_SAMPLING_RATE_KHZ * 4;
	}

	AvailableSamplesInCirBuf=CirAudioBuf_SpaceOccupiedInSamples_S32(CirBufPtr);

    //check samples in the buffer --- and do adjust packet size, one more or one less ---- should be used when USB upstream is in async mode
    if (AvailableSamplesInCirBuf > HiLimitInSample)
    {	//buffered USB upstreaming audio data is going to be too much
        PacketSize = AUDIO_IN_SAMPLING_RATE_KHZ + 1 ;	//increase one audio sample
    	//usb_echo("+\r\n");
    }
    else if (AvailableSamplesInCirBuf > LoLimitInSample)
    {	//buffered USB upstreaming audio data is not too many nor too little
        PacketSize = AUDIO_IN_SAMPLING_RATE_KHZ;	    //no increase no decrease
    	//usb_echo("x\r\n");
    }
    else if (AvailableSamplesInCirBuf > AUDIO_IN_SAMPLING_RATE_KHZ)
    {	//buffered USB upstreaming audio data is going to be not enough
        PacketSize = AUDIO_IN_SAMPLING_RATE_KHZ - 1 ;	//decrease one audio sample
    	//usb_echo("-\r\n");
    }else
    {
        PacketSize = 0 ;	    //this means there is almost no audio data to upstream
    	//usb_echo("0\r\n");
    }

    return PacketSize;
}

/*!
 * @brief device Audio callback function.
 *
 * This function handle the Audio class specified event.
 * @param handle          The USB class  handle.
 * @param event           The USB device event type.
 * @param param           The parameter of the class specific event.
 * @return kStatus_USB_Success or error.
 */
unsigned short int UsbAudioUpStreamDataRateAdjustCnt=0;
int UacTxPacketBuf[(AUDIO_IN_SAMPLING_RATE_KHZ+1)  * AUDIO_IN_FORMAT_CHANNELS];

usb_status_t USB_DeviceAudioCompositeCallback(class_handle_t handle, uint32_t event, void *param)
{
    usb_status_t error = kStatus_USB_Error;
    usb_device_endpoint_callback_message_struct_t *ep_cb_param;
    ep_cb_param = (usb_device_endpoint_callback_message_struct_t *)param;

    switch (event)
    {
        case kUSB_DeviceAudioEventStreamSendResponse:
            if ((g_deviceAudioComposite->audioUnified.attach) && (ep_cb_param->length != (USB_UNINITIALIZED_VAL_32)))
            {
#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
                if (0)
                {
                }
#else
                if (ep_cb_param->length == ((USB_SPEED_HIGH == g_composite.speed) ? HS_ISO_FEEDBACK_ENDP_PACKET_SIZE :
                                                                                    FS_ISO_FEEDBACK_ENDP_PACKET_SIZE))
                {
                    error =
                        USB_DeviceAudioSend(g_deviceAudioComposite->audioUnified.audioSpeakerHandle,
                                            USB_AUDIO_SPEAKER_FEEDBACK_ENDPOINT, audioFeedBackBuffer,
                                            (USB_SPEED_HIGH == g_composite.speed) ? HS_ISO_FEEDBACK_ENDP_PACKET_SIZE :
                                                                                    FS_ISO_FEEDBACK_ENDP_PACKET_SIZE);
                }
#endif
                else
                {
					GET_CYCLE_COUNTER(CycCnt1);
                	//take out samples from VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreaming, and put to Usb audio tx packet to send to USB host
					if(!(UsbAudioUpStreamDataRateAdjustCnt%4))
					{
						//adjust USB audio upstream data rate once every 16 packets --- adjust packet size, one sample more ore one sample less
						unsigned short int l;
						l=USB_UsbAudioUpStreamDataRateControl_AdjustPacketLength(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingL1);	//USB upstreaming L and R are always the same level statues, no need to check R
						if(l)
						{
							//upstream LR mixed
							int *TmpS32PtrL=CirAudioBuf_ReadSamples_GetRdPtr_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingL1,l);
							int *TmpS32PtrR=CirAudioBuf_ReadSamples_GetRdPtr_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingR1,l);
							int *TmpS32PtrL1=CirAudioBuf_ReadSamples_GetRdPtr_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingL2,l);
							int *TmpS32PtrR1=CirAudioBuf_ReadSamples_GetRdPtr_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingR2,l);

							int i;
							for(i=0;i<l;i++)
							{
								//normal upstreaming
								UacTxPacketBuf[4*i+0]=*TmpS32PtrL++;
								UacTxPacketBuf[4*i+1]=*TmpS32PtrR++;
								UacTxPacketBuf[4*i+2]=*TmpS32PtrL1++;
								UacTxPacketBuf[4*i+3]=*TmpS32PtrR1++;
							}
							USB_DeviceAudioSend(g_deviceAudioComposite->audioUnified.audioRecorderHandle,
												USB_AUDIO_RECORDER_STREAM_ENDPOINT,
												//s_wavBuff,
												(unsigned char *)UacTxPacketBuf,
												l*AUDIO_IN_FORMAT_CHANNELS*AUDIO_IN_FORMAT_SIZE);
						}else
						{
							//not enough data available, upstream buffer is empty or almost empty --- should never happen
							//usb_echo("e\r\n");
							error =
								USB_DeviceAudioSend(g_deviceAudioComposite->audioUnified.audioRecorderHandle,
													USB_AUDIO_RECORDER_STREAM_ENDPOINT,
													//s_wavBuff,
													(unsigned char *)AllZeroBuf_48PointsSingleCh,
													FS_ISO_IN_ENDP_PACKET_SIZE);
						}
					}else
					{
						if(CirAudioBuf_SpaceOccupiedInSamples_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingL1)>=AUDIO_IN_SAMPLING_RATE_KHZ)	//USB upstreaming L and R are always the same level statues, no need to check R
						{
							//upstream LR mixed
							//normal upstreaming
							int *TmpS32PtrL=CirAudioBuf_ReadSamples_GetRdPtr_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingL1,AUDIO_IN_SAMPLING_RATE_KHZ);
							int *TmpS32PtrR=CirAudioBuf_ReadSamples_GetRdPtr_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingR1,AUDIO_IN_SAMPLING_RATE_KHZ);
							int *TmpS32PtrL1=CirAudioBuf_ReadSamples_GetRdPtr_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingL2,AUDIO_IN_SAMPLING_RATE_KHZ);
							int *TmpS32PtrR1=CirAudioBuf_ReadSamples_GetRdPtr_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingR2,AUDIO_IN_SAMPLING_RATE_KHZ);

							int i;
							for(i=0;i<AUDIO_IN_SAMPLING_RATE_KHZ;i++)
							{
								UacTxPacketBuf[4*i+0]=*TmpS32PtrL++;
								UacTxPacketBuf[4*i+1]=*TmpS32PtrR++;
								UacTxPacketBuf[4*i+2]=*TmpS32PtrL1++;
								UacTxPacketBuf[4*i+3]=*TmpS32PtrR1++;
							}
							USB_DeviceAudioSend(g_deviceAudioComposite->audioUnified.audioRecorderHandle,
												USB_AUDIO_RECORDER_STREAM_ENDPOINT,
												//s_wavBuff,
												(unsigned char *)UacTxPacketBuf,
												FS_ISO_IN_ENDP_PACKET_SIZE);
						}else
						{
							//it is confirmed that buffer empty really happens --- if don't do upstream data rate adjust
							//now it is confirmed that buffer empty never happens again!
							//usb_echo("e\r\n");
							error =
								USB_DeviceAudioSend(g_deviceAudioComposite->audioUnified.audioRecorderHandle,
													USB_AUDIO_RECORDER_STREAM_ENDPOINT,
													//s_wavBuff,
													(unsigned char *)AllZeroBuf_48PointsSingleCh,
													FS_ISO_IN_ENDP_PACKET_SIZE);
						}
					}

					GET_CYCLE_COUNTER(CycCnt2);
					//VarBlockSharedByDspAndMcu.CycCnt[14]=CycCnt2-CycCnt1;

                	UsbAudioUpStreamDataRateAdjustCnt++;
                }
            }
            break;
        case kUSB_DeviceAudioEventStreamRecvResponse:
            if ((g_deviceAudioComposite->audioUnified.attach) && (ep_cb_param->length != (USB_UNINITIALIZED_VAL_32)))
            {
                if (g_deviceAudioComposite->audioUnified.startPlay == 0)
                {
                    g_deviceAudioComposite->audioUnified.startPlay = 1;
                }
				if(AudioSourceIdx==AudioSrc1_UsbAudioDnSyncByAsrc)
				{
				    if(g_deviceAudioComposite->audioUnified.startPlayHalfFull == 0)
				    {
					    SEMA42_Lock(APP_SEMA42, SEMA42_GATE, domainId);
						//USB audio sync by Cadence ASRC
						if (CirAudioBuf_SpaceOccupiedInSamples_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioDnStreamingL) >= AsrcBufLengthInSamples/2)
						{
							g_deviceAudioComposite->audioUnified.startPlayHalfFull = 1;
						}
					    SEMA42_Unlock(APP_SEMA42, SEMA42_GATE);
				    }
				}else if(AudioSourceIdx==AudioSrc0_UsbAudioDnSyncByCTimer)
				{
				    if(g_deviceAudioComposite->audioUnified.startPlayHalfFull == 0)
				    {
					    SEMA42_Lock(APP_SEMA42, SEMA42_GATE, domainId);
						//USB audio sync by CTimer
						if (CirAudioBuf_SpaceOccupiedInSamples_S32(&UsbDnSpkBuf_ForUacSyncModeL) >= AUDIO_SPEAKER_UsbDnBufCenterLevelInSamples)
						{
							g_deviceAudioComposite->audioUnified.startPlayHalfFull = 1;
						}
					    SEMA42_Unlock(APP_SEMA42, SEMA42_GATE);
					}
				}

                //g_deviceAudioComposite->audioUnified.usbRecvCount += ep_cb_param->length;
                g_deviceAudioComposite->audioUnified.usbRecvTimes++;
#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
                error = USB_DeviceAudioRecv(handle, USB_AUDIO_SPEAKER_STREAM_ENDPOINT, &UacRxPacketBuf[0], (FS_ISO_OUT_ENDP_PACKET_SIZE));
#else
                USB_AUDIO_ENTER_CRITICAL();
                USB_AudioFeedbackDataUpdate();
                USB_AUDIO_EXIT_CRITICAL();
                error = USB_DeviceAudioRecv(handle, USB_AUDIO_SPEAKER_STREAM_ENDPOINT, &UacRxPacketBuf[0], (FS_ISO_OUT_ENDP_PACKET_SIZE + AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE));
#endif

            	int *TmpPtrS32_1=(int32_t*)UacRxPacketBuf;
            	for(int i=0;i<ep_cb_param->length/(AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE);i++)
            	{
            		UsbDnS32BufL[i]=*TmpPtrS32_1++;
            		UsbDnS32BufR[i]=*TmpPtrS32_1++;
            	}


            	if(AudioSourceIdx==AudioSrc1_UsbAudioDnSyncByAsrc)
            	{
					//USB audio sync by Cadence ASRC
            		if(DelayCntAsrcFeedIn_UsbAudioDn)
            		{
            			DelayCntAsrcFeedIn_UsbAudioDn--;
            		}else
            		{
                		memcpy(VarBlockSharedByDspAndMcu.AsrcInBuf,UacRxPacketBuf,ep_cb_param->length);	//should be always: 6 samples *2ch
                		MU_SendMsgNonBlocking(APP_MU, CHN_MU_REG_NUM, ep_cb_param->length/(AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE));		//send number of samples to DSP, to trigger DSP MU interrupt
            		}
            	}else if(AudioSourceIdx==AudioSrc0_UsbAudioDnSyncByCTimer)
            	{
					//USB audio sync by CTimer
					if(CirAudioBuf_SpaceAvailableInSamples_S32(&UsbDnSpkBuf_ForUacSyncModeL) >= ep_cb_param->length/(AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE))
					{
						if(g_deviceAudioComposite->audioUnified.startPlayHalfFull == 1)
						{
							//half full play started --- copy real downstream audio in the data packet to the downstreaming (feedback calculation) buffer
							CirAudioBuf_WriteSamples_S32(&UsbDnSpkBuf_ForUacSyncModeL, ep_cb_param->length/(AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE), UsbDnS32BufL);
						}else
						{
							//half full play not started --- put 0 to buffer, this is to prevent dirty sampels from the host, seems there are dirty samples from the end of last time host playing
							CirAudioBuf_WriteSamples_S32(&UsbDnSpkBuf_ForUacSyncModeL, ep_cb_param->length/(AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE),
									(int32_t*)AllZeroBuf_48PointsSingleCh
									);	//this is to prevent play/pause click
						}
					}
					if(CirAudioBuf_SpaceAvailableInSamples_S32(&UsbDnSpkBuf_ForUacSyncModeR) >= ep_cb_param->length/(AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE))
					{
						if(g_deviceAudioComposite->audioUnified.startPlayHalfFull == 1)
						{
							//half full play started --- copy real downstream audio in the data packet to the downstreaming (feedback calculation) buffer
							CirAudioBuf_WriteSamples_S32(&UsbDnSpkBuf_ForUacSyncModeR, ep_cb_param->length/(AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE), UsbDnS32BufR);
						}else
						{
							//half full play not started --- put 0 to buffer, this is to prevent dirty sampels from the host, seems there are dirty samples from the end of last time host playing
							CirAudioBuf_WriteSamples_S32(&UsbDnSpkBuf_ForUacSyncModeR, ep_cb_param->length/(AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE),
									(int32_t*)AllZeroBuf_48PointsSingleCh
									);	//this is to prevent play/pause click
						}
					}
            	}
            }
            break;

        default:
            if (param && (event > 0xFF))
            {
                error = USB_DeviceAudioRequest(handle, event, param);
            }
            break;
    }

    return error;
}

/* The USB_DeviceAudioSpeakerStatusReset() function resets the audio speaker status to the initialized status */
void USB_DeviceAudioSpeakerStatusReset(void)
{
    g_deviceAudioComposite->audioUnified.startPlay              = 0;
    g_deviceAudioComposite->audioUnified.startPlayHalfFull      = 0;
    g_deviceAudioComposite->audioUnified.tdReadNumberPlay       = 0;
    g_deviceAudioComposite->audioUnified.tdWriteNumberPlay      = 0;
    //g_deviceAudioComposite->audioUnified.audioSendCount         = 0;
    //g_deviceAudioComposite->audioUnified.usbRecvCount           = 0;
    //g_deviceAudioComposite->audioUnified.lastAudioSendCount     = 0;
    //g_deviceAudioComposite->audioUnified.audioSendTimes         = 0;
    g_deviceAudioComposite->audioUnified.usbRecvTimes           = 0;
    g_deviceAudioComposite->audioUnified.speakerIntervalCount   = 0;
    g_deviceAudioComposite->audioUnified.speakerReservedSpace   = 0;
    g_deviceAudioComposite->audioUnified.timesFeedbackCalculate = 0;
    g_deviceAudioComposite->audioUnified.speakerDetachOrNoInput = 0;
#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
    g_deviceAudioComposite->audioUnified.audioPllTicksPrev   = 0;
    g_deviceAudioComposite->audioUnified.audioPllTicksDiff   = 0;
    g_deviceAudioComposite->audioUnified.audioPllTicksEma    = AUDIO_PLL_USB1_SOF_INTERVAL_COUNT;
    g_deviceAudioComposite->audioUnified.audioPllTickEmaFrac = 0;
    g_deviceAudioComposite->audioUnified.audioPllStep        = AUDIO_PLL_FRACTIONAL_CHANGE_STEP;
#endif
}

/*!
 * @brief Audio set configuration function.
 *
 * @param handle The Audio class handle.
 * @param configure The Audio class configure index.
 *
 * @return A USB error code or kStatus_USB_Success.
 */
usb_status_t USB_DeviceAudioCompositeSetConfigure(class_handle_t handle, uint8_t configure)
{
    if (USB_COMPOSITE_CONFIGURE_INDEX == configure)
    {
        g_deviceAudioComposite->audioUnified.attach = 1U;
    }
    return kStatus_USB_Success;
}

usb_status_t USB_DeviceAudioRecorderSetInterface(class_handle_t handle, uint8_t interface, uint8_t alternateSetting)
{
    usb_status_t error = kStatus_USB_Success;

	CirAudioBuf_ClearAllSamples_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingL1);
	CirAudioBuf_ClearAllSamples_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingR1);
	CirAudioBuf_ClearAllSamples_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingL2);
	CirAudioBuf_ClearAllSamples_S32(&VarBlockSharedByDspAndMcu.CirBufUsbAudioUpStreamingR2);

    if (alternateSetting == 1U)
    {
    	VarBlockSharedByDspAndMcu.UsbUpStreamingIsStarted=1;
        error = USB_DeviceAudioSend(g_deviceAudioComposite->audioUnified.audioRecorderHandle,
                                    USB_AUDIO_RECORDER_STREAM_ENDPOINT,
									//s_wavBuff,
									(unsigned char *)AllZeroBuf_48PointsSingleCh,
									//FS_ISO_IN_ENDP_PACKET_SIZE
									0
									);
    }else
    {
    	VarBlockSharedByDspAndMcu.UsbUpStreamingIsStarted=0;
    }
    return error;
}

usb_status_t USB_DeviceAudioSpeakerSetInterface(class_handle_t handle, uint8_t interface, uint8_t alternateSetting)
{
    usb_status_t error = kStatus_USB_Success;

    if (alternateSetting == 1U)
    {
        USB_DeviceAudioSpeakerStatusReset();
    	VarBlockSharedByDspAndMcu.UsbDnStreamingIsStarted=1;
        error =
            USB_DeviceAudioRecv(g_deviceAudioComposite->audioUnified.audioSpeakerHandle,
                                USB_AUDIO_SPEAKER_STREAM_ENDPOINT, 
								//&audioPlayDataBuff[0], 
								UacRxPacketBuf,
								//(uint8_t *)UsbDnSpkBuf_ForUacSyncMode.PtrWr,
								FS_ISO_OUT_ENDP_PACKET_SIZE
								);
        if (error != kStatus_USB_Success)
        {
            return error;
        }
        else
        {
#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
#else
            error = USB_DeviceAudioSend(g_deviceAudioComposite->audioUnified.audioSpeakerHandle,
                                        USB_AUDIO_SPEAKER_FEEDBACK_ENDPOINT, audioFeedBackBuffer,
                                        (USB_SPEED_HIGH == g_composite.speed) ? HS_ISO_FEEDBACK_ENDP_PACKET_SIZE :
                                                                                FS_ISO_FEEDBACK_ENDP_PACKET_SIZE);
#endif
        }
    }else
    {
    	VarBlockSharedByDspAndMcu.UsbDnStreamingIsStarted=0;
        USB_DeviceAudioSpeakerStatusReset();

		CirAudioBuf_ClearAllSamples_S32(&UsbDnSpkBuf_ForUacSyncModeL);
		CirAudioBuf_ClearAllSamples_S32(&UsbDnSpkBuf_ForUacSyncModeR);
    }
    return error;
}

/*!
 * @brief Audio init function.
 *
 * This function initializes the device with the composite device class information.
 *
 * @param device_composite          The pointer to the composite device structure.
 * @return kStatus_USB_Success .
 */
usb_status_t USB_DeviceAudioCompositeInit(usb_device_composite_struct_t *device_composite)
{
#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
    SCTIMER_CaptureInit();
#else
    AUDIO_UPDATE_FEEDBACK_DATA(audioFeedBackBuffer, AUDIO_SAMPLING_RATE_TO_10_14);
#endif
    g_deviceAudioComposite                                       = device_composite;
    g_deviceAudioComposite->audioUnified.copyProtect             = 0x01U;
    g_deviceAudioComposite->audioUnified.curMute                 = 0x00U;
    g_deviceAudioComposite->audioUnified.curVolume[0]            = 0x00U;
    g_deviceAudioComposite->audioUnified.curVolume[1]            = 0x1fU;
    g_deviceAudioComposite->audioUnified.minVolume[0]            = 0x00U;
    g_deviceAudioComposite->audioUnified.minVolume[1]            = 0x00U;
    g_deviceAudioComposite->audioUnified.maxVolume[0]            = 0x00U;
    g_deviceAudioComposite->audioUnified.maxVolume[1]            = 0X43U;
    g_deviceAudioComposite->audioUnified.resVolume[0]            = 0x01U;
    g_deviceAudioComposite->audioUnified.resVolume[1]            = 0x00U;
    g_deviceAudioComposite->audioUnified.curBass                 = 0x00U;
    g_deviceAudioComposite->audioUnified.curBass                 = 0x00U;
    g_deviceAudioComposite->audioUnified.minBass                 = 0x80U;
    g_deviceAudioComposite->audioUnified.maxBass                 = 0x7FU;
    g_deviceAudioComposite->audioUnified.resBass                 = 0x01U;
    g_deviceAudioComposite->audioUnified.curMid                  = 0x00U;
    g_deviceAudioComposite->audioUnified.minMid                  = 0x80U;
    g_deviceAudioComposite->audioUnified.maxMid                  = 0x7FU;
    g_deviceAudioComposite->audioUnified.resMid                  = 0x01U;
    g_deviceAudioComposite->audioUnified.curTreble               = 0x01U;
    g_deviceAudioComposite->audioUnified.minTreble               = 0x80U;
    g_deviceAudioComposite->audioUnified.maxTreble               = 0x7FU;
    g_deviceAudioComposite->audioUnified.resTreble               = 0x01U;
    g_deviceAudioComposite->audioUnified.curAutomaticGain        = 0x01U;
    g_deviceAudioComposite->audioUnified.curDelay[0]             = 0x00U;
    g_deviceAudioComposite->audioUnified.curDelay[1]             = 0x40U;
    g_deviceAudioComposite->audioUnified.minDelay[0]             = 0x00U;
    g_deviceAudioComposite->audioUnified.minDelay[1]             = 0x00U;
    g_deviceAudioComposite->audioUnified.maxDelay[0]             = 0xFFU;
    g_deviceAudioComposite->audioUnified.maxDelay[1]             = 0xFFU;
    g_deviceAudioComposite->audioUnified.resDelay[0]             = 0x00U;
    g_deviceAudioComposite->audioUnified.resDelay[1]             = 0x01U;
    g_deviceAudioComposite->audioUnified.curLoudness             = 0x01U;
    g_deviceAudioComposite->audioUnified.curSamplingFrequency[0] = 0x00U;
    g_deviceAudioComposite->audioUnified.curSamplingFrequency[1] = 0x00U;
    g_deviceAudioComposite->audioUnified.curSamplingFrequency[2] = 0x01U;
    g_deviceAudioComposite->audioUnified.minSamplingFrequency[0] = 0x00U;
    g_deviceAudioComposite->audioUnified.minSamplingFrequency[1] = 0x00U;
    g_deviceAudioComposite->audioUnified.minSamplingFrequency[2] = 0x01U;
    g_deviceAudioComposite->audioUnified.maxSamplingFrequency[0] = 0x00U;
    g_deviceAudioComposite->audioUnified.maxSamplingFrequency[1] = 0x00U;
    g_deviceAudioComposite->audioUnified.maxSamplingFrequency[2] = 0x01U;
    g_deviceAudioComposite->audioUnified.resSamplingFrequency[0] = 0x00U;
    g_deviceAudioComposite->audioUnified.resSamplingFrequency[1] = 0x00U;
    g_deviceAudioComposite->audioUnified.resSamplingFrequency[2] = 0x01U;
#if USB_DEVICE_CONFIG_AUDIO_CLASS_2_0
    g_deviceAudioComposite->audioUnified.curMute20                  = 0U;
    g_deviceAudioComposite->audioUnified.curClockValid              = 1U;
    g_deviceAudioComposite->audioUnified.curVolume20[0]             = 0x00U;
    g_deviceAudioComposite->audioUnified.curVolume20[1]             = 0x1FU;

    g_deviceAudioComposite->audioUnified.curSpeakerSampleFrequency  =            (AUDIO_OUT_SAMPLING_RATE_KHZ*1000);
    g_deviceAudioComposite->audioUnified.freqSpeakerControlRange.wNumSubRanges = 1U;
    g_deviceAudioComposite->audioUnified.freqSpeakerControlRange.wMIN          = (AUDIO_OUT_SAMPLING_RATE_KHZ*1000);
    g_deviceAudioComposite->audioUnified.freqSpeakerControlRange.wMAX          = (AUDIO_OUT_SAMPLING_RATE_KHZ*1000);
    g_deviceAudioComposite->audioUnified.freqSpeakerControlRange.wRES          = 0U;
	

    g_deviceAudioComposite->audioUnified.curRecorderSampleFrequency =             (AUDIO_IN_SAMPLING_RATE_KHZ*1000);
    g_deviceAudioComposite->audioUnified.freqRecorderControlRange.wNumSubRanges = 1U;
    g_deviceAudioComposite->audioUnified.freqRecorderControlRange.wMIN          = (AUDIO_IN_SAMPLING_RATE_KHZ*1000);
    g_deviceAudioComposite->audioUnified.freqRecorderControlRange.wMAX          = (AUDIO_IN_SAMPLING_RATE_KHZ*1000);
    g_deviceAudioComposite->audioUnified.freqRecorderControlRange.wRES          = 0U;

    g_deviceAudioComposite->audioUnified.volumeControlRange.wNumSubRanges = 1U;
    g_deviceAudioComposite->audioUnified.volumeControlRange.wMIN          = 0x8001U;
    g_deviceAudioComposite->audioUnified.volumeControlRange.wMAX          = 0x7FFFU;
    g_deviceAudioComposite->audioUnified.volumeControlRange.wRES          = 1U;

#endif
    g_deviceAudioComposite->audioUnified.tdReadNumberPlay       = 0;
    g_deviceAudioComposite->audioUnified.tdWriteNumberPlay      = 0;
    //g_deviceAudioComposite->audioUnified.audioSendCount         = 0;
    //g_deviceAudioComposite->audioUnified.lastAudioSendCount     = 0;
    //g_deviceAudioComposite->audioUnified.usbRecvCount           = 0;
    //g_deviceAudioComposite->audioUnified.audioSendTimes         = 0;
    g_deviceAudioComposite->audioUnified.usbRecvTimes           = 0;
    g_deviceAudioComposite->audioUnified.startPlay              = 0;
    g_deviceAudioComposite->audioUnified.startPlayHalfFull      = 0;
    g_deviceAudioComposite->audioUnified.speakerIntervalCount   = 0;
    g_deviceAudioComposite->audioUnified.speakerReservedSpace   = 0;
    g_deviceAudioComposite->audioUnified.timesFeedbackCalculate = 0;
    g_deviceAudioComposite->audioUnified.speakerDetachOrNoInput = 0;
#if defined(USB_DEVICE_AUDIO_USE_SYNC_MODE) && (USB_DEVICE_AUDIO_USE_SYNC_MODE > 0U)
    g_deviceAudioComposite->audioUnified.audioPllTicksPrev   = 0;
    g_deviceAudioComposite->audioUnified.audioPllTicksDiff   = 0;
    g_deviceAudioComposite->audioUnified.audioPllTicksEma    = AUDIO_PLL_USB1_SOF_INTERVAL_COUNT;
    g_deviceAudioComposite->audioUnified.audioPllTickEmaFrac = 0;
    g_deviceAudioComposite->audioUnified.audioPllStep        = AUDIO_PLL_FRACTIONAL_CHANGE_STEP;
#endif
    return kStatus_USB_Success;
}

void USB_AudioSpeakerResetTask(void)
{
    if (g_deviceAudioComposite->audioUnified.speakerDetachOrNoInput)
    {
        USB_DeviceAudioSpeakerStatusReset();
    }
}
