Decode Wav files

Committer:
UHSLMarcus
Date:
Fri Feb 24 15:18:01 2017 +0000
Revision:
1:c1046d91bff7
Child:
2:18fdd269b401
Reads from simple wav files

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 1:c1046d91bff7 68 int WAV_Reader::read(char buff[], int len) {
UHSLMarcus 1:c1046d91bff7 69 int data_left = config.data_length - _current_pos;
UHSLMarcus 1:c1046d91bff7 70 int to_read = len;
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 1:c1046d91bff7 80 size_t ret = fread(buff, 1, to_read, *fpp);
UHSLMarcus 1:c1046d91bff7 81 move_read_position(ret, _current_pos);
UHSLMarcus 1:c1046d91bff7 82
UHSLMarcus 1:c1046d91bff7 83 to_read = len - ret;
UHSLMarcus 1:c1046d91bff7 84 if (to_read > 0 && _loop) {
UHSLMarcus 1:c1046d91bff7 85 ret += read(buff + ret, to_read);
UHSLMarcus 1:c1046d91bff7 86 }
UHSLMarcus 1:c1046d91bff7 87
UHSLMarcus 1:c1046d91bff7 88 return ret;
UHSLMarcus 1:c1046d91bff7 89 }
UHSLMarcus 1:c1046d91bff7 90
UHSLMarcus 1:c1046d91bff7 91 void WAV_Reader::reset() {
UHSLMarcus 1:c1046d91bff7 92 seek(0, 0);
UHSLMarcus 1:c1046d91bff7 93 }
UHSLMarcus 1:c1046d91bff7 94
UHSLMarcus 1:c1046d91bff7 95 bool WAV_Reader::loop() {
UHSLMarcus 1:c1046d91bff7 96 return _loop;
UHSLMarcus 1:c1046d91bff7 97 }
UHSLMarcus 1:c1046d91bff7 98
UHSLMarcus 1:c1046d91bff7 99 void WAV_Reader::loop(bool enable) {
UHSLMarcus 1:c1046d91bff7 100 _loop = enable;
UHSLMarcus 1:c1046d91bff7 101 }
UHSLMarcus 1:c1046d91bff7 102
UHSLMarcus 1:c1046d91bff7 103 void WAV_Reader::seek(int num, int start) {
UHSLMarcus 1:c1046d91bff7 104 if (start < 0) start = _current_pos;
UHSLMarcus 1:c1046d91bff7 105 move_read_position(num, start);
UHSLMarcus 1:c1046d91bff7 106 fseek(*fpp, _current_pos + config.data_pos, SEEK_SET);
UHSLMarcus 1:c1046d91bff7 107 }
UHSLMarcus 1:c1046d91bff7 108
UHSLMarcus 1:c1046d91bff7 109 uint16_t WAV_Reader::channels() {
UHSLMarcus 1:c1046d91bff7 110 return config.channels;
UHSLMarcus 1:c1046d91bff7 111 }
UHSLMarcus 1:c1046d91bff7 112
UHSLMarcus 1:c1046d91bff7 113 uint32_t WAV_Reader::samples_per_sec() {
UHSLMarcus 1:c1046d91bff7 114 return config.samples_per_sec;
UHSLMarcus 1:c1046d91bff7 115 }
UHSLMarcus 1:c1046d91bff7 116
UHSLMarcus 1:c1046d91bff7 117 uint16_t WAV_Reader::block_align() {
UHSLMarcus 1:c1046d91bff7 118 return config.block_align;
UHSLMarcus 1:c1046d91bff7 119 }
UHSLMarcus 1:c1046d91bff7 120
UHSLMarcus 1:c1046d91bff7 121 uint16_t WAV_Reader::bits_per_sample() {
UHSLMarcus 1:c1046d91bff7 122 return config.bits_per_sample;
UHSLMarcus 1:c1046d91bff7 123 }
UHSLMarcus 1:c1046d91bff7 124
UHSLMarcus 1:c1046d91bff7 125 /** Private **/
UHSLMarcus 1:c1046d91bff7 126
UHSLMarcus 1:c1046d91bff7 127 int WAV_Reader::read_bytes(FILE *fp, char* out, int len_to_read, int start_off) {
UHSLMarcus 1:c1046d91bff7 128 fseek(fp, start_off, SEEK_SET);
UHSLMarcus 1:c1046d91bff7 129
UHSLMarcus 1:c1046d91bff7 130 for (int i = 0; i < len_to_read; i++) {
UHSLMarcus 1:c1046d91bff7 131 out[i] = fgetc(fp);
UHSLMarcus 1:c1046d91bff7 132 }
UHSLMarcus 1:c1046d91bff7 133
UHSLMarcus 1:c1046d91bff7 134 return len_to_read;
UHSLMarcus 1:c1046d91bff7 135
UHSLMarcus 1:c1046d91bff7 136 }
UHSLMarcus 1:c1046d91bff7 137
UHSLMarcus 1:c1046d91bff7 138 bool WAV_Reader::check_bytes(FILE *fp, char* check, int len, int start) {
UHSLMarcus 1:c1046d91bff7 139 bool success = false;
UHSLMarcus 1:c1046d91bff7 140 char extracted[len + 1];
UHSLMarcus 1:c1046d91bff7 141
UHSLMarcus 1:c1046d91bff7 142 read_bytes(fp, extracted, len, start);
UHSLMarcus 1:c1046d91bff7 143 extracted[len] = 0;
UHSLMarcus 1:c1046d91bff7 144
UHSLMarcus 1:c1046d91bff7 145 success = strcmp(extracted, check) == 0;
UHSLMarcus 1:c1046d91bff7 146
UHSLMarcus 1:c1046d91bff7 147 return success;
UHSLMarcus 1:c1046d91bff7 148 }
UHSLMarcus 1:c1046d91bff7 149
UHSLMarcus 1:c1046d91bff7 150 uint32_t WAV_Reader::read_num(FILE *fp, int len, int start) {
UHSLMarcus 1:c1046d91bff7 151 char extracted[len];
UHSLMarcus 1:c1046d91bff7 152 read_bytes(fp, extracted, len, start);
UHSLMarcus 1:c1046d91bff7 153
UHSLMarcus 1:c1046d91bff7 154 return get_num(extracted, len);
UHSLMarcus 1:c1046d91bff7 155 }
UHSLMarcus 1:c1046d91bff7 156
UHSLMarcus 1:c1046d91bff7 157 uint32_t WAV_Reader::get_num(char input[], int byte_count) {
UHSLMarcus 1:c1046d91bff7 158
UHSLMarcus 1:c1046d91bff7 159 uint32_t output = 0;
UHSLMarcus 1:c1046d91bff7 160 for (int i = 0; i < byte_count; i++) {
UHSLMarcus 1:c1046d91bff7 161 // numbers are stored least significant byte in the WAV header. So reverse and add to find the number
UHSLMarcus 1:c1046d91bff7 162 output += input[i] << (i * 8);
UHSLMarcus 1:c1046d91bff7 163 }
UHSLMarcus 1:c1046d91bff7 164
UHSLMarcus 1:c1046d91bff7 165 return output;
UHSLMarcus 1:c1046d91bff7 166
UHSLMarcus 1:c1046d91bff7 167 }
UHSLMarcus 1:c1046d91bff7 168
UHSLMarcus 1:c1046d91bff7 169 int WAV_Reader::find_chunk(FILE *fp, char* check, int max_len, int start) {
UHSLMarcus 1:c1046d91bff7 170 int result = -1;
UHSLMarcus 1:c1046d91bff7 171 char extracted[5];
UHSLMarcus 1:c1046d91bff7 172 int pos = start;
UHSLMarcus 1:c1046d91bff7 173
UHSLMarcus 1:c1046d91bff7 174 while ((pos + 8) < max_len && result == -1) {
UHSLMarcus 1:c1046d91bff7 175 if (check_bytes(fp, check, 4, pos)) result = pos;
UHSLMarcus 1:c1046d91bff7 176 else pos += read_num(fp, 4, pos + 4) + 8;
UHSLMarcus 1:c1046d91bff7 177 }
UHSLMarcus 1:c1046d91bff7 178
UHSLMarcus 1:c1046d91bff7 179 return result;
UHSLMarcus 1:c1046d91bff7 180
UHSLMarcus 1:c1046d91bff7 181 }
UHSLMarcus 1:c1046d91bff7 182
UHSLMarcus 1:c1046d91bff7 183 int WAV_Reader::move_read_position(int count, int start) {
UHSLMarcus 1:c1046d91bff7 184 _current_pos = start + count;
UHSLMarcus 1:c1046d91bff7 185 if (_current_pos > config.data_length) {
UHSLMarcus 1:c1046d91bff7 186 if (loop()) _current_pos %= config.data_length;
UHSLMarcus 1:c1046d91bff7 187 else _current_pos = config.data_length;
UHSLMarcus 1:c1046d91bff7 188 }
UHSLMarcus 1:c1046d91bff7 189
UHSLMarcus 1:c1046d91bff7 190 return _current_pos;
UHSLMarcus 1:c1046d91bff7 191 }