Safer fold and crush section
This commit is contained in:
@ -45,6 +45,7 @@ export class AudioPlayer {
|
||||
this.dispose()
|
||||
|
||||
this.audioContext = new AudioContext({ sampleRate: this.sampleRate })
|
||||
this.workletRegistered = false
|
||||
await this.registerWorklet(this.audioContext)
|
||||
|
||||
this.effectsChain = new EffectsChain(this.audioContext)
|
||||
@ -176,5 +177,6 @@ export class AudioPlayer {
|
||||
this.audioContext.close()
|
||||
this.audioContext = null
|
||||
}
|
||||
this.workletRegistered = false
|
||||
}
|
||||
}
|
||||
@ -72,12 +72,12 @@ export class BitcrushEffect implements Effect {
|
||||
}
|
||||
}
|
||||
|
||||
updateParams(values: Record<string, number>): void {
|
||||
if (values.bitcrushDepth !== undefined) {
|
||||
updateParams(values: Record<string, number | string>): void {
|
||||
if (values.bitcrushDepth !== undefined && typeof values.bitcrushDepth === 'number') {
|
||||
this.bitDepth = values.bitcrushDepth
|
||||
}
|
||||
|
||||
if (values.bitcrushRate !== undefined) {
|
||||
if (values.bitcrushRate !== undefined && typeof values.bitcrushRate === 'number') {
|
||||
this.crushAmount = values.bitcrushRate
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,8 +92,8 @@ export class DelayEffect implements Effect {
|
||||
}
|
||||
}
|
||||
|
||||
updateParams(values: Record<string, number>): void {
|
||||
if (values.delayTime !== undefined) {
|
||||
updateParams(values: Record<string, number | string>): void {
|
||||
if (values.delayTime !== undefined && typeof values.delayTime === 'number') {
|
||||
const time = values.delayTime / 1000
|
||||
this.delayNode.delayTime.setTargetAtTime(
|
||||
time,
|
||||
@ -102,7 +102,7 @@ export class DelayEffect implements Effect {
|
||||
)
|
||||
}
|
||||
|
||||
if (values.delayFeedback !== undefined) {
|
||||
if (values.delayFeedback !== undefined && typeof values.delayFeedback === 'number') {
|
||||
const feedback = values.delayFeedback / 100
|
||||
this.feedbackNode.gain.setTargetAtTime(
|
||||
feedback * 0.95,
|
||||
@ -111,7 +111,7 @@ export class DelayEffect implements Effect {
|
||||
)
|
||||
}
|
||||
|
||||
if (values.delayWetDry !== undefined) {
|
||||
if (values.delayWetDry !== undefined && typeof values.delayWetDry === 'number') {
|
||||
const wet = values.delayWetDry / 100
|
||||
this.currentWetValue = wet
|
||||
this.currentDryValue = 1 - wet
|
||||
@ -130,7 +130,7 @@ export class DelayEffect implements Effect {
|
||||
}
|
||||
}
|
||||
|
||||
if (values.delayTone !== undefined) {
|
||||
if (values.delayTone !== undefined && typeof values.delayTone === 'number') {
|
||||
const tone = values.delayTone / 100
|
||||
const freq = 200 + tone * 7800
|
||||
this.filterNode.frequency.setTargetAtTime(
|
||||
@ -140,12 +140,12 @@ export class DelayEffect implements Effect {
|
||||
)
|
||||
}
|
||||
|
||||
if (values.delaySaturation !== undefined) {
|
||||
if (values.delaySaturation !== undefined && typeof values.delaySaturation === 'number') {
|
||||
const saturation = values.delaySaturation / 100
|
||||
this.createSaturationCurve(saturation)
|
||||
}
|
||||
|
||||
if (values.delayFlutter !== undefined) {
|
||||
if (values.delayFlutter !== undefined && typeof values.delayFlutter === 'number') {
|
||||
const flutter = values.delayFlutter / 100
|
||||
const baseDelay = this.delayNode.delayTime.value
|
||||
const modDepth = baseDelay * flutter * 0.1
|
||||
|
||||
@ -2,7 +2,7 @@ export interface Effect {
|
||||
readonly id: string
|
||||
getInputNode(): AudioNode
|
||||
getOutputNode(): AudioNode
|
||||
updateParams(values: Record<string, number>): void
|
||||
updateParams(values: Record<string, number | string>): void
|
||||
setBypass(bypass: boolean): void
|
||||
dispose(): void
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ export class EffectsChain {
|
||||
this.masterGainNode.connect(this.outputNode)
|
||||
}
|
||||
|
||||
updateEffects(values: Record<string, number | boolean>): void {
|
||||
updateEffects(values: Record<string, number | boolean | string>): void {
|
||||
for (const effect of this.effects) {
|
||||
const effectId = effect.id
|
||||
const bypassKey = `${effectId}Bypass`
|
||||
@ -53,13 +53,13 @@ export class EffectsChain {
|
||||
effect.setBypass(Boolean(values[bypassKey]))
|
||||
}
|
||||
|
||||
const numericValues: Record<string, number> = {}
|
||||
const effectValues: Record<string, number | string> = {}
|
||||
for (const [key, value] of Object.entries(values)) {
|
||||
if (typeof value === 'number') {
|
||||
numericValues[key] = value
|
||||
if (typeof value === 'number' || typeof value === 'string') {
|
||||
effectValues[key] = value
|
||||
}
|
||||
}
|
||||
effect.updateParams(numericValues)
|
||||
effect.updateParams(effectValues)
|
||||
}
|
||||
|
||||
if (values.masterVolume !== undefined) {
|
||||
|
||||
@ -72,13 +72,13 @@ export class FilterEffect implements Effect {
|
||||
}
|
||||
}
|
||||
|
||||
updateParams(values: Record<string, number>): void {
|
||||
updateParams(values: Record<string, number | string>): void {
|
||||
if (values.hpEnable !== undefined) {
|
||||
this.hpEnabled = values.hpEnable === 1
|
||||
this.updateBypassState()
|
||||
}
|
||||
|
||||
if (values.hpFreq !== undefined) {
|
||||
if (values.hpFreq !== undefined && typeof values.hpFreq === 'number') {
|
||||
this.hpFilter.frequency.cancelScheduledValues(this.audioContext.currentTime)
|
||||
this.hpFilter.frequency.setValueAtTime(
|
||||
this.hpFilter.frequency.value,
|
||||
@ -90,7 +90,7 @@ export class FilterEffect implements Effect {
|
||||
)
|
||||
}
|
||||
|
||||
if (values.hpRes !== undefined) {
|
||||
if (values.hpRes !== undefined && typeof values.hpRes === 'number') {
|
||||
this.hpFilter.Q.cancelScheduledValues(this.audioContext.currentTime)
|
||||
this.hpFilter.Q.setValueAtTime(
|
||||
this.hpFilter.Q.value,
|
||||
@ -107,7 +107,7 @@ export class FilterEffect implements Effect {
|
||||
this.updateBypassState()
|
||||
}
|
||||
|
||||
if (values.lpFreq !== undefined) {
|
||||
if (values.lpFreq !== undefined && typeof values.lpFreq === 'number') {
|
||||
this.lpFilter.frequency.cancelScheduledValues(this.audioContext.currentTime)
|
||||
this.lpFilter.frequency.setValueAtTime(
|
||||
this.lpFilter.frequency.value,
|
||||
@ -119,7 +119,7 @@ export class FilterEffect implements Effect {
|
||||
)
|
||||
}
|
||||
|
||||
if (values.lpRes !== undefined) {
|
||||
if (values.lpRes !== undefined && typeof values.lpRes === 'number') {
|
||||
this.lpFilter.Q.cancelScheduledValues(this.audioContext.currentTime)
|
||||
this.lpFilter.Q.setValueAtTime(
|
||||
this.lpFilter.Q.value,
|
||||
@ -136,7 +136,7 @@ export class FilterEffect implements Effect {
|
||||
this.updateBypassState()
|
||||
}
|
||||
|
||||
if (values.bpFreq !== undefined) {
|
||||
if (values.bpFreq !== undefined && typeof values.bpFreq === 'number') {
|
||||
this.bpFilter.frequency.cancelScheduledValues(this.audioContext.currentTime)
|
||||
this.bpFilter.frequency.setValueAtTime(
|
||||
this.bpFilter.frequency.value,
|
||||
@ -148,7 +148,7 @@ export class FilterEffect implements Effect {
|
||||
)
|
||||
}
|
||||
|
||||
if (values.bpRes !== undefined) {
|
||||
if (values.bpRes !== undefined && typeof values.bpRes === 'number') {
|
||||
this.bpFilter.Q.cancelScheduledValues(this.audioContext.currentTime)
|
||||
this.bpFilter.Q.setValueAtTime(
|
||||
this.bpFilter.Q.value,
|
||||
|
||||
@ -15,8 +15,8 @@ export class FoldCrushEffect implements Effect {
|
||||
this.wetNode = audioContext.createGain()
|
||||
this.dryNode = audioContext.createGain()
|
||||
|
||||
this.wetNode.gain.value = 1
|
||||
this.dryNode.gain.value = 0
|
||||
this.wetNode.gain.value = 0
|
||||
this.dryNode.gain.value = 1
|
||||
|
||||
this.inputNode.connect(this.dryNode)
|
||||
this.dryNode.connect(this.outputNode)
|
||||
@ -51,13 +51,11 @@ export class FoldCrushEffect implements Effect {
|
||||
}
|
||||
}
|
||||
|
||||
updateParams(values: Record<string, number>): void {
|
||||
updateParams(values: Record<string, number | string>): void {
|
||||
if (!this.processorNode) return
|
||||
|
||||
if (values.clipMode !== undefined) {
|
||||
const modeIndex = values.clipMode
|
||||
const clipMode = ['wrap', 'clamp', 'fold'][modeIndex] || 'wrap'
|
||||
this.processorNode.port.postMessage({ type: 'clipMode', value: clipMode })
|
||||
this.processorNode.port.postMessage({ type: 'clipMode', value: values.clipMode })
|
||||
}
|
||||
if (values.wavefolderDrive !== undefined) {
|
||||
this.processorNode.port.postMessage({ type: 'drive', value: values.wavefolderDrive })
|
||||
|
||||
@ -21,7 +21,7 @@ export class PassThroughEffect implements Effect {
|
||||
setBypass(_bypass: boolean): void {
|
||||
}
|
||||
|
||||
updateParams(_values: Record<string, number>): void {
|
||||
updateParams(_values: Record<string, number | string>): void {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@ -153,20 +153,20 @@ export class ReverbEffect implements Effect {
|
||||
}
|
||||
}
|
||||
|
||||
updateParams(values: Record<string, number>): void {
|
||||
updateParams(values: Record<string, number | string>): void {
|
||||
let needsRegeneration = false
|
||||
|
||||
if (values.reverbDecay !== undefined && values.reverbDecay !== this.currentDecay) {
|
||||
if (values.reverbDecay !== undefined && typeof values.reverbDecay === 'number' && values.reverbDecay !== this.currentDecay) {
|
||||
this.currentDecay = values.reverbDecay
|
||||
needsRegeneration = true
|
||||
}
|
||||
|
||||
if (values.reverbDamping !== undefined && values.reverbDamping !== this.currentDamping) {
|
||||
if (values.reverbDamping !== undefined && typeof values.reverbDamping === 'number' && values.reverbDamping !== this.currentDamping) {
|
||||
this.currentDamping = values.reverbDamping
|
||||
needsRegeneration = true
|
||||
}
|
||||
|
||||
if (values.reverbWetDry !== undefined) {
|
||||
if (values.reverbWetDry !== undefined && typeof values.reverbWetDry === 'number') {
|
||||
const wet = values.reverbWetDry / 100
|
||||
this.currentWetValue = wet
|
||||
this.currentDryValue = 1 - wet
|
||||
@ -177,7 +177,7 @@ export class ReverbEffect implements Effect {
|
||||
}
|
||||
}
|
||||
|
||||
if (values.reverbPanRate !== undefined) {
|
||||
if (values.reverbPanRate !== undefined && typeof values.reverbPanRate === 'number') {
|
||||
const rate = values.reverbPanRate
|
||||
this.panLfoNode.frequency.setTargetAtTime(
|
||||
rate,
|
||||
@ -186,7 +186,7 @@ export class ReverbEffect implements Effect {
|
||||
)
|
||||
}
|
||||
|
||||
if (values.reverbPanWidth !== undefined) {
|
||||
if (values.reverbPanWidth !== undefined && typeof values.reverbPanWidth === 'number') {
|
||||
const width = values.reverbPanWidth / 100
|
||||
this.panLfoGainNode.gain.setTargetAtTime(
|
||||
width,
|
||||
|
||||
@ -96,12 +96,11 @@ export class WavefolderEffect implements Effect {
|
||||
}
|
||||
}
|
||||
|
||||
updateParams(values: Record<string, number>): void {
|
||||
if (values.clipMode !== undefined) {
|
||||
const modeIndex = values.clipMode
|
||||
this.mode = ['wrap', 'clamp', 'fold'][modeIndex] as ClipMode || 'wrap'
|
||||
updateParams(values: Record<string, number | string>): void {
|
||||
if (values.clipMode !== undefined && typeof values.clipMode === 'string') {
|
||||
this.mode = values.clipMode as ClipMode
|
||||
}
|
||||
if (values.wavefolderDrive !== undefined) {
|
||||
if (values.wavefolderDrive !== undefined && typeof values.wavefolderDrive === 'number') {
|
||||
this.drive = values.wavefolderDrive
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user