diff --git a/apps/fabric-example/ios/Podfile.lock b/apps/fabric-example/ios/Podfile.lock index 6f04e1a0..7c89d400 100644 --- a/apps/fabric-example/ios/Podfile.lock +++ b/apps/fabric-example/ios/Podfile.lock @@ -1656,7 +1656,7 @@ PODS: - React-logger (= 0.76.0) - React-perflogger (= 0.76.0) - React-utils (= 0.76.0) - - RNAudioAPI (0.3.0-rc2): + - RNAudioAPI (0.3.1): - DoubleConversion - glog - hermes-engine @@ -2152,7 +2152,7 @@ SPEC CHECKSUMS: React-utils: d9624101245ebaab39c9f1bd786132da0b4f27ff ReactCodegen: dbfef1fef26f42c900bb1884fa149d49d501d64d ReactCommon: 429ca28cd813c31359c73ffac6dc24f93347d522 - RNAudioAPI: 837e19b456700c09bfd3d3c0068b82d2a11c68d0 + RNAudioAPI: e7c191e81df9b2a725b8409767130b0af869f9bc RNGestureHandler: 0e5ae8d72ef4afb855e98dcdbe60f27d938abe13 RNReanimated: 006a5d3961bf09c1e96d62ed436e02b2e43b89bb RNScreens: e389d6a6a66a4f0d3662924ecae803073ccce8ec diff --git a/docs/web-audio-coverage.md b/docs/web-audio-coverage.md index 8500448d..ced594cf 100644 --- a/docs/web-audio-coverage.md +++ b/docs/web-audio-coverage.md @@ -7,7 +7,7 @@ Some of the noticeable implementation details that are still in progress or not - Support of different number of channels (current approach in most of the audio-graph nodes assumes working with two channel audio) - Multi-input for each node and input mixing (Although specification suggests that most of the nodes can cave only one input or output, common use-cases proves otherwise). Only node that mixes multiple inputs is `DestinationNode`. -## ✅ Completed (**9** out of 33) +## ✅ Completed (**10** out of 32)
AudioBuffer @@ -36,8 +36,11 @@ Some of the noticeable implementation details that are still in progress or not
StereoPannerNode
+
+ AudioParam +
-## 🚧 In Progress (**4** out of 33) +## 🚧 In Progress (**3** out of 32)
AudioContext @@ -80,28 +83,6 @@ Some of the noticeable implementation details that are still in progress or not
-
- AudioParam - -
- -| Property 🔹/ Method 🔘 | state | -| -------------------------- | ----- | -| 🔹 value | ✅ | -| 🔹 defaultValue | ✅ | -| 🔹 minValue | ✅ | -| 🔹 maxValue | ✅ | -| 🔘 setValueAtTime | ✅ | -| 🔘 linearRampToValueAtTime | ✅ | -| 🔘 setTargetAtTime | ❌ | -| 🔘 setValueCurveAtTime | ❌ | -| 🔘 cancelScheduledValues | ❌ | -| 🔘 cancelAndHoldAtTime | ❌ | - -
- -
-
BaseAudioContext @@ -138,7 +119,7 @@ Some of the noticeable implementation details that are still in progress or not
-## ❌ Not yet available (**20** out of 33) +## ❌ Not yet available (**19** out of 32)
AudioParamMap @@ -197,6 +178,3 @@ Some of the noticeable implementation details that are still in progress or not
OfflineAudioContext
-
- AudioParamMap -
diff --git a/packages/react-native-audio-api/common/cpp/HostObjects/AudioParamHostObject.h b/packages/react-native-audio-api/common/cpp/HostObjects/AudioParamHostObject.h index 066f3a61..d2a2b1e9 100644 --- a/packages/react-native-audio-api/common/cpp/HostObjects/AudioParamHostObject.h +++ b/packages/react-native-audio-api/common/cpp/HostObjects/AudioParamHostObject.h @@ -23,8 +23,11 @@ class AudioParamHostObject : public JsiHostObject { addFunctions( JSI_EXPORT_FUNCTION(AudioParamHostObject, setValueAtTime), JSI_EXPORT_FUNCTION(AudioParamHostObject, linearRampToValueAtTime), - JSI_EXPORT_FUNCTION( - AudioParamHostObject, exponentialRampToValueAtTime)); + JSI_EXPORT_FUNCTION(AudioParamHostObject, exponentialRampToValueAtTime), + JSI_EXPORT_FUNCTION(AudioParamHostObject, setTargetAtTime), + JSI_EXPORT_FUNCTION(AudioParamHostObject, setValueCurveAtTime), + JSI_EXPORT_FUNCTION(AudioParamHostObject, cancelScheduledValues), + JSI_EXPORT_FUNCTION(AudioParamHostObject, cancelAndHoldAtTime)); addSetters(JSI_EXPORT_PROPERTY_SETTER(AudioParamHostObject, value)); } @@ -66,6 +69,40 @@ class AudioParamHostObject : public JsiHostObject { return jsi::Value::undefined(); } + JSI_HOST_FUNCTION(setTargetAtTime) { + auto target = static_cast(args[0].getNumber()); + double startTime = args[1].getNumber(); + double timeConstant = args[2].getNumber(); + param_->setTargetAtTime(target, startTime, timeConstant); + return jsi::Value::undefined(); + } + + JSI_HOST_FUNCTION(setValueCurveAtTime) { + auto values = args[0].getObject(runtime).asArray(runtime); + auto length = static_cast(values.length(runtime)); + auto valuesData = new float[length]; + for (size_t i = 0; i < values.length(runtime); i++) { + valuesData[i] = + static_cast(values.getValueAtIndex(runtime, i).getNumber()); + } + double startTime = args[1].getNumber(); + double duration = args[2].getNumber(); + param_->setValueCurveAtTime(valuesData, length, startTime, duration); + return jsi::Value::undefined(); + } + + JSI_HOST_FUNCTION(cancelScheduledValues) { + double cancelTime = args[0].getNumber(); + param_->cancelScheduledValues(cancelTime); + return jsi::Value::undefined(); + } + + JSI_HOST_FUNCTION(cancelAndHoldAtTime) { + double cancelTime = args[0].getNumber(); + param_->cancelAndHoldAtTime(cancelTime); + return jsi::Value::undefined(); + } + JSI_PROPERTY_SETTER(value) { param_->setValue(static_cast(value.getNumber())); } diff --git a/packages/react-native-audio-api/common/cpp/core/AudioParam.cpp b/packages/react-native-audio-api/common/cpp/core/AudioParam.cpp index 43224b54..78f11cc4 100644 --- a/packages/react-native-audio-api/common/cpp/core/AudioParam.cpp +++ b/packages/react-native-audio-api/common/cpp/core/AudioParam.cpp @@ -1,4 +1,6 @@ #include "AudioParam.h" + +#include "AudioUtils.h" #include "BaseAudioContext.h" namespace audioapi { @@ -12,12 +14,11 @@ AudioParam::AudioParam( defaultValue_(defaultValue), minValue_(minValue), maxValue_(maxValue), - context_(context), - changesQueue_() { + context_(context) { startTime_ = 0; endTime_ = 0; - startValue_ = 0; - endValue_ = 0; + startValue_ = value_; + endValue_ = value_; calculateValue_ = [this](double, double, float, float, double) { return value_; }; @@ -40,94 +41,258 @@ float AudioParam::getMaxValue() const { } void AudioParam::setValue(float value) { - value_ = checkValue(value); + value_ = std::clamp(value, minValue_, maxValue_); } float AudioParam::getValueAtTime(double time) { - if (!changesQueue_.empty()) { - if (endTime_ < time) { - auto change = *changesQueue_.begin(); - startTime_ = change.getStartTime(); - endTime_ = change.getEndTime(); - startValue_ = change.getStartValue(); - endValue_ = change.getEndValue(); - calculateValue_ = change.getCalculateValue(); - changesQueue_.erase(changesQueue_.begin()); - } + if (endTime_ < time && !eventsQueue_.empty()) { + auto event = eventsQueue_.front(); + startTime_ = event.getStartTime(); + endTime_ = event.getEndTime(); + startValue_ = event.getStartValue(); + endValue_ = event.getEndValue(); + calculateValue_ = event.getCalculateValue(); + eventsQueue_.pop_front(); } - if (startTime_ <= time) { - value_ = - calculateValue_(startTime_, endTime_, startValue_, endValue_, time); - } + setValue(calculateValue_(startTime_, endTime_, startValue_, endValue_, time)); return value_; } -void AudioParam::setValueAtTime(float value, double time) { - value = checkValue(value); - auto calculateValue = [](double, double, float, float endValue, double) { +void AudioParam::setValueAtTime(float value, double startTime) { + if (startTime <= getQueueEndTime()) { + return; + } + + auto calculateValue = [](double startTime, + double, + float startValue, + float endValue, + double time) { + if (time < startTime) { + return startValue; + } + return endValue; }; - auto paramChange = ParamChange(time, time, value, value, calculateValue); - changesQueue_.insert(paramChange); + auto event = ParamChangeEvent( + startTime, + startTime, + getQueueEndValue(), + value, + calculateValue, + ParamChangeEventType::SET_VALUE); + updateQueue(event); } -void AudioParam::linearRampToValueAtTime(float value, double time) { - value = checkValue(value); +void AudioParam::linearRampToValueAtTime(float value, double endTime) { + if (endTime <= getQueueEndTime()) { + return; + } + auto calculateValue = [](double startTime, double endTime, float startValue, float endValue, double time) { - return time >= endTime ? endValue - : startValue + - (endValue - startValue) * (time - startTime) / - (endTime - startTime); + if (time < startTime) { + return startValue; + } + + if (time < endTime) { + return static_cast( + startValue + + (endValue - startValue) * (time - startTime) / (endTime - startTime)); + } + + return endValue; }; - auto paramChange = - ParamChange(getStartTime(), time, getStartValue(), value, calculateValue); - changesQueue_.emplace(paramChange); + auto event = ParamChangeEvent( + getQueueEndTime(), + endTime, + getQueueEndValue(), + value, + calculateValue, + ParamChangeEventType::LINEAR_RAMP); + updateQueue(event); } -void AudioParam::exponentialRampToValueAtTime(float value, double time) { - value = checkValue(value); +void AudioParam::exponentialRampToValueAtTime(float value, double endTime) { + if (endTime <= getQueueEndTime()) { + return; + } + auto calculateValue = [](double startTime, double endTime, float startValue, float endValue, double time) { - return time >= endTime ? endValue - : startValue * - pow(endValue / startValue, - (time - startTime) / (endTime - startTime)); + if (time < startTime) { + return startValue; + } + + if (time < endTime) { + return static_cast( + startValue * + pow(endValue / startValue, + (time - startTime) / (endTime - startTime))); + } + + return endValue; }; - auto paramChange = - ParamChange(getStartTime(), time, getStartValue(), value, calculateValue); - changesQueue_.emplace(paramChange); + auto event = ParamChangeEvent( + getQueueEndTime(), + endTime, + getQueueEndValue(), + value, + calculateValue, + ParamChangeEventType::EXPONENTIAL_RAMP); + updateQueue(event); } -float AudioParam::checkValue(float value) const { - return std::clamp(value, minValue_, maxValue_); +void AudioParam::setTargetAtTime( + float target, + double startTime, + double timeConstant) { + if (startTime <= getQueueEndTime()) { + return; + } + + auto calculateValue = + [timeConstant, target]( + double startTime, double, float startValue, float, double time) { + if (time < startTime) { + return startValue; + } + + return static_cast( + target + + (startValue - target) * exp(-(time - startTime) / timeConstant)); + }; + + auto event = ParamChangeEvent( + startTime, + startTime, + getQueueEndValue(), + getQueueEndValue(), + calculateValue, + ParamChangeEventType::SET_TARGET); + updateQueue(event); } -double AudioParam::getStartTime() { - if (changesQueue_.empty()) { - return context_->getCurrentTime(); +void AudioParam::setValueCurveAtTime( + const float *values, + int length, + double startTime, + double duration) { + if (startTime <= getQueueEndTime()) { + return; } - return changesQueue_.rbegin()->getEndTime(); + auto calculateValue = [&values, length]( + double startTime, + double endTime, + float startValue, + float endValue, + double time) { + if (time < startTime) { + return startValue; + } + + if (time < endTime) { + auto k = static_cast(std::floor( + (length - 1) / (endTime - startTime) * (time - startTime))); + auto factor = static_cast( + k - (time - startTime) * (length - 1) / (endTime - startTime)); + + return AudioUtils::linearInterpolate(values, k, k + 1, factor); + } + + return endValue; + }; + + auto event = ParamChangeEvent( + startTime, + startTime + duration, + getQueueEndValue(), + values[length - 1], + calculateValue, + ParamChangeEventType::SET_VALUE_CURVE); + updateQueue(event); +} + +void AudioParam::cancelScheduledValues(double cancelTime) { + auto it = eventsQueue_.rbegin(); + while (it->getEndTime() >= cancelTime) { + if (it->getStartTime() >= cancelTime || + it->getType() == ParamChangeEventType::SET_VALUE_CURVE) { + eventsQueue_.pop_back(); + } + + it++; + } } -float AudioParam::getStartValue() { - if (changesQueue_.empty()) { - return this->value_; +void AudioParam::cancelAndHoldAtTime(double cancelTime) { + auto it = eventsQueue_.rbegin(); + while (it->getEndTime() >= cancelTime) { + if (it->getStartTime() >= cancelTime) { + eventsQueue_.pop_back(); + } + + it++; + } + + if (eventsQueue_.empty()) { + endTime_ = cancelTime; + } + + if (!eventsQueue_.empty()) { + auto lastEvent = eventsQueue_.rbegin(); + if (lastEvent->getEndTime() > cancelTime) { + lastEvent->setEndTime(cancelTime); + } + } +} + +double AudioParam::getQueueEndTime() { + if (eventsQueue_.empty()) { + return endTime_; + } + + return eventsQueue_.back().getEndTime(); +} + +float AudioParam::getQueueEndValue() { + if (eventsQueue_.empty()) { + return this->endValue_; + } + + return eventsQueue_.back().getEndValue(); +} + +void AudioParam::updateQueue(ParamChangeEvent &event) { + if (!eventsQueue_.empty()) { + auto prev = eventsQueue_.back(); + + if (prev.getType() == ParamChangeEventType::SET_TARGET) { + prev.setEndTime(event.getStartTime()); + prev.setEndValue(prev.getCalculateValue()( + prev.getStartTime(), + prev.getEndTime(), + prev.getStartValue(), + prev.getEndValue(), + event.getStartTime())); + } + + event.setStartValue(prev.getEndValue()); } - return changesQueue_.rbegin()->getEndValue(); + eventsQueue_.push_back(event); } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/core/AudioParam.h b/packages/react-native-audio-api/common/cpp/core/AudioParam.h index 8604b52c..cc32eeee 100644 --- a/packages/react-native-audio-api/common/cpp/core/AudioParam.h +++ b/packages/react-native-audio-api/common/cpp/core/AudioParam.h @@ -1,10 +1,11 @@ #pragma once +#include #include -#include #include -#include "ParamChange.h" +#include "ParamChangeEvent.h" +#include "ParamChangeEventType.h" namespace audioapi { @@ -20,13 +21,23 @@ class AudioParam { [[nodiscard]] float getValue() const; float getValueAtTime(double time); - void setValue(float value); [[nodiscard]] float getDefaultValue() const; [[nodiscard]] float getMinValue() const; [[nodiscard]] float getMaxValue() const; + + void setValue(float value); + void setValueAtTime(float value, double startTime); void linearRampToValueAtTime(float value, double endTime); void exponentialRampToValueAtTime(float value, double endTime); + void setTargetAtTime(float target, double startTime, double timeConstant); + void setValueCurveAtTime( + const float *values, + int length, + double startTime, + double duration); + void cancelScheduledValues(double cancelTime); + void cancelAndHoldAtTime(double cancelTime); private: float value_; @@ -34,7 +45,7 @@ class AudioParam { float minValue_; float maxValue_; BaseAudioContext *context_; - std::set changesQueue_; + std::deque eventsQueue_; double startTime_; double endTime_; @@ -42,9 +53,9 @@ class AudioParam { float endValue_; std::function calculateValue_; - float checkValue(float value) const; - double getStartTime(); - float getStartValue(); + double getQueueEndTime(); + float getQueueEndValue(); + void updateQueue(ParamChangeEvent &event); }; } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/core/ParamChange.cpp b/packages/react-native-audio-api/common/cpp/core/ParamChange.cpp deleted file mode 100644 index 0e26fef9..00000000 --- a/packages/react-native-audio-api/common/cpp/core/ParamChange.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "ParamChange.h" - -#include - -namespace audioapi { - -ParamChange::ParamChange( - double startTime, - double endTime, - float startValue, - float endValue, - std::function calculateValue) - : startTime_(startTime), - endTime_(endTime), - startValue_(startValue), - endValue_(endValue), - calculateValue_(std::move(calculateValue)) {} - -double ParamChange::getEndTime() const { - return endTime_; -} - -double ParamChange::getStartTime() const { - return startTime_; -} - -float ParamChange::getEndValue() const { - return endValue_; -} - -float ParamChange::getStartValue() const { - return startValue_; -} - -std::function -ParamChange::getCalculateValue() const { - return calculateValue_; -} - -bool ParamChange::operator<(const ParamChange &other) const { - if (startTime_ != other.startTime_) - return startTime_ < other.startTime_; - return endTime_ < other.endTime_; -} - -} // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/core/ParamChangeEvent.cpp b/packages/react-native-audio-api/common/cpp/core/ParamChangeEvent.cpp new file mode 100644 index 00000000..3062e39c --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/core/ParamChangeEvent.cpp @@ -0,0 +1,58 @@ +#include "ParamChangeEvent.h" + +#include + +namespace audioapi { + +ParamChangeEvent::ParamChangeEvent( + double startTime, + double endTime, + float startValue, + float endValue, + std::function calculateValue, + ParamChangeEventType type) + : startTime_(startTime), + endTime_(endTime), + startValue_(startValue), + endValue_(endValue), + calculateValue_(std::move(calculateValue)), + type_(type) {} + +double ParamChangeEvent::getEndTime() const { + return endTime_; +} + +double ParamChangeEvent::getStartTime() const { + return startTime_; +} + +float ParamChangeEvent::getEndValue() const { + return endValue_; +} + +float ParamChangeEvent::getStartValue() const { + return startValue_; +} + +std::function +ParamChangeEvent::getCalculateValue() const { + return calculateValue_; +} + +ParamChangeEventType ParamChangeEvent::getType() const { + return type_; +} + +void ParamChangeEvent::setEndTime(double endTime) { + endTime_ = endTime; +} + +void ParamChangeEvent::setStartValue(float startValue) { + startValue_ = startValue; +} + +void ParamChangeEvent::setEndValue(float endValue) { + endValue_ = endValue; +} + +} // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/core/ParamChange.h b/packages/react-native-audio-api/common/cpp/core/ParamChangeEvent.h similarity index 68% rename from packages/react-native-audio-api/common/cpp/core/ParamChange.h rename to packages/react-native-audio-api/common/cpp/core/ParamChangeEvent.h index f431edc4..76520039 100644 --- a/packages/react-native-audio-api/common/cpp/core/ParamChange.h +++ b/packages/react-native-audio-api/common/cpp/core/ParamChangeEvent.h @@ -2,18 +2,19 @@ #include #include +#include "ParamChangeEventType.h" namespace audioapi { -class ParamChange { +class ParamChangeEvent { public: - explicit ParamChange( + explicit ParamChangeEvent( double startTime, double endTime, float startValue, float endValue, - std::function - calculateValue); + std::function calculateValue, + ParamChangeEventType type); [[nodiscard]] double getEndTime() const; [[nodiscard]] double getStartTime() const; @@ -21,7 +22,11 @@ class ParamChange { [[nodiscard]] float getStartValue() const; [[nodiscard]] std::function getCalculateValue() const; - bool operator<(const ParamChange &other) const; + [[nodiscard]] ParamChangeEventType getType() const; + + void setEndTime(double endTime); + void setStartValue(float startValue); + void setEndValue(float endValue); private: double startTime_; @@ -29,6 +34,7 @@ class ParamChange { float startValue_; float endValue_; std::function calculateValue_; + ParamChangeEventType type_; }; } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/types/BiquadFilterType.h b/packages/react-native-audio-api/common/cpp/types/BiquadFilterType.h index a7e763e4..f9e67a66 100644 --- a/packages/react-native-audio-api/common/cpp/types/BiquadFilterType.h +++ b/packages/react-native-audio-api/common/cpp/types/BiquadFilterType.h @@ -1,9 +1,5 @@ #pragma once -#include -#include -#include - namespace audioapi { enum class BiquadFilterType { diff --git a/packages/react-native-audio-api/common/cpp/types/ChannelCountMode.h b/packages/react-native-audio-api/common/cpp/types/ChannelCountMode.h index e2b54975..a91aa930 100644 --- a/packages/react-native-audio-api/common/cpp/types/ChannelCountMode.h +++ b/packages/react-native-audio-api/common/cpp/types/ChannelCountMode.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - namespace audioapi { enum class ChannelCountMode { MAX, CLAMPED_MAX, EXPLICIT }; diff --git a/packages/react-native-audio-api/common/cpp/types/ChannelInterpretation.h b/packages/react-native-audio-api/common/cpp/types/ChannelInterpretation.h index 244d17ec..45dc1ad7 100644 --- a/packages/react-native-audio-api/common/cpp/types/ChannelInterpretation.h +++ b/packages/react-native-audio-api/common/cpp/types/ChannelInterpretation.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - namespace audioapi { enum class ChannelInterpretation { SPEAKERS, DISCRETE }; diff --git a/packages/react-native-audio-api/common/cpp/types/ContextState.h b/packages/react-native-audio-api/common/cpp/types/ContextState.h index 3dd6806f..6a93b062 100644 --- a/packages/react-native-audio-api/common/cpp/types/ContextState.h +++ b/packages/react-native-audio-api/common/cpp/types/ContextState.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - namespace audioapi { enum class ContextState { SUSPENDED, RUNNING, CLOSED }; diff --git a/packages/react-native-audio-api/common/cpp/types/OscillatorType.h b/packages/react-native-audio-api/common/cpp/types/OscillatorType.h index 6dccb995..c25d9e72 100644 --- a/packages/react-native-audio-api/common/cpp/types/OscillatorType.h +++ b/packages/react-native-audio-api/common/cpp/types/OscillatorType.h @@ -1,9 +1,5 @@ #pragma once -#include -#include -#include - namespace audioapi { enum class OscillatorType { SINE, SQUARE, SAWTOOTH, TRIANGLE, CUSTOM }; diff --git a/packages/react-native-audio-api/common/cpp/types/ParamChangeEventType.h b/packages/react-native-audio-api/common/cpp/types/ParamChangeEventType.h new file mode 100644 index 00000000..e5bd6b52 --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/types/ParamChangeEventType.h @@ -0,0 +1,13 @@ +#pragma once + +namespace audioapi { + +enum class ParamChangeEventType { + LINEAR_RAMP, + EXPONENTIAL_RAMP, + SET_VALUE, + SET_TARGET, + SET_VALUE_CURVE, +}; + +} // namespace audioapi diff --git a/packages/react-native-audio-api/src/core/AudioParam.ts b/packages/react-native-audio-api/src/core/AudioParam.ts index 66bbc28d..768f0b36 100644 --- a/packages/react-native-audio-api/src/core/AudioParam.ts +++ b/packages/react-native-audio-api/src/core/AudioParam.ts @@ -52,4 +52,52 @@ export default class AudioParam { this.audioParam.exponentialRampToValueAtTime(value, endTime); } + + public setTargetAtTime( + target: number, + startTime: number, + timeConstant: number + ): void { + if (startTime < 0) { + throw new RangeError( + `Time must be a finite non-negative number: ${startTime}` + ); + } + + this.audioParam.setTargetAtTime(target, startTime, timeConstant); + } + + public setValueCurveAtTime( + values: number[], + startTime: number, + duration: number + ): void { + if (startTime < 0) { + throw new RangeError( + `Time must be a finite non-negative number: ${startTime}` + ); + } + + this.audioParam.setValueCurveAtTime(values, startTime, duration); + } + + public cancelScheduledValues(cancelTime: number): void { + if (cancelTime < 0) { + throw new RangeError( + `Time must be a finite non-negative number: ${cancelTime}` + ); + } + + this.audioParam.cancelScheduledValues(cancelTime); + } + + public cancelAndHoldAtTime(cancelTime: number): void { + if (cancelTime < 0) { + throw new RangeError( + `Time must be a finite non-negative number: ${cancelTime}` + ); + } + + this.audioParam.cancelAndHoldAtTime(cancelTime); + } } diff --git a/packages/react-native-audio-api/src/index.ts b/packages/react-native-audio-api/src/index.ts index 0d1d3b12..f9dfe049 100644 --- a/packages/react-native-audio-api/src/index.ts +++ b/packages/react-native-audio-api/src/index.ts @@ -244,6 +244,34 @@ export class AudioParam { public exponentialRampToValueAtTime(value: number, endTime: number): void { this.param.exponentialRampToValueAtTime(value, endTime); } + + public setTargetAtTime( + target: number, + startTime: number, + timeConstant: number + ): void { + this.param.setTargetAtTime(target, startTime, timeConstant); + } + + public setValueCurveAtTime( + values: number[], + startTime: number, + duration: number + ): void { + this.param.setValueCurveAtTime( + new Float32Array(values), + startTime, + duration + ); + } + + public cancelScheduledValues(startTime: number): void { + this.param.cancelScheduledValues(startTime); + } + + public cancelAndHoldAtTime(cancelTime: number): void { + this.param.cancelAndHoldAtTime(cancelTime); + } } export class BiquadFilterNode extends AudioNode { diff --git a/packages/react-native-audio-api/src/interfaces.ts b/packages/react-native-audio-api/src/interfaces.ts index 3d192966..58a7637c 100644 --- a/packages/react-native-audio-api/src/interfaces.ts +++ b/packages/react-native-audio-api/src/interfaces.ts @@ -121,6 +121,18 @@ export interface IAudioParam { setValueAtTime: (value: number, startTime: number) => void; linearRampToValueAtTime: (value: number, endTime: number) => void; exponentialRampToValueAtTime: (value: number, endTime: number) => void; + setTargetAtTime: ( + target: number, + startTime: number, + timeConstant: number + ) => void; + setValueCurveAtTime: ( + values: number[], + startTime: number, + duration: number + ) => void; + cancelScheduledValues: (cancelTime: number) => void; + cancelAndHoldAtTime: (cancelTime: number) => void; } export interface IPeriodicWave {}