Skip to content

Commit 85729e8

Browse files
committed
Created CoreAudioSettings
1 parent 1ceba26 commit 85729e8

File tree

1 file changed

+120
-1
lines changed

1 file changed

+120
-1
lines changed

sounddevice.py

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,33 @@
232232
PaError Pa_GetSampleSize( PaSampleFormat format );
233233
void Pa_Sleep( long msec );
234234
235+
/* pa_mac_core.h */
236+
237+
typedef int32_t SInt32;
238+
typedef struct
239+
{
240+
unsigned long size;
241+
PaHostApiTypeId hostApiType;
242+
unsigned long version;
243+
unsigned long flags;
244+
SInt32 const * channelMap;
245+
unsigned long channelMapSize;
246+
} PaMacCoreStreamInfo;
247+
void PaMacCore_SetupStreamInfo( PaMacCoreStreamInfo *data, unsigned long flags );
248+
void PaMacCore_SetupChannelMap( PaMacCoreStreamInfo *data, const SInt32 * const channelMap, unsigned long channelMapSize );
249+
const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input );
250+
#define paMacCoreChangeDeviceParameters 0x01
251+
#define paMacCoreFailIfConversionRequired 0x02
252+
#define paMacCoreConversionQualityMin 0x0100
253+
#define paMacCoreConversionQualityMedium 0x0200
254+
#define paMacCoreConversionQualityLow 0x0300
255+
#define paMacCoreConversionQualityHigh 0x0400
256+
#define paMacCoreConversionQualityMax 0x0000
257+
#define paMacCorePlayNice 0x00
258+
#define paMacCorePro 0x01
259+
#define paMacCoreMinimizeCPUButPlayNice 0x0100
260+
#define paMacCoreMinimizeCPU 0x0101
261+
235262
/* pa_win_waveformat.h */
236263
237264
typedef unsigned long PaWinWaveFormatChannelMask;
@@ -2182,7 +2209,7 @@ class default(object):
21822209
21832210
See Also
21842211
--------
2185-
AsioSettings, WasapiSettings
2212+
AsioSettings, CoreAudioSettings, WasapiSettings
21862213
21872214
"""
21882215
samplerate = None
@@ -2349,6 +2376,98 @@ def __init__(self, channel_selectors):
23492376
channelSelectors=self._selectors))
23502377

23512378

2379+
class CoreAudioSettings(object):
2380+
2381+
def __init__(self, channel_map=None, change_device_parameters=False,
2382+
fail_if_conversion_required=False, conversion_quality='max'):
2383+
"""Mac Core Audio-specific input/output settings.
2384+
2385+
Objects of this class can be used as *extra_settings* argument
2386+
to `Stream()` (and variants) or as `default.extra_settings`.
2387+
2388+
Parameters
2389+
----------
2390+
channel_map : sequence of int, optional
2391+
Support for opening only specific channels of a Core Audio
2392+
device. Note that *channel_map* is treated differently
2393+
between input and output channels.
2394+
2395+
For input devices, *channel_map* is a list of integers
2396+
specifying the (zero-based) channel numbers to use.
2397+
2398+
For output devices, *channel_map* must have the same length
2399+
as the number of output channels of the device. Specify
2400+
unused channels with -1, and a 0-based index for any desired
2401+
channels.
2402+
2403+
See the example below. For additional information, see the
2404+
`PortAudio documentation`__.
2405+
2406+
__ https://app.assembla.com/spaces/portaudio/git/source/
2407+
master/src/hostapi/coreaudio/notes.txt
2408+
change_device_parameters : bool, optional
2409+
If ``True``, allows PortAudio to change things like the
2410+
device's frame size, which allows for much lower latency,
2411+
but might disrupt the device if other programs are using it,
2412+
even when you are just querying the device. ``False`` is
2413+
the default.
2414+
fail_if_conversion_required : bool, optional
2415+
In combination with the above flag, ``True`` causes the
2416+
stream opening to fail, unless the exact sample rates are
2417+
supported by the device.
2418+
conversion_quality : {'min', 'low', 'medium', 'high', 'max'}, optional
2419+
This sets Core Audio's sample rate conversion quality.
2420+
``'max'`` is the default.
2421+
2422+
Example
2423+
-------
2424+
This example assumes a device having 6 input and 6 output
2425+
channels. Input is from the second and fourth channels, and
2426+
output is to the device's third and fifth channels:
2427+
2428+
>>> import sounddevice as sd
2429+
>>> ca_in = sd.CoreAudioSettings(channel_map=[1, 3])
2430+
>>> ca_out = sd.CoreAudioSettings(channel_map=[-1, -1, 0, -1, 1, -1])
2431+
>>> sd.playrec(..., channels=2, extra_settings=(ca_in, ca_out))
2432+
2433+
"""
2434+
conversion_dict = {
2435+
'min': _lib.paMacCoreConversionQualityMin,
2436+
'low': _lib.paMacCoreConversionQualityLow,
2437+
'medium': _lib.paMacCoreConversionQualityMedium,
2438+
'high': _lib.paMacCoreConversionQualityHigh,
2439+
'max': _lib.paMacCoreConversionQualityMax,
2440+
}
2441+
2442+
# Minimal checking on channel_map to catch errors that might
2443+
# otherwise go unnoticed:
2444+
if isinstance(channel_map, int):
2445+
raise TypeError('channel_map must be a list or tuple')
2446+
2447+
try:
2448+
self._flags = conversion_dict[conversion_quality.lower()]
2449+
except (KeyError, AttributeError):
2450+
raise ValueError('conversion_quality must be one of ' +
2451+
repr(list(conversion_dict)))
2452+
if change_device_parameters:
2453+
self._flags |= _lib.paMacCoreChangeDeviceParameters
2454+
if fail_if_conversion_required:
2455+
self._flags |= _lib.paMacCoreFailIfConversionRequired
2456+
2457+
# this struct must be kept alive!
2458+
self._streaminfo = _ffi.new('PaMacCoreStreamInfo*')
2459+
_lib.PaMacCore_SetupStreamInfo(self._streaminfo, self._flags)
2460+
2461+
if channel_map is not None:
2462+
# this array must be kept alive!
2463+
self._channel_map = _ffi.new('SInt32[]', channel_map)
2464+
if len(self._channel_map) == 0:
2465+
raise TypeError('channel_map must not be empty')
2466+
_lib.PaMacCore_SetupChannelMap(self._streaminfo,
2467+
self._channel_map,
2468+
len(self._channel_map))
2469+
2470+
23522471
class WasapiSettings(object):
23532472

23542473
def __init__(self, exclusive=False):

0 commit comments

Comments
 (0)