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;
265 if (bit_depth == 8 || bit_depth == 16 || bit_depth == 24 || bit_depth == 32)
266 this->sampleBits = bit_depth;
268 cerr <<
"Bit rate must 8,16,24 or 32!" <<
"\n";
280 int getSample(
int channelIndex,
int sampleIndex)
const {
281 return channels.at(channelIndex).getSample(sampleIndex);
291 void setSample(
int channelIndex,
int sampleIndex,
int value) {
292 if (value >= pow(2, getSampleBits() - 1) ||
293 value < -pow(2, getSampleBits() - 1))
294 throw "Audio value Out of Bound";
296 channels[channelIndex].setSample(sampleIndex, value);
307 void parseWaveFile (
const string & wave_file) {
312 infile.open (wave_file.c_str(), ios::binary | ios::in);
314 throw "Could not open " + wave_file;
318 WaveHeader wave_header = readWaveHeader(infile);
320 long size_of_each_sample = (wave_header.
channels *
324 if (this->sampleCount > 1000000000) {
325 throw "sampleCount must be less than 1 million";
330 for (
int i = 0; i < numChannels; i++) {
331 this->channels.push_back(
AudioChannel(this->sampleCount));
337 char data_buffer[size_of_each_sample];
338 int size_is_correct =
true;
342 long bytes_in_each_channel = (size_of_each_sample / wave_header.
channels);
343 if ((bytes_in_each_channel * wave_header.
channels) != size_of_each_sample) {
344 cout <<
"Error: Incorrect chunk size.. " << bytes_in_each_channel
345 <<
", " << wave_header.
channels <<
", " << size_of_each_sample <<
"\n";
346 size_is_correct =
false;
349 if (size_is_correct) {
352 long high_limit = 0
l;
364 low_limit = -16777216;
365 high_limit = 16777215;
368 low_limit = -2147483648;
369 high_limit = 2147483647;
372 for (
int sample = 0; sample < this->sampleCount;
375 if (!infile.fail()) {
376 for (
int ch = 0; ch < wave_header.
channels;
379 infile.read(data_buffer, bytes_in_each_channel);
382 switch (bytes_in_each_channel) {
384 amplitude = data_buffer[0] & 0x00ff;
389 (data_buffer[0] & 0x00ff) |
390 (data_buffer[1] << 8);
394 (data_buffer[0] & 0x00ff) |
395 ((data_buffer[1] & 0x00ff) << 8) |
396 (data_buffer[2] << 16);
400 (data_buffer[0] & 0x00ff) |
401 ((data_buffer[1] & 0x00ff) << 8) |
402 ((data_buffer[2] & 0x00ff) << 16) |
403 (data_buffer[3] << 24);
406 this->setSample(ch, sample, amplitude);
410 cout <<
"Error reading file\n.";
423 WaveHeader readWaveHeader(ifstream& infile) {
426 WaveHeader wave_header;
428 infile.read ((
char *)wave_header.riff, 4);
430 if (wave_header.riff[0] !=
'R' ||
431 wave_header.riff[1] !=
'I' ||
432 wave_header.riff[2] !=
'F' ||
433 wave_header.riff[3] !=
'F')
434 throw "malformed RIFF header";
436 unsigned char *buffer =
new unsigned char[4];
437 infile.read ((
char*) buffer, 4);
440 wave_header.
overall_size = buffer[0] | (buffer[1] << 8) |
441 (buffer[2] << 16) | (buffer[3] << 24);
444 std::cout <<
"overall size: " << wave_header.overall_size << std::endl;
446 infile.read ((
char*) wave_header.wave, 4);
448 if (wave_header.wave[0] !=
'W' ||
449 wave_header.wave[1] !=
'A' ||
450 wave_header.wave[2] !=
'V' ||
451 wave_header.wave[3] !=
'E')
452 throw "format is not WAVE";
454 infile.read ((
char*) wave_header.fmt_chunk_marker, 4);
455 if (wave_header.fmt_chunk_marker[0] !=
'f' ||
456 wave_header.fmt_chunk_marker[1] !=
'm' ||
457 wave_header.fmt_chunk_marker[2] !=
't' ||
458 wave_header.fmt_chunk_marker[3] !=
' ')
459 throw "malformed wave file";
461 infile.read ((
char *) buffer, 4);
462 wave_header.length_of_fmt = buffer[0] | (buffer[1] << 8) |
463 (buffer[2] << 16) | (buffer[3] << 24);
466 std::cout <<
"length of format: " << wave_header.length_of_fmt << std::endl;
468 char *buffer2 =
new char[2];
469 infile.read (buffer2, 2);
470 wave_header.format_type = buffer2[0] | (buffer2[1] << 8);
472 string format_name =
"";
473 switch (wave_header.format_type) {
478 format_name =
"A-law";
481 format_name =
"Mu-law";
484 throw "unsupported format";
488 infile.read (buffer2, 2);
489 wave_header.channels = buffer2[0] | (buffer2[1] << 8);
490 this->numChannels = wave_header.channels;
493 std::cout <<
"numChannels: " << numChannels << std::endl;
495 infile.read ((
char *) buffer, 4);
496 wave_header.sample_rate = buffer[0] | (buffer[1] << 8) |
497 (buffer[2] << 16) | (buffer[3] << 24);
498 this->sampleRate = wave_header.sample_rate;
501 std::cout <<
"sampleRate: " << sampleRate << std::endl;
503 infile.read ((
char *) buffer, 4);
504 wave_header.byterate = buffer[0] | (buffer[1] << 8) |
505 (buffer[2] << 16) | (buffer[3] << 24);
508 std::cout <<
"byte rate: " << wave_header.byterate << std::endl;
510 infile.read (buffer2, 2);
511 wave_header.block_align = buffer2[0] | (buffer2[1] << 8);
513 infile.read (buffer2, 2);
514 wave_header.bits_per_sample = buffer2[0] | (buffer2[1] << 8);
516 this->sampleBits = wave_header.bits_per_sample;
519 std::cout <<
"sample Bits: " << sampleBits << std::endl;
521 if (wave_header.byterate !=
522 wave_header.sample_rate * wave_header.channels * wave_header.bits_per_sample / 8)
523 throw "malformed wave file";
528 bool data_chunk_found =
false;
529 while (!data_chunk_found) {
530 infile.read ((
char *)wave_header.data_chunk_header, 4);
532 infile.read ((
char *) buffer, 4);
533 wave_header.data_size = buffer[0] | (buffer[1] << 8) |
534 (buffer[2] << 16) | (buffer[3] << 24);
536 if (wave_header.data_chunk_header[0] !=
'd' ||
537 wave_header.data_chunk_header[1] !=
'a' ||
538 wave_header.data_chunk_header[2] !=
't' ||
539 wave_header.data_chunk_header[3] !=
'a') {
541 int padding = (wave_header.data_size % 2 ? 0 : 1);
542 infile.ignore(wave_header.data_size + padding);
545 data_chunk_found =
true;
549 long num_samples = (8 * wave_header.data_size) /
550 (wave_header.channels * wave_header.bits_per_sample);
551 this->sampleCount = num_samples;
554 std::cout <<
"sample Count: " << this->sampleCount << std::endl;
556 long size_of_each_sample = (wave_header.channels *
557 wave_header.bits_per_sample) / 8;
563 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
void setSampleBits(int bit_depth)
Definition: AudioClip.h:264
virtual const string getDStype() const override
Definition: AudioClip.h:156
int getSample(int channelIndex, int sampleIndex) const
access a particular sample
Definition: AudioClip.h:280
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:291
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:74
std::string JSONencode(const T &d)
Definition: JSONutil.h:38
string encode(BYTE const *buf, unsigned int bufLen)
Definition: base64.h:56
Support for drawing Bar charts.
Definition: alltypes.h:4
const string COLON
Definition: DataStructure.h:52
const string COMMA
Definition: DataStructure.h:51
const string CLOSE_CURLY
Definition: DataStructure.h:54
const string QUOTE
Definition: DataStructure.h:50