Chris@12: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@12: Chris@28: #ifdef DECIMATE_B Chris@28: #include "qm-dsp/dsp/rateconversion/DecimatorB.h" Chris@28: #else Chris@15: #include "qm-dsp/dsp/rateconversion/Decimator.h" Chris@28: #endif Chris@28: Chris@15: #include "qm-dsp/maths/MathUtilities.h" Chris@12: Chris@12: #include Chris@12: #include Chris@12: #include Chris@12: #include Chris@12: #include Chris@12: #include Chris@12: #include Chris@12: #include Chris@12: #include Chris@12: #include Chris@12: Chris@12: using namespace std; Chris@12: Chris@12: int main(int argc, char **argv) Chris@12: { Chris@15: int factor = 0; Chris@12: bool version = false; Chris@12: bool help = false; Chris@12: int c = 0; Chris@12: Chris@12: while (1) { Chris@12: int optionIndex = 0; Chris@12: Chris@12: static struct option longOpts[] = { Chris@12: { "help", 0, 0, 'h' }, Chris@12: { "version", 0, 0, 'V' }, Chris@15: { "by", 1, 0, 'b' }, Chris@12: { 0, 0, 0, 0 } Chris@12: }; Chris@12: Chris@12: c = getopt_long(argc, argv, Chris@15: "b:hV", Chris@12: longOpts, &optionIndex); Chris@12: if (c == -1) break; Chris@12: Chris@12: switch (c) { Chris@12: case 'h': help = true; break; Chris@12: case 'V': version = true; break; Chris@15: case 'b': factor = atoi(optarg); break; Chris@12: default: help = true; break; Chris@12: } Chris@12: } Chris@12: Chris@12: if (version) { Chris@15: cerr << "decimate v0.1" << endl; //!!! Chris@12: return 0; Chris@12: } Chris@12: Chris@15: if (help || factor == 0 || optind + 2 != argc) { Chris@12: cerr << endl; Chris@15: cerr << "usage: " << argv[0] << " --by " << endl; Chris@12: cerr << endl; Chris@12: return 2; Chris@12: } Chris@15: Chris@15: if (!MathUtilities::isPowerOfTwo(factor)) { Chris@15: cerr << "ERROR: Factor must be a power of two" << endl; Chris@15: return 1; Chris@15: } Chris@28: #ifdef DECIMATE_B Chris@28: if (factor < 2) { Chris@28: cerr << "ERROR: Factor must be at least 2" << endl; Chris@28: return 1; Chris@28: } Chris@28: #else Chris@15: if (factor < 2 || factor > Decimator::getHighestSupportedFactor()) { Chris@15: cerr << "ERROR: Only factors between 2 and " Chris@15: << Decimator::getHighestSupportedFactor() Chris@15: << " inclusive are supported" < decimators; // one per channel Chris@28: for (int c = 0; c < channels; ++c) { Chris@28: decimators.push_back(new DecimatorB(ibs, factor)); Chris@28: } Chris@28: #else Chris@28: vector decimators; // one per channel Chris@13: for (int c = 0; c < channels; ++c) { Chris@15: decimators.push_back(new Decimator(ibs, factor)); Chris@13: } Chris@28: #endif Chris@13: Chris@12: float *ibuf = new float[channels * ibs]; Chris@12: float *obuf = new float[channels * obs]; Chris@12: Chris@12: double **prebuf = new double*[channels]; Chris@12: double **postbuf = new double*[channels]; Chris@12: Chris@12: for (int c = 0; c < channels; ++c) { Chris@12: prebuf[c] = new double[ibs]; Chris@12: postbuf[c] = new double[obs]; Chris@12: } Chris@12: Chris@12: int n = 0; Chris@12: Chris@12: while (true) { Chris@12: Chris@12: int count = sf_readf_float(sndfile, ibuf, ibs); Chris@12: if (count <= 0) break; Chris@12: Chris@12: for (int c = 0; c < channels; ++c) { Chris@12: Chris@12: for (int i = 0; i < count; ++i) { Chris@12: prebuf[c][i] = ibuf[i * channels + c]; Chris@12: } Chris@15: for (int i = count; i < ibs; ++i) { Chris@15: prebuf[c][i] = 0.0; Chris@15: } Chris@12: Chris@15: decimators[c]->process(prebuf[c], postbuf[c]); Chris@12: Chris@15: for (int i = 0; i < obs; ++i) { Chris@15: obuf[i * channels + c] = postbuf[c][i]; Chris@15: } Chris@12: } Chris@12: Chris@15: int ocount = obs; Chris@15: if (count < ibs) { Chris@15: ocount = count / factor; Chris@15: } Chris@15: Chris@15: sf_writef_float(sndfileOut, obuf, ocount); Chris@15: Chris@15: n += ocount; Chris@12: } Chris@12: Chris@12: sf_close(sndfile); Chris@12: sf_close(sndfileOut); Chris@12: Chris@12: for (int c = 0; c < channels; ++c) { Chris@12: delete[] prebuf[c]; Chris@12: delete[] postbuf[c]; Chris@15: delete decimators[c]; Chris@12: } Chris@12: Chris@12: delete[] prebuf; Chris@12: delete[] postbuf; Chris@12: delete[] ibuf; Chris@12: delete[] obuf; Chris@12: Chris@12: timeval etv; Chris@12: (void)gettimeofday(&etv, 0); Chris@12: Chris@12: etv.tv_sec -= tv.tv_sec; Chris@12: if (etv.tv_usec < tv.tv_usec) { Chris@12: etv.tv_usec += 1000000; Chris@12: etv.tv_sec -= 1; Chris@12: } Chris@12: etv.tv_usec -= tv.tv_usec; Chris@12: Chris@12: double sec = double(etv.tv_sec) + (double(etv.tv_usec) / 1000000.0); Chris@17: cerr << sfinfo.frames << " frames in, " << n << " frames out" Chris@17: << ", nominal factor " << (1.0/factor) Chris@17: << ", actual " << double(n)/double(sfinfo.frames) Chris@17: << endl << "Elapsed time: " << sec << " sec, in frames/sec: " Chris@17: << int(sfinfo.frames/sec) << ", out frames/sec: " << int(n/sec) << endl; Chris@12: Chris@12: return 0; Chris@12: } Chris@12: Chris@12: Chris@12: Chris@12: Chris@12: Chris@12: