desc:Saike Spectral Analyzer (beta) tags: analysis FFT meter spectrum version: 5.0.36 author: Joep Vanlier, Trond-Viggo Melssen, Cockos, Feed The Cat changelog: Force channel 1 and 2 to always be active in diff mode for convenience. provides: colormaps.jsfx-inc Copyright (C) 2007 Cockos Incorporated Copyright (C) 2018 Joep Vanlier, Trond-Viggo Melssen License: LGPL - http://www.gnu.org/licensses/lgpl.html This file was modified by Joep Vanlier and Trond-Viggo Melssen to enable multispectrum analysis analysis, sonogram and time domain plots. Thanks to cjewellstudios for the smooth colormap. options:maxmem=5000000 import colormaps.jsfx-inc slider1:9<0,9,1{16,32,64,128,256,512,1024,2048,4096,8192,16384,32768}>-FFT size slider2:-90<-450,-12,6>-floor slider3:0<0,1,1{disabled,enabled}>-show phase slider4:2<0,6,1{rectangular,hamming,blackman-harris,blackman,flat-top,gaussian}>-window slider5:200<0,2500,1>-integration time (ms) slider6:1<1,6,.2>-scaling slider7:smoothing=20<0,100,1>-smoothing slider8:1<0,14,1{dark,intense,fluo,colorblind,pimp,shades,fancy,pastel,purple,dark2,dark3,dark4,dark5,colorblind2,smooth}>-colormap slider9:16<1,16,1>-mxchannels slider10:.15<0,1,.4>-colorBackground slider11:1<0,1,1>-Ch1 slider12:1<0,1,1>-Ch2 slider13:0<0,1,1>-Ch3 slider14:0<0,1,1>-Ch4 slider15:0<0,1,1>-Ch5 slider16:0<0,1,1>-Ch6 slider17:0<0,1,1>-Ch7 slider18:0<0,1,1>-Ch8 slider19:0<0,1,1>-Ch9 slider20:0<0,1,1>-Ch10 slider21:0<0,1,1>-Ch11 slider22:0<0,1,1>-Ch12 slider23:0<0,1,1>-Ch13 slider24:0<0,1,1>-Ch14 slider25:0<0,1,1>-Ch15 slider26:0<0,1,1>-Ch16 slider27:1<0,1,1>-Sum slider28:-1<-1,1,16>-Channel slider29:0<1,0,3{Sonogram,Sample,Sample all,Off}>-Sonogram slider30:5000<10,45000,100>-SonoScale slider31:.5<0.1,3,.03>-SignalScale slider32:6<0,7,1{viridis,viridisinv,magma,magmainv,inferno,infernoinv,plasma,plasmainv}>-colormap2 slider33:1<1,0,1{Logarithmic,Linear}>-Sonolog slider34:0<0,0,1{Yes,No}>-SonoBig slider35:1<1,8,1>-Factor slider36:-1<-1,1,16>-Solo channel slider37:.15<0,1,.4>-Alpha slider38:0<0,9,.25>-slope slider39:1<0,1,1{disabled,enabled}>-show grid slider40:.15<0,1,.4>-gridAlpha slider41:0<0,1,1{disabled,enabled}>-show channels slider42:0<0,1,1{disabled,enabled}>-show options slider43:0<0,1,1{disabled,enabled}>-show theme slider44:0<0,1,1{disabled,enabled}>-freeze spectrum slider45:4<0,4,1{Average,Maximum,Loess,Adaptive,Fast}>-Smoothing method slider46:sonoGridAlpha=0.4<0,1,0.001>-Sonogram Grid Alpha slider47:Dummy=0<0,1,1>-Dummy slider48:Dummy=0<0,1,1>-Dummy slider49:Dummy=0<0,1,1>-Dummy slider50:0<0,1,0>-Initialized slider51:LatencyCompensation=0<0,1,0>-Latency Compensation slider52:Dummy=0<0,1,1>-Dummy slider53:showA=0<0,1,1>-Show A slider54:showB=0<0,1,1>-Show B slider55:maxIntegrate=0<0,1,0>-Integration mode slider56:showSide=0<0,1,0>-Show side channel slider57:noRenderBuffer=0<0,1,1>-Offscreen buffer slider58:interpolate_lines=0<0,1,1>-interpolate_lines slider59:dummy=0<0,1,1>-Dummy slider60:displayMode=0<0,1,1>-Display mode slider61:scale_offset_db_user=0<-48,48,1>-Scale offset slider62:sync=0<0,4,1>-Sync slider63:offset_x=0<0,0.5,0.00001>-shift //in_pin:left input //in_pin:right input options:no_meter options:gmem=saike_spectrum_analyzer @init lastIntegrate = -1; sono_sample = 0; last_sono_sample = 0; version = 2; chNames = 900; memory_debugging = 0; !memory_debugging ? ( ext_noinit = 1; ); copyTo = 0; magma = 1000; viridis = 2000; inferno = 3000; plasma = 4000; turbo = 5000; bluered = 6000; !sono_frac ? sono_frac = .35; freeze = 0; function setChannelNames() local(chName) global(chNames) ( chName = 1; while (chName <= 16) ( chName < 10 ? ( chNames[chName-1] = sprintf(chName-1, "Ch %d", chName); ) : ( chNames[chName-1] = sprintf(chName-1, "Ch%d", chName); ); chName = chName + 1; ); ); !trCnt ? setChannelNames(); function updateChannelSliders() global(slider11, slider12, slider13, slider14, slider15, slider16, slider17, slider18, slider19, slider20, slider21, slider22, slider23, slider24, slider25, slider26, slider27, slider28, num_ch, actc, activechannels, max_active_channels, displayMode, showSum) local(mx, ix) ( // For some reason this isn't being called in @slider actc = activechannels; ix = 0; loop(16, (ix > (num_ch / 2)) ? ( slider(11 + ix) = 0; ); ix += 1; ); (slider28 >= (num_ch / 2)) ? ( slider28 = 0; ); mx = 0; actc[] = slider11 ? (mx=1; 1); actc[1] = slider12 ? (mx=2; 1); actc[2] = slider13 ? (mx=3; 1); actc[3] = slider14 ? (mx=4; 1); actc[4] = slider15 ? (mx=5; 1); actc[5] = slider16 ? (mx=6; 1); actc[6] = slider17 ? (mx=7; 1); actc[7] = slider18 ? (mx=8; 1); actc[8] = slider19 ? (mx=9; 1); actc[9] = slider20 ? (mx=10; 1); actc[10] = slider21 ? (mx=11; 1); actc[11] = slider22 ? (mx=12; 1); actc[12] = slider23 ? (mx=13; 1); actc[13] = slider24 ? (mx=14; 1); actc[14] = slider25 ? (mx=15; 1); actc[15] = slider26 ? (mx=16; 1); (displayMode == 1) ? ( actc[] = actc[1] = 1; ); max_active_channels = max(mx, slider28); /* Slider28 contains the channel monitored on the sonogram */ showSum = slider27; ); function initCh() global(slider50, num_ch) local(ix) ( (slider50 == 0) ? ( ix = 0; loop(16, slider(11 + ix) = (ix < (num_ch / 2)); ix += 1; ); updateChannelSliders(); slider50 = 1; ) ); function printColorMapName(cmapidx, inv) ( ( cmapidx == 1 && inv == 0 ) ? gfx_printf( "Magma" ) : ( ( cmapidx == 1 && inv == 1 ) ? gfx_printf( "Magma inv" ) : ( ( cmapidx == 2 && inv == 0 ) ? gfx_printf( "Viridis" ) : ( ( cmapidx == 2 && inv == 1 ) ? gfx_printf( "Viridis inv" ) : ( ( cmapidx == 3 && inv == 0 ) ? gfx_printf( "Inferno" ) : ( ( cmapidx == 3 && inv == 1 ) ? gfx_printf( "Inferno inv" ) : ( ( cmapidx == 4 && inv == 0 ) ? gfx_printf( "Plasma" ) : ( ( cmapidx == 4 && inv == 1 ) ? gfx_printf( "Plasma inv" ) : ( gfx_printf("Unknown"); )))))))); ); gfx_ext_retina = 1.0; ext_nodenorm = 1; gfx_clear = -1; windowtype = -1; fftidx = -1; scaling = 1; max_fft_size = 32768; fftsize = max_fft_size; mem_block_size = 0.5 * max_fft_size; window = max_fft_size; /* Location of the window */ histsize = 4 * max_fft_size; /* Size of the audio buffer */ SONOSURFACE = 4; gfx_dest = SONOSURFACE; gfx_setimgdim(SONOSURFACE, 0.5*fftsize, 0.5*fftsize); gfx_x=gfx_y = 0; gfx_r=gfx_g = 0; gfx_b = 0; gfx_a = 1; gfx_rectto(0.5*fftsize, 0.5*fftsize); gfx_dest = -1; drawHz = 0; update = slider44 == 0; function init_memory_mapping() local(rpos, freemem, rpos, hsize, fftw, ibuf, csh, channel_offset, endpoints) global(recpositions, histsizes, fftworkspaces, integrate_bufs, shifts, activechannels, maxchannels, offscreenbuf, M_BLOCK_SIZE, window, histsize, max_fft_size, maxIntegrate, filtout, filtout2, sumshl, sumshr, sumposl, sumposr, fftwl, fftwr, ibufl, ibufr, sumhsl, sumhsr latencyBuffer, latencyBufferMax, latencyPtr, memA, memB, memA2, memB2,memory_debugging, ch_endpoints, mem_block_size, rec_positions_copy) ( memory_debugging ? ( memset(65536, 0, 512*512*1024); ); updateChannelSliders(); // Hardcoded ptr positions; note that 10000 - 30000 are taken by the colormaps recpositions = 100; histsizes = 200; fftworkspaces = 300; integrate_bufs = 400; shifts = 500; activechannels = 600; ch_endpoints = 700; rec_positions_copy = 800; maxchannels = 16; offscreenbuf = 1; M_BLOCK_SIZE = 65536; freemem = histsize + max_fft_size; // Post window and color map // Memory for the filter on the spectrum freemem = (filtout = freemem) + max_fft_size; // Should only be 0.5 * fftsize; but not clean atm memset(filtout, 0, max_fft_size); freemem = (filtout2 = freemem) + max_fft_size; memset(filtout2, 0, max_fft_size); // Memory for the sum signals freemem = (sumshl = sumposl = freemem) + histsize; // Buffer start sumhsl = freemem; // Buffer end freemem = (fftwl = freemem) + max_fft_size; freemem = (ibufl = freemem) + max_fft_size; freemem = (sumshr = sumposr = freemem) + histsize; // Buffer start sumhsr = freemem; // Buffer end freemem = (fftwr = freemem) + max_fft_size; freemem = (ibufr = freemem) + max_fft_size; memset(ibufl, - 100 * maxIntegrate, max_fft_size); memset(ibufr, - 100 * maxIntegrate, max_fft_size); // Buffer for delay compensation freemem = (latencyPtr = latencyBuffer = freemem) + max_fft_size; latencyBufferMax = freemem; memset(latencyBuffer, 0, latencyBufferMax - latencyBuffer); /* These blocks are needlessly big, but serialization needs to have a migration path if they are to be changed */ freemem = (memA = freemem) + mem_block_size; freemem = (memB = freemem) + mem_block_size; freemem = (memA2 = freemem) + mem_block_size; freemem = (memB2 = freemem) + mem_block_size; rpos = recpositions; hsize = histsizes; fftw = fftworkspaces; ibuf = integrate_bufs; csh = shifts; endpoints = ch_endpoints; loop(maxchannels, channel_offset = 0; loop(2, freemem = ((csh + channel_offset)[] = (rpos + channel_offset)[] = freemem) + histsize; // Buffer start (hsize + channel_offset)[] = freemem; // Buffer end freemem = ((fftw + channel_offset)[] = freemem) + max_fft_size; // Length of fftw space is max_fft_size freemem = ((ibuf + channel_offset)[] = freemem) + max_fft_size; // Integration buffer is 0.5 * fftsize long, we round off to a full fft size channel_offset = maxchannels; ); endpoints[] = freemem; rpos += 1; hsize += 1; fftw += 1; ibuf += 1; csh += 1; endpoints += 1; ); freemem ); (memA == 0 || memory_debugging) ? (total_mem = init_memory_mapping()); @serialize file_var(0, version); file_var(0, mem_block_size); file_mem(0, memA, mem_block_size); file_mem(0, memB, mem_block_size); file_mem(0, memA2, mem_block_size); file_mem(0, memB2, mem_block_size); file_var(0, sModeA); file_var(0, kernelSizeA); file_var(0, fftSizeA); file_var(0, xscaleA); file_var(0, sModeB); file_var(0, kernelSizeB); file_var(0, fftSizeB); file_var(0, xscaleB); file_var(0, showNotes); file_var(0, legacy_style); file_var(0, hide_spectrum); file_var(0, fast_proc); @slider slider2 != lfloor ? old_w=0; updateChannelSliders(); @block max_active_channels > 0 ? ( new_mem_endpoint = ch_endpoints[max_active_channels - 1]; (new_mem_endpoint != mem_endpoint) ? ( mem_endpoint = new_mem_endpoint; freembuf(mem_endpoint); ); ); displayMode != lastDisplayMode ? ( lastDisplayMode = displayMode; init_memory_mapping(); ); slider2 != lfloor ? ( lfloor = slider2; minvol=2*exp(log(10)/20*slider2); ); @sample sono_sample += 1; updateSliders ? ( updateSliders = 0; updateChannelSliders(); ); function update() local(jch, active, recpos, hs, sh, sl, sr, iLoad, left_signal, right_signal) global(activechannels, recpositions, histsizes, shifts, slider44, maxchannels, max_active_channels, slider28, showSide, sumposl, sumposr, sumhsl, sumshl, sumhsr, sumshr, num_ch) ( iLoad = 0; jch = 0; sl = 0; sr = 0; ( slider44 == 0 ) ? ( active = activechannels; recpos = recpositions; hs = histsizes; sh = shifts; loop(num_ch * 0.5, left_signal = spl(jch); right_signal = spl(jch + 1); (active[] == 1 || (slider28==iLoad)) ? ( recpos[][] = 0.5 * (left_signal + right_signal); recpos[] = ((recpos[]+1) >= hs[] ? sh[] : (recpos[]+1)); ); sl = sl + left_signal; sr = sr + right_signal; active += 1; recpos += 1; hs += 1; sh += 1; jch += 2; iLoad += 1; ); showSide ? ( jch = 0; iLoad = 0; active = activechannels; recpos = recpositions + maxchannels; hs = histsizes + maxchannels; sh = shifts + maxchannels; loop(num_ch * 0.5, (active[] == 1 || (slider28==iLoad)) ? ( recpos[][] = 0.5*(spl(jch)-spl(jch+1)); recpos[] = ((recpos[]+1) >= hs[] ? sh[] : (recpos[]+1)); ); active += 1; recpos += 1; hs += 1; sh += 1; jch += 2; iLoad += 1; ); sumposl[] = 0.5 * (sl + sr); sumposr[] = 0.5 * (sl - sr); ) : ( sumposl[] = sl; sumposr[] = sr; ); sumposl = ((sumposl+1) >= sumhsl ? sumshl : (sumposl+1)); sumposr = ((sumposr+1) >= sumhsr ? sumshr : (sumposr+1)); ); ); update(); latencyCompensation ? ( j = 0; loop(num_ch, latencyPtr[] = spl(j); latencyPtr += 1; j += 1; ); ( latencyPtr > latencyBufferMax ) ? latencyPtr -= (latencyBufferMax - latencyBuffer); latencyRead = latencyPtr - num_ch * latencyLength; ( latencyRead <= latencyBuffer ) ? latencyRead += (latencyBufferMax - latencyBuffer); j = 0; loop(num_ch, spl(j) = latencyRead[]; latencyRead += 1; j += 1; ); ); @gfx 900 600 function rescale(buf) global( mem_block_size, spectral_offset_pixels, spectrum_yoffset, logf_to_pixels, last_spectral_offset_pixels, last_spectrum_yoffset, last_logf_to_pixels, ) local(update, y_raw) instance() ( update = ( (spectral_offset_pixels != 0) || (spectrum_yoffset != 0) || (logf_to_pixels != 0) || (last_spectral_offset_pixels != 0) || (last_spectrum_yoffset != 0) || (last_logf_to_pixels != 0) || (spectral_offset_pixels != last_spectral_offset_pixels) || (spectrum_yoffset != last_spectrum_yoffset) || (logf_to_pixels != last_logf_to_pixels) ); update ? ( loop(mem_block_size, y_raw = - 2.0 * (buf[] + last_spectral_offset_pixels - last_spectrum_yoffset) / last_logf_to_pixels; buf[] = y_raw * -0.5 * logf_to_pixels + spectrum_yoffset - spectral_offset_pixels; buf += 1; ); ); ); // rescale rescale(memA); rescale(memB); rescale(memA2); rescale(memB2); last_spectral_offset_pixels = spectral_offset_pixels; last_spectrum_yoffset = spectrum_yoffset; last_logf_to_pixels = logf_to_pixels; (lastIntegrate != maxIntegrate) ? ( wipe = 1; ) : ( wipe = 0; ); lastIntegrate = maxIntegrate; initCh(); updateChannelSliders(); micro_view = gfx_ext_flags & 1; scaling = slider6; gfx_ext_retina>1 ? gfx_setfont(1,"Arial",max(12,12*gfx_ext_retina),'b') : gfx_setfont(0); function proceed(val, h) ( gfx_x < val ? ( gfx_y = gfx_y + h; gfx_x = optBar; ) : gfx_y = gfx_y - 5; gfx_y; ); function str_add_measure(str) instance(w, h, bw, bh) global(reset_measurements) local(tw, th) ( reset_measurements ? ( w = 0; h = 0; ); gfx_measurestr(str, tw, th); tw += 3; tw > bw ? bw = tw; th > bh ? bh = th; w = bw + 3; h = bh + 9; ); function draw_button_core(x, y, bw, bh) local(xp) globals(bgcolor, gfx_a, gfx_x, gfx_y) instance() ( gfx_set(bgcolor,bgcolor,bgcolor-.15*bgcolor); gfx_rect(x, y, bw, bh); ( bgcolor == 1 ) ? ( gfx_set(1-.4, 1-.6, 1-.8); ) : ( gfx_set(0 * bgColor + 0.9 * ( 1 - bgColor ), 1 * bgColor + 0.9 * ( 1 - bgColor ), 1 * bgColor + 0.6 * ( 1 - bgColor )); ); gfx_line(x, y,x + bw, y); gfx_line(x + bw,y, x + bw,y + bh); gfx_line(x, y + bh,x + bw,y + bh); gfx_line(x, y, x, y + bh); gfx_a = .333333*gfx_a; gfx_line(x-1,y+1,x+bw+1,y+1); gfx_line(x+bw+1,y,x+bw+1,y+bh+1); gfx_line(x,y+bh+1,x+bw,y+bh+1); gfx_line(x-1,y,x-1,y+bh+1); gfx_a = 3*gfx_a; ); /* Button that wraps when there is insufficient space*/ function draw_button_wrap(yp, str, wcomp) instance(w, h, x, y, bw, bh) globals(gfx_r,gfx_g,gfx_b,gfx_x,gfx_y,gfx_a,bgcolor,slider8) local(xp, wtxt, htxt) ( gfx_measurestr(str, wtxt, htxt); xp = gfx_x - (w+3); yp = proceed(wcomp+w+8, h); xp = gfx_x - (w+3); x=xp; y=yp; draw_button_core(x, y, w+2, h); gfx_x=floor(xp+2-.5*(wtxt-w)); gfx_y=yp+5; gfx_drawstr(str); gfx_x = xp - 8; y + h + 1 ); function draw_button(xp, yp, str) instance(w,h,x,y) globals(gfx_r,gfx_g,gfx_b,gfx_x,gfx_y,gfx_a,bgcolor,slider8) ( gfx_measurestr(str, w, h); w+=3; h+=9; xp -= w+3; x=xp; y=yp; gfx_set(bgcolor,bgcolor,bgcolor-.15*bgcolor); draw_button_core(x, y, w, h); gfx_x=xp+2; gfx_y=yp+5; gfx_drawstr(str); gfx_x = xp; y + h + 1 ); function draw_button_fixedWidth(xp, yp, iw, str) instance(w,h,x,y) local(fw, fh) globals(gfx_r,gfx_g,gfx_b,gfx_x,gfx_y,gfx_a,bgcolor,slider8) ( w = iw; gfx_measurestr(str, fw, h); xp -= w; x = xp; y = yp; h+=9; draw_button_core(x, y, w, h); h+=1; w+=1; gfx_x=x+.5*(w-fw); gfx_y=yp+5; gfx_drawstr(str); y+h ); function draw_button2_fixedWidth(xp, yp, _w, str, active, selected, solo, somethingsolo, coloridx) instance(x,y, w, h,fade,cc) globals(gfx_r,gfx_g,gfx_b,gfx_x,gfx_y,gfx_a,slider8,bgcolor) local(fw, fh) ( gfx_measurestr(str, fw, fh); w = _w; xp -= w; x = xp; y = yp; fh += 10; h = fh; gfx_set(bgcolor,bgcolor,bgcolor-.15*bgcolor); gfx_rect(x,y,w,fh); cc = (10000 + 100*floor(slider8)); cc += 3 * coloridx; ( coloridx > -1 ) ? ( gfx_set(cc[0], cc[1], cc[2]); gfx_a = 0.8; gfx_rect(x, y+h,w,3); gfx_a = .4; gfx_rect(x, y, w, h); gfx_a = 0.9; gfx_rect(x-1, y+h+2,w+3,3); gfx_a = 1; ); fade = .7+1 * active; ( bgcolor == 1 ) ? ( gfx_set(1-.4*fade+.8*solo, 1-.6*fade+.5*selected, 1-.8*fade); ) : ( gfx_set(.4*fade+.8*solo, .6*fade+.5*selected, .8*fade); ); gfx_line(x,y,x+w,y); gfx_line(x+w,y,x+w,y+fh); gfx_line(x,y+fh,x+w,y+fh); gfx_line(x,y,x,y+fh); gfx_a = .333333*gfx_a; gfx_line(x-1,y+1,x+w+1,y+1); gfx_line(x+w+1,y,x+w+1,y+fh+1); gfx_line(x,y+fh+1,x+w,y+fh+1); gfx_line(x-1,y,x-1,y+fh+1); gfx_a = 3*gfx_a; selected == 1 ? ( gfx_a = .5 + .5 * sin(5*time_precise()); gfx_line(x+1,y,x+1,y+fh); gfx_line(x,y+fh-1,x+w,y+fh-1); gfx_line(x,y+1,x+w,y+1); gfx_line(x+w-1,y,x+w-1,y+fh); gfx_line(x+2,y,x+2,y+fh); gfx_line(x,y+fh-2,x+w,y+fh-2); gfx_line(x,y+2,x+w,y+2); gfx_line(x+w-2,y,x+w-2,y+fh); ); gfx_a = 1.0; w+=1; gfx_x=x+.5*(w-fw); gfx_y=yp+5; gfx_drawstr(str); somethingsolo ? ( solo == 0 ? ( gfx_set(0, 0, 0, .4); gfx_rect(x, y, w, h); ); ); gfx_x = x; y+fh ); function hit_button(xp,yp,cm) instance(w,h,x,y) globals(cap_mode, cap_last_x, cap_last_y, hideUI, micro_view) ( xp>=x&&yp>=y&&xp z ? ( dx=y; y=z; z=dx; ); x > z ? y : x < y ? z : x; ); function scope.drawGrid(xp, yp, wp, hp, scaling) instance(w, h, x, y, dx, last, xcoord, hh, sig) globals(gfx_r, gfx_g, gfx_b, gfx_a, gfx_x, gfx_y, bufl, slider40) ( gfx_r=gfx_g=gfx_b=gfx_a=.5; gfx_a=0.8 * slider40; y = yp + 0.5*hp; while( y<(yp+hp) ? ( gfx_line(0, y, wp, y); y = y + 50*scaling; ) ); y = yp + 0.5*hp; while( y>yp ? ( gfx_line(0, y, wp, y); y = y - 50*scaling; ) ); x = xp; while( x<(xp+wp) ? ( gfx_line(x, yp, x, yp+hp); x = x + .1 * w; ) ); ); function get_color(ch, col) local(cidx, cref) global(slider8) ( cref = (10000 + 100*floor(slider8)); cidx = 3 * ch + col; cref[cidx] ); function scope.drawSignal_legacy(xp, yp, wp, hp, rpos, scaling, sampleSize, rr, gg, bb, fill) instance(w, h, x, y, dx, last, xcoord, hh, sig) globals(gfx_r, gfx_g, gfx_b, gfx_a, gfx_x, gfx_y, bufl, slider39) ( w = wp; h = hp; hh = 0.5 * h; dx = w / sampleSize; last = scaling * ( rpos[] ); xcoord = x; slider39 ? scope.drawGrid(xp, yp, wp, hp, scaling); x = xp; y = yp; gfx_r=rr; gfx_g=gg; gfx_b=bb; gfx_a=.6; loop(sampleSize, xcoord += dx; sig = scaling * ( rpos[] ); ( sig > 1.0 ) ? sig = 1.0 : ( sig < -1.0 ? sig = -1.0 ); gfx_line(xcoord,y+hh*sig+hh,xcoord+dx,y+hh*last+hh); last = sig; rpos += 1; ); ); function scope.drawSignal(xp, yp, wp, hp, rpos, scaling, sampleSize, rr, gg, bb, fill) instance(w, h, x, y, dx, xcoord, hh) globals(gfx_r, gfx_g, gfx_b, gfx_a, gfx_x, gfx_y, bufl, slider39, slider37) local(mn, mx, val, last_min, last_max) ( w = wp; h = hp; hh = 0.5 * h; slider39 ? scope.drawGrid(xp, yp, wp, hp, scaling); x = xp; y = yp; gfx_r=rr; gfx_g=gg; gfx_b=bb; dx = sampleSize / w; xcoord = x; loop(w, mn = 1000000; mx = -1000000; loop(dx, val = scaling * rpos[]; rpos += 1; (val > 1.0) ? val = 1.0 : ( val < -1.0 ? val = -1.0 ); mx = max(mx, val); mn = min(mn, val); ); mn = y + hh * mn + hh; mx = y + hh * mx + hh; (fill == 1) ? ( gfx_a=slider37; gfx_line(xcoord, mn, xcoord, mx); ); gfx_a = 0.85; gfx_line(xcoord - 1, last_min, xcoord, mn); gfx_line(xcoord - 1, last_max, xcoord, mx); xcoord += 1; last_min = mn; last_max = mx; ); ); function scope.drawSignal_resampled(xp, yp, wp, hp, rechead, endpos, startpos, scaling, sampleSize, rr, gg, bb, fill, sample_offset) instance(w, h, x, y, dx, xcoord, hh) globals(gfx_r, gfx_g, gfx_b, gfx_a, gfx_x, gfx_y, bufl, slider39, slider37) local(mn, mx, val, last_min, last_max, offset_scaled, rpos) ( w = wp; h = hp; hh = 0.5 * h; slider39 ? scope.drawGrid(xp, yp, wp, hp, scaling); x = xp; y = yp; gfx_r=rr; gfx_g=gg; gfx_b=bb; dx = floor(sampleSize / w); offset_scaled = sample_offset / dx; xcoord = x + offset_scaled; rpos = rechead - sampleSize; rpos < startpos ? rpos += (endpos - startpos); loop(w - offset_scaled, mn = 1000000; mx = -1000000; loop(dx, val = scaling * rpos[]; rpos += 1; rpos == endpos ? rpos = startpos; (val > 1.0) ? val = 1.0 : ( val < -1.0 ? val = -1.0 ); mx = max(mx, val); mn = min(mn, val); ); mn = y + hh * mn + hh; mx = y + hh * mx + hh; (fill == 1) ? ( gfx_a=slider37; gfx_line(xcoord, mn, xcoord, mx); ); gfx_a = 0.85; gfx_line(xcoord - 1, last_min, xcoord, mn); gfx_line(xcoord - 1, last_max, xcoord, mx); xcoord += 1; last_min = mn; last_max = mx; ); xcoord = x; rpos = rechead - sample_offset; rpos < startpos ? rpos += (endpos - startpos); loop(offset_scaled, mn = 1000000; mx = -1000000; loop(dx, val = scaling * rpos[]; rpos += 1; rpos == endpos ? rpos = startpos; (val > 1.0) ? val = 1.0 : ( val < -1.0 ? val = -1.0 ); mx = max(mx, val); mn = min(mn, val); ); mn = y + hh * mn + hh; mx = y + hh * mx + hh; (fill == 1) ? ( gfx_a=slider37; gfx_line(xcoord, mn, xcoord, mx); ); gfx_a = 0.85; gfx_line(xcoord - 1, last_min, xcoord, mn); gfx_line(xcoord - 1, last_max, xcoord, mx); xcoord += 1; last_min = mn; last_max = mx; ); ); function scope.drawMovingSignal_legacy( xp, yp, wp, hp, rpos, endpos, startpos, scaling, sampleSize, rr, gg, bb, fill) instance(w, h, x, y, dx, last, xcoord, hh, sig) globals(gfx_r, gfx_g, gfx_b, gfx_a, gfx_x, gfx_y, bufl) ( hh = 0.5 * h; rpos = rpos + 1; dx = w / sampleSize; last = scaling * ( rpos[] ); xcoord = x; scope.drawGrid(xp, yp, wp, hp, scaling); x = xp; y = yp; w = wp; h = hp; gfx_r=rr; gfx_g=gg; gfx_b=bb; gfx_a=.6; loop(sampleSize, xcoord += dx; sig = scaling * ( rpos[] ); ( sig > 1.0 ) ? sig = 1.0 : ( sig < -1.0 ? sig = -1.0 ); gfx_line(xcoord,y+hh*sig+hh,xcoord+dx,y+hh*last+hh); last = sig; rpos = ( rpos > endpos ) ? startpos : rpos + 1; ); ); function scope.drawMovingSignal( xp, yp, wp, hp, rpos, endpos, startpos, scaling, sampleSize, rr, gg, bb, fill) instance(w, h, x, y, dx, xcoord, hh, val, mn, mx, last_min, last_max) globals(gfx_r, gfx_g, gfx_b, gfx_a, gfx_x, gfx_y, bufl, slider37) ( hh = 0.5 * h; scope.drawGrid(xp, yp, wp, hp, scaling); x = xp; y = yp; w = wp; h = hp; gfx_r=rr; gfx_g=gg; gfx_b=bb; gfx_a=slider37; dx = sampleSize / w; xcoord = x; rpos = rpos + 1; loop(w, mn = 1000000; mx = -1000000; loop(dx, val = scaling * rpos[]; rpos = ( rpos > endpos ) ? startpos : rpos + 1; (val > 1.0) ? val = 1.0 : ( val < -1.0 ? val = -1.0 ); mx = max(mx, val); mn = min(mn, val); ); mn = y + hh * mn + hh; mx = y + hh * mx + hh; (fill == 1) ? ( gfx_a=slider37; gfx_line(xcoord, mn, xcoord, mx); ); gfx_a = 0.85; gfx_line(xcoord - 1, last_min, xcoord, mn); gfx_line(xcoord - 1, last_max, xcoord, mx); xcoord += 1; last_min = mn; last_max = mx; ); ); function hit(xp,yp,cm) instance(w,h,x,y) globals(cap_mode, cap_last_x, cap_last_y) ( xp>=x&&yp>=y&&xp 0 ? ( (slider36 == -1) ? ( slider(hit) = !slider(hit); slider_automate(slider(hit)); updateSliders = 1; old_w = 0; ) : ( slider36 = -1; ); ); chA.hit_button(mouse_x,mouse_y,200) ? ( showA=!showA; slider_automate(showA); ); chB.hit_button(mouse_x,mouse_y,200) ? ( showB=!showB; slider_automate(showB); ); hit > 0; ); function sonoGrid(logarithmic, x, y, w, h, factor) global(spectrum_xmax, srate, gfx_x, gfx_y, sonoGridAlpha) local(f, i, tx, fmax, xscale, wsc, txt, xc, sw, sh, yc, last_y) instance(fmaxFactorf) ( f = 0; fmaxFactorf = factor; fmax = srate / factor; xscale = 800 / (fmax - 4); wsc = h / (log(1+.5*fmax*xscale)); last_y = -10000; while( logarithmic ? ( f += (f<100?10:f<1000?100:f<10000?1000:5000); tx = log(1.0 + f * xscale) * wsc; txt = f < 1000 ? sprintf(14, "%dHz", f) : sprintf(14, "%dkHz", f / 1000); ) : ( factor < 1.1 ? ( f += 1000; txt = sprintf(14, "%dkHz", f / 1000); ) : ( factor < 2.5 ) ? ( f += 500; txt = f < 1000 ? sprintf(14, "%dHz", f) : sprintf(14, "%.1fkHz", f / 1000); ) : ( f += (f<100?10:f<1000?100:f<10000?200:5000); txt = f < 1000 ? sprintf(14, "%dHz", f) : sprintf(14, "%.1fkHz", f / 1000); ); tx = 2 * (f / fmax) * h; ); yc = y + h - tx; gfx_set(0, 0, 0, sonoGridAlpha); gfx_line(x, yc, x + w, yc + 2); gfx_line(x, yc, x + w, yc - 2); gfx_set(1, 1, 1, sonoGridAlpha); gfx_line(x, yc, x + w, yc); gfx_measurestr(txt, sw, sh); yc = y + h - tx - 0.5 * sh; // Don't print text on top of eachother abs(last_y - yc) > 2 * sh ? ( xc = x + 3; gfx_x = xc - 1; gfx_y = yc; gfx_set(0, 0, 0, 1); gfx_printf(txt); gfx_x = xc + 1; gfx_y = yc; gfx_printf(txt); gfx_x = xc; gfx_y = yc - 1; gfx_printf(txt); gfx_x = xc; gfx_y = yc + 1; gfx_printf(txt); gfx_x = xc; gfx_y = yc; gfx_set(1, 1, 1, 1); gfx_printf(txt); last_y = yc; ); ((f < srate / 2) && (yc > (y + 3 * sh))) ); ); SONOSURFACE2 = 3; COLORLEGEND = 5; function updateSono(sonogramBuffer, sonoColorMap, invert, sonoScale, logarithmic, fmaxFactor) instance(h, preSonoDest, preSonoX, preSonoY, sonoSize,sonoSizeX, sonoColorLoc, iv, sonosurf, blurred, tx, tl, i, xscale, wsc, cv, norm, fmax) globals(slider44, gfx_dest, gfx_r, gfx_g, gfx_b, gfx_a, gfx_x, gfx_y, fftsize, SONOSURFACE, SONOSURFACE2, COLORLEGEND, gfx_mode, slider2, scale_offset_db_user, micro_view, legacy_style) local(extra_scale, scaling, val, plot_val, f, accumulated_step, current_max, stepsize, N, better_scaling) ( sonosurf = SONOSURFACE; blurred = SONOSURFACE2; preSonoDest = gfx_dest; gfx_a = 1; //sonoSize = 2048; sonoSize = h; sonoSizeX = 256; // MaxF fmax = fftsize / fmaxFactor; // For log-drawing xscale = 800/(fmax-4); wsc = sonoSize/(log(1+.5*fmax*xscale)); // Start by drawing the previous buffer to this one better_scaling = 1 - legacy_style; scaling = 0.5 * 20 / log(10); extra_scale = 0.001 * sonoScale; ( slider44 == 0 ) ? ( gfx_dest = sonosurf; gfx_setimgdim(sonosurf, sonoSizeX, sonoSize); gfx_setimgdim(blurred, sonoSizeX, sonoSize); gfx_x = -1; gfx_y = 0; gfx_blit(sonosurf, 1, 0); // Draw the stuff gfx_x = sonoSizeX-10; gfx_y = sonoSize; tl = 0; i = 0; ( logarithmic == 0 ) ? ( // Actual FFT density is better than what we can display gfx_x = sonoSizeX-1; N = 0.5 * fmax / sonoSize; stepsize = 1.0 / N; norm = sonoScale / stepsize; ( stepsize < 1 ) ? ( current_max = 0; accumulated_step = 0; while( current_max = max(current_max, sonogramBuffer[]); sonogramBuffer += 1; accumulated_step += stepsize; (accumulated_step > 1) ? ( better_scaling ? ( // Maximum value is given by: - scale_offset_db_user // Minimum value is given by: slider2 - scale_offset_db_user plot_val = scaling * log(current_max + 0.00000000000000000000000000000001); plot_val = min(1, max(0, (plot_val - scale_offset_db_user + extra_scale) / slider2)); !invert ? plot_val = 1 - plot_val; sonoColorLoc = sonoColorMap + 3 * ceil(255 * plot_val); ) : ( sonoColorLoc = sonoColorMap + 3*ceil((invert + (1 - 2 * invert) * (1 - exp(-norm * current_max))) * 255); ); gfx_setpixel(sonoColorLoc[],sonoColorLoc[1],sonoColorLoc[2]); current_max = 0; accumulated_step -= 1; gfx_y -= 1; ); gfx_y > 0; ); ) : ( // Actual FFT density is crappier N = 1/N; i = sonoSize; loop(sonoSize/N, better_scaling ? ( // Maximum value is given by: - scale_offset_db_user // Minimum value is given by: slider2 - scale_offset_db_user plot_val = scaling * log(sonogramBuffer[] + 0.00000000000000000000000000000001); plot_val = min(1, max(0, (plot_val - scale_offset_db_user + extra_scale) / slider2)); !invert ? plot_val = 1 - plot_val; sonoColorLoc = sonoColorMap + 3 * ceil(255 * plot_val); ) : ( sonoColorLoc = sonoColorMap + 3*ceil((invert + (1 - 2 * invert) * (1 - exp(- sonogramBuffer[] * sonoScale))) * 255); ); gfx_r = sonoColorLoc[]; gfx_g = sonoColorLoc[1]; gfx_b = sonoColorLoc[2]; gfx_a = 1.0; gfx_line(sonoSizeX-1,i,sonoSizeX-1,i+N); i -= N; sonogramBuffer += 1; ); ) ) : ( tl = 0; val = 0; loop(0.5 * fmax, tx = log(1.0+i*xscale)*wsc; val = max(val, sonogramBuffer[]); (tx - tl) > 0.999999 ? ( better_scaling ? ( // Maximum value is given by: - scale_offset_db_user // Minimum value is given by: slider2 - scale_offset_db_user plot_val = scaling * log(val + 0.00000000000000000000000000000001); plot_val = min(1, max(0, (plot_val - scale_offset_db_user + extra_scale) / slider2)); !invert ? plot_val = 1 - plot_val; sonoColorLoc = sonoColorMap + 3 * ceil(255 * plot_val); ) : ( sonoColorLoc = sonoColorMap + 3 * ceil((invert + (1 - 2*invert) * (1 - exp(- val * sonoScale))) * 255); ); val = 0; gfx_r = sonoColorLoc[]; gfx_g = sonoColorLoc[1]; gfx_b = sonoColorLoc[2]; gfx_line(sonoSizeX-1,sonoSize-tl,sonoSizeX-1,sonoSize-tx); tl = tx; ); i += 1; sonogramBuffer += 1; ); ); ); gfx_dest = preSonoDest; ); function setPositionSono(xp, yp, wp, hp) global() instance(x, y, w, h) ( x = xp; y = yp; w = wp; h = hp; ); function drawSono(sonoColorMap, invert, sonoScale, logarithmic, fmaxFactor) instance(x, y, w, h, preSonoDest, sonoSize, sonoSizeX, sonosurf, blurred) globals( slider44, gfx_dest, gfx_x, gfx_y, gfx_a, gfx_mode, COLORLEGEND, scale_offset_db_user, micro_view, legacy_style, extra_scale, ) local(sono_start_x, better_scaling, val, sonoColorLoc) ( sono_start_x = (better_scaling && !micro_view) ? x + 35 : x; better_scaling = 1 - legacy_style; (better_scaling && !micro_view) ? ( /* Draw color legend */ extra_scale = 0.001 * sonoScale; gfx_dest = COLORLEGEND; gfx_setimgdim(COLORLEGEND, 1, 255); val = 0; loop(255, sonoColorLoc = sonoColorMap + 3 * ceil(max(0, min(255, (invert ? (255 - val - extra_scale) : val + extra_scale)))); gfx_x = 0; gfx_y = 254 - val; gfx_setpixel(sonoColorLoc[],sonoColorLoc[1],sonoColorLoc[2]); val += 1; ); gfx_dest = 0; ); // Draw the sonogram to the screen gfx_dest = preSonoDest; gfx_x = x; gfx_y = y; gfx_a = .95; gfx_blit(sonosurf, 1, 0, 0, 0, sonoSizeX, sonoSize, sono_start_x, y, w - sono_start_x, h); (better_scaling && !micro_view) ? gfx_blit(COLORLEGEND, 1, 0, 0, 0, 1, 255, x + 5, y + 10, 25, h - 20); // Blur it in a second buffer /*gfx_dest = blurred; gfx_x = gfx_y = 0; gfx_blit(sonosurf, 1, 0); gfx_x = gfx_y = 0; loop(2, gfx_blurto(sonoSizeX,sonoSizeX); ); // Add it on top gfx_mode = 1; gfx_x = gfx_y = 0; gfx_dest = preSonoDest; gfx_blit(blurred, 1, 0, 0, 0, sonoSizeX, sonoSize, x, y, w, h); gfx_blit(blurred, 1, 0, 0, 0, sonoSizeX, sonoSize, x, y, w, h); */ gfx_mode = 0; !micro_view ? this.sonoGrid(logarithmic, sono_start_x, y, w, h, fmaxFactor); ); function to_x(f) global(srate, spectrum_xoffset, wsc) ( log(800 * (f - srate * spectrum_xoffset) / srate + 1) * wsc ); function from_frequency(hz) local(octave, float_note, note, note_label, offset) global() ( note = log(hz / 261.6255653005986) / log(2); octave = floor(note); float_note = 12 * (note - octave); note = floor(float_note + 0.5); offset = float_note - note; note_label = note < 1 ? "C-" : note < 2 ? "C#" : note < 3 ? "D-" : note < 4 ? "D#" : note < 5 ? "E-" : note < 6 ? "F-" : note < 7 ? "F#" : note < 8 ? "G-" : note < 9 ? "G#" : note < 10 ? "A-" : note < 11 ? "A#" : "B"; sprintf(16, "%s%d (%+.2g ct)", note_label, octave + 4, offset) ); function note(hz) local(octave, float_note, note, note_label, offset) global() ( note = log(hz / 261.6255653005986) / log(2); octave = floor(note); float_note = 12 * (note - octave); note = floor(float_note + 0.5); offset = float_note - note; note < 1 ? "C" : note < 2 ? "C" : note < 3 ? "D" : note < 4 ? "D" : note < 5 ? "E" : note < 6 ? "F" : note < 7 ? "F" : note < 8 ? "G" : note < 9 ? "G" : note < 10 ? "A" : note < 11 ? "A" : "B"; ); function drawGrid() local(intensity, textintensity, gv, cnt, y, gfx_texth, bottom_line, f, lx, ltxt, tx, dotext, scale_offset, drawtext, f1, f2, color, text_y) global(bgColor, wsc, logf_to_pixels, scale_offset_db, gfx_r, gfx_g, gfx_b, gfx_a, gfx_x, gfx_y, gfx_w, gfx_h, slider39, slider40, srate, spectrum_yoffset, spectrum_yoffsetbottom, spectrum_xpad, scaling, spectrum_xmax, spectrum_xoffset, hideUI, micro_view, showNotes) ( intensity = 1 - bgColor; textintensity = 0.1 * bgColor + 1.0 * ( 1 - bgColor ); // draw horz grid gfx_r=gfx_g=gfx_b=intensity; gv=1; cnt=100; gfx_y = spectrum_yoffset; scale_offset = 10^(scale_offset_db/20); gv /= scale_offset; y=spectrum_yoffset-log(gv*scale_offset)*logf_to_pixels; drawtext = !hideUI && !micro_view; while( y > 0 ? ( gfx_r=gfx_g=gfx_b=intensity; gfx_a=0.8 * slider39 * slider40; gfx_line(0,y,gfx_w-spectrum_xpad,y,0); bottom_line = gfx_y; drawtext ? ( gfx_x=7; gfx_y=y+2; gfx_r=gfx_g=gfx_b=textintensity; gfx_a=0.9; gfx_drawnumber(log10(gv)*20,0); gfx_drawchar($'d'); gfx_drawchar($'B'); gfx_y+=gfx_texth; ); ); gv*=0.5; y=spectrum_yoffset-log(gv*scale_offset)*logf_to_pixels; y<(gfx_h-spectrum_yoffsetbottom) && cnt-=1 > 0; ); wsc = scaling*gfx_w/log(1+400) * (spectrum_xmax/gfx_w); // draw vert grid showNotes ? ( lx = 0; f2 = 0; gv = 0; f1 = to_x(27.5 * 2^((lx - 0.5)/12)); f2 = to_x(27.5 * 2^((lx + 0.5)/12)); gfx_setfont(4, "Arial", 4 * (f2 - f1)); loop(120, f2 < (gfx_w-spectrum_xpad) ? ( f = 27.5 * 2^(lx/12); f2 = floor(to_x(27.5 * 2^((lx + 0.5)/12))); color = 1.0 - ((gv == 1) || (gv == 4) || (gv == 6) || (gv == 9) || (gv == 11)); gfx_set(color, color, color, 0.10 * slider39 * slider40); gfx_rect(f1, 0, f2 - f1, gfx_h - spectrum_yoffsetbottom); color ? ( gfx_set(textintensity, textintensity, textintensity, 1); gfx_x = f1; gfx_y = gfx_h - spectrum_yoffsetbottom; gfx_drawstr(note(f), 1, f2, gfx_y + 20); ); lx += 1; gv += 1; gv > 11 ? gv = 0; f1 = f2; ); ); gfx_setfont(0) ) : ( f=20; gfx_x+=4; lx=gfx_x; ltxt = 0; tx = log(1.0+((f/srate-spectrum_xoffset)*2.0)*400) * wsc; while( gfx_r=gfx_g=gfx_b=intensity; gfx_a=0.8 * slider39 * slider40; dotext = drawtext && (tx > gfx_x && f!=40 && f!=4000 && f != 15000 && (f<400 || f >= 1000 || f == 500) && (f<6000 || f>=10000) || (tx-ltxt)>.1*gfx_w); tx > lx ? ( lx=tx+4; gfx_line(tx,spectrum_yoffset,tx,gfx_h - spectrum_yoffsetbottom - (dotext ? 0 : gfx_texth+2),0); ); // NOTE: Note that the line above didn't have a rescale Y dotext ? ( ltxt = tx; gfx_set(0, 0, 0, 1); gfx_x = tx + 2; text_y = gfx_h-gfx_texth-spectrum_yoffsetbottom; gfx_y = text_y; gfx_line( gfx_x-3, gfx_y, gfx_x-3, gfx_y+gfx_texth ); f>=1000 ? gfx_printf("%dkHz",f*.001) : gfx_printf("%dHz",f); gfx_x = tx + 4; text_y = gfx_h-gfx_texth-spectrum_yoffsetbottom; gfx_y = text_y + 1; gfx_line( gfx_x-3, gfx_y, gfx_x-3, gfx_y+gfx_texth ); f>=1000 ? gfx_printf("%dkHz",f*.001) : gfx_printf("%dHz",f); gfx_r=gfx_g=gfx_b=textintensity; gfx_a=0.9; gfx_x = tx + 3; gfx_y = text_y; gfx_line( gfx_x-3, gfx_y, gfx_x-3, gfx_y+gfx_texth ); f>=1000 ? gfx_printf("%dkHz",f*.001) : gfx_printf("%dHz",f); ); f += (f<100?10:f<1000?100:f<10000?1000:5000); tx = log(1.0+((f/srate-spectrum_xoffset)*2.0)*400) * wsc; tx < spectrum_xmax ); ); ); function drawFFT(bufout, fftsize, xscale, kernelSize, rr, gg, bb, fill, draw, offset) local(i, curh, ixsc, iwsc, prec, tx, ty, tx0, lx0, lx, ly, fill_slast, fill_slmin, ly2, ty2, bin, last_bin, left_bin, a, b, c, y1, y2, y3, xrel, scale1, scale2, cmax, idx, checked_bin, dbin) global(gfx_w, gfx_h, gfx_x, gfx_y, gfx_r, gfx_g, gfx_b, gfx_a, slider37, displayMode, srate, spectrum_yoffsetbottom, spectrum_yoffset, spectrum_xoffsetbottom, spectrum_xoffset wsc, spectrum_xmax, scale_offset_db, spectral_offset_pixels, zeroline, interpolate_lines) instance() ( i = 0; fill_slmin=gfx_h; fill_slast=0; curh = gfx_h-spectrum_yoffsetbottom; ixsc = 0; prec = fftsize*spectrum_xoffset*xscale; zeroline = spectrum_yoffset-spectral_offset_pixels; interpolate_lines ? ( tx = 0; scale1 = fftsize / 800; scale2 = spectrum_xoffset * fftsize; iwsc = 1 / wsc; gfx_r=rr; gfx_g=gg; gfx_b=bb; last_bin = -2; ly = 0; loop(spectrum_xmax, bin = scale1 * (exp(tx * iwsc) - 1) + scale2; dbin = floor(bin) - last_bin; // Update interpolant (dbin >= 1) ? ( // If we crossed multiple bins, seek the bin with the maximum in this range. (dbin >= 2) ? ( cmax = 1000000000000000; idx = last_bin + 1; loop(dbin, checked_bin = bufout[idx]; (checked_bin < cmax) ? ( cmax = checked_bin; bin = idx; ); idx += 1; ); ); last_bin = floor(bin); left_bin = max(0, floor(bin) - 1); // x-axis is defined at [0, 1, 2] y1 = bufout[left_bin]; y2 = bufout[left_bin + 1]; y3 = bufout[left_bin + 2]; a = - 0.5 * (2 * (y2 - y1) + (y1 - y3)); b = - 0.5 * (4 * (y1 - y2) + (y3 - y1)); c = y1; ); xrel = bin - left_bin; ty = a * xrel * xrel + b * xrel + c; ty = min(ty, gfx_h - spectrum_yoffsetbottom); gfx_a = 1; ly > 0 ? ( gfx_line(tx,ly,tx+1,ty); gfx_line(tx,ly-1,tx+1,ty-1); ); (fill == 1) ? ( gfx_a = slider37; gfx_line(tx,gfx_h - spectrum_yoffsetbottom,tx,ty); ); tx += 1; ly = ty; ); ) : ( loop(fftsize*0.5-kernelSize, tx = log(1.0+ixsc-prec)*wsc; ty = bufout[]; ty = min(ty, gfx_h - spectrum_yoffsetbottom); ( i && ( tx < spectrum_xmax ) ) ? ( gfx_r=rr; gfx_g=gg; gfx_b=bb; fill ? ( gfx_a=slider37; tx0=tx|0; lx0=lx|0; tx0>lx0? ( displayMode == 1 ? ( gfx_triangle(lx0,max(zeroline,ly),lx0,ly,tx0-1,ty,tx0-1,max(zeroline,ty)); gfx_triangle(lx0,min(zeroline,ly),lx0,ly,tx0-1,ty,tx0-1,min(zeroline,ty)); ) : ( ly < curh || ty < curh ? gfx_triangle(lx0,max(curh,ly),lx0,ly,tx0-1,ty,tx0-1,max(curh,ty)); ); ) : ( tx0 > fill_slast ? ( fill_slast < curh ? gfx_line(fill_slast,curh,fill_slast,fill_slmin); fill_slmin=curh; ) : ( fill_slmin=min(fill_slmin,ty); ); ); fill_slast=tx0; ); gfx_a=1; draw == 1 ? ( gfx_line(lx, ly, tx, ty); gfx_line(lx, ly - 1, tx, ty - 1) ); ); lx=tx; ly=ty; ly2=ty2; bufout+=1; i+=1; ixsc+=xscale; ); ); ); function prepareForDrawing(filtout, rpos, fftwspace, intbuf, bufStart, rr, gg, bb, fill, draw, fftsize, xscale, smoothMode, kernelSize) local(bufout, fout, scfac, jk, tmp, curSize, kern, tsc, i, curh sumWtY, iSize, xij, SumWtS, d, w, yAdaptive, res, M_est, S_est, alpha, Sq_est) global(smoothing, filtout2, spectrum_xmax, spectrum_center, slider37) instance() ( ( smoothing > 0 ) ? ( ( smoothMode == 0 ) ? ( // Convolve it bufout = filtout+kernelSize; fout = filtout2; scfac = kernelSize / log(1+400); jk = 1; loop(fftsize*0.5, tmp = 0; curSize = ceil(scfac * log(1.0+jk*xscale)); kern = bufout-curSize; tsc = 1 / (2*curSize+1); loop(2*curSize+1, tmp = tmp + kern[]; kern += 1; ); fout[] = tmp * tsc; bufout += 1; fout += 1; jk += 1; ); bufout = filtout2; ) : ( smoothMode == 1 ) ? ( // Determine maximum bufout = filtout+kernelSize; fout = filtout2; scfac = kernelSize / log(1+400); jk = 1; loop(fftsize*0.5, tmp = 10000; curSize = ceil( scfac * log(1.0+jk*xscale) ); kern = bufout-curSize; loop(2*curSize+1, tmp = min( tmp, kern[] ); kern += 1; ); fout[] = tmp; bufout += 1; fout += 1; jk += 1; ); bufout = filtout2; ) : ( smoothMode == 2 ) ? ( // LOESS filtering bufout = filtout+kernelSize; fout = filtout2; scfac = kernelSize / log(1+400); jk = 1; loop(fftsize*0.5, tmp = 10000; curSize = 1+ceil( scfac * log(1.0+jk*xscale) ); kern = bufout-curSize; SumWtY = 0; isize = 1.0 / curSize; xij = - curSize; SumWts = 1.1571 * curSize; loop(2*curSize+1, d = abs(xij) * isize; w = (1.0 - d*d*d); w = w*w*w; SumWtY = SumWtY + kern[] * w; kern += 1; xij += 1; ); fout[] = SumWtY / SumWts; bufout += 1; fout += 1; jk += 1; ); bufout = filtout2; ) : ( smoothMode == 3 ) ? ( // Adaptive filtering bufout = filtout+kernelSize; fout = filtout2; scfac = kernelSize / log(1+400); jk = 1; loop(fftsize*0.5, tmp = 10000; curSize = 1+ceil( scfac * log(1.0+jk*xscale) ); kern = bufout-curSize; SumWtY = 0; isize = 1.0 / curSize; xij = - curSize; SumWts = 1.1571 * curSize; loop(2*curSize+1, d = abs(xij) * isize; w = (1.0 - d*d*d); w = w*w*w; SumWtY = SumWtY + kern[] * w; kern += 1; xij += 1; ); yAdaptive = SumWtY / SumWts; res = bufout[] - yAdaptive; ( -res < abs( M_est + 2*sqrt( S_est ) ) ) ? ( alpha = 0.99; M_est = alpha * M_est + ( 1 - alpha ) * res; Sq_est = alpha * Sq_est + ( 1 - alpha ) * res * res; S_est = Sq_est - M_est*M_est; ) : ( // Don't use LOESS value at peaks yAdaptive = bufout[]; ); fout[] = yAdaptive; bufout += 1; fout += 1; jk += 1; ); bufout = filtout2; ) : ( smoothMode == 4 ) ? ( bufout = filtout + kernelSize; fout = filtout2; scfac = .00025 * kernelSize * kernelSize; jk = 1; tmp = bufout[]; loop(fftsize*0.5, kern = 1/(1+scfac*jk); tmp = kern * bufout[] + (1-kern) * tmp; fout[] = tmp; bufout += 1; fout += 1; jk += 1; ); bufout = filtout2 + fftsize * 0.5 - 1; fout = filtout2 + fftsize * 0.5 - 1; tmp = bufout[]; jk = fftsize*0.5; loop(fftsize*0.5, kern = 1/(1+scfac*jk); tmp = kern * bufout[] + (1-kern) * tmp; fout[] = tmp; bufout -= 1; fout -= 1; jk -= 1; ); bufout = filtout2; ); ) : bufout = filtout; draw ? drawFFT(bufout, fftsize, xscale, kernelSize, rr, gg, bb, fill, draw, 0); bufout ); function windowAndTransform(rpos, fftsize, bufStart, histSize, window, fftwspace, histEnd) local(buf1, buf2, buf3) local() global() instance() ( buf1=rpos-fftsize; buf1= histEnd ? buf1 -= histsize; ); buf2-=1; loop(fftsize*.5 - 1, buf3[] = buf1[]*(buf2-=1)[]; buf3+=1; (buf1+=1) >= histEnd ? buf1 -= histsize; ); fft_real(fftwspace,fftsize); fft_permute(fftwspace,fftsize/2); fftwspace[1]=0; fftwspace ); function processFFT(rpos, fftwspace, intbuf, bufStart, histEnd, rr, gg, bb, fill, draw) local(buf1, buf2, buf3, bufout, ascale, i, lx, ang, ty, ty2, tx, ly2, yOut, slope, prec, last) global(histsize, fftsize, window, filtout, wipe, max_fft_size, spectrum_yoffset, bottom_pad, spectrum_xmax, wsc, logf_to_pixels, spectral_offset_pixels, gfx_x, gfx_y, gfx_h, slider3, slider38, maxIntegrate, slider45, smoothing, integrate_en, integrate_sc, kernelSize, xscale) instance() ( fftwspace = windowAndTransform(rpos, fftsize, bufStart, histSize, window, fftwspace, histEnd); ascale=gfx_h/$pi*0.25; xscale=800.0/(fftsize-4.0); buf3=fftwspace; buf2=intbuf+max_fft_size*0.5; i=0; lx=0; // Draw phase (angle) draw ? ( slider3 ? loop(fftsize*0.5, ang=-atan2(buf3[1],buf3[]); buf3+=2; integrate_en ? ( ang = buf2[] += integrate_sc * (ang - buf2[]); buf2+=1; ); ty2=(ang*ascale + gfx_h*0.5) + spectrum_yoffset; tx = log(1.0+i*xscale)*wsc; i && ( tx < spectrum_xmax ) ? ( gfx_x=lx; gfx_y=ly2; gfx_lineto(tx,ty2,1) ; ); lx=tx; ly2=ty2; i+=1; ); ); lx=0; i=0; // Process FFT kernelSize = smoothing > 0 ? floor( smoothing/5 + 1 ) : 0; bufout = filtout + kernelSize; // Integrate the FFT over time to smooth it. // Note that yOut and buf3 both point to the FFTW space. yOut is written after buf3 is read so // they don't conflict. buf3 = fftwspace; yOut = fftwspace; buf2 = intbuf; i = 0; slope = .5*log(2)*slider38; prec = (10^(-500/20*2)); /* Check last mode and reset if needed */ wipe ? ( maxIntegrate ? memset(buf2, - 100, max_fft_size); ); loop(fftsize*0.5, yOut[] = sqr(buf3[0])+sqr(buf3[1]); ty = log(max(yOut[],prec)); ty = ty + slope*log(1.0+i*xscale); yOut += 1; buf3 += 2; integrate_en ? ( maxIntegrate ? ( ty = buf2[] = max(ty, buf2[] - integrate_sc); ) : ( ty = buf2[] += integrate_sc * (ty - buf2[]); ); buf2+=1; ); bufout[] = ty * -0.5 * logf_to_pixels + spectrum_yoffset - spectral_offset_pixels; bufout += 1; i += 1; ); // Copy the last few to the front bufout = filtout + kernelSize; last = bufout[]; loop(kernelSize, bufout -= 1; bufout[] = last; ); prepareForDrawing(filtout, rpos, fftwspace, intbuf, bufStart, rr, gg, bb, fill, draw, fftsize, xscale, floor(slider45), kernelSize) ); function processFFTDifference(rpos, fftwspace, intbuf, bufStart, histEnd, rpos2, fftwspace2, intbuf2, bufStart2, histEnd2, rr, gg, bb, fill, draw) local(buf1, buf2, buf3, bufout, ascale, i, lx, ang, last_ang, plot_ang, phase_diff, ty, ty2, tx, ly2, yOut, slope, prec, last, y1, y2, eps, yy, xx, mag, intbuf_ptr, intbuf2_ptr, ) global(histsize, fftsize, window, filtout, max_fft_size, spectrum_yoffset, bottom_pad, spectrum_xmax, wsc, logf_to_pixels, spectral_offset_pixels, spectrum_yoffsetbottom, gfx_x, gfx_y, gfx_h, slider3, slider38, maxIntegrate, slider45, smoothing, integrate_en, integrate_sc, kernelSize, xscale, unwrap) instance() ( fftwspace = windowAndTransform(rpos, fftsize, bufStart, histSize, window, fftwspace, histEnd); fftwspace2 = windowAndTransform(rpos2, fftsize, bufStart2, histSize, window, fftwspace2, histEnd2); ascale=(gfx_h - spectrum_yoffsetbottom - spectrum_yoffset)/$pi*0.25; xscale=800.0/(fftsize-4.0); buf3=fftwspace; buf1=fftwspace2; intbuf_ptr=intbuf+max_fft_size*0.5; i=0; lx=0; eps = 0.000000000001; plot_ang = last_ang = intbuf_ptr[]; ly2 = (plot_ang * ascale + (gfx_h - spectrum_yoffsetbottom - spectrum_yoffset)*0.5) + spectrum_yoffset; // Draw phase (angle) draw ? ( slider3 ? loop(fftsize*0.5, yy = buf3[0]*buf1[1]-buf3[1]*buf1[0]; xx = buf3[0]*buf1[0]+buf3[1]*buf1[1]; mag = 100000000000*(buf3[]*buf3[] + buf3[1]*buf3[1]) * (buf1[]*buf1[] + buf1[1]*buf1[1]); gfx_set(.6, .6, 1, min(mag, 1.0)); ang = -atan2(yy, xx); buf3+=2; buf1+=2; integrate_en ? ( ang = intbuf_ptr[] += integrate_sc * (ang - intbuf_ptr[]); intbuf_ptr+=1; ); unwrap = 0; unwrap ? ( phase_diff = ang - last_ang; phase_diff > ($pi-eps) ? phase_diff -= 2.0 * $pi; phase_diff < -($pi-eps) ? phase_diff += 2.0 * $pi; last_ang = ang; plot_ang += phase_diff; ) : plot_ang = ang; ty2=(plot_ang*ascale + (gfx_h - spectrum_yoffsetbottom - spectrum_yoffset)*0.5) + spectrum_yoffset; tx = log(1.0+i*xscale)*wsc; i && ( tx < spectrum_xmax ) ? ( //gfx_x=lx; gfx_y=ly2; gfx_lineto(tx,ty2,1) ; gfx_circle(tx, ty2, 2, 1); ); lx=tx; ly2=ty2; i+=1; ); ); // Process FFT kernelSize = smoothing > 0 ? floor( smoothing/5 + 1 ) : 0; bufout = filtout + kernelSize; // Integrate the FFT over time to smooth it. // Note that yOut and buf3 both point to the FFTW space. yOut is written after buf3 is read so // they don't conflict. buf3 = fftwspace2; buf1 = fftwspace; yOut = fftwspace; intbuf_ptr = intbuf; intbuf2_ptr = intbuf2; i = 0; slope = .5*log(2)*slider38; prec = (10^(-500/20*2)); eps = 0.000000000000000000001; loop(fftsize*0.5, y1 = sqr(buf3[0])+sqr(buf3[1]); y2 = sqr(buf1[0])+sqr(buf1[1]); ty = log(max(y1,prec)); ty2 = log(max(y2,prec)); integrate_en ? ( maxIntegrate ? ( ty = intbuf_ptr[] = max(ty, intbuf_ptr[] - integrate_sc); ty2 = intbuf2_ptr[] = max(ty2, intbuf2_ptr[] - integrate_sc); ) : ( ty = intbuf_ptr[] += integrate_sc * (ty - intbuf_ptr[]); ty2 = intbuf2_ptr[] += integrate_sc * (ty2 - intbuf2_ptr[]); ); intbuf_ptr+=1; intbuf2_ptr+=1; ); ty -= ty2; // ty2 < eps && ty > eps ? ty = 100000000; yOut[] = ty; yOut += 1; bufout[] = ty*-0.5*logf_to_pixels + spectrum_yoffset - spectral_offset_pixels; bufout += 1; i += 1; buf3 += 2; buf1 += 2; ); // Copy the last few to the front bufout = filtout + kernelSize; last = bufout[]; loop(kernelSize, bufout -= 1; bufout[] = last; ); prepareForDrawing(filtout, rpos, fftwspace, intbuf, bufStart, rr, gg, bb, fill, draw, fftsize, xscale, floor(slider45), kernelSize) ); // Scrollwheel (abs(mouse_wheel) > 0) ? ( mouse_wheel = 0.01 * mouse_wheel; sonogram.hit_button(mouse_x,mouse_y,-1) ? ( ( slider29 == 0 ) ? slider35 = mouse_wheel_button(slider35, 1, 8, mouse_wheel) : slider31 = mouse_wheel_button(slider31, 1, 8, mouse_wheel); ) : ( slider6 = mouse_wheel_button(slider6, 1, 8, mouse_wheel); ); mouse_wheel = 0; ); (mouse_cap & 2) ? ( !(last_mouse_cap & 2) ? ( ch1.hit_button(mouse_x,mouse_y,-1) ? ( slider28=0; slider_automate(slider28); old_w = 0); ch2.hit_button(mouse_x,mouse_y,-1) ? ( slider28=1; slider_automate(slider28); old_w = 0); ch3.hit_button(mouse_x,mouse_y,-1) ? ( slider28=2; slider_automate(slider28); old_w = 0); ch4.hit_button(mouse_x,mouse_y,-1) ? ( slider28=3; slider_automate(slider28); old_w = 0); ch5.hit_button(mouse_x,mouse_y,-1) ? ( slider28=4; slider_automate(slider28); old_w = 0); ch6.hit_button(mouse_x,mouse_y,-1) ? ( slider28=5; slider_automate(slider28); old_w = 0); ch7.hit_button(mouse_x,mouse_y,-1) ? ( slider28=6; slider_automate(slider28); old_w = 0); ch8.hit_button(mouse_x,mouse_y,-1) ? ( slider28=7; slider_automate(slider28); old_w = 0); ch9.hit_button(mouse_x,mouse_y,-1) ? ( slider28=8; slider_automate(slider28); old_w = 0); ch10.hit_button(mouse_x,mouse_y,-1) ? ( slider28=9; slider_automate(slider28); old_w = 0); ch11.hit_button(mouse_x,mouse_y,-1) ? ( slider28=10; slider_automate(slider28); old_w = 0); ch12.hit_button(mouse_x,mouse_y,-1) ? ( slider28=11; slider_automate(slider28); old_w = 0); ch13.hit_button(mouse_x,mouse_y,-1) ? ( slider28=12; slider_automate(slider28); old_w = 0); ch14.hit_button(mouse_x,mouse_y,-1) ? ( slider28=13; slider_automate(slider28); old_w = 0); ch15.hit_button(mouse_x,mouse_y,-1) ? ( slider28=14; slider_automate(slider28); old_w = 0); ch16.hit_button(mouse_x,mouse_y,-1) ? ( slider28=15; slider_automate(slider28); old_w = 0); showSumButton.hit_button(mouse_x,mouse_y,-1) ? ( slider28=-1; slider_automate(slider28); old_w = 0); showChannel = slider28; ( mouse_y < (gfx_h-sono_yoffset_bottom-sono_size) ) && ( mouse_x < ( gfx_w - spectrum_xpad ) ) ? ( ( zoomMode == 0 && (hide_spectrum == 0) ) ? ( // Not zooming old_mouse_x = mouse_x; old_mouse_y = mouse_y; zoomMode = 1; ); ( zoomMode == 2 ) ? ( spectrum_xoffset = 0; slider6 = 1.0; scaling = slider6; slider_automate(slider6); zoomMode = 0; ); ); slider29 == 0 && cap_last_y != mouse_y ) ? ( //sonogram.hit_button(mouse_x,mouse_y,-1) ? ( slider32 = cycle_slider(slider32, 0, 7, 1); ); ((mouse_y > gfx_h-sono_yoffset_bottom-sono_size) && (mouse_y < gfx_h - sono_yoffset_bottom)) ? ( gfx_x = mouse_x; gfx_y = mouse_y; sprintf(22, ">Colormaps|%sMagma|%sMagma (inverted)|%sViridis|%sViridis (inverted)|%sInferno|%sInferno (inverted)|%sPlasma|%sPlasma (inverted)|%sTurbo|%sTurbo (inverted)|%sRed Blue|<%sRed Blue (inverted)|%sLogarithmic|%sShow Grid|%sLegacy style|%sShow only sonogram|%s4x speed", slider32 == 0 ? "!" : "", slider32 == 1 ? "!" : "", slider32 == 2 ? "!" : "", slider32 == 3 ? "!" : "", slider32 == 4 ? "!" : "", slider32 == 5 ? "!" : "", slider32 == 6 ? "!" : "", slider32 == 7 ? "!" : "", slider32 == 8 ? "!" : "", slider32 == 9 ? "!" : "", slider32 == 10 ? "!" : "", slider32 == 11 ? "!" : "", slider33 ? "!" : "", (sonoGridAlpha == 0) ? "": "!", legacy_style ? "!" : "", hide_spectrum ? "!": "", fast_proc ? "!": "" ); ret = gfx_showmenu(22); (ret > 0 && ret < 13) ? ( slider32 = ret - 1; ) : (ret == 13) ? ( slider33 = 1 - slider33; ) : (ret == 14) ? ( sonoGridAlpha = (sonoGridAlpha == 0) ? 0.4 : 0; ) : (ret == 15) ? ( legacy_style = 1 - legacy_style; ) : (ret == 16) ? ( hide_spectrum = 1 - hide_spectrum; ) : (ret == 17) ? ( fast_proc = 1 - fast_proc; ); ); ); ) : ( ( zoomMode == 1 ) ? ( zoomMode = 2; f1 = (1/800) * ( exp(old_mouse_x/wsc)-1 ) + spectrum_xoffset; f2 = (1/800) * ( exp(mouse_x/wsc)-1 ) + spectrum_xoffset; f2 < f1 ? ( tmp = f2; f2 = f1; f1 = tmp; ); f2-f1 > .001 ? ( spectrum_xoffset = f1; diff = f2-spectrum_xoffset; // Notes // f = (1/800) * ( exp(mouse_x/wsc)-1 ) * srate + spectrum_xoffset * srate; // wsc = spectrum_xmax / log( 1.0 + 800 * diff ); // denom = spectrum_xmax / log( 1 + 400 ); newscale = log( 1 + 400 ) / log( 1.0 + 800 * diff ); slider6 = newscale; scaling = slider6; slider_automate(slider6); ); ); ); over_sono_divider = !hide_spectrum && (mouse_y > (gfx_h-sono_yoffset_bottom-sono_size-14)) && (mouse_y < (gfx_h-sono_yoffset_bottom-sono_size + 14)); over_sono_divider ? ( new_cursor = 32645; ) : ( new_cursor = 32512; ); (new_cursor != current_cursor) ? ( current_cursor = new_cursor; gfx_setcursor(current_cursor, "arrow"); ); (mouse_cap & 1) ? ( (cap_mode == 0) ? ( drawHz = 1; ) : ( drawHz = 0; ); !(last_mouse_cap & 1) ? ( // Reset to defaults (cap_mode == 1||cap_mode == 4||cap_mode == 5||cap_mode == 6||cap_mode == 8||cap_mode == 9||cap_mode == 10||cap_mode ==30||cap_mode ==31 ||cap_mode ==32 ||cap_mode ==40 ||cap_mode ==42||cap_mode == 44||cap_mode == 49|| (cap_mode > 10 && cap_mode < 27)||cap_mode==28) && !cap_drag && cap_timer < 12 ?( cap_mode == 1 ? ( slider2 = -90; slider_automate(slider2); ) : ( cap_mode == 49 ? ( scale_offset_db_user = 0; slider_automate(scale_offset_db_user); ) : ( cap_mode == 4 ? ( slider5 = 0; slider_automate(slider5); ) : ( cap_mode == 5 ? ( slider6 = 1.0; slider_automate(slider6); ) : ( cap_mode == 6 ? ( // Smoothing smoothing = 20; slider_automate(smoothing); ) : ( cap_mode == 8 ? ( // Sonogram slider34 = !slider34; // slider30 = 2500; slider_automate(slider34); ) : ( cap_mode == 9 ? ( // Time slider34 = !slider34; // slider31 = 1; slider_automate(slider31); ) : ( cap_mode == 10 ? ( // Sonogram scaling slider35 = 1; slider_automate(slider35); ) : ( cap_mode == 29 ? ( // Slope slider38 = 0; slider_automate(slider38); ) : ( cap_mode == 28 ? ( // Alpha slider37 = .5; ) : ( cap_mode == 30 ? ( // ColorBackground slider10 = .5; ) : ( cap_mode == 31 ? ( // gridAlpha slider40 = .5; ) : ( cap_mode == 32 ? ( // Freeze slider44 = 0; ) : ( cap_mode == 42 ? ( // Options slider42 = 1; slider_automate(slider42); ) : ( // One of the channel buttons (cap_mode > 10 && cap_mode < 27) ? ( // Was something solo'd? ( slider36 > -1 ) ? ( slider36 = -1; ) : ( ( ch1.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 11 ) ? ( slider36 = 0; slider11 = 1; slider_automate(slider11); updateSliders = 1; ) : checkChannelButtons(); ); ( ch2.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 12 ) ? ( slider36 = 1; slider12 = 1; slider_automate(slider12); updateSliders = 1; ) : checkChannelButtons(); ); ( ch3.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 13 ) ? ( slider36 = 2; slider13 = 1; slider_automate(slider13); updateSliders = 1; ) : checkChannelButtons(); ); ( ch4.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 14 ) ? ( slider36 = 3; slider14 = 1; slider_automate(slider14); updateSliders = 1; ) : checkChannelButtons(); ); ( ch5.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 15 ) ? ( slider36 = 4; slider15 = 1; slider_automate(slider15); updateSliders = 1; ) : checkChannelButtons(); ); ( ch6.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 16 ) ? ( slider36 = 5; slider16 = 1; slider_automate(slider16); updateSliders = 1; ) : checkChannelButtons(); ); ( ch7.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 17 ) ? ( slider36 = 6; slider17 = 1; slider_automate(slider17); updateSliders = 1; ) : checkChannelButtons(); ); ( ch8.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 18 ) ? ( slider36 = 7; slider18 = 1; slider_automate(slider18); updateSliders = 1; ) : checkChannelButtons(); ); ( ch9.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 19 ) ? ( slider36 = 8; slider19 = 1; slider_automate(slider19); updateSliders = 1; ) : checkChannelButtons(); ); ( ch10.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 20 ) ? ( slider36 = 9; slider20 = 1; slider_automate(slider20); updateSliders = 1; ) : checkChannelButtons(); ); ( ch11.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 21 ) ? ( slider36 = 10; slider21 = 1; slider_automate(slider21); updateSliders = 1; ) : checkChannelButtons(); ); ( ch12.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 22 ) ? ( slider36 = 11; slider22 = 1; slider_automate(slider22); updateSliders = 1; ) : checkChannelButtons(); ); ( ch13.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 23 ) ? ( slider36 = 12; slider23 = 1; slider_automate(slider23); updateSliders = 1; ) : checkChannelButtons(); ); ( ch14.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 24 ) ? ( slider36 = 13; slider24 = 1; slider_automate(slider24); updateSliders = 1; ) : checkChannelButtons(); ); ( ch15.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 25 ) ? ( slider36 = 14; slider25 = 1; slider_automate(slider25); updateSliders = 1; ) : checkChannelButtons(); ); ( ch16.hit_button(mouse_x,mouse_y,cap_mode) ? ( cap_mode == 26 ) ? ( slider36 = 15; slider26 = 1; slider_automate(slider26); updateSliders = 1; ) : checkChannelButtons(); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); ); cap_mode=0; old_w=0; ) : ( cap_mode = cap_drag = cap_timer = 0; store_a_button.hit_button(mouse_x,mouse_y,-1) ? ( copyTo = 1; showA = 1; ) : store_b_button.hit_button(mouse_x,mouse_y,-1) ? ( copyTo = 2; showB = 1; ) : freeze_button.hit_button(mouse_x,mouse_y,-1) ? ( slider44=1 - slider44; slider_automate(slider44); old_w = 0) : options_button.hit_button(mouse_x,mouse_y,-1) ? ( slider42=!slider42; slider_automate(slider42); old_w = 0; ) : ( slider42 == 0 ? ( phase_button.hit_button(mouse_x,mouse_y,-1) ? ( slider3=!slider3; slider_automate(slider3); old_w = 0; ); theme_button.hit_button(mouse_x,mouse_y,-1) ? ( slider43=!slider43; slider_automate(slider43); old_w = 0; ); grid_button.hit_button(mouse_x,mouse_y,-1) ? ( slider39=!slider39; slider_automate(slider39); old_w = 0; ); gridAlpha_button.hit_button(mouse_x,mouse_y,31); ); ); channels_button.hit_button(mouse_x,mouse_y,-1) ? ( slider41=!slider41; slider_automate(slider41); old_w = 0; ) : sonogram.hit_button(mouse_x,mouse_y,slider29 == 0 ? 8 : 9); showOptions = slider42 == 0; checkChannelButtons() ? : showOptions ? ( showSumButton.hit_button(mouse_x,mouse_y,-1) ? ( slider27=!slider27; slider_automate(slider27); updateSliders = 1; old_w = 0) : floor_button.hit_button(mouse_x,mouse_y,1); ceil_button.hit_button(mouse_x,mouse_y, 49); slope_button.hit_button(mouse_x,mouse_y,29); window_button.hit_button(mouse_x,mouse_y,2); fft_button.hit_button(mouse_x,mouse_y,3); integrate_button.hit_button(mouse_x,mouse_y,4); integration_type_button.hit_button(mouse_x, mouse_y, 46); show_side_button.hit_button(mouse_x, mouse_y, 47); show_notes_button.hit_button(mouse_x, mouse_y, 50); interpolation_button.hit_button(mouse_x, mouse_y, 51); diff_mode_button.hit_button(mouse_x, mouse_y, 48); scaling.hit_button(mouse_x,mouse_y,5); slider43 == 1 ? colormap.hit_button(mouse_x,mouse_y,7); smoothing_button.hit_button(mouse_x,mouse_y,6); slider43 == 1 ? alphalevel.hit_button(mouse_x,mouse_y,28); slider43 == 1 ? background_button.hit_button(mouse_x,mouse_y,30); sonoScale.hit_button(mouse_x,mouse_y,10) ? : smoothing_type.hit_button(mouse_x,mouse_y,45); // Note that the sonogram condition works for capmode8 and 9 (sonogram / scope) since they are in the same position sonogram_button.hit_button(mouse_x,mouse_y,-1) ? ( slider29=slider29+1; slider29>3?slider29=0; slider_automate(slider29); old_w = 0 ) : sonoLog.hit_button(mouse_x,mouse_y,-1) ? ( slider33=!slider33; slider_automate(slider33); updateSliders = 1; old_w = 0); // Only visible in TD mode ((slider29 == 1) || (slider29 == 2)) ? ( scrolling.hit_button(mouse_x, mouse_y, -1) ? ( slider34 = 1; ) : frozen.hit_button(mouse_x, mouse_y, -1) ? ( slider34 = 0; sync = 0; ) : sync1.hit_button(mouse_x, mouse_y, -1) ? ( slider34 = 0; sync = 1; ) : sync2.hit_button(mouse_x, mouse_y, -1) ? ( slider34 = 0; sync = 2; ) : sync3.hit_button(mouse_x, mouse_y, -1) ? ( slider34 = 0; sync = 3; ) : sync4.hit_button(mouse_x, mouse_y, -1) ? ( slider34 = 0; sync = 4; ); ); ); ); ( over_sono_divider ) ? ( !(cap_mode > 10 && cap_mode < 27) ? ( cap_mode = 60; cap_last_y = mouse_y; ); ); ) : cap_mode == 1 && cap_last_y != mouse_y ? ( slider2 = drag_slider_precise(slider2, -450, -12, 0.2); old_w=0; slider_automate(slider2); ) : cap_mode == 49 && cap_last_y != mouse_y ? ( scale_offset_db_user = drag_slider_precise(scale_offset_db_user, -48, 48, 0.1); old_w=0; slider_automate(scale_offset_db_user); ) : cap_mode == 2 && cap_last_y != mouse_y ? ( slider4 = drag_slider(slider4, 0.0, 5.0, .03); old_w=0; slider_automate(slider4); ) : cap_mode == 46 && cap_last_y != mouse_y ? ( maxIntegrate = drag_slider(maxIntegrate, 0.0, 1.0, .03); old_w=0; slider_automate(maxIntegrate); ) : cap_mode == 47 && cap_last_y != mouse_y ? ( showSide = drag_slider(showSide, 0.0, 1.0, .03); old_w=0; slider_automate(showSide); ) : cap_mode == 50 && cap_last_y != mouse_y ? ( showNotes = drag_slider(showNotes, 0.0, 1.0, .03); old_w=0; ) : cap_mode == 51 && cap_last_y != mouse_y ? ( interpolate_lines = drag_slider(interpolate_lines, 0.0, 1.0, .03); old_w = 0; ) : cap_mode == 48 && cap_last_y != mouse_y ? ( displayMode = drag_slider(displayMode, 0.0, 1.0, .03); old_w=0; slider_automate(displayMode); ) : cap_mode == 3 && cap_last_y != mouse_y ? ( slider1 = drag_slider(slider1, 0.0, 11.0, .03); old_w=0; slider_automate(slider1); ) : cap_mode == 4 && cap_last_y != mouse_y ? ( // Integration time slider5 = drag_slider_precise(slider5, 0.0, 25000.0, 5); old_w=0; slider_automate(slider5); ) : cap_mode == 5 && cap_last_y != mouse_y ? ( // Scale slider6 = drag_slider_precise(slider6, 1.0, 6, .2); old_w=0; slider_automate(slider6); ) : cap_mode == 6 && cap_last_y != mouse_y ? ( // Smoothing smoothing = drag_slider_precise(smoothing, 0.0, 100, 1); old_w=0; slider_automate(smoothing); ) : cap_mode == 7 && cap_last_y != mouse_y ? ( // Colormap slider8 = drag_slider(slider8, 0.01, 14, .03); old_w=0; slider_automate(slider8); ) : cap_mode == 8 && cap_last_y != mouse_y ? ( // Sonogram slider30 = drag_slider(slider30, 0, 35000, 100); old_w=0; slider_automate(slider30); ) : cap_mode == 9 && cap_last_y != mouse_y ? ( // Signal slider31 = drag_slider_precise(slider31, 0.1, 3, .03); offset_x = drag_slider_precise_x(offset_x, 0, 0.5, 0.001); old_w=0; slider_automate(slider31); slider_automate(offset_x); ) : cap_mode == 10 && cap_lasty_y != mouse_y ? ( // Sono scaling slider35 = floor(drag_slider_precise(slider35, 1, 8, .1)); old_w=0; slider_automate(slider35); ) : cap_mode == 28 && cap_lasty_y != mouse_y ? ( // Alpha level slider37 = drag_slider_precise(slider37, 0, 1, .025); old_w=0; slider_automate(slider37); ) : cap_mode == 29 && cap_lasty_y != mouse_y ? ( slider38 = drag_slider_precise(slider38, 0,9,.25); old_w=0; slider_automate(slider38); ) : cap_mode == 30 && cap_lasty_y != mouse_y ? ( // Alpha level slider10 = drag_slider_precise(slider10, 0, 1, .025); old_w=0; slider_automate(slider10); ) : cap_mode == 31 && cap_lasty_y != mouse_y ? ( // Grid Alpha slider40 = drag_slider_precise(slider40, 0, 1, .025); old_w=0; slider_automate(slider40); ) : cap_mode == 60 && cap_lasty_y != mouse_y ? ( sono_frac = (1-(mouse_y+sono_yoffset_bottom)/gfx_h); ) : cap_mode == 45 && cap_last_y != mouse_y ? ( slider45 = drag_slider(slider45, 0.0, 4.0, .03); old_w=0; slider_automate(slider45); ); ) : ( // RMB drawHz = 0; (last_mouse_cap & 1) && !cap_drag ? ( cap_mode == 2 ? ( slider4 = cycle_slider(slider4, 0.0, 3.0, 1.0); old_w=0; slider_automate(slider4); ); cap_mode == 3 ? ( slider1 = cycle_slider(slider1, 0.0, 11.0, 1.0); old_w=0; slider_automate(slider1); ); cap_mode == 45 ? ( slider45 = cycle_slider(slider45, 0.0, 4.0, 1.0); old_w=0; slider_automate(slider45); ); cap_mode == 46 ? ( maxIntegrate = cycle_slider(maxIntegrate, 0.0, 1.0, 1.0); old_w=0; slider_automate(maxIntegrate); ); cap_mode == 47 ? ( showSide = cycle_slider(showSide, 0.0, 1.0, 1.0); old_w=0; slider_automate(showSide); ); cap_mode == 50 ? ( showNotes = cycle_slider(showNotes, 0.0, 1.0, 1.0); old_w=0; ); cap_mode == 51 ? ( interpolate_lines = cycle_slider(interpolate_lines, 0.0, 1.0, 1.0); old_w=0; ); cap_mode == 48 ? ( displayMode = cycle_slider(displayMode, 0.0, 1.0, 1.0); old_w=0; slider_automate(displayMode); ); ); ); function DrawButtons() ( buttonPad = 3; gfx_measurestr(" >A", storeAX, freezeY); gfx_measurestr(" >A >B", storeBX, freezeY); frstr = slider44 == 1 ? "Unfreeze" : "Freeze"; gfx_measurestr(frstr, freezeX, freezeY); freeze_button.draw_button(freezeX+8, 3, frstr); gfx_measurestr(">", addX, freezeY); freezeX = freezeX + addX; storeAX = storeAX + freezeX; storeBX = storeBX + freezeX; store_a_button.draw_button(storeAX, 3, ">A"); store_b_button.draw_button(storeBX, 3, ">B"); // hide buttons gfx_measurestr("| <- |", arrowX, arrowY); arrowY = gfx_h-arrowY - 14; channels_button.draw_button(arrowX + 8, arrowY, slider41 ?"| -> |" : "| <- |"); postOptions = options_button.draw_button(gfx_w - 10, 3, slider42 ?"<<:: OPTIONS ::" : ">>:: OPTIONS ::"); gfx_x -= 8; optBar = gfx_x; gfx_y = 8; slider42 == 0 ? ( fft_button.str_add_measure("FFT 32768"); fft_button.draw_button_wrap(gfx_y, sprintf(#,"FFT: %d",16< 0 ? ( // Reset channel names setChannelNames(); gmem[0] == 2 ? ( // Back up current user colortheme cref_bak = slider8 != 15 ? slider8 : cref_bak; // Change to track colortheme sliderchange(slider8 = 15); cref = (10000 + 100*floor(slider8)); // Set default colors to dark gray cidx = 0; while (cidx < 16*3) ( cref[cidx] = 0.13; cidx = cidx + 1; ); ) : cref_bak > 0 && slider8 == 15 ? ( // Restore user colortheme sliderchange(slider8 = cref_bak); ); cidx = 0; addr = 1; chName = 0; while (gmem[addr] != 256) ( gmem[0] == 2 ? ( // Load RGB color to track colortheme cref[cidx+0] = gmem[addr+0] / 255; cref[cidx+1] = gmem[addr+1] / 255; cref[cidx+2] = gmem[addr+2] / 255; cidx = cidx + 3; addr = addr + 3; ); // Change channel name to track name sOffs = 0; while (gmem[addr] != 256) ( str_setchar(chName, sOffs, gmem[addr], 'c'); sOffs = sOffs + 1; addr = addr + 1; ); str_setlen(chName, min(10, sOffs)); chName = chName + 1; addr = addr + 1; ); trCnt = chName; update = 1; gmem[0] = 0; ); gfx_measurestr("Ch16", chW, chH); chButtonPad = !trCnt ? 8 : 10; chButtonWidth = !trCnt ? chW + 10 : chW + 58; chButtonSpace = chButtonWidth+chButtonPad; chButtonYSpace = chH + 24; totalButtonWidth = !trCnt ? 18 * chButtonSpace : (trCnt + 2) * chButtonSpace; xButBlocked = max(spectrum_xpad, theme_button.w+8); slider41 == 0 ?( gfx_w > ( totalButtonWidth + xButBlocked + arrowX + 8 ) ? ( chB.draw_button2_fixedWidth(gfx_w/2 -xButBlocked*0.5 + .5*totalButtonWidth + .5*arrowX, arrowY, chButtonWidth, "MemB", showB, 0, 0, 0, 15); chA.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, "MemA", showA, 0, 0, 0, 15); !trCnt || trCnt > 15 ? ch16.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[15], slider26, slider28==15, slider36==15, slider36>-1, 15); !trCnt || trCnt > 14 ? ch15.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[14], slider25, slider28==14, slider36==14, slider36>-1, 14); !trCnt || trCnt > 13 ? ch14.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[13], slider24, slider28==13, slider36==13, slider36>-1, 13); !trCnt || trCnt > 12 ? ch13.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[12], slider23, slider28==12, slider36==12, slider36>-1, 12); !trCnt || trCnt > 11 ? ch12.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[11], slider22, slider28==11, slider36==11, slider36>-1, 11); !trCnt || trCnt > 10 ? ch11.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[10], slider21, slider28==10, slider36==10, slider36>-1, 10); !trCnt || trCnt > 9 ? ch10.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[9], slider20, slider28==9, slider36==9, slider36>-1, 9); !trCnt || trCnt > 8 ? ch9.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[8], slider19, slider28==8, slider36==8, slider36>-1, 8); !trCnt || trCnt > 7 ? ch8.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[7], slider18, slider28==7, slider36==7, slider36>-1, 7); !trCnt || trCnt > 6 ? ch7.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[6], slider17, slider28==6, slider36==6, slider36>-1, 6); !trCnt || trCnt > 5 ? ch6.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[5], slider16, slider28==5, slider36==5, slider36>-1, 5); !trCnt || trCnt > 4 ? ch5.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[4], slider15, slider28==4, slider36==4, slider36>-1, 4); !trCnt || trCnt > 3 ? ch4.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[3], slider14, slider28==3, slider36==3, slider36>-1, 3); !trCnt || trCnt > 2 ? ch3.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[2], slider13, slider28==2, slider36==2, slider36>-1, 2); !trCnt || trCnt > 1 ? ch2.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[1], slider12, slider28==1, slider36==1, slider36>-1, 1); !trCnt || trCnt > 0 ? ch1.draw_button2_fixedWidth(gfx_x-=8, arrowY, chButtonWidth, chNames[0], slider11, slider28==0, slider36==0, slider36>-1, 0); ) : ( slider42 != 0 ?( yBStart = 6 * chButtonYSpace + chH + postOptions + spectrum_yoffset; // + 24 = Small fix? Avoid channel buttons overlapping with options ) : ( yBStart = gfx_h - yShift - chButtonYSpace; ); bRowCol1 = gfx_w-10; bRowCol2 = gfx_w-10-chButtonWidth-chButtonPad; chB.draw_button2_fixedWidth(bRowCol1 , yBStart, chButtonWidth, "MemB", showB, 0, 0, 0, 7); ch16.draw_button2_fixedWidth(bRowCol1 , gfx_y-chButtonYSpace, chButtonWidth, chNames[15], slider26, slider28==15, slider36==15, slider36>-1, 15); ch15.draw_button2_fixedWidth(bRowCol1 , gfx_y-chButtonYSpace, chButtonWidth, chNames[14], slider25, slider28==14, slider36==14, slider36>-1, 14); ch14.draw_button2_fixedWidth(bRowCol1 , gfx_y-chButtonYSpace, chButtonWidth, chNames[13], slider24, slider28==13, slider36==13, slider36>-1, 13); ch13.draw_button2_fixedWidth(bRowCol1 , gfx_y-chButtonYSpace, chButtonWidth, chNames[12], slider23, slider28==12, slider36==12, slider36>-1, 12); ch12.draw_button2_fixedWidth(bRowCol1 , gfx_y-chButtonYSpace, chButtonWidth, chNames[11], slider22, slider28==11, slider36==11, slider36>-1, 11); ch11.draw_button2_fixedWidth(bRowCol1 , gfx_y-chButtonYSpace, chButtonWidth, chNames[10], slider21, slider28==10, slider36==10, slider36>-1, 10); ch10.draw_button2_fixedWidth(bRowCol1 , gfx_y-chButtonYSpace, chButtonWidth, chNames[9], slider20, slider28==9, slider36==9, slider36>-1, 9); ch9.draw_button2_fixedWidth(bRowCol1 , gfx_y-chButtonYSpace, chButtonWidth, chNames[8], slider19, slider28==8, slider36==8, slider36>-1, 8); chA.draw_button2_fixedWidth(bRowCol2 , yBStart, chButtonWidth, "MemA", showA, 0, 0, 0, 7); ch8.draw_button2_fixedWidth(bRowCol2 , gfx_y-chButtonYSpace, chButtonWidth, chNames[7], slider18, slider28==7, slider36==7, slider36>-1, 7); ch7.draw_button2_fixedWidth(bRowCol2, gfx_y-chButtonYSpace, chButtonWidth, chNames[6], slider17, slider28==6, slider36==6, slider36>-1, 6); ch6.draw_button2_fixedWidth(bRowCol2, gfx_y-chButtonYSpace, chButtonWidth, chNames[5], slider16, slider28==5, slider36==5, slider36>-1, 5); ch5.draw_button2_fixedWidth(bRowCol2, gfx_y-chButtonYSpace, chButtonWidth, chNames[4], slider15, slider28==4, slider36==4, slider36>-1, 4); ch4.draw_button2_fixedWidth(bRowCol2, gfx_y-chButtonYSpace, chButtonWidth, chNames[3], slider14, slider28==3, slider36==3, slider36>-1, 3); ch3.draw_button2_fixedWidth(bRowCol2, gfx_y-chButtonYSpace, chButtonWidth, chNames[2], slider13, slider28==2, slider36==2, slider36>-1, 2); ch2.draw_button2_fixedWidth(bRowCol2, gfx_y-chButtonYSpace, chButtonWidth, chNames[1], slider12, slider28==1, slider36==1, slider36>-1, 1); ch1.draw_button2_fixedWidth(bRowCol2, gfx_y-chButtonYSpace, chButtonWidth, chNames[0], slider11, slider28==0, slider36==0, slider36>-1, 0); ) ); slider42 == 0 ? ( gfx_measurestr("Log(Sonogram)", sonoTxtW, sonoTxtH); gfx_measurestr("< Sonogram |", hideTxtW, sonoTxtH); postOptions = showSumButton.draw_button2_fixedWidth(gfx_w-10, postOptions+2*buttonPad, hideTxtW, "SUM", slider27, slider28==-1, 0, 0, -1); postOptions = phase_button.draw_button2_fixedWidth(gfx_w-10,postOptions+buttonPad, hideTxtW, "Phase", slider3, slider3>1, slider3== 2, slider3>-1, -1); postOptions = grid_button.draw_button2_fixedWidth(gfx_w-10, postOptions+buttonPad, hideTxtW, "GRID", slider39, slider39>1, slider39== 2, slider39>-1, -1); slider39 == 1 ? ( postOptions = gridAlpha_button.draw_button_fixedWidth(gfx_w-10, postOptions+buttonPad, hideTxtW, sprintf(#,"^ Alpha: %.1f ^" ,slider40)) ); postSono = sonogram_button.draw_button_fixedWidth(gfx_w-10, postOptions + 4*buttonPad, hideTxtW, slider29==2?">> Hide >>" : slider29==1?"< Time (all) >" : slider29==0?"< Time >" : "< Sonogram |"); slider29 == 0 ? ( sonoLog.draw_button2_fixedWidth(gfx_w-10, postSono+buttonPad, hideTxtW, "Log(Sonogram)", slider33, 0, 0, 0, -1) ) : ((slider29 == 1) || (slider29 == 2)) ? ( scrolling.draw_button2_fixedWidth(gfx_w-10, postSono + buttonPad, hideTxtW, "Scroll", slider34 == 1, 0, 0, 0, -1); frozen.draw_button2_fixedWidth(gfx_w-10, postSono + 2 * buttonPad + scrolling.h, hideTxtW, "Sync (Full)", slider34 == 0 && sync == 0, 0, 0, 0, -1); sync1.draw_button2_fixedWidth(gfx_w-10, postSono + 3 * buttonPad + 2 * scrolling.h, hideTxtW, "Sync (1/2)", slider34 == 0 && sync == 1, 0, 0, 0, -1); sync2.draw_button2_fixedWidth(gfx_w-10, postSono + 4 * buttonPad + 3 * scrolling.h, hideTxtW, "Sync (1)", slider34 == 0 && sync == 2, 0, 0, 0, -1); sync3.draw_button2_fixedWidth(gfx_w-10, postSono + 5 * buttonPad + 4 * scrolling.h, hideTxtW, "Sync (2)", slider34 == 0 && sync == 3, 0, 0, 0, -1); sync4.draw_button2_fixedWidth(gfx_w-10, postSono + 6 * buttonPad + 5 * scrolling.h, hideTxtW, "Sync (4)", slider34 == 0 && sync == 4, 0, 0, 0, -1); ); ); ); function updateSpectralBounds() ( slider29 == 3 ? ( sono_size = 0 ) : ( hide_spectrum ? ( sono_size = gfx_h - (25 + sono_yoffset_bottom) * (1.0 - micro_view); ) : ( sono_size = sono_frac * gfx_h ); ); // SET THE OFFSETS HERE spectrum_yoffset = 25 * (1 - hideUI) * (1 - micro_view) * (1 + 0.7 * (gfx_ext_retina == 2)); ( slider42 == 0 ) ? ( spectrum_xpad = 150 * (1 - hideUI) * (1 - micro_view); sono_yoffset_bottom = 35; spectrum_yoffsetbottom = sono_yoffset_bottom + sono_size; spectrum_xmax = gfx_w - spectrum_xpad; ) : ( spectrum_xpad = 0; sono_yoffset_bottom = 35; spectrum_yoffsetbottom = sono_yoffset_bottom + sono_size; spectrum_xmax = gfx_w - spectrum_xpad; ); ( slider41 == 0 ) ? ( sono_yoffset_bottom = 30 * (1 - hideUI) * (1 - micro_view); spectrum_yoffsetbottom = sono_yoffset_bottom + sono_size; ) : ( sono_yoffset_bottom = 6; spectrum_yoffsetbottom = sono_yoffset_bottom + sono_size; ); spectrum_center = spectrum_yoffset - spectral_offset_pixels; scaling = slider6; bgcolor = slider10; ); function sub(mem1, mem2, size) local() global() instance() ( loop(size, mem1[] -= mem2[]; mem1 += 1; mem2 += 1; ); ); function drawDifferenceSpectra(rpos, fftw, ibuf, shft, hsiz) global(maxchannels, activechannels, isActive, showSide, fftsize filtout, xscale, kernelSize, slider8, ss) local(j, first, second, from, to, rr, gg, bb, ccolor, cref) ( first = -1; second = -1; isActive = activechannels; from = 0; to = 0; j = 0; loop(maxchannels, (isActive[j] == 1) ? ( (first == -1) ? ( first = j; ) : ( second == -1 ) ? ( second = j; ); ); j += 1; ); cref = (10000 + 100*floor(slider8)); ccolor = cref; (first > -1) && (second > -1) ? ( showSide ? processFFTDifference((rpos + maxchannels)[first], (fftw + maxchannels)[first], (ibuf + maxchannels)[first], (shft + maxchannels)[first], (hsiz + maxchannels)[first], (rpos + maxchannels)[second], (fftw + maxchannels)[second], (ibuf + maxchannels)[second], (shft + maxchannels)[second], (hsiz + maxchannels)[second], ccolor[0], ccolor[1], ccolor[2], 1, 2); processFFTDifference(rpos[first], fftw[first], ibuf[first], shft[first], hsiz[first], rpos[second], fftw[second], ibuf[second], shft[second], hsiz[second], ccolor[0], ccolor[1], ccolor[2], 1, 1); ); ); function drawSpectra(rpos, fftw, ibuf, shft, hsiz) global(slider8, slider36, slider45, mem_block_size, maxchannels, max_active_channels, showSide, activechannels, showSum, copyTo, bgcolor, sumposr, fftwr, ibufr, sumshr, sumhsr, sumposl, fftwl, ibufl, sumshl, sumhsl fftw, ibuf, shft, hsiz, rpos, memA, memA2, memB, memB2, filtout, showA, showB, M_BLOCK_SIZE, kernelSize, fftsize, xscale, sModeA, kernelSizeA, fftSizeA, xScaleA, sModeB, kernelSizeB, fftSizeB, xScaleB, lockSettings, smoothing) local(jl, incr, cref, ccolor, jl, isActive, halfShade, shade) instance() ( incr = 3; cref = (10000 + 100*floor(slider8)); ccolor = cref; jl = 1; isActive = activechannels; loop(max_active_channels, (isActive[] == 1) ? ( ( slider36 < 0 || ( slider36 == (jl-1) ) ) ? ( showSide ? processFFT((rpos+maxchannels)[], (fftw+maxchannels)[], (ibuf+maxchannels)[], (shft+maxchannels)[], (hsiz+maxchannels)[], ccolor[0], ccolor[1], ccolor[2], 1, 2); processFFT(rpos[], fftw[], ibuf[], shft[], hsiz[], ccolor[0], ccolor[1], ccolor[2], 1, 1); ); ); rpos += 1; fftw += 1; ibuf += 1; shft += 1; hsiz += 1; jl += 1; ccolor += incr; isActive += 1; ); showSum || copyTo ? ( halfshade = 0.3 * bgcolor + 0.7 * ( 1-bgcolor ); shade = 1-bgcolor; processFFT(sumposr, fftwr, ibufr, sumshr, sumhsr, halfshade, halfshade, halfshade, 0, 1); (copyTo == 1) ? memcpy(memA2, filtout, mem_block_size); (copyTo == 2) ? memcpy(memB2, filtout, mem_block_size); processFFT(sumposl, fftwl, ibufl, sumshl, sumhsl, shade, shade, shade, 0, 1); copyTo == 1 ? ( memcpy(memA, filtout, mem_block_size); copyTo = 0; sModeA = floor(slider45); kernelSizeA = kernelSize; fftSizeA = fftsize; xscaleA = xscale; ); copyTo == 2 ? ( memcpy(memB, filtout, mem_block_size); copyTo = 0; sModeB = floor(slider45); kernelSizeB = kernelSize; fftSizeB = fftsize; xscaleB = xscale; ); ); lockSettings ? ( showA ? ( memcpy(filtout, memA, mem_block_size); prepareForDrawing(filtout, sumposl, fftwl, ibufl, sumshl, .5, .5, .5, 1, 1, fftsizeA, xscaleA, sModeA, kernelSizeA); memcpy(filtout, memA2, mem_block_size); prepareForDrawing(filtout, sumposl, fftwl, ibufl, sumshl, .5, .5, .5, 1, 1, fftsizeA, xscaleA, sModeA, kernelSizeA); ); showB ? ( memcpy(filtout, memB, mem_block_size); prepareForDrawing(filtout, sumposl, fftwl, ibufl, sumshl, .5, .5, .5, 1, 1, fftsizeB, xscaleB, sModeB, kernelSizeB); memcpy(filtout, memB2, mem_block_size); prepareForDrawing(filtout, sumposl, fftwl, ibufl, sumshl, .5, .5, .5, 1, 1, fftsizeB, xscaleB, sModeB, kernelSizeB); ); ) : ( kernelSize = smoothing > 0 ? floor( smoothing/5 + 1 ) : 0; showA ? ( memcpy(filtout, memA, mem_block_size); prepareForDrawing(filtout - kernelSize + kernelSizeA, sumposl, fftwl, ibufl, sumshl, .5, .5, .5, 1, 1, fftsizeA, xscale, floor(slider45), kernelSize); memcpy(filtout, memA2, mem_block_size); prepareForDrawing(filtout - kernelSize + kernelSizeA, sumposl, fftwl, ibufl, sumshl, .5, .5, .5, 1, 1, fftsizeA, xscale, floor(slider45), kernelSize); ); showB ? ( memcpy(filtout, memB, mem_block_size); prepareForDrawing(filtout - kernelSize + kernelSizeB, sumposl, fftwl, ibufl, sumshl, .5, .5, .5, 1, 1, fftsizeB, xscale, floor(slider45), kernelSize); memcpy(filtout, memB2, mem_block_size); prepareForDrawing(filtout - kernelSize + kernelSizeB, sumposl, fftwl, ibufl, sumshl, .5, .5, .5, 1, 1, fftsizeB, xscale, floor(slider45), kernelSize); ); ); ); cap_mode && cap_timer < 12 ? cap_timer += 1; last_mouse_cap = mouse_cap; UI_SCREEN = 1; // Force updates when mouse activity is registered mouse_cap > 0 ? ( update = 1; ); // only update if new fft data is there or if the size changed ( update == 1 || old_w != gfx_w || old_h!=gfx_h ) ? ( update = 0; noRenderBuffer ? ( gfx_dest = -1; ) : ( gfx_dest = UI_SCREEN; gfx_setimgdim(UI_SCREEN, gfx_w, gfx_h); ); gfx_clear = 0; //gfx_dest = scroll_buf; old_w=gfx_w; old_h=gfx_h; // Clear screen gfx_r=gfx_g=gfx_b=bgcolor -0; gfx_a=1.0; gfx_x=gfx_y=0; gfx_rectto(gfx_w,gfx_h); logdb_to_pixels=(gfx_h - spectrum_yoffset - spectrum_yoffsetbottom)/(-slider2); logf_to_pixels=logdb_to_pixels*20/log(10); scale_offset_db = scale_offset_db_user; displayMode == 1 ? scale_offset_db += 0.5 * slider2; spectral_offset_pixels = scale_offset_db * logdb_to_pixels; latencyLength = fftSize; ( latencyCompensation == 0 ) ? latencyLength = 0; ( pdc_delay != latencyLength ) ? ( pdc_top_ch = num_ch; pdc_delay = latencyLength; ); integrate_sc = 1; slider5 > 0 ? ( integrate_now = time_precise(); integrate_en ? ( // fps = 1/(integrate_now - integrate_lastt); integrate_sc -= exp(-5 * 1000.0 * (integrate_now - integrate_lastt) / slider5); ) : ( // force overwrite of buffer integrate_en = 1; ); integrate_lastt = integrate_now; ) : ( integrate_en = 0; ); fftidx != (slider1|0) ? ( fftidx=slider1|0; fftsize=2^(min(max(fftidx,0),11)+4); integrate_sc=1; ); ((windowsize != fftsize) || (windowtype != (slider4|0))) ? ( windowtype=slider4|0; windowsize=fftsize; dwindowpos = $pi*2/fftsize; i=pwr=0; ipi = 1.0 / $pi; loop(fftsize*.5+1, windowpos=i*dwindowpos; pwr += (window[i] = ( //rectangular,hamming,blackman-harris,blackman,flat-top,gaussian windowtype==0 ? ( 1 ) : windowtype==1 ? ( 0.53836 - cos(windowpos)*0.46164 ) : windowtype==2 ? ( 0.35875 - 0.48829 * cos(windowpos) + 0.14128 * cos(2*windowpos) - 0.01168 * cos(3*windowpos) ) : windowtype==3 ? ( 0.42659 - 0.49656 * cos(windowpos) + 0.076849 * cos(2.0*windowpos) ) : windowtype==4 ? ( 0.21557895 - 0.41663158 * cos(windowpos) + 0.277263158 * cos(2*windowpos) - 0.083578947 * cos(3*windowpos) + 0.006947368 * cos(4*windowpos) ) : windowtype==5 ? ( exp(- 5 * (windowpos * ipi - 1.0) * (windowpos * ipi - 1.0) ) ) ) ); i+=1; ); pwr=.5/(pwr*2-window[i-1]); loop(fftsize*.5+1,window[i-=1]*=pwr); integrate_sc=1; ); !hide_spectrum ? ( displayMode == 0 ? drawSpectra(recpositions, fftworkspaces, integrate_bufs, shifts, histsizes) : displayMode == 1 ? drawDifferenceSpectra(recpositions, fftworkspaces, integrate_bufs, shifts, histsizes); ( zoomMode == 1 ) ? ( gfx_r = gfx_g = gfx_b = gfx_a = 1.0; gfx_line( old_mouse_x, old_mouse_y, mouse_x, old_mouse_y ); gfx_line( old_mouse_x, old_mouse_y, old_mouse_x, mouse_y ); gfx_line( old_mouse_x, mouse_y, mouse_x, mouse_y ); gfx_line( mouse_x, old_mouse_y, mouse_x, mouse_y ); ); ); // Note: slider34 can still be used to detect clicks on the sono gfx_r = gfx_g = gfx_b = 1; gfx_a = 1; sigw = 1;// - spectrum_xpad/gfx_w; // <== Note: If you want the width to keep the bar free, uncomment this! sigh = sono_size/gfx_h; selected = slider28; gfx_x = 0; gfx_y = gfx_h-sono_yoffset_bottom-sono_size; // Freeze recpositions here memcpy(rec_positions_copy, recpositions, maxchannels); sumposl_copy = sumposl; sumposr_copy = sumposr; sync_factor = (sync == 1) ? ( 0.5 ) : ( sync == 2 ) ? ( 1.0 ) : ( sync == 3 ) ? ( 2.0 ) : ( sync == 4 ) ? ( 3.0 ) : ( sync == 5 ) ? ( 4.0 ) : ( sync == 6 ) ? ( 6.0 ); samples_per_beat = pow(2, sync - 2) * (srate / 2) / (tempo / 60); sample_increment = sono_sample - last_sample; last_sample = sono_sample; beat_offset += sample_increment; while(beat_offset > samples_per_beat) ( beat_offset -= samples_per_beat; ); total_offset = beat_offset + offset_x * samples_per_beat; ( slider29 == 2 ) ? ( isActive = activechannels; // Find any active channel to use as a reference point idx = 0; loop(maxchannels, (isActive[idx]) ? reference_chan = idx; idx += 1; ); // Draw all time tracks idx = 0; refpoint = recpositions[reference_chan]; loop(maxchannels, (isActive[]) ? ( ( slider34 == 0 ) ? ( !sync ? ( relative_position = shifts[reference_chan] - recpositions[reference_chan]; /* Forced resync */ cpos = recpositions[idx] + relative_position; cpos = (cpos < shifts[idx]) ? (cpos + histsizes[idx] - shifts[idx]) : cpos; scope.drawMovingSignal(gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, cpos, histsizes[idx], shifts[idx], slider31, histsizes[0] - shifts[0], get_color(idx, 0), get_color(idx, 1), get_color(idx, 2), 1); ) : ( scope.drawSignal_resampled(gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, rec_positions_copy[idx], histsizes[idx], shifts[idx], slider31, samples_per_beat, get_color(idx, 0), get_color(idx, 1), get_color(idx, 2), 1, total_offset); ); ) : ( relative_position = refpoint - recpositions[reference_chan]; /* Forced resync */ scope.drawMovingSignal(gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, recpositions[idx] + relative_position, histsizes[idx], shifts[idx], slider31, histsizes[0] - shifts[0], get_color(idx, 0), get_color(idx, 1), get_color(idx, 2), 1); ); ); isActive += 1; idx += 1; ); ) : ( slider29 == 1 ) ? ( // Time window ( selected > -1 ) ? ( ( slider34 == 0 ) ? ( !sync ? ( scope.drawSignal(gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, shifts[selected], slider31, histsizes[0] - shifts[0], get_color(selected, 0), get_color(selected, 1), get_color(selected, 2), 1); ) : ( scope.drawSignal_resampled(gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, rec_positions_copy[selected], histsizes[selected], shifts[selected], slider31, samples_per_beat, get_color(selected, 0), get_color(selected, 1), get_color(selected, 2), 1, total_offset); ); ) : ( scope.drawMovingSignal(gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, rec_positions_copy[selected], histsizes[selected], shifts[selected], slider31, histsizes[0] - shifts[0], get_color(selected, 0), get_color(selected, 1), get_color(selected, 2), 1); ); gfx_r=gfx_g=gfx_b=1.0-bgColor; gfx_y = gfx_h-sono_yoffset_bottom-sono_size + 5; gfx_x = 5; !micro_view ? gfx_printf( "Ch %d", selected + 1 ); ) : ( ( slider34 == 0 ) ? ( !sync ? ( scope.drawSignal( gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, sumshr, slider31, histsizes[0] - shifts[0], 0.5, 0.5, 0.5, 1); scope.drawSignal( gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, sumshl, slider31, histsizes[0] - shifts[0], 1, 1, 1, 1); ) : ( scope.drawSignal_resampled(gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, sumposl_copy, sumhsl, sumshl, slider31, samples_per_beat, 0.5, 0.5, 0.5, 1, total_offset); scope.drawSignal_resampled(gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, sumposr_copy, sumhsr, sumshr, slider31, samples_per_beat, 1.0, 1.0, 1.0, 1, total_offset); ); ) : ( scope.drawMovingSignal( gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, sumposr, sumhsr, sumshr, slider31, histsizes[0] - shifts[0], 0.5, 0.5, 0.5, 1); scope.drawMovingSignal( gfx_x, gfx_y, sigw*gfx_w, sigh*gfx_h, sumposl, sumhsl, sumshl, slider31, histsizes[0] - shifts[0], 1, 1, 1, 1); ); gfx_r=gfx_g=gfx_b=1.0-bgColor; gfx_y = gfx_h-sono_yoffset_bottom-sono_size + 5; gfx_x = 5; !micro_view ? gfx_printf( "Sum" ); ); ) : ( slider29 == 0 ) ? ( // Sonogram sonogram.setPositionSono(gfx_x, gfx_y, sigw * gfx_w, sigh * gfx_h); cmapidx = (floor(slider32/2) + 1); invert = slider32 - (floor(slider32/2))*2; ( selected > -1 ) ? ( fast_proc ? ( last_sono_sample ? ( sono_step = (sono_sample - last_sono_sample) / 4; ixx = - 4 * sono_step; loop(4, // Make sure that the sonogram is still updated if it's not currently being rendered. processFFT(recpositions[selected] + ixx, fftworkspaces[selected], integrate_bufs[selected], shifts[selected], histsizes[selected], ccolor[0], ccolor[1], ccolor[2], 1, 0); /* TO DO MAKE SONO WORK IN DIFF MODE */ ixx += sono_step; sonogram.updateSono(fftworkspaces[selected], cmapidx * 1000, invert, slider30, slider33, slider35); ); ); last_sono_sample = sono_sample; ) : ( // Make sure that the sonogram is still updated if it's not currently being rendered. (activeChannels[selected] == 0 || hide_spectrum) ? ( processFFT(recpositions[selected], fftworkspaces[selected], integrate_bufs[selected], shifts[selected], histsizes[selected], ccolor[0], ccolor[1], ccolor[2], 1, 0); ); sonogram.updateSono(fftworkspaces[selected], cmapidx * 1000, invert, slider30, slider33, slider35); ); sonogram.drawSono(cmapidx * 1000, invert, slider30, slider33, slider35); gfx_mode = 1; gfx_r = gfx_g = gfx_a = 1.0; gfx_measurestr("30 Hz", __, yhz); gfx_y = gfx_h-sono_yoffset_bottom-sono_size + 1.4 * yhz; gfx_x = 5; // gfx_printf( "Ch: %d, Sc: %d", selected + 1, slider30 ); !micro_view ? gfx_printf(" %d", selected + 1); ) : ( fast_proc ? ( last_sono_sample ? ( sono_step = (sono_sample - last_sono_sample) / 4; ixx = - 4 * sono_step; loop(4, // Make sure that the sonogram is still updated if it's not currently being rendered. processFFT(sumposr + ixx, fftwr, ibufr, sumshr, sumhsr, halfshade, halfshade, halfshade, 0, 0); /* TO DO MAKE SONO WORK IN DIFF MODE */ ixx += sono_step; sonogram.updateSono(fftwr, cmapidx * 1000, invert, slider30, slider33, slider35); ); ); last_sono_sample = sono_sample; ) : ( ( (showSum == 0) || (displayMode == 1) || hide_spectrum ) ? ( // Make sure that the sonogram is still updated if it's not currently being rendered. processFFT(sumposr, fftwr, ibufr, sumshr, sumhsr, halfshade, halfshade, halfshade, 0, 0); processFFT(sumposl, fftwl, ibufl, sumshl, sumhsl, shade, shade, shade, 0, 0); /* TO DO MAKE SONO WORK IN DIFF MODE */ ); sonogram.updateSono(fftwr, cmapidx * 1000, invert, slider30, slider33, slider35 ); ); sonogram.drawSono(cmapidx * 1000, invert, slider30, slider33, slider35); gfx_mode = 0; (!hideUI && !micro_view) ? ( gfx_r = gfx_g = gfx_a = 1.0; gfx_measurestr("30 Hz", __, yhz); gfx_y = gfx_h - sono_yoffset_bottom-sono_size + 1.2 * yhz; gfx_x = 5; // gfx_printf( "Sum, Sc: %d", slider30 ); gfx_printf("Sum"); ); ); (!hideUI && !micro_view) ? ( gfx_measurestr("Sum. Sc: 123456789", junk, tSkip); gfx_y = gfx_h-sono_yoffset_bottom-sono_size + 1.4 * yhz + 1.2 * tSkip; gfx_x = 5; //printColorMapName(cmapidx, invert); ); gfx_mode = 0; ); !hide_spectrum ? drawGrid(); (!hideUI && !micro_view) ? DrawButtons(); updateSpectralBounds(); gfx_r=gfx_g=gfx_b=gfx_a=1.0; !noRenderBuffer ? ( gfx_dest = -1; gfx_x = 0; gfx_y = 0; gfx_blit(UI_SCREEN, 1, 0); ); ( drawHz == 1 && !hide_spectrum ) ? ( gfx_r = gfx_g = gfx_b = 1 - bgColor; gfx_a = 1.0; gfx_x = mouse_x + 10; gfx_y = mouse_y; f = (1/800) * ( exp(mouse_x/wsc)-1 ) * srate + spectrum_xoffset * srate; y = -20 * ( (mouse_y - spectrum_yoffset + spectral_offset_pixels) / logf_to_pixels ) / log(10); micro_view ? gfx_setfont(1, "Arial", 9 * scaling) : gfx_setfont(0); gfx_printf("%dHz %.4gdB", f, y); gfx_x = mouse_x + 10; gfx_y += micro_view ? 9 * scaling : 15; gfx_printf(from_frequency(f)); ); lchar == 13 && gfx_getchar() == 0 ? hideUI = 1 - hideUI; lchar = gfx_getchar(); // Finished update = 1; ); function draw_memory_map() global(update, gfx_x, gfx_y, gfx_w, gfx_h, fftworkspaces, recpositions) local(draw_ptr, on, block, fftw, rpos) ( gfx_set(0, 0, 0, 0); gfx_rect(0, 0, gfx_w, gfx_h); draw_ptr = 0; // Blocks of 128 doubles // One row takes 128 blocks block = 1024; gfx_x = 10; gfx_y = 100; loop(128, gfx_x = 0; loop(128, on = 0; loop(block, on = on || (abs(draw_ptr[]) > 0); draw_ptr += 1; ); gfx_set(1, 1, 1, on ? 1 : .2); gfx_rect(gfx_x, gfx_y, 4, 4); gfx_x += 5; ); gfx_y += 5; ); gfx_x = 0; rpos = recpositions; fftw = fftworkspaces; gfx_set(1, 1, 1, 1); gfx_y = 100; loop(32, gfx_x = 700; gfx_printf("%d (%f) r: %d\n", fftw[], fftw[] / 65536, rpos[]); fftw += 1; rpos += 1; ); ); memory_debugging ? draw_memory_map(); /* gfx_set(1, 1, 1, 1); gfx_y = 100; ix = 0; loop(16, gfx_x = 700; gfx_printf("%d\n", ch_endpoints[ix]); ix += 1; ); */