// file: $isip/class/mmedia/AudioFile/adf_12.cc // version: $Id: adf_12.cc 9327 2003-10-27 17:19:32Z parihar $ // // isip include files // #include "AudioFile.h" // method: readAFData // // arguments: // Vector& data: (output) the audio data // int32 ctag: (input) the channel to read // int32 start_samp: (input) the start sample of the audio data // int32 num_samp: (input) number of samples // // return: the number of samples read // // this method gets data from the audio file in a format supported by // SGI's audiofile library and put each channel data into VectorFloat // int32 AudioFile::readAFData(Vector& data_a, int32 ctag_a, int32 start_samp_a, int32 num_samp_a) { #ifdef HAVE_AUDIOFILE // formats supported by SGI's audiofile library // if ((file_format_d != AIFF) && (file_format_d != AIFFC) && (file_format_d != AU) && (file_format_d != BICSF) && (file_format_d != WAV)) { Error::handle(name(), L"readAFData", ERR_TYPE, __FILE__, __LINE__); return -1; } // take care of the partial frame condition // int32 total_samples = getNumSamples() * num_channels_d; if ((num_samp_a == ALL_SAMPLES) || ((start_samp_a + num_samp_a) > total_samples)) { // set the number of samples to be all samples remaining // num_samp_a = total_samples - start_samp_a; if (debug_level_d >= Integral::DETAILED) { String output; output.assign(num_samp_a); output.insert(L"readAFData: clipping num_samp_a to ", 0); Console::put(output); } } data_a.setLength(num_channels_d); for (int32 i = 0; i < num_channels_d; i++) { data_a(i).setLength(num_samp_a / num_channels_d); } // seek to the right place // if (start_samp_a != afSeekFrame(af_file_d, AF_DEFAULT_TRACK, start_samp_a)) { return Error::handle(name(), L"readAFData", Error::IO, __FILE__, __LINE__, Error::WARNING); } // temporary holder for all the data // int32 num_read = num_samp_a * num_channels_d; if (sample_num_bytes_d == (Long)sizeof(byte8)) { byte8* samples = (byte8*)io_buf_d; if (afReadFrames(af_file_d, AF_DEFAULT_TRACK, samples, num_read) != num_read) { return Error::handle(name(), L"readAFData", Error::READ, __FILE__, __LINE__, Error::WARNING); } interleaved_d.assign(num_read, samples); } else if (sample_num_bytes_d == (Long)sizeof(int16)) { int16* samples = (int16*) io_buf_d; if (afReadFrames(af_file_d, AF_DEFAULT_TRACK, samples, num_read) != num_read) { return Error::handle(name(), L"readAFData", Error::READ, __FILE__, __LINE__, Error::WARNING); } interleaved_d.assign(num_read, samples); } else { Error::handle(name(), L"readAFData", Error::ENUM, __FILE__, __LINE__); return -1; } // now do interleave // for (int32 i = 0; i < num_channels_d; i++) { data_a(i).setLength(num_samp_a); for (int32 j = 0; j < num_samp_a; j++) { // pull the sample out of the single buffer // data_a(i)(j) = (float32)interleaved_d(j * num_channels_d + i); // scale the sample // data_a(i)(j) /= max_sample_val_d; } } // exit gracefully // return num_samp_a; #else // error if sgi's audiofile library is not available // Error::handle(name(), L"readAFData", Error::NOT_IMPLEM, __FILE__, __LINE__); return -1; #endif } // method: writeAFData // // arguments: // Vector& data: (input) the audio data to write // int32 ctag: (input) channel tag // // return: the number of elements written // // this method writes the audio data to audiofile in any of the // formats supported by SGI's audiofile library // int32 AudioFile::writeAFData(Vector& data_a, int32 ctag_a) { #ifdef HAVE_AUDIOFILE // check for formats supported by SGI's audiofile library // if ((file_format_d != AIFF) && (file_format_d != AIFFC) && (file_format_d != AU) && (file_format_d != BICSF) && (file_format_d != WAV)) { return Error::handle(name(), L"writeAFData", ERR, __FILE__, __LINE__); } // not implemented // if ((int32)num_channels_d != 1) { return Error::handle(name(), L"writeAFData", ERR, __FILE__, __LINE__); } if (sample_num_bytes_d == (Long)sizeof(byte8)) { byte8* samples = (byte8*)io_buf_d; for (int32 n = 0; n < data_a(0).length(); ++n) { *samples = (byte8)((float32)(data_a(0)(n)) / max_sample_val_d); if (!afWriteFrames(af_file_d, AF_DEFAULT_TRACK, samples, 1)) { return Error::handle(name(), L"writeAFData", Error::IO, __FILE__, __LINE__, Error::WARNING); } } } else if (sample_num_bytes_d == (Long)sizeof(int16)) { int16* samples = (int16*)io_buf_d; for (int32 n = 0; n < data_a(0).length(); ++n) { *samples = (int16)((float32)(data_a(0)(n)) / max_sample_val_d); if (!afWriteFrames(af_file_d, AF_DEFAULT_TRACK, samples, 1)) { return Error::handle(name(), L"writeAFData", Error::IO, __FILE__, __LINE__, Error::WARNING); } } } else { Error::handle(name(), L"writeAFData", Error::ENUM, __FILE__, __LINE__); return -1; } #else // error if sgi's audiofile library is not available // Error::handle(name(), L"writeAFData", Error::NOT_IMPLEM, __FILE__, __LINE__); return -1; #endif // exit gracefully // return true; } // method: readAFHeader // // arguments: none // // return: a bool8 value indicating status // // this method reads the header of the audiofile in any of the formats // supported by the SGI's audiofile library // bool8 AudioFile::readAFHeader() { #ifdef HAVE_AUDIOFILE // check for formats supported by the SGI's audiofile library // if ((file_format_d != AIFF) && (file_format_d != AIFFC) && (file_format_d != AU) && (file_format_d != BICSF) && (file_format_d != WAV)) { return Error::handle(name(), L"readAFHeader", ERR, __FILE__, __LINE__); } // make sure the object is allocated // if (af_file_d == (AFfilehandle)NULL) { return Error::handle(name(), L"readAFHeader", Error::MEM, __FILE__, __LINE__); } // read the required parameters from the audiofile // num_channels_d = afGetChannels(af_file_d, AF_DEFAULT_TRACK); sample_freq_d = afGetRate(af_file_d, AF_DEFAULT_TRACK); sample_num_bytes_d = (int32)afGetFrameSize(af_file_d, AF_DEFAULT_TRACK, 0); int32 byte_order = (int32)afGetByteOrder(af_file_d, AF_DEFAULT_TRACK); // if the compression if employed, the audiofile library returns the // number of bytes per sample as zero, so set the number of bytes // per sample to the default(2) // if (sample_num_bytes_d == (int32)0) { sample_num_bytes_d = DEF_SAMPLE_NUM_BYTES; } // now set the byte order // // little-endian // default for WAV // if (byte_order == AF_BYTEORDER_LITTLEENDIAN) { byte_mode_d = LITTLE_ENDIAN; } // big-endian // supported by only AIFF/AIFF-C, NeXT(4), BICSF(4) // else if (byte_order == AF_BYTEORDER_BIGENDIAN) { byte_mode_d = BIG_ENDIAN; } // else error // else { return Error::handle(name(), L"readAFHeader", Error::ARG, __FILE__, __LINE__); } // exit gracefully // return true; #else // error if sgi's audiofile library is not available // Error::handle(name(), L"readAFHeader", Error::NOT_IMPLEM, __FILE__, __LINE__); return -1; #endif } // method: writeAFHeader // // arguments: none // // return: a bool8 value indicating status // // this method writes the header of the audiofile in any of the formats // supported by the SGI's audiofile library // bool8 AudioFile::writeAFHeader() const { // check for formats supported by the SGI's audiofile library // if ((file_format_d != AIFF) && (file_format_d != AIFFC) && (file_format_d != AU) && (file_format_d != BICSF) && (file_format_d != WAV)) { return Error::handle(name(), L"writeAFHeader", ERR, __FILE__, __LINE__); } #ifdef HAVE_AUDIOFILE // file format type // // AIFF // if (file_format_d == AIFF) { afInitFileFormat(af_setup_d, AF_FILE_AIFF); } // AIFFC // else if (file_format_d == AIFFC) { afInitFileFormat(af_setup_d, AF_FILE_AIFFC); } // AU // else if (file_format_d == AU) { afInitFileFormat(af_setup_d, AF_FILE_NEXTSND); } // BICSF // else if (file_format_d == BICSF) { afInitFileFormat(af_setup_d, AF_FILE_BICSF); } // WAV // else if (file_format_d == WAV) { afInitFileFormat(af_setup_d, AF_FILE_WAVE); } // else error // else { return Error::handle(name(), L"writeAFHeader", Error::ARG, __FILE__, __LINE__); } // number of channels // afInitChannels(af_setup_d, AF_DEFAULT_TRACK, (int)num_channels_d); // sampling frequency // afInitRate(af_setup_d, AF_DEFAULT_TRACK, (float64)sample_freq_d); // sample format and sample width should agree. Note that there is // one-to-one mapping for them. see http://btrzxa.fddi.uni-bayreuth.de/ // cgi-bin/manpages/afInitSampleFormat/3dm for further details. // if (sample_num_bytes_d == (int32)1) { afInitSampleFormat(af_setup_d, AF_DEFAULT_TRACK, AF_SAMPFMT_UNSIGNED, sample_num_bytes_d*(int32)8); } else if (sample_num_bytes_d == (int32)2) { afInitSampleFormat(af_setup_d, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, sample_num_bytes_d*(int32)8); } else if (sample_num_bytes_d == (int32)4) { afInitSampleFormat(af_setup_d, AF_DEFAULT_TRACK, AF_SAMPFMT_FLOAT, sample_num_bytes_d*(int32)4); } else if (sample_num_bytes_d == (int32)8) { afInitSampleFormat(af_setup_d, AF_DEFAULT_TRACK, AF_SAMPFMT_DOUBLE, sample_num_bytes_d*(int32)8); } else { return Error::handle(name(), L"writeAFHeader", Error::ARG, __FILE__, __LINE__); } // compression type, we don't use this functionality of the // audiofile. the compression type is set to the compression of // default file format type // // byte ordering // // little-endian // standard for WAV // if (byte_mode_d == LITTLE_ENDIAN) { afInitByteOrder(af_setup_d, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN); } // big-endian // supported by only AIFF/AIFF-C, NeXT(4), BICSF(4) // else if (byte_mode_d == BIG_ENDIAN) { afInitByteOrder(af_setup_d, AF_DEFAULT_TRACK, AF_BYTEORDER_BIGENDIAN); } // else error // else { return Error::handle(name(), L"writeAFHeader", Error::ARG, __FILE__, __LINE__); } // exit gracefully // return true; #else // error if sgi's audiofile library is not available // Error::handle(name(), L"writeAFHeader", Error::NOT_IMPLEM, __FILE__, __LINE__); return -1; #endif }