5858// Obscure audio magic happens here
5959void IRAM_ATTR process_GDFT () {
6060 static bool interlace_flip = false;
61- interlace_flip = !interlace_flip ; // Switch field every frame on lower notes to save execution time
62-
61+ interlace_flip = !interlace_flip ; // Switch field every frame on lower notes to save execution time
62+
6363 // Reset magnitude caps every frame
6464 for (uint8_t i = 0 ; i < NUM_ZONES ; i ++ ) {
65- max_mags [i ] = CONFIG .MAGNITUDE_FLOOR ; // Higher than the average noise floor
65+ max_mags [i ] = CONFIG .MAGNITUDE_FLOOR / CONFIG . SENSITIVITY ; // Higher than the average noise floor
6666 }
6767
6868 // Increment spectrogram history index
@@ -73,10 +73,10 @@ void IRAM_ATTR process_GDFT() {
7373
7474 // Run GDFT (Goertzel-based Discrete Fourier Transform) with 64 frequencies
7575 // Fixed-point code adapted from example here: https://sourceforge.net/p/freetel/code/HEAD/tree/misc/goertzal/goertzal.c
76- for (uint16_t i = 0 ; i < NUM_FREQS ; i ++ ) { // Run 64 times
77- bool field = bitRead (i , 0 ); // odd or even
76+ for (uint16_t i = 0 ; i < NUM_FREQS ; i ++ ) { // Run 64 times
77+ bool field = bitRead (i , 0 ); // odd or even
7878
79- // If note is part of field being rendered, is >= index 16, or is the first note
79+ // If note is part of field being rendered, is >= index 16, or is the first note
8080 if (field == interlace_flip || i >= 16 ) {
8181 int32_t q0 , q1 , q2 ;
8282 int64_t mult ;
@@ -85,9 +85,10 @@ void IRAM_ATTR process_GDFT() {
8585 q2 = 0 ;
8686
8787 float window_pos = 0.0 ;
88- for (uint16_t n = 0 ; n < frequencies [i ].block_size ; n ++ ) { // Run Goertzel for "block_size" iterations
88+ for (uint16_t n = 0 ; n < frequencies [i ].block_size ; n ++ ) { // Run Goertzel for "block_size" iterations
8989 int32_t sample = 0 ;
90- sample = ((int32_t )sample_window [SAMPLE_HISTORY_LENGTH - 1 - n ] * (int32_t )window_lookup [uint16_t (window_pos )]) >> 16 ;
90+ //sample = ((int32_t)sample_window[SAMPLE_HISTORY_LENGTH - 1 - n] * (int32_t)window_lookup[uint16_t(window_pos)]) >> 16;
91+ sample = (int32_t )sample_window [SAMPLE_HISTORY_LENGTH - 1 - n ];
9192 mult = (int64_t )frequencies [i ].coeff_q14 * (int64_t )q1 ;
9293 q0 = (sample >> 6 ) + (mult >> 14 ) - q2 ;
9394 q2 = q1 ;
@@ -97,7 +98,7 @@ void IRAM_ATTR process_GDFT() {
9798 }
9899
99100 mult = (int64_t )frequencies [i ].coeff_q14 * (int64_t )q1 ;
100- magnitudes [i ] = q2 * q2 + q1 * q1 - ((int32_t )(mult >> 14 )) * q2 ; // Calculate raw magnitudes
101+ magnitudes [i ] = q2 * q2 + q1 * q1 - ((int32_t )(mult >> 14 )) * q2 ; // Calculate raw magnitudes
101102
102103 // Normalize output
103104 magnitudes [i ] *= float (frequencies [i ].block_size_recip );
@@ -110,7 +111,7 @@ void IRAM_ATTR process_GDFT() {
110111 }
111112 magnitudes [i ] *= prog ;
112113
113- if (magnitudes [i ] < 0.0 ) { // Prevent negative values
114+ if (magnitudes [i ] < 0.0 ) { // Prevent negative values
114115 magnitudes [i ] = 0.0 ;
115116 }
116117 }
@@ -139,23 +140,27 @@ void IRAM_ATTR process_GDFT() {
139140 }
140141 }
141142 noise_iterations ++ ;
142- if (noise_iterations >= 256 ) { // Calibration complete
143+ if (noise_iterations >= 1024 ) { // Calibration complete
143144 noise_complete = true;
144145 USBSerial .println ("NOISE CAL COMPLETE" );
145- CONFIG .DC_OFFSET = dc_offset_sum / 256 .0 ; // Calculate average DC offset and store it
146- save_ambient_noise_calibration (); // Save results to noise_cal.bin
147- save_config (); // Save config to config.bin
146+ CONFIG .DC_OFFSET = dc_offset_sum / 1024 .0 ; // Calculate average DC offset and store it
147+ save_ambient_noise_calibration (); // Save results to noise_cal.bin
148+ save_config (); // Save config to config.bin
148149 }
149150 }
150151
151152 // Apply noise reduction data, estimate max values
152153 for (uint8_t i = 0 ; i < NUM_FREQS ; i += 1 ) {
153154 if (noise_complete == true) {
154- magnitudes [i ] -= noise_samples [i ] * 1.2 ; // Treat noise 1.2x louder than calibration
155+ magnitudes [i ] -= noise_samples [i ] * 1.5 ; // Treat noise 1.5x louder than calibration
155156 if (magnitudes [i ] < 0.0 ) {
156157 magnitudes [i ] = 0.0 ;
157158 }
158159 }
160+ }
161+
162+ for (uint8_t i = 0 ; i < NUM_FREQS ; i ++ ) {
163+ //magnitudes[i] *= magnitude_scale;
159164
160165 mag_targets [i ] = magnitudes [i ];
161166 if (mag_targets [i ] > max_mags [frequencies [i ].zone ]) {
@@ -236,12 +241,12 @@ void IRAM_ATTR process_GDFT() {
236241 for (uint8_t i = 0 ; i < NUM_FREQS ; i += 1 ) {
237242 if (mag_targets [i ] > mag_followers [i ]) {
238243 float delta = mag_targets [i ] - mag_followers [i ];
239- mag_followers [i ] += delta * (smoothing_follower * 0.45 );
244+ mag_followers [i ] += delta * (smoothing_follower * 0.65 );
240245 }
241246
242247 else if (mag_targets [i ] < mag_followers [i ]) {
243248 float delta = mag_followers [i ] - mag_targets [i ];
244- mag_followers [i ] -= delta * (smoothing_follower * 0.55 );
249+ mag_followers [i ] -= delta * (smoothing_follower * 0.75 );
245250 }
246251 }
247252
@@ -250,11 +255,11 @@ void IRAM_ATTR process_GDFT() {
250255 for (uint8_t i = 0 ; i < NUM_ZONES ; i ++ ) {
251256 if (max_mags [i ] > max_mags_followers [i ]) {
252257 float delta = max_mags [i ] - max_mags_followers [i ];
253- max_mags_followers [i ] += delta * 0.05 ;
258+ max_mags_followers [i ] += delta * 0.0125 ;
254259 }
255260 if (max_mags [i ] < max_mags_followers [i ]) {
256261 float delta = max_mags_followers [i ] - max_mags [i ];
257- max_mags_followers [i ] -= delta * 0.05 ;
262+ max_mags_followers [i ] -= delta * 0.0125 ;
258263 }
259264 }
260265
@@ -269,12 +274,21 @@ void IRAM_ATTR process_GDFT() {
269274 USBSerial .println ("))" );
270275 }
271276
277+ float max_mag = CONFIG .MAGNITUDE_FLOOR / CONFIG .SENSITIVITY ;
278+ for (uint8_t i = 0 ; i < NUM_ZONES ; i ++ ) {
279+ if (max_mags_followers [i ] > max_mag ) {
280+ max_mag = max_mags_followers [i ];
281+ }
282+ }
283+
272284 // Make Spectrogram from raw magnitudes
273285 for (uint8_t i = 0 ; i < NUM_FREQS ; i += 1 ) {
274286 // Normalize our frequency bins to 0.0-1.0 range, which acts like an audio compressor at the same time
275287 float max_mag = interpolate (i / float (NUM_FREQS ), max_mags_followers , NUM_ZONES );
276288 float mag_float = mag_followers [i ] / max_mag ;
277289
290+ //mag_float *= 2.0;
291+
278292 // Restrict range, allowing for clipped values at peaks and valleys
279293 if (mag_float < 0.0 ) {
280294 mag_float = 0.0 ;
@@ -286,37 +300,50 @@ void IRAM_ATTR process_GDFT() {
286300 mag_float = mag_float * (1.0 - smoothing_exp_average ) + mag_float_last [i ] * smoothing_exp_average ;
287301 mag_float_last [i ] = mag_float ;
288302
289- mag_float *= (CONFIG .GAIN );
303+ // mag_float *= (CONFIG.GAIN);
290304 if (mag_float > 1.0 ) {
291305 mag_float = 1.0 ;
292306 }
293307
308+ mag_float = sqrt (sqrt (mag_float ));
309+
294310 note_spectrogram [i ] = mag_float ; // This array is the current value
295311 spectrogram_history [spectrogram_history_index ][i ] = note_spectrogram [i ]; // This array is the value's history
296312 }
313+ }
297314
315+ float calc_punch (uint8_t low_bin , uint8_t high_bin ) {
316+ const float push_max = 100000.0 ;
317+ float punch_pos_decay = 0.0 ;
298318
299- // Make Chromagram
300- chromagram_max_val = 0.0 ;
301- for (uint8_t i = 0 ; i < 12 ; i ++ ) {
302- note_chromagram [i ] = 0 ;
303- }
304- for (uint8_t octave = 0 ; octave < 6 ; octave ++ ) {
305- for (uint8_t note = 0 ; note < 12 ; note ++ ) {
306- uint16_t note_index = 12 * octave + note ;
307- if (note_index < NUM_FREQS && note_index < CONFIG .CHROMAGRAM_RANGE ) {
308- note_chromagram [note ] += note_spectrogram [note_index ] * 0.5 ;
319+ float smoothing = 0.128 ;
320+ float punch_pos = 0.0 ;
309321
310- if (note_chromagram [note ] > 1.0 ) {
311- note_chromagram [note ] = 1.0 ;
312- }
322+ float punch_scaling = NUM_FREQS / (high_bin - low_bin );
313323
314- if ( note_chromagram [ note ] > chromagram_max_val ) {
315- chromagram_max_val = note_chromagram [ note ];
316- }
317- }
324+ for ( uint8_t i = low_bin ; i < high_bin ; i ++ ) {
325+ float delta = spectrogram_history [ 2 ][ i ] * spectrogram_history [ 2 ][ i ] - spectrogram_history [ 0 ][ i ] * spectrogram_history [ 0 ][ i ];
326+ if ( delta < 0.0 ) {
327+ delta = 0.0 ;
318328 }
329+ punch_pos += (delta * punch_scaling );
330+ }
331+
332+ if (punch_pos > 1.0 ) {
333+ punch_pos = 1.0 ;
334+ }
335+
336+ float punch_pos_smooth = 0.0 ;
337+ punch_pos_smooth = punch_pos * (smoothing ) + punch_pos_smooth * (1.0 - smoothing );
338+
339+ punch_pos_decay *= 0.9 ;
340+
341+ if (punch_pos_smooth > punch_pos_decay ) {
342+ punch_pos_decay = punch_pos_smooth ;
319343 }
344+
345+ float punch = push_max * (punch_pos_decay * punch_pos_decay * punch_pos_decay * punch_pos_decay * punch_pos_decay );
346+ return punch ;
320347}
321348
322349void lookahead_smoothing () {
@@ -372,6 +399,40 @@ void lookahead_smoothing() {
372399 note_spectrogram_long_term [i ] = (note_spectrogram_long_term [i ] * 0.95 ) + (note_spectrogram_smooth [i ] * 0.05 );
373400 }
374401
402+ for (uint8_t i = 0 ; i < NATIVE_RESOLUTION ; i ++ ) {
403+ //note_spectrogram_smooth[i] = (note_spectrogram_smooth[i] + note_spectrogram_smooth_frame_blending[i]) * 0.5;
404+
405+ if (note_spectrogram_smooth [i ] > 1.0 ) {
406+ note_spectrogram_smooth [i ] = 1.0 ;
407+ }
408+
409+ note_spectrogram_smooth_frame_blending [i ] = note_spectrogram_smooth [i ];
410+ }
411+
412+ // Make Chromagram
413+ chromagram_max_val = 0.0 ;
414+ for (uint8_t i = 0 ; i < 12 ; i ++ ) {
415+ note_chromagram [i ] = 0 ;
416+ }
417+
418+ for (uint8_t octave = 0 ; octave < 6 ; octave ++ ) {
419+ for (uint8_t note = 0 ; note < 12 ; note ++ ) {
420+ uint16_t note_index = 12 * octave + note ;
421+ if (note_index < NUM_FREQS && note_index < CONFIG .CHROMAGRAM_RANGE ) {
422+ if (note_spectrogram_smooth [note_index ] > note_chromagram [note ]) {
423+ note_chromagram [note ] = note_spectrogram_smooth [note_index ];
424+ }
425+
426+ if (note_chromagram [note ] > chromagram_max_val ) {
427+ chromagram_max_val = note_chromagram [note ];
428+ }
429+ }
430+ }
431+ }
432+
433+ // Calculate "punch" of the full frequency range (used by auto color-cycling)
434+ current_punch = calc_punch (0 , NUM_FREQS ); // (lightshow_modes.h)
435+
375436 if (stream_spectrogram == true) {
376437 if (serial_iter >= 2 ) { // Don't print every frame
377438 serial_iter = 0 ;
@@ -386,4 +447,19 @@ void lookahead_smoothing() {
386447 USBSerial .println ("))" );
387448 }
388449 }
450+
451+ if (stream_chromagram == true) {
452+ if (serial_iter >= 2 ) { // Don't print every frame
453+ serial_iter = 0 ;
454+ USBSerial .print ("sbs((chromagram=" );
455+ for (uint16_t i = 0 ; i < 12 ; i ++ ) {
456+ uint16_t bin = 999 * note_chromagram [i ];
457+ USBSerial .print (bin );
458+ if (i < 12 - 1 ) {
459+ USBSerial .print (',' );
460+ }
461+ }
462+ USBSerial .println ("))" );
463+ }
464+ }
389465}
0 commit comments