Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LibWeb/WebAudio: Implement automation rate constraints #3301

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Libraries/LibWeb/WebAudio/AudioBufferSourceNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ GC_DEFINE_ALLOCATOR(AudioBufferSourceNode);
AudioBufferSourceNode::AudioBufferSourceNode(JS::Realm& realm, GC::Ref<BaseAudioContext> context, AudioBufferSourceOptions const& options)
: AudioScheduledSourceNode(realm, context)
, m_buffer(options.buffer)
, m_playback_rate(AudioParam::create(realm, context, options.playback_rate, NumericLimits<float>::lowest(), NumericLimits<float>::max(), Bindings::AutomationRate::ARate))
, m_detune(AudioParam::create(realm, context, options.detune, NumericLimits<float>::lowest(), NumericLimits<float>::max(), Bindings::AutomationRate::ARate))
, m_playback_rate(AudioParam::create(realm, context, options.playback_rate, NumericLimits<float>::lowest(), NumericLimits<float>::max(), Bindings::AutomationRate::KRate, AudioParam::FixedAutomationRate::Yes))
, m_detune(AudioParam::create(realm, context, options.detune, NumericLimits<float>::lowest(), NumericLimits<float>::max(), Bindings::AutomationRate::KRate, AudioParam::FixedAutomationRate::Yes))
, m_loop(options.loop)
, m_loop_start(options.loop_start)
, m_loop_end(options.loop_end)
Expand Down
11 changes: 7 additions & 4 deletions Libraries/LibWeb/WebAudio/AudioParam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@ namespace Web::WebAudio {

GC_DEFINE_ALLOCATOR(AudioParam);

AudioParam::AudioParam(JS::Realm& realm, GC::Ref<BaseAudioContext> context, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate)
AudioParam::AudioParam(JS::Realm& realm, GC::Ref<BaseAudioContext> context, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate, FixedAutomationRate fixed_automation_rate)
: Bindings::PlatformObject(realm)
, m_context(context)
, m_current_value(default_value)
, m_default_value(default_value)
, m_min_value(min_value)
, m_max_value(max_value)
, m_automation_rate(automation_rate)
, m_fixed_automation_rate(fixed_automation_rate)
{
}

GC::Ref<AudioParam> AudioParam::create(JS::Realm& realm, GC::Ref<BaseAudioContext> context, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate)
GC::Ref<AudioParam> AudioParam::create(JS::Realm& realm, GC::Ref<BaseAudioContext> context, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate, FixedAutomationRate fixed_automation_rate)
{
return realm.create<AudioParam>(realm, context, default_value, min_value, max_value, automation_rate);
return realm.create<AudioParam>(realm, context, default_value, min_value, max_value, automation_rate, fixed_automation_rate);
}

AudioParam::~AudioParam() = default;
Expand Down Expand Up @@ -56,7 +57,9 @@ Bindings::AutomationRate AudioParam::automation_rate() const
// https://webaudio.github.io/web-audio-api/#dom-audioparam-automationrate
WebIDL::ExceptionOr<void> AudioParam::set_automation_rate(Bindings::AutomationRate automation_rate)
{
dbgln("FIXME: Fully implement AudioParam::set_automation_rate");
if (automation_rate != m_automation_rate && m_fixed_automation_rate == FixedAutomationRate::Yes)
return WebIDL::InvalidStateError::create(realm(), "Automation rate cannot be changed"_string);

m_automation_rate = automation_rate;
return {};
}
Expand Down
10 changes: 8 additions & 2 deletions Libraries/LibWeb/WebAudio/AudioParam.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ class AudioParam final : public Bindings::PlatformObject {
GC_DECLARE_ALLOCATOR(AudioParam);

public:
static GC::Ref<AudioParam> create(JS::Realm&, GC::Ref<BaseAudioContext>, float default_value, float min_value, float max_value, Bindings::AutomationRate);
enum class FixedAutomationRate {
No,
Yes,
};
static GC::Ref<AudioParam> create(JS::Realm&, GC::Ref<BaseAudioContext>, float default_value, float min_value, float max_value, Bindings::AutomationRate, FixedAutomationRate = FixedAutomationRate::No);

virtual ~AudioParam() override;

Expand All @@ -43,7 +47,7 @@ class AudioParam final : public Bindings::PlatformObject {
WebIDL::ExceptionOr<GC::Ref<AudioParam>> cancel_and_hold_at_time(double cancel_time);

private:
AudioParam(JS::Realm&, GC::Ref<BaseAudioContext>, float default_value, float min_value, float max_value, Bindings::AutomationRate);
AudioParam(JS::Realm&, GC::Ref<BaseAudioContext>, float default_value, float min_value, float max_value, Bindings::AutomationRate, FixedAutomationRate = FixedAutomationRate::No);

GC::Ref<BaseAudioContext> m_context;

Expand All @@ -57,6 +61,8 @@ class AudioParam final : public Bindings::PlatformObject {

Bindings::AutomationRate m_automation_rate {};

FixedAutomationRate m_fixed_automation_rate { FixedAutomationRate::No };

virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
};
Expand Down
10 changes: 5 additions & 5 deletions Libraries/LibWeb/WebAudio/DynamicsCompressorNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ WebIDL::ExceptionOr<GC::Ref<DynamicsCompressorNode>> DynamicsCompressorNode::con

DynamicsCompressorNode::DynamicsCompressorNode(JS::Realm& realm, GC::Ref<BaseAudioContext> context, DynamicsCompressorOptions const& options)
: AudioNode(realm, context)
, m_threshold(AudioParam::create(realm, context, options.threshold, -100, 0, Bindings::AutomationRate::KRate))
, m_knee(AudioParam::create(realm, context, options.knee, 0, 40, Bindings::AutomationRate::KRate))
, m_ratio(AudioParam::create(realm, context, options.ratio, 1, 20, Bindings::AutomationRate::KRate))
, m_attack(AudioParam::create(realm, context, options.attack, 0, 1, Bindings::AutomationRate::KRate))
, m_release(AudioParam::create(realm, context, options.release, 0, 1, Bindings::AutomationRate::KRate))
, m_threshold(AudioParam::create(realm, context, options.threshold, -100, 0, Bindings::AutomationRate::KRate, AudioParam::FixedAutomationRate::Yes))
, m_knee(AudioParam::create(realm, context, options.knee, 0, 40, Bindings::AutomationRate::KRate, AudioParam::FixedAutomationRate::Yes))
, m_ratio(AudioParam::create(realm, context, options.ratio, 1, 20, Bindings::AutomationRate::KRate, AudioParam::FixedAutomationRate::Yes))
, m_attack(AudioParam::create(realm, context, options.attack, 0, 1, Bindings::AutomationRate::KRate, AudioParam::FixedAutomationRate::Yes))
, m_release(AudioParam::create(realm, context, options.release, 0, 1, Bindings::AutomationRate::KRate, AudioParam::FixedAutomationRate::Yes))
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
Harness status: OK

Found 122 tests

122 Pass
Pass # AUDIT TASK RUNNER STARTED.
Pass Executing "AudioBufferSourceNode"
Pass Executing "BiquadFilterNode"
Pass Executing "ConstantSourceNode"
Pass Executing "DelayNode"
Pass Executing "DynamicsCompressorNode"
Pass Executing "GainNode"
Pass Executing "OscillatorNode"
Pass Executing "PannerNode"
Pass Executing "StereoPannerNode"
Pass Executing "AudioListener"
Pass Audit report
Pass > [AudioBufferSourceNode]
Pass Default AudioBufferSourceNode.detune.automationRate is equal to k-rate.
Pass Set AudioBufferSourceNode.detune.automationRate to "a-rate" threw InvalidStateError: "Automation rate cannot be changed".
Pass Default AudioBufferSourceNode.playbackRate.automationRate is equal to k-rate.
Pass Set AudioBufferSourceNode.playbackRate.automationRate to "a-rate" threw InvalidStateError: "Automation rate cannot be changed".
Pass < [AudioBufferSourceNode] All assertions passed. (total 4 assertions)
Pass > [BiquadFilterNode]
Pass Default BiquadFilterNode.frequency.automationRate is equal to a-rate.
Pass Set BiquadFilterNode.frequency.automationRate to "k-rate" did not throw an exception.
Pass BiquadFilterNode.frequency.automationRate is equal to k-rate.
Pass Default BiquadFilterNode.detune.automationRate is equal to a-rate.
Pass Set BiquadFilterNode.detune.automationRate to "k-rate" did not throw an exception.
Pass BiquadFilterNode.detune.automationRate is equal to k-rate.
Pass Default BiquadFilterNode.Q.automationRate is equal to a-rate.
Pass Set BiquadFilterNode.Q.automationRate to "k-rate" did not throw an exception.
Pass BiquadFilterNode.Q.automationRate is equal to k-rate.
Pass Default BiquadFilterNode.gain.automationRate is equal to a-rate.
Pass Set BiquadFilterNode.gain.automationRate to "k-rate" did not throw an exception.
Pass BiquadFilterNode.gain.automationRate is equal to k-rate.
Pass < [BiquadFilterNode] All assertions passed. (total 12 assertions)
Pass > [ConstantSourceNode]
Pass Default ConstantSourceNode.offset.automationRate is equal to a-rate.
Pass Set ConstantSourceNode.offset.automationRate to "k-rate" did not throw an exception.
Pass ConstantSourceNode.offset.automationRate is equal to k-rate.
Pass < [ConstantSourceNode] All assertions passed. (total 3 assertions)
Pass > [DelayNode]
Pass Default DelayNode.delayTime.automationRate is equal to a-rate.
Pass Set DelayNode.delayTime.automationRate to "k-rate" did not throw an exception.
Pass DelayNode.delayTime.automationRate is equal to k-rate.
Pass < [DelayNode] All assertions passed. (total 3 assertions)
Pass > [DynamicsCompressorNode]
Pass Default DynamicsCompressorNode.threshold.automationRate is equal to k-rate.
Pass Set DynamicsCompressorNode.threshold.automationRate to "a-rate" threw InvalidStateError: "Automation rate cannot be changed".
Pass Default DynamicsCompressorNode.knee.automationRate is equal to k-rate.
Pass Set DynamicsCompressorNode.knee.automationRate to "a-rate" threw InvalidStateError: "Automation rate cannot be changed".
Pass Default DynamicsCompressorNode.ratio.automationRate is equal to k-rate.
Pass Set DynamicsCompressorNode.ratio.automationRate to "a-rate" threw InvalidStateError: "Automation rate cannot be changed".
Pass Default DynamicsCompressorNode.attack.automationRate is equal to k-rate.
Pass Set DynamicsCompressorNode.attack.automationRate to "a-rate" threw InvalidStateError: "Automation rate cannot be changed".
Pass Default DynamicsCompressorNode.release.automationRate is equal to k-rate.
Pass Set DynamicsCompressorNode.release.automationRate to "a-rate" threw InvalidStateError: "Automation rate cannot be changed".
Pass < [DynamicsCompressorNode] All assertions passed. (total 10 assertions)
Pass > [GainNode]
Pass Default GainNode.gain.automationRate is equal to a-rate.
Pass Set GainNode.gain.automationRate to "k-rate" did not throw an exception.
Pass GainNode.gain.automationRate is equal to k-rate.
Pass < [GainNode] All assertions passed. (total 3 assertions)
Pass > [OscillatorNode]
Pass Default OscillatorNode.frequency.automationRate is equal to a-rate.
Pass Set OscillatorNode.frequency.automationRate to "k-rate" did not throw an exception.
Pass OscillatorNode.frequency.automationRate is equal to k-rate.
Pass Default OscillatorNode.detune.automationRate is equal to a-rate.
Pass Set OscillatorNode.detune.automationRate to "k-rate" did not throw an exception.
Pass OscillatorNode.detune.automationRate is equal to k-rate.
Pass < [OscillatorNode] All assertions passed. (total 6 assertions)
Pass > [PannerNode]
Pass Default PannerNode.positionX.automationRate is equal to a-rate.
Pass Set PannerNode.positionX.automationRate to "k-rate" did not throw an exception.
Pass PannerNode.positionX.automationRate is equal to k-rate.
Pass Default PannerNode.positionY.automationRate is equal to a-rate.
Pass Set PannerNode.positionY.automationRate to "k-rate" did not throw an exception.
Pass PannerNode.positionY.automationRate is equal to k-rate.
Pass Default PannerNode.positionZ.automationRate is equal to a-rate.
Pass Set PannerNode.positionZ.automationRate to "k-rate" did not throw an exception.
Pass PannerNode.positionZ.automationRate is equal to k-rate.
Pass Default PannerNode.orientationX.automationRate is equal to a-rate.
Pass Set PannerNode.orientationX.automationRate to "k-rate" did not throw an exception.
Pass PannerNode.orientationX.automationRate is equal to k-rate.
Pass Default PannerNode.orientationY.automationRate is equal to a-rate.
Pass Set PannerNode.orientationY.automationRate to "k-rate" did not throw an exception.
Pass PannerNode.orientationY.automationRate is equal to k-rate.
Pass Default PannerNode.orientationZ.automationRate is equal to a-rate.
Pass Set PannerNode.orientationZ.automationRate to "k-rate" did not throw an exception.
Pass PannerNode.orientationZ.automationRate is equal to k-rate.
Pass < [PannerNode] All assertions passed. (total 18 assertions)
Pass > [StereoPannerNode]
Pass Default StereoPannerNode.pan.automationRate is equal to a-rate.
Pass Set StereoPannerNode.pan.automationRate to "k-rate" did not throw an exception.
Pass StereoPannerNode.pan.automationRate is equal to k-rate.
Pass < [StereoPannerNode] All assertions passed. (total 3 assertions)
Pass > [AudioListener]
Pass Default AudioListener.positionX.automationRate is equal to a-rate.
Pass Set AudioListener.positionX.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.positionX.automationRate is equal to k-rate.
Pass Default AudioListener.positionY.automationRate is equal to a-rate.
Pass Set AudioListener.positionY.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.positionY.automationRate is equal to k-rate.
Pass Default AudioListener.positionZ.automationRate is equal to a-rate.
Pass Set AudioListener.positionZ.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.positionZ.automationRate is equal to k-rate.
Pass Default AudioListener.forwardX.automationRate is equal to a-rate.
Pass Set AudioListener.forwardX.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.forwardX.automationRate is equal to k-rate.
Pass Default AudioListener.forwardY.automationRate is equal to a-rate.
Pass Set AudioListener.forwardY.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.forwardY.automationRate is equal to k-rate.
Pass Default AudioListener.forwardZ.automationRate is equal to a-rate.
Pass Set AudioListener.forwardZ.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.forwardZ.automationRate is equal to k-rate.
Pass Default AudioListener.upX.automationRate is equal to a-rate.
Pass Set AudioListener.upX.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.upX.automationRate is equal to k-rate.
Pass Default AudioListener.upY.automationRate is equal to a-rate.
Pass Set AudioListener.upY.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.upY.automationRate is equal to k-rate.
Pass Default AudioListener.upZ.automationRate is equal to a-rate.
Pass Set AudioListener.upZ.automationRate to "k-rate" did not throw an exception.
Pass AudioListener.upZ.automationRate is equal to k-rate.
Pass < [AudioListener] All assertions passed. (total 27 assertions)
Pass # AUDIT TASK RUNNER FINISHED: 10 tasks ran successfully.
Loading
Loading