diff --git a/apps/auracast.py b/apps/auracast.py index 5a8d9582..77e58ed4 100644 --- a/apps/auracast.py +++ b/apps/auracast.py @@ -924,6 +924,14 @@ async def run_transmit( if pcm_format.channels != 2: print("Only 2 channels PCM configurations are supported") return + if pcm_format.sample_type == audio_io.PcmFormat.SampleType.INT16: + pcm_bit_depth = 16 + elif pcm_format.sample_type == audio_io.PcmFormat.SampleType.FLOAT32: + pcm_bit_depth = None + else: + print("Only INT16 and FLOAT32 sample types are supported") + return + encoder = lc3.Encoder( frame_duration_us=AURACAST_DEFAULT_FRAME_DURATION, sample_rate_hz=AURACAST_DEFAULT_SAMPLE_RATE, @@ -971,7 +979,7 @@ async def run_transmit( frame_count = 0 async for pcm_frame in audio_input.frames(lc3_frame_samples): lc3_frame = encoder.encode( - pcm_frame, num_bytes=2 * lc3_frame_size, bit_depth=16 + pcm_frame, num_bytes=2 * lc3_frame_size, bit_depth=pcm_bit_depth ) mid = len(lc3_frame) // 2 @@ -1150,7 +1158,8 @@ def receive( "Use 'auto' for .wav files, or for the default setting with the devices. " "For other inputs, the format is specified as " ",, (supported : 'int16le' " - "for 16 bit signed integers with little-endian byte order)" + "for 16-bit signed integers with little-endian byte order or 'float32le' for " + "32-bit floating point with little-endian byte order)" ), ) @click.option( diff --git a/bumble/audio/io.py b/bumble/audio/io.py index 4a00f887..e7c7fe26 100644 --- a/bumble/audio/io.py +++ b/bumble/audio/io.py @@ -68,7 +68,7 @@ class PcmFormat: sample_type_str, sample_rate_str, channels_str = format_str.split(',') if sample_type_str == 'int16le': sample_type = cls.SampleType.INT16 - elif sample_rate_str == 'float32le': + elif sample_type_str == 'float32le': sample_type = cls.SampleType.FLOAT32 else: raise ValueError(f'sample type {sample_type_str} not supported') @@ -77,6 +77,10 @@ class PcmFormat: return cls(endianness, sample_type, sample_rate, channels) + @property + def bytes_per_sample(self) -> int: + return 2 if self.sample_type == self.SampleType.INT16 else 4 + def check_audio_output(output: str) -> bool: if output == 'device' or output.startswith('device:'): @@ -486,7 +490,9 @@ class StreamAudioInput(ThreadedAudioInput): return self._pcm_format def _read(self, frame_size: int) -> bytes: - return self._stream.read(frame_size * self._pcm_format.channels * 2) + return self._stream.read( + frame_size * self._pcm_format.channels * self._pcm_format.bytes_per_sample + ) class FileAudioInput(StreamAudioInput): @@ -496,9 +502,6 @@ class FileAudioInput(StreamAudioInput): self._stream = open(filename, "rb") super().__init__(self._stream, pcm_format) - def _read(self, frame_size: int) -> bytes: - return self._stream.read(frame_size * self._pcm_format.channels * 2) - def _close(self) -> None: self._stream.close()