Skip to content

Commit

Permalink
Automatically detect bit depth in FileEncoder, and raise error
Browse files Browse the repository at this point in the history
  • Loading branch information
joetoddsonos committed Mar 31, 2024
1 parent a3945c3 commit 949cf63
Show file tree
Hide file tree
Showing 7 changed files with 18 additions and 21 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
pyFLAC Changelog
----------------

**v2.3.0**
**v3.0.0**

* Fixed bug in the shutdown behaviour of the decoder (see #22 and #23).
* Automatically detect bit depth of input data in the `FileEncoder`, and
raise an error if not 16-bit or 32-bit PCM (see #24).

**v2.2.0**

Expand Down
2 changes: 0 additions & 2 deletions pyflac/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def get_args():
parser.add_argument('-c', '--compression-level', type=int, choices=range(0, 9), default=5,
help='0 is the fastest compression, 5 is the default, 8 is the highest compression')
parser.add_argument('-b', '--block-size', type=int, default=0, help='The block size')
parser.add_argument('-d', '--dtype', default='int16', help='The encoded data type (int16 or int32)')
parser.add_argument('-v', '--verify', action='store_false', default=True, help='Verify the compressed data')
args = parser.parse_args()
return args
Expand All @@ -45,7 +44,6 @@ def main():
input_file=args.input_file,
output_file=args.output_file,
blocksize=args.block_size,
dtype=args.dtype,
compression_level=args.compression_level,
verify=args.verify
)
Expand Down
2 changes: 1 addition & 1 deletion pyflac/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# pyFLAC decoder
#
# Copyright (c) 2020-2021, Sonos, Inc.
# Copyright (c) 2020-2024, Sonos, Inc.
# All rights reserved.
#
# ------------------------------------------------------------------------------
Expand Down
16 changes: 10 additions & 6 deletions pyflac/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# pyFLAC encoder
#
# Copyright (c) 2020-2021, Sonos, Inc.
# Copyright (c) 2020-2024, Sonos, Inc.
# All rights reserved.
#
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -335,6 +335,8 @@ class FileEncoder(_Encoder):
The pyFLAC file encoder reads the raw audio data from the WAV file and
writes the encoded audio data to a FLAC file.
Note that the input WAV file must be either PCM_16 or PCM_32.
Args:
input_file (pathlib.Path): Path to the input WAV file
output_file (pathlib.Path): Path to the output FLAC file, a temporary
Expand All @@ -345,8 +347,6 @@ class FileEncoder(_Encoder):
blocksize (int): The size of the block to be returned in the
callback. The default is 0 which allows libFLAC to determine
the best block size.
dtype (str): The data type to use in the FLAC encoder, either int16 or int32,
defaults to int16.
streamable_subset (bool): Whether to use the streamable subset for encoding.
If true the encoder will check settings for compatibility. If false,
the settings may take advantage of the full range that the format allows.
Expand All @@ -365,13 +365,17 @@ def __init__(self,
output_file: Path = None,
compression_level: int = 5,
blocksize: int = 0,
dtype: str = 'int16',
streamable_subset: bool = True,
verify: bool = False):
super().__init__()

if dtype not in ('int16', 'int32'):
raise ValueError('FLAC encoding data type must be either int16 or int32')
info = sf.info(str(input_file))
if info.subtype == 'PCM_16':
dtype = 'int16'
elif info.subtype == 'PCM_32':
dtype = 'int32'
else:
raise ValueError(f'WAV input data type must be either PCM_16 or PCM_32: Got {info.subtype}')

self.__raw_audio, sample_rate = sf.read(str(input_file), dtype=dtype)
if output_file:
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# pyFLAC
#
# Copyright (c) 2020-2023, Sonos, Inc.
# Copyright (c) 2020-2024, Sonos, Inc.
# All rights reserved.
#
# ------------------------------------------------------------------------------
Expand All @@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pyFLAC"
version = "2.3.0"
version = "3.0.0"
description = "A Python wrapper for libFLAC"
readme = "README.rst"
authors = [{ name = "Joe Todd", email = "[email protected]" }]
Expand Down
2 changes: 1 addition & 1 deletion tests/test_decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# pyFLAC decoder test suite
#
# Copyright (c) 2020-2021, Sonos, Inc.
# Copyright (c) 2020-2024, Sonos, Inc.
# All rights reserved.
#
# ------------------------------------------------------------------------------
Expand Down
9 changes: 1 addition & 8 deletions tests/test_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# pyFLAC encoder test suite
#
# Copyright (c) 2020-2021, Sonos, Inc.
# Copyright (c) 2020-2024, Sonos, Inc.
# All rights reserved.
#
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -237,12 +237,6 @@ def test_invalid_blocksize(self):
with self.assertRaisesRegex(EncoderInitException, 'FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE'):
self.encoder._init()

def test_invalid_dtype(self):
""" Test than an exception is raised if given an invalid dtype """
self.default_kwargs['dtype'] = 'int24'
with self.assertRaisesRegex(ValueError, 'FLAC encoding data type must be either int16 or int32'):
self.encoder = FileEncoder(**self.default_kwargs)

def test_blocksize_streamable_subset(self):
""" Test that an exception is raised if blocksize is outside the streamable subset """
self.default_kwargs['blocksize'] = 65535
Expand Down Expand Up @@ -291,7 +285,6 @@ def test_process_32_bit_file(self):
test_path = pathlib.Path(__file__).parent.absolute() / 'data/32bit.wav'
self.default_kwargs['input_file'] = test_path
self.default_kwargs['output_file'] = pathlib.Path(self.temp_file.name)
self.default_kwargs['dtype'] = 'int32'
self.encoder = FileEncoder(**self.default_kwargs)
self.encoder.process()

Expand Down

0 comments on commit 949cf63

Please sign in to comment.