Easy playback library for PwmOutSpeaker.
decoder/EasyDec_WavCnv2ch.h@0:41ab76b22961, 2017-07-06 (annotated)
- Committer:
- dkato
- Date:
- Thu Jul 06 04:42:29 2017 +0000
- Revision:
- 0:41ab76b22961
first commit
Who changed what in which revision?
User | Revision | Line number | New 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 |