/// A thread-safe version of CalcSummary. BlockFile::CalcSummary /// uses a static summary array across the class, which we can't use. /// Get a buffer containing a summary block describing this sample /// data. This must be called by derived classes when they /// are constructed, to allow them to construct their summary data, /// after which they should write that data to their disk file. /// /// This method also has the side effect of setting the mMin, mMax, /// and mRMS members of this class. /// /// Unlike BlockFile's implementation You SHOULD DELETE the returned buffer. /// this is protected so it shouldn't be hard to deal with - just override /// all BlockFile methods that use this method. /// /// @param buffer A buffer containing the sample data to be analyzed /// @param len The length of the sample data /// @param format The format of the sample data. void *ODDecodeBlockFile::CalcSummary(samplePtr buffer, size_t len, sampleFormat format, ArrayOf<char> &cleanup) { cleanup.reinit(mSummaryInfo.totalSummaryBytes); char* localFullSummary = cleanup.get(); memcpy(localFullSummary, bheaderTag, bheaderTagLen); float *summary64K = (float *)(localFullSummary + mSummaryInfo.offset64K); float *summary256 = (float *)(localFullSummary + mSummaryInfo.offset256); Floats floats; float *fbuffer; //mchinen: think we can hack this - don't allocate and copy if we don't need to., if(format==floatSample) { fbuffer = (float*)buffer; } else { floats.reinit(len); fbuffer = floats.get(); CopySamples(buffer, format, (samplePtr)fbuffer, floatSample, len); } BlockFile::CalcSummaryFromBuffer(fbuffer, len, summary256, summary64K); return localFullSummary; }
void PaulStretch::process(float *smps, size_t nsmps) { //add NEW samples to the pool if ((smps != NULL) && (nsmps != 0)) { if (nsmps > poolsize) { nsmps = poolsize; } int nleft = poolsize - nsmps; //move left the samples from the pool to make room for NEW samples for (int i = 0; i < nleft; i++) in_pool[i] = in_pool[i + nsmps]; //add NEW samples to the pool for (size_t i = 0; i < nsmps; i++) in_pool[i + nleft] = smps[i]; } //get the samples from the pool for (size_t i = 0; i < poolsize; i++) fft_smps[i] = in_pool[i]; WindowFunc(eWinFuncHanning, poolsize, fft_smps.get()); RealFFT(poolsize, fft_smps.get(), fft_c.get(), fft_s.get()); for (size_t i = 0; i < poolsize / 2; i++) fft_freq[i] = sqrt(fft_c[i] * fft_c[i] + fft_s[i] * fft_s[i]); process_spectrum(fft_freq.get()); //put randomize phases to frequencies and do a IFFT float inv_2p15_2pi = 1.0 / 16384.0 * (float)M_PI; for (size_t i = 1; i < poolsize / 2; i++) { unsigned int random = (rand()) & 0x7fff; float phase = random * inv_2p15_2pi; float s = fft_freq[i] * sin(phase); float c = fft_freq[i] * cos(phase); fft_c[i] = fft_c[poolsize - i] = c; fft_s[i] = s; fft_s[poolsize - i] = -s; } fft_c[0] = fft_s[0] = 0.0; fft_c[poolsize / 2] = fft_s[poolsize / 2] = 0.0; FFT(poolsize, true, fft_c.get(), fft_s.get(), fft_smps.get(), fft_tmp.get()); float max = 0.0, max2 = 0.0; for (size_t i = 0; i < poolsize; i++) { max = std::max(max, fabsf(fft_tmp[i])); max2 = std::max(max2, fabsf(fft_smps[i])); } //make the output buffer float tmp = 1.0 / (float) out_bufsize * M_PI; float hinv_sqrt2 = 0.853553390593f;//(1.0+1.0/sqrt(2))*0.5; float ampfactor = 1.0; if (rap < 1.0) ampfactor = rap * 0.707; else ampfactor = (out_bufsize / (float)poolsize) * 4.0; for (size_t i = 0; i < out_bufsize; i++) { float a = (0.5 + 0.5 * cos(i * tmp)); float out = fft_smps[i + out_bufsize] * (1.0 - a) + old_out_smp_buf[i] * a; out_buf[i] = out * (hinv_sqrt2 - (1.0 - hinv_sqrt2) * cos(i * 2.0 * tmp)) * ampfactor; } //copy the current output buffer to old buffer for (size_t i = 0; i < out_bufsize * 2; i++) old_out_smp_buf[i] = fft_smps[i]; }