From ab2deb1c8161fd44c9969efb8a3fe017e396501c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Damian=20Kara=C5=9B?= <s176030@student.pg.edu.pl>
Date: Sat, 11 Sep 2021 21:41:57 +0200
Subject: [PATCH] pulled changes from master

---
 .vscode/c_cpp_properties.json | 24 +++++++++++++-----
 CHANGELOG                     |  3 +++
 src/cpp/ALSA_support.cpp      |  4 +--
 src/cpp/DSP_IO.cpp            |  2 +-
 src/cpp/WMM_support.cpp       | 48 ++++++++++++++++++++++++++++++-----
 src/include/ALSA_support.h    |  2 +-
 src/include/DSP_lib.h         |  2 +-
 src/include/DSP_types.h       | 17 +++++++++++--
 src/include/WMM_support.h     |  3 ++-
 9 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 3ee473f..acfe4b8 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -4,7 +4,9 @@
         {
             "name": "Windows64-Release",
             "includePath": [
-                "${workspaceFolder}/src/**"
+                "${workspaceFolder}/src/",
+                "${workspaceFolder}/src/include",
+                "${workspaceFolder}/src/include/rls"
             ],
             "defines": [
                 "WIN32",
@@ -18,7 +20,9 @@
         {
             "name": "Windows32-Release",
             "includePath": [
-                "${workspaceFolder}/src/**"
+                "${workspaceFolder}/src/",
+                "${workspaceFolder}/src/include",
+                "${workspaceFolder}/src/include/rls"
             ],
             "defines": [
                 "WIN32",
@@ -32,7 +36,9 @@
         {
             "name": "Windows32-Debug",
             "includePath": [
-                "${workspaceFolder}/src/**"
+                "${workspaceFolder}/src/",
+                "${workspaceFolder}/src/include",
+                "${workspaceFolder}/src/include/dbg"
             ],
             "defines": [
                 "WIN32",
@@ -47,7 +53,9 @@
         {
             "name": "Windows64-Debug",
             "includePath": [
-                "${workspaceFolder}/src/**"
+                "${workspaceFolder}/src/",
+                "${workspaceFolder}/src/include",
+                "${workspaceFolder}/src/include/dbg"
             ],
             "defines": [
                 "WIN32",
@@ -77,7 +85,9 @@
         {
             "name": "Linux-Release",
             "includePath": [
-                "${workspaceFolder}/src/**"
+                "${workspaceFolder}/src",
+                "${workspaceFolder}/src/include",
+                "${workspaceFolder}/src/include/rls"
             ],
             "defines": [
                 "LINUX",
@@ -91,7 +101,9 @@
         {
             "name": "Linux-Debug",
             "includePath": [
-                "${workspaceFolder}/src/include/**"
+                "${workspaceFolder}/src/include",
+                "${workspaceFolder}/src/include",
+                "${workspaceFolder}/src/include/dbg"
             ],
             "defines": [
                 "LINUX",
diff --git a/CHANGELOG b/CHANGELOG
index d861133..0b860c4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,9 @@ TODO::
 LAST DONE:
 
 CHANGES:
+- ver. 0.20.009 - <b>2021.09.10</b> Changed: 
+  - Fixed: DSP::WMM_object_t and DSP::SOUND_object_t now send to sound card all pending data and wait for finish before closing
+
 - ver. 0.20.008 - <b>2021.05.16</b> Changed: 
   - Added SOUND_object_t::get_wave_in_raw_buffer for non-callback input operations
   - DSP::u::AudioInput now falls back to non-callback mode if SOUND_object_t doesn't support callbacks
diff --git a/src/cpp/ALSA_support.cpp b/src/cpp/ALSA_support.cpp
index 1414ee9..300b1ce 100644
--- a/src/cpp/ALSA_support.cpp
+++ b/src/cpp/ALSA_support.cpp
@@ -732,9 +732,9 @@ bool DSP::ALSA_object_t::close_PCM_device_input(void) {
   return true;
 }
 
-bool DSP::ALSA_object_t::close_PCM_device_output(void) {
+bool DSP::ALSA_object_t::close_PCM_device_output(bool do_drain) {
   //! \todo if IsPlayingNow == false first do pcm_writei on all already filled appended buffers (check also in WMM)
-  close_alsa_device(true);
+  close_alsa_device(do_drain);
   return true;
 }
 
diff --git a/src/cpp/DSP_IO.cpp b/src/cpp/DSP_IO.cpp
index 7187567..c5a112a 100644
--- a/src/cpp/DSP_IO.cpp
+++ b/src/cpp/DSP_IO.cpp
@@ -4179,7 +4179,7 @@ DSP::u::AudioOutput::~AudioOutput()
   { // if device was opened successfully
     snd_object.stop_playback();
 
-    snd_object.close_PCM_device_output();
+    snd_object.close_PCM_device_output(true);
 
     // #ifdef WINMMAPI
     //   result = waveOutReset(hWaveOut);
diff --git a/src/cpp/WMM_support.cpp b/src/cpp/WMM_support.cpp
index 2304440..04f005f 100644
--- a/src/cpp/WMM_support.cpp
+++ b/src/cpp/WMM_support.cpp
@@ -30,7 +30,7 @@ DSP::WMM_object_t::~WMM_object_t()
     close_PCM_device_input();
   }
   if (is_device_output_open) {
-    close_PCM_device_output();
+    close_PCM_device_output(true);
   }
 
 }
@@ -139,7 +139,21 @@ unsigned int DSP::WMM_object_t::select_input_device_by_number(const unsigned int
 
 bool DSP::WMM_object_t::stop_playback(void) {
   StopPlayback = true;
-  //! \TODO can we do more ?
+  
+  // if there are still buffers that haven't been yet sent to sound card then do it now
+  if (IsPlayingNow == false)
+  {
+    if (NextBufferOutInd == DSP::NoOfAudioOutputBuffers - 2) //all but one spare buffer are filled up
+    { // send all data from buffers to soundcard to start playback
+      for (unsigned int ind=0; ind < DSP::NoOfAudioOutputBuffers-1; ind++) //one spare buffer
+      {
+        result=waveOutWrite(hWaveOut,
+          &(waveHeaderOut[ind]), sizeof(WAVEHDR));
+        DSP::f::AudioCheckError(result);
+      }
+      IsPlayingNow = true;
+    }
+  }
 
   return true;
 }
@@ -269,7 +283,7 @@ long DSP::WMM_object_t::open_PCM_device_4_output(const int &no_of_channels, int
   if (is_device_output_open)
   {
     DSP::log << "DSP::WMM_object_t::open_PCM_device_4_output" << DSP::e::LogMode::second << "Device has been already opened: closing device before reopening" << endl;
-    close_PCM_device_output();
+    close_PCM_device_output(false);
   }
 
   switch (no_of_bits)
@@ -390,7 +404,29 @@ bool DSP::WMM_object_t::close_PCM_device_input(void) {
   return true;
 }
 
-bool DSP::WMM_object_t::close_PCM_device_output(void) {
+bool DSP::WMM_object_t::close_PCM_device_output(const bool &do_drain) {
+  bool DSP::WMM_object_t::close_PCM_device_output(const bool &do_drain) {
+  stop_playback(); // just to be sure that all prepared buffershave been sent to sound card
+
+  if (do_drain == true) {
+    bool still_playing = true;
+    while (still_playing) {
+      int counter = 0;
+      for (unsigned int ind=0; ind < DSP::NoOfAudioOutputBuffers; ind++) //one spare buffer
+      {
+        if (waveHeaderOut[NextBufferOutInd].dwFlags & WHDR_DONE)
+          counter++;
+      }
+      if (counter == DSP::NoOfAudioOutputBuffers) {
+        still_playing = false;
+      }
+      else {
+        // let system process others and then check again
+        DSP::f::Sleep(0);
+      }
+    }
+  }
+
   result = waveOutReset(hWaveOut);
   DSP::f::AudioCheckError(result);
   
@@ -578,10 +614,10 @@ long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer)
 
       if (IsPlayingNow == false)
       {
-        if (NextBufferOutInd == 1)
+        if (NextBufferOutInd == DSP::NoOfAudioOutputBuffers - 2) //all but one spare buffer are filled up
         {
           for (ind=0; ind < DSP::NoOfAudioOutputBuffers-1; ind++) //one spare buffer
-          {
+          { // send all data from buffers to soundcard to start playback
             result=waveOutWrite(hWaveOut,
               &(waveHeaderOut[ind]), sizeof(WAVEHDR));
             DSP::f::AudioCheckError(result);
diff --git a/src/include/ALSA_support.h b/src/include/ALSA_support.h
index a15fccc..57c64ec 100644
--- a/src/include/ALSA_support.h
+++ b/src/include/ALSA_support.h
@@ -106,7 +106,7 @@ namespace DSP {
         
         //! Closes PCM device
         bool close_PCM_device_input(void);
-        bool close_PCM_device_output(void);
+        bool close_PCM_device_output(const bool &do_drain);
 
         //! Returns true is the playback is on
         bool is_device_playing(void);
diff --git a/src/include/DSP_lib.h b/src/include/DSP_lib.h
index bca9649..e0ff366 100644
--- a/src/include/DSP_lib.h
+++ b/src/include/DSP_lib.h
@@ -11,7 +11,7 @@
 
 #define DSP_VER_MAJOR 0
 #define DSP_VER_MINOR 20
-#define DSP_VER_BUILD 8 // !!! without zeroes before, else this will be treated as octal number
+#define DSP_VER_BUILD 9 // !!! without zeroes before, else this will be treated as octal number
 #define DSP_VER_YEAR  2021
 #define DSP_VER       DSP_VER_MAJOR.DSP_VER_MINOR.DSP_VER_BUILD
 
diff --git a/src/include/DSP_types.h b/src/include/DSP_types.h
index 0822f61..29519d3 100644
--- a/src/include/DSP_types.h
+++ b/src/include/DSP_types.h
@@ -573,18 +573,31 @@ namespace DSP {
       //! audio_inbuffer_size is in samples (note that, for example, sample for 16bit stereo is represented by 4bytes)
       virtual long open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_inbuffer_size = -1) = 0;
       virtual bool close_PCM_device_input(void) = 0;
-      virtual bool close_PCM_device_output(void) = 0;
+       //! close sound card output
+      /*! if do_drain == true wait until sound card stops playing 
+       */ 
+      virtual bool close_PCM_device_output(const bool &do_drain) = 0;
 
       //! returns true is the playback is on
       virtual bool is_device_playing(void) = 0;
       //! initializes playback stopping
+      /*! If there are still buffers that haven't been yet sent to sound card then do it now
+       */
       virtual bool stop_playback(void) = 0;
       //! returns true is the sound capture is on
       virtual bool is_device_recording(void) = 0;
       //! returns true is the sound capture is on
       virtual bool stop_recording(void) = 0;
 
-      //! \note values stored in float_buffer might be altered
+      /*! Appends data to audio buffers and sends data to sound card is buffer is full.
+      * The class implementation should provide at least DSP::NoOfAudioOutputBuffers buffers with space for audio_outbuffer_size sample each.  
+      * When sound is playing then if the function call results in filling the buffer (or buffers) 
+      * all full buffers should be sent to the sound card.
+      * When sound has not stated playing yest then full buffers sould be sent to the sound card only when 
+      * DSP::NoOfAudioOutputBuffers-1 buffers are filled. This prevents sound staterring and leaves one spare buffer for new samples.
+      * 
+      * \note values stored in float_buffer might be altered
+      */
       virtual long append_playback_buffer(DSP::Float_vector &float_buffer)=0;
       //! Starts sound capture
       virtual bool start_recording(void) = 0;
diff --git a/src/include/WMM_support.h b/src/include/WMM_support.h
index 63af568..05f907f 100644
--- a/src/include/WMM_support.h
+++ b/src/include/WMM_support.h
@@ -83,8 +83,9 @@ namespace DSP {
         //! opens default PCM device for capture and returns selected sampling rate on success or negative error code
         long open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_inbuffer_size = -1);
 
+
         bool close_PCM_device_input(void);
-        bool close_PCM_device_output(void);
+        bool close_PCM_device_output(const bool &do_drain);
 
         bool stop_playback(void);
         bool stop_recording(void);
-- 
GitLab