MacOS Raw SpeakerMode Device?

How do I configure an output device in RAW speaker mode? I have output devices which have 24+ channels, but seem to be limited to the speaker configuration definitions in the “Audio MIDI Setup” tool (“Configure Speakers” - Stereo, 5.1, 7.1, etc.) How do I connect directly to the raw output channels?

The docs for fmod_speakermode_raw contain some relevant information.

FMOD_SPEAKERMODE_RAW
This mode is for output devices that are not specifically mono/stereo/quad/surround/5.1 or 7.1, but are multichannel.

  • Use System::setSoftwareFormat to specify the number of speakers you want to address, otherwise it will default to 2 (stereo).
  • Sound channels map to speakers sequentially, so a mono sound maps to output speaker 0, stereo sound maps to output speaker 0 & 1.
  • The user assumes knowledge of the speaker order. FMOD_SPEAKER enumerations may not apply, so raw channel indices should be used.
  • Multichannel sounds map input channels to output channels 1:1.
  • Speaker levels must be manually set with Channel::setMixMatrix.
  • Channel::setPan and Channel::setMixLevelsOutput do not work.

Thanks, that clarifies it a bit. My follow up question is: how do I remove the mono/stereo/quad/surround configuration to make it a “multichannel” device? This is probably a MacOS issue and not fmod, but it seems like fmod adheres to whatever speaker configuration is set. My 24 channel output is reported by fmod as mono/stereo/quad/surround, rather than the full 24 channels.

To clarify: I have called System::setSoftwareFormat(FMOD_SPEAKERMODE_RAW), but a follow up System::getSoftwareFormat returns a speakermode that is consistent with what has been configured in the Audio MIDI Setup tool. Is there a way to override this and get access to all of the outputs a device has to offer?

Are you checking the FMOD_RESULT of the setSoftwareFormat? It will tell you if it failed and why.
make sure it is being called before System::Init.

The call order was indeed the issue for setSoftwareFormat, but the overall behavior hasn’t improved. I am still only seeing output to the number of configured speakers in Audio MIDI Setup. What is more interesting is that the actual speaker numbers don’t seem to matter – the output always goes to the first X outputs, even if I remap one of the speaker numbers to some higher output.

For reference, here is the script I am testing (using pyfmodex for prototyping):

import pyfmodex as fmod

s = fmod.System()
format = s.software_format
format.raw_speakers = 24
format.speaker_mode = 1
s.software_format = format
s.driver = 1
s.init()

channel_group = s.create_channel_group("test")
matrix = [1] * (24 * 24)
channel_group.set_mix_matrix(matrix, 24, 24)

sound = s.create_sound("./media/jaguar.wav")
sound.mode = fmod.flags.MODE.LOOP_NORMAL
sound.play(channel_group)

And the net result is that the audio is output to the first X outputs. If I configured Stereo speakers, then the first two outputs are active. If I configure 5.1, then the first 6 outputs are active. Based on the mix_matrix, I would expect all 24 channels to be active.

At the channel level a mono sound is automatically panned to front left/right by default, so the other 22 channels are most likely going to be silence. You could try a 1x24 matrix on the channel, instead of the channelgroup.

That doesn’t seem to have any effect. But the channelgroup matrix is definitely working, to a degree. If I only set one output in the mix matrix, then only one channel will be active. Likewise, if I set three outputs in the mix matrix, then three outputs channels will be active.

The problem is that the number of output channels is always constrained by the Audio MIDI Setup speaker count. I have validated this by enabling all 24 outputs in the mix matrix and then changing the surround sound configuration and then restarting the script. Despite the same script and all 24 channels enabled, only the number of speakers enabled are active.

Hi,
You seem to be saying you’re not setting up your mac os speaker configuration properly, and that is the problem?

What is wrong with setting the audio midi setup speaker count to 24, if thats what coreaudio wants? You can’t output to speakers in the OS that are disabled.

Audio MIDI Setup only supports common speaker arrangements; I can’t specify an arbitrary number of speakers. However, high-end DAW applications (Pro Tools, Logic, etc.) are able to drive 24 outputs, which leads me to think that there is some way for software to bypass the speaker configuration. I assumed that fmod supported this based on the language around the System::setSoftwareFormat function, such as “numrawspeakers”.

Hi Matt,
We do have a ticket open about this actually, apparently yes, some DAWs on mac can basically overwrite the settings in the mac setup screen.
Can’t promise an immediate fix but we’re aware of that and will patch it for a future version.

Thanks for the clarification. I’m glad to hear it’s possible and on the roadmap.

I can add to this. In FMOD Ex, the “setHardwareChannels” call effecively overrode the Audio Midi setup (like other DAW applications) , but, in FMod 5 this call is no longer available. Older versions of my app work on multichannels as expected, but newer versions using FMOD 5 cannot address more channels than setup in Audio MIDI settings.

I have begun to try setting this myself by getting the Audio Unit handle from FMod and borrowing code from the Chromium project to set properties directly, but no luck yet.

If I knew how this worked before in setHardwareChannels, I could probably solve it!

