Skip to content

Commit 2a7db60

Browse files
src3453Copilotspessasus
authored
Improved triggering with multi pass trigger point detection (#206)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: spessasus <spesekspesek@gmail.com>
1 parent 4985433 commit 2a7db60

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "SpessaSynth",
3-
"version": "4.2.0",
3+
"version": "4.2.1",
44
"type": "module",
55
"private": true,
66
"scripts": {

src/website/changelog.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ export const WHATS_NEW: string[] = [
1111
`Delay effect!`,
1212
`Insertion effects!`,
1313
`Overhauled synthesizer controller!`,
14+
`Better waveform stabilization! (by src3453)`,
1415
`Bug fixes!`
1516
] as const;

src/website/js/renderer/render_waveforms.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)