diff --git a/CHANGELOG b/CHANGELOG
index f00b6a5a085a4d6033936353c41775eae42cf6a0..1f233a41fc90a6abe52053772c862a4f2a14694d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,7 +6,12 @@ TODO::
 LAST DONE:
 
 CHANGES:
-  - 2021.04.21 - Added ALSA tests in main.cpp and Launch configuration for Linux
+
+- ver. 0.20.005 - <b>2021.04.21</b> Changed: 
+  - Added ALSA tests in main.cpp and Launch configuration for Linux
+  - Added to DSP_types.h a SOUND_object_t abstract class, a wrapper for different sound cards' API
+  - Added WMM_object_t abstract class, a wrapper for Windows MultiMedia API
+  - DSP::u::AudioOutput now uses SOUND_object_t (currently just WMM_object_t) for soundcard API
 
 - ver. 0.20.004 - <b>2021.04.06</b> Changed: 
   - Fixed makefiles for Linux - install and examples compilation works
diff --git a/src/Main.cpp b/src/Main.cpp
index c6b39a83f6bc2c60d9101099257c031a30481e3a..d18918ac15e631b58c7d3a805e5ec0936d86714b 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -2909,7 +2909,7 @@ polling:
   int test_ALSA() {
     ALSA_object_t ALSA_object;
 
-    ALSA_object.log_alsa_data();
+    ALSA_object.log_driver_data();
 
     unsigned int Fs = 44100;
     int rs = ALSA_object.open_alsa_device(SND_PCM_STREAM_PLAYBACK, 2, Fs);
diff --git a/src/Makefile.win b/src/Makefile.win
index 7333ccfdf5b66f39e1c834cea3b58ae972a37efb..295ad8175c528e1e3693b860bf2458f9215f1ec5 100644
--- a/src/Makefile.win
+++ b/src/Makefile.win
@@ -32,7 +32,7 @@ LINKER_FLAGS_release = $(comflag)  -s -static-libgcc -static-libstdc++ -static
 
 SOURCES_NAMES = 
 SOURCES_NAMES += DSP_AudioMixer.cpp DSP_Fourier.cpp DSP_misc.cpp DSP_clocks.cpp DSP_modules.cpp DSP_modules2.cpp 
-SOURCES_NAMES += DSP_DOT.cpp DSP_modules_misc.cpp DSP_IO.cpp DSP_logstream.cpp
+SOURCES_NAMES += DSP_DOT.cpp DSP_modules_misc.cpp DSP_IO.cpp DSP_logstream.cpp WMM_support.cpp
 SOURCES = $(addprefix $(SRC_CPP_SUBDIR)/,$(SOURCES_NAMES))
 
 SOURCES_DBG =
diff --git a/src/cpp/ALSA_support.cpp b/src/cpp/ALSA_support.cpp
index 92be453cb781b76855493562edda4bcdb793b689..0632be7a8b7c8524e0915054e3ef21794d75cf74 100644
--- a/src/cpp/ALSA_support.cpp
+++ b/src/cpp/ALSA_support.cpp
@@ -24,7 +24,7 @@ ALSA_object_t::~ALSA_object_t()
 }
 
 
