4
votes

Everywhere I look suggests that 5.1/surround support should be in the modern Web Audio API, but nothing I do gets it working on either Firefox 40 or Chrome (not sure of the Chrome version but it should be recent/the latest, and the fact that it doesn't work in either browser suggests to me that it isn't a Chrome-specific issue.)

My setup

Creative Sound Blaster Omni 5.1 hooked into a typical 5.1 set of Desktop speakers. Windows 10. I can successfully play MP4 audio through surround channels. Similarly, DirectX-based surround sound games appear to work.

What I'm attempting

Writing a Crafty-based JS game, primarily developing on Firefox. I currently have a small 2-D world with a line of panner nodes playing breaking surf near the lower end. In stereo I can move around this world and hear the breakers change position as I turn and move. With my 5.1 speakers connected, nothing changes. That is, the behavior is just as it is in stereo despite me experiencing surround sound in other situations.

audioContext.destination.maxChannelCount is 6, so it seems like Firefox correctly detects my channels. I've tried explicitly setting channelCount on everything I can, and this works without error except on panners, which gives an "Operation not supported" error. I wonder if this might be my problem, but I don't know why it would work everywhere else, so I'm wondering if perhaps I'm being overzealous in assigning channels.

Anyhow, here are bits of my Crafty components for initializing sound. They're in LiveScript but should hopefully be easy to follow:

_initContext: ->
  return @_context if @_context?
  audioContext = window.AudioContext||window.webkitAudioContext
  if audioContext?
    @_context = new audioContext()
    @_context.destination.channelCount = if@_context.destination.maxChannelCount >= 6
      6
    else
      2
    @_context.destination.channelCountMode = "explicit"
    @_masterGain = @_context.createGain()
    @_masterGain.channelCount = @_context.destination.channelCount
    @_masterGain.channelCountMode = "explicit"
    @_masterGain.connect(@_context.destination)
    @_context
...
context = Crafty.sound._initContext()
return unless context?
@_gain = context.createGain()
@_gain.channelCount = context.destination.channelCount
@_gain.channelCountMode = "explicit"
@_gain.connect(Crafty.sound._masterGain)
@_panner = context.createPanner()
@_panner.channelCount = context.destination.channelCount # Fails
@_panner.connect(@_gain)

Thanks for any help.

1
Is the language of your sample JavaScript, or one of the web-intermediate languages like Coffeescript? Not sure knowing will help the answer, just curious.Katana314
@Katana314 OP mentions it's written in Livescript.Evert

1 Answers

2
votes

Figured it out. Looks like PannerNode is limited to stereo output, which is confusing given all the 3-D/spatial functionality in this API. It was also non-obvious that PannerNode's 2-channel restriction would result in only 2 channels at the destination (I.e. maybe it somehow handles up to 2 channels per source but positions them in the 6 channels I'd assigned at the destination.) Apparently it's possible to output multiple channels, but not with these interfaces. Maybe with a custom API...

How disenchanting.