Skip to content

Commit 0e9187a

Browse files
committed
switch to cffi out-of-line ABI mode
switch to out of line mode to improve sounddevice module import time. this adds a separate sounddevice_build.py file that becomes part of the setup.py build process and is only run once at install time rather than everytime the module is imported
1 parent 132e924 commit 0e9187a

File tree

4 files changed

+330
-320
lines changed

4 files changed

+330
-320
lines changed

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
include LICENSE
22
include *.rst
33
include doc/requirements.txt
4+
include sounddevice_build.py
45
recursive-include doc *.rst *.py
56
recursive-include examples *.py

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,10 @@ def get_tag(self):
7171
packages=packages,
7272
package_data=package_data,
7373
zip_safe=zip_safe,
74+
setup_requires=["CFFI>=1.0"],
7475
install_requires=['CFFI>=1.0'],
7576
extras_require={'NumPy': ['NumPy']},
77+
cffi_modules=["sounddevice_build.py:ffibuilder"],
7678
author='Matthias Geier',
7779
author_email='[email protected]',
7880
description='Play and Record Sound with Python',

sounddevice.py

Lines changed: 6 additions & 320 deletions
Original file line numberDiff line numberDiff line change
@@ -26,321 +26,15 @@
2626
__version__ = '0.3.8'
2727

2828
import atexit as _atexit
29-
from cffi import FFI as _FFI
3029
import os as _os
3130
import platform as _platform
3231
import sys as _sys
32+
from ctypes.util import find_library as _find_library
33+
from _sounddevice import ffi as _ffi
3334

