/src/serenity/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2024, Shannon Booth <shannon@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <LibWeb/Bindings/Intrinsics.h> |
8 | | #include <LibWeb/Bindings/OscillatorNodePrototype.h> |
9 | | #include <LibWeb/WebAudio/AudioParam.h> |
10 | | #include <LibWeb/WebAudio/BaseAudioContext.h> |
11 | | #include <LibWeb/WebAudio/OscillatorNode.h> |
12 | | |
13 | | namespace Web::WebAudio { |
14 | | |
15 | | JS_DEFINE_ALLOCATOR(OscillatorNode); |
16 | | |
17 | 0 | OscillatorNode::~OscillatorNode() = default; |
18 | | |
19 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<OscillatorNode>> OscillatorNode::create(JS::Realm& realm, JS::NonnullGCPtr<BaseAudioContext> context, OscillatorOptions const& options) |
20 | 0 | { |
21 | 0 | return construct_impl(realm, context, options); |
22 | 0 | } |
23 | | |
24 | | // https://webaudio.github.io/web-audio-api/#dom-oscillatornode-oscillatornode |
25 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<OscillatorNode>> OscillatorNode::construct_impl(JS::Realm& realm, JS::NonnullGCPtr<BaseAudioContext> context, OscillatorOptions const& options) |
26 | 0 | { |
27 | | // FIXME: Invoke "Initialize the AudioNode" steps. |
28 | 0 | TRY(verify_valid_type(realm, options.type)); |
29 | 0 | auto node = realm.vm().heap().allocate<OscillatorNode>(realm, realm, context, options); |
30 | 0 | return node; |
31 | 0 | } |
32 | | |
33 | | OscillatorNode::OscillatorNode(JS::Realm& realm, JS::NonnullGCPtr<BaseAudioContext> context, OscillatorOptions const& options) |
34 | 0 | : AudioScheduledSourceNode(realm, context) |
35 | 0 | , m_frequency(AudioParam::create(realm, options.frequency, -context->nyquist_frequency(), context->nyquist_frequency(), Bindings::AutomationRate::ARate)) |
36 | 0 | { |
37 | 0 | } |
38 | | |
39 | | // https://webaudio.github.io/web-audio-api/#dom-oscillatornode-type |
40 | | Bindings::OscillatorType OscillatorNode::type() const |
41 | 0 | { |
42 | 0 | return m_type; |
43 | 0 | } |
44 | | |
45 | | // https://webaudio.github.io/web-audio-api/#dom-oscillatornode-type |
46 | | WebIDL::ExceptionOr<void> OscillatorNode::verify_valid_type(JS::Realm& realm, Bindings::OscillatorType type) |
47 | 0 | { |
48 | | // The shape of the periodic waveform. It may directly be set to any of the type constant values except |
49 | | // for "custom". ⌛ Doing so MUST throw an InvalidStateError exception. The setPeriodicWave() method can |
50 | | // be used to set a custom waveform, which results in this attribute being set to "custom". The default |
51 | | // value is "sine". When this attribute is set, the phase of the oscillator MUST be conserved. |
52 | 0 | if (type == Bindings::OscillatorType::Custom) |
53 | 0 | return WebIDL::InvalidStateError::create(realm, "Oscillator node type cannot be set to 'custom'"_string); |
54 | | |
55 | 0 | return {}; |
56 | 0 | } |
57 | | |
58 | | // https://webaudio.github.io/web-audio-api/#dom-oscillatornode-type |
59 | | WebIDL::ExceptionOr<void> OscillatorNode::set_type(Bindings::OscillatorType type) |
60 | 0 | { |
61 | 0 | TRY(verify_valid_type(realm(), type)); |
62 | 0 | m_type = type; |
63 | 0 | return {}; |
64 | 0 | } |
65 | | |
66 | | void OscillatorNode::initialize(JS::Realm& realm) |
67 | 0 | { |
68 | 0 | Base::initialize(realm); |
69 | 0 | WEB_SET_PROTOTYPE_FOR_INTERFACE(OscillatorNode); |
70 | 0 | } |
71 | | |
72 | | void OscillatorNode::visit_edges(Cell::Visitor& visitor) |
73 | 0 | { |
74 | 0 | Base::visit_edges(visitor); |
75 | 0 | visitor.visit(m_frequency); |
76 | 0 | } |
77 | | |
78 | | } |