LibWeb: Implement OscillatorNode.frequency

Which is an AudioParam clamped by the nyquist_frequency.
This commit is contained in:
Shannon Booth 2024-05-01 21:34:44 +12:00 committed by Andreas Kling
parent 5f57596520
commit e2b5ff2450
7 changed files with 42 additions and 2 deletions

View file

@ -8,3 +8,5 @@ Error creating node: 'InvalidStateError: Oscillator node type cannot be set to '
oscillator node type: 'sine'
Error: 'InvalidStateError: Oscillator node type cannot be set to 'custom'', type is: sine
oscillator node type: 'triangle'
[object AudioParam] current: 440, default: 440, min: -22050, max: 22050, rate: a-rate
[object AudioParam] current: -52, default: 440, min: -22050, max: 22050, rate: a-rate

View file

@ -1,5 +1,9 @@
<script src="../include.js"></script>
<script>
function dumpAudioParam(param) {
println(`${param} current: ${param.value}, default: ${param.defaultValue}, min: ${param.minValue}, max: ${param.maxValue}, rate: ${param.automationRate}`);
}
test(() => {
const audioContext = new OfflineAudioContext(1, 5000, 44100);
@ -32,5 +36,11 @@
}
oscillator.type = 'triangle';
println(`oscillator node type: '${oscillator.type}'`);
// Frequency attribute
let frequency = oscillator.frequency;
dumpAudioParam(frequency);
frequency.value = -52;
dumpAudioParam(frequency);
});
</script>

View file

@ -13,6 +13,21 @@ namespace Web::WebAudio {
JS_DEFINE_ALLOCATOR(AudioParam);
AudioParam::AudioParam(JS::Realm& realm, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate)
: Bindings::PlatformObject(realm)
, 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)
{
}
JS::NonnullGCPtr<AudioParam> AudioParam::create(JS::Realm& realm, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate)
{
return realm.vm().heap().allocate<AudioParam>(realm, realm, default_value, min_value, max_value, automation_rate);
}
AudioParam::~AudioParam() = default;
// https://webaudio.github.io/web-audio-api/#dom-audioparam-value

View file

@ -18,6 +18,8 @@ class AudioParam final : public Bindings::PlatformObject {
JS_DECLARE_ALLOCATOR(AudioParam);
public:
static JS::NonnullGCPtr<AudioParam> create(JS::Realm&, float default_value, float min_value, float max_value, Bindings::AutomationRate);
virtual ~AudioParam() override;
float value() const;
@ -39,6 +41,8 @@ public:
WebIDL::ExceptionOr<JS::NonnullGCPtr<AudioParam>> cancel_and_hold_at_time(double cancel_time);
private:
AudioParam(JS::Realm&, float default_value, float min_value, float max_value, Bindings::AutomationRate);
// https://webaudio.github.io/web-audio-api/#dom-audioparam-current-value-slot
float m_current_value {}; // [[current value]]

View file

@ -6,6 +6,8 @@
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/OscillatorNodePrototype.h>
#include <LibWeb/WebAudio/AudioParam.h>
#include <LibWeb/WebAudio/BaseAudioContext.h>
#include <LibWeb/WebAudio/OscillatorNode.h>
namespace Web::WebAudio {
@ -28,8 +30,9 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<OscillatorNode>> OscillatorNode::construct_
return node;
}
OscillatorNode::OscillatorNode(JS::Realm& realm, JS::NonnullGCPtr<BaseAudioContext> context, OscillatorOptions const&)
OscillatorNode::OscillatorNode(JS::Realm& realm, JS::NonnullGCPtr<BaseAudioContext> context, OscillatorOptions const& options)
: AudioScheduledSourceNode(realm, context)
, m_frequency(AudioParam::create(realm, options.frequency, -context->nyquist_frequency(), context->nyquist_frequency(), Bindings::AutomationRate::ARate))
{
}
@ -69,6 +72,7 @@ void OscillatorNode::initialize(JS::Realm& realm)
void OscillatorNode::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_frequency);
}
}

View file

@ -33,6 +33,8 @@ public:
Bindings::OscillatorType type() const;
WebIDL::ExceptionOr<void> set_type(Bindings::OscillatorType);
JS::NonnullGCPtr<AudioParam const> frequency() const { return m_frequency; }
protected:
OscillatorNode(JS::Realm&, JS::NonnullGCPtr<BaseAudioContext>, OscillatorOptions const& = {});
@ -44,6 +46,9 @@ private:
// https://webaudio.github.io/web-audio-api/#dom-oscillatornode-type
Bindings::OscillatorType m_type { Bindings::OscillatorType::Sine };
// https://webaudio.github.io/web-audio-api/#dom-oscillatornode-frequency
JS::NonnullGCPtr<AudioParam> m_frequency;
};
}

View file

@ -23,7 +23,7 @@ dictionary OscillatorOptions : AudioNodeOptions {
interface OscillatorNode : AudioScheduledSourceNode {
constructor(BaseAudioContext context, optional OscillatorOptions options = {});
attribute OscillatorType type;
// FIXME: readonly attribute AudioParam frequency;
readonly attribute AudioParam frequency;
// FIXME: readonly attribute AudioParam detune;
// FIXME: undefined setPeriodicWave(PeriodicWave periodicWave);
};