|
8 | 8 | For further information, see https://python-soundfile.readthedocs.io/. |
9 | 9 |
|
10 | 10 | """ |
11 | | -__version__ = "0.10.3" |
| 11 | +__version__ = "0.11.0" |
12 | 12 |
|
13 | 13 | import os as _os |
14 | 14 | import sys as _sys |
15 | | -from platform import machine as _machine |
16 | 15 | from os import SEEK_SET, SEEK_CUR, SEEK_END |
17 | 16 | from ctypes.util import find_library as _find_library |
18 | 17 | from _soundfile import ffi as _ffi |
|
62 | 61 | 'OGG': 0x200000, # Xiph OGG container |
63 | 62 | 'MPC2K': 0x210000, # Akai MPC 2000 sampler |
64 | 63 | 'RF64': 0x220000, # RF64 WAV file |
| 64 | + 'MP3': 0x230000, # MPEG-1/2 audio stream |
65 | 65 | } |
66 | 66 |
|
67 | 67 | _subtypes = { |
68 | | - 'PCM_S8': 0x0001, # Signed 8 bit data |
69 | | - 'PCM_16': 0x0002, # Signed 16 bit data |
70 | | - 'PCM_24': 0x0003, # Signed 24 bit data |
71 | | - 'PCM_32': 0x0004, # Signed 32 bit data |
72 | | - 'PCM_U8': 0x0005, # Unsigned 8 bit data (WAV and RAW only) |
73 | | - 'FLOAT': 0x0006, # 32 bit float data |
74 | | - 'DOUBLE': 0x0007, # 64 bit float data |
75 | | - 'ULAW': 0x0010, # U-Law encoded. |
76 | | - 'ALAW': 0x0011, # A-Law encoded. |
77 | | - 'IMA_ADPCM': 0x0012, # IMA ADPCM. |
78 | | - 'MS_ADPCM': 0x0013, # Microsoft ADPCM. |
79 | | - 'GSM610': 0x0020, # GSM 6.10 encoding. |
80 | | - 'VOX_ADPCM': 0x0021, # OKI / Dialogix ADPCM |
81 | | - 'G721_32': 0x0030, # 32kbs G721 ADPCM encoding. |
82 | | - 'G723_24': 0x0031, # 24kbs G723 ADPCM encoding. |
83 | | - 'G723_40': 0x0032, # 40kbs G723 ADPCM encoding. |
84 | | - 'DWVW_12': 0x0040, # 12 bit Delta Width Variable Word encoding. |
85 | | - 'DWVW_16': 0x0041, # 16 bit Delta Width Variable Word encoding. |
86 | | - 'DWVW_24': 0x0042, # 24 bit Delta Width Variable Word encoding. |
87 | | - 'DWVW_N': 0x0043, # N bit Delta Width Variable Word encoding. |
88 | | - 'DPCM_8': 0x0050, # 8 bit differential PCM (XI only) |
89 | | - 'DPCM_16': 0x0051, # 16 bit differential PCM (XI only) |
90 | | - 'VORBIS': 0x0060, # Xiph Vorbis encoding. |
91 | | - 'ALAC_16': 0x0070, # Apple Lossless Audio Codec (16 bit). |
92 | | - 'ALAC_20': 0x0071, # Apple Lossless Audio Codec (20 bit). |
93 | | - 'ALAC_24': 0x0072, # Apple Lossless Audio Codec (24 bit). |
94 | | - 'ALAC_32': 0x0073, # Apple Lossless Audio Codec (32 bit). |
| 68 | + 'PCM_S8': 0x0001, # Signed 8 bit data |
| 69 | + 'PCM_16': 0x0002, # Signed 16 bit data |
| 70 | + 'PCM_24': 0x0003, # Signed 24 bit data |
| 71 | + 'PCM_32': 0x0004, # Signed 32 bit data |
| 72 | + 'PCM_U8': 0x0005, # Unsigned 8 bit data (WAV and RAW only) |
| 73 | + 'FLOAT': 0x0006, # 32 bit float data |
| 74 | + 'DOUBLE': 0x0007, # 64 bit float data |
| 75 | + 'ULAW': 0x0010, # U-Law encoded. |
| 76 | + 'ALAW': 0x0011, # A-Law encoded. |
| 77 | + 'IMA_ADPCM': 0x0012, # IMA ADPCM. |
| 78 | + 'MS_ADPCM': 0x0013, # Microsoft ADPCM. |
| 79 | + 'GSM610': 0x0020, # GSM 6.10 encoding. |
| 80 | + 'VOX_ADPCM': 0x0021, # OKI / Dialogix ADPCM |
| 81 | + 'NMS_ADPCM_16': 0x0022, # 16kbs NMS G721-variant encoding. |
| 82 | + 'NMS_ADPCM_24': 0x0023, # 24kbs NMS G721-variant encoding. |
| 83 | + 'NMS_ADPCM_32': 0x0024, # 32kbs NMS G721-variant encoding. |
| 84 | + 'G721_32': 0x0030, # 32kbs G721 ADPCM encoding. |
| 85 | + 'G723_24': 0x0031, # 24kbs G723 ADPCM encoding. |
| 86 | + 'G723_40': 0x0032, # 40kbs G723 ADPCM encoding. |
| 87 | + 'DWVW_12': 0x0040, # 12 bit Delta Width Variable Word encoding. |
| 88 | + 'DWVW_16': 0x0041, # 16 bit Delta Width Variable Word encoding. |
| 89 | + 'DWVW_24': 0x0042, # 24 bit Delta Width Variable Word encoding. |
| 90 | + 'DWVW_N': 0x0043, # N bit Delta Width Variable Word encoding. |
| 91 | + 'DPCM_8': 0x0050, # 8 bit differential PCM (XI only) |
| 92 | + 'DPCM_16': 0x0051, # 16 bit differential PCM (XI only) |
| 93 | + 'VORBIS': 0x0060, # Xiph Vorbis encoding. |
| 94 | + 'OPUS': 0x0064, # Xiph/Skype Opus encoding. |
| 95 | + 'ALAC_16': 0x0070, # Apple Lossless Audio Codec (16 bit). |
| 96 | + 'ALAC_20': 0x0071, # Apple Lossless Audio Codec (20 bit). |
| 97 | + 'ALAC_24': 0x0072, # Apple Lossless Audio Codec (24 bit). |
| 98 | + 'ALAC_32': 0x0073, # Apple Lossless Audio Codec (32 bit). |
| 99 | + 'MPEG_LAYER_I': 0x0080, # MPEG-1 Audio Layer I. |
| 100 | + 'MPEG_LAYER_II': 0x0081, # MPEG-1 Audio Layer II. |
| 101 | + 'MPEG_LAYER_III': 0x0082, # MPEG-2 Audio Layer III. |
95 | 102 | } |
96 | 103 |
|
97 | 104 | _endians = { |
|
128 | 135 | 'OGG': 'VORBIS', |
129 | 136 | 'MPC2K': 'PCM_16', |
130 | 137 | 'RF64': 'PCM_16', |
| 138 | + 'MP3': 'MPEG_LAYER_III', |
131 | 139 | } |
132 | 140 |
|
133 | 141 | _ffi_types = { |
|
144 | 152 | _snd = _ffi.dlopen(_libname) |
145 | 153 | except OSError: |
146 | 154 | if _sys.platform == 'darwin': |
| 155 | + from platform import machine as _machine |
| 156 | + _packaged_libname = 'libsndfile_' + _machine() + '.dylib' |
147 | 157 | _libname = 'libsndfile.dylib' |
148 | 158 | elif _sys.platform == 'win32': |
149 | 159 | from platform import architecture as _architecture |
150 | | - _libname = 'libsndfile' + _architecture()[0] + '.dll' |
| 160 | + _packaged_libname = 'libsndfile_' + _architecture()[0] + '.dll' |
| 161 | + _libname = 'libsndfile.dll' |
| 162 | + elif _sys.platform == 'linux': |
| 163 | + _packaged_libname = 'libsndfile.so' # not provided! |
| 164 | + _libname = 'libsndfile.so' |
151 | 165 | else: |
152 | 166 | raise |
153 | 167 |
|
|
160 | 174 | while not _os.path.isdir(_path): |
161 | 175 | _path = _os.path.abspath(_os.path.join(_path, '..')) |
162 | 176 |
|
163 | | - # Homebrew on Apple M1 uses a `/opt/homebrew/lib` instead of |
164 | | - # `/usr/local/lib`. We are making sure we pick that up. |
165 | | - if _sys.platform == 'darwin' and _machine() == 'arm64': |
166 | | - _hbrew_path = '/opt/homebrew/lib/' if _os.path.isdir('/opt/homebrew/lib/') \ |
167 | | - else '/usr/local/lib/' |
168 | | - _snd = _ffi.dlopen(_os.path.join( |
169 | | - _hbrew_path, _libname)) |
170 | | - else: |
171 | | - _snd = _ffi.dlopen(_os.path.join( |
172 | | - _path, '_soundfile_data', _libname)) |
| 177 | + try: # packaged libsndfile: |
| 178 | + _snd = _ffi.dlopen(_os.path.join(_path, '_soundfile_data', _packaged_libname)) |
| 179 | + except OSError: # try system-wide libsndfile: |
| 180 | + # Homebrew on Apple M1 uses a `/opt/homebrew/lib` instead of |
| 181 | + # `/usr/local/lib`. We are making sure we pick that up. |
| 182 | + from platform import machine as _machine |
| 183 | + if _sys.platform == 'darwin' and _machine() == 'arm64': |
| 184 | + _hbrew_path = '/opt/homebrew/lib/' if _os.path.isdir('/opt/homebrew/lib/') \ |
| 185 | + else '/usr/local/lib/' |
| 186 | + _snd = _ffi.dlopen(_os.path.join(_hbrew_path, _libname)) |
| 187 | + else: |
| 188 | + # Try explicit file name, if the general does not work (e.g. on nixos) |
| 189 | + _snd = _ffi.dlopen(_libname) |
173 | 190 |
|
174 | 191 | __libsndfile_version__ = _ffi.string(_snd.sf_version_string()).decode('utf-8', 'replace') |
175 | 192 | if __libsndfile_version__.startswith('libsndfile-'): |
@@ -1368,9 +1385,9 @@ def copy_metadata(self): |
1368 | 1385 | ------- |
1369 | 1386 |
|
1370 | 1387 | metadata: dict[str, str] |
1371 | | - A dict with all metadata. Possible keys are: 'title', 'copyright', |
1372 | | - 'software', 'artist', 'comment', 'date', 'album', 'license', |
1373 | | - 'tracknumber' and 'genre'. |
| 1388 | + A dict with all metadata. Possible keys are: 'title', 'copyright', |
| 1389 | + 'software', 'artist', 'comment', 'date', 'album', 'license', |
| 1390 | + 'tracknumber' and 'genre'. |
1374 | 1391 | """ |
1375 | 1392 | strs = {} |
1376 | 1393 | for strtype, strid in _str_types.items(): |
|
0 commit comments