From 8f48ee3a00543b0b9eaad170869e49394a6a083f Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 16:24:26 +0300 Subject: [PATCH 01/13] $mol_audio refactor, added sample and scheduled nodes --- audio/context/context.node.ts | 12 ++++ audio/context/context.ts | 3 + audio/context/context.web.ts | 5 ++ .../{demo.web.view.tree => demo.view.tree} | 0 audio/demo/{demo.web.view.ts => demo.view.ts} | 0 .../{vibe.web.view.tree => vibe.view.tree} | 0 .../vibe/{vibe.web.view.ts => vibe.view.ts} | 0 audio/gain/{gain.web.ts => gain.ts} | 2 +- audio/node/{node.web.ts => node.ts} | 12 ++-- audio/room/room.ts | 28 ++++++++++ audio/room/room.web.ts | 19 ------- audio/sample/sample.ts | 29 ++++++++++ audio/scheduled/scheduled.ts | 53 ++++++++++++++++++ audio/vibe/vibe.ts | 34 ++++++++++++ audio/vibe/vibe.web.ts | 55 ------------------- 15 files changed, 169 insertions(+), 83 deletions(-) create mode 100644 audio/context/context.node.ts create mode 100644 audio/context/context.ts create mode 100644 audio/context/context.web.ts rename audio/demo/{demo.web.view.tree => demo.view.tree} (100%) rename audio/demo/{demo.web.view.ts => demo.view.ts} (100%) rename audio/demo/vibe/{vibe.web.view.tree => vibe.view.tree} (100%) rename audio/demo/vibe/{vibe.web.view.ts => vibe.view.ts} (100%) rename audio/gain/{gain.web.ts => gain.ts} (82%) rename audio/node/{node.web.ts => node.ts} (78%) create mode 100644 audio/room/room.ts delete mode 100644 audio/room/room.web.ts create mode 100644 audio/sample/sample.ts create mode 100644 audio/scheduled/scheduled.ts create mode 100644 audio/vibe/vibe.ts delete mode 100644 audio/vibe/vibe.web.ts diff --git a/audio/context/context.node.ts b/audio/context/context.node.ts new file mode 100644 index 00000000000..8f7501917be --- /dev/null +++ b/audio/context/context.node.ts @@ -0,0 +1,12 @@ +namespace $ { + // const api = require('web-audio-api') as { AudioContext: new() => AudioContext } + + // export const $mol_audio_context_node = new api.AudioContext() + export const $mol_audio_context_node = new Proxy({} as AudioContext, { + get() { + throw new Error('Not implemented') + } + }) + + $.$mol_audio_context = $mol_audio_context_node +} diff --git a/audio/context/context.ts b/audio/context/context.ts new file mode 100644 index 00000000000..625eccc49f9 --- /dev/null +++ b/audio/context/context.ts @@ -0,0 +1,3 @@ +namespace $ { + export let $mol_audio_context = undefined as unknown as AudioContext +} diff --git a/audio/context/context.web.ts b/audio/context/context.web.ts new file mode 100644 index 00000000000..fb9742f5bfa --- /dev/null +++ b/audio/context/context.web.ts @@ -0,0 +1,5 @@ +namespace $ { + export const $mol_audio_context_web = new AudioContext() + + $.$mol_audio_context = $mol_audio_context_web +} diff --git a/audio/demo/demo.web.view.tree b/audio/demo/demo.view.tree similarity index 100% rename from audio/demo/demo.web.view.tree rename to audio/demo/demo.view.tree diff --git a/audio/demo/demo.web.view.ts b/audio/demo/demo.view.ts similarity index 100% rename from audio/demo/demo.web.view.ts rename to audio/demo/demo.view.ts diff --git a/audio/demo/vibe/vibe.web.view.tree b/audio/demo/vibe/vibe.view.tree similarity index 100% rename from audio/demo/vibe/vibe.web.view.tree rename to audio/demo/vibe/vibe.view.tree diff --git a/audio/demo/vibe/vibe.web.view.ts b/audio/demo/vibe/vibe.view.ts similarity index 100% rename from audio/demo/vibe/vibe.web.view.ts rename to audio/demo/vibe/vibe.view.ts diff --git a/audio/gain/gain.web.ts b/audio/gain/gain.ts similarity index 82% rename from audio/gain/gain.web.ts rename to audio/gain/gain.ts index f304a31bfc0..7db9f17c278 100644 --- a/audio/gain/gain.web.ts +++ b/audio/gain/gain.ts @@ -3,7 +3,7 @@ namespace $ { export class $mol_audio_gain extends $mol_audio_node { @ $mol_mem - node() { return $mol_audio_node.context().createGain() } + node() { return this.context().createGain() } @ $mol_mem gain( next = 1 ) { return next } diff --git a/audio/node/node.web.ts b/audio/node/node.ts similarity index 78% rename from audio/node/node.web.ts rename to audio/node/node.ts index 71953d99772..55ae9e2af94 100644 --- a/audio/node/node.web.ts +++ b/audio/node/node.ts @@ -1,14 +1,10 @@ namespace $ { export class $mol_audio_node extends $mol_object2 { - - @ $mol_memo.method - static context() { - return new AudioContext - } + context() { return this.$.$mol_audio_context } @ $mol_mem - node() { return $mol_audio_node.context().destination as AudioNode } - + node() { return this.context().destination as AudioNode } + @ $mol_mem input( next = [] as readonly $mol_audio_node[] ) { return next } @@ -38,7 +34,7 @@ namespace $ { return this.node() } - time() { return $mol_audio_node.context().currentTime } + time() { return this.context().currentTime } destructor() { diff --git a/audio/room/room.ts b/audio/room/room.ts new file mode 100644 index 00000000000..f885894d9cc --- /dev/null +++ b/audio/room/room.ts @@ -0,0 +1,28 @@ +namespace $ { + + /** + * @see https://mol.hyoo.ru/#!section=demos/demo=mol_audio_demo + */ + export class $mol_audio_room extends $mol_audio_node { + + duration_default() { + return 1000 + } + + duration() { + let duration = 0 + for (const input of this.input_connected()) { + if (input instanceof $mol_audio_room) duration += input.duration() + if (input instanceof $mol_audio_sample) duration += input.duration() + } + return duration || this.duration_default() + } + + @ $mol_action + play() { + this.output() + this.$.$mol_wait_timeout( this.duration() ) + } + + } +} diff --git a/audio/room/room.web.ts b/audio/room/room.web.ts deleted file mode 100644 index 6f958854117..00000000000 --- a/audio/room/room.web.ts +++ /dev/null @@ -1,19 +0,0 @@ -namespace $ { - - /** - * @see https://mol.hyoo.ru/#!section=demos/demo=mol_audio_demo - */ - export class $mol_audio_room extends $mol_audio_node { - - duration() { - return 1000 - } - - @ $mol_action - play() { - this.output() - this.$.$mol_wait_timeout( this.duration() ) - } - - } -} diff --git a/audio/sample/sample.ts b/audio/sample/sample.ts new file mode 100644 index 00000000000..1287e78d64c --- /dev/null +++ b/audio/sample/sample.ts @@ -0,0 +1,29 @@ +namespace $ { + export class $mol_audio_sample extends $mol_audio_scheduled { + @ $mol_mem + override node() { return this.context().createBufferSource() } + + duration() { + return this.audio_buffer().duration * 1000 + } + + buffer() { + return new ArrayBuffer(0) + } + + @ $mol_mem + audio_buffer() { + return $mol_wire_sync(this.context()).decodeAudioData(this.buffer()) + } + + @ $mol_mem + override node_configured() { + const node = this.node() + node.buffer = this.audio_buffer() + node.onended = $mol_wire_async(() => this.active(false)) + + return node + } + + } +} diff --git a/audio/scheduled/scheduled.ts b/audio/scheduled/scheduled.ts new file mode 100644 index 00000000000..19afa500d45 --- /dev/null +++ b/audio/scheduled/scheduled.ts @@ -0,0 +1,53 @@ +namespace $ { + export class $mol_audio_scheduled extends $mol_audio_node { + @ $mol_mem + override node(): AudioScheduledSourceNode { + throw new Error('implement') + } + + @ $mol_mem + node_configured() { + return this.node() + } + + promise = $mol_promise() + + @ $mol_mem + wait() { + return this.promise + } + + @ $mol_mem + active( next?: boolean ): boolean { + + $mol_wire_solid() + + const node = this.node_configured() + + const prev = $mol_wire_probe( ()=> this.active() ) + if( prev === next ) return next ?? false + + if( next === true ) { + node.start() + } else if( prev === true ) { + node.stop() + this.promise.done() + this.promise = $mol_promise() + } + + return next ?? false + } + + override destructor() { + this.active( false ) + super.destructor() + } + + @ $mol_mem + override output() { + this.active( true ) + return super.output() + } + + } +} diff --git a/audio/vibe/vibe.ts b/audio/vibe/vibe.ts new file mode 100644 index 00000000000..00f13f9cf60 --- /dev/null +++ b/audio/vibe/vibe.ts @@ -0,0 +1,34 @@ +namespace $ { + + export type $mol_audio_vibe_shape = + | 'sine' + | 'square' + | 'sawtooth' + | 'triangle' + | 'custom' + + /** + * @see https://mol.hyoo.ru/#!section=demos/demo=mol_audio_demo_vibe + */ + export class $mol_audio_vibe extends $mol_audio_scheduled { + + @ $mol_mem + override node() { return this.context().createOscillator() } + + @ $mol_mem + freq( next = 440 ) { return next } + + @ $mol_mem + shape( next: $mol_audio_vibe_shape = 'sine' ) { return next } + + @ $mol_mem + override node_configured(): AudioScheduledSourceNode { + const node = this.node() + node.frequency.setValueAtTime( this.freq(), this.time() ) + node.type = this.shape() + + return node + } + + } +} diff --git a/audio/vibe/vibe.web.ts b/audio/vibe/vibe.web.ts deleted file mode 100644 index 10c561a4112..00000000000 --- a/audio/vibe/vibe.web.ts +++ /dev/null @@ -1,55 +0,0 @@ -namespace $ { - - export type $mol_audio_vibe_shape = - | 'sine' - | 'square' - | 'sawtooth' - | 'triangle' - | 'custom' - - /** - * @see https://mol.hyoo.ru/#!section=demos/demo=mol_audio_demo_vibe - */ - export class $mol_audio_vibe extends $mol_audio_node { - - @ $mol_mem - node() { return $mol_audio_node.context().createOscillator() } - - @ $mol_mem - freq( next = 440 ) { return next } - - @ $mol_mem - shape( next: $mol_audio_vibe_shape = 'sine' ) { return next } - - @ $mol_mem - active( next?: boolean ): boolean { - - $mol_wire_solid() - - const prev = $mol_wire_probe( ()=> this.active() ) - if( prev === next ) return next ?? false - - if( next === true ) this.node().start() - else if( prev === true ) this.node().stop() - - return next ?? false - } - - @ $mol_mem - output() { - const node = this.node() - - node.frequency.setValueAtTime( this.freq(), this.time() ) - node.type = this.shape() - - this.active( true ) - return super.output() - } - - destructor() { - this.active( false ) - super.destructor() - } - - } -} From b5dbf192ae62b67dd86ccd063d14fd1add7c0829 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 16:43:54 +0300 Subject: [PATCH 02/13] $mol_audio_scheduled moved duration --- audio/room/room.ts | 2 +- audio/sample/sample.ts | 2 +- audio/scheduled/scheduled.ts | 4 ++++ audio/vibe/vibe.ts | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/audio/room/room.ts b/audio/room/room.ts index f885894d9cc..1a258518b6e 100644 --- a/audio/room/room.ts +++ b/audio/room/room.ts @@ -13,7 +13,7 @@ namespace $ { let duration = 0 for (const input of this.input_connected()) { if (input instanceof $mol_audio_room) duration += input.duration() - if (input instanceof $mol_audio_sample) duration += input.duration() + if (input instanceof $mol_audio_scheduled) duration += input.duration() } return duration || this.duration_default() } diff --git a/audio/sample/sample.ts b/audio/sample/sample.ts index 1287e78d64c..25e112adfde 100644 --- a/audio/sample/sample.ts +++ b/audio/sample/sample.ts @@ -3,7 +3,7 @@ namespace $ { @ $mol_mem override node() { return this.context().createBufferSource() } - duration() { + override duration() { return this.audio_buffer().duration * 1000 } diff --git a/audio/scheduled/scheduled.ts b/audio/scheduled/scheduled.ts index 19afa500d45..06a38d087a0 100644 --- a/audio/scheduled/scheduled.ts +++ b/audio/scheduled/scheduled.ts @@ -5,6 +5,10 @@ namespace $ { throw new Error('implement') } + duration() { + return 1000 + } + @ $mol_mem node_configured() { return this.node() diff --git a/audio/vibe/vibe.ts b/audio/vibe/vibe.ts index 00f13f9cf60..22cb2f1f430 100644 --- a/audio/vibe/vibe.ts +++ b/audio/vibe/vibe.ts @@ -14,7 +14,7 @@ namespace $ { @ $mol_mem override node() { return this.context().createOscillator() } - + @ $mol_mem freq( next = 440 ) { return next } From 1945903ca466284ea1394c35aa85ec6ba55ec56f Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 19:54:48 +0300 Subject: [PATCH 03/13] $mol_audio_scheduled fixes 1 --- audio/context/context.node.ts | 13 ++++++------ audio/context/context.ts | 6 +++++- audio/context/context.web.ts | 8 +++++++- audio/gain/gain.ts | 4 ++-- .../scheduled.ts => instrument/instrument.ts} | 20 ++++++++++--------- audio/node/node.ts | 14 ++++++++----- audio/room/room.ts | 2 +- audio/sample/sample.ts | 12 +++++------ audio/vibe/vibe.ts | 8 ++++---- 9 files changed, 52 insertions(+), 35 deletions(-) rename audio/{scheduled/scheduled.ts => instrument/instrument.ts} (74%) diff --git a/audio/context/context.node.ts b/audio/context/context.node.ts index 8f7501917be..eed40341192 100644 --- a/audio/context/context.node.ts +++ b/audio/context/context.node.ts @@ -1,12 +1,13 @@ namespace $ { - // const api = require('web-audio-api') as { AudioContext: new() => AudioContext } - // export const $mol_audio_context_node = new api.AudioContext() - export const $mol_audio_context_node = new Proxy({} as AudioContext, { - get() { - throw new Error('Not implemented') + export class $mol_audio_context_node extends $mol_audio_context { + + @ $mol_memo.method + static override context() { + const AudioContext = this.$.$mol_dom_context.AudioContext || this.$.$node['web-audio-api'].AudioContext + return new AudioContext() } - }) + } $.$mol_audio_context = $mol_audio_context_node } diff --git a/audio/context/context.ts b/audio/context/context.ts index 625eccc49f9..e25bdc66292 100644 --- a/audio/context/context.ts +++ b/audio/context/context.ts @@ -1,3 +1,7 @@ namespace $ { - export let $mol_audio_context = undefined as unknown as AudioContext + export class $mol_audio_context extends $mol_object2 { + static context(): AudioContext { + throw new Error('implement') + } + } } diff --git a/audio/context/context.web.ts b/audio/context/context.web.ts index fb9742f5bfa..98ce70c756a 100644 --- a/audio/context/context.web.ts +++ b/audio/context/context.web.ts @@ -1,5 +1,11 @@ namespace $ { - export const $mol_audio_context_web = new AudioContext() + export class $mol_audio_context_web extends $mol_audio_context { + + @ $mol_memo.method + static override context() { + return new this.$.$mol_dom_context.AudioContext() + } + } $.$mol_audio_context = $mol_audio_context_web } diff --git a/audio/gain/gain.ts b/audio/gain/gain.ts index 7db9f17c278..6e18e14a163 100644 --- a/audio/gain/gain.ts +++ b/audio/gain/gain.ts @@ -3,14 +3,14 @@ namespace $ { export class $mol_audio_gain extends $mol_audio_node { @ $mol_mem - node() { return this.context().createGain() } + node_raw() { return this.context().createGain() } @ $mol_mem gain( next = 1 ) { return next } @ $mol_mem output() { - this.node().gain.setValueAtTime( this.gain(), this.time() ) + this.node_raw().gain.setValueAtTime( this.gain(), this.time() ) return super.output() } diff --git a/audio/scheduled/scheduled.ts b/audio/instrument/instrument.ts similarity index 74% rename from audio/scheduled/scheduled.ts rename to audio/instrument/instrument.ts index 06a38d087a0..ddf96d01952 100644 --- a/audio/scheduled/scheduled.ts +++ b/audio/instrument/instrument.ts @@ -1,17 +1,15 @@ namespace $ { - export class $mol_audio_scheduled extends $mol_audio_node { - @ $mol_mem - override node(): AudioScheduledSourceNode { + export class $mol_audio_instrument extends $mol_audio_node { + override node_raw(): AudioScheduledSourceNode { throw new Error('implement') } - duration() { - return 1000 + override node() { + return this.node_raw() } - @ $mol_mem - node_configured() { - return this.node() + duration() { + return 1 } promise = $mol_promise() @@ -21,12 +19,16 @@ namespace $ { return this.promise } + end() { + this.active( false ) + } + @ $mol_mem active( next?: boolean ): boolean { $mol_wire_solid() - const node = this.node_configured() + const node = this.node() const prev = $mol_wire_probe( ()=> this.active() ) if( prev === next ) return next ?? false diff --git a/audio/node/node.ts b/audio/node/node.ts index 55ae9e2af94..56a7c38447f 100644 --- a/audio/node/node.ts +++ b/audio/node/node.ts @@ -1,9 +1,13 @@ namespace $ { export class $mol_audio_node extends $mol_object2 { - context() { return this.$.$mol_audio_context } + context() { return this.$.$mol_audio_context.context() } @ $mol_mem - node() { return this.context().destination as AudioNode } + node_raw() { return this.context().destination as AudioNode } + + node() { + return this.node_raw() + } @ $mol_mem input( next = [] as readonly $mol_audio_node[] ) { return next } @@ -11,7 +15,7 @@ namespace $ { @ $mol_mem input_connected() { - const node = this.node() + const node = this.node_raw() const prev = $mol_mem_cached( ()=> this.input_connected() ) ?? [] const next = this.input() @@ -31,14 +35,14 @@ namespace $ { @ $mol_mem output() { this.input_connected() - return this.node() + return this.node_raw() } time() { return this.context().currentTime } destructor() { - const node = this.node() + const node = this.node_raw() for( const src of this.input() ) { src.output().disconnect( node ) diff --git a/audio/room/room.ts b/audio/room/room.ts index 1a258518b6e..b9d45d2aead 100644 --- a/audio/room/room.ts +++ b/audio/room/room.ts @@ -13,7 +13,7 @@ namespace $ { let duration = 0 for (const input of this.input_connected()) { if (input instanceof $mol_audio_room) duration += input.duration() - if (input instanceof $mol_audio_scheduled) duration += input.duration() + if (input instanceof $mol_audio_instrument) duration += input.duration() } return duration || this.duration_default() } diff --git a/audio/sample/sample.ts b/audio/sample/sample.ts index 25e112adfde..e4288ac0245 100644 --- a/audio/sample/sample.ts +++ b/audio/sample/sample.ts @@ -1,10 +1,10 @@ namespace $ { - export class $mol_audio_sample extends $mol_audio_scheduled { + export class $mol_audio_sample extends $mol_audio_instrument { @ $mol_mem - override node() { return this.context().createBufferSource() } + override node_raw() { return this.context().createBufferSource() } override duration() { - return this.audio_buffer().duration * 1000 + return this.audio_buffer().duration } buffer() { @@ -17,10 +17,10 @@ namespace $ { } @ $mol_mem - override node_configured() { - const node = this.node() + override node() { + const node = this.node_raw() node.buffer = this.audio_buffer() - node.onended = $mol_wire_async(() => this.active(false)) + node.onended = $mol_wire_async(() => this.end()) return node } diff --git a/audio/vibe/vibe.ts b/audio/vibe/vibe.ts index 22cb2f1f430..726bd7e543c 100644 --- a/audio/vibe/vibe.ts +++ b/audio/vibe/vibe.ts @@ -10,10 +10,10 @@ namespace $ { /** * @see https://mol.hyoo.ru/#!section=demos/demo=mol_audio_demo_vibe */ - export class $mol_audio_vibe extends $mol_audio_scheduled { + export class $mol_audio_vibe extends $mol_audio_instrument { @ $mol_mem - override node() { return this.context().createOscillator() } + override node_raw() { return this.context().createOscillator() } @ $mol_mem freq( next = 440 ) { return next } @@ -22,8 +22,8 @@ namespace $ { shape( next: $mol_audio_vibe_shape = 'sine' ) { return next } @ $mol_mem - override node_configured(): AudioScheduledSourceNode { - const node = this.node() + override node() { + const node = this.node_raw() node.frequency.setValueAtTime( this.freq(), this.time() ) node.type = this.shape() From dd83f2d9ce417257fb2c88a640c7f65677e20a12 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 20:07:24 +0300 Subject: [PATCH 04/13] $mol_audio_scheduled fixes 2 --- audio/context/context.ts | 5 +++-- audio/context/context.web.ts | 11 ----------- audio/demo/vibe/vibe.view.tree | 6 +++--- audio/gain/gain.ts | 17 +++++++++-------- audio/instrument/instrument.ts | 6 +++++- audio/node/node.ts | 2 +- audio/room/room.ts | 3 +-- audio/sample/sample.ts | 3 +-- audio/vibe/vibe.ts | 2 +- 9 files changed, 24 insertions(+), 31 deletions(-) delete mode 100644 audio/context/context.web.ts diff --git a/audio/context/context.ts b/audio/context/context.ts index e25bdc66292..4697db74358 100644 --- a/audio/context/context.ts +++ b/audio/context/context.ts @@ -1,7 +1,8 @@ namespace $ { export class $mol_audio_context extends $mol_object2 { - static context(): AudioContext { - throw new Error('implement') + @ $mol_memo.method + static context() { + return new this.$.$mol_dom_context.AudioContext() } } } diff --git a/audio/context/context.web.ts b/audio/context/context.web.ts deleted file mode 100644 index 98ce70c756a..00000000000 --- a/audio/context/context.web.ts +++ /dev/null @@ -1,11 +0,0 @@ -namespace $ { - export class $mol_audio_context_web extends $mol_audio_context { - - @ $mol_memo.method - static override context() { - return new this.$.$mol_dom_context.AudioContext() - } - } - - $.$mol_audio_context = $mol_audio_context_web -} diff --git a/audio/demo/vibe/vibe.view.tree b/audio/demo/vibe/vibe.view.tree index 2676dbc9c1f..b5c61b02226 100644 --- a/audio/demo/vibe/vibe.view.tree +++ b/audio/demo/vibe/vibe.view.tree @@ -10,11 +10,11 @@ $mol_audio_demo_vibe $mol_example_small sub / <= List $mol_list rows / <= Duration $mol_labeler - title <= duration_label \Duration, ms + title <= duration_label \Duration, s content / <= Duration_num $mol_number - precision_change 50 - value? <=> duration? 500 + precision_change 0.05 + value? <=> duration? 0.5 <= Frequency $mol_labeler title <= frequency_label \Frequency, Hz content / diff --git a/audio/gain/gain.ts b/audio/gain/gain.ts index 6e18e14a163..63c74ffa860 100644 --- a/audio/gain/gain.ts +++ b/audio/gain/gain.ts @@ -3,16 +3,17 @@ namespace $ { export class $mol_audio_gain extends $mol_audio_node { @ $mol_mem - node_raw() { return this.context().createGain() } - - @ $mol_mem - gain( next = 1 ) { return next } - + override node_raw() { return this.context().createGain() } + @ $mol_mem - output() { - this.node_raw().gain.setValueAtTime( this.gain(), this.time() ) - return super.output() + override node() { + const node = super.node() + node.gain.setValueAtTime( this.gain(), this.time() ) + return node } + + @ $mol_mem + gain( next = 1 ) { return next } } diff --git a/audio/instrument/instrument.ts b/audio/instrument/instrument.ts index ddf96d01952..5db663f49d7 100644 --- a/audio/instrument/instrument.ts +++ b/audio/instrument/instrument.ts @@ -4,8 +4,12 @@ namespace $ { throw new Error('implement') } + @ $mol_mem override node() { - return this.node_raw() + const node = super.node() + node.onended = $mol_wire_async(() => this.end()) + + return node } duration() { diff --git a/audio/node/node.ts b/audio/node/node.ts index 56a7c38447f..5177ca1d2b9 100644 --- a/audio/node/node.ts +++ b/audio/node/node.ts @@ -6,7 +6,7 @@ namespace $ { node_raw() { return this.context().destination as AudioNode } node() { - return this.node_raw() + return this.node_raw() as ReturnType } @ $mol_mem diff --git a/audio/room/room.ts b/audio/room/room.ts index b9d45d2aead..f1b52b43e72 100644 --- a/audio/room/room.ts +++ b/audio/room/room.ts @@ -6,13 +6,12 @@ namespace $ { export class $mol_audio_room extends $mol_audio_node { duration_default() { - return 1000 + return .5 } duration() { let duration = 0 for (const input of this.input_connected()) { - if (input instanceof $mol_audio_room) duration += input.duration() if (input instanceof $mol_audio_instrument) duration += input.duration() } return duration || this.duration_default() diff --git a/audio/sample/sample.ts b/audio/sample/sample.ts index e4288ac0245..738d12d686b 100644 --- a/audio/sample/sample.ts +++ b/audio/sample/sample.ts @@ -18,9 +18,8 @@ namespace $ { @ $mol_mem override node() { - const node = this.node_raw() + const node = super.node() node.buffer = this.audio_buffer() - node.onended = $mol_wire_async(() => this.end()) return node } diff --git a/audio/vibe/vibe.ts b/audio/vibe/vibe.ts index 726bd7e543c..65d1f870cda 100644 --- a/audio/vibe/vibe.ts +++ b/audio/vibe/vibe.ts @@ -23,7 +23,7 @@ namespace $ { @ $mol_mem override node() { - const node = this.node_raw() + const node = super.node() node.frequency.setValueAtTime( this.freq(), this.time() ) node.type = this.shape() From 8ac790b7ec960040ea60ffe0f9f59e4e93727537 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 20:19:19 +0300 Subject: [PATCH 05/13] $mol_audio_scheduled duration fix --- audio/demo/demo.view.tree | 4 ++-- audio/room/room.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/audio/demo/demo.view.tree b/audio/demo/demo.view.tree index 8b59d4f17ce..4392e60fc89 100644 --- a/audio/demo/demo.view.tree +++ b/audio/demo/demo.view.tree @@ -2,13 +2,13 @@ $mol_audio_demo $mol_example_small title \WebAudio API example Beep $mol_audio_room play => beep_play - duration 100 + duration .1 input / <= Beep_vibe $mol_audio_vibe freq 440 Noise $mol_audio_room play => noise_play - duration 1000 + duration 1 input / <= Noise_vibe $mol_audio_vibe freq <= noise_freq 440 diff --git a/audio/room/room.ts b/audio/room/room.ts index f1b52b43e72..cda410f3d6b 100644 --- a/audio/room/room.ts +++ b/audio/room/room.ts @@ -20,7 +20,7 @@ namespace $ { @ $mol_action play() { this.output() - this.$.$mol_wait_timeout( this.duration() ) + this.$.$mol_wait_timeout( this.duration() * 1000 ) } } From 10aa7cc7d5cb3cf192282fc791006f6009c881f5 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 20:22:34 +0300 Subject: [PATCH 06/13] $mol_audio_scheduled duration fix 2 --- audio/demo/demo.view.tree | 2 +- audio/instrument/instrument.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/audio/demo/demo.view.tree b/audio/demo/demo.view.tree index 4392e60fc89..47f86c0f1c0 100644 --- a/audio/demo/demo.view.tree +++ b/audio/demo/demo.view.tree @@ -2,7 +2,7 @@ $mol_audio_demo $mol_example_small title \WebAudio API example Beep $mol_audio_room play => beep_play - duration .1 + duration 0.1 input / <= Beep_vibe $mol_audio_vibe freq 440 diff --git a/audio/instrument/instrument.ts b/audio/instrument/instrument.ts index 5db663f49d7..2397e664bdb 100644 --- a/audio/instrument/instrument.ts +++ b/audio/instrument/instrument.ts @@ -32,7 +32,7 @@ namespace $ { $mol_wire_solid() - const node = this.node() + const node = next === false ? this.node_raw() : this.node() const prev = $mol_wire_probe( ()=> this.active() ) if( prev === next ) return next ?? false From 25aad23916b7407563e67bc81ed249049cff1bf8 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 21:03:47 +0300 Subject: [PATCH 07/13] $mol_audio_room duration mem --- audio/demo/vibe/vibe.view.tree | 2 +- audio/instrument/instrument.ts | 2 +- audio/room/room.ts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/audio/demo/vibe/vibe.view.tree b/audio/demo/vibe/vibe.view.tree index b5c61b02226..2e0232df7db 100644 --- a/audio/demo/vibe/vibe.view.tree +++ b/audio/demo/vibe/vibe.view.tree @@ -28,7 +28,7 @@ $mol_audio_demo_vibe $mol_example_small Filter null value? <=> shape? null options /$mol_audio_vibe_shape - \sine + \sine \square \sawtooth \triangle diff --git a/audio/instrument/instrument.ts b/audio/instrument/instrument.ts index 2397e664bdb..2bb7a6fab36 100644 --- a/audio/instrument/instrument.ts +++ b/audio/instrument/instrument.ts @@ -16,7 +16,7 @@ namespace $ { return 1 } - promise = $mol_promise() + protected promise = $mol_promise() @ $mol_mem wait() { diff --git a/audio/room/room.ts b/audio/room/room.ts index cda410f3d6b..5cc3c2819e5 100644 --- a/audio/room/room.ts +++ b/audio/room/room.ts @@ -9,6 +9,7 @@ namespace $ { return .5 } + @ $mol_mem duration() { let duration = 0 for (const input of this.input_connected()) { From af0de3d3a53a73492b223fbc6b92caa25b400224 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 21:26:37 +0300 Subject: [PATCH 08/13] $mol_audio_room duration moved to $mol_audio_node --- audio/instrument/instrument.ts | 8 ++------ audio/node/node.ts | 9 +++++++++ audio/room/room.ts | 13 ------------- audio/vibe/vibe.ts | 4 ++++ 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/audio/instrument/instrument.ts b/audio/instrument/instrument.ts index 2bb7a6fab36..621fd7c6160 100644 --- a/audio/instrument/instrument.ts +++ b/audio/instrument/instrument.ts @@ -7,15 +7,11 @@ namespace $ { @ $mol_mem override node() { const node = super.node() - node.onended = $mol_wire_async(() => this.end()) + node.onended = $mol_wire_async((e: Event) => this.end(e)) return node } - duration() { - return 1 - } - protected promise = $mol_promise() @ $mol_mem @@ -23,7 +19,7 @@ namespace $ { return this.promise } - end() { + end(e: Event) { this.active( false ) } diff --git a/audio/node/node.ts b/audio/node/node.ts index 5177ca1d2b9..9ad6e3de567 100644 --- a/audio/node/node.ts +++ b/audio/node/node.ts @@ -9,6 +9,15 @@ namespace $ { return this.node_raw() as ReturnType } + @ $mol_mem + duration() { + let duration = 0 + for (const input of this.input_connected()) duration = Math.max(duration, input.duration()) + + return duration + } + + @ $mol_mem input( next = [] as readonly $mol_audio_node[] ) { return next } diff --git a/audio/room/room.ts b/audio/room/room.ts index 5cc3c2819e5..4684f6ece70 100644 --- a/audio/room/room.ts +++ b/audio/room/room.ts @@ -5,19 +5,6 @@ namespace $ { */ export class $mol_audio_room extends $mol_audio_node { - duration_default() { - return .5 - } - - @ $mol_mem - duration() { - let duration = 0 - for (const input of this.input_connected()) { - if (input instanceof $mol_audio_instrument) duration += input.duration() - } - return duration || this.duration_default() - } - @ $mol_action play() { this.output() diff --git a/audio/vibe/vibe.ts b/audio/vibe/vibe.ts index 65d1f870cda..e7ac418568f 100644 --- a/audio/vibe/vibe.ts +++ b/audio/vibe/vibe.ts @@ -21,6 +21,10 @@ namespace $ { @ $mol_mem shape( next: $mol_audio_vibe_shape = 'sine' ) { return next } + override duration() { + return 0.5 + } + @ $mol_mem override node() { const node = super.node() From e711ead3cb2c99e9e62e73e8b02ed9924bc18a2a Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 22:22:39 +0300 Subject: [PATCH 09/13] $mol_audio_context added speaker for node --- audio/context/context.node.ts | 26 ++++++++++++++++++++++++-- audio/context/context.ts | 6 +++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/audio/context/context.node.ts b/audio/context/context.node.ts index eed40341192..63890269537 100644 --- a/audio/context/context.node.ts +++ b/audio/context/context.node.ts @@ -1,11 +1,33 @@ namespace $ { + type AudioContextNode = { + outStream?: InstanceType | null + format: { + numberOfChannels: number + bitDepth: number + } + } + export class $mol_audio_context_node extends $mol_audio_context { + static override create_context(): AudioContext & AudioContextNode { + const AudioContext = this.$.$node['web-audio-api'].AudioContext + return new AudioContext() + } + @ $mol_memo.method static override context() { - const AudioContext = this.$.$mol_dom_context.AudioContext || this.$.$node['web-audio-api'].AudioContext - return new AudioContext() + const context = this.create_context() + + const Speaker = this.$.$node['speaker'] + + context.outStream = new Speaker({ + channels: context.format.numberOfChannels, + bitDepth: context.format.bitDepth, + sampleRate: context.sampleRate + }) + + return context } } diff --git a/audio/context/context.ts b/audio/context/context.ts index 4697db74358..d74944de55c 100644 --- a/audio/context/context.ts +++ b/audio/context/context.ts @@ -1,8 +1,12 @@ namespace $ { export class $mol_audio_context extends $mol_object2 { + static create_context() { + return new this.$.$mol_dom_context.AudioContext() + } + @ $mol_memo.method static context() { - return new this.$.$mol_dom_context.AudioContext() + return this.create_context() } } } From ff2c04a80b12d2b99af92c2e1733433aa65631e9 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 22:33:30 +0300 Subject: [PATCH 10/13] $mol_audio_context moved to process.stdout for node --- audio/context/context.node.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/audio/context/context.node.ts b/audio/context/context.node.ts index 63890269537..f4baf8ab034 100644 --- a/audio/context/context.node.ts +++ b/audio/context/context.node.ts @@ -18,14 +18,14 @@ namespace $ { @ $mol_memo.method static override context() { const context = this.create_context() - - const Speaker = this.$.$node['speaker'] - - context.outStream = new Speaker({ - channels: context.format.numberOfChannels, - bitDepth: context.format.bitDepth, - sampleRate: context.sampleRate - }) + context.outStream = process.stdout + + // const Speaker = this.$.$node.speaker + // context.outStream = new Speaker({ + // channels: context.format.numberOfChannels, + // bitDepth: context.format.bitDepth, + // sampleRate: context.sampleRate + // }) return context } From 6fa0b7ee154e129d18f69d2df7ffdf16ddd05a69 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Fri, 29 Dec 2023 23:48:55 +0300 Subject: [PATCH 11/13] $mol_audio_context null stdout for node --- audio/context/context.node.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/audio/context/context.node.ts b/audio/context/context.node.ts index f4baf8ab034..f9d16ee18a2 100644 --- a/audio/context/context.node.ts +++ b/audio/context/context.node.ts @@ -1,7 +1,7 @@ namespace $ { type AudioContextNode = { - outStream?: InstanceType | null + outStream?: NodeJS.WriteStream | null format: { numberOfChannels: number bitDepth: number @@ -18,7 +18,6 @@ namespace $ { @ $mol_memo.method static override context() { const context = this.create_context() - context.outStream = process.stdout // const Speaker = this.$.$node.speaker // context.outStream = new Speaker({ From 27bf8ce3f81bca1e82f0cd8dfe9a68421bf2dada Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Sat, 30 Dec 2023 00:37:41 +0300 Subject: [PATCH 12/13] $mol_audio_context removed node version --- audio/context/context.node.ts | 34 ---------------------------------- audio/context/context.ts | 6 +----- 2 files changed, 1 insertion(+), 39 deletions(-) delete mode 100644 audio/context/context.node.ts diff --git a/audio/context/context.node.ts b/audio/context/context.node.ts deleted file mode 100644 index f9d16ee18a2..00000000000 --- a/audio/context/context.node.ts +++ /dev/null @@ -1,34 +0,0 @@ -namespace $ { - - type AudioContextNode = { - outStream?: NodeJS.WriteStream | null - format: { - numberOfChannels: number - bitDepth: number - } - } - - export class $mol_audio_context_node extends $mol_audio_context { - - static override create_context(): AudioContext & AudioContextNode { - const AudioContext = this.$.$node['web-audio-api'].AudioContext - return new AudioContext() - } - - @ $mol_memo.method - static override context() { - const context = this.create_context() - - // const Speaker = this.$.$node.speaker - // context.outStream = new Speaker({ - // channels: context.format.numberOfChannels, - // bitDepth: context.format.bitDepth, - // sampleRate: context.sampleRate - // }) - - return context - } - } - - $.$mol_audio_context = $mol_audio_context_node -} diff --git a/audio/context/context.ts b/audio/context/context.ts index d74944de55c..ffc68e51902 100644 --- a/audio/context/context.ts +++ b/audio/context/context.ts @@ -1,12 +1,8 @@ namespace $ { export class $mol_audio_context extends $mol_object2 { - static create_context() { - return new this.$.$mol_dom_context.AudioContext() - } - @ $mol_memo.method static context() { - return this.create_context() + return new this.$.$mol_dom_context.AudioContext() || this.$.$node['web-audio-api'].AudioContext } } } From fc89ecd43747dbcbf8ec1c10d6ab7b09e752e2c8 Mon Sep 17 00:00:00 2001 From: Sergey Yuferev Date: Sat, 30 Dec 2023 00:41:43 +0300 Subject: [PATCH 13/13] $mol_audio_context fix AudioContext --- audio/context/context.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/audio/context/context.ts b/audio/context/context.ts index ffc68e51902..48a79244ba8 100644 --- a/audio/context/context.ts +++ b/audio/context/context.ts @@ -2,7 +2,8 @@ namespace $ { export class $mol_audio_context extends $mol_object2 { @ $mol_memo.method static context() { - return new this.$.$mol_dom_context.AudioContext() || this.$.$node['web-audio-api'].AudioContext + const AudioContext = this.$.$mol_dom_context.AudioContext || this.$.$node['web-audio-api'].AudioContext + return new AudioContext() } } }