-void ALSA_object_t::log_alsa_data() {
+void ALSA_object_t::log_driver_data() {
   int val;
 
   DSP::log << "ALSA library version: " << SND_LIB_VERSION_STR << endl;
diff --git a/src/cpp/DSP_IO.cpp b/src/cpp/DSP_IO.cpp
index 3a40d1a2f78e2db9deb0a9a693198419d08ce914..a356b67c064d05481daac179906fbf850b8abcf2 100644
--- a/src/cpp/DSP_IO.cpp
+++ b/src/cpp/DSP_IO.cpp
@@ -3607,56 +3607,6 @@ uint32_t DSP::f::GetAudioBufferSize(const unsigned long &SamplingFreq, const DSP
 }
 
 #ifdef WINMMAPI
-  void CALLBACK DSP::u::AudioOutput::waveOutProc(HWAVEOUT hwo, UINT uMsg,
-    uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2)
-  {
-    UNUSED_ARGUMENT(hwo);
-    UNUSED_ARGUMENT(uMsg);
-    UNUSED_ARGUMENT(dwInstance);
-    UNUSED_ARGUMENT(dwParam1);
-    UNUSED_ARGUMENT(dwParam2);
-  #ifdef __DEBUG__
-  #ifdef AUDIO_DEBUG_MESSAGES_ON
-  //  MMRESULT result;
-    DSP::u::AudioOutput *Current;
-    bool AllDone;
-    int ind;
-    string tekst;
-
-    Current = AudioObjects[dwInstance];
-
-    switch (uMsg)
-    {
-      case WOM_OPEN:
-        DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second
-          << "WOM_OPEN(" << (int)dwInstance << ")" << endl;
-        break;
-      case WOM_CLOSE:
-        DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second
-          << "WOM_CLOSE(" << (int)dwInstance << ")" << endl;
-        break;
-      case WOM_DONE:
-        DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second
-          << "WOM_DONE(" << (int)dwInstance << ")" << endl;
-
-        if (Current->StopPlaying)
-        {
-          DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second << "StopPlaying is set" << endl;
-          return;
-        }
-        else
-        {
-          AllDone=true;
-          for (ind=0; ind < DSP_NoOfAudioOutputBuffers; ind++)
-            AllDone &= (Current->waveHeaderOut[ind].dwFlags & WHDR_DONE);
-          if (AllDone)
-            DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second << "All buffers had been used - nothing to play" << endl;
-        }
-        break;
-    }
-  #endif
-  #endif
-  }
 
   //! \bug allow user to select number of internal buffers
   void CALLBACK DSP::u::AudioInput::waveInProc_short(HWAVEIN hwi, UINT uMsg,
@@ -3949,14 +3899,14 @@ void DSP::u::AudioOutput::Init(unsigned long SamplingFreq,
                            unsigned int WaveOutDevNo)
 {
   #ifdef WINMMAPI
-    MMRESULT result;
-    DWORD_PTR Callback;
-
-    //Rezerwacja pamięci dla formatu WAVE
-    //  WAVEFORMATEX wfx; //to wymaga korekty
-    PCMWAVEFORMAT wfx;
-
-    unsigned long ind;
+    // MMRESULT result;
+    // DWORD_PTR Callback;
+    //
+    // //Rezerwacja pamięci dla formatu WAVE
+    // //  WAVEFORMATEX wfx; //to wymaga korekty
+    // PCMWAVEFORMAT wfx;
+    //
+    // unsigned long ind;
   #else
     UNUSED_ARGUMENT(WaveOutDevNo);
   #endif
@@ -3989,10 +3939,10 @@ void DSP::u::AudioOutput::Init(unsigned long SamplingFreq,
     ClockGroups.AddInput2Group("input", Input(temp));
   }
 
-  #ifdef WINMMAPI
-    //! \bug in Debug mode this callback does nothing so it would be better just not use it
-    Callback = (DWORD_PTR)(&DSP::u::AudioOutput::waveOutProc);
-  #endif
+//  #ifdef WINMMAPI
+//    //! \bug in Debug mode this callback does nothing so it would be better just not use it
+//    Callback = (DWORD_PTR)(&DSP::u::AudioOutput::waveOutProc);
+//  #endif
   Current_CallbackInstance=Next_CallbackInstance;
   Next_CallbackInstance++;
   AudioObjects.resize(Current_CallbackInstance+1);
@@ -4000,96 +3950,28 @@ void DSP::u::AudioOutput::Init(unsigned long SamplingFreq,
 
   StopPlaying = false;
 
-  switch (BitPrec)
-  {
-    case 8:
-      OutSampleType=DSP::e::SampleType::ST_uchar;
-      break;
-    case 16:
-      OutSampleType=DSP::e::SampleType::ST_short;
-      break;
-    default:
-      OutSampleType=DSP::e::SampleType::ST_short;
-      BitPrec=16;
-      break;
-  }
-
   audio_outbuffer_size = DSP::f::GetAudioBufferSize(SamplingFreq, DSP::e::AudioBufferType::output);
 
-  #ifdef WINMMAPI
-    //Wypeniamy struktur wfx
-    wfx.wf.wFormatTag=WAVE_FORMAT_PCM;
-    wfx.wf.nChannels=(uint16_t)NoOfInputs;
-    wfx.wf.nSamplesPerSec=(UINT)SamplingFreq;
-    wfx.wBitsPerSample=BitPrec;
-    wfx.wf.nAvgBytesPerSec=wfx.wf.nSamplesPerSec*(wfx.wBitsPerSample/8);
-    wfx.wf.nBlockAlign=(uint16_t)(wfx.wf.nChannels*(wfx.wBitsPerSample/8));
+  snd_object.select_device_by_number(WaveOutDevNo); // use default device
+  snd_object.open_PCM_device_4_output(NoOfInputs, BitPrec, SamplingFreq, audio_outbuffer_size);
 
-    if (WaveOutDevNo >= (UINT)waveOutGetNumDevs())
-      result=waveOutOpen(&hWaveOut,
-        WAVE_MAPPER, //&DeviceID,
-        (WAVEFORMATEX *)(&wfx),
-        Callback,
-        Current_CallbackInstance, //CallbackInstance,
-        CALLBACK_FUNCTION | WAVE_ALLOWSYNC | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL
-        );
-    else
-      result=waveOutOpen(&hWaveOut,
-        WaveOutDevNo, //&DeviceID,
-        (WAVEFORMATEX *)(&wfx),
-        Callback,
-        Current_CallbackInstance, //CallbackInstance,
-        CALLBACK_FUNCTION | WAVE_ALLOWSYNC | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL
-        );
-    if (DSP::f::AudioCheckError(result) == false)
-    { // everything  is ok
-      waveHeaderOut.resize(DSP::NoOfAudioOutputBuffers);
-      WaveOutBufferLen=wfx.wf.nBlockAlign*audio_outbuffer_size;
-      WaveOutBuffers.resize(DSP::NoOfAudioOutputBuffers);
-      for (ind=0; ind< DSP::NoOfAudioOutputBuffers; ind++)
-      {
-        WaveOutBuffers[ind].clear();
-        WaveOutBuffers[ind].resize(WaveOutBufferLen, 0);
-      }
+  OutBufferLen=NoOfInputs*audio_outbuffer_size;
+  OutBuffer.clear(); OutBuffer.resize(OutBufferLen, 0.0);
+  BufferIndex=0;
 
-      OutBufferLen=NoOfInputs*audio_outbuffer_size;
-      OutBuffer.clear(); OutBuffer.resize(OutBufferLen, 0.0);
-      BufferIndex=0;
+  // #ifdef WINMMAPI
 
-      for (ind=0; ind< DSP::NoOfAudioOutputBuffers; ind++)
-      {
-        waveHeaderOut[ind].lpData=(char *)(WaveOutBuffers[ind].data());
-        waveHeaderOut[ind].dwBufferLength=OutBufferLen*(BitPrec/8); //sizeof(short);
-        waveHeaderOut[ind].dwFlags= 0; // WHDR_BEGINLOOP | WHDR_ENDLOOP;
-        waveHeaderOut[ind].dwLoops=0;
-
-        result=waveOutPrepareHeader(hWaveOut,
-          &(waveHeaderOut[ind]), sizeof(WAVEHDR));
-        DSP::f::AudioCheckError(result);
-        waveHeaderOut[ind].dwFlags= WHDR_DONE; // WHDR_BEGINLOOP | WHDR_ENDLOOP;
-      }
-    }
-    else
-    { //error while creating audio output
-      waveHeaderOut.clear();
-      WaveOutBuffers.clear();
-      WaveOutBufferLen = 0;
-      OutBuffer.clear(); 
-      OutBufferLen = 0;
-      BufferIndex=0;
-    }
+  // #else
 
-  #else
+  //   WaveOutBufferLen = 0;
+  //   WaveOutBuffers.clear();
+  //   OutBuffer.clear(); OutBufferLen = 0;
+  //   BufferIndex=0;
 
-    WaveOutBufferLen = 0;
-    WaveOutBuffers.clear();
-    OutBuffer.clear(); OutBufferLen = 0;
-    BufferIndex=0;
+  // #endif  // WINMMAPI
 
-  #endif  // WINMMAPI
-
-  IsPlayingNow = false;
-  NextBufferInd=0;
+  // IsPlayingNow = false;
+  //NextBufferInd=0;
 
   Execute_ptr = &InputExecute;
 }
@@ -4294,50 +4176,52 @@ void DSP::u::AudioInput::Init(DSP::Clock_ptr ParentClock,
 
 DSP::u::AudioOutput::~AudioOutput()
 {
-  #ifdef WINMMAPI
-    MMRESULT result;
-    unsigned long ind;
-  #endif
+  // #ifdef WINMMAPI
+  //   MMRESULT result;
+  //   unsigned long ind;
+  // #endif
 
   if (OutBufferLen != 0)
   { // if device was opened successfully
     StopPlaying=true;
 
-    #ifdef WINMMAPI
-      result = waveOutReset(hWaveOut);
-      DSP::f::AudioCheckError(result);
-      for (ind=0; ind< DSP::NoOfAudioOutputBuffers; ind++)
-      {
-        result=waveOutUnprepareHeader(hWaveOut,
-          &(waveHeaderOut[ind]), sizeof(WAVEHDR));
-        DSP::f::AudioCheckError(result);
-      }
-
-      #ifdef AUDIO_DEBUG_MESSAGES_ON
-        DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Closing DSP::u::AudioOutput" << endl;
-      #endif
-      result=waveOutClose(hWaveOut);
-      while (result==WAVERR_STILLPLAYING)
-      {
-      //    #ifdef WINBASEAPI
-        DSP::f::Sleep(100);
-      //    #else
-      //      sleep(100);
-      //    #endif
-        #ifdef AUDIO_DEBUG_MESSAGES_ON
-          DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Closing DSP::u::AudioOutput" << endl;
-        #endif
-        result=waveOutClose(hWaveOut);
-      }
-      DSP::f::AudioCheckError(result);
-    #endif
-
-
-    // 2) Free buffers
-    WaveOutBuffers.clear();
-    #ifdef WINMMAPI
-      waveHeaderOut.clear();
-    #endif
+    snd_object.close_PCM_device();
+
+    // #ifdef WINMMAPI
+    //   result = waveOutReset(hWaveOut);
+    //   DSP::f::AudioCheckError(result);
+    //   for (ind=0; ind< DSP::NoOfAudioOutputBuffers; ind++)
+    //   {
+    //     result=waveOutUnprepareHeader(hWaveOut,
+    //       &(waveHeaderOut[ind]), sizeof(WAVEHDR));
+    //     DSP::f::AudioCheckError(result);
+    //   }
+
+    //   #ifdef AUDIO_DEBUG_MESSAGES_ON
+    //     DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Closing DSP::u::AudioOutput" << endl;
+    //   #endif
+    //   result=waveOutClose(hWaveOut);
+    //   while (result==WAVERR_STILLPLAYING)
+    //   {
+    //   //    #ifdef WINBASEAPI
+    //     DSP::f::Sleep(100);
+    //   //    #else
+    //   //      sleep(100);
+    //   //    #endif
+    //     #ifdef AUDIO_DEBUG_MESSAGES_ON
+    //       DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Closing DSP::u::AudioOutput" << endl;
+    //     #endif
+    //     result=waveOutClose(hWaveOut);
+    //   }
+    //   DSP::f::AudioCheckError(result);
+    // #endif
+
+
+    // // 2) Free buffers
+    // WaveOutBuffers.clear();
+    // #ifdef WINMMAPI
+    //   waveHeaderOut.clear();
+    // #endif
 
     OutBuffer.clear();
   }
@@ -4416,114 +4300,116 @@ DSP::u::AudioInput::~AudioInput()
 
 void DSP::u::AudioOutput::FlushBuffer(void)
 {
-  #ifdef WINMMAPI
-    MMRESULT result;
-    uint8_t *temp8;
-    short *temp16;
-    DSP::Float_ptr Sample;
-    short Znak;
-    uint32_t ind;
-
-    // ************************************************** //
-    // Send buffer to the audio device
-
-  #ifdef AUDIO_DEBUG_MESSAGES_ON
-    DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Flushing output buffer" << endl;
-  #endif
-
-  while (1)
-  {
-    if (waveHeaderOut[NextBufferInd].dwFlags & WHDR_DONE)
-    {
-      result=waveOutUnprepareHeader(hWaveOut,
-        &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
-      DSP::f::AudioCheckError(result);
-
-      Sample=OutBuffer.data();
-      // ************************************************** //
-      // Converts samples format to the one suitable for the audio device
-      switch (OutSampleType)
-      {
-        case DSP::e::SampleType::ST_uchar:
-          temp8=(uint8_t *)(WaveOutBuffers[NextBufferInd].data());
-          for (ind=0; ind<OutBufferLen; ind++)
-          {
-            if (*Sample < 0)
-              Znak=-1;
-            else
-              Znak=1;
-
-            *Sample*=127;
-            if ((*Sample)*Znak > 127)
-              *temp8=(unsigned char)(128+Znak*127);
-            else
-              *temp8=(unsigned char)(128+*Sample+Znak*0.5);
-
-            Sample++;
-            temp8++;
-          }
-          break;
-        case DSP::e::SampleType::ST_short:
-          temp16=(short *)(WaveOutBuffers[NextBufferInd].data());
-          for (ind=0; ind<OutBufferLen; ind++)
-          {
-            if (*Sample < 0)
-              Znak=-1;
-            else
-              Znak=1;
-
-            *Sample*=SHRT_MAX;
-            if ((*Sample)*Znak > SHRT_MAX)
-              *temp16=(short)(Znak*SHRT_MAX);
-            else
-              *temp16=(short)(*Sample+Znak*0.5);
-            Sample++;
-            temp16++;
-          }
-          break;
-        default:
-          break;
-      }
-
-      result=waveOutPrepareHeader(hWaveOut,
-        &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
-      DSP::f::AudioCheckError(result);
-
-      if (IsPlayingNow == false)
-      {
-        if (NextBufferInd == 1)
-        {
-          for (ind=0; ind < DSP::NoOfAudioOutputBuffers-1; ind++) //one spare buffer
-          {
-            result=waveOutWrite(hWaveOut,
-              &(waveHeaderOut[ind]), sizeof(WAVEHDR));
-            DSP::f::AudioCheckError(result);
-          }
-          IsPlayingNow = true;
-        }
-
-      }
-      else
-      {
-        result=waveOutWrite(hWaveOut,
-          &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
-        DSP::f::AudioCheckError(result);
-      }
-      NextBufferInd++;
-      NextBufferInd %= DSP::NoOfAudioOutputBuffers;
-
-      break;
-    }
-    else
-    {
-  //    Sleep(10);
-  #ifdef AUDIO_DEBUG_MESSAGES_ON
-      DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Waiting for free output buffer" << endl;
-  #endif
-      DSP::f::Sleep(0);
-    }
-  }
-  #endif // WINMMAPI
+  snd_object.append_playback_buffer(OutBuffer);
+
+  // #ifdef WINMMAPI
+  //   MMRESULT result;
+  //   uint8_t *temp8;
+  //   short *temp16;
+  //   DSP::Float_ptr Sample;
+  //   short Znak;
+  //   uint32_t ind;
+
+  //   // ************************************************** //
+  //   // Send buffer to the audio device
+
+  // #ifdef AUDIO_DEBUG_MESSAGES_ON
+  //   DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Flushing output buffer" << endl;
+  // #endif
+
+  // while (1)
+  // {
+  //   if (waveHeaderOut[NextBufferInd].dwFlags & WHDR_DONE)
+  //   {
+  //     result=waveOutUnprepareHeader(hWaveOut,
+  //       &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
+  //     DSP::f::AudioCheckError(result);
+
+  //     Sample=OutBuffer.data();
+  //     // ************************************************** //
+  //     // Converts samples format to the one suitable for the audio device
+  //     switch (OutSampleType)
+  //     {
+  //       case DSP::e::SampleType::ST_uchar:
+  //         temp8=(uint8_t *)(WaveOutBuffers[NextBufferInd].data());
+  //         for (ind=0; ind<OutBufferLen; ind++)
+  //         {
+  //           if (*Sample < 0)
+  //             Znak=-1;
+  //           else
+  //             Znak=1;
+
+  //           *Sample*=127;
+  //           if ((*Sample)*Znak > 127)
+  //             *temp8=(unsigned char)(128+Znak*127);
+  //           else
+  //             *temp8=(unsigned char)(128+*Sample+Znak*0.5);
+
+  //           Sample++;
+  //           temp8++;
+  //         }
+  //         break;
+  //       case DSP::e::SampleType::ST_short:
+  //         temp16=(short *)(WaveOutBuffers[NextBufferInd].data());
+  //         for (ind=0; ind<OutBufferLen; ind++)
+  //         {
+  //           if (*Sample < 0)
+  //             Znak=-1;
+  //           else
+  //             Znak=1;
+
+  //           *Sample*=SHRT_MAX;
+  //           if ((*Sample)*Znak > SHRT_MAX)
+  //             *temp16=(short)(Znak*SHRT_MAX);
+  //           else
+  //             *temp16=(short)(*Sample+Znak*0.5);
+  //           Sample++;
+  //           temp16++;
+  //         }
+  //         break;
+  //       default:
+  //         break;
+  //     }
+
+  //     result=waveOutPrepareHeader(hWaveOut,
+  //       &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
+  //     DSP::f::AudioCheckError(result);
+
+  //     if (IsPlayingNow == false)
+  //     {
+  //       if (NextBufferInd == 1)
+  //       {
+  //         for (ind=0; ind < DSP::NoOfAudioOutputBuffers-1; ind++) //one spare buffer
+  //         {
+  //           result=waveOutWrite(hWaveOut,
+  //             &(waveHeaderOut[ind]), sizeof(WAVEHDR));
+  //           DSP::f::AudioCheckError(result);
+  //         }
+  //         IsPlayingNow = true;
+  //       }
+
+  //     }
+  //     else
+  //     {
+  //       result=waveOutWrite(hWaveOut,
+  //         &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
+  //       DSP::f::AudioCheckError(result);
+  //     }
+  //     NextBufferInd++;
+  //     NextBufferInd %= DSP::NoOfAudioOutputBuffers;
+
+  //     break;
+  //   }
+  //   else
+  //   {
+  // //    Sleep(10);
+  // #ifdef AUDIO_DEBUG_MESSAGES_ON
+  //     DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Waiting for free output buffer" << endl;
+  // #endif
+  //     DSP::f::Sleep(0);
+  //   }
+  // }
+  // #endif // WINMMAPI
 }
 
 void DSP::u::AudioOutput::InputExecute(INPUT_EXECUTE_ARGS)
diff --git a/src/cpp/WMM_support.cpp b/src/cpp/WMM_support.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f53a2bc1bace805fe4288b6ca7d4d80facd1b4a7
--- /dev/null
+++ b/src/cpp/WMM_support.cpp
@@ -0,0 +1,360 @@
+/*! \file WMM_support.cpp
+ * WMM support code file
+ *
+ * \author Marek Blok
+ */
+
+#include <WMM_support.h>
+
+#include <DSP_lib.h> // for logging 
+
+DSP::WMM_object_t::WMM_object_t()
+{
+  is_device_openned = false;
+  WaveOutDevNo = UINT_MAX;
+
+  NextBufferInd=0;
+  IsPlayingNow = false;
+};
+DSP::WMM_object_t::~WMM_object_t()
+{
+  if (is_device_openned) {
+    close_PCM_device();
+  }
+}
+
+void CALLBACK DSP::WMM_object_t::waveOutProc(HWAVEOUT hwo, UINT uMsg,
+  uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2)
+{
+  UNUSED_ARGUMENT(hwo);
+  UNUSED_ARGUMENT(uMsg);
+  UNUSED_ARGUMENT(dwInstance);
+  UNUSED_ARGUMENT(dwParam1);
+  UNUSED_ARGUMENT(dwParam2);
+#ifdef __DEBUG__
+#ifdef AUDIO_DEBUG_MESSAGES_ON
+//  MMRESULT result;
+  DSP::u::AudioOutput *Current;
+  bool AllDone;
+  int ind;
+  string tekst;
+
+  Current = AudioObjects[dwInstance];
+
+  switch (uMsg)
+  {
+    case WOM_OPEN:
+      DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second
+        << "WOM_OPEN(" << (int)dwInstance << ")" << endl;
+      break;
+    case WOM_CLOSE:
+      DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second
+        << "WOM_CLOSE(" << (int)dwInstance << ")" << endl;
+      break;
+    case WOM_DONE:
+      DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second
+        << "WOM_DONE(" << (int)dwInstance << ")" << endl;
+
+      if (Current->StopPlaying)
+      {
+        DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second << "StopPlaying is set" << endl;
+        return;
+      }
+      else
+      {
+        AllDone=true;
+        for (ind=0; ind < DSP_NoOfAudioOutputBuffers; ind++)
+          AllDone &= (Current->waveHeaderOut[ind].dwFlags & WHDR_DONE);
+        if (AllDone)
+          DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second << "All buffers had been used - nothing to play" << endl;
+      }
+      break;
+  }
+#endif
+#endif
+}
+
+
+void DSP::WMM_object_t::log_driver_data() {
+  /*
+  int val;
+
+  DSP::log << "WMM library version: " << SND_LIB_VERSION_STR << endl;
+
+  DSP::log << endl;
+  DSP::log << "PCM stream types:" << endl;
+  for (val = 0; val <= SND_PCM_STREAM_LAST; val++)
+    DSP::log << "  " << snd_pcm_stream_name((snd_pcm_stream_t)val) << endl;
+
+  DSP::log << endl;
+  DSP::log << "PCM access types:" << endl;
+  for (val = 0; val <= SND_PCM_ACCESS_LAST; val++)
+    DSP::log << "  " << snd_pcm_access_name((snd_pcm_access_t)val) << endl;
+
+  DSP::log << endl;
+  DSP::log << "PCM formats:" << endl;
+  for (val = 0; val <= SND_PCM_FORMAT_LAST; val++)
+    if (snd_pcm_format_name((snd_pcm_format_t)val) != NULL)
+      DSP::log << "  " << snd_pcm_format_name((snd_pcm_format_t)val) <<
+        "(" << snd_pcm_format_description((snd_pcm_format_t)val) << ")" << endl;
+
+  DSP::log << endl;
+  DSP::log << "PCM subformats:" << endl;
+  for (val = 0; val <= SND_PCM_SUBFORMAT_LAST; val++)
+    DSP::log << "  " << snd_pcm_subformat_name((snd_pcm_subformat_t)val) <<
+      "(" << snd_pcm_subformat_description((snd_pcm_subformat_t)val) << ")" << endl;
+
+  DSP::log << endl;
+  DSP::log << "PCM states:" << endl;
+  for (val = 0; val <= SND_PCM_STATE_LAST; val++)
+    DSP::log << "  " << snd_pcm_state_name((snd_pcm_state_t)val) << endl;
+  */
+}
+
+//    Callback = (DWORD_PTR)(&DSP::u::AudioOutput::waveOutProc);
+
+bool DSP::WMM_object_t::select_device_by_number(const unsigned int &device_number) {
+  WaveOutDevNo = device_number;
+
+  return WaveOutDevNo;
+}
+
+bool DSP::WMM_object_t::is_device_playing(void) {
+  return IsPlayingNow;
+}
+
+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) {
+  if (is_device_openned)
+  {
+    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();
+  }
+
+  switch (no_of_bits)
+  {
+    case 8:
+      OutSampleType=DSP::e::SampleType::ST_uchar;
+      break;
+    case 16:
+      OutSampleType=DSP::e::SampleType::ST_short;
+      break;
+    default:
+      OutSampleType=DSP::e::SampleType::ST_short;
+      no_of_bits=16;
+      break;
+  }
+
+  //Wypeniamy struktur wfx
+  wfx.wf.wFormatTag=WAVE_FORMAT_PCM;
+  wfx.wf.nChannels=(uint16_t)no_of_channels;
+  wfx.wf.nSamplesPerSec=(UINT)sampling_rate;
+  wfx.wBitsPerSample=(uint16_t)no_of_bits;
+  wfx.wf.nAvgBytesPerSec=wfx.wf.nSamplesPerSec*(wfx.wBitsPerSample/8);
+  wfx.wf.nBlockAlign=(uint16_t)(wfx.wf.nChannels*(wfx.wBitsPerSample/8));
+
+  if (WaveOutDevNo >= (UINT)waveOutGetNumDevs())
+    result=waveOutOpen(&hWaveOut,
+      WAVE_MAPPER, //&DeviceID,
+      (WAVEFORMATEX *)(&wfx),
+      DWORD_PTR(NULL), //Callback,
+      0, //Current_CallbackInstance, 
+      WAVE_ALLOWSYNC | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL
+      //CALLBACK_FUNCTION | WAVE_ALLOWSYNC | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL
+      );
+  else
+    result=waveOutOpen(&hWaveOut,
+      WaveOutDevNo, //&DeviceID,
+      (WAVEFORMATEX *)(&wfx),
+      DWORD_PTR(NULL), //Callback,
+      0, // Current_CallbackInstance, //CallbackInstance,
+      WAVE_ALLOWSYNC | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL
+//      CALLBACK_FUNCTION | WAVE_ALLOWSYNC | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL
+      );
+
+  if (DSP::f::AudioCheckError(result) == false)
+  { // everything  is ok
+    waveHeaderOut.resize(DSP::NoOfAudioOutputBuffers);
+    WaveOutBufferLen=wfx.wf.nBlockAlign*audio_outbuffer_size;
+    WaveOutBuffers.resize(DSP::NoOfAudioOutputBuffers);
+    for (unsigned int ind=0; ind< DSP::NoOfAudioOutputBuffers; ind++)
+    {
+      WaveOutBuffers[ind].clear();
+      WaveOutBuffers[ind].resize(WaveOutBufferLen, 0);
+    }
+
+
+    for (unsigned int ind=0; ind< DSP::NoOfAudioOutputBuffers; ind++)
+    {
+      waveHeaderOut[ind].lpData=(char *)(WaveOutBuffers[ind].data());
+      waveHeaderOut[ind].dwBufferLength=no_of_channels*audio_outbuffer_size*(no_of_bits/8); //sizeof(short);
+      waveHeaderOut[ind].dwFlags= 0; // WHDR_BEGINLOOP | WHDR_ENDLOOP;
+      waveHeaderOut[ind].dwLoops=0;
+
+      result=waveOutPrepareHeader(hWaveOut,
+        &(waveHeaderOut[ind]), sizeof(WAVEHDR));
+      DSP::f::AudioCheckError(result);
+      waveHeaderOut[ind].dwFlags= WHDR_DONE; // WHDR_BEGINLOOP | WHDR_ENDLOOP;
+    }
+  }
+  else
+  { //error while creating audio output
+    waveHeaderOut.clear();
+    WaveOutBuffers.clear();
+    WaveOutBufferLen = 0;
+  }
+
+  return sampling_rate;
+}
+
+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_outbuffer_size) {
+  return -1;
+}
+
+
+bool DSP::WMM_object_t::close_PCM_device(void) {
+  result = waveOutReset(hWaveOut);
+  DSP::f::AudioCheckError(result);
+  
+  for (unsigned int ind=0; ind< DSP::NoOfAudioOutputBuffers; ind++)
+  {
+    result=waveOutUnprepareHeader(hWaveOut,
+      &(waveHeaderOut[ind]), sizeof(WAVEHDR));
+    DSP::f::AudioCheckError(result);
+  }
+
+  #ifdef AUDIO_DEBUG_MESSAGES_ON
+    DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Closing DSP::u::AudioOutput" << endl;
+  #endif
+  result=waveOutClose(hWaveOut);
+  while (result==WAVERR_STILLPLAYING)
+  {
+    DSP::f::Sleep(100);
+    #ifdef AUDIO_DEBUG_MESSAGES_ON
+      DSP::log << "DSP::u::AudioOutput" << DSP::e::LogMode::second << "Closing DSP::u::AudioOutput" << endl;
+    #endif
+    result=waveOutClose(hWaveOut);
+  }  
+  DSP::f::AudioCheckError(result);
+
+  // 2) Free buffers
+  WaveOutBuffers.clear();
+  #ifdef WINMMAPI
+    waveHeaderOut.clear();
+  #endif
+
+  #ifdef AUDIO_DEBUG_MESSAGES_ON
+    DSP::log << "WMM PCM sound closed" << endl;
+  #endif
+
+  return true; // device has been closed
+}
+
+
+long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) {
+  uint8_t *temp8;
+  short *temp16;
+  short Znak;
+  uint32_t ind;
+
+  // ************************************************** //
+  // Send float_buffer to the audio device
+
+  #ifdef AUDIO_DEBUG_MESSAGES_ON
+    DSP::log << "DSP::WMM_object_t::append_playback_buffer" << DSP::e::LogMode::second << "Flushing output buffer" << endl;
+  #endif
+
+  while (1)
+  {
+    if (waveHeaderOut[NextBufferInd].dwFlags & WHDR_DONE)
+    {
+      result=waveOutUnprepareHeader(hWaveOut,
+        &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
+      DSP::f::AudioCheckError(result);
+
+      DSP::Float_ptr Sample=float_buffer.data();
+      // ************************************************** //
+      // Converts samples format to the one suitable for the audio device
+      switch (OutSampleType)
+      {
+        case DSP::e::SampleType::ST_uchar:
+          temp8=(uint8_t *)(WaveOutBuffers[NextBufferInd].data());
+          for (ind=0; ind<float_buffer.size(); ind++)
+          {
+            if (*Sample < 0)
+              Znak=-1;
+            else
+              Znak=1;
+
+            *Sample*=127;
+            if ((*Sample)*Znak > 127)
+              *temp8=(unsigned char)(128+Znak*127);
+            else
+              *temp8=(unsigned char)(128+*Sample+Znak*0.5);
+
+            Sample++;
+            temp8++;
+          }
+          break;
+        case DSP::e::SampleType::ST_short:
+          temp16=(short *)(WaveOutBuffers[NextBufferInd].data());
+          for (ind=0; ind<float_buffer.size(); ind++)
+          {
+            if (*Sample < 0)
+              Znak=-1;
+            else
+              Znak=1;
+
+            *Sample*=SHRT_MAX;
+            if ((*Sample)*Znak > SHRT_MAX)
+              *temp16=(short)(Znak*SHRT_MAX);
+            else
+              *temp16=(short)(*Sample+Znak*0.5);
+            Sample++;
+            temp16++;
+          }
+          break;
+        default:
+          break;
+      }
+
+      result=waveOutPrepareHeader(hWaveOut,
+        &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
+      DSP::f::AudioCheckError(result);
+
+      if (IsPlayingNow == false)
+      {
+        if (NextBufferInd == 1)
+        {
+          for (ind=0; ind < DSP::NoOfAudioOutputBuffers-1; ind++) //one spare buffer
+          {
+            result=waveOutWrite(hWaveOut,
+              &(waveHeaderOut[ind]), sizeof(WAVEHDR));
+            DSP::f::AudioCheckError(result);
+          }
+          IsPlayingNow = true;
+        }
+
+      }
+      else
+      {
+        result=waveOutWrite(hWaveOut,
+          &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR));
+        DSP::f::AudioCheckError(result);
+      }
+      NextBufferInd++;
+      NextBufferInd %= DSP::NoOfAudioOutputBuffers;
+
+      break;
+    }
+    else
+    {
+  //    Sleep(10);
+  #ifdef AUDIO_DEBUG_MESSAGES_ON
+      DSP::log << "DSP::WMM_object_t::append_playback_buffer" << DSP::e::LogMode::second << "Waiting for free output buffer" << endl;
+  #endif
+      DSP::f::Sleep(0);
+    }
+  }
+
+  return long(float_buffer.size());
+}
\ No newline at end of file
diff --git a/src/include/ALSA_support.h b/src/include/ALSA_support.h
index 1dd3993c8f2169520c5831e4b51b353c7605881c..cf7084b2ca81cff2fce3a277f7db52d1b217a756 100644
--- a/src/include/ALSA_support.h
+++ b/src/include/ALSA_support.h
@@ -13,30 +13,34 @@
 /* All of the ALSA library API is defined in this header */
 #include <alsa/asoundlib.h>
 
-#include <DSP_lib.h> // for logging
+#include <DSP_lib.h> // for logging and types
 
-class ALSA_object_t {
-private:
-    snd_pcm_t *alsa_handle;
-    snd_pcm_hw_params_t *hw_params;
+namespace DSP {
+    
+    class ALSA_object_t : public DSP::SOUND_object_t {
+    private:
+        snd_pcm_t *alsa_handle;
+        snd_pcm_hw_params_t *hw_params;
 
-public:
+    public:
 
-    //! log basic ALSA information
-    void log_alsa_data();
+        //! 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);
+        //! 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);
-    snd_pcm_sframes_t pcm_writei(const void *buffer, snd_pcm_uframes_t &frames);
+        void get_params(snd_pcm_uframes_t &frames, unsigned int &period_time);
+        snd_pcm_sframes_t pcm_writei(const void *buffer, snd_pcm_uframes_t &frames);
 
-    //! object constructor
-    ALSA_object_t();
-    ~ALSA_object_t();
-};
+        //! object constructor
+        ALSA_object_t();
+        ~ALSA_object_t();
+    };
+
+}
 
 #endif // ALSA_support_H
diff --git a/src/include/DSP_IO.h b/src/include/DSP_IO.h
index 74bf78f6d999c6a5c81c729e7800abf39e4420c2..76cb695a23034dd8da0476a1e82c740607f016f6 100644
--- a/src/include/DSP_IO.h
+++ b/src/include/DSP_IO.h
@@ -23,8 +23,7 @@
 ////#ifdef __CYGWIN__
 //#ifdef WIN32
 #if defined(WIN32) || defined(WIN64)
-  #include <windef.h>
-  #include <mmsystem.h>
+  #include <WMM_support.h>
 #else
   #ifdef LINUX
     //! \TODO adapt for linux
@@ -834,21 +833,22 @@ class DSP::u::AudioOutput : public DSP::Block
   private:
     DSP::T_WAVEchunk WAVEchunk;
     #ifdef WINMMAPI
-      HWAVEOUT hWaveOut;
+      //HWAVEOUT hWaveOut;
+      DSP::WMM_object_t snd_object;
     #endif
 
-    //! Index of the buffer which must be used next time
-    unsigned long NextBufferInd;
-    //! Type of samples in WaveOutBuffers
-    DSP::e::SampleType OutSampleType;
-    #ifdef WINMMAPI
-      std::vector<WAVEHDR> waveHeaderOut;
-    #endif
-    uint32_t WaveOutBufferLen;  // in bytes
-    //! Buffers for audio samples prepared for playing
-    std::vector<std::vector<uint8_t>> WaveOutBuffers;
-
-    //! size of the buffers used internally with WMM driver
+    // //! Index of the buffer which must be used next time
+    // unsigned long NextBufferInd;
+    // //! Type of samples in WaveOutBuffers
+    // DSP::e::SampleType OutSampleType;
+    //#ifdef WINMMAPI
+    //  std::vector<WAVEHDR> waveHeaderOut;
+    //#endif
+    // uint32_t WaveOutBufferLen;  // in bytes
+    // //! Buffers for audio samples prepared for playing
+    // std::vector<std::vector<uint8_t>> WaveOutBuffers;
+
+    //! size of the buffers used internally with audio driver
     uint32_t audio_outbuffer_size;
 
     //! in samples times number of channels
@@ -861,7 +861,7 @@ class DSP::u::AudioOutput : public DSP::Block
     /*! saturation logic should be implemented */
     void FlushBuffer(void);
 
-    bool IsPlayingNow;
+    //bool IsPlayingNow;
 
     bool StartAudio(void);
     bool StopAudio(void);
@@ -877,10 +877,10 @@ class DSP::u::AudioOutput : public DSP::Block
     //! (returns number of samples read per channel)
     uint32_t GetAudioSegment(void);
 
-    #ifdef WINMMAPI
-      static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg,
-        uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2);
-    #endif
+    //#ifdef WINMMAPI
+    //  static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg,
+    //    uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2);
+    //#endif
 
     void Init(unsigned long SamplingFreq,
               unsigned int InputsNo=1, //just one channel
diff --git a/src/include/DSP_lib.h b/src/include/DSP_lib.h
index e6d13c603eadb5a1ea9684e7e610c5ee8d5d0135..d89b1f4e1ca42b3fc9c7f767cca699242e4cf1bc 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 4 // !!! without zeroes before, else this will be treated as octal number
+#define DSP_VER_BUILD 5 // !!! 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 ce092f4f8ef9ddd7d30f343338159dafe4a17f03..c6b5e3d859e9efccf2c2f50bf2ba3d04868da90f 100644
--- a/src/include/DSP_types.h
+++ b/src/include/DSP_types.h
@@ -528,6 +528,31 @@ namespace DSP {
 #endif
 
 
+namespace DSP {
+    //! 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 {
+
+    public:
+      virtual void log_driver_data() = 0;
+
+      virtual bool select_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 bool close_PCM_device(void) = 0;
+
+      //! returns true is the playback is on
+      virtual bool is_device_playing(void) = 0;
+
+      //! \note values stored in float_buffer might be altered
+      long append_playback_buffer(DSP::Float_vector &float_buffer);
+
+      virtual ~SOUND_object_t() {};
+    };
+}
+
 
 #include <DSP_DOT.h>
 
diff --git a/src/include/WMM_support.h b/src/include/WMM_support.h
new file mode 100644
index 0000000000000000000000000000000000000000..5706e99e88c2c54ebeaef4e4d21d3bce2bab37d0
--- /dev/null
+++ b/src/include/WMM_support.h
@@ -0,0 +1,83 @@
+/*! \file WMM_support.h
+ * WMM support header file
+ *
+ * \author Marek Blok
+ */
+//---------------------------------------------------------------------------
+#ifndef WMM_support_H
+#define WMM_support_H
+
+/* inluce WMM API */
+////#ifdef __CYGWIN__
+//#ifdef WIN32
+#if defined(WIN32) || defined(WIN64)
+  #include <windef.h>
+  #include <mmsystem.h>
+#else
+  #error NO WIN32
+#endif
+
+#include <DSP_types.h> // for types
+
+namespace DSP {
+    class WMM_object_t : public DSP::SOUND_object_t {
+    private:
+      bool is_device_openned;
+
+      HWAVEOUT hWaveOut;
+
+      MMRESULT result;
+      DWORD_PTR Callback;
+
+      //Rezerwacja pamięci dla formatu WAVE
+      //  WAVEFORMATEX wfx; //to wymaga korekty
+      PCMWAVEFORMAT wfx;
+
+      unsigned int WaveOutDevNo; // device numer used in next open operations
+
+      std::vector<WAVEHDR> waveHeaderOut;
+      uint32_t WaveOutBufferLen;  // in bytes
+      //! Buffers for audio samples prepared for playing
+      std::vector<std::vector<uint8_t>> WaveOutBuffers;
+      //! Type of samples in WaveOutBuffers
+      DSP::e::SampleType OutSampleType;
+      //! Index of the buffer which must be used next time
+      unsigned long NextBufferInd;
+      
+      bool IsPlayingNow;
+
+      static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg,
+        uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2);
+
+
+    public:
+
+        //! log basic WMM information
+        void log_driver_data();
+
+        // returns false if device is already opened
+        bool select_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);
+        //! 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_outbuffer_size);
+
+        bool close_PCM_device(void);
+
+        //! returns true is the playback is on
+        bool is_device_playing(void);
+
+        //void get_params(snd_pcm_uframes_t &frames, unsigned int &period_time);
+        //snd_pcm_sframes_t pcm_writei(const void *buffer, snd_pcm_uframes_t &frames);
+        //! \note values stored in float_buffer might be altered
+        long append_playback_buffer(DSP::Float_vector &float_buffer);
+
+        //! object constructor \TODO check use of virtual in constructor and destructor
+        WMM_object_t();
+        ~WMM_object_t();
+    };
+
+}
+
+#endif // WMM_support_H