Skip to content

Commit a299a8b

Browse files
committed
Merge pull request #145 from bastibe/int-float-scaling
Activate SFC_SET_SCALE_INT_FLOAT_WRITE?
2 parents 10c22f3 + e5361e8 commit a299a8b

File tree

1 file changed

+102
-15
lines changed

1 file changed

+102
-15
lines changed

soundfile.py

Lines changed: 102 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
SFC_GET_FORMAT_SUBTYPE = 0x1033,
4141
SFC_FILE_TRUNCATE = 0x1080,
4242
SFC_SET_CLIPPING = 0x10C0,
43+
44+
SFC_SET_SCALE_FLOAT_INT_READ = 0x1014,
45+
SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015,
4346
} ;
4447
4548
enum
@@ -300,6 +303,11 @@ def read(file, frames=-1, start=0, stop=None, dtype='float64', always_2d=False,
300303
``-2**15`` to ``2**15-1`` for ``'int16'`` and from ``-2**31`` to
301304
``2**31-1`` for ``'int32'``.
302305
306+
.. note:: Reading int values from a float file will *not*
307+
scale the data to [-1.0, 1.0). If the file contains
308+
``np.array([42.6], dtype='float32')``, you will read
309+
``np.array([43], dtype='int32')`` for ``dtype='int32'``.
310+
303311
Returns
304312
-------
305313
audiodata : numpy.ndarray or type(out)
@@ -373,8 +381,13 @@ def write(file, data, samplerate, subtype=None, endian=None, format=None,
373381
and ``'int16'`` are supported.
374382
375383
.. note:: The data type of `data` does **not** select the data
376-
type of the written file.
377-
Audio data will be converted to the given `subtype`.
384+
type of the written file. Audio data will be
385+
converted to the given `subtype`. Writing int values
386+
to a float file will *not* scale the values to
387+
[-1.0, 1.0). If you write the value ``np.array([42],
388+
dtype='int32')``, to a ``subtype='FLOAT'`` file, the
389+
file will then contain ``np.array([42.],
390+
dtype='float32')``.
378391
379392
samplerate : int
380393
The sample rate of the audio data.
@@ -389,8 +402,7 @@ def write(file, data, samplerate, subtype=None, endian=None, format=None,
389402
390403
Examples
391404
--------
392-
393-
Write 10 frames of random data to a file:
405+
Write 10 frames of random data to a new file:
394406
395407
>>> import numpy as np
396408
>>> import soundfile as sf
@@ -865,18 +877,52 @@ def read(self, frames=-1, dtype='float64', always_2d=False,
865877
The number of frames to read. If ``frames < 0``, the whole
866878
rest of the file is read.
867879
dtype : {'float64', 'float32', 'int32', 'int16'}, optional
868-
See :func:`read`.
880+
Data type of the returned array, by default ``'float64'``.
881+
Floating point audio data is typically in the range from
882+
``-1.0`` to ``1.0``. Integer data is in the range from
883+
``-2**15`` to ``2**15-1`` for ``'int16'`` and from
884+
``-2**31`` to ``2**31-1`` for ``'int32'``.
885+
886+
.. note:: Reading int values from a float file will *not*
887+
scale the data to [-1.0, 1.0). If the file contains
888+
``np.array([42.6], dtype='float32')``, you will read
889+
``np.array([43], dtype='int32')`` for
890+
``dtype='int32'``.
869891
870892
Returns
871893
-------
872-
numpy.ndarray or type(out)
873-
The read data; either a new array or `out` or a view into
874-
`out`. See :func:`read` for details.
894+
audiodata : numpy.ndarray or type(out)
895+
A two-dimensional NumPy array is returned, where the
896+
channels are stored along the first dimension, i.e. as
897+
columns. If the sound file has only one channel, a
898+
one-dimensional array is returned. Use ``always_2d=True``
899+
to return a two-dimensional array anyway.
900+
901+
If `out` was specified, it is returned. If `out` has more
902+
frames than available in the file (or if `frames` is
903+
smaller than the length of `out`) and no `fill_value` is
904+
given, then only a part of `out` is overwritten and a view
905+
containing all valid frames is returned. numpy.ndarray or
906+
type(out)
875907
876908
Other Parameters
877909
----------------
878-
always_2d, fill_value, out
879-
See :func:`read`.
910+
always_2d : bool, optional
911+
By default, reading a mono sound file will return a
912+
one-dimensional array. With ``always_2d=True``, audio data
913+
is always returned as a two-dimensional array, even if the
914+
audio file has only one channel.
915+
fill_value : float, optional
916+
If more frames are requested than available in the file,
917+
the rest of the output is be filled with `fill_value`. If
918+
`fill_value` is not specified, a smaller array is
919+
returned.
920+
out : numpy.ndarray or subclass, optional
921+
If `out` is specified, the data is written into the given
922+
array instead of creating a new array. In this case, the
923+
arguments `dtype` and `always_2d` are silently ignored! If
924+
`frames` is not given, it is obtained from the length of
925+
`out`.
880926
881927
Examples
882928
--------
@@ -962,7 +1008,7 @@ def buffer_read_into(self, buffer, ctype='double'):
9621008
9631009
Returns
9641010
-------
965-
int
1011+
num_read : int
9661012
The number of frames that were read from the file.
9671013
This can be less than the size of `buffer`.
9681014
The rest of the buffer is not filled with meaningful data.
@@ -983,10 +1029,39 @@ def write(self, data):
9831029
file. This also advances the read/write position by the same
9841030
number of frames and enlarges the file if necessary.
9851031
1032+
Note that writing int values to a float file will *not* scale
1033+
the values to [-1.0, 1.0). If you write the value
1034+
``np.array([42], dtype='int32')``, to a ``subtype='FLOAT'``
1035+
file, the file will then contain ``np.array([42.],
1036+
dtype='float32')``.
1037+
9861038
Parameters
9871039
----------
9881040
data : array_like
989-
See :func:`write`.
1041+
The data to write. Usually two-dimensional (channels x
1042+
frames), but one-dimensional `data` can be used for mono
1043+
files. Only the data types ``'float64'``, ``'float32'``,
1044+
``'int32'`` and ``'int16'`` are supported.
1045+
1046+
.. note:: The data type of `data` does **not** select the
1047+
data type of the written file. Audio data will be
1048+
converted to the given `subtype`. Writing int values
1049+
to a float file will *not* scale the values to
1050+
[-1.0, 1.0). If you write the value ``np.array([42],
1051+
dtype='int32')``, to a ``subtype='FLOAT'`` file, the
1052+
file will then contain ``np.array([42.],
1053+
dtype='float32')``.
1054+
1055+
Examples
1056+
--------
1057+
>>> import numpy as np
1058+
>>> from soundfile import SoundFile
1059+
>>> myfile = SoundFile('stereo_file.wav')
1060+
1061+
Write 10 frames of random data to a new file:
1062+
1063+
>>> with SoundFile('stereo_file.wav', 'w', 44100, 2, 'PCM_24') as f:
1064+
>>> f.write(np.random.randn(10, 2))
9901065
9911066
See Also
9921067
--------
@@ -1044,17 +1119,29 @@ def blocks(self, blocksize=None, overlap=0, frames=-1, dtype='float64',
10441119
The number of frames to read.
10451120
If ``frames < 1``, the file is read until the end.
10461121
dtype : {'float64', 'float32', 'int32', 'int16'}, optional
1047-
See :func:`read`.
1122+
See :meth:`.read`.
10481123
10491124
Yields
10501125
------
10511126
numpy.ndarray or type(out)
1052-
Blocks of audio data. See :func:`blocks` for details.
1127+
Blocks of audio data.
1128+
If `out` was given, and the requested frames are not an
1129+
integer multiple of the length of `out`, and no
1130+
`fill_value` was given, the last block will be a smaller
1131+
view into `out`.
1132+
10531133
10541134
Other Parameters
10551135
----------------
10561136
always_2d, fill_value, out
1057-
See :func:`read`.
1137+
See :meth:`.read`.
1138+
1139+
Examples
1140+
--------
1141+
>>> from soundfile import SoundFile
1142+
>>> with SoundFile('stereo_file.wav') as f:
1143+
>>> for block in f.blocks(blocksize=1024):
1144+
>>> pass # do something with 'block'
10581145
10591146
"""
10601147
if 'r' not in self.mode and '+' not in self.mode:

0 commit comments

Comments
 (0)