Decode Wav files
WAV_Reader.cpp
- Committer:
- UHSLMarcus
- Date:
- 2017-02-24
- Revision:
- 1:c1046d91bff7
- Child:
- 2:18fdd269b401
File content as of revision 1:c1046d91bff7:
/* * WAV_Reader.cpp * * Created on: 23 Feb 2017 * Author: ML15AAF */ #include <WAV_Reader.h> WAV_Reader::Config::Config() { format_tag = 0; channels = 0; samples_per_sec = 0; avg_bytes_per_sec = 0; block_align = 0; bits_per_sample = 0; data_pos = 0; data_length = 0; file_size = 0; } WAV_Reader::WAV_Reader() : fpp(NULL), _current_pos(0), _loop(false) { } int WAV_Reader::open(FILE **filepp) { int success = 0; fpp = filepp; if (*filepp != NULL) { if (check_bytes(*fpp, "RIFF", 4)) { if (check_bytes(*fpp, "WAVE", 4, 8)) { config.file_size = read_num(*fpp, 4, 4); int chunk_pos = find_chunk(*fpp, "fmt ", config.file_size, 12); if (chunk_pos != -1) { config.format_tag = read_num(*fpp, 2, chunk_pos + 8); config.channels = read_num(*fpp, 2, chunk_pos + 10); config.samples_per_sec = read_num(*fpp, 4, chunk_pos + 12); config.avg_bytes_per_sec = read_num(*fpp, 4, chunk_pos + 16); config.block_align = read_num(*fpp, 2, chunk_pos + 20); config.bits_per_sample = read_num(*fpp, 2, chunk_pos + 22); } else success = WAV_READER_FO_NO_FMT; chunk_pos = find_chunk(*fpp, "data", config.file_size, 12); if (chunk_pos != -1) { config.data_length = read_num(*fpp, 4, chunk_pos + 4); config.data_pos = chunk_pos + 8; reset(); } else success = success + WAV_READER_FO_NO_DATA; if (success == 0) success = config.data_length; } else success = WAV_READER_FO_NOT_WAV; } else success = WAV_READER_FO_NOT_RIFF; } else success = WAV_READER_FO_NULL_PTR; return success; } int WAV_Reader::read(char buff[], int len) { int data_left = config.data_length - _current_pos; int to_read = len; if (to_read > data_left) { if (data_left == 0 && _loop) { reset(); } else { to_read = data_left; } } size_t ret = fread(buff, 1, to_read, *fpp); move_read_position(ret, _current_pos); to_read = len - ret; if (to_read > 0 && _loop) { ret += read(buff + ret, to_read); } return ret; } void WAV_Reader::reset() { seek(0, 0); } bool WAV_Reader::loop() { return _loop; } void WAV_Reader::loop(bool enable) { _loop = enable; } void WAV_Reader::seek(int num, int start) { if (start < 0) start = _current_pos; move_read_position(num, start); fseek(*fpp, _current_pos + config.data_pos, SEEK_SET); } uint16_t WAV_Reader::channels() { return config.channels; } uint32_t WAV_Reader::samples_per_sec() { return config.samples_per_sec; } uint16_t WAV_Reader::block_align() { return config.block_align; } uint16_t WAV_Reader::bits_per_sample() { return config.bits_per_sample; } /** Private **/ int WAV_Reader::read_bytes(FILE *fp, char* out, int len_to_read, int start_off) { fseek(fp, start_off, SEEK_SET); for (int i = 0; i < len_to_read; i++) { out[i] = fgetc(fp); } return len_to_read; } bool WAV_Reader::check_bytes(FILE *fp, char* check, int len, int start) { bool success = false; char extracted[len + 1]; read_bytes(fp, extracted, len, start); extracted[len] = 0; success = strcmp(extracted, check) == 0; return success; } uint32_t WAV_Reader::read_num(FILE *fp, int len, int start) { char extracted[len]; read_bytes(fp, extracted, len, start); return get_num(extracted, len); } uint32_t WAV_Reader::get_num(char input[], int byte_count) { uint32_t output = 0; for (int i = 0; i < byte_count; i++) { // numbers are stored least significant byte in the WAV header. So reverse and add to find the number output += input[i] << (i * 8); } return output; } int WAV_Reader::find_chunk(FILE *fp, char* check, int max_len, int start) { int result = -1; char extracted[5]; int pos = start; while ((pos + 8) < max_len && result == -1) { if (check_bytes(fp, check, 4, pos)) result = pos; else pos += read_num(fp, 4, pos + 4) + 8; } return result; } int WAV_Reader::move_read_position(int count, int start) { _current_pos = start + count; if (_current_pos > config.data_length) { if (loop()) _current_pos %= config.data_length; else _current_pos = config.data_length; } return _current_pos; }