0

我正在尝试通过 SDIO 从我的 SD 中读取 2 个带有 FATFS 的文件并混合 16 位 PCM 音频数据。它可以工作,但输出声音在播放 2 个文件时速度较慢,听起来不太好。

我使用 I2S 将数据发送到 IC。我的 Buffersize 是 4096。如果不混合 2 个缓冲区,音频质量就很好。当我使用该示例混合我在网上找到的缓冲区时,您会听到很多噪音。

有任何想法吗?

我的代码:

volatile uint16_t* signal_play_buff = NULL;
uint16_t* signal_read_buff = NULL;
uint16_t* signal_read_buff2 = NULL;

volatile uint16_t signal_buff1[4096];
volatile uint16_t signal_buff2[4096];

HAL_StatusTypeDef hal_res;
    int nsamples = sizeof(signal_buff1) / sizeof(signal_buff1[0]);
    hal_res = HAL_I2S_Transmit_IT(&hi2s2, (uint16_t*)signal_buff1, nsamples);
    if(hal_res != HAL_OK) {
        UART_Printf("I2S - HAL_I2S_Transmit failed, hal_res = %d!\r\n", hal_res);
        f_close(&file);
        return -12;
    }
        FIL file2;
        FRESULT res2 = f_open(&file2, "over.raw", FA_READ);

        while(bytesRead >= sizeof(signal_buff1)) {
                if(!read_next_chunk) {
                    continue;
                }

                read_next_chunk = false;

                res = f_read(&file, (uint8_t*)signal_read_buff, sizeof(signal_buff1), &bytesRead);
                res2 = f_read(&file2, (uint8_t*)signal_buff3, sizeof(signal_buff3), &bytesRead2);

                for(int i = 0; i < sizeof(signal_buff1) /2; i++){
                    uint16_t a = signal_read_buff[i]; // first sample
                    uint16_t b = signal_buff3[i]; // second sample
                    uint16_t m; // mixed result will go here

                    // Pick the equation
                    if ((a < 32768) || (b < 32768)) {
                        // Viktor's first equation when both sources are "quiet"
                        // (i.e. less than middle of the dynamic range)
                        m = a * b / 32768;
                    } else {
                        // Viktor's second equation when one or both sources are loud
                        m = 2 * (a + b) - (a * b) / 32768 - 65536;
                    }

                    if (m == 65536) m = 65535;
                    signal_read_buff[i] = m;
                }

                if(res != FR_OK) {
                    UART_Printf("f_read() failed, res = %d\r\n", res);
                    f_close(&file);
                    return -13;
                }

            }

            end_of_file_reached = true;   
    res = f_close(&file);
    if(res != FR_OK) {
        UART_Printf("f_close() failed, res = %d\r\n", res);
        return -14;
    }

    return 0;
}

I2S 回调发送下一个缓冲区

void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) {
    if(end_of_file_reached)
        return;

    volatile uint16_t* temp = signal_play_buff;
    signal_play_buff = signal_read_buff;
    signal_read_buff = temp;

    int nsamples = sizeof(signal_buff1) / sizeof(signal_buff1[0]);
    HAL_I2S_Transmit_IT(&hi2s2, (uint16_t*)signal_play_buff, nsamples);
    read_next_chunk = true;
}
4

0 回答 0