Quite a big update

This commit is contained in:
2025-10-13 17:35:47 +02:00
parent fb92c3ae2a
commit b700c68b4d
12 changed files with 1366 additions and 5 deletions

View File

@ -45,11 +45,17 @@ export abstract class CsoundEngine<T = any> implements SynthEngine<T> {
await csound.terminateInstance();
const leftChannel = new Float32Array(audioBuffer.leftChannel);
const rightChannel = new Float32Array(audioBuffer.rightChannel);
let leftChannel = new Float32Array(audioBuffer.leftChannel);
let rightChannel = new Float32Array(audioBuffer.rightChannel);
this.removeDCOffset(leftChannel, rightChannel);
const trimmed = this.trimToZeroCrossing(leftChannel, rightChannel, sampleRate);
leftChannel = trimmed.left;
rightChannel = trimmed.right;
// Apply short fade-in to prevent click at start
this.applyFadeIn(leftChannel, rightChannel, sampleRate);
this.applyFadeOut(leftChannel, rightChannel, sampleRate);
const peak = this.findPeak(leftChannel, rightChannel);
if (peak > 0.001) {
@ -218,22 +224,95 @@ e
}
}
private removeDCOffset(leftChannel: Float32Array, rightChannel: Float32Array): void {
let leftSum = 0;
let rightSum = 0;
const length = leftChannel.length;
for (let i = 0; i < length; i++) {
leftSum += leftChannel[i];
rightSum += rightChannel[i];
}
const leftDC = leftSum / length;
const rightDC = rightSum / length;
for (let i = 0; i < length; i++) {
leftChannel[i] -= leftDC;
rightChannel[i] -= rightDC;
}
}
private trimToZeroCrossing(
leftChannel: Float32Array,
rightChannel: Float32Array,
sampleRate: number
): { left: Float32Array; right: Float32Array } {
const maxSearchSamples = Math.min(Math.floor(sampleRate * 0.01), leftChannel.length);
let trimIndex = 0;
for (let i = 1; i < maxSearchSamples; i++) {
const prevL = leftChannel[i - 1];
const currL = leftChannel[i];
const prevR = rightChannel[i - 1];
const currR = rightChannel[i];
if (
(prevL <= 0 && currL >= 0) || (prevL >= 0 && currL <= 0) ||
(prevR <= 0 && currR >= 0) || (prevR >= 0 && currR <= 0)
) {
trimIndex = i;
break;
}
}
if (trimIndex > 0) {
const newLeft = new Float32Array(leftChannel.length - trimIndex);
const newRight = new Float32Array(rightChannel.length - trimIndex);
newLeft.set(leftChannel.subarray(trimIndex));
newRight.set(rightChannel.subarray(trimIndex));
return { left: newLeft, right: newRight };
}
return { left: leftChannel, right: rightChannel };
}
private applyFadeIn(
leftChannel: Float32Array,
rightChannel: Float32Array,
sampleRate: number
): void {
const fadeInMs = 5; // 5ms fade-in to prevent clicks
const fadeInMs = 5;
const fadeSamples = Math.floor((fadeInMs / 1000) * sampleRate);
const actualFadeSamples = Math.min(fadeSamples, leftChannel.length);
for (let i = 0; i < actualFadeSamples; i++) {
const gain = i / actualFadeSamples;
const phase = i / actualFadeSamples;
const gain = 0.5 - 0.5 * Math.cos(phase * Math.PI);
leftChannel[i] *= gain;
rightChannel[i] *= gain;
}
}
private applyFadeOut(
leftChannel: Float32Array,
rightChannel: Float32Array,
sampleRate: number
): void {
const fadeOutMs = 5;
const fadeSamples = Math.floor((fadeOutMs / 1000) * sampleRate);
const actualFadeSamples = Math.min(fadeSamples, leftChannel.length);
const startSample = leftChannel.length - actualFadeSamples;
for (let i = 0; i < actualFadeSamples; i++) {
const sampleIndex = startSample + i;
const phase = i / actualFadeSamples;
const gain = 0.5 + 0.5 * Math.cos(phase * Math.PI);
leftChannel[sampleIndex] *= gain;
rightChannel[sampleIndex] *= gain;
}
}
protected randomRange(min: number, max: number): number {
return min + Math.random() * (max - min);
}