From b66e1a230e0463bbaddcfdefb3d75b900b73bf2b Mon Sep 17 00:00:00 2001 From: miloszwielgus Date: Thu, 30 Oct 2025 14:15:50 +0100 Subject: [PATCH] fix: clamping aligned with spec, nits --- packages/audiodocs/docs/core/audio-param.mdx | 14 ++++----- .../src/core/AudioParam.ts | 29 ++++++++++++------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/packages/audiodocs/docs/core/audio-param.mdx b/packages/audiodocs/docs/core/audio-param.mdx index eb78844ac..93f476a25 100644 --- a/packages/audiodocs/docs/core/audio-param.mdx +++ b/packages/audiodocs/docs/core/audio-param.mdx @@ -41,7 +41,7 @@ as they are more efficient for continuous changes. For more specific use cases, | Parameter | Type | Description | | :---: | :---: | :---- | | `value` | `number` | A float representing the value the `AudioParam` will be set at given time | -| `startTime` | `number` | The time, in seconds, at which the change in value is going to happen. | +| `startTime` | `number` | The time, in seconds, at which the change in value is going to happen. If it's smaller than [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties), it will be clamped to [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties). | #### Errors: @@ -61,7 +61,7 @@ The change begins at the time designated for the previous event. It follows a li | Parameter | Type | Description | | :---: | :---: | :---- | | `value` | `number` | A float representing the value, the `AudioParam` will ramp to by given time. | -| `endTime` | `number` | The time, in seconds, at which the value ramp will end. | +| `endTime` | `number` | The time, in seconds, at which the value ramp will end. If it's smaller than [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties), it will be clamped to [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties). | #### Errors @@ -81,7 +81,7 @@ The change begins at the time designated for the previous event. It follows an e | Parameter | Type | Description | | :---: | :---: | :---- | | `value` | `number` | A float representing the value the `AudioParam` will ramp to by given time. | -| `endTime` | `number` | The time, in seconds, at which the value ramp will end. | +| `endTime` | `number` | The time, in seconds, at which the value ramp will end. If it's smaller than [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties), it will be clamped to [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties).| #### Errors @@ -101,7 +101,7 @@ This method is useful for decay or release portions of [ADSR envelopes](/docs/ef | Parameter | Type | Description | | :---: | :---: | :---- | | `target` | `number` | A float representing the value to which the `AudioParam` will start transitioning. | -| `startTime` | `number` | The time, in seconds, at which exponential transition will begin. | +| `startTime` | `number` | The time, in seconds, at which exponential transition will begin. If it's smaller than [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties), it will be clamped to [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties). | | `timeConstant` | `number` | A double representing the time-constant value of an exponential approach to the `target`. | #### Errors @@ -122,7 +122,7 @@ Schedules the parameters's value change following a curve defined by given array | Parameter | Type | Description | | :---: | :---: | :---- | | `values` | `Float32Array` | The array of values defining a curve, which change will follow. | -| `startTime` | `number` | The time, in seconds, at which change will begin. | +| `startTime` | `number` | The time, in seconds, at which change will begin. If it's smaller than [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties), it will be clamped to [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties). | | `duration` | `number` | A double representing total time over which the change will happen. | #### Errors @@ -139,7 +139,7 @@ Cancels all scheduled changes after given cancel time. | Parameter | Type | Description | | :---: | :---: | :---- | -| `cancelTime` | `number` | The time, in seconds, after which all scheduled changes will be cancelled. | +| `cancelTime` | `number` | The time, in seconds, after which all scheduled changes will be cancelled. If it's smaller than [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties), it will be clamped to [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties). | #### Errors @@ -155,7 +155,7 @@ Cancels all scheduled changes after given cancel time, but holds its value at gi | Parameter | Type | Description | | :---: | :---: | :---- | -| `cancelTime` | `number` | The time, in seconds, after which all scheduled changes will be cancelled. | +| `cancelTime` | `number` | The time, in seconds, after which all scheduled changes will be cancelled. If it's smaller than [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties), it will be clamped to [`currentTime`](https://docs.swmansion.com/react-native-audio-api/docs/core/base-audio-context#properties).| #### Errors diff --git a/packages/react-native-audio-api/src/core/AudioParam.ts b/packages/react-native-audio-api/src/core/AudioParam.ts index d8cfb5fed..3f5d1ee19 100644 --- a/packages/react-native-audio-api/src/core/AudioParam.ts +++ b/packages/react-native-audio-api/src/core/AudioParam.ts @@ -33,7 +33,8 @@ export default class AudioParam { ); } - this.audioParam.setValueAtTime(value, startTime); + const clampedTime = Math.max(startTime, this.context.currentTime); + this.audioParam.setValueAtTime(value, clampedTime); return this; } @@ -45,7 +46,8 @@ export default class AudioParam { ); } - this.audioParam.linearRampToValueAtTime(value, endTime); + const clampedTime = Math.max(endTime, this.context.currentTime); + this.audioParam.linearRampToValueAtTime(value, clampedTime); return this; } @@ -54,13 +56,14 @@ export default class AudioParam { value: number, endTime: number ): AudioParam { - if (endTime < 0) { + if (endTime <= 0) { throw new RangeError( `endTime must be a finite non-negative number: ${endTime}` ); } - this.audioParam.exponentialRampToValueAtTime(value, endTime); + const clampedTime = Math.max(endTime, this.context.currentTime); + this.audioParam.exponentialRampToValueAtTime(value, clampedTime); return this; } @@ -78,11 +81,12 @@ export default class AudioParam { if (timeConstant < 0) { throw new RangeError( - `timeConstant must be a finite non-negative number: ${startTime}` + `timeConstant must be a finite non-negative number: ${timeConstant}` ); } - this.audioParam.setTargetAtTime(target, startTime, timeConstant); + const clampedTime = Math.max(startTime, this.context.currentTime); + this.audioParam.setTargetAtTime(target, clampedTime, timeConstant); return this; } @@ -98,9 +102,9 @@ export default class AudioParam { ); } - if (duration < 0) { + if (duration <= 0) { throw new RangeError( - `duration must be a finite non-negative number: ${startTime}` + `duration must be a finite strictly-positive number: ${duration}` ); } @@ -108,7 +112,8 @@ export default class AudioParam { throw new InvalidStateError(`values must contain at least two values`); } - this.audioParam.setValueCurveAtTime(values, startTime, duration); + const clampedTime = Math.max(startTime, this.context.currentTime); + this.audioParam.setValueCurveAtTime(values, clampedTime, duration); return this; } @@ -120,7 +125,8 @@ export default class AudioParam { ); } - this.audioParam.cancelScheduledValues(cancelTime); + const clampedTime = Math.max(cancelTime, this.context.currentTime); + this.audioParam.cancelScheduledValues(clampedTime); return this; } @@ -132,7 +138,8 @@ export default class AudioParam { ); } - this.audioParam.cancelAndHoldAtTime(cancelTime); + const clampedTime = Math.max(cancelTime, this.context.currentTime); + this.audioParam.cancelAndHoldAtTime(clampedTime); return this; }