[SCM] pysoundfile/master: New upstream version 0.9.0
umlaeute at users.alioth.debian.org
umlaeute at users.alioth.debian.org
Mon Jun 19 11:07:13 UTC 2017
The following commit has been merged in the master branch:
commit 1d0906852a4cea708dfdb4940a4b8c645bb22fb9
Author: IOhannes m zmölnig <zmoelnig at umlautQ.umlaeute.mur.at>
Date: Mon Jun 19 12:53:29 2017 +0200
New upstream version 0.9.0
diff --git a/.travis.yml b/.travis.yml
index ac3132a..860fe77 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,17 +6,18 @@ python:
- "3.3"
- "3.4"
- "3.5"
+ - "3.6"
- "nightly"
- - "pypy"
- # TODO: Enable pypy3 once NumPy is working there:
+ - "pypy-5.3.1"
+ - "pypy-5.4.1"
+ # TODO: Enable pypy3 once NumPy is working there, see
+ # https://bitbucket.org/pypy/pypy/issues/1567/
#- "pypy3"
addons:
apt:
packages:
- libsndfile1
install:
- # TODO: remove "@pypy-2.6.0" once
- # https://github.com/travis-ci/travis-ci/issues/4756 is closed:
- - "if [ $TRAVIS_PYTHON_VERSION = pypy -o $TRAVIS_PYTHON_VERSION = pypy3 ]; then pip install git+https://bitbucket.org/pypy/numpy.git@pypy-2.6.0 ; fi"
+ - "if [[ $TRAVIS_PYTHON_VERSION == pypy* ]]; then pip install git+https://bitbucket.org/pypy/numpy.git ; fi"
script:
- python setup.py test
diff --git a/LICENSE b/LICENSE
index 5def83f..74d836a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -11,7 +11,7 @@ met:
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
- * Neither the name of the <ORGANIZATION> nor the names
+ * Neither the name of PySoundFile nor the names
of its contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
@@ -26,4 +26,4 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.rst b/README.rst
index 8dbcaa4..2c1312e 100644
--- a/README.rst
+++ b/README.rst
@@ -31,6 +31,10 @@ In 0.8.0, we changed the default value of ``always_2d`` from ``True``
to ``False``. Also, the order of arguments of the ``write`` function
changed from ``write(data, file, ...)`` to ``write(file, data, ...)``.
+In 0.9.0, we changed the ``ctype`` arguments of the ``buffer_*``
+methods to ``dtype``, using the Numpy ``dtype`` notation. The old
+``ctype`` arguments still work, but are now officially deprecated.
+
Installation
------------
@@ -229,3 +233,16 @@ News
``write(data, file, ...)`` to ``write(file, data, ...)``
And many more minor bug fixes.
+
+2017-02-02 V0.9.0 Bastian Bechtold:
+ Thank you, Matthias Geier, Tomas Garcia, and Todd, for contributions
+ for this release.
+
+ - Adds support for ALAC files.
+ - Adds new member ``__libsndfile_version__``
+ - Adds number of frames to ``info`` class
+ - Adds ``dtype`` argument to ``buffer_*`` methods
+ - Deprecates ``ctype`` argument to ``buffer_*`` methods
+ - Adds official support for Python 3.6
+
+ And some minor bug fixes.
diff --git a/doc/fake_cffi.py b/doc/fake_cffi.py
index 66ed279..ea1cc30 100644
--- a/doc/fake_cffi.py
+++ b/doc/fake_cffi.py
@@ -2,10 +2,17 @@
class FFI(object):
+
def cdef(self, _):
pass
def dlopen(self, _):
return self
+ def string(self, _):
+ return b'not implemented'
+
+ def sf_version_string(self):
+ return NotImplemented
+
SFC_GET_FORMAT_INFO = NotImplemented
diff --git a/setup.py b/setup.py
index e75b421..cfd57f1 100644
--- a/setup.py
+++ b/setup.py
@@ -7,9 +7,9 @@ import sys
PYTHON_INTERPRETERS = '.'.join([
'cp26', 'cp27',
- 'cp32', 'cp33', 'cp34', 'cp35',
+ 'cp32', 'cp33', 'cp34', 'cp35', 'cp36',
'pp27',
- 'pp32',
+ 'pp32', 'pp33',
])
MACOSX_VERSIONS = '.'.join([
'macosx_10_5_x86_64',
@@ -29,15 +29,18 @@ elif platform == 'win32':
else:
libname = None
-if libname:
+if libname and os.path.isdir('_soundfile_data'):
packages = ['_soundfile_data']
package_data = {'_soundfile_data': [libname, 'COPYING']}
+ zip_safe = False
else:
packages = None
package_data = None
+ zip_safe = True
class PyTest(TestCommand):
+
user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")]
def initialize_options(self):
@@ -62,8 +65,10 @@ try:
except ImportError:
pass
else:
+
class bdist_wheel_half_pure(bdist_wheel):
"""Create OS-dependent, but Python-independent wheels."""
+
def get_tag(self):
pythons = 'py2.py3.' + PYTHON_INTERPRETERS
if platform == 'darwin':
@@ -82,7 +87,7 @@ else:
setup(
name='SoundFile',
- version='0.8.1',
+ version='0.9.0',
description='An audio library based on libsndfile, CFFI and NumPy',
author='Bastian Bechtold',
author_email='basti at bastibe.de',
@@ -91,6 +96,7 @@ setup(
py_modules=['soundfile'],
packages=packages,
package_data=package_data,
+ zip_safe=zip_safe,
license='BSD 3-Clause License',
install_requires=['cffi>=0.6'],
extras_require={'numpy': ['numpy']},
diff --git a/soundfile.py b/soundfile.py
index e1d34e0..4e62296 100644
--- a/soundfile.py
+++ b/soundfile.py
@@ -8,7 +8,7 @@ Alternatively, sound files can be opened as :class:`SoundFile` objects.
For further information, see http://pysoundfile.readthedocs.org/.
"""
-__version__ = "0.8.1"
+__version__ = "0.9.0"
import os as _os
import sys as _sys
@@ -31,6 +31,7 @@ enum
enum
{
+ SFC_GET_LIB_VERSION = 0x1000,
SFC_GET_LOG_INFO = 0x1001,
SFC_GET_FORMAT_INFO = 0x1028,
@@ -92,10 +93,12 @@ 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) ;
-sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
-sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
-sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
-sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
+/* 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) ;
@@ -114,6 +117,7 @@ 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) ;
@@ -210,6 +214,10 @@ _subtypes = {
'DPCM_8': 0x0050, # 8 bit differential PCM (XI only)
'DPCM_16': 0x0051, # 16 bit differential PCM (XI only)
'VORBIS': 0x0060, # Xiph Vorbis encoding.
+ 'ALAC_16': 0x0070, # Apple Lossless Audio Codec (16 bit).
+ 'ALAC_20': 0x0071, # Apple Lossless Audio Codec (20 bit).
+ 'ALAC_24': 0x0072, # Apple Lossless Audio Codec (24 bit).
+ 'ALAC_32': 0x0073, # Apple Lossless Audio Codec (32 bit).
}
_endians = {
@@ -257,7 +265,7 @@ _ffi_types = {
try:
_snd = _ffi.dlopen('sndfile')
-except OSError as err:
+except OSError:
if _sys.platform == 'darwin':
_libname = 'libsndfile.dylib'
elif _sys.platform == 'win32':
@@ -269,6 +277,10 @@ except OSError as err:
_os.path.dirname(_os.path.abspath(__file__)),
'_soundfile_data', _libname))
+__libsndfile_version__ = _ffi.string(_snd.sf_version_string()).decode('utf-8', 'replace')
+if __libsndfile_version__.startswith('libsndfile-'):
+ __libsndfile_version__ = __libsndfile_version__[len('libsndfile-'):]
+
def read(file, frames=-1, start=0, stop=None, dtype='float64', always_2d=False,
fill_value=None, out=None, samplerate=None, channels=None,
@@ -481,13 +493,15 @@ def blocks(file, blocksize=None, overlap=0, frames=-1, start=0, stop=None,
class _SoundFileInfo(object):
"""Information about a SoundFile"""
+
def __init__(self, file, verbose):
self.verbose = verbose
with SoundFile(file) as f:
self.name = f.name
self.samplerate = f.samplerate
self.channels = f.channels
- self.duration = len(f)/f.samplerate
+ self.frames = len(f)
+ self.duration = self.frames/f.samplerate
self.format = f.format
self.subtype = f.subtype
self.endian = f.endian
@@ -520,6 +534,7 @@ class _SoundFileInfo(object):
info += "\n".join(
["\nendian: {0.endian}",
"sections: {0.sections}",
+ "frames: {0.frames}",
'extra_info: """',
' {1}"""'])
indented_extra_info = ("\n"+" "*4).join(self.extra_info.split("\n"))
@@ -616,7 +631,6 @@ def default_subtype(format):
class SoundFile(object):
-
"""A sound file.
For more documentation see the __init__() docstring (which is also
@@ -768,7 +782,7 @@ class SoundFile(object):
info = _ffi.new("char[]", 2**14)
_snd.sf_command(self._file, _snd.SFC_GET_LOG_INFO,
info, _ffi.sizeof(info))
- return _ffi.string(info).decode()
+ return _ffi.string(info).decode('utf-8', 'replace')
# avoid confusion if something goes wrong before assigning self._file:
_file = None
@@ -803,7 +817,7 @@ class SoundFile(object):
if name in _str_types:
self._check_if_closed()
data = _snd.sf_get_string(self._file, _str_types[name])
- return _ffi.string(data).decode() if data else ""
+ return _ffi.string(data).decode('utf-8', 'replace') if data else ""
else:
raise AttributeError(
"'SoundFile' object has no attribute {0!r}".format(name))
@@ -956,10 +970,10 @@ class SoundFile(object):
out[frames:] = fill_value
return out
- def buffer_read(self, frames=-1, ctype='double'):
+ def buffer_read(self, frames=-1, ctype=None, dtype=None):
"""Read from the file and return data as buffer object.
- Reads the given number of frames in the given data format
+ Reads the given number of `frames` in the given data format
starting at the current read/write position. This advances the
read/write position by the same number of frames.
By default, all frames from the current read/write position to
@@ -971,8 +985,8 @@ class SoundFile(object):
frames : int, optional
The number of frames to read. If `frames < 0`, the whole
rest of the file is read.
- ctype : {'double', 'float', 'int', 'short'}, optional
- Audio data will be converted to the given C data type.
+ dtype : {'float64', 'float32', 'int32', 'int16'}
+ Audio data will be converted to the given data type.
Returns
-------
@@ -985,30 +999,32 @@ class SoundFile(object):
"""
frames = self._check_frames(frames, fill_value=None)
+ dtype = self._ctype_is_deprecated(ctype, dtype)
+ ctype = self._check_dtype(dtype)
cdata = _ffi.new(ctype + '[]', frames * self.channels)
read_frames = self._cdata_io('read', cdata, ctype, frames)
assert read_frames == frames
return _ffi.buffer(cdata)
- def buffer_read_into(self, buffer, ctype='double'):
- """Read from the file into a buffer object.
+ def buffer_read_into(self, buffer, ctype=None, dtype=None):
+ """Read from the file into a given buffer object.
- Reads the given number of frames in the given data format
- starting at the current read/write position. This advances the
- read/write position by the same number of frames.
- By default, all frames from the current read/write position to
- the end of the file are returned.
- Use :meth:`.seek` to move the current read/write position.
+ Fills the given `buffer` with frames in the given data format
+ starting at the current read/write position (which can be
+ changed with :meth:`.seek`) until the buffer is full or the end
+ of the file is reached. This advances the read/write position
+ by the number of frames that were read.
Parameters
----------
- out : writable buffer, optional
- If specified, audio data from the file is written to this
- buffer instead of a newly created buffer.
+ buffer : writable buffer
+ Audio frames from the file are written to this buffer.
+ dtype : {'float64', 'float32', 'int32', 'int16'}
+ The data type of `buffer`.
Returns
-------
- num_read : int
+ int
The number of frames that were read from the file.
This can be less than the size of `buffer`.
The rest of the buffer is not filled with meaningful data.
@@ -1018,6 +1034,8 @@ class SoundFile(object):
buffer_read, .read
"""
+ dtype = self._ctype_is_deprecated(ctype, dtype)
+ ctype = self._check_dtype(dtype)
cdata, frames = self._check_buffer(buffer, ctype)
frames = self._cdata_io('read', cdata, ctype, frames)
return frames
@@ -1075,26 +1093,29 @@ class SoundFile(object):
assert written == len(data)
self._update_len(written)
- def buffer_write(self, data, ctype):
+ def buffer_write(self, data, ctype=None, dtype=None):
"""Write audio data from a buffer/bytes object to the file.
- Writes a number of frames at the read/write position to the
- file. This also advances the read/write position by the same
- number of frames and enlarges the file if necessary.
+ Writes the contents of `data` to the file at the current
+ read/write position.
+ This also advances the read/write position by the number of
+ frames that were written and enlarges the file if necessary.
Parameters
----------
data : buffer or bytes
- A buffer object or bytes containing the audio data to be
+ A buffer or bytes object containing the audio data to be
written.
- ctype : {'double', 'float', 'int', 'short'}, optional
- The data type of the audio data stored in `buffer`.
+ dtype : {'float64', 'float32', 'int32', 'int16'}
+ The data type of the audio data stored in `data`.
See Also
--------
.write, buffer_read
"""
+ dtype = self._ctype_is_deprecated(ctype, dtype)
+ ctype = self._check_dtype(dtype)
cdata, frames = self._check_buffer(data, ctype)
written = self._cdata_io('write', cdata, ctype, frames)
assert written == frames
@@ -1332,6 +1353,7 @@ class SoundFile(object):
def _check_buffer(self, data, ctype):
"""Convert buffer to cdata and check for valid size."""
+ assert ctype in _ffi_types.values()
if not isinstance(data, bytes):
data = _ffi.from_buffer(data)
frames, remainder = divmod(len(data),
@@ -1349,6 +1371,31 @@ class SoundFile(object):
shape = frames,
return np.empty(shape, dtype, order='C')
+ def _check_dtype(self, dtype):
+ """Check if dtype string is valid and return ctype string."""
+ try:
+ return _ffi_types[dtype]
+ except KeyError:
+ raise ValueError("dtype must be one of {0!r}".format(
+ sorted(_ffi_types.keys())))
+
+ def _ctype_is_deprecated(self, ctype, dtype):
+ """Show warning if ctype is used instead of dtype.
+
+ At some point, ctype arguments shall be removed and the
+ corresponding dtype arguments shall lose their default value.
+
+ """
+ if ctype is not None:
+ from warnings import warn
+ warn('ctype is deprecated; use dtype instead', Warning)
+ if dtype is not None:
+ raise TypeError('Use dtype instead of ctype')
+ for k, v in _ffi_types.items():
+ if v == ctype:
+ return k
+ return dtype
+
def _array_io(self, action, array, frames):
"""Check array and call low-level IO function."""
if (array.ndim not in (1, 2) or
@@ -1357,19 +1404,14 @@ class SoundFile(object):
raise ValueError("Invalid shape: {0!r}".format(array.shape))
if not array.flags.c_contiguous:
raise ValueError("Data must be C-contiguous")
- try:
- ctype = _ffi_types[array.dtype.name]
- except KeyError:
- raise TypeError("dtype must be one of {0!r}".format(
- sorted(_ffi_types.keys())))
+ ctype = self._check_dtype(array.dtype.name)
assert array.dtype.itemsize == _ffi.sizeof(ctype)
cdata = _ffi.cast(ctype + '*', array.__array_interface__['data'][0])
return self._cdata_io(action, cdata, ctype, frames)
def _cdata_io(self, action, data, ctype, frames):
"""Call one of libsndfile's read/write functions."""
- if ctype not in _ffi_types.values():
- raise ValueError("Unsupported data type: {0!r}".format(ctype))
+ assert ctype in _ffi_types.values()
self._check_if_closed()
if self.seekable():
curr = self.tell()
@@ -1410,7 +1452,7 @@ def _error_check(err, prefix=""):
"""Pretty-print a numerical error code if there is an error."""
if err != 0:
err_str = _snd.sf_error_number(err)
- raise RuntimeError(prefix + _ffi.string(err_str).decode())
+ raise RuntimeError(prefix + _ffi.string(err_str).decode('utf-8', 'replace'))
def _format_int(format, subtype, endian):
@@ -1506,7 +1548,7 @@ def _get_format_from_filename(file, mode):
# This raises an exception if file is not a (Unicode/byte) string:
format = _os.path.splitext(file)[-1][1:]
# Convert bytes to unicode (raises AttributeError on Python 3 str):
- format = format.decode()
+ format = format.decode('utf-8', 'replace')
except Exception:
pass
if format.upper() not in _formats and 'r' not in mode:
@@ -1521,6 +1563,8 @@ def _format_str(format_int):
for k, v in dictionary.items():
if v == format_int:
return k
+ else:
+ return 'n/a'
def _format_info(format_int, format_flag=_snd.SFC_GET_FORMAT_INFO):
@@ -1531,7 +1575,7 @@ def _format_info(format_int, format_flag=_snd.SFC_GET_FORMAT_INFO):
_ffi.sizeof("SF_FORMAT_INFO"))
name = format_info.name
return (_format_str(format_info.format),
- _ffi.string(name).decode() if name else "")
+ _ffi.string(name).decode('utf-8', 'replace') if name else "")
def _available_formats_helper(count_flag, format_flag):
diff --git a/tests/test_pysoundfile.py b/tests/test_pysoundfile.py
index fad54f0..ca10325 100644
--- a/tests/test_pysoundfile.py
+++ b/tests/test_pysoundfile.py
@@ -193,7 +193,7 @@ def test_read_into_non_contiguous_out(file_stereo_r):
def test_read_into_out_with_invalid_dtype(file_stereo_r):
out = np.empty((3, 2), dtype='int64')
- with pytest.raises(TypeError) as excinfo:
+ with pytest.raises(ValueError) as excinfo:
sf.read(file_stereo_r, out=out)
assert "dtype must be one of" in str(excinfo.value)
@@ -522,6 +522,7 @@ def test_if_open_with_mode_w_truncates(file_stereo_rplus, mode):
class LimitedFile(object):
+
def __init__(self, file, attrs):
for attr in attrs:
setattr(self, attr, getattr(file, attr))
@@ -730,33 +731,33 @@ def test_read_into_out_over_end_with_fill_should_return_full_data_and_write_into
def test_buffer_read(sf_stereo_r):
- buf = sf_stereo_r.buffer_read(2)
+ buf = sf_stereo_r.buffer_read(2, dtype='float64')
assert len(buf) == 2 * 2 * 8
assert sf_stereo_r.seek(0, sf.SEEK_CUR) == 2
data = np.frombuffer(buf, dtype='float64').reshape(-1, 2)
assert np.all(data == data_stereo[:2])
- buf = sf_stereo_r.buffer_read(ctype='float')
+ buf = sf_stereo_r.buffer_read(dtype='float32')
assert len(buf) == 2 * 2 * 4
assert sf_stereo_r.seek(0, sf.SEEK_CUR) == 4
data = np.frombuffer(buf, dtype='float32').reshape(-1, 2)
assert np.all(data == data_stereo[2:])
- buf = sf_stereo_r.buffer_read()
+ buf = sf_stereo_r.buffer_read(dtype='float32')
assert len(buf) == 0
- buf = sf_stereo_r.buffer_read(666)
+ buf = sf_stereo_r.buffer_read(666, dtype='float32')
assert len(buf) == 0
with pytest.raises(ValueError) as excinfo:
- sf_stereo_r.buffer_read(ctype='char')
- assert "Unsupported data type" in str(excinfo.value)
+ sf_stereo_r.buffer_read(dtype='int8')
+ assert "dtype must be one of" in str(excinfo.value)
@xfail_from_buffer
def test_buffer_read_into(sf_stereo_r):
out = np.ones((3, 2))
- frames = sf_stereo_r.buffer_read_into(out)
+ frames = sf_stereo_r.buffer_read_into(out, dtype='float64')
assert frames == 3
assert np.all(out == data_stereo[:3])
assert sf_stereo_r.seek(0, sf.SEEK_CUR) == 3
- frames = sf_stereo_r.buffer_read_into(out)
+ frames = sf_stereo_r.buffer_read_into(out, dtype='float64')
assert frames == 1
assert np.all(out[:1] == data_stereo[3:])
assert sf_stereo_r.seek(0, sf.SEEK_CUR) == 4
@@ -814,7 +815,7 @@ def test_rplus_append_data(sf_stereo_rplus):
@xfail_from_buffer
def test_buffer_write(sf_stereo_w):
buf = np.array([[1, 2], [-1, -2]], dtype='int16')
- sf_stereo_w.buffer_write(buf, 'short')
+ sf_stereo_w.buffer_write(buf, dtype='int16')
sf_stereo_w.close()
data, fs = sf.read(filename_new, dtype='int16')
assert np.all(data == buf)
@@ -823,7 +824,7 @@ def test_buffer_write(sf_stereo_w):
def test_buffer_write_with_bytes(sf_stereo_w):
b = b"\x01\x00\xFF\xFF\xFF\x00\x00\xFF"
- sf_stereo_w.buffer_write(b, 'short')
+ sf_stereo_w.buffer_write(b, dtype='int16')
sf_stereo_w.close()
data, fs = sf.read(filename_new, dtype='int16')
assert np.all(data == [[1, -1], [255, -256]])
@@ -834,7 +835,7 @@ def test_buffer_write_with_bytes(sf_stereo_w):
def test_buffer_write_with_wrong_size(sf_stereo_w):
buf = np.array([1, 2, 3], dtype='int16')
with pytest.raises(ValueError) as excinfo:
- sf_stereo_w.buffer_write(buf, 'short')
+ sf_stereo_w.buffer_write(buf, dtype='int16')
assert "multiple of frame size" in str(excinfo.value)
@@ -910,6 +911,10 @@ def test_read_int_data_from_float_file(file_inmemory):
assert fs == 44100
+def test_libsndfile_version():
+ assert '.' in sf.__libsndfile_version__
+
+
# -----------------------------------------------------------------------------
# RAW tests
# -----------------------------------------------------------------------------
--
pysoundfile packaging
More information about the pkg-multimedia-commits
mailing list