Easy playback library for PwmOutSpeaker.

Committer:
dkato
Date:
Thu Jul 06 04:42:29 2017 +0000
Revision:
0:41ab76b22961
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:41ab76b22961 1 /* mbed EasyDec_WavCnv2ch Library
dkato 0:41ab76b22961 2 * Copyright (C) 2017 dkato
dkato 0:41ab76b22961 3 *
dkato 0:41ab76b22961 4 * Licensed under the Apache License, Version 2.0 (the "License");
dkato 0:41ab76b22961 5 * you may not use this file except in compliance with the License.
dkato 0:41ab76b22961 6 * You may obtain a copy of the License at
dkato 0:41ab76b22961 7 *
dkato 0:41ab76b22961 8 * http://www.apache.org/licenses/LICENSE-2.0
dkato 0:41ab76b22961 9 *
dkato 0:41ab76b22961 10 * Unless required by applicable law or agreed to in writing, software
dkato 0:41ab76b22961 11 * distributed under the License is distributed on an "AS IS" BASIS,
dkato 0:41ab76b22961 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dkato 0:41ab76b22961 13 * See the License for the specific language governing permissions and
dkato 0:41ab76b22961 14 * limitations under the License.
dkato 0:41ab76b22961 15 */
dkato 0:41ab76b22961 16
dkato 0:41ab76b22961 17 /**************************************************************************//**
dkato 0:41ab76b22961 18 * @file EasyDec_WavCnv2ch.h
dkato 0:41ab76b22961 19 * @brief wav
dkato 0:41ab76b22961 20 ******************************************************************************/
dkato 0:41ab76b22961 21 #ifndef __EASY_DEC_WAV_CNV_2CH_H__
dkato 0:41ab76b22961 22 #define __EASY_DEC_WAV_CNV_2CH_H__
dkato 0:41ab76b22961 23
dkato 0:41ab76b22961 24 #include "EasyDecoder.h"
dkato 0:41ab76b22961 25
dkato 0:41ab76b22961 26 /** A class to communicate a EasyDec_WavCnv2ch
dkato 0:41ab76b22961 27 *
dkato 0:41ab76b22961 28 */
dkato 0:41ab76b22961 29 class EasyDec_WavCnv2ch : public EasyDecoder {
dkato 0:41ab76b22961 30 public:
dkato 0:41ab76b22961 31
dkato 0:41ab76b22961 32 static inline EasyDecoder* inst() { return new EasyDec_WavCnv2ch; }
dkato 0:41ab76b22961 33
dkato 0:41ab76b22961 34 /** analyze header
dkato 0:41ab76b22961 35 *
dkato 0:41ab76b22961 36 * @param p_title title tag buffer
dkato 0:41ab76b22961 37 * @param p_artist artist tag buffer
dkato 0:41ab76b22961 38 * @param p_album album tag buffer
dkato 0:41ab76b22961 39 * @param tag_size tag buffer size
dkato 0:41ab76b22961 40 * @param fp file pointer
dkato 0:41ab76b22961 41 * @return true = success, false = failure
dkato 0:41ab76b22961 42 */
dkato 0:41ab76b22961 43 virtual bool AnalyzeHeder(char* p_title, char* p_artist, char* p_album, uint16_t tag_size, FILE* fp) {
dkato 0:41ab76b22961 44 bool result = false;
dkato 0:41ab76b22961 45 size_t read_size;
dkato 0:41ab76b22961 46 uint8_t wk_read_buff[36];
dkato 0:41ab76b22961 47 char *data;
dkato 0:41ab76b22961 48 uint32_t chunk_size;
dkato 0:41ab76b22961 49 uint32_t sub_chunk_size;
dkato 0:41ab76b22961 50 uint32_t list_index_max;
dkato 0:41ab76b22961 51 bool list_ok = false;
dkato 0:41ab76b22961 52 uint32_t read_index = 0;
dkato 0:41ab76b22961 53 uint32_t data_index = 0;
dkato 0:41ab76b22961 54 uint16_t wk_len;
dkato 0:41ab76b22961 55
dkato 0:41ab76b22961 56 if (fp == NULL) {
dkato 0:41ab76b22961 57 return false;
dkato 0:41ab76b22961 58 }
dkato 0:41ab76b22961 59 music_data_size = 0;
dkato 0:41ab76b22961 60 music_data_index = 0;
dkato 0:41ab76b22961 61 wav_fp = fp;
dkato 0:41ab76b22961 62 if (p_title != NULL) {
dkato 0:41ab76b22961 63 p_title[0] = '\0';
dkato 0:41ab76b22961 64 }
dkato 0:41ab76b22961 65 if (p_artist != NULL) {
dkato 0:41ab76b22961 66 p_artist[0] = '\0';
dkato 0:41ab76b22961 67 }
dkato 0:41ab76b22961 68 if (p_album != NULL) {
dkato 0:41ab76b22961 69 p_album[0] = '\0';
dkato 0:41ab76b22961 70 }
dkato 0:41ab76b22961 71
dkato 0:41ab76b22961 72 read_size = fread(&wk_read_buff[0], sizeof(char), 36, wav_fp);
dkato 0:41ab76b22961 73 if (read_size < 36) {
dkato 0:41ab76b22961 74 // do nothing
dkato 0:41ab76b22961 75 } else if (memcmp(&wk_read_buff[0], "RIFF", 4) != 0) {
dkato 0:41ab76b22961 76 // do nothing
dkato 0:41ab76b22961 77 } else if (memcmp(&wk_read_buff[8], "WAVE", 4) != 0) {
dkato 0:41ab76b22961 78 // do nothing
dkato 0:41ab76b22961 79 } else if (memcmp(&wk_read_buff[12], "fmt ", 4) != 0) {
dkato 0:41ab76b22961 80 // do nothing
dkato 0:41ab76b22961 81 } else {
dkato 0:41ab76b22961 82 read_index += 36;
dkato 0:41ab76b22961 83 channel = ((uint32_t)wk_read_buff[22] << 0) + ((uint32_t)wk_read_buff[23] << 8);
dkato 0:41ab76b22961 84 sampling_rate = ((uint32_t)wk_read_buff[24] << 0)
dkato 0:41ab76b22961 85 + ((uint32_t)wk_read_buff[25] << 8)
dkato 0:41ab76b22961 86 + ((uint32_t)wk_read_buff[26] << 16)
dkato 0:41ab76b22961 87 + ((uint32_t)wk_read_buff[27] << 24);
dkato 0:41ab76b22961 88 block_size = ((uint32_t)wk_read_buff[34] << 0) + ((uint32_t)wk_read_buff[35] << 8);
dkato 0:41ab76b22961 89 while (1) {
dkato 0:41ab76b22961 90 read_size = fread(&wk_read_buff[0], sizeof(char), 8, wav_fp);
dkato 0:41ab76b22961 91 read_index += 8;
dkato 0:41ab76b22961 92 if (read_size < 8) {
dkato 0:41ab76b22961 93 break;
dkato 0:41ab76b22961 94 } else {
dkato 0:41ab76b22961 95 chunk_size = ((uint32_t)wk_read_buff[4] << 0)
dkato 0:41ab76b22961 96 + ((uint32_t)wk_read_buff[5] << 8)
dkato 0:41ab76b22961 97 + ((uint32_t)wk_read_buff[6] << 16)
dkato 0:41ab76b22961 98 + ((uint32_t)wk_read_buff[7] << 24);
dkato 0:41ab76b22961 99 if (memcmp(&wk_read_buff[0], "data", 4) == 0) {
dkato 0:41ab76b22961 100 result = true;
dkato 0:41ab76b22961 101 music_data_size = chunk_size;
dkato 0:41ab76b22961 102 if (list_ok == true) {
dkato 0:41ab76b22961 103 break;
dkato 0:41ab76b22961 104 } else {
dkato 0:41ab76b22961 105 data_index = read_index;
dkato 0:41ab76b22961 106 fseek(wav_fp, chunk_size, SEEK_CUR);
dkato 0:41ab76b22961 107 read_index += chunk_size;
dkato 0:41ab76b22961 108 }
dkato 0:41ab76b22961 109 } else if (memcmp(&wk_read_buff[0], "LIST", 4) == 0) {
dkato 0:41ab76b22961 110 list_ok = true;
dkato 0:41ab76b22961 111 list_index_max = read_index + chunk_size;
dkato 0:41ab76b22961 112 read_size = fread(&wk_read_buff[0], sizeof(char), 4, wav_fp);
dkato 0:41ab76b22961 113 read_index += 4;
dkato 0:41ab76b22961 114 while (read_index < list_index_max) {
dkato 0:41ab76b22961 115 read_size = fread(&wk_read_buff[0], sizeof(char), 8, wav_fp);
dkato 0:41ab76b22961 116 read_index += 8;
dkato 0:41ab76b22961 117 if (read_size < 8) {
dkato 0:41ab76b22961 118 break;
dkato 0:41ab76b22961 119 } else if (memcmp(&wk_read_buff[0], "INAM", 4) == 0) {
dkato 0:41ab76b22961 120 data = p_title;
dkato 0:41ab76b22961 121 } else if (memcmp(&wk_read_buff[0], "IART", 4) == 0) {
dkato 0:41ab76b22961 122 data = p_artist;
dkato 0:41ab76b22961 123 } else if (memcmp(&wk_read_buff[0], "IPRD", 4) == 0) {
dkato 0:41ab76b22961 124 data = p_album;
dkato 0:41ab76b22961 125 } else {
dkato 0:41ab76b22961 126 data = NULL;
dkato 0:41ab76b22961 127 }
dkato 0:41ab76b22961 128 sub_chunk_size = ((uint32_t)wk_read_buff[4] << 0)
dkato 0:41ab76b22961 129 + ((uint32_t)wk_read_buff[5] << 8)
dkato 0:41ab76b22961 130 + ((uint32_t)wk_read_buff[6] << 16)
dkato 0:41ab76b22961 131 + ((uint32_t)wk_read_buff[7] << 24);
dkato 0:41ab76b22961 132 if ((data != NULL) && (tag_size != 0)) {
dkato 0:41ab76b22961 133 if (sub_chunk_size > (uint32_t)(tag_size - 1)) {
dkato 0:41ab76b22961 134 wk_len = (tag_size - 1);
dkato 0:41ab76b22961 135 } else {
dkato 0:41ab76b22961 136 wk_len = sub_chunk_size;
dkato 0:41ab76b22961 137 }
dkato 0:41ab76b22961 138 read_size = fread(data, sizeof(char), wk_len, wav_fp);
dkato 0:41ab76b22961 139 data[wk_len] = '\0';
dkato 0:41ab76b22961 140 }
dkato 0:41ab76b22961 141 if ((sub_chunk_size & 0x00000001) != 0) {
dkato 0:41ab76b22961 142 sub_chunk_size += 1;
dkato 0:41ab76b22961 143 }
dkato 0:41ab76b22961 144 read_index += sub_chunk_size;
dkato 0:41ab76b22961 145 fseek(wav_fp, read_index, SEEK_SET);
dkato 0:41ab76b22961 146 }
dkato 0:41ab76b22961 147 if (data_index != 0) {
dkato 0:41ab76b22961 148 break;
dkato 0:41ab76b22961 149 } else {
dkato 0:41ab76b22961 150 fseek(wav_fp, list_index_max, SEEK_SET);
dkato 0:41ab76b22961 151 }
dkato 0:41ab76b22961 152 } else {
dkato 0:41ab76b22961 153 fseek(wav_fp, chunk_size, SEEK_CUR);
dkato 0:41ab76b22961 154 read_index += chunk_size;
dkato 0:41ab76b22961 155 }
dkato 0:41ab76b22961 156 }
dkato 0:41ab76b22961 157 }
dkato 0:41ab76b22961 158
dkato 0:41ab76b22961 159 if (data_index != 0) {
dkato 0:41ab76b22961 160 fseek(wav_fp, data_index, SEEK_SET);
dkato 0:41ab76b22961 161 }
dkato 0:41ab76b22961 162 }
dkato 0:41ab76b22961 163
dkato 0:41ab76b22961 164 return result;
dkato 0:41ab76b22961 165 };
dkato 0:41ab76b22961 166
dkato 0:41ab76b22961 167 /** get next data
dkato 0:41ab76b22961 168 *
dkato 0:41ab76b22961 169 * @param buf data buffer address
dkato 0:41ab76b22961 170 * @param len data buffer length
dkato 0:41ab76b22961 171 * @return get data size
dkato 0:41ab76b22961 172 */
dkato 0:41ab76b22961 173 virtual size_t GetNextData(void *buf, size_t len) {
dkato 0:41ab76b22961 174 size_t ret_size;
dkato 0:41ab76b22961 175 size_t read_max = len;
dkato 0:41ab76b22961 176
dkato 0:41ab76b22961 177 if ((block_size < 8) || ((block_size & 0x07) != 0)) {
dkato 0:41ab76b22961 178 return -1;
dkato 0:41ab76b22961 179 }
dkato 0:41ab76b22961 180
dkato 0:41ab76b22961 181 if ((channel == 1) && (len != 0)) {
dkato 0:41ab76b22961 182 read_max /= 2;
dkato 0:41ab76b22961 183 }
dkato 0:41ab76b22961 184
dkato 0:41ab76b22961 185 if (block_size == 24) {
dkato 0:41ab76b22961 186 // Add padding
dkato 0:41ab76b22961 187 uint32_t write_index = 0;
dkato 0:41ab76b22961 188 uint32_t wavfile_index;
dkato 0:41ab76b22961 189 uint32_t read_len;
dkato 0:41ab76b22961 190 uint32_t pading_index = 0;
dkato 0:41ab76b22961 191 uint8_t * p_buf = (uint8_t *)buf;
dkato 0:41ab76b22961 192 size_t ret;
dkato 0:41ab76b22961 193
dkato 0:41ab76b22961 194 if ((music_data_index + read_max) > music_data_size) {
dkato 0:41ab76b22961 195 read_max = music_data_size - music_data_index;
dkato 0:41ab76b22961 196 }
dkato 0:41ab76b22961 197 while (write_index < (uint32_t)read_max) {
dkato 0:41ab76b22961 198 read_len = (read_max - write_index) * 3 / 4;
dkato 0:41ab76b22961 199 if (read_len > sizeof(wk_wavfile_buff)) {
dkato 0:41ab76b22961 200 read_len = sizeof(wk_wavfile_buff);
dkato 0:41ab76b22961 201 }
dkato 0:41ab76b22961 202 music_data_index += read_len;
dkato 0:41ab76b22961 203 ret = fread(wk_wavfile_buff, sizeof(char), read_len, wav_fp);
dkato 0:41ab76b22961 204 if (ret < read_len) {
dkato 0:41ab76b22961 205 break;
dkato 0:41ab76b22961 206 }
dkato 0:41ab76b22961 207 wavfile_index = 0;
dkato 0:41ab76b22961 208 while ((write_index < read_max) && (wavfile_index < read_len)) {
dkato 0:41ab76b22961 209 if (pading_index == 0) {
dkato 0:41ab76b22961 210 p_buf[write_index] = 0;
dkato 0:41ab76b22961 211 } else {
dkato 0:41ab76b22961 212 p_buf[write_index] = wk_wavfile_buff[wavfile_index];
dkato 0:41ab76b22961 213 wavfile_index++;
dkato 0:41ab76b22961 214 }
dkato 0:41ab76b22961 215 if (pading_index < 3) {
dkato 0:41ab76b22961 216 pading_index++;
dkato 0:41ab76b22961 217 } else {
dkato 0:41ab76b22961 218 pading_index = 0;
dkato 0:41ab76b22961 219 }
dkato 0:41ab76b22961 220 write_index++;
dkato 0:41ab76b22961 221 }
dkato 0:41ab76b22961 222 }
dkato 0:41ab76b22961 223 ret_size = write_index;
dkato 0:41ab76b22961 224 } else {
dkato 0:41ab76b22961 225 if ((music_data_index + read_max) > music_data_size) {
dkato 0:41ab76b22961 226 read_max = music_data_size - music_data_index;
dkato 0:41ab76b22961 227 }
dkato 0:41ab76b22961 228 music_data_index += read_max;
dkato 0:41ab76b22961 229
dkato 0:41ab76b22961 230 ret_size = fread(buf, sizeof(char), read_max, wav_fp);
dkato 0:41ab76b22961 231 }
dkato 0:41ab76b22961 232
dkato 0:41ab76b22961 233 if ((channel == 1) && (ret_size > 0)) {
dkato 0:41ab76b22961 234 int block_byte;
dkato 0:41ab76b22961 235 int idx_w = len - 1;
dkato 0:41ab76b22961 236 int idx_r = ret_size - 1;
dkato 0:41ab76b22961 237 int idx_r_last;
dkato 0:41ab76b22961 238 int j;
dkato 0:41ab76b22961 239
dkato 0:41ab76b22961 240 if (block_size == 24) {
dkato 0:41ab76b22961 241 block_byte = 4;
dkato 0:41ab76b22961 242 } else {
dkato 0:41ab76b22961 243 block_byte = block_size / 8;
dkato 0:41ab76b22961 244 }
dkato 0:41ab76b22961 245 while (idx_w >= 0) {
dkato 0:41ab76b22961 246 idx_r_last = idx_r;
dkato 0:41ab76b22961 247 for (j = 0; j < block_byte; j++) {
dkato 0:41ab76b22961 248 ((uint8_t*)buf)[idx_w--] = ((uint8_t*)buf)[idx_r--];
dkato 0:41ab76b22961 249 }
dkato 0:41ab76b22961 250 idx_r = idx_r_last;
dkato 0:41ab76b22961 251 for (j = 0; j < block_byte; j++) {
dkato 0:41ab76b22961 252 ((uint8_t*)buf)[idx_w--] = ((uint8_t*)buf)[idx_r--];
dkato 0:41ab76b22961 253 }
dkato 0:41ab76b22961 254 }
dkato 0:41ab76b22961 255 ret_size *= 2;
dkato 0:41ab76b22961 256 }
dkato 0:41ab76b22961 257
dkato 0:41ab76b22961 258 return ret_size;
dkato 0:41ab76b22961 259 };
dkato 0:41ab76b22961 260
dkato 0:41ab76b22961 261 /** get channel
dkato 0:41ab76b22961 262 *
dkato 0:41ab76b22961 263 * @return channel
dkato 0:41ab76b22961 264 */
dkato 0:41ab76b22961 265 virtual uint16_t GetChannel() {
dkato 0:41ab76b22961 266 if (channel == 1) {
dkato 0:41ab76b22961 267 return 2;
dkato 0:41ab76b22961 268 } else {
dkato 0:41ab76b22961 269 return channel;
dkato 0:41ab76b22961 270 }
dkato 0:41ab76b22961 271 };
dkato 0:41ab76b22961 272
dkato 0:41ab76b22961 273 /** get block size
dkato 0:41ab76b22961 274 *
dkato 0:41ab76b22961 275 * @return block size
dkato 0:41ab76b22961 276 */
dkato 0:41ab76b22961 277 virtual uint16_t GetBlockSize() {
dkato 0:41ab76b22961 278 return block_size;
dkato 0:41ab76b22961 279 };
dkato 0:41ab76b22961 280
dkato 0:41ab76b22961 281 /** get sampling rate
dkato 0:41ab76b22961 282 *
dkato 0:41ab76b22961 283 * @return sampling rate
dkato 0:41ab76b22961 284 */
dkato 0:41ab76b22961 285 virtual uint32_t GetSamplingRate() {
dkato 0:41ab76b22961 286 return sampling_rate;
dkato 0:41ab76b22961 287 };
dkato 0:41ab76b22961 288
dkato 0:41ab76b22961 289 private:
dkato 0:41ab76b22961 290 FILE * wav_fp;
dkato 0:41ab76b22961 291 uint32_t music_data_size;
dkato 0:41ab76b22961 292 uint32_t music_data_index;
dkato 0:41ab76b22961 293 uint16_t channel;
dkato 0:41ab76b22961 294 uint16_t block_size;
dkato 0:41ab76b22961 295 uint32_t sampling_rate;
dkato 0:41ab76b22961 296 uint8_t wk_wavfile_buff[3072];
dkato 0:41ab76b22961 297 };
dkato 0:41ab76b22961 298
dkato 0:41ab76b22961 299 #endif