Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tighten spec on ABSN output channels? #1481

Closed
rtoy opened this issue Feb 2, 2018 · 5 comments
Closed

Tighten spec on ABSN output channels? #1481

rtoy opened this issue Feb 2, 2018 · 5 comments
Milestone

Comments

@rtoy
Copy link
Member

rtoy commented Feb 2, 2018

This is follow up from #1471 (comment).

I think the proposal there is that ABSNs output exactly one channel of silence until the buffer starts playing and when the buffer stops playing (if ever), the node produces again a single channel of silence.

The difficulty with this is if the ABSN is scheduled to start in the middle of a render quantum. It seems impossible to change the channel counts at that point, so the count has to happen at the render quantum before or after the the start time. Stopping the source has exactly the same problem.

I think Chrome sets the output channel count when the AudioBuffer is assigned.

@karlt
Copy link
Contributor

karlt commented Feb 4, 2018

The following example demonstrates that Chrome does set the output channel count when the AudioBuffer is assigned, but resets to mono (or zero channels) when the ABSN stops.

I wouldn't argue that the spec should be changed just to enshrine implementation bugs in perpetuity, but this may be useful for avoiding unnecessary up-mixing when ABSNs with large numbers of channels are not playing and not explicitly disconnected. The same benefit would exist before and after the ABSN is playing.


  // The splitter should have channelCount 2, channelCountMode explicit, and
  // channelInterpretation discrete.
  var splitter = context.createChannelSplitter(2);
  splitter.connect(context.destination, 1);

  // Work around unexpected up-mixing in Chrome's splitter.
  var discrete_gain = context.createGain();
  discrete_gain.channelCount = 2;
  discrete_gain.channelCountMode = "explicit";
  discrete_gain.channelInterpretation = "discrete";
  discrete_gain.connect(splitter);

  // The gain will have channelCountMode max, and channelInterpretation
  // speakers.
  var gain = context.createGain();
  gain.connect(discrete_gain);

  // Oscillators have 1 channel.  Connecting only the oscillator will produce
  // only 1 channel of output from the gain.  discrete up-mixing at the
  // splitter will produce no sound in the additional channel, and so there
  // would be no sound in output 1 of the splitter (for the destination).
  var osc = context.createOscillator();
  osc.start(0);
  osc.connect(gain);

  // But connecting a (silent) stereo input to the splitter will cause the
  // mono oscillator signal to be up-mixed using speaker interpretation at the
  // gain (as long as the source is producing 2 channels of output).  The
  // oscillator signal is then in both channels.
  //
  // The buffer plays for 1 second, starting at 2 seconds.
  var buffer = context.createBuffer(2, context.sampleRate, context.sampleRate);
  // Work around Gecko null buffers having zero channels.
  buffer.getChannelData(0)[0] = 0.0;

  var source = context.createBufferSource();
  source.buffer = buffer;
  source.connect(gain);
  source.start(2);

@rtoy
Copy link
Member Author

rtoy commented Feb 6, 2018

Thanks for the nice test code!

Since it appears the GC observability issue is gone, perhaps there's nothing that needs to be done here. It's an optimization for the browser to do if desired?

@mdjp mdjp added this to the Web Audio V1 milestone Feb 8, 2018
@karlt
Copy link
Contributor

karlt commented Feb 8, 2018

I suggest leaving this open as an option at least until the solution to
#1471 is clear and complete.

The spec is currently clear that that ABSN always and indefinitely
has output channel count matching the buffer channel count, and so, if we are
happy with that, then there is nothing that need be done here.

With this behavior, I don't see much optimization possible for multiple identical
channels to AudioWorklet, but I don't see that a problem either.

Still, this is an option to resolve some of the optimization concerns people
had with solution of #1471,
and so let's leave it for consideration, at least until we know exactly what
that solution is.

@rtoy rtoy added this to To Do in V1 Feb 27, 2018
@rtoy
Copy link
Member Author

rtoy commented May 21, 2018

I think, as an optimization, that when stop() is called and the stop time has passed, the output of the ABSN is a single channel of silence. This doesn't affect GC observability because it happens when stop() stops the source, not because GC occurred.

@karlt
Copy link
Contributor

karlt commented Oct 3, 2018

An ABSN that has a buffer, but for which start() has not been called, would
benefit from a single channel of silence in the same way as an ABSN that has
completed, both in terms of fewer channels to process downstream and because
it makes it easier for an implementation to garbage collect the resources
associated with the node (without any need to keep the effects of
multiple channels on downstream nodes).

@hoch hoch closed this as completed in 86bb206 Oct 19, 2018
hoch added a commit that referenced this issue Oct 19, 2018
Fix #1481: ABSN outputs mono silence when stopped
V1 automation moved this from To Do to Done Oct 19, 2018
rtoy added a commit to rtoy/web-audio-api that referenced this issue Jan 17, 2019
Specify that when an ABSN is done playing the number of channels in
the output is one, instead of the number of channels in the
`AudioBuffer`.  Update the playback algorithm as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants