/*************************************************************************** * * Copyright 2015-2019 BES. * All rights reserved. All unpublished rights reserved. * * No part of this work may be used or reproduced in any form or by any * means, or stored in a database or retrieval system, without prior written * permission of BES. * * Use of this work is governed by a license granted by BES. * This work contains confidential and proprietary information of * BES. which is protected by copyright, trade secret, * trademark and other intellectual property rights. * ****************************************************************************/ #ifdef MBED #include "mbed.h" #endif // Standard C Included Files #include #include #include #include #include #include "hal_uart.h" #include "hal_trace.h" #include "hal_timer.h" /*! * * @brief Standard Winodws PCM wave file header length * */ #define WAVE_FILE_HEADER_SIZE 0x2CU typedef struct wave_header { uint8_t riff[4]; uint32_t size; uint8_t waveFlag[4]; uint8_t fmt[4]; uint32_t fmtLen; uint16_t tag; uint16_t channels; uint32_t sampFreq; uint32_t byteRate; uint16_t blockAlign; uint16_t bitSamp; uint8_t dataFlag[4]; uint32_t length; } wave_header_t; /*! * * @brief Wave file structure * */ typedef struct wave_file { wave_header_t header; uint32_t *data; }wave_file_t; /* player */ static unsigned int g_total_play_count = 0; static unsigned int g_curr_play_index = 0; /* wave */ wave_file_t g_wave_file_info; static char g_wav_header[WAVE_FILE_HEADER_SIZE]; FILE *g_wave_file_handle = NULL; static int32_t (*wav_file_playback_callback)(int32_t ) = NULL; //////////////////////////////////////////////////////////////////////////////// // Code //////////////////////////////////////////////////////////////////////////////// void wav_file_set_playeback_cb(int32_t (* cb)(int32_t)) { wav_file_playback_callback = cb; } bool wav_file_isplaydone(void) { return (g_curr_play_index >= g_total_play_count)? true : false; } uint32_t wav_file_audio_more_data(uint8_t *buf, uint32_t len) { // static uint32_t g_preIrqTime = 0; uint32_t reallen = 0; // int32_t stime,etime; int32_t status; /* play done ? */ if(wav_file_isplaydone()) { memset(buf, 0, len); status = 0; if (wav_file_playback_callback) wav_file_playback_callback(status); return (len); } // stime = hal_sys_timer_get(); /* read file */ if (g_wave_file_handle) reallen = fread(buf, 1, len, g_wave_file_handle); // etime = hal_sys_timer_get(); if (reallen != len){ memset(buf, 0, len); status = -1; if (wav_file_playback_callback) wav_file_playback_callback(status); return (len); } // TRACE(5,"wav_file_audio_more_data irqDur:%d fsSpend:%d, readbuff:0x%08x %d/%d\n ", TICKS_TO_MS(stime - g_preIrqTime),TICKS_TO_MS(etime - stime),buf,reallen,len); // g_preIrqTime = stime; /* walk index */ g_curr_play_index += reallen; return reallen; } uint32_t get_wav_data(wave_file_t *waveFile) { uint8_t *dataTemp = (uint8_t *)waveFile->data; // check for RIFF memcpy(waveFile->header.riff, dataTemp, 4); dataTemp += 4; if( memcmp( (uint8_t*)waveFile->header.riff, "RIFF", 4) ) { return 0; } // Get size memcpy(&waveFile->header.size, dataTemp, 4); dataTemp += 4; TRACE(1,"WAV header size [%d]\n", waveFile->header.size); // .wav file flag memcpy(waveFile->header.waveFlag, dataTemp, 4); dataTemp += 4; if( memcmp( (uint8_t*)waveFile->header.waveFlag, "WAVE", 4) ) { return 0; } // fmt memcpy(waveFile->header.fmt, dataTemp, 4); dataTemp += 4; if( memcmp( (uint8_t*)waveFile->header.fmt, "fmt ", 4) ) { return 0; } // fmt length memcpy(&waveFile->header.fmtLen, dataTemp, 4); dataTemp += 4; // Tag: PCM or not memcpy(&waveFile->header.tag, dataTemp, 4); dataTemp += 2; // Channels memcpy(&waveFile->header.channels, dataTemp, 4); dataTemp += 2; TRACE(1,"WAV channels [%d]\n", waveFile->header.channels); // Sample Rate in Hz memcpy(&waveFile->header.sampFreq, dataTemp, 4); dataTemp += 4; memcpy(&waveFile->header.byteRate, dataTemp, 4); dataTemp += 4; TRACE(1,"WAV sample_rate [%d]\n", waveFile->header.sampFreq); TRACE(1,"WAV byteRate [%d]\n", waveFile->header.byteRate); // quantize bytes for per samp point memcpy(&waveFile->header.blockAlign, dataTemp, 4); dataTemp += 2; memcpy(&waveFile->header.bitSamp, dataTemp, 4); dataTemp += 2; TRACE(1,"WAV bitSamp [%d]\n", waveFile->header.bitSamp); // Data memcpy(waveFile->header.dataFlag, dataTemp, 4); dataTemp += 4; if( memcmp( (uint8_t*)waveFile->header.dataFlag, "data ", 4) ) { return 0; } memcpy(&waveFile->header.length, dataTemp, 4); dataTemp += 4; return 0; } void audio_wav_init(wave_file_t *newWav) { get_wav_data(newWav); // Configure the play audio g_format //g_format.bits = newWav->header.bitSamp; //g_format.sample_rate = newWav->header.sampFreq; //g_format.mclk = 256 * g_format.sample_rate ; //g_format.mono_streo = (sai_mono_streo_t)((newWav->header.channels) - 1); } uint32_t play_wav_file(char *file_path) { uint32_t bytesToRead = 0; wave_file_t *newWav = &g_wave_file_info; memset(&g_wave_file_info, 0, sizeof(g_wave_file_info)); g_wave_file_handle = fopen(file_path, "rb"); if(g_wave_file_handle == NULL) { TRACE(1,"WAV file %s open fail\n", file_path); return 1; } fread(&g_wav_header, WAVE_FILE_HEADER_SIZE, 1, g_wave_file_handle); newWav->data = (uint32_t *)&g_wav_header; audio_wav_init(newWav); // Remove header size from byte count // Adjust note duration by divider value, wav tables in pcm_data.h are 200ms by default bytesToRead = (newWav->header.length - WAVE_FILE_HEADER_SIZE); g_curr_play_index = 0; g_total_play_count = bytesToRead; return newWav->header.sampFreq; } uint32_t stop_wav_file(void) { memset(&g_wave_file_info, 0, sizeof(g_wave_file_info)); g_curr_play_index = 0; g_total_play_count = 0; if (g_wave_file_handle){ fclose(g_wave_file_handle); g_wave_file_handle = NULL; } if (wav_file_playback_callback) wav_file_playback_callback = NULL; return 0; }