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('<i', sample)[0:3] for sample in frame)
-            elif self._bits_per_sample == 32:
-                byte_data = pack('i' * len(frame), *frame)
+    def _pcm_to_bytes(self, pcm) -> 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('<i', sample)[0:3] for sample in pcm)
+        elif self._bits_per_sample == 32:
+            byte_data = pack('i' * len(pcm), *pcm)
+        return byte_data
+
+    def write(self, pcm) -> 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 500813e..35224af 100644
Binary files a/lib/linux/x86_64/libpv_speaker.so and b/lib/linux/x86_64/libpv_speaker.so differ
diff --git a/lib/mac/arm64/libpv_speaker.dylib b/lib/mac/arm64/libpv_speaker.dylib
index 1d31380..8ffa211 100644
Binary files a/lib/mac/arm64/libpv_speaker.dylib and b/lib/mac/arm64/libpv_speaker.dylib differ
diff --git a/lib/mac/x86_64/libpv_speaker.dylib b/lib/mac/x86_64/libpv_speaker.dylib
index 0ed8d21..35b9dc8 100644
Binary files a/lib/mac/x86_64/libpv_speaker.dylib and b/lib/mac/x86_64/libpv_speaker.dylib differ
diff --git a/lib/raspberry-pi/cortex-a53-aarch64/libpv_speaker.so b/lib/raspberry-pi/cortex-a53-aarch64/libpv_speaker.so
index 7fecb08..9f75113 100644
Binary files a/lib/raspberry-pi/cortex-a53-aarch64/libpv_speaker.so and b/lib/raspberry-pi/cortex-a53-aarch64/libpv_speaker.so differ
diff --git a/lib/raspberry-pi/cortex-a53/libpv_speaker.so b/lib/raspberry-pi/cortex-a53/libpv_speaker.so
index 6975727..6e1d8f6 100644
Binary files a/lib/raspberry-pi/cortex-a53/libpv_speaker.so and b/lib/raspberry-pi/cortex-a53/libpv_speaker.so differ
diff --git a/lib/raspberry-pi/cortex-a72-aarch64/libpv_speaker.so b/lib/raspberry-pi/cortex-a72-aarch64/libpv_speaker.so
index 57df94c..19cd3bc 100644
Binary files a/lib/raspberry-pi/cortex-a72-aarch64/libpv_speaker.so and b/lib/raspberry-pi/cortex-a72-aarch64/libpv_speaker.so differ
diff --git a/lib/raspberry-pi/cortex-a72/libpv_speaker.so b/lib/raspberry-pi/cortex-a72/libpv_speaker.so
index 1163e4c..e408b29 100644
Binary files a/lib/raspberry-pi/cortex-a72/libpv_speaker.so and b/lib/raspberry-pi/cortex-a72/libpv_speaker.so differ
diff --git a/lib/raspberry-pi/cortex-a76-aarch64/libpv_speaker.so b/lib/raspberry-pi/cortex-a76-aarch64/libpv_speaker.so
index fabbef3..c21f374 100644
Binary files a/lib/raspberry-pi/cortex-a76-aarch64/libpv_speaker.so and b/lib/raspberry-pi/cortex-a76-aarch64/libpv_speaker.so differ
diff --git a/lib/raspberry-pi/cortex-a76/libpv_speaker.so b/lib/raspberry-pi/cortex-a76/libpv_speaker.so
index 63c0bf7..2270c7d 100644
Binary files a/lib/raspberry-pi/cortex-a76/libpv_speaker.so and b/lib/raspberry-pi/cortex-a76/libpv_speaker.so differ
diff --git a/lib/windows/amd64/libpv_speaker.dll b/lib/windows/amd64/libpv_speaker.dll
index 56a66b5..08f99ea 100644
Binary files a/lib/windows/amd64/libpv_speaker.dll and b/lib/windows/amd64/libpv_speaker.dll differ
diff --git a/project/README.md b/project/README.md
index 864a371..bc3be9f 100644
--- a/project/README.md
+++ b/project/README.md
@@ -32,22 +32,21 @@ to get a list of possible values.
 ## Usage
 
 1. Create a PvSpeaker object:
+
 ```c
 #include "pv_speaker.h"
 
 const int32_t sample_rate = 22050;
-const int32_t frame_length = 512;
 const int16_t bits_per_sample = 16;
+const int32_t buffer_size_secs = 20;
 const int32_t device_index = -1; // -1 == default device
-const int32_t buffered_frame_count = 10;
 
 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,
-        buffered_frame_count,
         &speaker);
 if (status != PV_SPEAKER_STATUS_SUCCESS) {
     // handle PvSpeaker init error
@@ -63,29 +62,33 @@ if (status != PV_SPEAKER_STATUS_SUCCESS) {
 }
 ```
 
