void DCTFFTW::DCTBytes2D(const uint8_t *srcp, int src_pitch, uint8_t *dctp, int dct_pitch) { if (bitsPerSample == 8) { Bytes2Float<uint8_t>(srcp, src_pitch, fSrc); fftwf_execute_r2r(dctplan, fSrc, fSrcDCT); Float2Bytes<uint8_t>(dctp, dct_pitch, fSrcDCT); } else { Bytes2Float<uint16_t>(srcp, src_pitch, fSrc); fftwf_execute_r2r(dctplan, fSrc, fSrcDCT); Float2Bytes<uint16_t>(dctp, dct_pitch, fSrcDCT); } }
void DCT::apply(float * in, float * out, int sign) { static float n2 = n*2; if(sign>0){ fftwf_execute_r2r(pf,in,out); for(int i=1;i<n;i++) out[i] *=sqrt2; } else{ for( int i=1;i<n;i++) out[i] = in[i]*cd; out[0] =in[0]/n2; fftwf_execute_r2r(pi,out,out); } }
extern "C" void compute_ifft(const Element * const fft1, const Element * const fft2, Element * const ifft_out) { char *first; char *second; int first_offset; int second_offset; #ifndef MATCHIT_NO_DEBUG // sort them if (std::strcmp(fft1->get(filter_filepath), fft2->get(filter_filepath)) < 0) { first = fft1->get(filter_filepath); second = fft2->get(filter_filepath); first_offset = fft1->get(segment_offset); second_offset = fft2->get(segment_offset); } else { first = fft2->get(filter_filepath); second = fft1->get(filter_filepath); first_offset = fft2->get(segment_offset); second_offset = fft1->get(segment_offset); } #else first = fft1->get(filter_filepath); second = fft2->get(filter_filepath); first_offset = fft1->get(segment_offset); second_offset = fft2->get(segment_offset); #endif ifft_out->init_ids(); IFDEBUGF(output_file, mutex, "computing ifft of " << first << " with offset " << first_offset << " and " << second << " with offset " << second_offset << std::endl); ifft_out->group(fft1, fft2); // complex multiplication float *fft1_fft = fft1->get(fft); float *fft2_fft = fft2->get(fft); float buff[fft_size]; float ifft_buff[fft_size]; for (size_t real_idx = 1; real_idx < fft_size / 2; real_idx++) { unsigned int imag_idx = fft_size - real_idx; float real = fft1_fft[real_idx] * fft2_fft[real_idx] - fft1_fft[imag_idx] * fft2_fft[imag_idx]; float imag = fft1_fft[real_idx] * fft2_fft[imag_idx] + fft1_fft[imag_idx] * fft2_fft[real_idx]; buff[real_idx] = real; buff[imag_idx] = imag; } // the imaginary part of these is 0, so it is not stored buff[0] = fft1_fft[0] * fft2_fft[0]; buff[fft_size/2] = fft1_fft[fft_size/2] * fft2_fft[fft_size/2]; // compute inverse FFT and threshold the compared values unsigned int idx = 0; fftwf_execute_r2r(*ifft_plan, buff, ifft_buff); for (size_t i = seg_size - 2; i < fft_size; i++) { // MYSTERY float clipped_data = ifft_buff[i] / (float)fft_size * 32767.0; if (clipped_data > 32767.0) { clipped_data = 32767.0; } else if (clipped_data < -32767.0) { clipped_data = -32767.0; } ifft_out->set(clipped, idx++, clipped_data); } }
extern "C" void compute_fft(const Element * const input, Element * const output) { output->init_ids(); output->pass_through(input, filter_filepath); output->pass_through(input, segment_offset); IFDEBUGF(output_file, mutex, "computing FFT for " << output->get(filter_filepath) << " that starts at offset " << output->get(segment_offset) << std::endl); output->init(fft, fft_size); fftwf_execute_r2r(*fft_plan, &(input->get(audio)[input->get(segment_offset)]), output->get(fft)); }
/* * PADsynth-ize a WhySynth wavetable. */ int padsynth_render(y_sample_t *sample) { int N, i, fc0, nh, plimit_low, plimit_high, rndlim_low, rndlim_high; float bw, stretch, bwscale, damping; float f, max, samplerate, bw0_Hz, relf; float *inbuf = global.padsynth_inbuf; float *outfreqs, *smp; /* handle the special case where the sample key limit is 256 -- these * don't get rendered because they're usually just sine waves, and are * played at very high frequency */ if (sample->max_key == 256) { sample->data = (signed short *)malloc((WAVETABLE_POINTS + 8) * sizeof(signed short)); if (!sample->data) return 0; sample->data += 4; /* guard points */ memcpy(sample->data - 4, sample->source - 4, (WAVETABLE_POINTS + 8) * sizeof(signed short)); /* including guard points */ sample->length = WAVETABLE_POINTS; sample->period = (float)WAVETABLE_POINTS; return 1; } /* calculate the output table size */ i = lrintf((float)global.sample_rate * 2.5f); /* at least 2.5 seconds long -FIX- this should be configurable */ N = WAVETABLE_POINTS * 2; while (N < i) { if (N * 5 / 4 >= i) { N = N * 5 / 4; break; } if (N * 3 / 2 >= i) { N = N * 3 / 2; break; } N <<= 1; } /* check temporary memory and IFFT plan, allocate if needed */ if (global.padsynth_table_size != N) { padsynth_free_temp(); if (global.padsynth_ifft_plan) { #ifdef FFTW_VERSION_2 rfftw_destroy_plan(global.padsynth_ifft_plan); #else fftwf_destroy_plan(global.padsynth_ifft_plan); #endif global.padsynth_ifft_plan = NULL; } global.padsynth_table_size = N; } if (!global.padsynth_outfreqs) global.padsynth_outfreqs = (float *)fftwf_malloc(N * sizeof(float)); if (!global.padsynth_outsamples) global.padsynth_outsamples = (float *)fftwf_malloc(N * sizeof(float)); if (!global.padsynth_outfreqs || !global.padsynth_outsamples) return 0; outfreqs = global.padsynth_outfreqs; smp = global.padsynth_outsamples; if (!global.padsynth_ifft_plan) global.padsynth_ifft_plan = #ifdef FFTW_VERSION_2 (void *)rfftw_create_plan(N, FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE); #else (void *)fftwf_plan_r2r_1d(N, global.padsynth_outfreqs, global.padsynth_outsamples, FFTW_HC2R, FFTW_ESTIMATE); #endif if (!global.padsynth_ifft_plan) return 0; /* allocate sample memory */ sample->data = (signed short *)malloc((N + 8) * sizeof(signed short)); if (!sample->data) return 0; sample->data += 4; /* guard points */ sample->length = N; /* condition parameters */ bw = (sample->param1 ? (float)(sample->param1 * 2) : 1.0f); /* partial width: 1, or 2 to 100 cents by 2 */ stretch = (float)(sample->param2 - 10) / 10.0f; stretch *= stretch * stretch / 10.0f; /* partial stretch: -10% to +10% */ switch (sample->param3) { default: case 0: bwscale = 1.0f; break; /* width scale: 10% to 250% */ case 2: bwscale = 0.5f; break; case 4: bwscale = 0.25f; break; case 6: bwscale = 0.1f; break; case 8: bwscale = 1.5f; break; case 10: bwscale = 2.0f; break; case 12: bwscale = 2.5f; break; case 14: bwscale = 0.75f; break; } damping = (float)sample->param4 / 20.0f; damping = damping * damping * -6.0f * logf(10.0f) / 20.0f; /* damping: 0 to -6dB per partial */ /* obtain spectrum of input wavetable */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: analyzing input table\n"); for (i = 0; i < WAVETABLE_POINTS; i++) inbuf[i] = (float)sample->source[i] / 32768.0f; #ifdef FFTW_VERSION_2 rfftw_one((rfftw_plan)global.padsynth_fft_plan, inbuf, inbuf); #else fftwf_execute((const fftwf_plan)global.padsynth_fft_plan); /* transform inbuf in-place */ #endif max = 0.0f; if (damping > -1e-3f) { /* no damping */ for (i = 1; i < WAVETABLE_POINTS / 2; i++) { inbuf[i] = sqrtf(inbuf[i] * inbuf[i] + inbuf[WAVETABLE_POINTS - i] * inbuf[WAVETABLE_POINTS - i]); if (fabsf(inbuf[i]) > max) max = fabsf(inbuf[i]); } if (fabsf(inbuf[WAVETABLE_POINTS / 2]) > max) max = fabsf(inbuf[WAVETABLE_POINTS / 2]); } else { /* damping */ for (i = 1; i < WAVETABLE_POINTS / 2; i++) { inbuf[i] = sqrtf(inbuf[i] * inbuf[i] + inbuf[WAVETABLE_POINTS - i] * inbuf[WAVETABLE_POINTS - i]) * expf((float)i * damping); if (fabsf(inbuf[i]) > max) max = fabsf(inbuf[i]); } inbuf[WAVETABLE_POINTS / 2] = 0.0f; /* lazy */ } if (max < 1e-5f) max = 1e-5f; for (i = 1; i <= WAVETABLE_POINTS / 2; i++) inbuf[i] /= max; /* create new frequency profile */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: creating frequency profile\n"); memset(outfreqs, 0, N * sizeof(float)); /* render the fundamental at 4 semitones below the key limit */ f = 440.0f * y_pitch[sample->max_key - 4]; /* Find a nominal samplerate close to the real samplerate such that the * input partials fall exactly at integer output partials. This ensures * that especially the lower partials are not out of tune. Example: * N = 131072 * global.samplerate = 44100 * f = 261.625565 * fi = f / global.samplerate = 0.00593255 * fc0 = int(fi * N) = int(777.592) = 778 * so we find a new 'samplerate' that will result in fi * N being exactly 778: * samplerate = f * N / fc = 44076.8 */ fc0 = lrintf(f / (float)global.sample_rate * (float)N); sample->period = (float)N / (float)fc0; /* frames per period */ samplerate = f * sample->period; /* YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: size = %d, f = %f, fc0 = %d, period = %f\n", N, f, fc0, sample->period); */ bw0_Hz = (powf(2.0f, bw / 1200.0f) - 1.0f) * f; /* Find the limits of the harmonics to be used in the output table. These * are 20Hz and Nyquist, corrected for the nominal-to-actual sample rate * difference, with the latter also corrected for the 4-semitone shift in * the fundamental frequency. * lower partial limit: * (20Hz * samplerate / global.sample_rate) / samplerate * N * 4-semitone shift: * (2 ^ -12) ^ 4 * upper partial limit: * ((global.sample_rate / 2) * samplerate / global.sample_rate) / samplerate * N / shift */ plimit_low = lrintf(20.0f / (float)global.sample_rate * (float)N); /* plimit_high = lrintf(20000.0f / (float)global.sample_rate * (float)N / 1.25992f); */ plimit_high = lrintf((float)N / 2 / 1.25992f); /* YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: nominal rate = %f, plimit low = %d, plimit high = %d\n", samplerate, plimit_low, plimit_high); */ rndlim_low = N / 2; rndlim_high = 0; for (nh = 1; nh <= WAVETABLE_POINTS / 2; nh++) { int fc, contributed; float bw_Hz; /* bandwidth of the current harmonic measured in Hz */ float bwi; float fi; float plimit_amp; if (inbuf[nh] < 1e-5f) continue; relf = relF(nh, stretch); if (relf < 1e-10f) continue; bw_Hz = bw0_Hz * powf(relf, bwscale); bwi = bw_Hz / (2.0f * samplerate); fi = f * relf / samplerate; fc = lrintf(fi * (float)N); /* printf("...... kl = %d, nh = %d, fn = %f, fc = %d, bwi*N = %f\n", sample->max_key, nh, f * relf, fc, bwi * (float)N); */ /* set plimit_amp such that we don't calculate harmonics -100dB or more * below the profile peak for this harmonic */ plimit_amp = profile(0.0f, bwi) * 1e-5f / inbuf[nh]; /* printf("...... (nh = %d, fc = %d, prof(0) = %e, plimit_amp = %e, amp = %e)\n", nh, fc, profile(0.0f, bwi), plimit_amp, inbuf[nh]); */ /* scan profile and add partial's contribution to outfreqs */ contributed = 0; for (i = (fc < plimit_high ? fc : plimit_high); i >= plimit_low; i--) { float hprofile = profile(((float)i / (float)N) - fi, bwi); if (hprofile < plimit_amp) { /* printf("...... (i = %d, profile = %e)\n", i, hprofile); */ break; } outfreqs[i] += hprofile * inbuf[nh]; contributed = 1; } if (contributed && rndlim_low > i + 1) rndlim_low = i + 1; contributed = 0; for (i = (fc + 1 > plimit_low ? fc + 1 : plimit_low); i <= plimit_high; i++) { float hprofile = profile(((float)i / (float)N) - fi, bwi); if (hprofile < plimit_amp) { /* printf("...... (i = %d, profile = %e)\n", i, hprofile); */ break; } outfreqs[i] += hprofile * inbuf[nh]; contributed = 1; } if (contributed && rndlim_high < i - 1) rndlim_high = i - 1; }; if (rndlim_low > rndlim_high) { /* somehow, outfreqs is still empty */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render WARNING: empty output table (key limit = %d)\n", sample->max_key); rndlim_low = rndlim_high = fc0; outfreqs[fc0] = 1.0f; } /* randomize the phases */ /* YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: randomizing phases (%d to %d, kl=%d)\n", rndlim_low, rndlim_high, sample->max_key); */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: randomizing phases\n"); if (rndlim_high >= N / 2) rndlim_high = N / 2 - 1; for (i = rndlim_low; i < rndlim_high; i++) { float phase = RND() * 2.0f * M_PI_F; outfreqs[N - i] = outfreqs[i] * cosf(phase); outfreqs[i] = outfreqs[i] * sinf(phase); }; /* inverse FFT back to time domain */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: performing inverse FFT\n"); #ifdef FFTW_VERSION_2 rfftw_one((rfftw_plan)global.padsynth_ifft_plan, outfreqs, smp); #else /* remember restrictions on FFTW3 'guru' execute: buffers must be the same * sizes, same in-place-ness or out-of-place-ness, and same alignment as * when plan was created. */ fftwf_execute_r2r((const fftwf_plan)global.padsynth_ifft_plan, outfreqs, smp); #endif /* normalize and convert output data */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: normalizing output\n"); max = 0.0f; for (i = 0; i < N; i++) if (fabsf(smp[i]) > max) max = fabsf(smp[i]); if (max < 1e-5f) max = 1e-5f; max = 32767.0f / max; for (i = 0; i < N; i++) sample->data[i] = lrintf(smp[i] * max); /* copy guard points */ for (i = -4; i < 0; i++) sample->data[i] = sample->data[i + N]; for (i = 0; i < 4; i++) sample->data[N + i] = sample->data[i]; YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: done\n"); return 1; }
int prep_subbands(float *fdata, float *rawdata, int *delays, int numsubbands, struct spectra_info *s, int transpose, int *maskchans, int *nummasked, mask * obsmask) // This routine preps a block of raw spectra for subbanding. It uses // dispersion delays in 'delays' to de-disperse the data into // 'numsubbands' subbands. It stores the resulting data in vector // 'fdata' of length 'numsubbands' * 's->spectra_per_subint'. The low // freq subband is stored first, then the next highest subband etc, // with 's->spectra_per_subint' floating points per subband. It // returns the # of points read if succesful, 0 otherwise. // 'maskchans' is an array of length numchans which contains a list of // the number of channels that were masked. The # of channels masked // is returned in 'nummasked'. 'obsmask' is the mask structure to use // for masking. If 'transpose'==0, the data will be kept in time // order instead of arranged by subband as above. { int ii, jj, trtn, offset; double starttime = 0.0; static float *tmpswap, *rawdata1, *rawdata2; static float *currentdata, *lastdata; static int firsttime = 1, mask = 0; static fftwf_plan tplan1, tplan2; *nummasked = 0; if (firsttime) { if (obsmask->numchan) mask = 1; rawdata1 = gen_fvect(s->spectra_per_subint * s->num_channels); rawdata2 = gen_fvect(s->spectra_per_subint * s->num_channels); currentdata = rawdata1; lastdata = rawdata2; // Make plans to do fast transposes using FFTW tplan1 = plan_transpose(s->spectra_per_subint, s->num_channels, currentdata, currentdata); tplan2 = plan_transpose(numsubbands, s->spectra_per_subint, fdata, fdata); } /* Read and de-disperse */ memcpy(currentdata, rawdata, s->spectra_per_subint * s->num_channels * sizeof(float)); starttime = currentspectra * s->dt; // or -1 subint? if (mask) *nummasked = check_mask(starttime, s->time_per_subint, obsmask, maskchans); /* Clip nasty RFI if requested and we're not masking all the channels*/ if ((s->clip_sigma > 0.0) && !(mask && (*nummasked == -1))) clip_times(currentdata, s->spectra_per_subint, s->num_channels, s->clip_sigma, s->padvals); if (mask) { if (*nummasked == -1) { /* If all channels are masked */ for (ii = 0; ii < s->spectra_per_subint; ii++) memcpy(currentdata + ii * s->num_channels, s->padvals, s->num_channels * sizeof(float)); } else if (*nummasked > 0) { /* Only some of the channels are masked */ int channum; for (ii = 0; ii < s->spectra_per_subint; ii++) { offset = ii * s->num_channels; for (jj = 0; jj < *nummasked; jj++) { channum = maskchans[jj]; currentdata[offset + channum] = s->padvals[channum]; } } } } // In mpiprepsubband, the nodes do not call read_subbands() where // currentspectra gets incremented. if (using_MPI) currentspectra += s->spectra_per_subint; // Now transpose the raw block of data so that the times in each // channel are the most rapidly varying index fftwf_execute_r2r(tplan1, currentdata, currentdata); if (firsttime) { SWAP(currentdata, lastdata); firsttime = 0; return 0; } else { dedisp_subbands(currentdata, lastdata, s->spectra_per_subint, s->num_channels, delays, numsubbands, fdata); SWAP(currentdata, lastdata); // Transpose the resulting data into spectra as a function of time if (transpose==0) fftwf_execute_r2r(tplan2, fdata, fdata); return s->spectra_per_subint; } }