void __TFWT2D_TransformerRep::init_kernel(float *pkrnl, long nkrows, long nkcols) { // should never happen... but disallow kernel sizes larger // than the expected image size. Even though we could theoretically // accommodate to the ceiling power of two in size that would destroy // the zero fill needed for user image padding... check_valid_transformer(); if(nkcols > m_nucols || nkrows > m_nurows) throw("TFWT2D_Transformer: kernel size too large."); VDSP_CRITICAL_SECTION { // prep output buffer for this run setup_split_complex_outbuf(); // just move the kernel into the input buffer without regard // for its phase center. We will correct afterward. implant_kernel(pkrnl, nkcols, nkrows); // perform the forward FFT of the kernel fwd_fft(); // Correct the phase center. We only nead real-valued amplitudes. // Prep for use as an element-by-element real-real vector multipy // this uses a bit more memory but it is faster in the face of the // 2-D packed output format of the real-to-complex FFT // first get back to packed format from this wierd output format provided ztoc(&m_outdata, 1, m_pkrnlmask, 2, m_tsize2); // then, for each row and every complex column except the first... for(long iy = m_nirows; --iy >= 0; ) { long off = iy * m_nicols2; for(long ix = m_nicols2; --ix > 0; ) { long k = off + ix; double re = (double)m_pkrnlmask[k].real; double im = (double)m_pkrnlmask[k].imag; float v = (float)hypot(re,im); (*m_poutbuf)[k].real = v; (*m_poutbuf)[k].imag = v; } } // Then in the first complex column, for all rows except the first two... float *pdst = *(float**)m_poutbuf; float *psrc = (float*)m_pkrnlmask; for(long iy = 2; iy < m_nirows; iy += 2) { long kre = iy*m_nicols; long kim = kre + m_nicols; double re = (double)psrc[kre]; double im = (double)psrc[kim]; float v = (float)hypot(re,im); pdst[kre] = v; pdst[kim] = v; ++kre; ++kim; re = psrc[kre]; im = psrc[kim]; v = (float)hypot(re,im); pdst[kre] = v; pdst[kim] = v; } // finally, copy over the remaining untouched 4 cells for(long iy = 2; --iy >= 0;) { long off = iy * m_nicols; for(long ix = 2; --ix >= 0;) { long k = ix + off; pdst[k] = psrc[k]; } } // now refold the kernel so that we can do straight multiplies in the filter DSPSplitComplex kdata = {(float*)m_pkrnlmask, (float*)m_pkrnlmask + m_tsize2}; ctoz(*m_poutbuf, 2, &kdata, 1, m_tsize2); } END_VDSP_CRITICAL_SECTION; // apply descaling for round-trip amplification // = *2 for forward FFT on image // = *tsize for inverse FFT on image // = *2 for forward FFT on kernel long tsize = m_nicols * m_nirows; float sf = 0.25/tsize; vsmul((const float*)m_pkrnlmask, 1, &sf, (float*)m_pkrnlmask, 1, tsize); }
void noisiness_tick_G4(t_noisiness *x) { t_int i, index=0, cpt; t_float Spz = 0.0f, SFM = 0.0f; double prod = 1.0f, sum = 0.0f; double invNumBand = 0.04f; // Zero padding for (i=x->BufSize; i<x->FFTSize; i++) x->BufFFT[i] = 0.0f; // Window the samples if (x->x_window != Recta) for (i=0; i<x->BufSize; ++i) x->BufFFT[i] *= x->WindFFT[i]; // Look at the real signal as an interleaved complex vector by casting it. // Then call the transformation function ctoz to get a split complex vector, // which for a real signal, divides into an even-odd configuration. ctoz ((COMPLEX *) x->BufFFT, 2, &x->x_A, 1, x->x_FFTSizeOver2); // Carry out a Forward FFT transform fft_zrip(x->x_setup, &x->x_A, 1, x->x_log2n, FFT_FORWARD); // The output signal is now in a split real form. Use the function // ztoc to get a split real vector. ztoc ( &x->x_A, 1, (COMPLEX *) x->BufFFT, 2, x->x_FFTSizeOver2); // Squared Absolute for (i=0; i<x->FFTSize; i+=2) x->BufFFT[i/2] = (x->BufFFT[i] * x->BufFFT[i]) + (x->BufFFT[i+1] * x->BufFFT[i+1]); // Band Spz for (i=0; i<NUMBAND; i++) { cpt = x->BufSizeBark[i]; Spz = 0.0f; while (cpt > 0) { Spz += x->BufFFT[index]; cpt--; index++; } Spz = Spz/x->BufSizeBark[i]; sum += Spz; prod *= Spz; } prod = pow(prod,invNumBand); sum = invNumBand * sum; SFM = prod/sum; // Spectral Flatness Measure (SFM) if (SFM > 0) { SFM = 10*log10(prod/sum); } else { SFM = 0.0f; } // Tonality factor or Peakiness x->x_noisiness = MINF((SFM/-SFM_MAX),1); // minimum of both // Output result outlet_float(x->x_outnois, (1.0 - x->x_noisiness)); }
void pitch_tick_G4(t_pitch *x) { t_int halfFFTSize = x->FFTSize/2; t_float FsOverFFTSize = x->x_Fs/((t_float)x->FFTSize); t_pitchhist *ph; t_int i; // Zero padding for (i=x->BufSize; i<x->FFTSize; i++) x->BufFFT[i] = 0.0f; // Window the samples if (x->x_window != Recta) for (i=0; i<x->BufSize; ++i) x->BufFFT[i] *= x->WindFFT[i]; // Look at the real signal as an interleaved complex vector by casting it. // Then call the transformation function ctoz to get a split complex vector, // which for a real signal, divides into an even-odd configuration. ctoz ((COMPLEX *) x->BufFFT, 2, &x->x_A, 1, x->x_FFTSizeOver2); // Carry out a Forward FFT transform fft_zrip(x->x_setup, &x->x_A, 1, x->x_log2n, FFT_FORWARD); // Fast rescaling required // vsmul( x->x_A.realp, 1, &x->x_scaleFactor, x->x_A.realp, 1, x->x_FFTSizeOver2); // vsmul( x->x_A.imagp, 1, &x->x_scaleFactor, x->x_A.imagp, 1, x->x_FFTSizeOver2); // The output signal is now in a split real form. Use the function // ztoc to get a split real vector. ztoc ( &x->x_A, 1, (COMPLEX *) x->BufFFT, 2, x->x_FFTSizeOver2); // Squared Absolute for (i=0; i<x->FFTSize; i+=2) x->BufPower[i/2] = (x->BufFFT[i] * x->BufFFT[i]) + (x->BufFFT[i+1] * x->BufFFT[i+1]); // Go into fiddle~ code pitch_getit(x); // Output results if (x->x_npeakout) { // Output peaks t_peakout *po; for (i=0, po=x->peakBuf; i<x->x_npeakout; i++, po++) { t_atom at[3]; atom_setlong(at, i+1); atom_setfloat(at+1, po->po_freq); atom_setfloat(at+2, po->po_amp); outlet_list(x->x_peakout, 0, 3, at); } } // Output amplitude outlet_float(x->x_envout, x->x_dbs[x->x_histphase]); // Output fundamental frequencies + amplitudes if (x->x_npitch > 1) { for (i=0, ph=x->x_hist; i<x->x_npitch; i++, ph++) { t_atom at[3]; atom_setlong(at, i+1); atom_setfloat(at+1, ph->h_pitches[x->x_histphase]); atom_setfloat(at+2, ph->h_amps[x->x_histphase]); outlet_list(x->x_pitchout, 0, 3, at); } } else { for (i=0, ph=x->x_hist; i<x->x_npitch; i++, ph++) { t_atom at[2]; atom_setfloat(at, ph->h_pitches[x->x_histphase]); atom_setfloat(at+1, ph->h_amps[x->x_histphase]); outlet_list(x->x_pitchout, 0, 2, at); } } // Output cooked MIDI/Frequency pitch if (x->x_npitch > 1) { for (i=0, ph=x->x_hist; i<x->x_npitch; i++, ph++) if (ph->h_pitch) { t_atom at[3]; atom_setlong(at, i+1); atom_setfloat(at+1, ph->h_pitch); atom_setfloat(at+2, mtof(ph->h_pitch)); outlet_list(x->x_noteout, 0, 3, at); } } else { ph = x->x_hist; if (ph->h_pitch) { t_atom at[2]; atom_setfloat(at, ph->h_pitch); atom_setfloat(at+1, mtof(ph->h_pitch)); outlet_list(x->x_noteout, 0, 2, at); } } // Output attack bang if (x->x_attackvalue) outlet_bang(x->x_attackout); }