From 28937e1464355bce8a929f778f88855ea7b8992f Mon Sep 17 00:00:00 2001 From: Gabriel Brito Date: Fri, 5 Jun 2026 15:15:12 -0700 Subject: [PATCH 1/2] Initial draft --- index.bs | 103 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 17 deletions(-) diff --git a/index.bs b/index.bs index 2e5930f46..e7ae07d5b 100644 --- a/index.bs +++ b/index.bs @@ -2480,9 +2480,10 @@ returned promise with the rendered result as an interface OfflineAudioContext : BaseAudioContext { constructor(OfflineAudioContextOptions contextOptions); constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate); - Promise startRendering(); + Promise startRendering(unsigned long chunkSize); Promise resume(); Promise suspend(double suspendTime); + Promise close(); readonly attribute unsigned long length; attribute EventHandler oncomplete; }; @@ -2576,7 +2577,7 @@ Constructors
         numberOfChannels: Determines how many channels the buffer will have. See {{BaseAudioContext/createBuffer()}} for the supported number of channels.
-        length: Determines the size of the buffer in sample-frames.
+        length: Determines the total size of the audio render in sample-frames.
         sampleRate: Describes the sample-rate of the [=linear PCM=] audio data in the buffer in sample-frames per second. See [[#sample-rates]] for the required supported range.
         
@@ -2587,9 +2588,11 @@ Attributes
: length :: - The size of the buffer in sample-frames. This is the same as the + The total size of the audio render in sample-frames. This is the same as the value of the length parameter for the constructor. + For undefined-length rendering, this attribute SHOULD be set to positive infinity. + : oncomplete :: The event type of this event handler is complete. The event @@ -2601,7 +2604,7 @@ Attributes Methods
- : startRendering() + : startRendering(chunkSize) :: Given the current connections and scheduled changes, starts rendering audio. @@ -2620,21 +2623,29 @@ Methods
  1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=fully active=] then return [=a promise rejected with=] "{{InvalidStateError}}" {{DOMException}}. -
  2. If the {{[[rendering started]]}} slot on the - {{OfflineAudioContext}} is true, return a rejected - promise with {{InvalidStateError}}, and abort these - steps. -
  3. Set the {{[[rendering started]]}} slot of the {{OfflineAudioContext}} to true.
  4. Let promise be a new promise. +
  5. Let bufferLength be a number initialized to the value of {{OfflineAudioContext/length}}. + +
      +
    1. If {{OfflineAudioContext/startRendering(chunkSize)/chunkSize}} is provided: +
        +
      1. Let renderedFrames be the number of sample-frames already rendered by the {{OfflineAudioContext}}. +
      2. If renderedFrames + {{OfflineAudioContext/startRendering(chunkSize)/chunkSize}} <= {{OfflineAudioContext/length}}, set bufferLength to {{OfflineAudioContext/startRendering(chunkSize)/chunkSize}}. +
      3. Otherwise, set bufferLength to {{OfflineAudioContext/length}} - renderedFrames. +
      +
    2. Otherwise, if {{OfflineAudioContext/length}} is positive infinity, set bufferLength to the render quantum size. +
    +
  6. Create a new {{AudioBuffer}}, with a number of - channels, length and sample rate equal respectively to the - numberOfChannels, length and + channels and sample rate equal respectively to the + numberOfChannels and sampleRate values passed to this instance's - constructor in the contextOptions parameter. + constructor in the contextOptions parameter; + and length equal to bufferLength. Assign this buffer to an internal slot [[rendered buffer]] in the {{OfflineAudioContext}}. @@ -2658,7 +2669,7 @@ Methods
    1. Given the current connections and scheduled changes, start - rendering length sample-frames of audio into + rendering {{[[rendered buffer/length]]}} sample-frames of audio into {{[[rendered buffer]]}}
    2. For every render quantum, check and @@ -2676,7 +2687,8 @@ Methods
    3. Resolve the promise created by {{startRendering()}} with {{[[rendered buffer]]}}. -
    4. [=Queue a media element task=] to [=fire an event=] named +
    5. If {{OfflineAudioContext/length}} is not positive infinity, + [=Queue a media element task=] to [=fire an event=] named {{OfflineAudioContext/complete}} at the {{OfflineAudioContext}} using {{OfflineAudioCompletionEvent}} whose `renderedBuffer` property is set to {{[[rendered buffer]]}}. @@ -2686,9 +2698,9 @@ Methods
    -
    - No parameters. -
    +
    +            chunkSize: The size of the desired {{AudioBuffer}}.
    +        
    Return type: {{Promise}}<{{AudioBuffer}}>
    @@ -2783,6 +2795,63 @@ Methods
    Return type: {{Promise}}<{{undefined}}>
    + + : close() + :: + Closes the {{AudioContext}}. This will not automatically release + all {{AudioContext}}-created objects, but will suspend the + progression of the {{AudioContext}}'s + {{BaseAudioContext/currentTime}}, and stop + processing audio data. + +
    + When close is called, execute these steps: + + 1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=fully active=] then return [=a promise rejected with=] "{{InvalidStateError}}" {{DOMException}}. + + 1. Let promise be a new Promise. + + 1. If the {{[[control thread state]]}} flag on the + {{OfflineAudioContext}} is closed reject the promise + with {{InvalidStateError}}, abort these steps, + returning promise. + + 1. Set the {{[[control thread state]]}} flag on the {{OfflineAudioContext}} to + closed. + + 1. Queue a control message to close the {{OfflineAudioContext}}. + + 1. Return promise. +
    + +
    + Running a control message to close an + {{OfflineAudioContext}} means running these steps on the + rendering thread: + + 1. Set the {{[[rendering thread state]]}} to suspended. +
    + This will stop rendering. +
    + + 1. If this control message is being run in a reaction to the + document being unloaded, abort this algorithm. +
    + There is no need to notify the control thread in this case. +
    + + 1. + queue a media element task to execute the following steps: + + 1. Resolve promise. + 1. If the {{BaseAudioContext/state}} attribute of the {{OfflineAudioContext}} is not already "{{AudioContextState/closed}}": + 1. Set the {{BaseAudioContext/state}} attribute of the {{OfflineAudioContext}} to "{{AudioContextState/closed}}". + + 1. + queue a media element task to fire + an event named {{BaseAudioContext/statechange}} at the {{OfflineAudioContext}}. +
    +

From d4834650c1db06d7bc1c79618ac13e6b3108e28c Mon Sep 17 00:00:00 2001 From: Gabriel Brito Date: Fri, 5 Jun 2026 15:37:04 -0700 Subject: [PATCH 2/2] Attempt to fix compile error --- index.bs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index e7ae07d5b..23f4c6362 100644 --- a/index.bs +++ b/index.bs @@ -2668,9 +2668,12 @@ Methods

occasion.
    +
  1. Let nFrames be a number initialized to the value + of the length of {{[[rendered buffer]]}}. +
  2. Given the current connections and scheduled changes, start - rendering {{[[rendered buffer/length]]}} sample-frames of audio into - {{[[rendered buffer]]}} + rendering nFrames sample-frames of audio into + {{[[rendered buffer]]}}.
  3. For every render quantum, check and {{OfflineAudioContext/suspend()|suspend}}