Decode Wav files

Committer:
UHSLMarcus
Date:
Wed Mar 01 10:35:59 2017 +0000
Revision:
2:18fdd269b401
Parent:
1:c1046d91bff7
trying triple buffered aproach

Who changed what in which revision?

UserRevisionLine numberNew contents of line
UHSLMarcus 1:c1046d91bff7 1 /*
UHSLMarcus 1:c1046d91bff7 2 * WAV_Reader.cpp
UHSLMarcus 1:c1046d91bff7 3 *
UHSLMarcus 1:c1046d91bff7 4 * Created on: 23 Feb 2017
UHSLMarcus 1:c1046d91bff7 5 * Author: ML15AAF
UHSLMarcus 1:c1046d91bff7 6 */
UHSLMarcus 1:c1046d91bff7 7
UHSLMarcus 1:c1046d91bff7 8 #include <WAV_Reader.h>
UHSLMarcus 1:c1046d91bff7 9
UHSLMarcus 1:c1046d91bff7 10 WAV_Reader::Config::Config() {
UHSLMarcus 1:c1046d91bff7 11 format_tag = 0;
UHSLMarcus 1:c1046d91bff7 12 channels = 0;
UHSLMarcus 1:c1046d91bff7 13 samples_per_sec = 0;
UHSLMarcus 1:c1046d91bff7 14 avg_bytes_per_sec = 0;
UHSLMarcus 1:c1046d91bff7 15 block_align = 0;
UHSLMarcus 1:c1046d91bff7 16 bits_per_sample = 0;
UHSLMarcus 1:c1046d91bff7 17 data_pos = 0;
UHSLMarcus 1:c1046d91bff7 18 data_length = 0;
UHSLMarcus 1:c1046d91bff7 19 file_size = 0;
UHSLMarcus 1:c1046d91bff7 20 }
UHSLMarcus 1:c1046d91bff7 21
UHSLMarcus 1:c1046d91bff7 22 WAV_Reader::WAV_Reader() :
UHSLMarcus 1:c1046d91bff7 23 fpp(NULL), _current_pos(0), _loop(false) {
UHSLMarcus 1:c1046d91bff7 24
UHSLMarcus 1:c1046d91bff7 25 }
UHSLMarcus 1:c1046d91bff7 26
UHSLMarcus 1:c1046d91bff7 27 int WAV_Reader::open(FILE **filepp) {
UHSLMarcus 1:c1046d91bff7 28 int success = 0;
UHSLMarcus 1:c1046d91bff7 29
UHSLMarcus 1:c1046d91bff7 30 fpp = filepp;
UHSLMarcus 1:c1046d91bff7 31
UHSLMarcus 1:c1046d91bff7 32 if (*filepp != NULL) {
UHSLMarcus 1:c1046d91bff7 33 if (check_bytes(*fpp, "RIFF", 4)) {
UHSLMarcus 1:c1046d91bff7 34 if (check_bytes(*fpp, "WAVE", 4, 8)) {
UHSLMarcus 1:c1046d91bff7 35 config.file_size = read_num(*fpp, 4, 4);
UHSLMarcus 1:c1046d91bff7 36
UHSLMarcus 1:c1046d91bff7 37 int chunk_pos = find_chunk(*fpp, "fmt ", config.file_size, 12);
UHSLMarcus 1:c1046d91bff7 38
UHSLMarcus 1:c1046d91bff7 39 if (chunk_pos != -1) {
UHSLMarcus 1:c1046d91bff7 40 config.format_tag = read_num(*fpp, 2, chunk_pos + 8);
UHSLMarcus 1:c1046d91bff7 41 config.channels = read_num(*fpp, 2, chunk_pos + 10);
UHSLMarcus 1:c1046d91bff7 42 config.samples_per_sec = read_num(*fpp, 4, chunk_pos + 12);
UHSLMarcus 1:c1046d91bff7 43 config.avg_bytes_per_sec = read_num(*fpp, 4, chunk_pos + 16);
UHSLMarcus 1:c1046d91bff7 44 config.block_align = read_num(*fpp, 2, chunk_pos + 20);
UHSLMarcus 1:c1046d91bff7 45 config.bits_per_sample = read_num(*fpp, 2, chunk_pos + 22);
UHSLMarcus 1:c1046d91bff7 46 } else success = WAV_READER_FO_NO_FMT;
UHSLMarcus 1:c1046d91bff7 47
UHSLMarcus 1:c1046d91bff7 48 chunk_pos = find_chunk(*fpp, "data", config.file_size, 12);
UHSLMarcus 1:c1046d91bff7 49
UHSLMarcus 1:c1046d91bff7 50 if (chunk_pos != -1) {
UHSLMarcus 1:c1046d91bff7 51 config.data_length = read_num(*fpp, 4, chunk_pos + 4);
UHSLMarcus 1:c1046d91bff7 52 config.data_pos = chunk_pos + 8;
UHSLMarcus 1:c1046d91bff7 53 reset();
UHSLMarcus 1:c1046d91bff7 54
UHSLMarcus 1:c1046d91bff7 55 } else success = success + WAV_READER_FO_NO_DATA;
UHSLMarcus 1:c1046d91bff7 56
UHSLMarcus 1:c1046d91bff7 57 if (success == 0) success = config.data_length;
UHSLMarcus 1:c1046d91bff7 58
UHSLMarcus 1:c1046d91bff7 59 } else success = WAV_READER_FO_NOT_WAV;
UHSLMarcus 1:c1046d91bff7 60 } else success = WAV_READER_FO_NOT_RIFF;
UHSLMarcus 1:c1046d91bff7 61 } else success = WAV_READER_FO_NULL_PTR;
UHSLMarcus 1:c1046d91bff7 62
UHSLMarcus 1:c1046d91bff7 63
UHSLMarcus 1:c1046d91bff7 64
UHSLMarcus 1:c1046d91bff7 65 return success;
UHSLMarcus 1:c1046d91bff7 66 }
UHSLMarcus 1:c1046d91bff7 67
UHSLMarcus 2:18fdd269b401 68 int WAV_Reader::read(int buff[], int size, int len) {
UHSLMarcus 1:c1046d91bff7 69 int data_left = config.data_length - _current_pos;
UHSLMarcus 2:18fdd269b401 70 int to_read = len*size;
UHSLMarcus 1:c1046d91bff7 71
UHSLMarcus 1:c1046d91bff7 72 if (to_read > data_left) {
UHSLMarcus 1:c1046d91bff7 73 if (data_left == 0 && _loop) {
UHSLMarcus 1:c1046d91bff7 74 reset();
UHSLMarcus 1:c1046d91bff7 75 } else {
UHSLMarcus 1:c1046d91bff7 76 to_read = data_left;
UHSLMarcus 1:c1046d91bff7 77 }
UHSLMarcus 1:c1046d91bff7 78 }
UHSLMarcus 1:c1046d91bff7 79
UHSLMarcus 2:18fdd269b401 80 char* bytes = new char[to_read];
UHSLMarcus 2:18fdd269b401 81 size_t read_bytes = fread(bytes, 1, to_read, *fpp);
UHSLMarcus 2:18fdd269b401 82 read_bytes -= read_bytes % size;
UHSLMarcus 2:18fdd269b401 83 int count = 0;
UHSLMarcus 2:18fdd269b401 84 for (int i = 0; i < read_bytes; i += size){
UHSLMarcus 2:18fdd269b401 85 buff[count++] = get_num(bytes+i, size);
UHSLMarcus 2:18fdd269b401 86 }
UHSLMarcus 2:18fdd269b401 87 delete[] bytes;
UHSLMarcus 2:18fdd269b401 88 move_read_position(read_bytes, _current_pos);
UHSLMarcus 1:c1046d91bff7 89
UHSLMarcus 2:18fdd269b401 90 to_read = len*size - read_bytes;
UHSLMarcus 1:c1046d91bff7 91 if (to_read > 0 && _loop) {
UHSLMarcus 2:18fdd269b401 92 read_bytes += read(buff + read_bytes/size, size, to_read);
UHSLMarcus 1:c1046d91bff7 93 }
UHSLMarcus 1:c1046d91bff7 94
UHSLMarcus 2:18fdd269b401 95 return read_bytes;
UHSLMarcus 1:c1046d91bff7 96 }
UHSLMarcus 1:c1046d91bff7 97
UHSLMarcus 1:c1046d91bff7 98 void WAV_Reader::reset() {
UHSLMarcus 1:c1046d91bff7 99 seek(0, 0);
UHSLMarcus 1:c1046d91bff7 100 }
UHSLMarcus 1:c1046d91bff7 101
UHSLMarcus 1:c1046d91bff7 102 bool WAV_Reader::loop() {
UHSLMarcus 1:c1046d91bff7 103 return _loop;
UHSLMarcus 1:c1046d91bff7 104 }
UHSLMarcus 1:c1046d91bff7 105
UHSLMarcus 1:c1046d91bff7 106 void WAV_Reader::loop(bool enable) {
UHSLMarcus 1:c1046d91bff7 107 _loop = enable;
UHSLMarcus 1:c1046d91bff7 108 }
UHSLMarcus 1:c1046d91bff7 109
UHSLMarcus 1:c1046d91bff7 110 void WAV_Reader::seek(int num, int start) {
UHSLMarcus 1:c1046d91bff7 111 if (start < 0) start = _current_pos;
UHSLMarcus 1:c1046d91bff7 112 move_read_position(num, start);
UHSLMarcus 1:c1046d91bff7 113 fseek(*fpp, _current_pos + config.data_pos, SEEK_SET);
UHSLMarcus 1:c1046d91bff7 114 }
UHSLMarcus 1:c1046d91bff7 115
UHSLMarcus 1:c1046d91bff7 116 uint16_t WAV_Reader::channels() {
UHSLMarcus 1:c1046d91bff7 117 return config.channels;
UHSLMarcus 1:c1046d91bff7 118 }
UHSLMarcus 1:c1046d91bff7 119
UHSLMarcus 1:c1046d91bff7 120 uint32_t WAV_Reader::samples_per_sec() {
UHSLMarcus 1:c1046d91bff7 121 return config.samples_per_sec;
UHSLMarcus 1:c1046d91bff7 122 }
UHSLMarcus 1:c1046d91bff7 123
UHSLMarcus 2:18fdd269b401 124 uint32_t WAV_Reader::bytes_per_sec() {
UHSLMarcus 2:18fdd269b401 125 return config.avg_bytes_per_sec;
UHSLMarcus 2:18fdd269b401 126 }
UHSLMarcus 2:18fdd269b401 127
UHSLMarcus 1:c1046d91bff7 128 uint16_t WAV_Reader::block_align() {
UHSLMarcus 1:c1046d91bff7 129 return config.block_align;
UHSLMarcus 1:c1046d91bff7 130 }
UHSLMarcus 1:c1046d91bff7 131
UHSLMarcus 1:c1046d91bff7 132 uint16_t WAV_Reader::bits_per_sample() {
UHSLMarcus 1:c1046d91bff7 133 return config.bits_per_sample;
UHSLMarcus 1:c1046d91bff7 134 }
UHSLMarcus 1:c1046d91bff7 135
UHSLMarcus 2:18fdd269b401 136 uint32_t WAV_Reader::data_length() {
UHSLMarcus 2:18fdd269b401 137 return config.data_length;
UHSLMarcus 2:18fdd269b401 138 }
UHSLMarcus 2:18fdd269b401 139
UHSLMarcus 1:c1046d91bff7 140 /** Private **/
UHSLMarcus 1:c1046d91bff7 141
UHSLMarcus 1:c1046d91bff7 142 int WAV_Reader::read_bytes(FILE *fp, char* out, int len_to_read, int start_off) {
UHSLMarcus 1:c1046d91bff7 143 fseek(fp, start_off, SEEK_SET);
UHSLMarcus 1:c1046d91bff7 144
UHSLMarcus 1:c1046d91bff7 145 for (int i = 0; i < len_to_read; i++) {
UHSLMarcus 1:c1046d91bff7 146 out[i] = fgetc(fp);
UHSLMarcus 1:c1046d91bff7 147 }
UHSLMarcus 1:c1046d91bff7 148
UHSLMarcus 1:c1046d91bff7 149 return len_to_read;
UHSLMarcus 1:c1046d91bff7 150
UHSLMarcus 1:c1046d91bff7 151 }
UHSLMarcus 1:c1046d91bff7 152
UHSLMarcus 1:c1046d91bff7 153 bool WAV_Reader::check_bytes(FILE *fp, char* check, int len, int start) {
UHSLMarcus 1:c1046d91bff7 154 bool success = false;
UHSLMarcus 1:c1046d91bff7 155 char extracted[len + 1];
UHSLMarcus 1:c1046d91bff7 156
UHSLMarcus 1:c1046d91bff7 157 read_bytes(fp, extracted, len, start);
UHSLMarcus 1:c1046d91bff7 158 extracted[len] = 0;
UHSLMarcus 1:c1046d91bff7 159
UHSLMarcus 1:c1046d91bff7 160 success = strcmp(extracted, check) == 0;
UHSLMarcus 1:c1046d91bff7 161
UHSLMarcus 1:c1046d91bff7 162 return success;
UHSLMarcus 1:c1046d91bff7 163 }
UHSLMarcus 1:c1046d91bff7 164
UHSLMarcus 1:c1046d91bff7 165 uint32_t WAV_Reader::read_num(FILE *fp, int len, int start) {
UHSLMarcus 1:c1046d91bff7 166 char extracted[len];
UHSLMarcus 1:c1046d91bff7 167 read_bytes(fp, extracted, len, start);
UHSLMarcus 1:c1046d91bff7 168
UHSLMarcus 1:c1046d91bff7 169 return get_num(extracted, len);
UHSLMarcus 1:c1046d91bff7 170 }
UHSLMarcus 1:c1046d91bff7 171
UHSLMarcus 1:c1046d91bff7 172 uint32_t WAV_Reader::get_num(char input[], int byte_count) {
UHSLMarcus 1:c1046d91bff7 173
UHSLMarcus 1:c1046d91bff7 174 uint32_t output = 0;
UHSLMarcus 1:c1046d91bff7 175 for (int i = 0; i < byte_count; i++) {
UHSLMarcus 2:18fdd269b401 176 // numbers are stored least significant byte. So reverse and add to find the number
UHSLMarcus 1:c1046d91bff7 177 output += input[i] << (i * 8);
UHSLMarcus 1:c1046d91bff7 178 }
UHSLMarcus 1:c1046d91bff7 179
UHSLMarcus 1:c1046d91bff7 180 return output;
UHSLMarcus 1:c1046d91bff7 181
UHSLMarcus 1:c1046d91bff7 182 }
UHSLMarcus 1:c1046d91bff7 183
UHSLMarcus 1:c1046d91bff7 184 int WAV_Reader::find_chunk(FILE *fp, char* check, int max_len, int start) {
UHSLMarcus 1:c1046d91bff7 185 int result = -1;
UHSLMarcus 2:18fdd269b401 186
UHSLMarcus 1:c1046d91bff7 187 int pos = start;
UHSLMarcus 1:c1046d91bff7 188
UHSLMarcus 1:c1046d91bff7 189 while ((pos + 8) < max_len && result == -1) {
UHSLMarcus 1:c1046d91bff7 190 if (check_bytes(fp, check, 4, pos)) result = pos;
UHSLMarcus 1:c1046d91bff7 191 else pos += read_num(fp, 4, pos + 4) + 8;
UHSLMarcus 1:c1046d91bff7 192 }
UHSLMarcus 1:c1046d91bff7 193
UHSLMarcus 1:c1046d91bff7 194 return result;
UHSLMarcus 1:c1046d91bff7 195
UHSLMarcus 1:c1046d91bff7 196 }
UHSLMarcus 1:c1046d91bff7 197
UHSLMarcus 1:c1046d91bff7 198 int WAV_Reader::move_read_position(int count, int start) {
UHSLMarcus 1:c1046d91bff7 199 _current_pos = start + count;
UHSLMarcus 1:c1046d91bff7 200 if (_current_pos > config.data_length) {
UHSLMarcus 1:c1046d91bff7 201 if (loop()) _current_pos %= config.data_length;
UHSLMarcus 1:c1046d91bff7 202 else _current_pos = config.data_length;
UHSLMarcus 1:c1046d91bff7 203 }
UHSLMarcus 1:c1046d91bff7 204
UHSLMarcus 1:c1046d91bff7 205 return _current_pos;
UHSLMarcus 1:c1046d91bff7 206 }