pinebuds/apps/audioplayers/wavplay.cpp

243 lines
6.2 KiB
C++
Raw Permalink Normal View History

2022-08-15 04:20:27 -05:00
/***************************************************************************
*
* 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>
2022-08-15 04:20:27 -05:00
#include "hal_timer.h"
#include "hal_trace.h"
#include "hal_uart.h"
2022-08-15 04:20:27 -05:00
/*!
* * @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;
2022-08-15 04:20:27 -05:00
} wave_header_t;
/*!
* * @brief Wave file structure
* */
typedef struct wave_file {
wave_header_t header;
uint32_t *data;
} wave_file_t;
2022-08-15 04:20:27 -05:00
/* 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;
2022-08-15 04:20:27 -05:00
////////////////////////////////////////////////////////////////////////////////
// Code
////////////////////////////////////////////////////////////////////////////////
void wav_file_set_playeback_cb(int32_t (*cb)(int32_t)) {
wav_file_playback_callback = cb;
2022-08-15 04:20:27 -05:00
}
bool wav_file_isplaydone(void) {
return (g_curr_play_index >= g_total_play_count) ? true : false;
2022-08-15 04:20:27 -05:00
}
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;
2022-08-15 04:20:27 -05:00
}
uint32_t get_wav_data(wave_file_t *waveFile) {
uint8_t *dataTemp = (uint8_t *)waveFile->data;
2022-08-15 04:20:27 -05:00
// check for RIFF
memcpy(waveFile->header.riff, dataTemp, 4);
dataTemp += 4;
if (memcmp((uint8_t *)waveFile->header.riff, "RIFF", 4)) {
2022-08-15 04:20:27 -05:00
return 0;
}
2022-08-15 04:20:27 -05:00
// Get size
memcpy(&waveFile->header.size, dataTemp, 4);
dataTemp += 4;
2022-08-15 04:20:27 -05:00
TRACE(1, "WAV header size [%d]\n", waveFile->header.size);
2022-08-15 04:20:27 -05:00
// .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;
}
2022-08-15 04:20:27 -05:00
// fmt length
memcpy(&waveFile->header.fmtLen, dataTemp, 4);
dataTemp += 4;
2022-08-15 04:20:27 -05:00
// Tag: PCM or not
memcpy(&waveFile->header.tag, dataTemp, 4);
dataTemp += 2;
2022-08-15 04:20:27 -05:00
// Channels
memcpy(&waveFile->header.channels, dataTemp, 4);
dataTemp += 2;
2022-08-15 04:20:27 -05:00
TRACE(1, "WAV channels [%d]\n", waveFile->header.channels);
2022-08-15 04:20:27 -05:00
// Sample Rate in Hz
memcpy(&waveFile->header.sampFreq, dataTemp, 4);
dataTemp += 4;
memcpy(&waveFile->header.byteRate, dataTemp, 4);
dataTemp += 4;
2022-08-15 04:20:27 -05:00
TRACE(1, "WAV sample_rate [%d]\n", waveFile->header.sampFreq);
TRACE(1, "WAV byteRate [%d]\n", waveFile->header.byteRate);
2022-08-15 04:20:27 -05:00
// quantize bytes for per samp point
memcpy(&waveFile->header.blockAlign, dataTemp, 4);
dataTemp += 2;
memcpy(&waveFile->header.bitSamp, dataTemp, 4);
dataTemp += 2;
2022-08-15 04:20:27 -05:00
TRACE(1, "WAV bitSamp [%d]\n", waveFile->header.bitSamp);
2022-08-15 04:20:27 -05:00
// 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;
2022-08-15 04:20:27 -05:00
return 0;
}
2022-08-15 04:20:27 -05:00
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);
2022-08-15 04:20:27 -05:00
}
uint32_t play_wav_file(char *file_path) {
uint32_t bytesToRead = 0;
2022-08-15 04:20:27 -05:00
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;
2022-08-15 04:20:27 -05:00
}