setHardwareChannels was meant for platforms that had hardware voice support (ie ‘channels’. As far as I remember this was Xbox and Playstation type platforms.
There is no evidence that the mac platform used setHardwareChannels at all in FMOD Ex, it is just not referenced.

Maybe that call wasn’t the difference it seems. I haven’t been able to discover an init sequence that makes the current version behave the same as FMod Ex though. My testers report they cannot address more than 2 channels on some interfaces, but on others I’ve addressed 4 successfully. They are running the old and new side by side with the same audio midi setup to test, one after the other. Strange. I never had any prior code to manipulate the audio unit directly.

i will double check as fmod ex probably went through a few iterations with different output modes leading up to coreaudio.

Here is what I am trying:

    SoundSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_RAW, ap->settings->numMultichannels);

    SoundSystem->setDriver(ap->settings->selectedAudioDeviceNum );

    result = SoundSystem->init(60, FMOD_INIT_NORMAL, 0);


    static const AudioChannelLabel kCoreAudioChannelMapping[] = {
        kAudioChannelLabel_Discrete_0,
        kAudioChannelLabel_Discrete_1,
        kAudioChannelLabel_Discrete_2,
        kAudioChannelLabel_Discrete_3,
        kAudioChannelLabel_Discrete_4,
        kAudioChannelLabel_Discrete_5,
        kAudioChannelLabel_Discrete_6,
        kAudioChannelLabel_Discrete_7,
        kAudioChannelLabel_Discrete_8,
        kAudioChannelLabel_Discrete_9,
        kAudioChannelLabel_Discrete_10,
        kAudioChannelLabel_Discrete_11,
        kAudioChannelLabel_Discrete_12,
        kAudioChannelLabel_Discrete_13,
        kAudioChannelLabel_Discrete_14,
        kAudioChannelLabel_Discrete_15,
    };
    AudioUnit audioUnit;
    SoundSystem->getOutputHandle((void **)&audioUnit);
    const size_t layout_size =
    offsetof(AudioChannelLayout, mChannelDescriptions[ap->settings->numMultichannels]);
    std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[layout_size]);
    memset(layout_storage.get(), 0, layout_size);
    AudioChannelLayout* coreaudio_layout =
    reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
    
    coreaudio_layout->mNumberChannelDescriptions = numMultichannels;
    
    coreaudio_layout->mChannelLayoutTag =
    kAudioChannelLayoutTag_UseChannelDescriptions;
    AudioChannelDescription* descriptions =
    coreaudio_layout->mChannelDescriptions;
    
    for (int ch = 0; ch < numMultichannels; ++ch)
    {
        descriptions[ch].mChannelLabel = ch > 16
        ? kAudioChannelLabel_Unknown
        : kCoreAudioChannelMapping[ch];
        descriptions[ch].mChannelFlags = kAudioChannelFlags_AllOff;
    }
    
    OSStatus ret = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input,
                         0, coreaudio_layout, layout_size);

and I use SetMixMatrix to assign the levels, of course

Did anything ever happen with this? I was having a huge amount of trouble with fmod and an aggregate CoreAudio device, until i switched it to “Quadrophonic”. It seems to work now, but i’m unsure how portable what i’m doing is!

if you mean having fmod override the default speaker mode in the OS, I dont see evidence that this was added. is quadraphonic meaning 4 speakers, the number of speakers you want to address?

I’m running into this also. I have a USB audio interface with 22 outputs. If I set the speakers in Audio/MIDI settings to 5.1 or 7.1, then FMOD reports 6 or 8 channels, respectively, with the matching mode. If I set the speakers to 9.1.6 Atmos (which is the highest channel-count available in those settings), then FMOD reports 16 channels in RAW mode. There doesn’t seem to be a way to tell the OS to report the device without the speaker configuration.

Interestingly I have a virtual audio device with 130 channels, for which FMOD reports all 130 channels, and in RAW mode. If I run system_profiler SPAudioDataType, which shows info on all the audio devices, the only thing that stands out is that for the virtual device, it says “Transport: Virtual”, but for the USB interface it says “Transport: USB”.

I created an aggregate device that just has my USB device in it, and it says “Transport:Unknown”

I also installed Blackhole, in the 2-channel, 16-channel, and 64-channel varieties. FMOD reported all the channels. It reported the 2-channel as stereo, and the other two in RAW.

I went into Audio/midi settings and set the 64-channel Blackhole device to 5.1, which caused FMOD to report 6 channels in 5.1 mode. There’s no way for me to get all 64 channels back from Audio/MIDI settings, because 9.1.6 is the highest channel count you can select.

Conclusion:

  • CoreAudio must report the speaker configuration, but that configuration could be in some null state, for which FMOD will report the device as RAW (maybe related to the states listed here)
  • from Audio/MIDI settings, the best you can do is 16 channels, which FMOD will interpret as RAW.
  • by deleting the plist files in /Library/Preferences/Audio, I was able to clear the speaker configuration and get back to the full 64 channels for the blackhole interface. My USB interface defaulted to 5.1, so maybe CoreAudio uses some kind of heuristic to set the default configuration?

Not sure if this is helpful at all. It would definitely be great to have an option to force RAW mode when opening a device, and either specify the number of channels, or at least access all the available hardware channels.