From ca7660270b00e7798ca11f69c9dc8dc470c7a299 Mon Sep 17 00:00:00 2001 From: Albert Ho <82767499+albho@users.noreply.github.com> Date: Wed, 24 Jul 2024 12:32:31 -0700 Subject: [PATCH] Change api (#4) --- .github/workflows/python.yml | 21 +++ README.md | 16 +- binding/python/README.md | 14 +- binding/python/_pvspeaker.py | 109 ++++++----- binding/python/setup.py | 2 +- binding/python/test_pv_speaker.py | 76 ++++---- demo/c/README.md | 2 +- demo/c/pv_speaker_demo.c | 61 +++--- demo/python/README.md | 4 +- demo/python/pv_speaker_demo.py | 48 ++++- demo/python/requirements.txt | 2 +- demo/python/setup.py | 4 +- lib/linux/x86_64/libpv_speaker.so | Bin 877128 -> 877208 bytes lib/mac/arm64/libpv_speaker.dylib | Bin 623536 -> 623568 bytes lib/mac/x86_64/libpv_speaker.dylib | Bin 680952 -> 681000 bytes .../cortex-a53-aarch64/libpv_speaker.so | Bin 824592 -> 824672 bytes lib/raspberry-pi/cortex-a53/libpv_speaker.so | Bin 756280 -> 756376 bytes .../cortex-a72-aarch64/libpv_speaker.so | Bin 824592 -> 824672 bytes lib/raspberry-pi/cortex-a72/libpv_speaker.so | Bin 780920 -> 781016 bytes .../cortex-a76-aarch64/libpv_speaker.so | Bin 816832 -> 816912 bytes lib/raspberry-pi/cortex-a76/libpv_speaker.so | Bin 849648 -> 849744 bytes lib/windows/amd64/libpv_speaker.dll | Bin 958817 -> 959909 bytes project/README.md | 52 +++--- project/include/pv_circular_buffer.h | 11 +- project/include/pv_speaker.h | 59 +++--- project/src/pv_circular_buffer.c | 12 +- project/src/pv_speaker.c | 175 +++++++++++------- project/test/test_pv_circular_buffer.c | 11 +- project/test/test_pv_speaker.c | 125 +++++++++---- 29 files changed, 520 insertions(+), 284 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index d68eee5..8589aa0 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -46,6 +46,14 @@ jobs: with: python-version: ${{ matrix.python-version }} + # GitHub Actions runners do not have sound cards, so a virtual one must be created in order for unit tests to run. + - name: Install PulseAudio on Ubuntu + run: | + sudo apt-get update + sudo apt-get install -y pulseaudio + pulseaudio --check || pulseaudio --start + pactl load-module module-null-sink + - name: Test run: python3 test_pv_speaker.py @@ -61,6 +69,19 @@ jobs: with: submodules: recursive + - name: Install PulseAudio + if: matrix.machine == 'rpi3-32' || + matrix.machine == 'rpi3-64' || + matrix.machine == 'rpi4-32' || + matrix.machine == 'rpi4-64' || + matrix.machine == 'rpi5-32' || + matrix.machine == 'rpi5-64' + run: | + sudo apt-get update + sudo apt-get install -y pulseaudio + pulseaudio --check || pulseaudio --start + pactl load-module module-null-sink + - name: Test run: python3 test_pv_speaker.py if: ${{ matrix.machine != 'pv-windows' }} diff --git a/README.md b/README.md index b208f16..75fa817 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ With a working speaker connected to your device run the following in the termina pv_speaker_demo --input_wav_path {INPUT_WAV_PATH} ``` -Replace `{INPUT_WAV_PATH}` with the path to the pcm `wav` file you wish to play. +Replace `{INPUT_WAV_PATH}` with the path to the PCM WAV file you wish to play. For more information about the Python demos go to [demo/python](demo/python). @@ -89,7 +89,7 @@ Play from a single-channel PCM WAV file with a given audio device index: ./pv_speaker_demo -i test.wav -d 2 ``` -Hit `Ctrl+C` if you wish to stop audio playback before it completes. If no audio device index (`-d`) is provided, the demo will use the system's default audio player device. +Hit `Ctrl+C` if you wish to stop playing audio before it completes. If no audio device index (`-d`) is provided, the demo will use the system's default audio player device. For more information about the C demo, go to [demo/c](demo/c). @@ -119,13 +119,21 @@ def get_next_audio_frame(): speaker.write(get_next_audio_frame()) ``` -When all frames have been written, run `stop()` on the instance: +When all frames have been written, run `flush()` to wait for all buffered PCM data to be played: + +```python +speaker.flush() +``` + +To stop playing audio, run `stop()`: ```python speaker.stop() ``` -Once you are done, free the resources acquired by PvSpeaker. You do not have to call `stop()` before `delete()`: +Note that in order to stop the audio before it finishes playing, `stop` must be run on a separate thread from `flush`. + +Once you are done (i.e. no longer need PvSpeaker to write and/or play PCM), free the resources acquired by PvSpeaker by calling `delete`. Be sure to first call `stop` if the audio is still playing. Otherwise, if the audio has already finished playing, you do not have to call `stop` before `delete`: ```python speaker.delete() diff --git a/binding/python/README.md b/binding/python/README.md index 9eb992f..7857924 100644 --- a/binding/python/README.md +++ b/binding/python/README.md @@ -25,6 +25,7 @@ from pvspeaker import PvSpeaker speaker = PvSpeaker( sample_rate=22050, bits_per_sample=16, + buffer_size_secs=20, device_index=0) speaker.start() @@ -42,6 +43,7 @@ devices = PvSpeaker.get_available_devices() speaker = PvSpeaker( sample_rate=22050, bits_per_sample=16, + buffer_size_secs=20, device_index=0) speaker.start() @@ -56,13 +58,21 @@ def get_next_audio_frame(): speaker.write(get_next_audio_frame()) ``` -When all frames have been written, run `stop()` on the instance: +When all frames have been written, run `flush()` to wait for all buffered pcm data to be played: + +```python +speaker.flush() +``` + +To stop playing audio, run `stop()`: ```python speaker.stop() ``` -Once you are done, free the resources acquired by PvSpeaker. You do not have to call `stop()` before `delete()`: +Note that in order to stop the audio before it finishes playing, `stop` must be run on a separate thread from `flush`. + +Once you are done (i.e. no longer need PvSpeaker to write and/or play PCM), free the resources acquired by PvSpeaker by calling `delete`. Be sure to first call `stop` if the audio is still playing. Otherwise, if the audio has already finished playing, you do not have to call `stop` before `delete`: ```python speaker.delete() diff --git a/binding/python/_pvspeaker.py b/binding/python/_pvspeaker.py index 1ec0950..6eee654 100644 --- a/binding/python/_pvspeaker.py +++ b/binding/python/_pvspeaker.py @@ -57,7 +57,6 @@ class PvSpeakerStatuses(Enum): OUT_OF_MEMORY = 1 INVALID_ARGUMENT = 2 INVALID_STATE = 3 - BUFFER_OVERFLOW = 3 BACKEND_ERROR = 4 DEVICE_ALREADY_INITIALIZED = 5 DEVICE_NOT_INITIALIZED = 6 @@ -68,7 +67,6 @@ class PvSpeakerStatuses(Enum): PvSpeakerStatuses.OUT_OF_MEMORY: MemoryError, PvSpeakerStatuses.INVALID_ARGUMENT: ValueError, PvSpeakerStatuses.INVALID_STATE: ValueError, - PvSpeakerStatuses.BUFFER_OVERFLOW: IOError, PvSpeakerStatuses.BACKEND_ERROR: SystemError, PvSpeakerStatuses.DEVICE_ALREADY_INITIALIZED: ValueError, PvSpeakerStatuses.DEVICE_NOT_INITIALIZED: ValueError, @@ -86,19 +84,16 @@ def __init__( self, sample_rate: int, bits_per_sample: int, - device_index: int = -1, - frame_length: int = 512, - buffered_frames_count: int = 50): + buffer_size_secs: int = 20, + device_index: int = -1): """ Constructor :param sample_rate: The sample rate of the audio to be played. :param bits_per_sample: The number of bits per sample. + :param buffer_size_secs: The size in seconds of the internal buffer used to buffer pcm data + - i.e. internal circular buffer will be of size `sample_rate` * `buffer_size_secs`. :param device_index: The index of the audio device to use. A value of (-1) will resort to default device. - :param frame_length: The maximum length of audio frame that will be passed to each write call. - :param buffered_frames_count: The number of audio frames buffered internally for writing - i.e. internal - circular buffer will be of size `frame_length` * `buffered_frames_count`. If this value is too low, - buffer overflows could occur audio frames could be dropped. A higher value will increase memory usage. """ library = self._get_library() @@ -109,18 +104,17 @@ def __init__( c_int32, c_int32, c_int32, - c_int32, POINTER(POINTER(self.CPvSpeaker)) ] init_func.restype = self.PvSpeakerStatuses self._handle = POINTER(self.CPvSpeaker)() self._sample_rate = sample_rate - self._frame_length = frame_length self._bits_per_sample = bits_per_sample + self._buffer_size_secs = buffer_size_secs status = init_func( - sample_rate, frame_length, bits_per_sample, device_index, buffered_frames_count, byref(self._handle)) + sample_rate, bits_per_sample, buffer_size_secs, device_index, byref(self._handle)) if status is not self.PvSpeakerStatuses.SUCCESS: raise self._PVSPEAKER_STATUS_TO_EXCEPTION[status]("Failed to initialize PvSpeaker.") @@ -136,14 +130,14 @@ def __init__( self._stop_func.argtypes = [POINTER(self.CPvSpeaker)] self._stop_func.restype = self.PvSpeakerStatuses - self._set_debug_logging_func = library.pv_speaker_set_debug_logging - self._set_debug_logging_func.argtypes = [POINTER(self.CPvSpeaker), c_bool] - self._set_debug_logging_func.restype = None - self._write_func = library.pv_speaker_write - self._write_func.argtypes = [POINTER(self.CPvSpeaker), c_int32, c_void_p] + self._write_func.argtypes = [POINTER(self.CPvSpeaker), c_char_p, c_int32, POINTER(c_int32)] self._write_func.restype = self.PvSpeakerStatuses + self._flush_func = library.pv_speaker_flush + self._flush_func.argtypes = [POINTER(self.CPvSpeaker), c_char_p, c_int32, POINTER(c_int32)] + self._flush_func.restype = self.PvSpeakerStatuses + self._get_is_started_func = library.pv_speaker_get_is_started self._get_is_started_func.argtypes = [POINTER(self.CPvSpeaker)] self._get_is_started_func.restype = c_bool @@ -169,49 +163,54 @@ def start(self) -> None: raise self._PVSPEAKER_STATUS_TO_EXCEPTION[status]("Failed to start device.") def stop(self) -> None: - """Stops playing audio.""" + """Stops the device.""" status = self._stop_func(self._handle) if status is not self.PvSpeakerStatuses.SUCCESS: raise self._PVSPEAKER_STATUS_TO_EXCEPTION[status]("Failed to stop device.") - def write(self, pcm) -> None: - """Synchronous call to write pcm frames to selected device for audio playback.""" - - i = 0 - while i < len(pcm): - is_last_frame = i + self._frame_length >= len(pcm) - write_frame_length = len(pcm) - i if is_last_frame else self._frame_length - - start_index = i - end_index = i + write_frame_length - frame = pcm[start_index:end_index] - - byte_data = None - if self._bits_per_sample == 8: - byte_data = pack('B' * len(frame), *frame) - elif self._bits_per_sample == 16: - byte_data = pack('h' * len(frame), *frame) - elif self._bits_per_sample == 24: - byte_data = b''.join(pack(' bytes: + byte_data = None + if self._bits_per_sample == 8: + byte_data = pack('B' * len(pcm), *pcm) + elif self._bits_per_sample == 16: + byte_data = pack('h' * len(pcm), *pcm) + elif self._bits_per_sample == 24: + byte_data = b''.join(pack(' int: + """ + Synchronous call to write PCM data to the internal circular buffer for audio playback. + Only writes as much PCM data as the internal circular buffer can currently fit, and + returns the length of the PCM data that was successfully written. + """ - status = self._write_func(self._handle, c_int32(len(frame)), c_char_p(byte_data)) - if status is not self.PvSpeakerStatuses.SUCCESS: - raise self._PVSPEAKER_STATUS_TO_EXCEPTION[status]("Failed to write to device.") + written_length = c_int32() + status = self._write_func( + self._handle, c_char_p(self._pcm_to_bytes(pcm)), c_int32(len(pcm)), byref(written_length)) + if status is not self.PvSpeakerStatuses.SUCCESS: + raise self._PVSPEAKER_STATUS_TO_EXCEPTION[status]("Failed to write to device.") - i += self._frame_length + return written_length.value - def set_debug_logging(self, is_debug_logging_enabled: bool) -> None: + def flush(self, pcm=None) -> int: """ - Enable or disable debug logging for PvSpeaker. Debug logs will indicate when there are overflows - in the internal frame buffer. - - :param is_debug_logging_enabled: Boolean indicating whether the debug logging is enabled or disabled. + Synchronous call to write PCM data to the internal circular buffer for audio playback. + This call blocks the thread until all PCM data has been successfully written and played. """ - self._set_debug_logging_func(self._handle, is_debug_logging_enabled) + if pcm is None: + pcm = [] + written_length = c_int32() + status = self._flush_func( + self._handle, c_char_p(self._pcm_to_bytes(pcm)), c_int32(len(pcm)), byref(written_length)) + if status is not self.PvSpeakerStatuses.SUCCESS: + raise self._PVSPEAKER_STATUS_TO_EXCEPTION[status]("Failed to write to device.") + + return written_length.value @property def is_started(self) -> bool: @@ -239,18 +238,18 @@ def sample_rate(self) -> int: return self._sample_rate - @property - def frame_length(self) -> int: - """Gets the frame length matching the value given to `__init__()`.""" - - return self._frame_length - @property def bits_per_sample(self) -> int: """Gets the bits per sample matching the value given to `__init__()`.""" return self._bits_per_sample + @property + def buffer_size_secs(self) -> int: + """Gets the buffer size in seconds matching the value given to `__init__()`.""" + + return self._buffer_size_secs + @staticmethod def get_available_devices() -> List[str]: """Gets the list of available audio devices that can be used for playing. diff --git a/binding/python/setup.py b/binding/python/setup.py index f8373b4..55c8500 100644 --- a/binding/python/setup.py +++ b/binding/python/setup.py @@ -56,7 +56,7 @@ setuptools.setup( name="pvspeaker", - version="1.0.0", + version="1.0.1", author="Picovoice", author_email="hello@picovoice.ai", description="Speaker library for Picovoice.", diff --git a/binding/python/test_pv_speaker.py b/binding/python/test_pv_speaker.py index 302b882..571b2a9 100644 --- a/binding/python/test_pv_speaker.py +++ b/binding/python/test_pv_speaker.py @@ -20,47 +20,57 @@ class PvSpeakerTestCase(unittest.TestCase): def setUpClass(cls): PvSpeaker.set_default_library_path(os.path.join('..', '..')) - def test_invalid_device_index(self): + def test_invalid_sample_rate(self): with self.assertRaises(ValueError): - _ = PvSpeaker(16000, 16, -2) + _ = PvSpeaker(0, 16, 20, 0) - def test_invalid_frame_length(self): + def test_invalid_bits_per_sample(self): with self.assertRaises(ValueError): - _ = PvSpeaker(16000, 16, 0, 0) + _ = PvSpeaker(16000, 0, 20, 0) - def test_invalid_buffered_frame_count(self): + def test_invalid_buffer_size_secs(self): with self.assertRaises(ValueError): - _ = PvSpeaker(16000, 16, 0, 512, 0) + _ = PvSpeaker(16000, 16, 0, 0) - def test_set_frame_length(self): - speaker = PvSpeaker(16000, 16, 0, 256) - frame_length = speaker.frame_length - self.assertEqual(frame_length, 256) - self.assertIsInstance(frame_length, int) - speaker.delete() + def test_invalid_device_index(self): + with self.assertRaises(ValueError): + _ = PvSpeaker(16000, 16, 20, -2) def test_start_stop(self): error = False try: - speaker = PvSpeaker(16000, 16, 0) + speaker = PvSpeaker(16000, 16, 20) speaker.start() - frame = [0] * (512 * 2) - speaker.write(frame) + pcm = [0] * (512 * 2) + speaker.write(pcm) + speaker.flush(pcm) + speaker.flush() speaker.stop() speaker.delete() except ValueError or IOError: error = True self.assertFalse(error) - def test_set_debug_logging(self): - speaker = PvSpeaker(16000, 16, 0) - speaker.set_debug_logging(True) - speaker.set_debug_logging(False) - self.assertIsNotNone(speaker) + def test_write_flow(self): + sample_rate = 16000 + buffer_size_secs = 1 + circular_buffer_size = sample_rate * buffer_size_secs + pcm = [0] * (circular_buffer_size + 1) + + speaker = PvSpeaker(sample_rate, 16, buffer_size_secs) + speaker.start() + + write_count = speaker.write(pcm) + self.assertEqual(write_count, circular_buffer_size) + write_count = speaker.flush(pcm) + self.assertEqual(write_count, len(pcm)) + write_count = speaker.flush() + self.assertEqual(write_count, 0) + speaker.delete() def test_is_started(self): - speaker = PvSpeaker(16000, 16, 0) + speaker = PvSpeaker(16000, 16, 20) speaker.start() self.assertTrue(speaker.is_started) speaker.stop() @@ -68,14 +78,14 @@ def test_is_started(self): speaker.delete() def test_selected_device(self): - speaker = PvSpeaker(16000, 16, 0) + speaker = PvSpeaker(16000, 16, 20) device = speaker.selected_device self.assertIsNotNone(device) self.assertIsInstance(device, str) speaker.delete() def test_get_available_devices(self): - speaker = PvSpeaker(16000, 16, 0) + speaker = PvSpeaker(16000, 16, 20) devices = speaker.get_available_devices() self.assertIsNotNone(devices) for device in devices: @@ -84,33 +94,33 @@ def test_get_available_devices(self): speaker.delete() def test_version(self): - speaker = PvSpeaker(16000, 16, 0) + speaker = PvSpeaker(16000, 16, 20) version = speaker.version self.assertGreater(len(version), 0) self.assertIsInstance(version, str) speaker.delete() def test_sample_rate(self): - speaker = PvSpeaker(16000, 16, 0) + speaker = PvSpeaker(16000, 16, 20) sample_rate = speaker.sample_rate self.assertEqual(sample_rate, 16000) self.assertIsInstance(sample_rate, int) speaker.delete() - def test_frame_length(self): - speaker = PvSpeaker(16000, 16, 0) - frame_length = speaker.frame_length - self.assertEqual(frame_length, 512) - self.assertIsInstance(frame_length, int) - speaker.delete() - def test_bits_per_sample(self): - speaker = PvSpeaker(16000, 16, 0) + speaker = PvSpeaker(16000, 16, 20) bits_per_sample = speaker.bits_per_sample self.assertEqual(bits_per_sample, 16) self.assertIsInstance(bits_per_sample, int) speaker.delete() + def test_buffer_size_secs(self): + speaker = PvSpeaker(16000, 16, 20) + buffer_size_secs = speaker.buffer_size_secs + self.assertEqual(buffer_size_secs, 20) + self.assertIsInstance(buffer_size_secs, int) + speaker.delete() + if __name__ == '__main__': unittest.main() diff --git a/demo/c/README.md b/demo/c/README.md index 4ae6557..d0f8f6a 100644 --- a/demo/c/README.md +++ b/demo/c/README.md @@ -49,4 +49,4 @@ Play from a single-channel PCM WAV file with a given audio device index: ./pv_speaker_demo -i test.wav -d 2 ``` -Hit `Ctrl+C` if you wish to stop audio playback before it completes. If no audio device index (`-d`) is provided, the demo will use the system's default audio player device. +Hit `Ctrl+C` if you wish to stop playing audio before it completes. If no audio device index (`-d`) is provided, the demo will use the system's default audio player device. diff --git a/demo/c/pv_speaker_demo.c b/demo/c/pv_speaker_demo.c index ed91fb7..a7ebcc6 100644 --- a/demo/c/pv_speaker_demo.c +++ b/demo/c/pv_speaker_demo.c @@ -20,20 +20,25 @@ static volatile bool is_interrupted = false; +pv_speaker_t *speaker = NULL; + void interrupt_handler(int _) { (void) _; is_interrupted = true; + pv_speaker_stop(speaker); + fprintf(stdout, "\nStopped...\n"); } static struct option long_options[] = { {"show_audio_devices", no_argument, NULL, 's'}, {"input_wav_path", required_argument, NULL, 'i'}, - {"audio_device_index", required_argument, NULL, 'd'} + {"audio_device_index", required_argument, NULL, 'd'}, + {"buffer_size_secs", required_argument, NULL, 'b'} }; static void print_usage(const char *program_name) { fprintf(stderr, - "Usage : %s -i INPUT_WAV_PATH [-d AUDIO_DEVICE_INDEX]\n" + "Usage : %s -i INPUT_WAV_PATH [-d AUDIO_DEVICE_INDEX] [-b BUFFER_SIZE_SECS]\n" " %s --show_audio_devices\n", program_name, program_name); @@ -107,13 +112,12 @@ void *read_wav_file(const char *filename, uint32_t *num_samples, uint32_t *sampl } *sample_rate = header.sample_rate; - *bits_per_sample = header.bits_per_sample; - uint32_t bytes_per_sample = header.bits_per_sample / 8; *num_samples = header.subchunk2_size / bytes_per_sample; void *pcm_data = malloc(header.subchunk2_size); + if (!pcm_data) { perror("Memory allocation failed"); fclose(file); @@ -130,9 +134,10 @@ void *read_wav_file(const char *filename, uint32_t *num_samples, uint32_t *sampl int main(int argc, char *argv[]) { const char *input_wav_path = NULL; int32_t device_index = -1; + int32_t buffer_size_secs = 20; int c; - while ((c = getopt_long(argc, argv, "si:d:", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "si:d:b:", long_options, NULL)) != -1) { switch (c) { case 's': show_audio_devices(); @@ -143,6 +148,9 @@ int main(int argc, char *argv[]) { case 'd': device_index = (int32_t) strtol(optarg, NULL, 10); break; + case 'b': + buffer_size_secs = (int32_t) strtol(optarg, NULL, 10); + break; default: exit(1); } @@ -158,25 +166,20 @@ int main(int argc, char *argv[]) { uint32_t num_samples, sample_rate; uint16_t bits_per_sample; - void *pcm = read_wav_file(input_wav_path, &num_samples, &sample_rate, &bits_per_sample); + void *pcm_data = read_wav_file(input_wav_path, &num_samples, &sample_rate, &bits_per_sample); fprintf(stdout, "Initializing pv_speaker...\n"); - const int32_t frame_length = 512; - pv_speaker_t *speaker = NULL; pv_speaker_status_t status = pv_speaker_init( sample_rate, - frame_length, bits_per_sample, + buffer_size_secs, device_index, - 10, &speaker); if (status != PV_SPEAKER_STATUS_SUCCESS) { fprintf(stderr, "Failed to initialize device with %s.\n", pv_speaker_status_to_string(status)); exit(1); } - pv_speaker_set_debug_logging(speaker, true); - const char *selected_device = pv_speaker_get_selected_device(speaker); fprintf(stdout, "Selected device: %s.\n", selected_device); @@ -187,31 +190,35 @@ int main(int argc, char *argv[]) { } fprintf(stdout, "Playing audio...\n"); - if (pcm) { - char *pcmData = (char *) pcm; - for (int i = 0; i < num_samples; i += frame_length) { - bool is_last_frame = i + frame_length >= num_samples; + if (pcm_data) { + int8_t *pcm = (int8_t *) pcm_data; + int32_t total_written_length = 0; + while (!is_interrupted && total_written_length < num_samples) { + int32_t written_length = 0; status = pv_speaker_write( speaker, - is_last_frame ? num_samples - i : frame_length, - &pcmData[i * bits_per_sample / 8]); + &pcm[total_written_length * bits_per_sample / 8], + num_samples - total_written_length, + &written_length); if (status != PV_SPEAKER_STATUS_SUCCESS) { fprintf(stderr, "Failed to write with %s.\n", pv_speaker_status_to_string(status)); exit(1); } - if (is_interrupted) { - fprintf(stdout, "\nStopped audio...\n"); - break; - } + total_written_length += written_length; } free(pcm); } - status = pv_speaker_stop(speaker); + fprintf(stdout, "Waiting for audio to finish...\n"); + int32_t pcm_length = 0; + int16_t pcm[pcm_length]; + int8_t *pcm_ptr = (int8_t *) pcm; + int32_t written_length = 0; + status = pv_speaker_flush(speaker, pcm_ptr, pcm_length, &written_length); if (status != PV_SPEAKER_STATUS_SUCCESS) { - fprintf(stderr, "Failed to stop device with %s.\n", pv_speaker_status_to_string(status)); + fprintf(stderr, "Failed to flush pcm with %s.\n", pv_speaker_status_to_string(status)); exit(1); } @@ -219,6 +226,12 @@ int main(int argc, char *argv[]) { fprintf(stdout, "Finished playing audio...\n"); } + status = pv_speaker_stop(speaker); + if (status != PV_SPEAKER_STATUS_SUCCESS) { + fprintf(stderr, "Failed to stop device with %s.\n", pv_speaker_status_to_string(status)); + exit(1); + } + fprintf(stdout, "Deleting pv_speaker...\n"); pv_speaker_delete(speaker); diff --git a/demo/python/README.md b/demo/python/README.md index 13f8b31..0fa8b0f 100644 --- a/demo/python/README.md +++ b/demo/python/README.md @@ -33,4 +33,6 @@ To run PvSpeaker run: ```console pv_speaker_demo --audio_device_index {AUDIO_DEVICE_INDEX} --input_wav_path {INPUT_WAV_PATH} -``` \ No newline at end of file +``` + +Hit `Ctrl+C` if you wish to stop playing audio before it completes. If no audio device index (`-d`) is provided, the demo will use the system's default audio player device. \ No newline at end of file diff --git a/demo/python/pv_speaker_demo.py b/demo/python/pv_speaker_demo.py index 7871a52..68ac813 100644 --- a/demo/python/pv_speaker_demo.py +++ b/demo/python/pv_speaker_demo.py @@ -14,28 +14,53 @@ import wave import array +import threading + from pvspeaker import PvSpeaker +def blocking_call(speaker): + speaker.flush() + + +def worker_function(speaker, completion_event): + blocking_call(speaker) + completion_event.set() + + +def split_list(input_list, x): + return [input_list[i:i + x] for i in range(0, len(input_list), x)] + + def main(): parser = argparse.ArgumentParser() parser.add_argument( "--show_audio_devices", + "-s", help="List of audio devices currently available for use.", action="store_true") parser.add_argument( "--audio_device_index", + "-d", help="Index of input audio device.", type=int, default=-1) parser.add_argument( "--input_wav_path", + "-i", help="Path to PCM WAV file to be played.", default=None) + parser.add_argument( + "--buffer_size_secs", + "-b", + help="Size of internal PCM buffer in seconds.", + type=int, + default=20) + args = parser.parse_args() if args.show_audio_devices: @@ -45,6 +70,7 @@ def main(): else: device_index = args.audio_device_index input_path = args.input_wav_path + buffer_size_secs = args.buffer_size_secs wavfile = None speaker = None @@ -71,6 +97,7 @@ def main(): speaker = PvSpeaker( sample_rate=sample_rate, bits_per_sample=bits_per_sample, + buffer_size_secs=buffer_size_secs, device_index=device_index) print("pvspeaker version: %s" % speaker.version) print("Using device: %s" % speaker.selected_device) @@ -90,18 +117,35 @@ def main(): elif bits_per_sample == 32: pcm = list(array.array('i', wav_bytes)) + pcm_list = split_list(pcm, sample_rate) speaker.start() print("Playing audio...") - speaker.write(pcm) + for pcm_sublist in pcm_list: + sublist_length = len(pcm_sublist) + total_written_length = 0 + while total_written_length < sublist_length: + written_length = speaker.write(pcm_sublist[total_written_length:]) + total_written_length += written_length + + print("Waiting for audio to finish...") + + completion_event = threading.Event() + worker_thread = threading.Thread(target=worker_function, args=(speaker, completion_event)) + worker_thread.start() + completion_event.wait() + worker_thread.join() + speaker.stop() print("Finished playing audio...") wavfile.close() except KeyboardInterrupt: - print("Stopping...") + speaker.stop() + print("\nStopped...") finally: + print("Deleting PvSpeaker...") if speaker is not None: speaker.delete() if wavfile is not None: diff --git a/demo/python/requirements.txt b/demo/python/requirements.txt index 3c5aeaa..acf2ad5 100644 --- a/demo/python/requirements.txt +++ b/demo/python/requirements.txt @@ -1 +1 @@ -pvspeaker==1.0.0 \ No newline at end of file +pvspeaker==1.0.1 \ No newline at end of file diff --git a/demo/python/setup.py b/demo/python/setup.py index 9e61692..6090c52 100644 --- a/demo/python/setup.py +++ b/demo/python/setup.py @@ -23,7 +23,7 @@ setuptools.setup( name="pvspeakerdemo", - version="1.0.0", + version="1.0.1", author="Picovoice", author_email="hello@picovoice.ai", description="Speaker library for Picovoice.", @@ -31,7 +31,7 @@ long_description_content_type="text/markdown", url="https://github.com/Picovoice/pvspeaker", packages=["pvspeakerdemo"], - install_requires=["pvspeaker==1.0.0"], + install_requires=["pvspeaker==1.0.1"], include_package_data=True, classifiers=[ "Development Status :: 5 - Production/Stable", diff --git a/lib/linux/x86_64/libpv_speaker.so b/lib/linux/x86_64/libpv_speaker.so index 500813e161a3cf6cb8d258495a0d6fe5829ea67c..35224af09821a0245d5014152939d723531c2dc2 100644 GIT binary patch delta 163216 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˳@fD6e@juu; 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