mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-30 16:01:51 +00:00
Add an 'audio.coreaudio.channel-map' setting to enable multi-channel output routing for CoreAudio.
This commit is contained in:
parent
49a3b410f0
commit
326d90e952
2 changed files with 99 additions and 1 deletions
|
@ -452,6 +452,27 @@ Developers:
|
|||
Selects the CoreAudio device to use.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
<name>coreaudio.channel-map</name>
|
||||
<type>str</type>
|
||||
<def>0,1</def>
|
||||
<desc>
|
||||
This setting is a comma-separated integer list that maps CoreAudio channels
|
||||
to output device channels. The value of each position in the list, up to the number of
|
||||
output channels available on your device, is the zero-based index of the fluidsynth
|
||||
output channel to route there. Additionally, the special value of -1 will turn off
|
||||
an output.
|
||||
|
||||
For example, the default map for a single stereo output is "0,1". A value of "0,0" will
|
||||
copy the left channel to the right, a value of "1,0" will flip left and right, and a
|
||||
value of "-1,1" will play only the right channel.
|
||||
|
||||
With a six channel output device, and the synth.audio-channels and synth.audio-groups
|
||||
settings both set to "2", a channel map of "-1,-1,0,1,2,3" will result in notes from odd
|
||||
MIDI channels being sent to outputs 3 and 4, and even MIDI channels being send to
|
||||
outputs 5 and 6.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
<name>dart.device</name>
|
||||
<type>str</type>
|
||||
|
|
|
@ -114,6 +114,75 @@ get_num_outputs(AudioDeviceID deviceID)
|
|||
return total;
|
||||
}
|
||||
|
||||
void
|
||||
set_channel_map(AudioUnit outputUnit, int audio_channels, const char *map_string)
|
||||
{
|
||||
OSStatus status;
|
||||
long int number_of_channels;
|
||||
int i, *channel_map;
|
||||
UInt32 property_size;
|
||||
Boolean writable = false;
|
||||
|
||||
status = AudioUnitGetPropertyInfo(outputUnit,
|
||||
kAudioOutputUnitProperty_ChannelMap,
|
||||
kAudioUnitScope_Output,
|
||||
0,
|
||||
&property_size, &writable);
|
||||
if(status != noErr)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to get the channel map size. Status=%ld\n", (long int) status);
|
||||
return;
|
||||
}
|
||||
|
||||
number_of_channels = property_size / sizeof(int);
|
||||
if(!number_of_channels)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
channel_map = FLUID_ARRAY(int, number_of_channels);
|
||||
if(channel_map == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(channel_map, 0, property_size);
|
||||
|
||||
status = AudioUnitGetProperty(outputUnit,
|
||||
kAudioOutputUnitProperty_ChannelMap,
|
||||
kAudioUnitScope_Output,
|
||||
0,
|
||||
channel_map, &property_size);
|
||||
if(status != noErr)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to get the existing channel map. Status=%ld\n", (long int) status);
|
||||
FLUID_FREE(channel_map);
|
||||
return;
|
||||
}
|
||||
|
||||
fluid_settings_split_csv(map_string, channel_map, (int) number_of_channels);
|
||||
for(i = 0; i < number_of_channels; i++)
|
||||
{
|
||||
if(channel_map[i] < -1 || channel_map[i] >= audio_channels)
|
||||
{
|
||||
channel_map[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
status = AudioUnitSetProperty(outputUnit,
|
||||
kAudioOutputUnitProperty_ChannelMap,
|
||||
kAudioUnitScope_Output,
|
||||
0,
|
||||
channel_map, property_size);
|
||||
if(status != noErr)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to set the channel map. Status=%ld\n", (long int) status);
|
||||
}
|
||||
|
||||
FLUID_FREE(channel_map);
|
||||
}
|
||||
|
||||
void
|
||||
fluid_core_audio_driver_settings(fluid_settings_t *settings)
|
||||
{
|
||||
|
@ -125,6 +194,7 @@ fluid_core_audio_driver_settings(fluid_settings_t *settings)
|
|||
pa.mElement = kAudioObjectPropertyElementMain;
|
||||
|
||||
fluid_settings_register_str(settings, "audio.coreaudio.device", "default", 0);
|
||||
fluid_settings_register_str(settings, "audio.coreaudio.channel-map", "", 0);
|
||||
fluid_settings_add_option(settings, "audio.coreaudio.device", "default");
|
||||
|
||||
if(OK(AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa, 0, 0, &size)))
|
||||
|
@ -169,7 +239,7 @@ new_fluid_core_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
|||
fluid_audio_driver_t *
|
||||
new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data)
|
||||
{
|
||||
char *devname = NULL;
|
||||
char *devname = NULL, *channel_map = NULL;
|
||||
fluid_core_audio_driver_t *dev = NULL;
|
||||
int period_size, periods, audio_channels = 1;
|
||||
double sample_rate;
|
||||
|
@ -335,6 +405,13 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
if(fluid_settings_dupstr(settings, "audio.coreaudio.channel-map", &channel_map) == FLUID_OK /* alloc channel map */
|
||||
&& channel_map && strlen(channel_map) > 0)
|
||||
{
|
||||
set_channel_map(dev->outputUnit, audio_channels, channel_map);
|
||||
}
|
||||
FLUID_FREE(channel_map); /* free channel map */
|
||||
|
||||
status = AudioUnitSetProperty(dev->outputUnit,
|
||||
kAudioUnitProperty_MaximumFramesPerSlice,
|
||||
kAudioUnitScope_Input,
|
||||
|
|
Loading…
Reference in a new issue