From 08a3caf0b60fbf1d1776acb4d135bca483ddb91a Mon Sep 17 00:00:00 2001
From: Marek Blok <marek.blok@pg.edu.pl>
Date: Sun, 16 May 2021 12:06:59 +0200
Subject: [PATCH] initial convertion of ALSA_object_t to class based on
 SOUND_object_t

---
 CHANGELOG                  |  3 ++
 src/Main.cpp               | 39 ++++++++++-------
 src/Makefile.linux         | 20 +++++++--
 src/cpp/ALSA_support.cpp   | 90 ++++++++++++++++++++++++++++++++++----
 src/cpp/DSP_IO.cpp         | 23 ++++++++--
 src/cpp/WMM_support.cpp    |  4 +-
 src/include/ALSA_support.h | 42 +++++++++++++++---
 src/include/DSP_IO.h       | 12 ++++-
 src/include/DSP_lib.h      |  2 +-
 src/include/DSP_types.h    | 25 ++++++++---
 src/include/WMM_support.h  |  4 +-
 11 files changed, 212 insertions(+), 52 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 00975c4..15826cb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,9 @@ TODO::
 LAST DONE:
 
 CHANGES:
+- ver. 0.20.007 - <b>2021.05.16</b> Changed: 
+  - initial convertion of ALSA_object_t to class based on SOUND_object_t
+
 - ver. 0.20.006 - <b>2021.05.14</b> Changed: 
   - Included examples tests in DEBUG compilation for windows (test_hello, test_sound_input)
   - DSP::u::AudioInput now uses SOUND_object_t (currently just WMM_object_t) for soundcard API
diff --git a/src/Main.cpp b/src/Main.cpp
index 2b929e3..339600d 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -2718,21 +2718,22 @@ int test_ZPSTC_cw_3()
   to the default PCM device for 5 seconds of data.
   */
 
