11-- @description Perfect Timing! - Audio Quantizer
22-- @author 80icio
3- -- @version 0.40
3+ -- @version 0.41
44-- @changelog
5- -- - Improved transient detection with more accurate peak and RMS measurements,
6- -- DC offset correction, and smarter retrigger behavior
7- -- - Major speed improvements for filters (lowcut, hicut, transient, gain) -
8- -- up to 2x faster processing
9- -- - Fixed incorrect grid drawing in the internal visualizer
5+ -- - Improved Visualizer performance when zoomed out on long waveforms
6+ -- - Fixed additional cases of incorrect grid drawing in the Visualizer
7+ -- - Simplified gridscan logic from "choose closest and most powerful transient" to "choose closest transient"
108-- @link Forum thread https://forum.cockos.com/showthread.php?t=288964
119-- @about
1210-- # PERFECT TIMING!
@@ -1453,7 +1451,7 @@ local output ={}
14531451
14541452 for i = 1 , h do
14551453 self .grid_diff_temp = {}
1456- self .rms_battle = {}
1454+ -- self.rms_battle = {}
14571455 local idtotal = {}
14581456 if IsEven (i )== false then
14591457 for c = 1 , # input , 2 do
@@ -1462,14 +1460,15 @@ local output ={}
14621460
14631461 if diff <= grid_dist then
14641462 self .grid_diff_temp [# self .grid_diff_temp + 1 ] = diff
1465- self .rms_battle [# self .rms_battle + 1 ] = input [c + 1 ][1 ]
1463+ -- self.rms_battle[#self.rms_battle+1] = input[c+1][1]
14661464 idtotal [# idtotal + 1 ] = c
14671465 end
14681466 end
14691467 end
14701468
1471- id = getHighest (self .rms_battle )
1472-
1469+ -- id = getHighest(self.rms_battle)
1470+ id = getLowest (self .grid_diff_temp )
1471+
14731472 if idtotal [id ] then
14741473 output [# output + 1 ] = input [idtotal [id ]]
14751474 output [# output + 1 ] = input [(idtotal [id ])+ 1 ]
@@ -1529,7 +1528,7 @@ function Create_Grid_table()
15291528
15301529 local blocklineQN_check = abs (blocklineQN - floor (blocklineQN ))
15311530
1532- if blocklineQN_check < 1e-13 or blocklineQN_check > 1 - 1e-13 then
1531+ if blocklineQN_check < 1e-10 or blocklineQN_check > 1 - 1e-10 then
15331532 Grid_blocks_Ruler_thickness [h ] = 2
15341533 else
15351534 Grid_blocks_Ruler_thickness [h ] = 1
@@ -2664,11 +2663,12 @@ function thresh_histogram() ---------- draw Threshold PEAK Histogram
26642663end
26652664local LRarrow = 0
26662665function waveform_visualizer ()
2667-
2666+
2667+ local total_samples = # Wave .out_buf
26682668 local w = m_window_width - ImGui .StyleVar_CellPadding - 2
26692669 local y_pos = 0
26702670 local y_neg = 0
2671- local max_zoom_h = floor (# Wave . out_buf / (m_window_width * 2 ))
2671+ local max_zoom_h = floor (total_samples / (m_window_width * 2 ))
26722672
26732673 local i_array = 1
26742674
@@ -2702,105 +2702,124 @@ function waveform_visualizer()
27022702
27032703 local mouse_wheel_v , mouse_wheel_h = ImGui .GetMouseWheel ( ctx )
27042704
2705- if ImGui .IsMouseClicked ( ctx , 0 ) or mouse_wheel_v ~= 0 or mouse_wheel_h ~= 0 then ---- ---- zoom when click left
2706- new_zoom_pos_range = (1 / waveform_zoom_h )
2707- new_zoom_pos_start = (startsample /# Wave .out_buf )
2708- local x_mouse , _ = r .GetMousePosition (ctx )
2709- x_mouse = x_mouse - histo_x
2710- x_mouse = x_mouse / histo_w
2711- if x_mouse > 1 then x_mouse = 1 end
2712- if x_mouse < 0 then x_mouse = 0 end
2713- local x_mouse_rel = (x_mouse * new_zoom_pos_range ) + new_zoom_pos_start
2714- h_zoom_center = x_mouse_rel
2715- h_zoom_absolute_center = x_mouse
2716- samplesdifference = h_zoom_center - h_zoom_absolute_center
2717- end
2718-
2719-
2720- if ImGui .IsMouseDragging ( ctx , 1 ) then ---- --right click dragging
2721- -- ImGui.SetMouseCursor( ctx, ImGui.MouseCursor_Hand )
2722- local x_delta_rc , _ = ImGui .GetMouseDelta ( ctx )
2723- h_zoom_center = h_zoom_center - x_delta_rc / w / waveform_zoom_h
2724-
2725- right_click_dragging = true
2726- else
2727- right_click_dragging = false
2728- end
2729-
2730- if h_zoom_center > 1 then h_zoom_center = 1 end
2731- if h_zoom_center < 0 then h_zoom_center = 0 end
2705+ if ImGui .IsMouseClicked (ctx , 0 ) or mouse_wheel_v ~= 0 or mouse_wheel_h ~= 0 then ---- ---- zoom when click left and drag down
2706+ new_zoom_pos_range = 1 / waveform_zoom_h
2707+ new_zoom_pos_start = startsample / total_samples
2708+
2709+ local x_mouse = r .GetMousePosition (ctx ) - histo_x
2710+ x_mouse = x_mouse / histo_w
2711+
2712+ if x_mouse > 1 then x_mouse = 1 end
2713+ if x_mouse < 0 then x_mouse = 0 end
2714+
2715+ local x_mouse_rel = (x_mouse * new_zoom_pos_range ) + new_zoom_pos_start
2716+ h_zoom_center = x_mouse_rel
2717+ h_zoom_absolute_center = x_mouse
2718+ samplesdifference = x_mouse_rel - x_mouse
2719+ end
27322720
27332721
2734- if ImGui .IsMouseDragging ( ctx , 0 ) or mouse_wheel_v ~= 0 or mouse_wheel_h ~= 0 then ---- ---------------get horizontal zoom value
2735- h_zoom_dragging = true
2736- local x_delta , y_delta = ImGui .GetMouseDelta ( ctx )
2737- mouse_wheel_h = (mouse_wheel_h ^ 3 )*- 1
2738- mouse_wheel_h = min (mouse_wheel_h ,600 )
2739- mouse_wheel_h = max (mouse_wheel_h ,- 600 )
2740-
2741- local zoom_factor_y = (y_delta / 10 ) / histo_h
2742- local zoom_factor_wheel = mouse_wheel_v / histo_h
2743- waveform_zoom_h = waveform_zoom_h + (zoom_factor_y + zoom_factor_wheel ) * (max_zoom_h / 2 )
2744- -- waveform_zoom_h = waveform_zoom_h^2/2
2745- -- waveform_zoom_h = waveform_zoom_h + (y_delta/histo_h)*(max_zoom_h/2) + (mouse_wheel_v/histo_h)*(max_zoom_h/2)
2746- moving_h = floor (((x_delta ^ 3 )/ waveform_zoom_h ) + (mouse_wheel_h * 100 / waveform_zoom_h )) + moving_h
2747-
2748- if waveform_zoom_h > max_zoom_h then waveform_zoom_h = max_zoom_h end
2749- if waveform_zoom_h < min_visualzer_rangeview then waveform_zoom_h = min_visualzer_rangeview end
2750- else
2751- h_zoom_dragging = false
2752- moving_h = 0
2753- end
2722+ if ImGui .IsMouseDragging (ctx , 0 ) or mouse_wheel_v ~= 0 or mouse_wheel_h ~= 0 then
2723+ h_zoom_dragging = true
2724+ local x_delta , y_delta = ImGui .GetMouseDelta (ctx )
2725+
2726+ -- Process horizontal wheel (cube, negate, clamp)
2727+ mouse_wheel_h = mouse_wheel_h * mouse_wheel_h * mouse_wheel_h * - 1
2728+ if mouse_wheel_h > 600 then mouse_wheel_h = 600 end
2729+ if mouse_wheel_h < - 600 then mouse_wheel_h = - 600 end
2730+
2731+ -- Cache inverse values
2732+ local inv_histo_h = 1 / histo_h
2733+ local inv_zoom_h = 1 / waveform_zoom_h
2734+
2735+
2736+ local delta_scaling = 0.01 * (total_samples / zoomedsamples )^ 0.5
2737+
2738+ -- Calculate zoom
2739+ local zoom_factor_y = (y_delta * delta_scaling ) * inv_histo_h
2740+ local zoom_factor_wheel = mouse_wheel_v * delta_scaling * inv_histo_h
2741+ waveform_zoom_h = waveform_zoom_h + (zoom_factor_y + zoom_factor_wheel ) * (max_zoom_h * 0.5 )
2742+
2743+ -- Calculate movement
2744+ local x_cubed = x_delta * x_delta * x_delta
2745+ moving_h = floor ((x_cubed * inv_zoom_h ) + (mouse_wheel_h * 100 * inv_zoom_h )) + moving_h
2746+
2747+ -- Clamp zoom
2748+ if waveform_zoom_h > max_zoom_h then waveform_zoom_h = max_zoom_h end
2749+ if waveform_zoom_h < min_visualzer_rangeview then waveform_zoom_h = min_visualzer_rangeview end
2750+ else
2751+ h_zoom_dragging = false
2752+ moving_h = 0
2753+ end
27542754
27552755
27562756 else
27572757 ImGui .SetMouseCursor ( ctx , ImGui .MouseCursor_Arrow )
27582758 end
2759-
2759+
27602760 if w_check ~= w or cyclecount == 1 or h_zoom_dragging or LRarrow ~= 0 or right_click_dragging then --- or v_zoom_dragging then
27612761 line_array_pos = {}
27622762 line_array_neg = {}
27632763
2764- zoomedsamples = floor (# Wave . out_buf / waveform_zoom_h )
2764+ zoomedsamples = floor (total_samples / waveform_zoom_h )
27652765
2766- startsample = floor (# Wave . out_buf * ((1 - (1 / waveform_zoom_h ))* h_zoom_center + (samplesdifference / waveform_zoom_h )))
2766+ startsample = floor (total_samples * ((1 - (1 / waveform_zoom_h ))* h_zoom_center + (samplesdifference / waveform_zoom_h )))
27672767 startsample = startsample + moving_h
27682768
27692769 if startsample < 0 then startsample = 0 end
27702770
27712771 local endsample = zoomedsamples + startsample
27722772
2773- if endsample ># Wave . out_buf then
2774- endsample =# Wave . out_buf ; startsample = # Wave . out_buf - zoomedsamples
2773+ if endsample > total_samples then
2774+ endsample = total_samples ; startsample = total_samples - zoomedsamples
27752775 end
27762776
27772777 local w_zoom = (w )/ (zoomedsamples )
2778+
2779+ local sample_count = endsample - startsample
2780+ local threshold = 5000000 -- adjust this based on testing
27782781
2779- for i = 1 + startsample , endsample do
2780- local x_poly = floor (i * w_zoom )
2781- local x_poly_next = floor ((i + 1 )* w_zoom )
2782-
2783- if x_poly == x_poly_next then
2784-
2785- if Wave .out_buf [i ]>= (y_pos ) then
2786- y_pos = Wave .out_buf [i ]
2787- end
2788- if Wave .out_buf [i ]<= (y_neg ) then
2789- y_neg = Wave .out_buf [i ]
2790- end
2791-
2792- else
2793-
2794- line_array_pos [i_array ] = y_pos
2795-
2796- line_array_neg [i_array ] = y_neg
2797-
2798- y_pos = 0
2799- y_neg = 0
2800- i_array = i_array + 1
2782+ if sample_count < threshold then
2783+ -- DETAILED MODE: Your current precise function
2784+ local x_poly = floor (startsample * w_zoom )
2785+ for i = 1 + startsample , endsample do
2786+ local x_poly_next = floor ((i + 1 )* w_zoom )
2787+ local val = Wave .out_buf [i ]
28012788
2789+ if x_poly == x_poly_next then
2790+ if val > y_pos then y_pos = val end
2791+ if val < y_neg then y_neg = val end
2792+ else
2793+ line_array_pos [i_array ] = y_pos
2794+ line_array_neg [i_array ] = y_neg
2795+ i_array = i_array + 1
2796+ y_pos , y_neg = 0 , 0
2797+ x_poly = x_poly_next
2798+ end
28022799 end
2803- end
2800+
2801+ else
2802+ -- FAST MODE: Same logic as detailed mode but with stride
2803+ local stride = max (10 , floor (sample_count / 100000 )) -- adjust divisor for speed vs quality
2804+
2805+ local x_poly = floor (startsample * w_zoom )
2806+ for i = 1 + startsample , endsample , stride do
2807+ local x_poly_next = floor ((i + 1 )* w_zoom )
2808+ local val = Wave .out_buf [i ]
2809+
2810+ if x_poly == x_poly_next then
2811+ if val > y_pos then y_pos = val end
2812+ if val < y_neg then y_neg = val end
2813+ else
2814+ line_array_pos [i_array ] = y_pos
2815+ line_array_neg [i_array ] = y_neg
2816+ i_array = i_array + 1
2817+ y_pos , y_neg = 0 , 0
2818+ x_poly = x_poly_next
2819+ end
2820+ end
2821+ end
2822+
28042823 end
28052824
28062825 w_check = w
0 commit comments