void CFFTOSX::GetMagnitude(sample* pfSamples) throw (IException*) { // Only 32-bit sample is supported if (sizeof(sample) != 4) { throw IException::Create(IException::TypeCode, IException::ReasonGeneric, EXCEPTION_INFO, (tchar*)"Unknown or unsupported sample size"); } // Convert to required format ctoz((COMPLEX*)pfSamples, 2, &mA, 1, muiFFTSize / 2); // FFT fft_zrip(mFFT, &mA, 1, muiOrder, FFT_FORWARD); // Scale it float fScale = 1.0f / (2 * muiFFTSize); vsmul(mA.realp, 1, &fScale, mA.realp, 1, muiFFTSize / 2); vsmul(mA.imagp, 1, &fScale, mA.imagp, 1, muiFFTSize / 2); // Convert to magnitude tint32 iIndex; for (iIndex = 1; iIndex < muiFFTSize / 2; iIndex++) { pfSamples[iIndex] = (float)sqrt((mA.realp[iIndex] * mA.realp[iIndex]) + (mA.imagp[iIndex] * mA.imagp[iIndex])); } // Special cases pfSamples[0] = (float)sqrt(mA.realp[0] * mA.realp[0]); pfSamples[muiFFTSize / 2] = (float)sqrt(mA.realp[1] * mA.realp[1]); }
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)); }
ITunesPixelFormat ivis_render( ITunesVis* plugin, short audio_data[][512], float freq_data[][512], void* buffer, long buffer_size, bool idle ) { ITunesPixelFormat format = ITunesPixelFormatUnknown; /* make sure we have a plugin and a visual handler */ if ( !plugin || !plugin->imports.visual_handler ) return format; int i=0, w=0; RenderVisualData visual_data; DSPSplitComplex splitComplex[2]; float *data[2]; /* perform FFT if we're not idling */ if ( ! idle ) { /* allocate some complex vars */ for ( i = 0 ; i < 2 ; i++ ) { splitComplex[i].realp = calloc( 512, sizeof(float) ); splitComplex[i].imagp = calloc( 512, sizeof(float) ); data[i] = calloc( 512, sizeof(float) ); } /* 2 channels for spectrum and waveform data */ visual_data.numWaveformChannels = 2; visual_data.numSpectrumChannels = 2; /* copy spectrum audio data to visual data strucure */ for ( w = 0 ; w < 512 ; w++ ) { /* iTunes visualizers expect waveform data from 0 - 255, with level 0 at 128 */ visual_data.waveformData[0][w] = (UInt8)( (long)(audio_data[0][w]) / 128 + 128 ); visual_data.waveformData[1][w] = (UInt8)( (long)(audio_data[1][w]) / 128 + 128 ); /* scale to -1, +1 */ *( data[0] + w ) = (float)(( audio_data[0][w]) / (2.0 * 8192.0) ); *( data[1] + w ) = (float)(( audio_data[1][w]) / (2.0 * 8192.0) ); } /* FFT scaler */ float scale = ( 1.0 / 1024.0 ) ; /* scale by length of input * 2 (due to how vDSP does FFTs) */ float nyq=0, dc=0, freq=0; for ( i = 0 ; i < 2 ; i++ ) { /* pack data into format fft_zrip expects it */ vDSP_ctoz( (COMPLEX*)( data[i] ), 2, &( splitComplex[i] ), 1, 256 ); /* perform FFT on normalized audio data */ fft_zrip( plugin->fft_setup, &( splitComplex[i] ), 1, 9, FFT_FORWARD ); /* scale the values */ vDSP_vsmul( splitComplex[i].realp, 1, &scale, splitComplex[i].realp, 1, 256 ); vDSP_vsmul( splitComplex[i].imagp, 1, &scale, splitComplex[i].imagp, 1, 256 ); /* unpack data */ vDSP_ztoc( &splitComplex[i], 1, (COMPLEX*)( data[i] ), 2, 256 ); /* ignore phase */ dc = *(data[i]) = fabs( *(data[i]) ); nyq = fabs( *(data[i] + 1) ); for ( w = 1 ; w < 256 ; w++ ) { /* don't use vDSP for this since there's some overflow */ freq = hypot( *(data[i] + w * 2), *(data[i] + w * 2 + 1) ) * 256 * 16; freq = MAX( 0, freq ); freq = MIN( 255, freq ); visual_data.spectrumData[i][ w - 1 ] = (UInt8)( freq ); } visual_data.spectrumData[i][256] = nyq; } /* deallocate complex vars */ for ( i = 0 ; i < 2 ; i++ ) { free( splitComplex[i].realp ); free( splitComplex[i].imagp ); free( data[i] ); } /* update the render message with the new visual data and timestamp */ plugin->visual_message.u.renderMessage.renderData = &visual_data; plugin->visual_message.u.renderMessage.timeStampID++; } /* update time */ plugin->visual_message.u.renderMessage.currentPositionInMS = ivis_current_time() - plugin->start_time; // FIXME: real time /* save our GL context and send the vis a render message */ CGLContextObj currentContext = CGLGetCurrentContext(); if ( plugin->gl_context ) aglSetCurrentContext( (AGLContext)(plugin->gl_context ) ); /* call the plugin's render method */ if ( idle ) { /* idle message */ if ( plugin->wants_idle ) plugin->imports.visual_handler( kVisualPluginIdleMessage, &( plugin->visual_message ), plugin->vis_ref ); } else { /* render message */ plugin->imports.visual_handler( kVisualPluginRenderMessage, &( plugin->visual_message ), plugin->vis_ref ); /* set position message */ plugin->visual_message.u.setPositionMessage.positionTimeInMS = plugin->visual_message.u.renderMessage.currentPositionInMS; plugin->imports.visual_handler( kVisualPluginSetPositionMessage, &( plugin->visual_message ), plugin->vis_ref ); } /* update message */ plugin->imports.visual_handler( kVisualPluginUpdateMessage, NULL, plugin->vis_ref ); /* read pixels and restore our GL context */ CGLLockContext( CGLGetCurrentContext() ); switch ( get_pixels( buffer, buffer_size, CGLGetCurrentContext() != currentContext ) ) { case 3: format = ITunesPixelFormatRGB24; break; case 4: format = ITunesPixelFormatRGBA32; break; default: break; } CGLUnlockContext ( CGLGetCurrentContext() ); /* restore our GL context */ CGLSetCurrentContext( currentContext ); return format; }
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); }