diff --git a/CHANGELOG b/CHANGELOG
index 15826cb4087912dae22a5afe1fe60145a409dbec..d86113381380377d43420e28f64ed6790d79c674 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,11 @@ TODO::
 LAST DONE:
 
 CHANGES:
+- 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
+  - Added in DSP::AudioInput::OutputExecute and DSP::AudioInput::Init support for SOUND_object_t without callbacks for audio input
+
 - ver. 0.20.007 - <b>2021.05.16</b> Changed: 
   - initial convertion of ALSA_object_t to class based on SOUND_object_t
 
diff --git a/src/cpp/ALSA_support.cpp b/src/cpp/ALSA_support.cpp
index 7013fd0e32ba5d1c6f5fab51d1a607530b1c7272..a2f6270af18c56efb4ea9adc3906b7ba7df92e05 100644
--- a/src/cpp/ALSA_support.cpp
+++ b/src/cpp/ALSA_support.cpp
@@ -309,6 +309,9 @@ bool DSP::ALSA_object_t::start_recording(void) {
   assert(!"DSP::ALSA_object_t::stop_recording not implemented yet");
 }
 
+bool DSP::ALSA_object_t::get_wave_in_raw_buffer(DSP::e::SampleType &InSampleType, std::vector<char> &wave_in_raw_buffer) {
+  assert(!"DSP::ALSA_object_t::get_wave_in_raw_buffer 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);
diff --git a/src/cpp/DSP_IO.cpp b/src/cpp/DSP_IO.cpp
index af3da1be4a46319844b793eedebf56f294c6eb62..7187567c818266bfe6116f1d9ba944027c1b1661 100644
--- a/src/cpp/DSP_IO.cpp
+++ b/src/cpp/DSP_IO.cpp
@@ -4129,8 +4129,19 @@ void DSP::u::AudioInput::Init(DSP::Clock_ptr ParentClock,
 
   snd_object.select_input_device_by_number(WaveInDevNo); // 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.is_input_callback_supported() == true) {
+    // use callbacks if available
+    DSP::input_callback_function  cp = &DSP::u::AudioInput::SOUND_object_callback;
+    snd_object.register_input_callback_object(this, cp); // use default device
+#ifdef __DEBUG__
+    DSP::log << "DSP::u::AudioInput::Init" << DSP::e::LogMode::second << "using callback mode" << endl;
+#endif // __DEBUG__
+  }
+#ifdef __DEBUG__
+  else {
+    DSP::log << "DSP::u::AudioInput::Init" << DSP::e::LogMode::second << "using non-callback mode" << endl;
+  }
+#endif // __DEBUG__
   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++)
@@ -4439,6 +4450,17 @@ bool DSP::u::AudioInput::OutputExecute(OUTPUT_EXECUTE_ARGS)
     return true;
   }
 
+  // If there are free buffers check whether the sound card has any audio data already available
+  if (DSP_THIS->snd_object.get_input_callback_object() == NULL) {
+    // callbacks are not used thus audio data has to be obtained directly from snd_object
+    if (DSP_THIS->GetNoOfFreeBuffers() > 0) {
+      DSP::e::SampleType InSampleType;
+      std::vector<char> wave_in_raw_buffer;
+      if (DSP_THIS->snd_object.get_wave_in_raw_buffer(InSampleType, wave_in_raw_buffer)) {
+        DSP_THIS->SOUND_object_callback(InSampleType, wave_in_raw_buffer);
+      }
+    }
+  }
 
   // if no input buffer is ready return false (system will later return here)
   if (DSP_THIS->snd_object.is_device_recording() == true)
@@ -5816,6 +5838,8 @@ DSP::u::AudioInput *DSP::SOUND_object_t::get_input_callback_object() {
 }
 
 bool DSP::SOUND_object_t::input_callback_call(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer) {
+  if (AudioInput_object == NULL)
+    return false;
   return (AudioInput_object->*AudioInput_callback)(InSampleType, wave_in_raw_buffer);
 }
 
@@ -5846,6 +5870,8 @@ DSP::u::AudioOutput *DSP::SOUND_object_t::get_output_callback_object() {
 
 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)();
