📄 adf_08.cc
字号:
// file: $isip/class/mmedia/AudioFile/adf_08.cc// version: $Id: adf_08.cc,v 1.12 2002/08/05 21:47:52 gao Exp $//// isip include files//#include "AudioFile.h"// method: getData//// arguments: none// Vector<VectorFloat>& data: (output) the audio data// long start_samp: (input) the start sample of the audio data// long num_samp: (input) the number of samples// // return: number of samples read//// this method gets the filtered data, if they are already in the circular// buffer, get them directly, or else get them from the audio file and filter// them//long AudioFile::getData(Vector<VectorFloat>& data_a, long start_samp_a, long num_samp_a) { // loop over each channel // long num_read = 0; // file is binary format // for (long ctag = 0; ctag < num_channels_d; ctag++) { long n = getData(data_a(ctag), ctag, start_samp_a, num_samp_a); // error check // if (n < 0) { return -1; } num_read += n; } // exit gracefully // return num_read;}// method: getData//// arguments: none// VectorFloat& data: (output) the audio data// long ctag: (input) the channel to read// long start_samp: (input) the start sample of the audio data// long num_samp: (input) the duration of the audio data// // return: number of samples read//// this method gets the filtered data, if they are already in the circular// buffer, get them directly, or else get them from the audio file and filter// them//long AudioFile::getData(VectorFloat& data_a, long ctag_a, long start_samp_a, long num_samp_a) { // check argument // if (ctag_a < 0) { Error::handle(name(), L"getData", Error::ARG, __FILE__, __LINE__); return -1; } // bad arguments // if (num_samp_a < 0) { Error::handle(name(), L"getData", Error::ARG, __FILE__, __LINE__); return -1; } // this is a common loop termination condition // else if (num_samp_a == 0) { data_a.clear(); return -1; } long output_index = 0; // determine the maximum sample in the file // long total_nsamp = getNumSamples(); // possibly clip the number of samples based on file length // if ((start_samp_a + num_samp_a) > total_nsamp) { num_samp_a = total_nsamp - start_samp_a; if (debug_level_d >= Integral::DETAILED) { String output; output.assign(num_samp_a); output.insert(L"getData: clipping nsamp to ", 0); Console::put(output); } } if (num_samp_a <= 0) { data_a.setLength(0); return 0; } // calculate the total number of bytes to read // data_a.setLength(num_samp_a); // get the start and end time of the data already in circular buffer // long buf_duration = buffers_d(ctag_a).getNumElements(); long buf_end = buf_end_samp_d(ctag_a); long buf_start = getStartSamp(ctag_a); long buf_max_sample = buf_end + (((long)buf_size_d - 1) * (block_size_d / (sample_num_bytes_d * num_channels_d))); // do we need samples that start before the circular buffer starts? // // or is the start sample much farther in the future, such that the // current samples would be pushed out before we get there? // // if so we need to reset everything and start over. // if ((start_samp_a < buf_start) || (start_samp_a > buf_max_sample)) { if (debug_level_d >= Integral::BRIEF) { String output(L"clearing bufs..."); Console::put(output); // printf("clearing bufs; either %ld < %ld or %ld > %ld = %ld + (%ld-1)*%ld/(%ld*%ld)\n", // start_samp_a, buf_start, start_samp_a, buf_max_sample, // buf_end, (long)buf_size_d, // (long)block_size_d, (long)sample_num_bytes_d, // (long)num_channels_d); } // clear out buffer // resetBuffer(ctag_a); // determine the new starting point that lines up on a block boundary // buf_start = blockFloor(start_samp_a); buf_duration = 0; // set pointers and time indices // buf_end = buf_start - 1; for (long x = 0; x < buf_end_samp_d.length(); x++) { buf_end_samp_d(x) = buf_end; } } // do we need to read ? // while (!end_of_file_d && ((start_samp_a + num_samp_a - 1) > getEndSamp(ctag_a))) { if (debug_level_d >= Integral::DETAILED) { String output; String numeric; output.assign(L"we need to read since "); numeric.assign(start_samp_a); output.concat(numeric); output.concat(L"+"); numeric.assign(num_samp_a); output.concat(numeric); output.concat(L"="); numeric.assign(start_samp_a + num_samp_a); output.concat(numeric); output.concat(L" > "); numeric.assign(getEndSamp(ctag_a)); output.concat(numeric); Console::put(output); } // pull in the next block of data // appendData(); if (debug_level_d >= Integral::ALL) { String output; output.assign(getEndSamp(ctag_a)); output.insert(L"now end_samp = ", 0); Console::put(output); } // recalculate boundaries // buf_duration = buffers_d(ctag_a).getNumElements(); buf_start = getStartSamp(ctag_a); // copy over the part of the user's vector we can // if ((start_samp_a + output_index) >= buf_start) { // we now give the user either: // the number of bytes they asked for, or // the all the bytes in the buffer if not all are available // // last_samp itself will not be read in // Long last_samp; last_samp.min((long)buf_end_samp_d(ctag_a) + 1, start_samp_a + num_samp_a); // the absolute reference we keep as the buf_end_samp_d is the // last valid element, represented by the zeroeth element in the // buffer. everything valid is non-positive. // long buf_index = start_samp_a + output_index - buf_end_samp_d(ctag_a); while ((output_index + start_samp_a) < last_samp) { data_a(output_index++) = buffers_d(ctag_a)(buf_index++); } } } // possibly pull data from the circular buffer // if (output_index < num_samp_a) { // make sure the data is in the buffer // buf_duration = buffers_d(ctag_a).getNumElements(); buf_start = getStartSamp(ctag_a); if ((start_samp_a + output_index) < buf_start) { Error::handle(name(), L"getData", ERR, __FILE__, __LINE__); return -1; } if ((start_samp_a + num_samp_a - 1) > buf_end_samp_d(ctag_a)) { buf_end_samp_d.debug(L"buf_end_samp"); Error::handle(name(), L"getData", ERR, __FILE__, __LINE__); return -1; } // copy over data from the circular buffer to the output vector // long buf_index = start_samp_a + output_index - buf_end_samp_d(ctag_a); while ((output_index) < (num_samp_a)) { data_a(output_index++) = buffers_d(ctag_a)(buf_index++); } } // exit gracefully // return num_samp_a;}// method: blockFloor//// arguments:// long samp_num: (input) exact sample number//// return: a rounded sample number (floored by block boundaries)//// this method gets the begining sample number of the block this// sample belongs to//long AudioFile::blockFloor(long samp_num_a) const { long samples_per_block = block_size_d / sample_num_bytes_d; long i = 0; for (; i < samp_num_a; i += samples_per_block); if (i > 0) { i -= samples_per_block; } return i;}// method: blockCeil//// arguments:// long samp_num: (input) exact sample number//// return: a rounded sample number //// this method gets the starting sample number of the next block//long AudioFile::blockCeil(long samp_num_a) const { long samples_per_block = block_size_d / sample_num_bytes_d; long i = 0; for (; i < samp_num_a; i += samples_per_block); if (i == 0) { i += samples_per_block; } return i;}// method: appendData//// arguments: none// // return: a boolean value indicating status//// this method reads the next block of data from the audiofile and places// it on the circular buffer//boolean AudioFile::appendData() { if (end_of_file_d) { return false; } // determine the current location of the buffer // long first_samp = (long)buf_end_samp_d(0) + 1; long block_samp = block_size_d / sample_num_bytes_d; for (long ctag = 0; ctag < num_channels_d; ctag++) { // determine if we are about to overwrite data // long num_bytes_left = (buffers_d(ctag).getCapacity() - buffers_d(ctag).getNumElements()) * sample_num_bytes_d; if (num_bytes_left < block_size_d) { if (debug_level_d >= Integral::DETAILED) { String output(L"Channel "); output.concat(ctag); output.concat(L": num_bytes_left = "); output.concat(num_bytes_left); output.concat(L"; clearing out old block"); Console::put(output); } // clear out the oldest block by advancing the read pointer // buffers_d(ctag).setRead(block_samp); } } // read a block of data // Vector<VectorFloat> raw_data; // compute time boundaries for the next block // // channel is ignored, it gives you all of them // long nsamp = readAudioData(raw_data, -1, first_samp, block_samp); if (debug_level_d >= Integral::DETAILED) { String numeric; String output(L"read "); numeric.assign(nsamp); output.concat(numeric); output.concat(L" samples, ending at file position "); numeric.assign(tell()); output.concat(numeric); Console::put(output); } if (nsamp != block_samp) { if (debug_level_d >= Integral::DETAILED) { String numeric; String output(L"end of file at sample "); numeric.assign(nsamp + first_samp); output.concat(numeric); Console::put(output); } end_of_file_d = true; } for (long ctag = 0; ctag < num_channels_d; ctag++) { for (long i = 0; i < nsamp; i++) { // insert the input data into ma filter memory // ma_mem_d(ctag).append(raw_data(ctag)(i)); ma_mem_d(ctag).setRead(1); if (ma_mem_d(ctag).getNumElements() > 1) { ma_mem_d(ctag).seekCurr(1); } Float sum = 0.0; // handle ma coefficients // for (long i = 0; i < ma_coeff_d.length(); i++) { sum += ma_coeff_d(i) * ma_mem_d(ctag)(-i); } // handle ar coefficients with non-zero lag (note that read has // not yet been updated yet, so ar[0] is corresponds to the same // time as ma[-1]. // for (long i = 0; i < (ar_coeff_d.length() - 1); i++) { sum += ar_coeff_d(i + 1) * ar_mem_d(ctag)(-i); } // handle the ar[0] term as output gain, note: // // y[n] = x[n] + 0.9 * y[n]; // // (1 - 0.9) * y[n] = x[n]; // // y[n] = x[n] / (1 - 0.9) // // therefore, sum = sum / (1 - ar[0]) // // update: for now we enforce that ar[0] must be 1, still waiting // on mathematics to clear it up. // // sum /= (1 - ar_coeff_d(0)); // insert the output into both the data circular buffer and the ar // memory. // ar_mem_d(ctag).append(sum); ar_mem_d(ctag).setRead(1); if (ar_mem_d(ctag).getNumElements() > 1) { ar_mem_d(ctag).seekCurr(1); } buffers_d(ctag).append(sum); // only seek if we can // if (buffers_d(ctag).getNumElements() > 1) { buffers_d(ctag).seekCurr(1); } buf_end_samp_d(ctag) += 1; } } // exit gracefully // return true;}// method: getNumSamples//// arguments: none//// return: the long value of the number of samples//// this method gets the number of samples//long AudioFile::getNumSamples() const { long total_nsamp = -1; if (file_format_d == RAW) { String output; String values; long lines = 0; // save the current file position and seek end // long cur_file_pos = tell(); if (file_type_d == TEXT) { const_cast<AudioFile*>(this)->rewind(); while (!eof()) { lines++; values.assign(lines); values.concat(L": "); const_cast<AudioFile*>(this)->get(output); values.concat(output); // Console::put(values); } const_cast<AudioFile*>(this)->rewind(); total_nsamp = lines / num_channels_d; const_cast<AudioFile*>(this)->seek(cur_file_pos, POS); } else { // seek end // const_cast<AudioFile*>(this)->seek(0, POS_PLUS_END); long total_len = tell(); // compute the total number of samples // long bytes_per_samp = (sample_num_bytes_d * num_channels_d); total_nsamp = total_len / bytes_per_samp; // resume the file position // const_cast<AudioFile*>(this)->seek(cur_file_pos, POS); } } else if (file_format_d == SOF) { if (sof_d == (Sof*)NULL) { return Error::handle(name(), L"getNumSamples", Error::MEM, __FILE__, __LINE__); } if (sof_d->isBinary()) { sof_d->seek(sof_length_pos_d, File::POS); Long len; len.readData(*sof_d, PARAM_DATA); total_nsamp = (long)len / (long)num_channels_d; } else { long len = sof_d->getVecParser().countTokens(SofParser::implicitPname()); total_nsamp = len / (long)num_channels_d; } } else { return Error::handle(name(), L"getNumSamples", Error::NOT_IMPLEM, __FILE__, __LINE__); } // return the number of samples // return total_nsamp;}// method: readAudioData//// arguments:// Vector<VectorFloat>& data: (output) the audio data// long ctag: (input) the channel to read// long start_samp: (input) the start time of the audio data// long num_samp: (input) the end time of the audio data// // return: number of samples read//// this method gets data from the audio file and put each channel data into a// VectorFloat//long AudioFile::readAudioData(Vector<VectorFloat>& data_a, long ctag_a, long start_samp_a, long num_samp_a) { // make sure the file is open // if (!isOpen()) { return Error::handle(name(), L"", ERR_NOTOPN, __FILE__, __LINE__); } // for binary read // if (file_format_d == RAW) { return readRawData(data_a, ctag_a, start_samp_a, num_samp_a); } // sof file // if (file_format_d == SOF) { return readSofData(data_a, ctag_a, start_samp_a, num_samp_a); } // file types other than RAW and Sof // else if (file_format_d == WAV) { // readWavData(data_a, ctag_a, start_time_a, end_time_a); Error::handle(name(), L"readAudioData", Error::NOT_IMPLEM, __FILE__, __LINE__); return -1; } else if (file_format_d == SPHERE) { // readSphereData(data_a, ctag_a, start_time_a, end_time_a); Error::handle(name(), L"readAudioData", Error::NOT_IMPLEM, __FILE__, __LINE__); return -1; } // bad type // Error::handle(name(), L"readAudioData", ERR_TYPE, __FILE__, __LINE__); return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -