diff --git a/MANIFEST.in b/MANIFEST.in index 90a504a..dd0e55e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,4 @@ include LICENSE +include soundfile_build.py recursive-include doc *.py *.rst *.txt Makefile recursive-include tests *.py *.wav *.raw diff --git a/setup.py b/setup.py index 717acfb..7207cc4 100644 --- a/setup.py +++ b/setup.py @@ -98,7 +98,9 @@ def get_tag(self): package_data=package_data, zip_safe=zip_safe, license='BSD 3-Clause License', - install_requires=['cffi>=0.6'], + setup_requires=["cffi>=1.0"], + install_requires=['cffi>=1.0'], + cffi_modules=["soundfile_build.py:ffibuilder"], extras_require={'numpy': ['numpy']}, platforms='any', classifiers=[ diff --git a/soundfile.py b/soundfile.py index a0dc569..86226a0 100644 --- a/soundfile.py +++ b/soundfile.py @@ -12,142 +12,15 @@ import os as _os import sys as _sys -from cffi import FFI as _FFI from os import SEEK_SET, SEEK_CUR, SEEK_END +from ctypes.util import find_library as _find_library +from _soundfile import ffi as _ffi try: _unicode = unicode # doesn't exist in Python 3.x except NameError: _unicode = str -_ffi = _FFI() -_ffi.cdef(""" -enum -{ - SF_FORMAT_SUBMASK = 0x0000FFFF, - SF_FORMAT_TYPEMASK = 0x0FFF0000, - SF_FORMAT_ENDMASK = 0x30000000 -} ; - -enum -{ - SFC_GET_LIB_VERSION = 0x1000, - SFC_GET_LOG_INFO = 0x1001, - SFC_GET_FORMAT_INFO = 0x1028, - - SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, - SFC_GET_FORMAT_MAJOR = 0x1031, - SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, - SFC_GET_FORMAT_SUBTYPE = 0x1033, - SFC_FILE_TRUNCATE = 0x1080, - SFC_SET_CLIPPING = 0x10C0, - - SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, - SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015, -} ; - -enum -{ - SF_FALSE = 0, - SF_TRUE = 1, - - /* Modes for opening files. */ - SFM_READ = 0x10, - SFM_WRITE = 0x20, - SFM_RDWR = 0x30, -} ; - -typedef int64_t sf_count_t ; - -typedef struct SNDFILE_tag SNDFILE ; - -typedef struct SF_INFO -{ - sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ - int samplerate ; - int channels ; - int format ; - int sections ; - int seekable ; -} SF_INFO ; - -SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; -int sf_format_check (const SF_INFO *info) ; - -sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; - -int sf_command (SNDFILE *sndfile, int cmd, void *data, int datasize) ; - -int sf_error (SNDFILE *sndfile) ; -const char* sf_strerror (SNDFILE *sndfile) ; -const char* sf_error_number (int errnum) ; - -int sf_perror (SNDFILE *sndfile) ; -int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; - -int sf_close (SNDFILE *sndfile) ; -void sf_write_sync (SNDFILE *sndfile) ; - -sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; -sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; -sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; -sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; - -/* Note: Data ptr argument types are declared as void* here in order to - avoid an implicit cast warning. (gh183). */ -sf_count_t sf_readf_short (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; -sf_count_t sf_readf_int (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; -sf_count_t sf_readf_float (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; -sf_count_t sf_readf_double (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; - -sf_count_t sf_write_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; -sf_count_t sf_write_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; -sf_count_t sf_write_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; -sf_count_t sf_write_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; - -/* Note: The argument types were changed to void* in order to allow - writing bytes in SoundFile.buffer_write() */ -sf_count_t sf_writef_short (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; -sf_count_t sf_writef_int (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; -sf_count_t sf_writef_float (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; -sf_count_t sf_writef_double (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; - -sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; -sf_count_t sf_write_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; - -const char* sf_get_string (SNDFILE *sndfile, int str_type) ; -int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; -const char * sf_version_string (void) ; - -typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ; -typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ; -typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ; -typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ; -typedef sf_count_t (*sf_vio_tell) (void *user_data) ; - -typedef struct SF_VIRTUAL_IO -{ sf_count_t (*get_filelen) (void *user_data) ; - sf_count_t (*seek) (sf_count_t offset, int whence, void *user_data) ; - sf_count_t (*read) (void *ptr, sf_count_t count, void *user_data) ; - sf_count_t (*write) (const void *ptr, sf_count_t count, void *user_data) ; - sf_count_t (*tell) (void *user_data) ; -} SF_VIRTUAL_IO ; - -SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; -SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; - -typedef struct SF_FORMAT_INFO -{ - int format ; - const char* name ; - const char* extension ; -} SF_FORMAT_INFO ; -""") - -if _sys.platform == 'win32': - _ffi.cdef(""" - SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ; - """) _str_types = { 'title': 0x01, @@ -264,7 +137,7 @@ } try: - _snd = _ffi.dlopen('sndfile') + _snd = _ffi.dlopen(_find_library('sndfile')) except OSError: if _sys.platform == 'darwin': _libname = 'libsndfile.dylib' diff --git a/soundfile_build.py b/soundfile_build.py new file mode 100644 index 0000000..5fdcc17 --- /dev/null +++ b/soundfile_build.py @@ -0,0 +1,135 @@ +import sys +from cffi import FFI + +ffibuilder = FFI() +ffibuilder.set_source("_soundfile", None) +ffibuilder.cdef(""" +enum +{ + SF_FORMAT_SUBMASK = 0x0000FFFF, + SF_FORMAT_TYPEMASK = 0x0FFF0000, + SF_FORMAT_ENDMASK = 0x30000000 +} ; + +enum +{ + SFC_GET_LIB_VERSION = 0x1000, + SFC_GET_LOG_INFO = 0x1001, + SFC_GET_FORMAT_INFO = 0x1028, + + SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, + SFC_GET_FORMAT_MAJOR = 0x1031, + SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, + SFC_GET_FORMAT_SUBTYPE = 0x1033, + SFC_FILE_TRUNCATE = 0x1080, + SFC_SET_CLIPPING = 0x10C0, + + SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, + SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015, +} ; + +enum +{ + SF_FALSE = 0, + SF_TRUE = 1, + + /* Modes for opening files. */ + SFM_READ = 0x10, + SFM_WRITE = 0x20, + SFM_RDWR = 0x30, +} ; + +typedef int64_t sf_count_t ; + +typedef struct SNDFILE_tag SNDFILE ; + +typedef struct SF_INFO +{ + sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ + int samplerate ; + int channels ; + int format ; + int sections ; + int seekable ; +} SF_INFO ; + +SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; +int sf_format_check (const SF_INFO *info) ; + +sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; + +int sf_command (SNDFILE *sndfile, int cmd, void *data, int datasize) ; + +int sf_error (SNDFILE *sndfile) ; +const char* sf_strerror (SNDFILE *sndfile) ; +const char* sf_error_number (int errnum) ; + +int sf_perror (SNDFILE *sndfile) ; +int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; + +int sf_close (SNDFILE *sndfile) ; +void sf_write_sync (SNDFILE *sndfile) ; + +sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; +sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; +sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; +sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; + +/* Note: Data ptr argument types are declared as void* here in order to + avoid an implicit cast warning. (gh183). */ +sf_count_t sf_readf_short (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; +sf_count_t sf_readf_int (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; +sf_count_t sf_readf_float (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; +sf_count_t sf_readf_double (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; + +sf_count_t sf_write_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; +sf_count_t sf_write_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; +sf_count_t sf_write_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; +sf_count_t sf_write_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; + +/* Note: The argument types were changed to void* in order to allow + writing bytes in SoundFile.buffer_write() */ +sf_count_t sf_writef_short (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; +sf_count_t sf_writef_int (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; +sf_count_t sf_writef_float (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; +sf_count_t sf_writef_double (SNDFILE *sndfile, void *ptr, sf_count_t frames) ; + +sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; +sf_count_t sf_write_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; + +const char* sf_get_string (SNDFILE *sndfile, int str_type) ; +int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; +const char * sf_version_string (void) ; + +typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ; +typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ; +typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_tell) (void *user_data) ; + +typedef struct SF_VIRTUAL_IO +{ sf_count_t (*get_filelen) (void *user_data) ; + sf_count_t (*seek) (sf_count_t offset, int whence, void *user_data) ; + sf_count_t (*read) (void *ptr, sf_count_t count, void *user_data) ; + sf_count_t (*write) (const void *ptr, sf_count_t count, void *user_data) ; + sf_count_t (*tell) (void *user_data) ; +} SF_VIRTUAL_IO ; + +SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; +SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; + +typedef struct SF_FORMAT_INFO +{ + int format ; + const char* name ; + const char* extension ; +} SF_FORMAT_INFO ; +""") + +if sys.platform == 'win32': + ffibuilder.cdef(""" + SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ; + """) + +if __name__ == "__main__": + ffibuilder.compile(verbose=True)