+  if (AudioOutput_object == NULL)
+    return false;
   return (AudioOutput_object->*AudioOutput_callback)(OutSampleType, wave_out_raw_buffer);
 }
 
diff --git a/src/cpp/WMM_support.cpp b/src/cpp/WMM_support.cpp
index 75d984294fb6492627864868da865f15538d5b18..12c65361a08619118beba78c6cd3456ac9dfb26b 100644
--- a/src/cpp/WMM_support.cpp
+++ b/src/cpp/WMM_support.cpp
@@ -166,7 +166,6 @@ long DSP::WMM_object_t::open_PCM_device_4_input(const int &no_of_channels, int n
     close_PCM_device_input();
   }
 
-  DWORD_PTR Callback;
   switch (no_of_bits)
   {
     case 8:
@@ -180,7 +179,20 @@ long DSP::WMM_object_t::open_PCM_device_4_input(const int &no_of_channels, int n
       no_of_bits=16;
       break;
   }
-  Callback = (DWORD_PTR)(&DSP::WMM_object_t::waveInProc);
+
+  DWORD_PTR Callback;
+  DWORD_PTR dwInstance;
+  uint32_t fdwOpen;
+  if (get_input_callback_object() != NULL) {
+    Callback = (DWORD_PTR)(&DSP::WMM_object_t::waveInProc);
+    dwInstance = get_current_CallbackInstance();
+    fdwOpen = CALLBACK_FUNCTION;
+  }
+  else {
+    Callback = (DWORD_PTR)(NULL);
+    dwInstance = (DWORD_PTR)(0);
+    fdwOpen = 0;
+  }
 
   //Wypeniamy struktur wfx
   wfx.wf.wFormatTag=WAVE_FORMAT_PCM;
@@ -190,21 +202,22 @@ long DSP::WMM_object_t::open_PCM_device_4_input(const int &no_of_channels, int n
   wfx.wf.nAvgBytesPerSec=wfx.wf.nSamplesPerSec*(wfx.wBitsPerSample/8);
   wfx.wf.nBlockAlign=(uint16_t)(wfx.wf.nChannels*(wfx.wBitsPerSample/8));
 
+  fdwOpen |= WAVE_FORMAT_DIRECT;
   if (waveInGetNumDevs() <= WaveInDevNo)
     result=waveInOpen(&hWaveIn,
       WAVE_MAPPER, //&DeviceID,
       (WAVEFORMATEX *)(&wfx),
       Callback,
-      get_current_CallbackInstance(), //CallbackInstance,
-      CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL
+      dwInstance, //CallbackInstance,
+      fdwOpen //| WAVE_MAPPED //CALLBACK_NULL
       );
   else
     result=waveInOpen(&hWaveIn,
       WaveInDevNo, //&DeviceID,
       (WAVEFORMATEX *)(&wfx),
       Callback,
-      get_current_CallbackInstance(), //CallbackInstance,
-      CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL
+      dwInstance, //CallbackInstance,
+      fdwOpen //| WAVE_MAPPED //CALLBACK_NULL
       );
 
   if (DSP::f::AudioCheckError(result) == false)
@@ -427,10 +440,10 @@ bool DSP::WMM_object_t::start_recording(void) {
     DSP::log << "DSP::u::AudioInput::Execute" << DSP::e::LogMode::second << "Starting recording using two wave buffers" << endl;
   #endif
 
-  if (get_input_callback_object() == NULL) {
-    DSP::log << DSP::e::LogMode::Error << "DSP::WMM_object_t::start_recording" << DSP::e::LogMode::second << "No AudioInput object registered for callbacks" << endl;
-    return false;
-  }
+  // if (get_input_callback_object() == NULL) {
+  //   DSP::log << DSP::e::LogMode::Error << "DSP::WMM_object_t::start_recording" << DSP::e::LogMode::second << "No AudioInput object registered for callbacks" << endl;
+  //   return false;
+  // }
 
   result=waveInAddBuffer(hWaveIn, &(waveHeaderIn[0]), sizeof(WAVEHDR));
   DSP::f::AudioCheckError(result);
@@ -456,6 +469,42 @@ bool DSP::WMM_object_t::is_output_callback_supported(void) {
 }
 
 
+bool DSP::WMM_object_t::get_wave_in_raw_buffer(DSP::e::SampleType &InSampleType_in, std::vector<char> &wave_in_raw_buffer) {
+  if (StopRecording)
+    return false;
+  else
+  {
+    if (waveHeaderIn[NextBufferInInd].dwFlags & WHDR_DONE)
+    {
+      result=waveInUnprepareHeader(hWaveIn, &(waveHeaderIn[NextBufferInInd]), sizeof(WAVEHDR));
+      DSP::f::AudioCheckError(result);
+    
+      InSampleType_in = this->InSampleType;
+      std::swap(wave_in_raw_buffer, WaveInBuffers[NextBufferInInd]);
+      WaveInBuffers[NextBufferInInd].resize(WaveInBufferLen, 0);
+      waveHeaderIn[NextBufferInInd].lpData=(char *)(WaveInBuffers[NextBufferInInd].data());
+
+      //add put back into recording queue
+      result=waveInPrepareHeader(hWaveIn, &(waveHeaderIn[NextBufferInInd]), sizeof(WAVEHDR));
+      DSP::f::AudioCheckError(result);
+      result=waveInAddBuffer(hWaveIn, &(waveHeaderIn[NextBufferInInd]), sizeof(WAVEHDR));
+      DSP::f::AudioCheckError(result);
+
+      NextBufferInInd++; NextBufferInInd %= 2; //just two buffers
+    }
+    else
+    {
+#ifdef __DEBUG__
+#ifdef AUDIO_DEBUG_MESSAGES_ON
+        DSP::log << "DSP::WMM_object_t::get_wave_in_raw_buffer" << DSP::e::LogMode::second << "Wrong audio frame ready or other unexpected error" << endl;
+#endif
+#endif
+      return false;
+    }
+  }
+  return true;
+}
+
 long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) {
   uint8_t *temp8;
   short *temp16;
diff --git a/src/include/ALSA_support.h b/src/include/ALSA_support.h
index a6a62a422385a8e4a898c36946ec708cca1c05e5..76183e4bbd33c100d5d7aff20282597ce57000e8 100644
--- a/src/include/ALSA_support.h
+++ b/src/include/ALSA_support.h
@@ -57,6 +57,7 @@ namespace DSP {
         long append_playback_buffer(DSP::Float_vector &float_buffer);
         //! Starts sound capture
         bool start_recording(void);
+        bool get_wave_in_raw_buffer(DSP::e::SampleType &InSampleType, std::vector<char> &wave_in_raw_buffer);
 
         //! Returns false if callbacks are not supported of recording
         bool is_input_callback_supported(void);
diff --git a/src/include/DSP_lib.h b/src/include/DSP_lib.h
index 0abe1b44709cf32cbc7723371e72d6858e378412..bca9649159175e1d1ad39fa344562296aa81665b 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 7 // !!! without zeroes before, else this will be treated as octal number
+#define DSP_VER_BUILD 8 // !!! 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 750f7ea8c508cbe15393ba1011bac6a428357d8a..d9b0948f4c86b439f0e03501f1f5c8947f27e08f 100644
--- a/src/include/DSP_types.h
+++ b/src/include/DSP_types.h
@@ -558,6 +558,10 @@ namespace DSP {
       static std::vector<DSP::SOUND_object_t *> CallbackSoundObjects;
       static unsigned long get_free_CallbackInstance(void);
 
+    protected:
+      long int get_current_CallbackInstance();
+      static const DSP::SOUND_object_t * get_CallbackSoundObject(const long int &instance_number);
+
     public:
       virtual void log_driver_data() = 0;
 
@@ -584,32 +588,57 @@ namespace DSP {
       virtual bool start_recording(void) = 0;
 
 
-      long int get_current_CallbackInstance();
-      static const DSP::SOUND_object_t * get_CallbackSoundObject(const long int &instance_number);
-
       // https://stackoverflow.com/questions/8865766/get-a-pointer-to-objects-member-function
-      /*! Returns false if callbacks are not supported of recording
+      /*! Returns false if callbacks are not supported for recording
        */
       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?
+      /*! Registers callback for input buffer data ready. Returns false if callbacks are not supported
+       * If this method fails or is not used the SOUND_ocject falls back into non-callback mode.
+       * 
+       * Registers as a callback function that is a member function of the AudioInput class along with the object of the AudioInput class for which it should be called.
+       * - bool input_callback_function(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer);
        * 
-       * bool register_input_callback_object(DSP::u::AudioInput *callback_object, bool(DSP::u::AudioInput::*cp)(const DSP::e::SampleType &, const std::vector<char> &));
+       * The callback function will be called by the SOUND_object when sound card's input buffer is ready.
+       * The callback function has to return true when it processed the input buffer or false when it cannot to process it.
+       * On false the SOUND_object most probably will discard the buffer. Nevertheless it can try to call the callback again for the same data.
        */
       bool register_input_callback_object(DSP::u::AudioInput *callback_object, input_callback_function &cp);
+      //! Returns pointer to DSP::u::AudioInput for which callback is registered.
+      /*! \note If this function  returns NULL, callbacks are not used even if they are supported.
+       */
       DSP::u::AudioInput *get_input_callback_object();
+  protected:
+      //! \note this method should be used only by descending classes
       bool input_callback_call(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer);
+  public:
+      //! If enough audio data are already available then fills InSampleType and wave_in_raw_buffer
+      /*! return true on success or false if the data are not available 
+       * \note this method should be used only if callbacks are not active
+       */
+      virtual bool get_wave_in_raw_buffer(DSP::e::SampleType &InSampleType, std::vector<char> &wave_in_raw_buffer) = 0;
 
-      /*! Returns false if callbacks are not supported of playback
+      /*! Returns false if callbacks are not supported for playback
        */
       virtual bool is_output_callback_supported(void) = 0;
       /*! Returns false if callbacks are not supported
-       * \TODO define when it will be called and what for?
+       * 
+       * Registers as a callback function that is a member function of the AudioOutput class along with the object of the AudioOutput class for which it should be called.
+       * - bool output_callback_function(const DSP::e::SampleType &OutSampleType, const std::vector<char> &wave_out_raw_buffer);
+       * 
+       * The callback function will be called by the SOUND_object when new sound card's output buffer can processed.
+       * The callback function has to return true when it filled the buffer with samples or false when there is not enought data.
+       * On false the SOUND_object most probably will discard the buffer. Nevertheless it can try to call the callback again.
+       * \TODO revise the concept when the there will be a SOUND_object_t derivative that uses this approach.
+       * \note Needs addaptation of DSP::u::AudioOutput class.
        */
       bool register_output_callback_object(DSP::u::AudioOutput *callback_object, output_callback_function &cp);
+      /*! \note If this function  returns NULL, callbacks are not used are not used even if they are supported.
+       */
       DSP::u::AudioOutput *get_output_callback_object();
+  protected:
       bool output_callback_call(const DSP::e::SampleType &OutSampleType, const std::vector<char> &wave_out_raw_buffer);
-
+  
+  public:
       SOUND_object_t();
       virtual ~SOUND_object_t();
   };
diff --git a/src/include/WMM_support.h b/src/include/WMM_support.h
index 1f61d1200674ba9c2b610d2778121cada7b0a2eb..63af56851b7b18e0dc00a4ef859afcee8db217c8 100644
--- a/src/include/WMM_support.h
+++ b/src/include/WMM_support.h
@@ -101,6 +101,7 @@ namespace DSP {
         //! \note values stored in float_buffer might be altered
         long append_playback_buffer(DSP::Float_vector &float_buffer);
         bool start_recording(void);
+        bool get_wave_in_raw_buffer(DSP::e::SampleType &InSampleType, std::vector<char> &wave_in_raw_buffer);
 
         //! object constructor \TODO check use of virtual in constructor and destructor
         WMM_object_t();