[chuck-users] DSP question: accumulating frequency info using FFT?

Jascha Narveson jnarveson at wesleyan.edu
Sat Oct 14 13:31:58 EDT 2017


Here’s the same thing as my original questions, but with some polite windowing - same problems persist: I’m hearing attacks (why?) and it’s pretty noisy - I guess because letting magnitudes creep up across the spectrum I’m just ultimately aiming for a big loud saw wave.  

So I guess I’m looking to do two things:

- avoid hearing attacks in the resynthesized sound from my “accumulated magnitudes” spectrum

- artfully avoid the inevitable sawtooth sound by changing my approach to something the follows the spirit of the original idea and not the actual idea.  

Thoughts?

cheers,

- jascha



- - - - same thing, a bit better maybe - - - -

SinOsc synth => FFT fft => blackhole;
UAnaBlob blob;
IFFT ifft => dac;

synth.freq(440);
synth.gain(0.5);


second / samp => float srate;

// set parameters
1024 => fft.size;
Windowing.hamming(fft.size() / 2) => fft.window;
Windowing.hamming(fft.size() / 2) => ifft.window;

// hold the FFT data as it comes in
complex spec[fft.size()/2];

// store the accumulated FFT data
complex acc[fft.size()/2];

// fill the accumulated complex spectral array with zeroes
for(0 => int i; i < acc.cap(); i++) {
  #(0, 0) => acc[i];
}

// spork shreds
spork ~ synthTune();
spork ~ accumulateMagnitudesViaFFT();

while (true) {
  1::second => now;
}

fun void accumulateMagnitudesViaFFT() {
  while( true )
  {
      fft.upchuck() @=> blob;
      // get the data
      blob.cvals() @=> spec;

      // for every bin...
      for(0 => int i; i < spec.cap(); i++) {
        // get the mag/phase for each bin by converting to polar
        spec[i] $ polar => polar newBin;

        // and get our running totals from acc
        acc[i] $ polar => polar accBin;

        // scale the inocming mag and add it to acc
        newBin.mag * 0.001 +=> accBin.mag;

        // let phase pass through
        newBin.phase => accBin.phase;

        // conver back to complex and put back in the acc array
        accBin $ complex => acc[i];
      }

      ifft.transform(acc);
      (fft.size() / 4)::samp => now;
  }
}

fun void synthTune() {
  while (true) {
    Math.random2(48, 72) => int midinote;
    Math.mtof(midinote) => synth.freq;
    333::ms => now;
    <<<acc[6] $ polar >>>; // just to check - yep: they're getting bigger...
  }
}



> On Oct 14, 2017, at 12:26 PM, Jascha Narveson <jnarveson at wesleyan.edu> wrote:
> 
> 
> Chuck list! Help!
> 
> I have the following idea and I’d like to hear what it sounds like:
> 
> - play a sound into an FFT
> - as the FFT runs, for each bin:
> - - look at the magnitude info
> - - take a small fraction of this info and store it in a running total
> - - let the phase pass through unchanged
> - use the spectral data in the running total for the IFFT
> 
> What I was hoping for was a slow emerging smear of all the frequencies from the input sound, kind of like a weird version of some kind of “infinite sustain” reverb.  
> 
> What I’m getting is the attacks of the original sound coming through, although fading in, and covered with noise.  
> 
> I think I’m doing something wrong by not doing something with the phase, but I’m not sure what.
> 
> I’d love some advice…
> 
> cheers,
> 
> j
> 
> 
> - - - - c o d e  e x a m p l e - - - - 
> 
> SinOsc synth => FFT fft => blackhole;
> UAnaBlob blob;
> IFFT ifft => dac;
> 
> synth.freq(440);
> synth.gain(0.1);
> 
> // set parameters
> 2048 => fft.size;
> 
> // place to hold the FFT data as it comes in
> complex spec[fft.size()/2];
> 
> // place to store the accumulated FFT data, preload with zeroes
> complex acc[fft.size()/2];
> for(0 => int i; i < acc.cap(); i++) {
>  #(0, 0) => acc[i];
> }
> 
> // do it!
> spork ~ sawTune();
> spork ~ accumulateFrequenciesViaFFT();
> 
> while (true) {
>  1::second => now;
> }
> 
> fun void accumulateFrequenciesViaFFT() {
>  while( true )
>  {
>      fft.upchuck() @=> blob;
>      // get the data
>      blob.cvals() @=> spec;
> 
>      // for every bin...
>      for(0 => int i; i < spec.cap(); i++) {
>        // get the mag/phase for each bin by converting to polar
>        spec[i] $ polar => polar newBin;
> 
>        // and get our running totals from acc
>        acc[i] $ polar => polar accBin;
> 
>        // scale the inocming mag and add it to acc
>        newBin.mag * 0.001 +=> accBin.mag;
> 
>        // let phase pass through
>        newBin.phase => accBin.phase;
> 				/*Math.random2f(0, TWO_PI) => accBin.phase;*/
> 
>        // convert back to complex and put back in the acc array
>        accBin $ complex => acc[i];
>      }
> 
>      ifft.transform(acc);
>      fft.size()::samp => now;
>  }
> }
> 
> fun void sawTune() {
>  while (true) {
>    Math.random2(48, 72) => int midinote;
>    Math.mtof(midinote) => synth.freq;
>    333::ms => now;
>  }
> }
> 
> _______________________________________________
> chuck-users mailing list
> chuck-users at lists.cs.princeton.edu
> https://lists.cs.princeton.edu/mailman/listinfo/chuck-users



More information about the chuck-users mailing list