5 #include "rapidjson/stringbuffer.h"
17 unsigned char riff[4];
19 unsigned char wave[4];
20 unsigned char fmt_chunk_marker[4];
28 unsigned char data_chunk_header[4];
35 namespace datastructure {
102 const bool debug =
false;
108 vector<AudioChannel> channels;
110 union ShortByteUnion {
111 signed short asShort;
112 unsigned char asBytes[2];
123 AudioClip(
int sampleCount,
int numChannels,
int sampleBits,
int sampleRate) {
124 if (sampleCount > 1000000000) {
125 throw "sampleCount must be less than 1 million";
128 if (sampleBits != 8 && sampleBits != 16 && sampleBits != 24 && sampleBits != 32) {
129 throw "sampleBits must be either 8, 16, 24, or 32";
132 if (numChannels <= 0) {
133 throw "numChannels should be positive";
136 if (sampleRate <= 0) {
137 throw "sampleRate should be positive";
140 this->sampleCount = sampleCount;
141 this->numChannels = numChannels;
142 this->channels = vector<AudioChannel>();
144 for (
int i = 0; i < numChannels; i++) {
147 for (
int j = 0; j < sampleCount; j++) {
148 this->channels[i].setSample(j, 0);
152 this->sampleRate = sampleRate;
153 this->sampleBits = sampleBits;
167 parseWaveFile (wave_file);
174 int len = numChannels * sampleCount * (sampleBits / 8);
175 std::vector<BYTE> byteBuff;
177 int checkSampleBits = sampleBits;
179 for (
int i = 0; i < sampleCount; i++) {
180 for (
int c = 0; c < numChannels; c++) {
181 int num = getSample(c, i);
183 if (this->sampleBits == 8) {
184 byteBuff.push_back(num & 0x000000FF);
186 else if (this->sampleBits == 16) {
188 sbu.asShort = (uint16_t)num;
189 byteBuff.push_back(sbu.asBytes[0]);
190 byteBuff.push_back(sbu.asBytes[1]);
192 else if (this->sampleBits == 32 || this->sampleBits == 24) {
194 int minmax = (int)((pow(2, sampleBits) / 2) - 1);
195 int minmax16 = (int)((pow(2, 16) / 2) - 1);
197 num = (int)((num / (
float)minmax) * minmax16) & 0xFFFF;
200 sbu.asShort = (uint16_t)num;
201 byteBuff.push_back(sbu.asBytes[0]);
202 byteBuff.push_back(sbu.asBytes[1]);
203 checkSampleBits = 16;
225 return this->numChannels;
233 return this->sampleRate;
244 return this->sampleCount;
261 return this->sampleBits;
273 int getSample(
int channelIndex,
int sampleIndex)
const {
274 return channels.at(channelIndex).getSample(sampleIndex);
284 void setSample(
int channelIndex,
int sampleIndex,
int value) {
285 if (value >= pow(2, getSampleBits() - 1) ||
286 value < -pow(2, getSampleBits() - 1))
287 throw "Audio value Out of Bound";
289 channels[channelIndex].setSample(sampleIndex, value);
300 void parseWaveFile (
const string & wave_file) {
305 infile.open (wave_file.c_str(), ios::binary | ios::in);
307 throw "Could not open " + wave_file;
311 WaveHeader wave_header = readWaveHeader(infile);
313 long size_of_each_sample = (wave_header.
channels *
317 if (this->sampleCount > 1000000000) {
318 throw "sampleCount must be less than 1 million";
323 for (
int i = 0; i < numChannels; i++) {
324 this->channels.push_back(
AudioChannel(this->sampleCount));
330 char data_buffer[size_of_each_sample];
331 int size_is_correct =
true;
335 long bytes_in_each_channel = (size_of_each_sample / wave_header.
channels);
336 if ((bytes_in_each_channel * wave_header.
channels) != size_of_each_sample) {
337 cout <<
"Error: Incorrect chunk size.. " << bytes_in_each_channel
338 <<
", " << wave_header.
channels <<
", " << size_of_each_sample <<
"\n";
339 size_is_correct =
false;
342 if (size_is_correct) {
345 long high_limit = 0
l;
357 low_limit = -16777216;
358 high_limit = 16777215;
361 low_limit = -2147483648;
362 high_limit = 2147483647;
365 for (
int sample = 0; sample < this->sampleCount;
368 if (!infile.fail()) {
369 for (
int ch = 0; ch < wave_header.
channels;
372 infile.read(data_buffer, bytes_in_each_channel);
375 switch (bytes_in_each_channel) {
377 amplitude = data_buffer[0] & 0x00ff;
382 (data_buffer[0] & 0x00ff) |
383 (data_buffer[1] << 8);
387 (data_buffer[0] & 0x00ff) |
388 ((data_buffer[1] & 0x00ff) << 8) |
389 (data_buffer[2] << 16);
393 (data_buffer[0] & 0x00ff) |
394 ((data_buffer[1] & 0x00ff) << 8) |
395 ((data_buffer[2] & 0x00ff) << 16) |
396 (data_buffer[3] << 24);
399 this->setSample(ch, sample, amplitude);
403 cout <<
"Error reading file\n.";
416 WaveHeader readWaveHeader(ifstream& infile) {
419 WaveHeader wave_header;
421 infile.read ((
char *)wave_header.riff, 4);
423 if (wave_header.riff[0] !=
'R' ||
424 wave_header.riff[1] !=
'I' ||
425 wave_header.riff[2] !=
'F' ||
426 wave_header.riff[3] !=
'F')
427 throw "malformed RIFF header";
429 unsigned char *buffer =
new unsigned char[4];
430 infile.read ((
char*) buffer, 4);
433 wave_header.
overall_size = buffer[0] | (buffer[1] << 8) |
434 (buffer[2] << 16) | (buffer[3] << 24);
437 std::cout <<
"overall size: " << wave_header.overall_size << std::endl;
439 infile.read ((
char*) wave_header.wave, 4);
441 if (wave_header.wave[0] !=
'W' ||
442 wave_header.wave[1] !=
'A' ||
443 wave_header.wave[2] !=
'V' ||
444 wave_header.wave[3] !=
'E')
445 throw "format is not WAVE";
447 infile.read ((
char*) wave_header.fmt_chunk_marker, 4);
448 if (wave_header.fmt_chunk_marker[0] !=
'f' ||
449 wave_header.fmt_chunk_marker[1] !=
'm' ||
450 wave_header.fmt_chunk_marker[2] !=
't' ||
451 wave_header.fmt_chunk_marker[3] !=
' ')
452 throw "malformed wave file";
454 infile.read ((
char *) buffer, 4);
455 wave_header.length_of_fmt = buffer[0] | (buffer[1] << 8) |
456 (buffer[2] << 16) | (buffer[3] << 24);
459 std::cout <<
"length of format: " << wave_header.length_of_fmt << std::endl;
461 char *buffer2 =
new char[2];
462 infile.read (buffer2, 2);
463 wave_header.format_type = buffer2[0] | (buffer2[1] << 8);
465 string format_name =
"";
466 switch (wave_header.format_type) {
471 format_name =
"A-law";
474 format_name =
"Mu-law";
477 throw "unsupported format";
481 infile.read (buffer2, 2);
482 wave_header.channels = buffer2[0] | (buffer2[1] << 8);
483 this->numChannels = wave_header.channels;
486 std::cout <<
"numChannels: " << numChannels << std::endl;
488 infile.read ((
char *) buffer, 4);
489 wave_header.sample_rate = buffer[0] | (buffer[1] << 8) |
490 (buffer[2] << 16) | (buffer[3] << 24);
491 this->sampleRate = wave_header.sample_rate;
494 std::cout <<
"sampleRate: " << sampleRate << std::endl;
496 infile.read ((
char *) buffer, 4);
497 wave_header.byterate = buffer[0] | (buffer[1] << 8) |
498 (buffer[2] << 16) | (buffer[3] << 24);
501 std::cout <<
"byte rate: " << wave_header.byterate << std::endl;
503 infile.read (buffer2, 2);
504 wave_header.block_align = buffer2[0] | (buffer2[1] << 8);
506 infile.read (buffer2, 2);
507 wave_header.bits_per_sample = buffer2[0] | (buffer2[1] << 8);
509 this->sampleBits = wave_header.bits_per_sample;
512 std::cout <<
"sample Bits: " << sampleBits << std::endl;
514 if (wave_header.byterate !=
515 wave_header.sample_rate * wave_header.channels * wave_header.bits_per_sample / 8)
516 throw "malformed wave file";
521 bool data_chunk_found =
false;
522 while (!data_chunk_found) {
523 infile.read ((
char *)wave_header.data_chunk_header, 4);
525 infile.read ((
char *) buffer, 4);
526 wave_header.data_size = buffer[0] | (buffer[1] << 8) |
527 (buffer[2] << 16) | (buffer[3] << 24);
529 if (wave_header.data_chunk_header[0] !=
'd' ||
530 wave_header.data_chunk_header[1] !=
'a' ||
531 wave_header.data_chunk_header[2] !=
't' ||
532 wave_header.data_chunk_header[3] !=
'a') {
534 int padding = (wave_header.data_size % 2 ? 0 : 1);
535 infile.ignore(wave_header.data_size + padding);
538 data_chunk_found =
true;
542 long num_samples = (8 * wave_header.data_size) /
543 (wave_header.channels * wave_header.bits_per_sample);
544 this->sampleCount = num_samples;
547 std::cout <<
"sample Count: " << this->sampleCount << std::endl;
549 long size_of_each_sample = (wave_header.channels *
550 wave_header.bits_per_sample) / 8;
556 throw "malformed RIFF header";
class that represents an audio channel.
Definition: AudioChannel.h:9
This class provides support for reading, modifying, and playing audio waveforms.
Definition: AudioClip.h:101
virtual const string getDStype() const override
Definition: AudioClip.h:156
int getSample(int channelIndex, int sampleIndex) const
access a particular sample
Definition: AudioClip.h:273
AudioClip(const string &wave_file)
create an audio clip from a File
Definition: AudioClip.h:166
int getSampleRate() const
returns the sampling rate of the clip
Definition: AudioClip.h:232
virtual const string getDataStructureRepresentation() const override final
Definition: AudioClip.h:171
AudioClip(int sampleCount, int numChannels, int sampleBits, int sampleRate)
create an audio clip
Definition: AudioClip.h:123
void setSample(int channelIndex, int sampleIndex, int value)
change a particular sample
Definition: AudioClip.h:284
int getSampleCount() const
returns the number of samples in the clip
Definition: AudioClip.h:243
int getSampleBits() const
returns the sampling depth.
Definition: AudioClip.h:260
int getNumChannels() const
returns the number of channels of the clip
Definition: AudioClip.h:224
This is the superclass of all data structure types in BRIDGES.
Definition: DataStructure.h:73
std::string JSONencode(const T &d)
Definition: JSONutil.h:36
string encode(BYTE const *buf, unsigned int bufLen)
Definition: base64.h:56
these methods convert byte arrays in to base64 codes and are used in BRIDGES to represent the color a...
Definition: alltypes.h:4
const string COLON
Definition: DataStructure.h:51
const string COMMA
Definition: DataStructure.h:50
const string CLOSE_CURLY
Definition: DataStructure.h:53
const string QUOTE
Definition: DataStructure.h:49