34-
_ffi = _FFI()
35-
_ffi.cdef("""
36-
int Pa_GetVersion( void );
37-
const char* Pa_GetVersionText( void );
38-
typedef int PaError;
39-
typedef enum PaErrorCode
40-
{
41-
paNoError = 0,
42-
paNotInitialized = -10000,
43-
paUnanticipatedHostError,
44-
paInvalidChannelCount,
45-
paInvalidSampleRate,
46-
paInvalidDevice,
47-
paInvalidFlag,
48-
paSampleFormatNotSupported,
49-
paBadIODeviceCombination,
50-
paInsufficientMemory,
51-
paBufferTooBig,
52-
paBufferTooSmall,
53-
paNullCallback,
54-
paBadStreamPtr,
55-
paTimedOut,
56-
paInternalError,
57-
paDeviceUnavailable,
58-
paIncompatibleHostApiSpecificStreamInfo,
59-
paStreamIsStopped,
60-
paStreamIsNotStopped,
61-
paInputOverflowed,
62-
paOutputUnderflowed,
63-
paHostApiNotFound,
64-
paInvalidHostApi,
65-
paCanNotReadFromACallbackStream,
66-
paCanNotWriteToACallbackStream,
67-
paCanNotReadFromAnOutputOnlyStream,
68-
paCanNotWriteToAnInputOnlyStream,
69-
paIncompatibleStreamHostApi,
70-
paBadBufferPtr
71-
} PaErrorCode;
72-
const char *Pa_GetErrorText( PaError errorCode );
73-
PaError Pa_Initialize( void );
74-
PaError Pa_Terminate( void );
75-
typedef int PaDeviceIndex;
76-
#define paNoDevice -1
77-
#define paUseHostApiSpecificDeviceSpecification -2
78-
typedef int PaHostApiIndex;
79-
PaHostApiIndex Pa_GetHostApiCount( void );
80-
PaHostApiIndex Pa_GetDefaultHostApi( void );
81-
typedef enum PaHostApiTypeId
82-
{
83-
paInDevelopment=0,
84-
paDirectSound=1,
85-
paMME=2,
86-
paASIO=3,
87-
paSoundManager=4,
88-
paCoreAudio=5,
89-
paOSS=7,
90-
paALSA=8,
91-
paAL=9,
92-
paBeOS=10,
93-
paWDMKS=11,
94-
paJACK=12,
95-
paWASAPI=13,
96-
paAudioScienceHPI=14
97-
} PaHostApiTypeId;
98-
typedef struct PaHostApiInfo
99-
{
100-
int structVersion;
101-
PaHostApiTypeId type;
102-
const char *name;
103-
int deviceCount;
104-
PaDeviceIndex defaultInputDevice;
105-
PaDeviceIndex defaultOutputDevice;
106-
} PaHostApiInfo;
107-
const PaHostApiInfo * Pa_GetHostApiInfo( PaHostApiIndex hostApi );
108-
PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type );
109-
PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi,
110-
int hostApiDeviceIndex );
111-
typedef struct PaHostErrorInfo{
112-
PaHostApiTypeId hostApiType;
113-
long errorCode;
114-
const char *errorText;
115-
}PaHostErrorInfo;
116-
const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void );
117-
PaDeviceIndex Pa_GetDeviceCount( void );
118-
PaDeviceIndex Pa_GetDefaultInputDevice( void );
119-
PaDeviceIndex Pa_GetDefaultOutputDevice( void );
120-
typedef double PaTime;
121-
typedef unsigned long PaSampleFormat;
122-
#define paFloat32 0x00000001
123-
#define paInt32 0x00000002
124-
#define paInt24 0x00000004
125-
#define paInt16 0x00000008
126-
#define paInt8 0x00000010
127-
#define paUInt8 0x00000020
128-
#define paCustomFormat 0x00010000
129-
#define paNonInterleaved 0x80000000
130-
typedef struct PaDeviceInfo
131-
{
132-
int structVersion;
133-
const char *name;
134-
PaHostApiIndex hostApi;
135-
int maxInputChannels;
136-
int maxOutputChannels;
137-
PaTime defaultLowInputLatency;
138-
PaTime defaultLowOutputLatency;
139-
PaTime defaultHighInputLatency;
140-
PaTime defaultHighOutputLatency;
141-
double defaultSampleRate;
142-
} PaDeviceInfo;
143-
const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device );
144-
typedef struct PaStreamParameters
145-
{
146-
PaDeviceIndex device;
147-
int channelCount;
148-
PaSampleFormat sampleFormat;
149-
PaTime suggestedLatency;
150-
void *hostApiSpecificStreamInfo;
151-
} PaStreamParameters;
152-
#define paFormatIsSupported 0
153-
PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
154-
const PaStreamParameters *outputParameters,
155-
double sampleRate );
156-
typedef void PaStream;
157-
#define paFramesPerBufferUnspecified 0
158-
typedef unsigned long PaStreamFlags;
159-
#define paNoFlag 0
160-
#define paClipOff 0x00000001
161-
#define paDitherOff 0x00000002
162-
#define paNeverDropInput 0x00000004
163-
#define paPrimeOutputBuffersUsingStreamCallback 0x00000008
164-
#define paPlatformSpecificFlags 0xFFFF0000
165-
typedef struct PaStreamCallbackTimeInfo{
166-
PaTime inputBufferAdcTime;
167-
PaTime currentTime;
168-
PaTime outputBufferDacTime;
169-
} PaStreamCallbackTimeInfo;
170-
typedef unsigned long PaStreamCallbackFlags;
171-
#define paInputUnderflow 0x00000001
172-
#define paInputOverflow 0x00000002
173-
#define paOutputUnderflow 0x00000004
174-
#define paOutputOverflow 0x00000008
175-
#define paPrimingOutput 0x00000010
176-
typedef enum PaStreamCallbackResult
177-
{
178-
paContinue=0,
179-
paComplete=1,
180-
paAbort=2
181-
} PaStreamCallbackResult;
182-
typedef int PaStreamCallback(
183-
const void *input, void *output,
184-
unsigned long frameCount,
185-
const PaStreamCallbackTimeInfo* timeInfo,
186-
PaStreamCallbackFlags statusFlags,
187-
void *userData );
188-
PaError Pa_OpenStream( PaStream** stream,
189-
const PaStreamParameters *inputParameters,
190-
const PaStreamParameters *outputParameters,
191-
double sampleRate,
192-
unsigned long framesPerBuffer,
193-
PaStreamFlags streamFlags,
194-
PaStreamCallback *streamCallback,
195-
void *userData );
196-
PaError Pa_OpenDefaultStream( PaStream** stream,
197-
int numInputChannels,
198-
int numOutputChannels,
199-
PaSampleFormat sampleFormat,
200-
double sampleRate,
201-
unsigned long framesPerBuffer,
202-
PaStreamCallback *streamCallback,
203-
void *userData );
204-
PaError Pa_CloseStream( PaStream *stream );
205-
typedef void PaStreamFinishedCallback( void *userData );
206-
PaError Pa_SetStreamFinishedCallback( PaStream *stream,
207-
PaStreamFinishedCallback* streamFinishedCallback );
208-
PaError Pa_StartStream( PaStream *stream );
209-
PaError Pa_StopStream( PaStream *stream );
210-
PaError Pa_AbortStream( PaStream *stream );
211-
PaError Pa_IsStreamStopped( PaStream *stream );
212-
PaError Pa_IsStreamActive( PaStream *stream );
213-
typedef struct PaStreamInfo
214-
{
215-
int structVersion;
216-
PaTime inputLatency;
217-
PaTime outputLatency;
218-
double sampleRate;
219-
} PaStreamInfo;
220-
const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream );
221-
PaTime Pa_GetStreamTime( PaStream *stream );
222-
double Pa_GetStreamCpuLoad( PaStream* stream );
223-
PaError Pa_ReadStream( PaStream* stream,
224-
void *buffer,
225-
unsigned long frames );
226-
PaError Pa_WriteStream( PaStream* stream,
227-
const void *buffer,
228-
unsigned long frames );
229-
signed long Pa_GetStreamReadAvailable( PaStream* stream );
230-
signed long Pa_GetStreamWriteAvailable( PaStream* stream );
231-
PaHostApiTypeId Pa_GetStreamHostApiType( PaStream* stream );
232-
PaError Pa_GetSampleSize( PaSampleFormat format );
233-
void Pa_Sleep( long msec );
234-
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-
262-
/* pa_win_waveformat.h */
263-
264-
typedef unsigned long PaWinWaveFormatChannelMask;
265-
266-
/* pa_asio.h */
267-
268-
#define paAsioUseChannelSelectors 0x01
269-
270-
typedef struct PaAsioStreamInfo
271-
{
272-
unsigned long size;
273-
PaHostApiTypeId hostApiType;
274-
unsigned long version;
275-
unsigned long flags;
276-
int *channelSelectors;
277-
} PaAsioStreamInfo;
278-
279-
/* pa_win_wasapi.h */
280-
281-
typedef enum PaWasapiFlags
282-
{
283-
paWinWasapiExclusive = 1,
284-
paWinWasapiRedirectHostProcessor = 2,
285-
paWinWasapiUseChannelMask = 4,
286-
paWinWasapiPolling = 8,
287-
paWinWasapiThreadPriority = 16
288-
} PaWasapiFlags;
289-
290-
typedef void (*PaWasapiHostProcessorCallback) (
291-
void *inputBuffer, long inputFrames,
292-
void *outputBuffer, long outputFrames, void *userData);
293-
294-
typedef enum PaWasapiThreadPriority
295-
{
296-
eThreadPriorityNone = 0,
297-
eThreadPriorityAudio,
298-
eThreadPriorityCapture,
299-
eThreadPriorityDistribution,
300-
eThreadPriorityGames,
301-
eThreadPriorityPlayback,
302-
eThreadPriorityProAudio,
303-
eThreadPriorityWindowManager
304-
} PaWasapiThreadPriority;
305-
306-
typedef enum PaWasapiStreamCategory
307-
{
308-
eAudioCategoryOther = 0,
309-
eAudioCategoryCommunications = 3,
310-
eAudioCategoryAlerts = 4,
311-
eAudioCategorySoundEffects = 5,
312-
eAudioCategoryGameEffects = 6,
313-
eAudioCategoryGameMedia = 7,
314-
eAudioCategoryGameChat = 8,
315-
eAudioCategorySpeech = 9,
316-
eAudioCategoryMovie = 10,
317-
eAudioCategoryMedia = 11
318-
} PaWasapiStreamCategory;
319-
320-
typedef enum PaWasapiStreamOption
321-
{
322-
eStreamOptionNone = 0,
323-
eStreamOptionRaw = 1,
324-
eStreamOptionMatchFormat = 2
325-
} PaWasapiStreamOption;
326-
327-
typedef struct PaWasapiStreamInfo
328-
{
329-
unsigned long size;
330-
PaHostApiTypeId hostApiType;
331-
unsigned long version;
332-
unsigned long flags;
333-
PaWinWaveFormatChannelMask channelMask;
334-
PaWasapiHostProcessorCallback hostProcessorOutput;
335-
PaWasapiHostProcessorCallback hostProcessorInput;
336-
PaWasapiThreadPriority threadPriority;
337-
PaWasapiStreamCategory streamCategory;
338-
PaWasapiStreamOption streamOption;
339-
} PaWasapiStreamInfo;
340-
""")
34135

