<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">Okay, a little closer: &nbsp;I’ve switched my approach to taking a running average of the mags and phases - it’s sounding better, but is plagued by clicking at a rate related to my hop size. &nbsp;I thought windowing might’ve smoothed that out - any further ideas?</div><div class=""><br class=""></div><div class="">- - - - taking averages of mag and phase - - - - -</div><div class=""><br class=""></div><div class=""><div class="">SinOsc synth =&gt; FFT fft =&gt; blackhole;</div><div class="">IFFT ifft =&gt; dac;</div><div class=""><br class=""></div><div class="">synth.gain(1);</div><div class="">synth.freq(430);</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">// set parameters</div><div class="">16384 &nbsp;=&gt; fft.size;</div><div class="">fft.size() / 2 =&gt; int HALF_FFT_SIZE;</div><div class="">Windowing.hamming(fft.size() / 2) =&gt; fft.window;</div><div class="">Windowing.hamming(fft.size() / 2) =&gt; ifft.window;</div><div class="">1 =&gt; int FRAME_COUNT;</div><div class=""><br class=""></div><div class="">// for monitoring the bin for middle-C</div><div class="">second / samp / fft.size() =&gt; float binWidth;</div><div class="">Math.ceil(Math.mtof(60) / binWidth) $ int =&gt; int middleCBinNum;</div><div class=""><br class=""></div><div class="">// place to hold the FFT data as it comes in</div><div class="">complex spec[HALF_FFT_SIZE];</div><div class=""><br class=""></div><div class="">// place to store the averaged FFT data, preload with an analysis frame</div><div class="">complex avg[HALF_FFT_SIZE];</div><div class=""><br class=""></div><div class="">// do it!</div><div class="">spork ~ synthTune();</div><div class="">spork ~ averageFrequenciesViaFFT(HALF_FFT_SIZE / 4);</div><div class=""><br class=""></div><div class="">while (true) {</div><div class="">&nbsp; &nbsp; 1::second =&gt; now;</div><div class="">}</div><div class=""><br class=""></div><div class="">fun void averageFrequenciesViaFFT(int HOP_SIZE) {</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; while( true )</div><div class="">&nbsp; &nbsp; {</div><div class="">&nbsp; &nbsp; &nbsp; FRAME_COUNT++;</div><div class="">&nbsp; &nbsp; &nbsp; 1.0 / FRAME_COUNT =&gt; float FRAME_RECIPROCAL;</div><div class="">&nbsp; &nbsp; &nbsp; fft.upchuck();</div><div class="">&nbsp; &nbsp; &nbsp; fft.spectrum(spec);</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; &nbsp; // for every bin...</div><div class="">&nbsp; &nbsp; &nbsp; for(0 =&gt; int i; i &lt; HALF_FFT_SIZE; i++) {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // get the mag/phase for each bin by converting to polar</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; spec[i] $ polar =&gt; polar newBin;</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // and get our running average from avg</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; avg[i] $ polar =&gt; polar avgBin;</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ( (avgBin.mag * (FRAME_COUNT - 1)) + newBin.mag) * FRAME_RECIPROCAL =&gt; float newAvgMag;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ( ( (avgBin.phase * (FRAME_COUNT - 1)) + newBin.phase) * FRAME_RECIPROCAL) % Math.TWO_PI =&gt; float newAvgPhase;</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; polar newAvgBin;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newAvgMag =&gt; newAvgBin.mag;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newAvgPhase =&gt; newAvgBin.phase;</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // convert back to complex and put back in the acc array</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newAvgBin $ complex =&gt; avg[i];</div><div class="">&nbsp; &nbsp; &nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; &nbsp; &lt;&lt;&lt;"note 60's bin: live: ", spec[middleCBinNum] $ polar, "avg: ", avg[middleCBinNum] $ polar&gt;&gt;&gt;; // how's midinote 60 doing?</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; &nbsp; ifft.transform(avg);</div><div class="">&nbsp; &nbsp; &nbsp; HOP_SIZE::samp =&gt; now;</div><div class="">&nbsp; }</div><div class="">}</div><div class=""><br class=""></div><div class="">fun void synthTune() {</div><div class="">&nbsp; &nbsp; while (true) {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; Math.random2(48, 92) =&gt; int midinote;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; Math.mtof(midinote) =&gt; synth.freq;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; 333::ms =&gt; now;</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Oct 14, 2017, at 2:10 PM, Jascha Narveson &lt;<a href="mailto:jnarveson@wesleyan.edu" class="">jnarveson@wesleyan.edu</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div>Hi, Eric -<div class=""><br class=""></div><div class="">Interesting! &nbsp;This is definitely a step closer.</div><div class=""><br class=""></div><div class="">On my own, I also tried running my original code with a constant mag of 0.1 in every bin, but with the phase updating live, and voila: I was hearing a dirty and distant version of the original signal, attacks and all. &nbsp;So, you’re right about that: phase info is important, and can sound like the source even if the mags are all kept steady.</div><div class=""><br class=""></div><div class="">Your averaging idea seems like a good route to try - maybe what I’m after is more of an average of a series of successive FFT-freezes, or something…</div><div class=""><br class=""></div><div class="">…back to the drawing board…</div><div class=""><br class=""></div><div class="">Thanks!</div><div class=""><br class=""></div><div class="">-j-</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div class=""><blockquote type="cite" class=""><div class="">On Oct 14, 2017, at 1:59 PM, Eric Heep &lt;<a href="mailto:ericheep@gmail.com" class="">ericheep@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">I have a feeling that the phase information may be important to keep around.<div class=""><br class=""></div><div class="">I added a moving average filter into your code, and then added that average into the accumulation spectrum. I'm also including the phase information, and while it all sounds more "smeary", it is also introducing windowing artifacts (I think that's what those are).&nbsp;</div><div class=""><br class=""></div><div class="">I would be interested in a way to clean those up.<br class=""><div class=""><br class=""></div><div class=""><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s1">SinOsc</span><span class="gmail-s2"> </span>synth<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s1">FFT</span><span class="gmail-s2"> </span>fft<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">blackhole</span>;</font></p><p class="gmail-p2"><font face="monospace, monospace" class="">UAnaBlob<span class="gmail-s2"> blob;</span></font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s1">IFFT</span><span class="gmail-s2"> </span>ifft<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">dac</span>;</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p1"><font face="monospace, monospace" class="">synth.freq(<span class="gmail-s4">440</span>);</font></p><p class="gmail-p1"><font face="monospace, monospace" class="">synth.gain(<span class="gmail-s4">0</span>.<span class="gmail-s4">1</span>);</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p4"><font face="monospace, monospace" class="">// set parameters</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s4">1024</span><span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span>fft.size;</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s5">Windowing</span>.hamming(fft.size() / <span class="gmail-s4">2</span>) =&gt; fft.window;</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s5">Windowing</span>.hamming(fft.size() / <span class="gmail-s4">2</span>) =&gt; ifft.window;</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p4"><font face="monospace, monospace" class="">// place to hold the FFT data as it comes in</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s3">complex</span><span class="gmail-s2"> </span>spec[fft.size()/<span class="gmail-s4">2</span>];</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p4"><font face="monospace, monospace" class="">// place to store the accumulated FFT data, preload with zeroes</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s3">complex</span><span class="gmail-s2"> </span>acc[fft.size()/<span class="gmail-s4">2</span>];</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s3">for</span>(<span class="gmail-s4">0</span><span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">int</span><span class="gmail-s2"> </span>i;<span class="gmail-s2"> </span>i<span class="gmail-s2"> </span>&lt;<span class="gmail-s2"> </span>acc.cap();<span class="gmail-s2"> </span>i++)<span class="gmail-s2"> </span>{</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; </span>#(<span class="gmail-s4">0</span>,<span class="gmail-s2"> </span><span class="gmail-s4">0</span>)<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span>acc[i];</font></p><p class="gmail-p1"><font face="monospace, monospace" class="">}</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p4"><font face="monospace, monospace" class="">// do it!</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s3">spork</span><span class="gmail-s2"> </span>~<span class="gmail-s2"> </span>sawTune();</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s3">spork</span><span class="gmail-s2"> </span>~<span class="gmail-s2"> </span>accumulateFrequenciesViaFFT(fft.size()/<span class="gmail-s4">2</span>);</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p5"><font face="monospace, monospace" class="">while<span class="gmail-s2"> (</span>true<span class="gmail-s2">) {</span></font></p><p class="gmail-p5"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; </span><span class="gmail-s4">1</span><span class="gmail-s2">::</span>second<span class="gmail-s2"> =&gt; </span>now<span class="gmail-s2">;</span></font></p><p class="gmail-p1"><font face="monospace, monospace" class="">}</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s3">fun</span><span class="gmail-s2"> </span><span class="gmail-s3">void</span><span class="gmail-s2"> </span>accumulateFrequenciesViaFFT(<span class="gmail-s3">int</span><span class="gmail-s2"> </span>HALF_FFT_SIZE)<span class="gmail-s2"> </span>{</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; </span><span class="gmail-s4">4</span><span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">int</span><span class="gmail-s2"> </span>FILTER_SIZE;</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; </span><span class="gmail-s3">float</span><span class="gmail-s2"> </span>movingAverageMag[FILTER_SIZE][HALF_FFT_SIZE];</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; </span><span class="gmail-s3">float</span><span class="gmail-s2"> </span>movingAveragePhase[FILTER_SIZE][HALF_FFT_SIZE];</font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p5"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; </span>while<span class="gmail-s2">( </span>true<span class="gmail-s2"> )</span></font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; </span><span class="gmail-s2">{</span></font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span>fft.upchuck()<span class="gmail-s2"> </span>@=&gt;<span class="gmail-s2"> </span>blob;</font></p><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span>// get the data</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span>blob.cvals()<span class="gmail-s2"> </span>@=&gt;<span class="gmail-s2"> </span>spec;</font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span>// for every bin...</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s3">for</span>(<span class="gmail-s4">0</span><span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">int</span><span class="gmail-s2"> </span>i;<span class="gmail-s2"> </span>i<span class="gmail-s2"> </span>&lt;<span class="gmail-s2"> </span>spec.cap();<span class="gmail-s2"> </span>i++)<span class="gmail-s2"> </span>{</font></p><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// get the mag/phase for each bin by converting to polar</font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s2">spec[i]</span> <span class="gmail-s2">$</span> <span class="gmail-s3">polar</span> <span class="gmail-s2">=&gt;</span> <span class="gmail-s3">polar</span> <span class="gmail-s2">newBin;</span></font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// and get our running totals from acc</font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s2">acc[i]</span> <span class="gmail-s2">$</span> <span class="gmail-s3">polar</span> <span class="gmail-s2">=&gt;</span> <span class="gmail-s3">polar</span> <span class="gmail-s2">accBin;</span></font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// move old values down the line</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s3">for</span><span class="gmail-s2"> </span>(FILTER_SIZE<span class="gmail-s2"> </span>-<span class="gmail-s2"> </span><span class="gmail-s4">1</span><span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">int</span><span class="gmail-s2"> </span>j;<span class="gmail-s2"> </span>j<span class="gmail-s2"> </span>&gt;<span class="gmail-s2"> </span><span class="gmail-s4">0</span>;<span class="gmail-s2"> </span>j--)<span class="gmail-s2"> </span>{</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>movingAverageMag[j<span class="gmail-s2"> </span>-<span class="gmail-s2"> </span><span class="gmail-s4">1</span>][i]<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span>movingAverageMag[j][i];</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>movingAveragePhase[j<span class="gmail-s2"> </span>-<span class="gmail-s2"> </span><span class="gmail-s4">1</span>][i]<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span>movingAveragePhase[j][i];</font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s2">}</span> <span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span></font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// add in new value</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>newBin.mag<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span>movingAverageMag[<span class="gmail-s4">0</span>][i];</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>newBin.phase<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span>movingAveragePhase[<span class="gmail-s4">0</span>][i];</font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// get sums for averaging</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s3">float</span><span class="gmail-s2"> </span>magSum,<span class="gmail-s2"> </span>phaseSum;</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s3">for</span><span class="gmail-s2"> </span>(<span class="gmail-s4">0</span><span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">int</span><span class="gmail-s2"> </span>j;<span class="gmail-s2"> </span>j<span class="gmail-s2"> </span>&lt;<span class="gmail-s2"> </span>FILTER_SIZE;<span class="gmail-s2"> </span>j++)<span class="gmail-s2"> </span>{</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>movingAverageMag[j][i]<span class="gmail-s2"> </span>+=&gt;<span class="gmail-s2"> </span>magSum;</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>movingAveragePhase[j][i]<span class="gmail-s2"> </span>+=&gt;<span class="gmail-s2"> </span>phaseSum;</font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s2">}</span></font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s6">// average</span></font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>magSum/FILTER_SIZE<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">float</span><span class="gmail-s2"> </span>magAvg;</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>phaseSum/FILTER_SIZE<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">float</span><span class="gmail-s2"> </span>phaseAvg;</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>magAvg<span class="gmail-s2"> </span>*<span class="gmail-s2"> </span><span class="gmail-s4">0</span>.<span class="gmail-s4">005</span><span class="gmail-s2"> </span>+=&gt;<span class="gmail-s2"> </span>accBin.mag;</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>phaseAvg<span class="gmail-s2"> </span>*<span class="gmail-s2"> </span><span class="gmail-s4">0</span>.<span class="gmail-s4">005</span><span class="gmail-s2"> </span>+=&gt;<span class="gmail-s2"> </span>accBin.phase;</font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// let phase pass through</font></p><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//newBin.phase =&gt; accBin.phase;</font></p><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>/*Math.random2f(0, 2*pi) =&gt; accBin.phase;*/</font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p4"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// convert back to complex and put back in the acc array</font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s2">accBin</span> <span class="gmail-s2">$</span> <span class="gmail-s3">complex</span> <span class="gmail-s2">=&gt;</span> <span class="gmail-s2">acc[i];</span></font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s2">}</span></font></p><div class=""><span class="gmail-Apple-converted-space"><font face="monospace, monospace" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</font></span><br class="webkit-block-placeholder"></div><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span>ifft.transform(acc);</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span>(fft.size() / <span class="gmail-s4">4</span>)::<span class="gmail-s3">samp</span><span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">now</span>;</font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; </span><span class="gmail-s2">}</span></font></p><p class="gmail-p1"><font face="monospace, monospace" class="">}</font></p><p class="gmail-p3"><font face="monospace, monospace" class=""><br class=""></font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s3">fun</span><span class="gmail-s2"> </span><span class="gmail-s3">void</span><span class="gmail-s2"> </span>sawTune()<span class="gmail-s2"> </span>{</font></p><p class="gmail-p5"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; </span>while<span class="gmail-s2"> (</span>true<span class="gmail-s2">) {</span></font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s5">Math</span>.random2(<span class="gmail-s4">48</span>,<span class="gmail-s2"> </span><span class="gmail-s4">92</span>)<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span><span class="gmail-s3">int</span><span class="gmail-s2"> </span>midinote;</font></p><p class="gmail-p1"><font face="monospace, monospace" class=""><span class="gmail-s2">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s5">Math</span>.mtof(midinote)<span class="gmail-s2"> </span>=&gt;<span class="gmail-s2"> </span>synth.freq;</font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="gmail-s4">333</span><span class="gmail-s2">::</span><span class="gmail-s3">ms</span> <span class="gmail-s2">=&gt;</span> <span class="gmail-s3">now</span><span class="gmail-s2">;</span></font></p><p class="gmail-p6"><font face="monospace, monospace" class=""><span class="gmail-Apple-converted-space">&nbsp; &nbsp; </span><span class="gmail-s2">}</span></font></p><p class="gmail-p1"><font face="monospace, monospace" class="">}</font></p></div></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Sat, Oct 14, 2017 at 10:31 AM, Jascha Narveson <span dir="ltr" class="">&lt;<a href="mailto:jnarveson@wesleyan.edu" target="_blank" class="">jnarveson@wesleyan.edu</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br class="">
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.<br class="">
<br class="">
So I guess I’m looking to do two things:<br class="">
<br class="">
- avoid hearing attacks in the resynthesized sound from my “accumulated magnitudes” spectrum<br class="">
<br class="">
- 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.<br class="">
<br class="">
Thoughts?<br class="">
<br class="">
cheers,<br class="">
<br class="">
- jascha<br class="">
<br class="">
<br class="">
<br class="">
- - - - same thing, a bit better maybe - - - -<br class="">
<span class=""><br class="">
SinOsc synth =&gt; FFT fft =&gt; blackhole;<br class="">
UAnaBlob blob;<br class="">
IFFT ifft =&gt; dac;<br class="">
<br class="">
synth.freq(440);<br class="">
</span>synth.gain(0.5);<br class="">
<br class="">
<br class="">
second / samp =&gt; float srate;<br class="">
<br class="">
// set parameters<br class="">
1024 =&gt; fft.size;<br class="">
Windowing.hamming(fft.size() / 2) =&gt; fft.window;<br class="">
Windowing.hamming(fft.size() / 2) =&gt; ifft.window;<br class="">
<br class="">
// hold the FFT data as it comes in<br class="">
complex spec[fft.size()/2];<br class="">
<br class="">
// store the accumulated FFT data<br class="">
complex acc[fft.size()/2];<br class="">
<br class="">
// fill the accumulated complex spectral array with zeroes<br class="">
<span class="">for(0 =&gt; int i; i &lt; acc.cap(); i++) {<br class="">
&nbsp; #(0, 0) =&gt; acc[i];<br class="">
}<br class="">
<br class="">
</span>// spork shreds<br class="">
spork ~ synthTune();<br class="">
spork ~ accumulateMagnitudesViaFFT();<br class="">
<span class=""><br class="">
while (true) {<br class="">
&nbsp; 1::second =&gt; now;<br class="">
}<br class="">
<br class="">
</span>fun void accumulateMagnitudesViaFFT() {<br class="">
<span class="">&nbsp; while( true )<br class="">
&nbsp; {<br class="">
&nbsp; &nbsp; &nbsp; fft.upchuck() @=&gt; blob;<br class="">
&nbsp; &nbsp; &nbsp; // get the data<br class="">
&nbsp; &nbsp; &nbsp; blob.cvals() @=&gt; spec;<br class="">
<br class="">
&nbsp; &nbsp; &nbsp; // for every bin...<br class="">
&nbsp; &nbsp; &nbsp; for(0 =&gt; int i; i &lt; spec.cap(); i++) {<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; // get the mag/phase for each bin by converting to polar<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; spec[i] $ polar =&gt; polar newBin;<br class="">
<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; // and get our running totals from acc<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; acc[i] $ polar =&gt; polar accBin;<br class="">
<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; // scale the inocming mag and add it to acc<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; newBin.mag * 0.001 +=&gt; accBin.mag;<br class="">
<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; // let phase pass through<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; newBin.phase =&gt; accBin.phase;<br class="">
<br class="">
</span>&nbsp; &nbsp; &nbsp; &nbsp; // conver back to complex and put back in the acc array<br class="">
<span class="">&nbsp; &nbsp; &nbsp; &nbsp; accBin $ complex =&gt; acc[i];<br class="">
&nbsp; &nbsp; &nbsp; }<br class="">
<br class="">
&nbsp; &nbsp; &nbsp; ifft.transform(acc);<br class="">
</span>&nbsp; &nbsp; &nbsp; (fft.size() / 4)::samp =&gt; now;<br class="">
&nbsp; }<br class="">
}<br class="">
<br class="">
fun void synthTune() {<br class="">
<span class="">&nbsp; while (true) {<br class="">
&nbsp; &nbsp; Math.random2(48, 72) =&gt; int midinote;<br class="">
&nbsp; &nbsp; Math.mtof(midinote) =&gt; synth.freq;<br class="">
&nbsp; &nbsp; 333::ms =&gt; now;<br class="">
</span>&nbsp; &nbsp; &lt;&lt;&lt;acc[6] $ polar &gt;&gt;&gt;; // just to check - yep: they're getting bigger...<br class="">
<div class="HOEnZb"><div class="h5">&nbsp; }<br class="">
}<br class="">
<br class="">
<br class="">
<br class="">
&gt; On Oct 14, 2017, at 12:26 PM, Jascha Narveson &lt;<a href="mailto:jnarveson@wesleyan.edu" class="">jnarveson@wesleyan.edu</a>&gt; wrote:<br class="">
&gt;<br class="">
&gt;<br class="">
&gt; Chuck list! Help!<br class="">
&gt;<br class="">
&gt; I have the following idea and I’d like to hear what it sounds like:<br class="">
&gt;<br class="">
&gt; - play a sound into an FFT<br class="">
&gt; - as the FFT runs, for each bin:<br class="">
&gt; - - look at the magnitude info<br class="">
&gt; - - take a small fraction of this info and store it in a running total<br class="">
&gt; - - let the phase pass through unchanged<br class="">
&gt; - use the spectral data in the running total for the IFFT<br class="">
&gt;<br class="">
&gt; 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.<br class="">
&gt;<br class="">
&gt; What I’m getting is the attacks of the original sound coming through, although fading in, and covered with noise.<br class="">
&gt;<br class="">
&gt; I think I’m doing something wrong by not doing something with the phase, but I’m not sure what.<br class="">
&gt;<br class="">
&gt; I’d love some advice…<br class="">
&gt;<br class="">
&gt; cheers,<br class="">
&gt;<br class="">
&gt; j<br class="">
&gt;<br class="">
&gt;<br class="">
&gt; - - - - c o d e&nbsp; e x a m p l e - - - -<br class="">
&gt;<br class="">
&gt; SinOsc synth =&gt; FFT fft =&gt; blackhole;<br class="">
&gt; UAnaBlob blob;<br class="">
&gt; IFFT ifft =&gt; dac;<br class="">
&gt;<br class="">
&gt; synth.freq(440);<br class="">
&gt; synth.gain(0.1);<br class="">
&gt;<br class="">
&gt; // set parameters<br class="">
&gt; 2048 =&gt; fft.size;<br class="">
&gt;<br class="">
&gt; // place to hold the FFT data as it comes in<br class="">
&gt; complex spec[fft.size()/2];<br class="">
&gt;<br class="">
&gt; // place to store the accumulated FFT data, preload with zeroes<br class="">
&gt; complex acc[fft.size()/2];<br class="">
&gt; for(0 =&gt; int i; i &lt; acc.cap(); i++) {<br class="">
&gt;&nbsp; #(0, 0) =&gt; acc[i];<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; // do it!<br class="">
&gt; spork ~ sawTune();<br class="">
&gt; spork ~ accumulateFrequenciesViaFFT();<br class="">
&gt;<br class="">
&gt; while (true) {<br class="">
&gt;&nbsp; 1::second =&gt; now;<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; fun void accumulateFrequenciesViaFFT() {<br class="">
&gt;&nbsp; while( true )<br class="">
&gt;&nbsp; {<br class="">
&gt;&nbsp; &nbsp; &nbsp; fft.upchuck() @=&gt; blob;<br class="">
&gt;&nbsp; &nbsp; &nbsp; // get the data<br class="">
&gt;&nbsp; &nbsp; &nbsp; blob.cvals() @=&gt; spec;<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; &nbsp; // for every bin...<br class="">
&gt;&nbsp; &nbsp; &nbsp; for(0 =&gt; int i; i &lt; spec.cap(); i++) {<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // get the mag/phase for each bin by converting to polar<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; spec[i] $ polar =&gt; polar newBin;<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // and get our running totals from acc<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; acc[i] $ polar =&gt; polar accBin;<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // scale the inocming mag and add it to acc<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; newBin.mag * 0.001 +=&gt; accBin.mag;<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // let phase pass through<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; newBin.phase =&gt; accBin.phase;<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/*Math.random2f(0, TWO_PI) =&gt; accBin.phase;*/<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; // convert back to complex and put back in the acc array<br class="">
&gt;&nbsp; &nbsp; &nbsp; &nbsp; accBin $ complex =&gt; acc[i];<br class="">
&gt;&nbsp; &nbsp; &nbsp; }<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; &nbsp; ifft.transform(acc);<br class="">
&gt;&nbsp; &nbsp; &nbsp; fft.size()::samp =&gt; now;<br class="">
&gt;&nbsp; }<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; fun void sawTune() {<br class="">
&gt;&nbsp; while (true) {<br class="">
&gt;&nbsp; &nbsp; Math.random2(48, 72) =&gt; int midinote;<br class="">
&gt;&nbsp; &nbsp; Math.mtof(midinote) =&gt; synth.freq;<br class="">
&gt;&nbsp; &nbsp; 333::ms =&gt; now;<br class="">
&gt;&nbsp; }<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; ______________________________<wbr class="">_________________<br class="">
&gt; chuck-users mailing list<br class="">
&gt; <a href="mailto:chuck-users@lists.cs.princeton.edu" class="">chuck-users@lists.cs.<wbr class="">princeton.edu</a><br class="">
&gt; <a href="https://lists.cs.princeton.edu/mailman/listinfo/chuck-users" rel="noreferrer" target="_blank" class="">https://lists.cs.princeton.<wbr class="">edu/mailman/listinfo/chuck-<wbr class="">users</a><br class="">
<br class="">
______________________________<wbr class="">_________________<br class="">
chuck-users mailing list<br class="">
<a href="mailto:chuck-users@lists.cs.princeton.edu" class="">chuck-users@lists.cs.<wbr class="">princeton.edu</a><br class="">
<a href="https://lists.cs.princeton.edu/mailman/listinfo/chuck-users" rel="noreferrer" target="_blank" class="">https://lists.cs.princeton.<wbr class="">edu/mailman/listinfo/chuck-<wbr class="">users</a><br class="">
</div></div></blockquote></div><br class=""></div>
_______________________________________________<br class="">chuck-users mailing list<br class=""><a href="mailto:chuck-users@lists.cs.princeton.edu" class="">chuck-users@lists.cs.princeton.edu</a><br class=""><a href="https://lists.cs.princeton.edu/mailman/listinfo/chuck-users" class="">https://lists.cs.princeton.edu/mailman/listinfo/chuck-users</a><br class=""></div></blockquote></div><br class=""></div></div>_______________________________________________<br class="">chuck-users mailing list<br class=""><a href="mailto:chuck-users@lists.cs.princeton.edu" class="">chuck-users@lists.cs.princeton.edu</a><br class="">https://lists.cs.princeton.edu/mailman/listinfo/chuck-users<br class=""></div></blockquote></div><br class=""></body></html>