|
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