@@ -73,8 +73,40 @@ export function renderSingleWaveform(
7373 }
7474 const halfLength = Math . floor ( length / 2 ) ;
7575 triggerPoint = waveform . length - halfLength ;
76- for ( let i = triggerPoint ; i >= 1 ; i -- ) {
77- if ( waveform [ i - 1 ] < 0 && waveform [ i ] >= 0 ) {
76+ let max = - Infinity ;
77+ // Multi-pass trigger point detection
78+ // Pass 1: find the maximum in the last part of the waveform
79+ // TODO: optimize by using max function on a subarray when available
80+ const searchStart = Math . max ( 0 , triggerPoint - halfLength ) ;
81+ let bestIndex ;
82+ for ( let i = triggerPoint ; i >= searchStart ; i -- ) {
83+ const value = waveform [ i ] ;
84+ if ( value > max ) {
85+ max = value ;
86+ bestIndex = i ;
87+ }
88+ }
89+ // Pass 2: find the maximum within a tolerance range around the first trigger point
90+ bestIndex = triggerPoint ;
91+ triggerPoint = waveform . length - halfLength ;
92+ const maximumTolerance = 0.04 ; // 4% tolerance for the second pass
93+ for ( let i = triggerPoint ; i >= searchStart ; i -- ) {
94+ const value = waveform [ i ] ;
95+ if ( value > max * ( 1 - maximumTolerance ) ) {
96+ bestIndex = i ;
97+ break ;
98+ }
99+ }
100+ triggerPoint = bestIndex ;
101+ // Pass 3: find the zero crossing after the trigger point
102+ const zeroCrossEnd = Math . max ( triggerPoint - Math . floor ( halfLength ) , 0 ) ;
103+ const waveformAverage =
104+ waveform . reduce ( ( sum , v ) => sum + v , 0 ) / waveform . length ;
105+ // Look for the average to remove DC offset
106+ for ( let i = triggerPoint ; i >= zeroCrossEnd ; i -- ) {
107+ // Reverse search for zero crossing
108+ if ( waveform [ i ] <= waveformAverage ) {
109+ // Zero crossing detected
78110 triggerPoint = i ;
79111 break ;
80112 }
0 commit comments