243 lines
6.2 KiB
C++
243 lines
6.2 KiB
C++
/***************************************************************************
|
|
*
|
|
* 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 <math.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "hal_timer.h"
|
|
#include "hal_trace.h"
|
|
#include "hal_uart.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;
|
|
}
|