-3. Write frames of audio to the speaker:
+3. Write PCM data to the speaker:
+
 ```c
-if (pcm) {
-    for (int i = 0; i < num_samples; i += frame_length) {
-        // must have length equal to or less than `frame_length` that was given to `pv_speaker_init()`
-        // be sure to handle the last frame properly (i.e. the last frame will likely not have length `frame_length`)
-        bool is_last_frame = i + frame_length >= num_samples;
-        int32_t last_frame_length = num_samples - i;
-
-        status = pv_speaker_write(
-                speaker,
-                is_last_frame ? last_frame_length : frame_length,
-                &pcm[i * bits_per_sample / 8]);
-        if (status != PV_SPEAKER_STATUS_SUCCESS) {
-            // handle PvSpeaker write error
-        }
-    }
-
-    free(pcm);
+int32_3 num_samples;
+int8_t *pcm = get_pcm_data(&num_samples);
+int32_3 written_length = 0;
+
+pv_speaker_status_t status = pv_speaker_write(speaker, pcm, num_samples, &written_length);
+if (status != PV_SPEAKER_STATUS_SUCCESS) {
+    // handle PvSpeaker start error
 }
 ```
 
-4. Stop playing:
+4. Wait for buffered audio to finish playing:
+
+```c
+int32_3 num_samples;
+int8_t *pcm = get_pcm_data(&num_samples);
+int32_3 written_length = 0;
+
+pv_speaker_status_t status = pv_speaker_flush(speaker, pcm, num_samples, &written_length);
+if (status != PV_SPEAKER_STATUS_SUCCESS) {
+    // handle PvSpeaker flush error
+}
+```
+
+5. Stop the speaker:
 
 ```c
 pv_speaker_status_t status = pv_speaker_stop(speaker);
@@ -94,7 +97,8 @@ if (status != PV_SPEAKER_STATUS_SUCCESS) {
 }
 ```
 
-5. Release resources used by PvSpeaker:
+6. Release resources used by PvSpeaker:
+
 ```c
 pv_speaker_delete(speaker);
 ```
diff --git a/project/include/pv_circular_buffer.h b/project/include/pv_circular_buffer.h
index fc48ab1..d262333 100644
--- a/project/include/pv_circular_buffer.h
+++ b/project/include/pv_circular_buffer.h
@@ -80,6 +80,15 @@ pv_circular_buffer_status_t pv_circular_buffer_write(
         const void *buffer,
         int32_t buffer_length);
 
+/**
+* Gets the current amount of available space in the object's buffer.
+*
+* @param object Circular buffer object.
+* @param available[out] The current amount of available space in the buffer.
+* @return Status Code. Returns PV_CIRCULAR_BUFFER_STATUS_INVALID_ARGUMENT on failure.
+*/
+pv_circular_buffer_status_t pv_circular_buffer_get_available(pv_circular_buffer_t *object, int32_t *available);
+
 /**
 * Gets the current size of the object's buffer.
 *
@@ -104,4 +113,4 @@ void pv_circular_buffer_reset(pv_circular_buffer_t *object);
 */
 const char *pv_circular_buffer_status_to_string(pv_circular_buffer_status_t status);
 
-#endif //PV_CIRCULAR_BUFFER_H
\ No newline at end of file
+#endif //PV_CIRCULAR_BUFFER_H
diff --git a/project/include/pv_speaker.h b/project/include/pv_speaker.h
index 0b8af32..e09d18c 100644
--- a/project/include/pv_speaker.h
+++ b/project/include/pv_speaker.h
@@ -17,11 +17,11 @@
 
 #if __PV_PLATFORM_WINDOWS__
 
-#define PV_API __attribute__ ((dllexport))
+#define PV_API __attribute__((dllexport))
 
 #else
 
-#define PV_API __attribute__((visibility ("default")))
+#define PV_API __attribute__((visibility("default")))
 
 #endif
 