-  int test_playback(vector<int16_t> buffer) {
+  int test_playback(DSP::Float_vector &float_buffer) {
     long loops;
-    int rc;
+    long rc;
     int frames_size;
     snd_pcm_uframes_t frames;
     //char *buffer;
     unsigned int period_time;
 
-    ALSA_object_t ALSA_object;
+    DSP::ALSA_object_t ALSA_object;
 
     /* Open PCM device for playback (2 channels). */
-    unsigned int Fs = 44100;
-    rc = ALSA_object.open_alsa_device(SND_PCM_STREAM_PLAYBACK, 2, Fs);
+    long Fs = 44100;
+    //rc = ALSA_object.open_alsa_device(SND_PCM_STREAM_PLAYBACK, 2, Fs);
+    rc = ALSA_object.open_PCM_device_4_output(2, 16, Fs);
 
-    ALSA_object.get_params(frames, period_time);
+    //ALSA_object.get_period_size(frames, period_time);
 
   //  /* Allocate a hardware parameters object. */
   //  snd_pcm_hw_params_alloca(&params);
@@ -2741,15 +2742,17 @@ int test_ZPSTC_cw_3()
   //
   //  /* Use a buffer large enough to hold one period */
   //  snd_pcm_hw_params_get_period_size(params, &frames, &dir);
-    frames_size = frames * 2/sizeof(int16_t) * 2; /* 2 bytes/sample, 2 channels */
+//    frames_size = frames * 2/sizeof(int16_t) * 2; /* 2 bytes/sample, 2 channels */
+    frames_size = 1024 * 2/sizeof(int16_t) * 2; /* 2 bytes/sample, 2 channels */
     //buffer = (char *) malloc(size);
   //
   //  /* We want to loop for 5 seconds */
   //  snd_pcm_hw_params_get_period_time(params, &val, &dir);
     /* 5 seconds in microseconds divided by
     * period time */
+    period_time = Fs/frames_size;
     loops = 5000000 / period_time;
-    buffer.resize(loops * frames_size, 0);
+    float_buffer.resize(loops * frames_size, 0);
 
     int loop_index = 0;
     while (loops > 0) {
@@ -2758,16 +2761,18 @@ int test_ZPSTC_cw_3()
   //    //rc = read(0, buffer, size);
       for (int ind = 0; ind < frames_size; ind++)
       {
-          buffer[ind + loop_index * frames_size] = (4*ind) % INT16_MAX;
+          float_buffer[ind + loop_index * frames_size] = (4*ind) % INT16_MAX;
       }
 
       //! \TODO check problem with vector aligments
-      rc = ALSA_object.pcm_writei(buffer.data() + loop_index * frames_size, frames);
+      //rc = ALSA_object.pcm_writei(buffer.data() + loop_index * frames_size, frames);
+      rc = ALSA_object.append_playback_buffer(float_buffer);
 
       loop_index++;
     }
 
-    ALSA_object.close_alsa_device(true); //snd_pcm_close(alsa_handle);
+    //ALSA_object.close_alsa_device(true); //snd_pcm_close(alsa_handle);
+    ALSA_object.close_PCM_device_output(); 
     //free(buffer);
 
     return 0;
@@ -2907,19 +2912,23 @@ polling:
 */ 
 
   int test_ALSA() {
-    ALSA_object_t ALSA_object;
+    DSP::ALSA_object_t ALSA_object;
 
     ALSA_object.log_driver_data();
 
     unsigned int Fs = 44100;
-    int rs = ALSA_object.open_alsa_device(SND_PCM_STREAM_PLAYBACK, 2, Fs);
+    int rs = ALSA_object.open_PCM_device_4_output(2, 16, Fs);
     if (rs == 1) {
-      ALSA_object.close_alsa_device();
+      ALSA_object.close_PCM_device_output();
     }
 
 
     vector<int16_t> signal = test_record();
-    test_playback(signal);
+    DSP::Float_vector float_signal;
+    for (auto ind=0; ind < signal.size(); ind++) {
+      float_signal[ind] = signal[ind];
+    }
+    test_playback(float_signal);
 
     return 0;
   } 
diff --git a/src/Makefile.linux b/src/Makefile.linux
index bb16c0b..2443d6c 100644
--- a/src/Makefile.linux
+++ b/src/Makefile.linux
@@ -11,6 +11,7 @@ com_ver = $(shell gcc -dumpmachine)-gcc_$(shell gcc -dumpversion)
 INSTALL_DIR_ROOT = ../_DSPE_lib_linux_
 
 SRC_DIR = ./src
+SRC_EXAMPLES_DIR = ./examples
 SRC_CPP_SUBDIR = $(SRC_DIR)/cpp
 
 
@@ -42,6 +43,9 @@ SOURCES = $(addprefix $(SRC_CPP_SUBDIR)/,$(SOURCES_NAMES))
 SOURCES_DBG =
 SOURCES_DBG += $(SRC_DIR)/Main.cpp
 
+SOURCES_EXAMPLES_DBG =
+SOURCES_EXAMPLES_DBG += $(SRC_EXAMPLES_DIR)/hello.cpp $(SRC_EXAMPLES_DIR)/sound_input.cpp 
+
 # ################################################# #
 # Just sockets // currently not supported in Linux
 SOURCES_SOCKETS_NAMES = DSP_sockets.cpp 
@@ -64,6 +68,8 @@ OBJECTS_Debug 		  := $(SOURCES:%.cpp=$(OUT_DIR_DBG)/%.o)
 DEPENDS_Debug 		  := $(SOURCES:%.cpp=$(OUT_DIR_DBG)/%.d)
 OBJECTS_Debug 		  += $(SOURCES_DBG:%.cpp=$(OUT_DIR_DBG)/%.o)
 DEPENDS_Debug 		  += $(SOURCES_DBG:%.cpp=$(OUT_DIR_DBG)/%.d)
+OBJECTS_EXAMPLES_Debug := $(SOURCES_EXAMPLES_DBG:%.cpp=$(OUT_DIR_DBG)/%.o)
+DEPENDS_EXAMPLES_Debug := $(SOURCES_EXAMPLES_DBG:%.cpp=$(OUT_DIR_DBG)/%.d)
 OBJECTS_SOCKETS_Debug := $(SOURCES_SOCKETS:%.cpp=$(OUT_DIR_DBG)/%.o)
 DEPENDS_SOCKETS_Debug := $(SOURCES_SOCKETS:%.cpp=$(OUT_DIR_DBG)/%.d)
 
@@ -77,6 +83,7 @@ OBJECTS_MISC_Debug :=
 -include $(DEPENDS_SOCKETS_Release)
 -include $(DEPENDS_Debug)
 -include $(DEPENDS_SOCKETS_Debug)
+-include $(DEPENDS_EXAMPLES_Debug)
 
 all: Debug Release
 
@@ -105,11 +112,11 @@ $(OBJECTS_Release) $(OBJECTS_SOCKETS_Release): $(OUT_DIR_RLS)/%.o : %.cpp
 
 # ########################################################################################### #	
 # ########################################################################################### #	
-# Debug: $(OUT_DIR_DBG)/libDSPE.a $(OUT_DIR_DBG)/libDSPEsockets.a
+# Debug: $(OUT_DIR_DBG)/libDSPE.a $(OUT_DIR_DBG)/libDSPEsockets.a $(OUT_DIR_DBG)/libDSPEexamples.a
 Debug: $(OUT_DIR_DBG)/DSPElib.exe
 
-$(OUT_DIR_DBG)/DSPElib.exe: $(OUT_DIR_DBG)/libDSPE.a $(OUT_DIR_DBG)/libDSPEsockets.a 
-	$(CC) -L"$(OUT_DIR_DBG)" "$(OUT_DIR_DBG)/src/Main.o" -o"$(OUT_DIR_DBG)/DSPElib.exe" $(LINKER_FLAGS_debug) -lDSPE $(LIBS)
+$(OUT_DIR_DBG)/DSPElib.exe: $(OUT_DIR_DBG)/libDSPE.a $(OUT_DIR_DBG)/libDSPEsockets.a  $(OUT_DIR_DBG)/libDSPEexamples.a
+	$(CC) -L"$(OUT_DIR_DBG)" "$(OUT_DIR_DBG)/src/Main.o" -o"$(OUT_DIR_DBG)/DSPElib.exe" $(LINKER_FLAGS_debug) -lDSPE -lDSPEexamples $(LIBS)
 
 $(OUT_DIR_DBG)/libDSPE.a: $(OBJECTS_Debug) $(OBJECTS_MISC_Debug)
 	@echo Preparing lib file $@
@@ -120,8 +127,13 @@ $(OUT_DIR_DBG)/libDSPEsockets.a:  $(OBJECTS_SOCKETS_Debug)
 	ar rc $@  $(OBJECTS_SOCKETS_Debug)
 	ranlib $@
 
+$(OUT_DIR_DBG)/libDSPEexamples.a:  $(OBJECTS_EXAMPLES_Debug)
+	@echo Preparing lib file $@
+	ar rc $@  $(OBJECTS_EXAMPLES_Debug)
+	ranlib $@
+
 # Z podanej listy usuwany $(OUT_DIR_RLS)/ oraz '.o' zamieniamy na '.cpp'
-$(OBJECTS_Debug) $(OBJECTS_SOCKETS_Debug) $(OBJECTS_MISC_Debug): $(OUT_DIR_DBG)/%.o : %.cpp
+$(OBJECTS_Debug) $(OBJECTS_EXAMPLES_Debug) $(OBJECTS_SOCKETS_Debug) $(OBJECTS_MISC_Debug): $(OUT_DIR_DBG)/%.o : %.cpp
 	@echo $(@D) $< $@
 	
 	mkdir -p $(@D)
diff --git a/src/cpp/ALSA_support.cpp b/src/cpp/ALSA_support.cpp
index 0632be7..7013fd0 100644
--- a/src/cpp/ALSA_support.cpp
+++ b/src/cpp/ALSA_support.cpp
@@ -4,18 +4,20 @@
  * \author Marek Blok
  */
 
-#include "ALSA_support.h"
+#include <ALSA_support.h>
+
+#include <DSP_lib.h> // for logging 
 
 // ============================================================= //
 // Based on: https://www.linuxjournal.com/article/6735
 // ============================================================= //
 
-ALSA_object_t::ALSA_object_t()
+DSP::ALSA_object_t::ALSA_object_t()
 {
   alsa_handle = NULL;
   hw_params = NULL;
 };
-ALSA_object_t::~ALSA_object_t()
+DSP::ALSA_object_t::~ALSA_object_t()
 {
   if (hw_params != NULL){
     snd_pcm_hw_params_free(hw_params);
@@ -23,8 +25,25 @@ ALSA_object_t::~ALSA_object_t()
   }
 }
 
+unsigned int DSP::ALSA_object_t::select_input_device_by_number(const unsigned int &device_number) {
+  assert(!"ALSA_object_t::select_input_device_by_number not yet implemented");
+}
+
+unsigned int DSP::ALSA_object_t::select_output_device_by_number(const unsigned int &device_number) {
+  assert(!"ALSA_object_t::select_output_device_by_number not yet implemented");
+}
+
+bool DSP::ALSA_object_t::is_output_callback_supported(void) {
+  assert(!"ALSA_object_t::is_output_callback_supported not yet implemented");
+  return false;
+}
+
+bool DSP::ALSA_object_t::is_input_callback_supported(void) {
+  assert(!"ALSA_object_t::is_input_callback_supported not yet implemented");
+  return false;
+}
 
-void ALSA_object_t::log_driver_data() {
+void DSP::ALSA_object_t::log_driver_data() {
   int val;
 
   DSP::log << "ALSA library version: " << SND_LIB_VERSION_STR << endl;
@@ -69,7 +88,7 @@ perform any sound playback or recording.
 returns actually selected sampling_rate
 
 */
-int ALSA_object_t::open_alsa_device(snd_pcm_stream_t stream_type, int no_of_channels, unsigned int &sampling_rate) {
+int DSP::ALSA_object_t::open_alsa_device(snd_pcm_stream_t stream_type, int no_of_channels, unsigned int &sampling_rate) {
   int rc;
   snd_pcm_t *handle;
   unsigned int val, val2;
@@ -86,7 +105,7 @@ int ALSA_object_t::open_alsa_device(snd_pcm_stream_t stream_type, int no_of_chan
     //! \TODO Test mode:	Open mode (see SND_PCM_NONBLOCK, SND_PCM_ASYNC)
     /* Open PCM device for playback. */
     rc = snd_pcm_open(&handle, "default",
-                      stream_type, 0);
+                      stream_type, SND_PCM_NONBLOCK);
     if (rc < 0) {
       DSP::log << "unable to open pcm device: " << snd_strerror(rc) << endl;
       //exit(1);
@@ -120,6 +139,8 @@ int ALSA_object_t::open_alsa_device(snd_pcm_stream_t stream_type, int no_of_chan
     /* 44100 bits/second sampling rate (CD quality) */
     snd_pcm_hw_params_set_rate_near(alsa_handle, params, &sampling_rate, &dir);
 
+    //snd_pcm_hw_params_set_buffer_size();
+
     /* Write the parameters to the driver */
     rc = snd_pcm_hw_params(alsa_handle, params);
     if (rc < 0) {
@@ -225,12 +246,16 @@ int ALSA_object_t::open_alsa_device(snd_pcm_stream_t stream_type, int no_of_chan
   return 1;
 }
 
-void ALSA_object_t::get_params(snd_pcm_uframes_t &frames, unsigned int &period_time) {
+void DSP::ALSA_object_t::get_period_size(snd_pcm_uframes_t &frames, unsigned int &period_time) {
   int dir;
 
   // snd_pcm_hw_params_current() // Retreive current PCM hardware configuration chosen with snd_pcm_hw_params.
   //snd_pcm_hw_params_current(alsa_handle, hw_params);
 
+  // https://www.alsa-project.org/wiki/FramesPeriods
+  // frame - size of sample in byts
+  // A period is the number of frames in between each hardware interrupt
+
   /* Use a buffer large enough to hold one period */
   snd_pcm_hw_params_get_period_size(hw_params, &frames, &dir);
 
@@ -238,7 +263,54 @@ void ALSA_object_t::get_params(snd_pcm_uframes_t &frames, unsigned int &period_t
   snd_pcm_hw_params_get_period_time(hw_params, &period_time, &dir);
 }
 
-snd_pcm_sframes_t ALSA_object_t::pcm_writei(const void *buffer, snd_pcm_uframes_t &frames) {
+long DSP::ALSA_object_t::open_PCM_device_4_output(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size) {
+  assert(!"DSP::ALSA_object_t::open_PCM_device_4_output not implemented yet");
+}
+
+long DSP::ALSA_object_t::open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size) {
+  assert(!"DSP::ALSA_object_t::open_PCM_device_4_input not implemented yet");
+}
+
+long DSP::ALSA_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) {
+  assert(!"DSP::ALSA_object_t::append_playback_buffer not implemented yet");
+}
+
+bool DSP::ALSA_object_t::close_PCM_device_input(void) {
+  assert(!"DSP::ALSA_object_t::close_PCM_device_input not implemented yet");
+  close_alsa_device(true);
+  return true;
+}
+
+bool DSP::ALSA_object_t::close_PCM_device_output(void) {
+  assert(!"DSP::ALSA_object_t::close_PCM_device_output not implemented yet");
+  close_alsa_device(true);
+  return true;
+}
+
+bool DSP::ALSA_object_t::is_device_playing(void) {
+  assert(!"DSP::ALSA_object_t::is_device_playing not implemented yet");
+  return false;
+}
+
+bool DSP::ALSA_object_t::is_device_recording(void) {
+  assert(!"DSP::ALSA_object_t::is_device_recording not implemented yet");
+  return false;
+}
+
+bool DSP::ALSA_object_t::stop_playback(void) {
+  assert(!"DSP::ALSA_object_t::stop_playback not implemented yet");
+}
+
+bool DSP::ALSA_object_t::stop_recording(void) {
+  assert(!"DSP::ALSA_object_t::stop_recording not implemented yet");
+}
+
+bool DSP::ALSA_object_t::start_recording(void) {
+  assert(!"DSP::ALSA_object_t::stop_recording not implemented yet");
+}
+
+
+snd_pcm_sframes_t DSP::ALSA_object_t::pcm_writei(const void *buffer, snd_pcm_uframes_t &frames) {
   snd_pcm_sframes_t rc = snd_pcm_writei(alsa_handle, buffer, frames);
   if (rc == -EPIPE) {
     /* EPIPE means underrun */
@@ -255,7 +327,7 @@ snd_pcm_sframes_t ALSA_object_t::pcm_writei(const void *buffer, snd_pcm_uframes_
   return rc;
 }
 
-void ALSA_object_t::close_alsa_device(bool do_drain, bool use_log) {
+void DSP::ALSA_object_t::close_alsa_device(bool do_drain, bool use_log) {
   if (alsa_handle != NULL) {
     if (do_drain == true) {
       snd_pcm_drain(alsa_handle);
diff --git a/src/cpp/DSP_IO.cpp b/src/cpp/DSP_IO.cpp
index dea7ebd..af3da1b 100644
--- a/src/cpp/DSP_IO.cpp
+++ b/src/cpp/DSP_IO.cpp
@@ -14,6 +14,7 @@
 #include <limits.h>
 #include <typeinfo>
 #include <cstdint> // int16_t, itp.
+#include <functional> 
 
 #ifdef WINMMAPI
 //  #include <stdarg.h>
@@ -4127,7 +4128,9 @@ void DSP::u::AudioInput::Init(DSP::Clock_ptr ParentClock,
   audio_inbuffer_size = DSP::f::GetAudioBufferSize(SamplingFreq, DSP::e::AudioBufferType::input);
 
   snd_object.select_input_device_by_number(WaveInDevNo); // use default device
-  snd_object.register_input_callback_object(this, SOUND_object_callback); // use default device
+//  DSP::input_callback_function  cp = std::bind(&DSP::u::AudioInput::SOUND_object_callback, this, std::placeholders::_1, std::placeholders::_2);
+  DSP::input_callback_function  cp = &DSP::u::AudioInput::SOUND_object_callback;
+  snd_object.register_input_callback_object(this, cp); // use default device
   if (snd_object.open_PCM_device_4_input(NoOfOutputs, BitPrec, SamplingFreq, audio_inbuffer_size) > 0) {
     InBufferLen=NoOfOutputs*audio_inbuffer_size;
     for (ind = 0; ind < DSP::NoOfAudioInputBuffers; ind++)
@@ -5841,11 +5844,13 @@ DSP::u::AudioOutput *DSP::SOUND_object_t::get_output_callback_object() {
   return AudioOutput_object;
 }
 
-bool DSP::SOUND_object_t::output_callback_call() {
-  return (AudioOutput_object->*AudioOutput_callback)();
+bool DSP::SOUND_object_t::output_callback_call(const DSP::e::SampleType &OutSampleType, const std::vector<char> &wave_out_raw_buffer) {
+//  return (AudioOutput_object->*AudioOutput_callback)();
+  return (AudioOutput_object->*AudioOutput_callback)(OutSampleType, wave_out_raw_buffer);
 }
 
-bool DSP::SOUND_object_t::register_input_callback_object(DSP::u::AudioInput *callback_object, bool(DSP::u::AudioInput::*cp)(const DSP::e::SampleType &, const std::vector<char> &)) {
+//bool DSP::SOUND_object_t::register_input_callback_object(DSP::u::AudioInput *callback_object, bool(DSP::u::AudioInput::*cp)(const DSP::e::SampleType &, const std::vector<char> &)) {
+bool DSP::SOUND_object_t::register_input_callback_object(DSP::u::AudioInput *callback_object, input_callback_function &cp) {
   if (is_input_callback_supported() == true) {
     AudioInput_object = callback_object;
     AudioInput_callback = cp;
@@ -5854,6 +5859,16 @@ bool DSP::SOUND_object_t::register_input_callback_object(DSP::u::AudioInput *cal
   return false;
 }
 
+bool DSP::SOUND_object_t::register_output_callback_object(DSP::u::AudioOutput *callback_object, output_callback_function &cp) {
+  if (is_output_callback_supported() == true) {
+    AudioOutput_object = callback_object;
+    AudioOutput_callback = cp;
+    return true;
+  }
+  return false;
+}
+
+
 long int DSP::SOUND_object_t::get_current_CallbackInstance() {
   return Current_CallbackInstance;
 }
diff --git a/src/cpp/WMM_support.cpp b/src/cpp/WMM_support.cpp
index 75d9842..dbb8067 100644
--- a/src/cpp/WMM_support.cpp
+++ b/src/cpp/WMM_support.cpp
@@ -159,7 +159,7 @@ bool DSP::WMM_object_t::is_device_recording(void) {
   return IsRecordingNow;
 }
 
-long DSP::WMM_object_t::open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_inbuffer_size) {
+long DSP::WMM_object_t::open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_inbuffer_size = -1) {
   if (is_device_input_open)
   {
     DSP::log << "DSP::WMM_object_t::open_PCM_device_4_input" << DSP::e::LogMode::second << "Device has been already opened: closing device before reopening" << endl;
@@ -252,7 +252,7 @@ long DSP::WMM_object_t::open_PCM_device_4_input(const int &no_of_channels, int n
   return -1;
 }
 
-long DSP::WMM_object_t::open_PCM_device_4_output(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size) {
+long DSP::WMM_object_t::open_PCM_device_4_output(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size = -1) {
   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;
diff --git a/src/include/ALSA_support.h b/src/include/ALSA_support.h
index cf7084b..a6a62a4 100644
--- a/src/include/ALSA_support.h
+++ b/src/include/ALSA_support.h
@@ -13,7 +13,7 @@
 /* All of the ALSA library API is defined in this header */
 #include <alsa/asoundlib.h>
 
-#include <DSP_lib.h> // for logging and types
+#include <DSP_types.h> // for types
 
 namespace DSP {
     
@@ -22,20 +22,48 @@ namespace DSP {
         snd_pcm_t *alsa_handle;
         snd_pcm_hw_params_t *hw_params;
 
-    public:
-
-        //! log basic ALSA information
-        void log_driver_data();
-
         //! open default PCM device and return 1 on success or negative error code
         /*! stream_type = SND_PCM_STREAM_PLAYBACK or SND_PCM_STREAM_CAPTURE
         */
         int open_alsa_device(snd_pcm_stream_t stream_type, int no_of_channels, unsigned int &sampling_rate);
         void close_alsa_device(bool do_drain = false, bool use_log = false);
 
-        void get_params(snd_pcm_uframes_t &frames, unsigned int &period_time);
+        void get_period_size(snd_pcm_uframes_t &frames, unsigned int &period_time);
         snd_pcm_sframes_t pcm_writei(const void *buffer, snd_pcm_uframes_t &frames);
 
+    public:
+
+        //! log basic ALSA information
+        void log_driver_data();
+
+        unsigned int select_input_device_by_number(const unsigned int &device_number=UINT_MAX);
+        unsigned int select_output_device_by_number(const unsigned int &device_number=UINT_MAX);
+
+        long open_PCM_device_4_output(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size = -1);
+        long open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size = -1);
+        bool close_PCM_device_input(void);
+        bool close_PCM_device_output(void);
+
+        //! returns true is the playback is on
+        bool is_device_playing(void);
+        //! initializes playback stopping
+        bool stop_playback(void);
+        //! returns true is the sound capture is on
+        bool is_device_recording(void);
+        //! returns true is the sound capture is on
+        bool stop_recording(void);
+
+        //! \note values stored in float_buffer might be altered
+        long append_playback_buffer(DSP::Float_vector &float_buffer);
+        //! Starts sound capture
+        bool start_recording(void);
+
+        //! Returns false if callbacks are not supported of recording
+        bool is_input_callback_supported(void);
+
+        //! Returns false if callbacks are not supported of playback
+        bool is_output_callback_supported(void);
+
         //! object constructor
         ALSA_object_t();
         ~ALSA_object_t();
diff --git a/src/include/DSP_IO.h b/src/include/DSP_IO.h
index faf93e2..b084891 100644
--- a/src/include/DSP_IO.h
+++ b/src/include/DSP_IO.h
@@ -27,7 +27,7 @@
 #else
   #ifdef LINUX
     //! \TODO adapt for linux
-    #include "ALSA_support.h"
+    #include <ALSA_support.h>
 
   #else
     #error NO WIN32
@@ -719,6 +719,11 @@ class DSP::u::AudioInput : public DSP::Source
     #ifdef WINMMAPI
       // HWAVEIN hWaveIn;
       DSP::WMM_object_t snd_object;
+    #else
+      #ifdef ALSA_support_H
+        DSP::ALSA_object_t snd_object;
+      #else
+      #endif
     #endif
 
     //! Called by SOUND_object_t when new data buffer is ready
@@ -839,6 +844,11 @@ class DSP::u::AudioOutput : public DSP::Block
     #ifdef WINMMAPI
       //HWAVEOUT hWaveOut;
       DSP::WMM_object_t snd_object;
+    #else
+      #ifdef ALSA_support_H
+        DSP::ALSA_object_t snd_object;
+      #else
+      #endif
     #endif
 
     // //! Index of the buffer which must be used next time
diff --git a/src/include/DSP_lib.h b/src/include/DSP_lib.h
index 5b12ff0..0abe1b4 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 6 // !!! without zeroes before, else this will be treated as octal number
+#define DSP_VER_BUILD 7 // !!! 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 76880e7..750f7ea 100644
--- a/src/include/DSP_types.h
+++ b/src/include/DSP_types.h
@@ -13,6 +13,7 @@
 #include <limits.h>
 #include <vector>
 #include <string>
+#include <functional>
 
 using namespace std;
 //---------------------------------------------------------------------------
@@ -534,15 +535,23 @@ namespace DSP {
     class AudioOutput;
   }
 
+//  typedef std::function<bool(const DSP::e::SampleType &, const std::vector<char> &)> input_callback_function;
+  // https://isocpp.org/wiki/faq/pointers-to-members#typedef-for-ptr-to-memfn
+  //! defining a type for pointer to member funtion of DSP::u::AudioInput
+  typedef bool(DSP::u::AudioInput::*input_callback_function)(const DSP::e::SampleType &, const std::vector<char> &);
+  //! defining a type for pointer to member funtion of DSP::u::AudioOutput
+  typedef bool(DSP::u::AudioOutput::*output_callback_function)(const DSP::e::SampleType &, const std::vector<char> &);
+
     //! Base class for classes implementing sound card support for DSP::u::AudioInput and DSP::u::AudioOutput 
     /*! \TODO  convert WMM support in DSP::u::AudioInput and DSP::u::AudioOutput into support through WMM_object_t
      */
   class SOUND_object_t {
     private:
       DSP::u::AudioInput * AudioInput_object;
-      bool (DSP::u::AudioInput::*AudioInput_callback)(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer);
+      //bool (DSP::u::AudioInput::*AudioInput_callback)(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer);
+      input_callback_function AudioInput_callback;
       DSP::u::AudioOutput * AudioOutput_object;
-      bool (DSP::u::AudioOutput::*AudioOutput_callback)(void);
+      output_callback_function AudioOutput_callback;
 
       //static unsigned long Next_CallbackInstance;
       unsigned long Current_CallbackInstance;
@@ -555,8 +564,8 @@ namespace DSP {
       virtual unsigned int select_input_device_by_number(const unsigned int &device_number=UINT_MAX) = 0;
       virtual unsigned int select_output_device_by_number(const unsigned int &device_number=UINT_MAX) = 0;
 
-      virtual long open_PCM_device_4_output(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size) = 0;
-      virtual long open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size) = 0;
+      virtual long open_PCM_device_4_output(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size = -1) = 0;
+      virtual long open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size = -1) = 0;
       virtual bool close_PCM_device_input(void) = 0;
       virtual bool close_PCM_device_output(void) = 0;
 
@@ -584,8 +593,10 @@ namespace DSP {
       virtual bool is_input_callback_supported(void) = 0;
       /*! Returns false if callbacks are not supported
        * \TODO define when it will be called and what for?
+       * 
+       * bool register_input_callback_object(DSP::u::AudioInput *callback_object, bool(DSP::u::AudioInput::*cp)(const DSP::e::SampleType &, const std::vector<char> &));
        */
-      bool register_input_callback_object(DSP::u::AudioInput *callback_object, bool(DSP::u::AudioInput::*cp)(const DSP::e::SampleType &, const std::vector<char> &));
+      bool register_input_callback_object(DSP::u::AudioInput *callback_object, input_callback_function &cp);
       DSP::u::AudioInput *get_input_callback_object();
       bool input_callback_call(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer);
 
@@ -595,9 +606,9 @@ namespace DSP {
       /*! Returns false if callbacks are not supported
        * \TODO define when it will be called and what for?
        */
-      bool register_output_callback_object(DSP::u::AudioOutput *callback_object, bool(DSP::u::AudioOutput::*cp)());
+      bool register_output_callback_object(DSP::u::AudioOutput *callback_object, output_callback_function &cp);
       DSP::u::AudioOutput *get_output_callback_object();
-      bool output_callback_call();
+      bool output_callback_call(const DSP::e::SampleType &OutSampleType, const std::vector<char> &wave_out_raw_buffer);
 
       SOUND_object_t();
       virtual ~SOUND_object_t();
diff --git a/src/include/WMM_support.h b/src/include/WMM_support.h
index c16f8c0..1f61d12 100644
--- a/src/include/WMM_support.h
+++ b/src/include/WMM_support.h
@@ -79,9 +79,9 @@ namespace DSP {
         unsigned int select_output_device_by_number(const unsigned int &device_number=UINT_MAX);
 
         //! opens default PCM device for playback and returns selected sampling rate on success or negative error code
-        long open_PCM_device_4_output(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size);
+        long open_PCM_device_4_output(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_outbuffer_size = -1);
         //! 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);
+        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);
-- 
GitLab