34236
try:
343-
_lib = _ffi.dlopen('portaudio')
37+
_lib = _ffi.dlopen(_find_library('portaudio'))
34438
except OSError:
34539
if _platform.system() == 'Darwin':
34640
_libname = 'libportaudio.dylib'
@@ -2935,25 +2629,17 @@ def _exit_handler():
29352629

29362630
def _ignore_stderr():
29372631
"""Try to forward PortAudio messages from stderr to /dev/null."""
2938-
ffi = _FFI()
2939-
ffi.cdef("""
2940-
/* from stdio.h */
2941-
FILE* fopen(const char* path, const char* mode);
2942-
int fclose(FILE* fp);
2943-
FILE* stderr; /* GNU C library */
2944-
FILE* __stderrp; /* macOS */
2945-
""")
29462632
try:
2947-
stdio = ffi.dlopen(None)
2633+
stdio = _ffi.dlopen(None)
29482634
devnull = stdio.fopen(_os.devnull.encode(), b'w')
29492635
except (OSError, AttributeError):
29502636
return
29512637
try:
29522638
stdio.stderr = devnull
2953-
except KeyError:
2639+
except _ffi.error:
29542640
try:
29552641
stdio.__stderrp = devnull
2956-
except KeyError:
2642+
except _ffi.error:
29572643
stdio.fclose(devnull)
29582644

29592645

0 commit comments

Comments
 (0)