@@ -38,7 +38,6 @@ typedef enum {
     PV_SPEAKER_STATUS_OUT_OF_MEMORY,
     PV_SPEAKER_STATUS_INVALID_ARGUMENT,
     PV_SPEAKER_STATUS_INVALID_STATE,
-    PV_SPEAKER_STATUS_BUFFER_OVERFLOW,
     PV_SPEAKER_STATUS_BACKEND_ERROR,
     PV_SPEAKER_STATUS_DEVICE_ALREADY_INITIALIZED,
     PV_SPEAKER_STATUS_DEVICE_NOT_INITIALIZED,
@@ -51,22 +50,19 @@ typedef enum {
 * using the `pv_speaker_delete() function.
 *
 * @param sample_rate The sample rate of the audio to be played.
-* @param frame_length The maximum length of audio frame that will be passed to `pv_speaker_write`.
 * @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 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
-* and audio frames could be dropped. A higher value will increase memory usage.
 * @param[out] object PvSpeaker object to be initialized.
 * @return Status Code. PV_SPEAKER_STATUS_INVALID_ARGUMENT, PV_SPEAKER_STATUS_BACKEND_ERROR,
 * PV_SPEAKER_STATUS_DEVICE_INITIALIZED or PV_SPEAKER_STATUS_OUT_OF_MEMORY on failure.
 */
 PV_API pv_speaker_status_t pv_speaker_init(
         int32_t sample_rate,
-        int32_t frame_length,
         int16_t bits_per_sample,
+        int32_t buffer_size_secs,
         int32_t device_index,
-        int32_t buffered_frames_count,
         pv_speaker_t **object);
 
 /**
@@ -77,7 +73,8 @@ PV_API pv_speaker_status_t pv_speaker_init(
 PV_API void pv_speaker_delete(pv_speaker_t *object);
 
 /**
-* Starts the audio output device. After starting, pcm frames can be sent to the audio output device via `pv_speaker_write`.
+* Starts the audio output device. After starting, PCM data can be sent to the audio output device via `pv_speaker_write`
+* and/or `pv_speaker_flush`.
 *
 * @param object PvSpeaker object.
 * @returnStatus Status Code. Returns PV_SPEAKER_STATUS_INVALID_ARGUMENT, PV_SPEAKER_STATUS_DEVICE_NOT_INITIALIZED
@@ -86,42 +83,46 @@ PV_API void pv_speaker_delete(pv_speaker_t *object);
 PV_API pv_speaker_status_t pv_speaker_start(pv_speaker_t *object);
 
 /**
-* Stops playing audio.
+* 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.
 *
 * @param object PvSpeaker object.
-* @return Status Code. Returns PV_SPEAKER_STATUS_INVALID_ARGUMENT, PV_SPEAKER_STATUS_DEVICE_NOT_INITIALIZED
-* or PV_SPEAKER_STATUS_INVALID_STATE on failure.
+* @param pcm Pointer to the PCM data that will be written.
+* @param pcm_length Length of the PCM data that is passed in.
+* @param written_length[out] Length of the PCM data that was successfully written. This value may be less than or equal
+* to `pcm_length`, depending on the current state of the internal circular buffer.
+* @return Status Code. Returns PV_SPEAKER_STATUS_INVALID_ARGUMENT, PV_SPEAKER_INVALID_STATE or PV_SPEAKER_IO_ERROR on
+* failure.
 */
-PV_API pv_speaker_status_t pv_speaker_stop(pv_speaker_t *object);
+PV_API pv_speaker_status_t pv_speaker_write(pv_speaker_t *object, int8_t *pcm, int32_t pcm_length, int32_t *written_length);
 
 /**
-* Synchronous call to write frames. Copies amount of frames to `frame` array provided to input.
-* Array size must not be greater than the `frame_length` value that was given to `pv_speaker_init()`.
+* Synchronous call to write PCM data to the internal circular buffer for audio playback.
+* This call blocks the thread until all PCM data have been successfully written and played.
 *
 * @param object PvSpeaker object.
-* @param frame_length Size of the array that is passed in.
-* @param frame Pointer to the array that will be written.
-* @return Status Code. Returns PV_SPEAKER_STATUS_INVALID_ARGUMENT, PV_SPEAKER_INVALID_STATE or PV_SPEAKER_IO_ERROR on failure.
-* Returns PV_SPEAKER_STATUS_BUFFER_OVERFLOW if audio frames aren't being written fast enough. This means audio frames will be dropped.
+* @param pcm Pointer to the PCM data that will be written.
+* @param pcm_length Length of the PCM data that is passed in.
+* @param written_length[out] Length of the PCM data that was successfully written. This value should always match
+* `pcm_length`, unless an error occurred.
+* @return Status Code. Returns PV_SPEAKER_STATUS_INVALID_ARGUMENT, PV_SPEAKER_INVALID_STATE or PV_SPEAKER_IO_ERROR on
+* failure.
 */
-PV_API pv_speaker_status_t pv_speaker_write(pv_speaker_t *object, int32_t frame_length, void *frame);
+PV_API pv_speaker_status_t pv_speaker_flush(pv_speaker_t *object, int8_t *pcm, int32_t pcm_length, int32_t *written_length);
 
 /**
-* Enable or disable debug logging for PvSpeaker. Debug logs will indicate when there are overflows in the internal
-* frame buffer and when an audio source is generating frames of silence.
+* Stops the device.
 *
 * @param object PvSpeaker object.
-* @param is_debug_logging_enabled Boolean indicating whether the debug logging is enabled or disabled.
+* @return Status Code. Returns PV_SPEAKER_STATUS_INVALID_ARGUMENT or PV_SPEAKER_STATUS_INVALID_STATE on failure.
 */
-PV_API void pv_speaker_set_debug_logging(
-        pv_speaker_t *object,
-        bool is_debug_logging_enabled);
+PV_API pv_speaker_status_t pv_speaker_stop(pv_speaker_t *object);
 
 /**
-* Gets whether the given `pv_speaker_t` instance has started and available to receive pcm frames or not.
+* Gets whether the given `pv_speaker_t` instance has started and is available to receive PCM data.
 *
 * @param object PvSpeaker object.
-* @returns A boolean indicating whether PvSpeaker has started and available to receive pcm frames or not.
+* @returns A boolean indicating whether PvSpeaker has started and is available to receive PCM data.
 */
 PV_API bool pv_speaker_get_is_started(pv_speaker_t *object);
 
diff --git a/project/src/pv_circular_buffer.c b/project/src/pv_circular_buffer.c
index 0c93d60..abdf56f 100644
--- a/project/src/pv_circular_buffer.c
+++ b/project/src/pv_circular_buffer.c
@@ -153,6 +153,16 @@ pv_circular_buffer_status_t pv_circular_buffer_write(
     return PV_CIRCULAR_BUFFER_STATUS_SUCCESS;
 }
 
+pv_circular_buffer_status_t pv_circular_buffer_get_available(pv_circular_buffer_t *object, int32_t *available) {
+    if (!object) {
+        return PV_CIRCULAR_BUFFER_STATUS_INVALID_ARGUMENT;
+    }
+
+    *available = object->capacity - object->count;
+
+    return PV_CIRCULAR_BUFFER_STATUS_SUCCESS;
+}
+
 pv_circular_buffer_status_t pv_circular_buffer_get_count(pv_circular_buffer_t *object, int32_t *count) {
     if (!object) {
         return PV_CIRCULAR_BUFFER_STATUS_INVALID_ARGUMENT;
@@ -182,4 +192,4 @@ const char *pv_circular_buffer_status_to_string(pv_circular_buffer_status_t stat
     }
 
     return STRINGS[status - PV_CIRCULAR_BUFFER_STATUS_SUCCESS];
-}
\ No newline at end of file
+}
diff --git a/project/src/pv_speaker.c b/project/src/pv_speaker.c
index 3cb086c..aeafb98 100644
--- a/project/src/pv_speaker.c
+++ b/project/src/pv_speaker.c
@@ -26,19 +26,18 @@
 
 #define PV_SPEAKER_VERSION "1.0.0"
 
-static const int32_t WRITE_RETRY_COUNT = 500;
-static const int32_t WRITE_SLEEP_MILLI_SECONDS = 2;
-
-static bool is_stopped_and_empty = false;
+static bool is_stopped = false;
+static bool is_flushed_and_empty = false;
 static bool is_data_requested_while_empty = false;
 
+static const int32_t FLUSH_SLEEP_MS = 2;
+
 struct pv_speaker {
     ma_context context;
     ma_device device;
     pv_circular_buffer_t *buffer;
-    int32_t frame_length;
+    int32_t bits_per_sample;
     bool is_started;
-    bool is_debug_logging_enabled;
     ma_mutex mutex;
 };
 
@@ -49,9 +48,9 @@ static void pv_speaker_ma_callback(ma_device *device, void *output, const void *
 
     ma_mutex_lock(&object->mutex);
 
-    // this callback being invoked after calling `pv_speaker_stop` and the circular buffer is empty indicates that all
+    // this callback being invoked after calling `pv_speaker_flush` and the circular buffer is empty indicates that all
     // frames have been passed to the output buffer, and the device can stop without truncating the last frame of audio
-    if (is_stopped_and_empty) {
+    if (is_flushed_and_empty) {
         is_data_requested_while_empty = true;
         ma_mutex_unlock(&object->mutex);
         return;
@@ -65,10 +64,9 @@ static void pv_speaker_ma_callback(ma_device *device, void *output, const void *
 
 PV_API pv_speaker_status_t pv_speaker_init(
         int32_t sample_rate,
-        int32_t frame_length,
         int16_t bits_per_sample,
+        int32_t buffer_size_secs,
         int32_t device_index,
-        int32_t buffered_frames_count,
         pv_speaker_t **object) {
     if (device_index < PV_SPEAKER_DEFAULT_DEVICE_INDEX) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
@@ -76,16 +74,13 @@ PV_API pv_speaker_status_t pv_speaker_init(
     if (sample_rate <= 0) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
-    if (frame_length <= 0) {
-        return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
-    }
     if (bits_per_sample != 8 &&
         bits_per_sample != 16 &&
         bits_per_sample != 24 &&
         bits_per_sample != 32) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
-    if (buffered_frames_count < 1) {
+    if (buffer_size_secs <= 0) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
     if (!object) {
@@ -188,10 +183,11 @@ PV_API pv_speaker_status_t pv_speaker_init(
         }
     }
 
-    const int32_t buffer_capacity = frame_length * buffered_frames_count;
+    const int32_t buffer_capacity = buffer_size_secs * sample_rate;
+    const int32_t element_size = bits_per_sample / 8;
     pv_circular_buffer_status_t status = pv_circular_buffer_init(
             buffer_capacity,
-            bits_per_sample / 8,
+            element_size,
             &(o->buffer));
 
     if (status != PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
@@ -199,7 +195,7 @@ PV_API pv_speaker_status_t pv_speaker_init(
         return PV_SPEAKER_STATUS_OUT_OF_MEMORY;
     }
 
-    o->frame_length = frame_length;
+    o->bits_per_sample = bits_per_sample;
 
     *object = o;
 
@@ -221,7 +217,7 @@ PV_API pv_speaker_status_t pv_speaker_start(pv_speaker_t *object) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
 
-    is_stopped_and_empty = false;
+    is_flushed_and_empty = false;
     is_data_requested_while_empty = false;
 
     ma_result result = ma_device_start(&(object->device));
@@ -239,88 +235,140 @@ PV_API pv_speaker_status_t pv_speaker_start(pv_speaker_t *object) {
     return PV_SPEAKER_STATUS_SUCCESS;
 }
 
-PV_API pv_speaker_status_t pv_speaker_stop(pv_speaker_t *object) {
+PV_API pv_speaker_status_t pv_speaker_write(pv_speaker_t *object, int8_t *pcm, int32_t pcm_length, int32_t *written_length) {
     if (!object) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
+    if (!pcm) {
+        return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
+    }
+    if (pcm_length <= 0) {
+        return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
+    }
+    if (!written_length) {
+        return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
+    }
+    if (!(object->is_started)) {
+        return PV_SPEAKER_STATUS_INVALID_STATE;
+    }
 
-    // waits for all frames to be copied to output buffer before stopping
-    while (!is_stopped_and_empty || !is_data_requested_while_empty) {
-        ma_mutex_lock(&object->mutex);
-        int32_t count = 0;
-        pv_circular_buffer_status_t status = pv_circular_buffer_get_count(object->buffer, &count);
-        if (status == PV_CIRCULAR_BUFFER_STATUS_SUCCESS && count == 0) {
-            is_stopped_and_empty = true;
-        } else if (status != PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
-            ma_mutex_unlock(&object->mutex);
-            return PV_SPEAKER_STATUS_RUNTIME_ERROR;
-        }
+    is_stopped = false;
+
+    ma_mutex_lock(&object->mutex);
+
+    int32_t available = 0;
+    pv_circular_buffer_status_t status = pv_circular_buffer_get_available(object->buffer, &available);
+    if (status != PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
         ma_mutex_unlock(&object->mutex);
-        ma_sleep(WRITE_SLEEP_MILLI_SECONDS);
+        return PV_SPEAKER_STATUS_RUNTIME_ERROR;
     }
 
-    ma_result result = ma_device_stop(&(object->device));
-    if (result != MA_SUCCESS) {
-        if (result == MA_DEVICE_NOT_INITIALIZED) {
-            return PV_SPEAKER_STATUS_DEVICE_NOT_INITIALIZED;
-        } else {
-            // device already stopped
-            return PV_SPEAKER_STATUS_INVALID_STATE;
+    int32_t to_write = pcm_length < available ? pcm_length : available;
+    if (to_write > 0) {
+        status = pv_circular_buffer_write(object->buffer, pcm, to_write);
+        if (status != PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
+            ma_mutex_unlock(&object->mutex);
+            return PV_SPEAKER_STATUS_RUNTIME_ERROR;
         }
     }
 
-    ma_mutex_lock(&object->mutex);
-    pv_circular_buffer_reset(object->buffer);
-    object->is_started = false;
+    *written_length = to_write;
+
     ma_mutex_unlock(&object->mutex);
 
     return PV_SPEAKER_STATUS_SUCCESS;
 }
 
-PV_API pv_speaker_status_t pv_speaker_write(pv_speaker_t *object, int32_t frame_length, void *frame) {
+PV_API pv_speaker_status_t pv_speaker_flush(pv_speaker_t *object, int8_t *pcm, int32_t pcm_length, int32_t *written_length) {
     if (!object) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
-    if (!frame) {
+    if (!pcm) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
-    if (frame_length > object->frame_length) {
+    if (pcm_length < 0) {
+        return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
+    }
+    if (!written_length) {
         return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
     if (!(object->is_started)) {
         return PV_SPEAKER_STATUS_INVALID_STATE;
     }
 
-    for (int32_t i = 0; i < WRITE_RETRY_COUNT; i++) {
+    int32_t written = 0;
+    *written_length = 0;
+
+    while (!is_stopped && written < pcm_length) {
         ma_mutex_lock(&object->mutex);
 
-        pv_circular_buffer_status_t status = pv_circular_buffer_write(
-                object->buffer,
-                frame,
-                frame_length);
-        if (status == PV_CIRCULAR_BUFFER_STATUS_WRITE_OVERFLOW && (i == (WRITE_RETRY_COUNT - 1))) {
+        int32_t available = 0;
+        pv_circular_buffer_status_t status = pv_circular_buffer_get_available(object->buffer, &available);
+        if (status != PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
             ma_mutex_unlock(&object->mutex);
-            return PV_SPEAKER_STATUS_BUFFER_OVERFLOW;
-        } else if (status == PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
-            ma_mutex_unlock(&object->mutex);
-            return PV_SPEAKER_STATUS_SUCCESS;
-        } else {
+            return PV_SPEAKER_STATUS_RUNTIME_ERROR;
+        }
+
+        int32_t remaining = pcm_length - written;
+        int32_t to_write = remaining < available ? remaining : available;
+        if (to_write > 0) {
+            status = pv_circular_buffer_write(
+                    object->buffer,
+                    &pcm[written * object->bits_per_sample / 8],
+                    to_write);
+            if (status == PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
+                written += to_write;
+                *written_length = written;
+            }
+        }
+
+        ma_mutex_unlock(&object->mutex);
+        ma_sleep(FLUSH_SLEEP_MS);
+    }
+
+    // waits for all frames to be copied to output buffer
+    while (!is_stopped && !is_data_requested_while_empty) {
+        ma_mutex_lock(&object->mutex);
+
+        int32_t count = 0;
+        pv_circular_buffer_status_t status = pv_circular_buffer_get_count(object->buffer, &count);
+        if (status == PV_CIRCULAR_BUFFER_STATUS_SUCCESS && count == 0) {
+            is_flushed_and_empty = true;
+        } else if (status != PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
             ma_mutex_unlock(&object->mutex);
-            ma_sleep(WRITE_SLEEP_MILLI_SECONDS);
+            return PV_SPEAKER_STATUS_RUNTIME_ERROR;
         }
+
+        ma_mutex_unlock(&object->mutex);
+        ma_sleep(FLUSH_SLEEP_MS);
     }
 
-    return PV_SPEAKER_STATUS_IO_ERROR;
+    return PV_SPEAKER_STATUS_SUCCESS;
 }
 
-PV_API void pv_speaker_set_debug_logging(
-        pv_speaker_t *object,
-        bool is_debug_logging_enabled) {
+PV_API pv_speaker_status_t pv_speaker_stop(pv_speaker_t *object) {
     if (!object) {
-        return;
+        return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
     }
 
-    object->is_debug_logging_enabled = is_debug_logging_enabled;
+    is_stopped = true;
+
+    ma_result result = ma_device_stop(&(object->device));
+    if (result != MA_SUCCESS) {
+        if (result == MA_DEVICE_NOT_INITIALIZED) {
+            return PV_SPEAKER_STATUS_DEVICE_NOT_INITIALIZED;
+        } else {
+            // device already stopped
+            return PV_SPEAKER_STATUS_INVALID_STATE;
+        }
+    }
+
+    ma_mutex_lock(&object->mutex);
+    pv_circular_buffer_reset(object->buffer);
+    object->is_started = false;
+    ma_mutex_unlock(&object->mutex);
+
+    return PV_SPEAKER_STATUS_SUCCESS;
 }
 
 PV_API bool pv_speaker_get_is_started(pv_speaker_t *object) {
@@ -419,7 +467,6 @@ PV_API const char *pv_speaker_status_to_string(pv_speaker_status_t status) {
             "OUT_OF_MEMORY",
             "INVALID_ARGUMENT",
             "INVALID_STATE",
-            "BUFFER_OVERFLOW",
             "BACKEND_ERROR",
             "DEVICE_INITIALIZED",
             "DEVICE_NOT_INITIALIZED",
@@ -436,4 +483,4 @@ PV_API const char *pv_speaker_status_to_string(pv_speaker_status_t status) {
 
 PV_API const char *pv_speaker_version(void) {
     return PV_SPEAKER_VERSION;
-}
\ No newline at end of file
+}
diff --git a/project/test/test_pv_circular_buffer.c b/project/test/test_pv_circular_buffer.c
index 5599248..92e839d 100644
--- a/project/test/test_pv_circular_buffer.c
+++ b/project/test/test_pv_circular_buffer.c
@@ -13,8 +13,9 @@
 #include "test_helper.h"
 
 static void test_pv_circular_buffer_once(void) {
+    int32_t element_count = 128;
     pv_circular_buffer_t *cb;
-    pv_circular_buffer_status_t status = pv_circular_buffer_init(128, sizeof(int16_t), &cb);
+    pv_circular_buffer_status_t status = pv_circular_buffer_init(element_count, sizeof(int16_t), &cb);
     check_condition(
             status == PV_CIRCULAR_BUFFER_STATUS_SUCCESS,
             __FUNCTION__,
@@ -31,6 +32,14 @@ static void test_pv_circular_buffer_once(void) {
     status = pv_circular_buffer_write(cb, in_buffer, in_size);
     check_condition(status == PV_CIRCULAR_BUFFER_STATUS_SUCCESS, __FUNCTION__, __LINE__, "Failed to write buffer.");
 
+    int32_t available = 0;
+    status = pv_circular_buffer_get_available(cb, &available);
+    check_condition(
+            (status == PV_CIRCULAR_BUFFER_STATUS_SUCCESS && available == (element_count - in_size)),
+            __FUNCTION__,
+            __LINE__,
+            "Failed to get correct amount of available space before write.");
+
     int32_t count = 0;
     status = pv_circular_buffer_get_count(cb, &count);
     check_condition(
diff --git a/project/test/test_pv_speaker.c b/project/test/test_pv_speaker.c
index 915d06d..75b5f83 100644
--- a/project/test/test_pv_speaker.c
+++ b/project/test/test_pv_speaker.c
@@ -16,20 +16,18 @@
 
 static void init_test_helper(
         int32_t sample_rate,
-        int32_t frame_length,
         int16_t bits_per_sample,
+        int32_t buffer_size_secs,
         int32_t device_index,
-        int32_t buffered_frames_count,
         pv_speaker_status_t expected_status) {
     pv_speaker_t *speaker = NULL;
     pv_speaker_status_t status;
 
     status = pv_speaker_init(
             sample_rate,
-            frame_length,
             bits_per_sample,
+            buffer_size_secs,
             device_index,
-            buffered_frames_count,
             &speaker);
 
     check_condition(
@@ -46,34 +44,28 @@ static void init_test_helper(
 
 static void test_pv_speaker_init(void) {
     printf("Initialize with valid parameters\n");
-    init_test_helper(16000, 512, 16, 0, 10, PV_SPEAKER_STATUS_SUCCESS);
+    init_test_helper(16000, 16, 20, 0, PV_SPEAKER_STATUS_SUCCESS);
 
     printf("Initialize with valid parameters (different sample rate)\n");
-    init_test_helper(22050, 512, 16, 0, 10, PV_SPEAKER_STATUS_SUCCESS);
-
-    printf("Initialize with valid parameters (different frame length)\n");
-    init_test_helper(16000, 256, 16, 0, 10, PV_SPEAKER_STATUS_SUCCESS);
+    init_test_helper(22050, 16, 20, 0, PV_SPEAKER_STATUS_SUCCESS);
 
     printf("Initialize with valid parameters (different bits per sample)\n");
-    init_test_helper(16000, 512, 8, 0, 10, PV_SPEAKER_STATUS_SUCCESS);
+    init_test_helper(16000, 8, 20, 0, PV_SPEAKER_STATUS_SUCCESS);
 
     printf("Initialize with invalid device index (negative)\n");
-    init_test_helper(16000, 512, 16, -2, 10, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
+    init_test_helper(16000, 16, 20, -2, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
 
     printf("Initialize with invalid device index (too high)\n");
-    init_test_helper(16000, 512, 16, 500, 10, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
-
-    printf("Initialize with invalid frame length\n");
-    init_test_helper(16000, -1, 16, 0, 10, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
+    init_test_helper(16000, 16, 20, 500, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
 
     printf("Initialize with invalid bits per sample\n");
-    init_test_helper(16000, 512, -1, -2, 10, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
+    init_test_helper(16000, -1, 20, 0, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
 
-    printf("Initialize with invalid buffered frames count\n");
-    init_test_helper(16000, 512, 16, 0, 0, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
+    printf("Initialize with invalid buffer size secs\n");
+    init_test_helper(16000, 16, 0, 20, PV_SPEAKER_STATUS_INVALID_ARGUMENT);
 
     printf("Initialize with null speaker pointer\n");
-    pv_speaker_status_t status = pv_speaker_init(16000, 512, 16, 0, 10, NULL);
+    pv_speaker_status_t status = pv_speaker_init(16000, 16, 20, 0, NULL);
     check_condition(
             status == PV_SPEAKER_STATUS_INVALID_ARGUMENT,
             __FUNCTION__,
@@ -86,11 +78,12 @@ static void test_pv_speaker_init(void) {
 static void test_pv_speaker_start_stop(void) {
     pv_speaker_t *speaker = NULL;
     pv_speaker_status_t status;
-    int32_t frame_length = 512;
-    int16_t frame[frame_length];
-    char *frame_ptr = (char *) frame;
+    int32_t pcm_length = 512;
+    int16_t pcm[pcm_length];
+    int8_t *pcm_ptr = (int8_t *) pcm;
+    int32_t written_length = 0;
 
-    status = pv_speaker_init(16000, frame_length, 16, 0, 10, &speaker);
+    status = pv_speaker_init(16000, 16, 20, 0, &speaker);
     check_condition(
             status == PV_SPEAKER_STATUS_SUCCESS,
             __FUNCTION__,
@@ -125,8 +118,8 @@ static void test_pv_speaker_start_stop(void) {
             pv_speaker_status_to_string(status),
             pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT));
 
-    printf("Call read before start object\n");
-    status = pv_speaker_write(speaker, frame_length, frame_ptr);
+    printf("Call write before start object\n");
+    status = pv_speaker_write(speaker, pcm_ptr, pcm_length, &written_length);
     check_condition(
             status == PV_SPEAKER_STATUS_INVALID_STATE,
             __FUNCTION__,
@@ -146,7 +139,17 @@ static void test_pv_speaker_start_stop(void) {
             pv_speaker_status_to_string(PV_SPEAKER_STATUS_SUCCESS));
 
     printf("Call write on null speaker\n");
-    status = pv_speaker_write(NULL, frame_length, frame_ptr);
+    status = pv_speaker_write(NULL, pcm_ptr, pcm_length, &written_length);
+    check_condition(
+            status == PV_SPEAKER_STATUS_INVALID_ARGUMENT,
+            __FUNCTION__,
+            __LINE__,
+            "Speaker write returned %s - expected %s.",
+            pv_speaker_status_to_string(status),
+            pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT));
+
+    printf("Call write with null pcm\n");
+    status = pv_speaker_write(speaker, NULL, pcm_length, &written_length);
     check_condition(
             status == PV_SPEAKER_STATUS_INVALID_ARGUMENT,
             __FUNCTION__,
@@ -155,8 +158,8 @@ static void test_pv_speaker_start_stop(void) {
             pv_speaker_status_to_string(status),
             pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT));
 
-    printf("Call write with null frame\n");
-    status = pv_speaker_write(speaker, frame_length, NULL);
+    printf("Call write with null written length\n");
+    status = pv_speaker_write(speaker, pcm_ptr, pcm_length, NULL);
     check_condition(
             status == PV_SPEAKER_STATUS_INVALID_ARGUMENT,
             __FUNCTION__,
@@ -166,7 +169,7 @@ static void test_pv_speaker_start_stop(void) {
             pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT));
 
     printf("Call write with valid args\n");
-    status = pv_speaker_write(speaker, frame_length, frame_ptr);
+    status = pv_speaker_write(speaker, pcm_ptr, pcm_length, &written_length);
     check_condition(
             status == PV_SPEAKER_STATUS_SUCCESS,
             __FUNCTION__,
@@ -183,16 +186,36 @@ static void test_pv_speaker_start_stop(void) {
             __LINE__,
             "get_is_started returned false - expected true.");
 
-    printf("Call stop on null speaker object\n");
-    status = pv_speaker_stop(NULL);
+    printf("Call flush on null speaker\n");
+    status = pv_speaker_flush(NULL, pcm_ptr, pcm_length, &written_length);
     check_condition(
             status == PV_SPEAKER_STATUS_INVALID_ARGUMENT,
             __FUNCTION__,
             __LINE__,
-            "Speaker stop returned %s - expected %s.",
+            "Speaker flush returned %s - expected %s.",
             pv_speaker_status_to_string(status),
             pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT));
 
+    printf("Call flush with null pcm\n");
+    status = pv_speaker_flush(speaker, NULL, pcm_length, &written_length);
+    check_condition(
+            status == PV_SPEAKER_STATUS_INVALID_ARGUMENT,
+            __FUNCTION__,
+            __LINE__,
+            "Speaker flush returned %s - expected %s.",
+            pv_speaker_status_to_string(status),
+            pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT));
+
+    printf("Call flush with valid args\n");
+    status = pv_speaker_flush(speaker, pcm_ptr, pcm_length, &written_length);
+    check_condition(
+            status == PV_SPEAKER_STATUS_SUCCESS,
+            __FUNCTION__,
+            __LINE__,
+            "Speaker flush returned %s - expected %s.",
+            pv_speaker_status_to_string(status),
+            pv_speaker_status_to_string(PV_SPEAKER_STATUS_SUCCESS));
+
     printf("Call stop on valid speaker object\n");
     status = pv_speaker_stop(speaker);
     check_condition(
@@ -214,9 +237,18 @@ static void test_pv_speaker_start_stop(void) {
     pv_speaker_delete(speaker);
 }
 
-static void test_pv_speaker_set_debug_logging(void) {
+static void test_pv_speaker_write_flow(void) {
     pv_speaker_t *speaker = NULL;
-    pv_speaker_status_t status = pv_speaker_init(16000, 512, 16, 0, 10, &speaker);
+    pv_speaker_status_t status;
+    int32_t sample_rate = 16000;
+    int32_t buffer_size_secs = 1;
+    int32_t circular_buffer_size = sample_rate * buffer_size_secs;
+    int32_t pcm_length = circular_buffer_size + 1;
+    int16_t pcm[pcm_length];
+    int8_t *pcm_ptr = (int8_t *) pcm;
+    int32_t written_length = 0;
+
+    status = pv_speaker_init(sample_rate, 16, buffer_size_secs, 0, &speaker);
     check_condition(
             status == PV_SPEAKER_STATUS_SUCCESS,
             __FUNCTION__,
@@ -225,15 +257,33 @@ static void test_pv_speaker_set_debug_logging(void) {
             pv_speaker_status_to_string(status),
             pv_speaker_status_to_string(PV_SPEAKER_STATUS_SUCCESS));
 
-    pv_speaker_set_debug_logging(NULL, true);
-    pv_speaker_set_debug_logging(speaker, true);
+    printf("Call write with pcm length greater than circular buffer's capacity/available space\n");
+    status = pv_speaker_write(speaker, pcm_ptr, pcm_length, &written_length);
+    check_condition(
+            (status == PV_SPEAKER_STATUS_SUCCESS && written_length == circular_buffer_size),
+            __FUNCTION__,
+            __LINE__,
+            "Speaker write returned %s - expected %s.",
+            pv_speaker_status_to_string(status),
+            pv_speaker_status_to_string(PV_SPEAKER_STATUS_SUCCESS));
+
+    printf("Call flush with pcm length greater than circular buffer's capacity/available space\n");
+    status = pv_speaker_flush(speaker, pcm_ptr, pcm_length, &written_length);
+    check_condition(
+            (status == PV_SPEAKER_STATUS_SUCCESS && written_length == pcm_length),
+            __FUNCTION__,
+            __LINE__,
+            "Speaker flush returned %s - expected %s.",
+            pv_speaker_status_to_string(status),
+            pv_speaker_status_to_string(PV_SPEAKER_STATUS_SUCCESS));
 
+    pv_speaker_stop(speaker);
     pv_speaker_delete(speaker);
 }
 
 static void test_pv_speaker_get_selected_device(void) {
     pv_speaker_t *speaker = NULL;
-    pv_speaker_status_t status = pv_speaker_init(16000, 512, 16, 0, 10, &speaker);
+    pv_speaker_status_t status = pv_speaker_init(16000, 16, 20, 0, &speaker);
     check_condition(
             status == PV_SPEAKER_STATUS_SUCCESS,
             __FUNCTION__,
@@ -319,7 +369,6 @@ int main() {
     test_pv_speaker_version();
     test_pv_speaker_init();
     test_pv_speaker_start_stop();
-    test_pv_speaker_set_debug_logging();
     test_pv_speaker_get_selected_device();
 
     return 0;