diff --git a/index.bs b/index.bs index 4375c7e6b..a3a10af15 100644 --- a/index.bs +++ b/index.bs @@ -717,7 +717,8 @@ for="BaseAudioContext">[[control thread state]] that take values from enum AudioContextState { "suspended", "running", - "closed" + "closed", + "interrupted" }; @@ -745,6 +746,12 @@ enum AudioContextState { This context has been released, and can no longer be used to process audio. All system audio resources have been released. + + + "interrupted" + + This context is currently interrupted and cannot process audio + until the [=interruption=] ends. @@ -1963,28 +1970,46 @@ Methods When resume 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. 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. - 2. If the {{[[control thread state]]}} on the + 1. If the {{[[control thread state]]}} on the {{AudioContext}} is closed reject the promise with {{InvalidStateError}}, abort these steps, returning promise. - 3. Set {{[[suspended by user]]}} to false. + 1. Set {{[[suspended by user]]}} to false. - 4. If the context is not allowed to start, append - promise to {{BaseAudioContext/[[pending promises]]}} and - {{AudioContext/[[pending resume promises]]}} and abort these steps, returning - promise. + 1. If the {{[[control thread state]]}} on the {{AudioContext}} is + suspended and there is an ongoing + [=interruption=]: - 5. Set the {{[[control thread state]]}} on the - {{AudioContext}} to running. + 1. Queue a media element task to execute the following steps: - 6. Queue a control message to resume the {{AudioContext}}. + 1. Set the {{BaseAudioContext/state}} attribute of the + {{AudioContext}} to "{{AudioContextState/interrupted}}". - 7. Return promise. + 1. [=Queue a media element task=] to [=fire an event=] named + {{BaseAudioContext/statechange}} at the {{AudioContext}}. + + 1. Reject the promise with {{InvalidStateError}}, abort these + steps, returning promise. + + 1. If the context is not allowed to start, append + promise to {{BaseAudioContext/[[pending promises]]}} + and {{AudioContext/[[pending resume promises]]}} and abort + these steps, returning promise. + + 1. Set the {{[[control thread state]]}} on the {{AudioContext}} to + running. + + 1. Queue a control message to resume the {{AudioContext}}. + + 1. Return promise.
@@ -4196,7 +4221,7 @@ Methods scheduled parameter changes with times greater than or equal to {{AudioParam/cancelAndHoldAtTime()/cancelTime!!argument}}. However, in addition, the automation value that would have happened at {{AudioParam/cancelAndHoldAtTime()/cancelTime!!argument}} is - then proprogated for all future time until other automation + then propagated for all future time until other automation events are introduced. The behavior of the timeline in the face of @@ -11662,7 +11687,7 @@ and a rendering thread. The control thread is the thread from which the {{AudioContext}} is instantiated, and from which authors -manipulate the audio graph, that is, from where the operation on a +manipulate the audio graph, that is, from where the operations on a {{BaseAudioContext}} are invoked. The rendering thread is the thread on which the actual audio output is computed, in reaction to the calls from the control thread. It can be a @@ -11769,7 +11794,7 @@ The algorithm for rendering a block of audio from a {{BaseAudioContext}} in the algorithm of rendering a graph. The {{AudioContext}} rendering thread is driven by a -system-level audio callback, that is periodically +system-level audio callback, that is periodically called at regular intevals. Each call has a system-level audio callback buffer size, which is a varying number of sample-frames that needs to be computed on time before the next system-level audio callback arrives. @@ -12089,6 +12114,102 @@ running the algorithm for an {{AudioNode}}, using an input buffer and the value(s) of the {{AudioParam}}(s) of this {{AudioNode}} as the input for this algorithm. +

Handling an interruption on the {{AudioContext}}

+ +An interruption is an event generated by the user agent when it needs +to halt audio playback for an {{AudioContext}}. For example, The user agent may +create an interruption when another application requests exclusive access to the +audio output hardware. + +When an [=interruption=] happens, the user agent must queue a control message +to interrupt the {{AudioContext}}. + +Running a control message to interrupt an {{AudioContext}} |context| +means running these steps on the rendering thread: + +1. If the |context|'s {{[[rendering thread state]]}} is closed + or interrupted: + + 1. Abort these steps. + +1. If the |context|'s {{[[rendering thread state]]}} is + running: + + 1. Attempt to release system resources. + + 1. [=Queue a media element task=] to execute the following steps: + + 1. Set the |context|'s {{[[control thread state]]}} to + interrupted. + + 1. [=Fire an event=] named {{BaseAudioContext/statechange}} at the + |context|. + +1. If the |context|'s {{[[rendering thread state]]}} is + suspended: + + 1. [=Queue a media element task=] to execute the following steps: + + 1. Set the |context|'s {{[[control thread state]]}} to + interrupted. + +1. Set the |context|'s {{[[rendering thread state]]}} to + interrupted. + +Note: If the {{AudioContext}} is suspended a +{{BaseAudioContext/statechange}} event is not fired for privacy reasons to avoid +over-sharing user activity - e.g. when a phone call comes in or when the screen +gets locked. + +When an [=interruption=] ends, the user agent must queue a control message +to end the +{{AudioContext}} interruption. + +Linear pulse code modulation + +Running a control message to end an {{AudioContext}} |context| +[=interruption=] means running these steps on the rendering thread: + +1. If the |context|'s {{[[rendering thread state]]}} is not + interrupted: + + 1. Abort these steps. + +1. If the |context|'s {{[[rendering thread state]]}} was + running before the [=interruption=] or if the the + |context|'s {{[[rendering thread state]]}} was suspended + and {{AudioContext/resume}} was called during the [=interruption=]: + + 1. Attempt to acquire system resources. + + 1. Set the {{[[rendering thread state]]}} on the {{AudioContext}} to + running. + + 1. Start rendering the audio graph. + + 1. [=Queue a media element task=] to execute the following steps: + + 1. If the {{BaseAudioContext/state}} attribute of the {{AudioContext}} + is not already "{{AudioContextState/running}}": + + 1. Set the |context|'s {{[[control thread state]]}} to + running. + + 1. [=Fire an event=] named {{BaseAudioContext/statechange}} at the + |context|. + +1. If the |context|'s {{[[rendering thread state]]}} was + suspended before the [=interruption=]: + + 1. Set the {{[[rendering thread state]]}} on the {{AudioContext}} to + suspended. + + 1. [=Queue a media element task=] to execute the following steps: + + 1. Set the |context|'s {{[[control thread state]]}} to + suspended. +

Handling an error from System Audio Resources on the {{AudioContext}}