diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 992d0b314bad02d6a9224b21e28acda0e09532c7..095e7fc7f995eff09683030f2b14492c52b09a15 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -36,7 +36,8 @@ ], "defines": [ "WIN32", - "__DEBUG__=1" + "__DEBUG__=1", + "INCLUDE_DSPE_EXAMPLES" ], "compilerPath": "gcc.exe", "cStandard": "c11", @@ -50,7 +51,8 @@ ], "defines": [ "WIN32", - "__DEBUG__=1" + "__DEBUG__=1", + "INCLUDE_DSPE_EXAMPLES" ], "compilerPath": "gcc.exe", "cStandard": "c11", diff --git a/CHANGELOG b/CHANGELOG index 766bdcc19125bc3baff146103ddc4a7e271773fb..00975c44a21584c9faf88164aff64be62e740f9a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,9 @@ TODO:: LAST DONE: CHANGES: +- 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 - ver. 0.20.005 - <b>2021.04.21</b> Changed: - Added ALSA tests in main.cpp and Launch configuration for Linux diff --git a/examples/DSPE_examples.h b/examples/DSPE_examples.h index 1c7ac473dc47f5d17e553d1aeb6b5cf707292819..5bd1f3c5e2806f862dd60ed578223c15d34de1ec 100644 --- a/examples/DSPE_examples.h +++ b/examples/DSPE_examples.h @@ -9,6 +9,7 @@ #define EXAMPLES_DSPE_EXAMPLES_H_ int test_hello(void); +int test_sound_input(void); #endif /* EXAMPLES_DSPE_EXAMPLES_H_ */ diff --git a/examples/hello.cpp b/examples/hello.cpp index 5f1bfaf6e3723c2926aa59e602383e4ed3b3aa0c..2e0fcc5ea9a29f7bf9c58e60b6bca35dd8cb7045 100644 --- a/examples/hello.cpp +++ b/examples/hello.cpp @@ -5,12 +5,12 @@ */ #include <DSP_lib.h> -#ifndef _DSPE_TEST_ +#ifndef INCLUDE_DSPE_EXAMPLES int main(void) #else #include "DSPE_examples.h" int test_hello(void) -#endif // _DSPE_TEST_ +#endif // INCLUDE_DSPE_EXAMPLES { DSP::Clock_ptr MasterClock; string tekst; diff --git a/examples/sound_input.cpp b/examples/sound_input.cpp index f1f1bc5c187a872a2f70d40390d59ef0404fd4ff..e15d363e1afee5af3f9895d1ae5731608e7b50b1 100644 --- a/examples/sound_input.cpp +++ b/examples/sound_input.cpp @@ -5,12 +5,12 @@ */ #include <DSP_lib.h> -#ifndef _DSPE_TEST_ +#ifndef INCLUDE_DSPE_EXAMPLES int main(void) #else #include "DSPE_examples.h" int test_sound_input(void) -#endif // _DSPE_TEST_ +#endif // INCLUDE_DSPE_EXAMPLES { DSP::Clock_ptr MasterClock, AudioInClock; string tekst; diff --git a/src/Main.cpp b/src/Main.cpp index d18918ac15e631b58c7d3a805e5ec0936d86714b..2b929e35bf3faeda3abd3f8e32b4f7b92504cc9a 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -2931,9 +2931,8 @@ int main(int argc, char*argv[]) DSP::log.SetLogState(DSP::e::LogState::console | DSP::e::LogState::file); DSP::log.SetLogFileName("DSPElib_test_log.txt"); - DSP::log << "test ALSA" << endl; - #ifdef ALSA_support_H + DSP::log << "test ALSA" << endl; test_ALSA(); return 0; #endif // ALSA_support_H @@ -2952,6 +2951,16 @@ int main(int argc, char*argv[]) //! \TODO test also DSP::f::LPF_LS DSP::log << DSP::e::LogMode::pause << "Finished SolveMatrix test" << endl; +#ifdef INCLUDE_DSPE_EXAMPLES + DSP::log << "Starting test_sound_input" << endl; + test_sound_input(); + DSP::log << DSP::e::LogMode::Error << "Finished test_sound_input" << endl; + + DSP::log << "Starting test_hello" << endl; + test_hello(); + DSP::log << DSP::e::LogMode::Error << "Finished test_hello" << endl; +#endif // INCLUDE_DSPE_EXAMPLES + DSP::log << "Starting SymbolMapper test" << endl; test_SymbolMapper(); DSP::log << DSP::e::LogMode::pause << "Finished SymbolMapper test" << endl; @@ -2960,12 +2969,6 @@ int main(int argc, char*argv[]) test_ZPSTC_cw_3(); DSP::log << "Finished test_ZPSTC_cw_3" << DSP::e::LogMode::pause << endl; -#ifdef INCLUDE_DSPE_EXAMPLES - DSP::log << "Starting test_hello" << endl; - test_hello(); - DSP::log << DSP::e::LogMode::Error << "Finished test_hello" << endl; -#endif // INCLUDE_DSPE_EXAMPLES - DSP::log << "Starting test_1" << endl; test_1(argc, argv); DSP::log << DSP::e::LogMode::pause << "Finished test_1" << endl; diff --git a/src/Makefile.linux b/src/Makefile.linux index b7524fb5a32ef0a37b878f880b01b3137aeb2b3f..bb16c0b9281101061af641e25dcaa040bf244533 100644 --- a/src/Makefile.linux +++ b/src/Makefile.linux @@ -23,7 +23,7 @@ INCLUDES_RLS := -I./src/include -I./src/include/rls LIBS := -lasound # \TODO is DEVCPP ok or is it unnecessary -DFLAGS = -DLINUX -DDEVCPP +DFLAGS = -DLINUX -DDEVCPP -DINCLUDE_DSPE_EXAMPLES CFLAGS_release = $(comflag) -std=c++0x -O3 -Wall -c -fmessage-length=0 -fno-strict-aliasing CFLAGS_debug = $(comflag) -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -W -Wshadow -Wconversion -fstrict-aliasing -fmax-errors=5 # -U__STRICT_ANSI__ jest potrzebne do kompilacji debug_new.cpp, jeďż˝eli pomin�� ten plik to moďż˝na rďż˝wnieďż˝ wyrzuciďż˝ tďż˝ opcjďż˝ diff --git a/src/Makefile.win b/src/Makefile.win index 295ad8175c528e1e3693b860bf2458f9215f1ec5..bb7bcb6ce710fb66128a904a3c3889fa9841a236 100644 --- a/src/Makefile.win +++ b/src/Makefile.win @@ -11,6 +11,7 @@ com_ver = MinGW-W64_8.1.0 INSTALL_DIR_ROOT = ../_DSPE_lib_minGW_ SRC_DIR = ./src +SRC_EXAMPLES_DIR = ./examples SRC_CPP_SUBDIR = $(SRC_DIR)/cpp OUT_DIR_RLS = ./out_win_rls @@ -21,7 +22,7 @@ INCLUDES_DBG := -I"$(SRC_DIR)/include" -I"$(SRC_DIR)/include/dbg" INCLUDES_RLS := -I"$(SRC_DIR)/include" -I"$(SRC_DIR)/include/rls" LIBS := -lwinmm -lws2_32 -DFLAGS = -DWIN32 -DDEVCPP +DFLAGS = -DWIN32 -DDEVCPP -DINCLUDE_DSPE_EXAMPLES # -D INCLUDE_DSPE_EXAMPLES # TODO: uĹźycie w ramach kompilacji Main.cpp w trybie DEBUG CFLAGS_release = $(comflag) -std=c++0x -O3 -Wall -c -fmessage-length=0 -fno-strict-aliasing CFLAGS_debug = $(comflag) -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -W -Wshadow -Wconversion -fstrict-aliasing -fmax-errors=5 @@ -36,7 +37,10 @@ SOURCES_NAMES += DSP_DOT.cpp DSP_modules_misc.cpp DSP_IO.cpp DSP_logstream.cpp W SOURCES = $(addprefix $(SRC_CPP_SUBDIR)/,$(SOURCES_NAMES)) SOURCES_DBG = -SOURCES_DBG += $(SRC_DIR)/Main.cpp +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 @@ -56,12 +60,14 @@ DEPENDS_SOCKETS_Release := $(DEPENDS_SOCKETS:%.cpp=$(OUT_DIR_RLS)/%.d) # ################################################# # # DEBUG -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_SOCKETS_Debug := $(SOURCES_SOCKETS:%.cpp=$(OUT_DIR_DBG)/%.o) -DEPENDS_SOCKETS_Debug := $(SOURCES_SOCKETS:%.cpp=$(OUT_DIR_DBG)/%.d) +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) # SRC_DBG_SUBDIR = nvwa # SOURCES_MISC_Debug += debug_new.cpp @@ -72,7 +78,8 @@ OBJECTS_MISC_Debug := -include $(DEPENDS_Release) -include $(DEPENDS_SOCKETS_Release) -include $(DEPENDS_Debug) --include $(DEPENDS_SOCKETS_Debug) +-include $(DEPENDS_SOCKETS_Release) +-include $(DEPENDS_EXAMPLES_Debug) all: Debug Release @@ -101,11 +108,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 -lDSPEsockets $(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 -lDSPEsockets -lDSPEexamples $(LIBS) $(OUT_DIR_DBG)/libDSPE.a: $(OBJECTS_Debug) $(OBJECTS_MISC_Debug) @echo Preparing lib file $@ @@ -116,8 +123,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/DSP_IO.cpp b/src/cpp/DSP_IO.cpp index a356b67c064d05481daac179906fbf850b8abcf2..dea7ebd1549971a91c01dc98e6f485026e85b8ac 100644 --- a/src/cpp/DSP_IO.cpp +++ b/src/cpp/DSP_IO.cpp @@ -3513,58 +3513,58 @@ inline void CDirectXInput::SourceDescription(TStringList *Text) switch (result) { case MMSYSERR_ALLOCATED: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "Specified resource is already allocated." << endl; break; case MMSYSERR_BADDEVICEID: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "Specified device identifier is out of range." << endl; break; case MMSYSERR_NODRIVER: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "No device driver is present." << endl; break; case MMSYSERR_NOMEM: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "Unable to allocate or lock memory." << endl; break; case WAVERR_BADFORMAT: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "Attempted to open with an unsupported waveform-audio format." << endl; break; case WAVERR_SYNC: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "The device is synchronous but waveOutOpen was called without using the WAVE_ALLOWSYNC flag." << endl; break; case MMSYSERR_INVALFLAG: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "Invalid flag" << endl; break; case MMSYSERR_NOERROR: return false; - //printf("DSP_AudioCheckError: "); + //printf("DSP::f::AudioCheckError: "); //printf("No error."); //printf("\n"); getchar(); break; case MMSYSERR_INVALHANDLE: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "Specified device handle is invalid." << endl; break; case WAVERR_UNPREPARED: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "The data block pointed to by the pwh parameter hasn't been prepared." << endl; break; case MMSYSERR_HANDLEBUSY: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "Handle busy." << endl; break; case WAVERR_STILLPLAYING: - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second << + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "There are still buffers in the queue." << endl; break; default: { - DSP::log << DSP::e::LogMode::Error << "DSP_AudioCheckError" << DSP::e::LogMode::second + DSP::log << DSP::e::LogMode::Error << "DSP::f::AudioCheckError" << DSP::e::LogMode::second << "Unknown error " << WAVERR_BASE << " " << result << endl; } break; @@ -3606,260 +3606,260 @@ uint32_t DSP::f::GetAudioBufferSize(const unsigned long &SamplingFreq, const DSP return size; } -#ifdef WINMMAPI - - //! \bug allow user to select number of internal buffers - void CALLBACK DSP::u::AudioInput::waveInProc_short(HWAVEIN hwi, UINT uMsg, - uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2) - { - UNUSED_ARGUMENT(hwi); - UNUSED_ARGUMENT(dwParam1); - UNUSED_ARGUMENT(dwParam2); - - MMRESULT result; - DSP::u::AudioInput *Current; - short *temp16; - DSP::Float_ptr Sample; - unsigned int ind; - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - stringstream tekst; - #endif - #endif +//#ifdef WINMMAPI - Current = AudioObjects[dwInstance]; + // //! \bug allow user to select number of internal buffers + // void CALLBACK DSP::u::AudioInput::waveInProc_short(HWAVEIN hwi, UINT uMsg, + // uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2) + // { + // UNUSED_ARGUMENT(hwi); + // UNUSED_ARGUMENT(dwParam1); + // UNUSED_ARGUMENT(dwParam2); - switch (uMsg) - { - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - case WIM_OPEN: - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second - << "WIM_OPEN(" << (int)dwInstance << ")" << endl; - break; - case WIM_CLOSE: - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second - << "WIM_CLOSE(" << (int)dwInstance << ")" << endl; - break; - #endif - #endif + // MMRESULT result; + // DSP::u::AudioInput *Current; + // short *temp16; + // DSP::Float_ptr Sample; + // unsigned int ind; + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // stringstream tekst; + // #endif + // #endif - case WIM_DATA: - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second - << "WIM_DATA(" << (int)dwInstance << ")" << endl; - #endif - #endif + // Current = AudioObjects[dwInstance]; - if (Current->StopRecording) - return; - else - { - if (Current->EmptyBufferIndex == Current->CurrentBufferIndex) - { - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "All buffers had been used - skipping input audio frame" << endl; - #endif - #endif - result=waveInUnprepareHeader(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - // ignore data - - //add put back into recording queue - result=waveInPrepareHeader(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - result=waveInAddBuffer(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - - Current->NextBufferInd++; Current->NextBufferInd %= 2; //just two buffers - } - else - { //copy audio frame to buffer form audio frame NextBufferInd - if (Current->waveHeaderIn[Current->NextBufferInd].dwFlags & WHDR_DONE) - { - //copy data - result=waveInUnprepareHeader(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - - Sample=Current->InBuffers[Current->EmptyBufferIndex].data(); - // ************************************************** // - // Converts samples format to the one suitable for the audio device - #ifdef __DEBUG__ - if (Current->InSampleType != DSP::e::SampleType::ST_short) - { - DSP::log << "DSP::u::AudioInput::waveInProc_short" << DSP::e::LogMode::second << "Current->InSampleType != DSP::e::SampleType::ST_short" << endl; - } - #endif + // switch (uMsg) + // { + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // case WIM_OPEN: + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + // << "WIM_OPEN(" << (int)dwInstance << ")" << endl; + // break; + // case WIM_CLOSE: + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + // << "WIM_CLOSE(" << (int)dwInstance << ")" << endl; + // break; + // #endif + // #endif - temp16=(short *)(Current->WaveInBuffers[Current->NextBufferInd].data()); - for (ind=0; ind<Current->InBufferLen; ind++) - { - *Sample = (DSP::Float)(*temp16) / SHRT_MAX; - Sample++; - temp16++; - } - Current->EmptyBufferIndex++; Current->EmptyBufferIndex %= DSP::NoOfAudioInputBuffers; + // case WIM_DATA: + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + // << "WIM_DATA(" << (int)dwInstance << ")" << endl; + // #endif + // #endif - //add put back into recording queue - result=waveInPrepareHeader(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - result=waveInAddBuffer(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); + // if (Current->StopRecording) + // return; + // else + // { + // if (Current->EmptyBufferIndex == Current->CurrentBufferIndex) + // { + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "All buffers had been used - skipping input audio frame" << endl; + // #endif + // #endif + // result=waveInUnprepareHeader(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + // // ignore data - Current->NextBufferInd++; Current->NextBufferInd %= 2; //just two buffers - } - else - { - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "Wrong audio frame ready or other unexpected error" << endl; - #endif - #endif - } - } - } - break; // WIM_DATA - } - } + // //add put back into recording queue + // result=waveInPrepareHeader(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + // result=waveInAddBuffer(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); - //! \bug allow user to select number of internal buffers - void CALLBACK DSP::u::AudioInput::waveInProc_uchar(HWAVEIN hwi, UINT uMsg, - uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2) - { - UNUSED_ARGUMENT(hwi); - UNUSED_ARGUMENT(dwParam1); - UNUSED_ARGUMENT(dwParam2); + // Current->NextBufferInd++; Current->NextBufferInd %= 2; //just two buffers + // } + // else + // { //copy audio frame to buffer form audio frame NextBufferInd + // if (Current->waveHeaderIn[Current->NextBufferInd].dwFlags & WHDR_DONE) + // { + // //copy data + // result=waveInUnprepareHeader(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + + // Sample=Current->InBuffers[Current->EmptyBufferIndex].data(); + // // ************************************************** // + // // Converts samples format to the one suitable for the audio device + // #ifdef __DEBUG__ + // if (Current->InSampleType != DSP::e::SampleType::ST_short) + // { + // DSP::log << "DSP::u::AudioInput::waveInProc_short" << DSP::e::LogMode::second << "Current->InSampleType != DSP::e::SampleType::ST_short" << endl; + // } + // #endif + + // temp16=(short *)(Current->WaveInBuffers[Current->NextBufferInd].data()); + // for (ind=0; ind<Current->InBufferLen; ind++) + // { + // *Sample = (DSP::Float)(*temp16) / SHRT_MAX; + // Sample++; + // temp16++; + // } + // Current->EmptyBufferIndex++; Current->EmptyBufferIndex %= DSP::NoOfAudioInputBuffers; + + // //add put back into recording queue + // result=waveInPrepareHeader(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + // result=waveInAddBuffer(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + + // Current->NextBufferInd++; Current->NextBufferInd %= 2; //just two buffers + // } + // else + // { + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "Wrong audio frame ready or other unexpected error" << endl; + // #endif + // #endif + // } + // } + // } + // break; // WIM_DATA + // } + // } - MMRESULT result; - DSP::u::AudioInput *Current; - uint8_t *temp8; - DSP::Float_ptr Sample; - unsigned int ind; - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - stringstream tekst; - #else - UNUSED_DEBUG_ARGUMENT(uMsg); - #endif - #endif + // //! \bug allow user to select number of internal buffers + // void CALLBACK DSP::u::AudioInput::waveInProc_uchar(HWAVEIN hwi, UINT uMsg, + // uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2) + // { + // UNUSED_ARGUMENT(hwi); + // UNUSED_ARGUMENT(dwParam1); + // UNUSED_ARGUMENT(dwParam2); - Current = AudioObjects[dwInstance]; + // MMRESULT result; + // DSP::u::AudioInput *Current; + // uint8_t *temp8; + // DSP::Float_ptr Sample; + // unsigned int ind; + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // stringstream tekst; + // #else + // UNUSED_DEBUG_ARGUMENT(uMsg); + // #endif + // #endif - switch (uMsg) - { - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - case WIM_OPEN: - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second - << "WIM_OPEN(" << (int)dwInstance << ")" << end; - break; - case WIM_CLOSE: - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second - << "WIM_CLOSE(" << (int)dwInstance << ")" << endl; - break; - #endif - #endif + // Current = AudioObjects[dwInstance]; - case WIM_DATA: - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second - << "WIM_DATA(" << (int)dwInstance << ")" << endl; - #endif - #endif + // switch (uMsg) + // { + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // case WIM_OPEN: + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + // << "WIM_OPEN(" << (int)dwInstance << ")" << end; + // break; + // case WIM_CLOSE: + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + // << "WIM_CLOSE(" << (int)dwInstance << ")" << endl; + // break; + // #endif + // #endif - if (Current->StopRecording) - return; - else - { - if (Current->EmptyBufferIndex == Current->CurrentBufferIndex) - { - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "All buffers had been used - skipping input audio frame" << endl; - #endif - #endif - result=waveInUnprepareHeader(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - // ignore data - - //add put back into recording queue - result=waveInPrepareHeader(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - result=waveInAddBuffer(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - - Current->NextBufferInd++; Current->NextBufferInd %= 2; //just two buffers - } - else - { //copy audio frame to buffer form audio frame NextBufferInd - if (Current->waveHeaderIn[Current->NextBufferInd].dwFlags & WHDR_DONE) - { - //copy data - result=waveInUnprepareHeader(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - - Sample=Current->InBuffers[Current->EmptyBufferIndex].data(); - // ************************************************** // - // Converts samples format to the one suitable for the audio device - #ifdef __DEBUG__ - if (Current->InSampleType != DSP::e::SampleType::ST_uchar) - { - DSP::log << "DSP::u::AudioInput::waveInProc_uchar" << DSP::e::LogMode::second << "Current->InSampleType != DSP::e::SampleType::ST_uchar" << endl; - } - #endif + // case WIM_DATA: + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + // << "WIM_DATA(" << (int)dwInstance << ")" << endl; + // #endif + // #endif - temp8=(uint8_t *)(Current->WaveInBuffers[Current->NextBufferInd].data()); - for (ind=0; ind<Current->InBufferLen; ind++) - { - *Sample = (DSP::Float)(*temp8 - 128) / 128; - Sample++; - temp8++; - } - Current->EmptyBufferIndex++; Current->EmptyBufferIndex %= DSP::NoOfAudioInputBuffers; + // if (Current->StopRecording) + // return; + // else + // { + // if (Current->EmptyBufferIndex == Current->CurrentBufferIndex) + // { + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "All buffers had been used - skipping input audio frame" << endl; + // #endif + // #endif + // result=waveInUnprepareHeader(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + // // ignore data - //add put back into recording queue - result=waveInPrepareHeader(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - result=waveInAddBuffer(Current->hWaveIn, - &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); + // //add put back into recording queue + // result=waveInPrepareHeader(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + // result=waveInAddBuffer(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); - Current->NextBufferInd++; Current->NextBufferInd %= 2; //just two buffers - } - else - { - #ifdef __DEBUG__ - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "Wrong audio frame ready or other unexpected error" << endl; - #endif - #endif - } - } - break; - } + // Current->NextBufferInd++; Current->NextBufferInd %= 2; //just two buffers + // } + // else + // { //copy audio frame to buffer form audio frame NextBufferInd + // if (Current->waveHeaderIn[Current->NextBufferInd].dwFlags & WHDR_DONE) + // { + // //copy data + // result=waveInUnprepareHeader(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + + // Sample=Current->InBuffers[Current->EmptyBufferIndex].data(); + // // ************************************************** // + // // Converts samples format to the one suitable for the audio device + // #ifdef __DEBUG__ + // if (Current->InSampleType != DSP::e::SampleType::ST_uchar) + // { + // DSP::log << "DSP::u::AudioInput::waveInProc_uchar" << DSP::e::LogMode::second << "Current->InSampleType != DSP::e::SampleType::ST_uchar" << endl; + // } + // #endif + + // temp8=(uint8_t *)(Current->WaveInBuffers[Current->NextBufferInd].data()); + // for (ind=0; ind<Current->InBufferLen; ind++) + // { + // *Sample = (DSP::Float)(*temp8 - 128) / 128; + // Sample++; + // temp8++; + // } + // Current->EmptyBufferIndex++; Current->EmptyBufferIndex %= DSP::NoOfAudioInputBuffers; + + // //add put back into recording queue + // result=waveInPrepareHeader(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + // result=waveInAddBuffer(Current->hWaveIn, + // &(Current->waveHeaderIn[Current->NextBufferInd]), sizeof(WAVEHDR)); + // DSP::f::AudioCheckError(result); + + // Current->NextBufferInd++; Current->NextBufferInd %= 2; //just two buffers + // } + // else + // { + // #ifdef __DEBUG__ + // #ifdef AUDIO_DEBUG_MESSAGES_ON + // DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "Wrong audio frame ready or other unexpected error" << endl; + // #endif + // #endif + // } + // } + // break; + // } - } - } -#endif // WINMMAPI + // } + // } +//#endif // WINMMAPI -unsigned long DSP::u::AudioOutput::Next_CallbackInstance=0; -unsigned long DSP::u::AudioInput::Next_CallbackInstance =0; -std::vector<DSP::u::AudioOutput *> DSP::u::AudioOutput::AudioObjects; -std::vector<DSP::u::AudioInput *> DSP::u::AudioInput::AudioObjects; +// unsigned long DSP::u::AudioOutput::Next_CallbackInstance=0; +// unsigned long DSP::u::AudioInput::Next_CallbackInstance =0; +// std::vector<DSP::u::AudioOutput *> DSP::u::AudioOutput::AudioObjects; +// std::vector<DSP::u::AudioInput *> DSP::u::AudioInput::AudioObjects; DSP::u::AudioOutput::AudioOutput(void) : DSP::Block() @@ -3943,16 +3943,14 @@ void DSP::u::AudioOutput::Init(unsigned long SamplingFreq, // //! \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); - AudioObjects[Current_CallbackInstance]=this; - - StopPlaying = false; + // Current_CallbackInstance=Next_CallbackInstance; + // Next_CallbackInstance++; + // AudioObjects.resize(Current_CallbackInstance+1); + // AudioObjects[Current_CallbackInstance]=this; audio_outbuffer_size = DSP::f::GetAudioBufferSize(SamplingFreq, DSP::e::AudioBufferType::output); - snd_object.select_device_by_number(WaveOutDevNo); // use default device + snd_object.select_output_device_by_number(WaveOutDevNo); // use default device snd_object.open_PCM_device_4_output(NoOfInputs, BitPrec, SamplingFreq, audio_outbuffer_size); OutBufferLen=NoOfInputs*audio_outbuffer_size; @@ -3991,6 +3989,57 @@ DSP::u::AudioInput::AudioInput( OutputExecute_ptr = &OutputExecute; } +bool DSP::u::AudioInput::SOUND_object_callback(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer) { + if (EmptyBufferIndex != CurrentBufferIndex) { + DSP::Float_ptr Sample; + unsigned int ind; + + // reading sound card input buffer + Sample=InBuffers[EmptyBufferIndex].data(); + // ************************************************** // + // Converts samples format from the one used in the audio device + switch (InSampleType) { + case DSP::e::SampleType::ST_short: { + short *temp16; + + temp16=(short *)(wave_in_raw_buffer.data()); + for (ind=0; ind<InBufferLen; ind++) + { + *Sample = (DSP::Float)(*temp16) / SHRT_MAX; + Sample++; + temp16++; + } + } + break; + + case DSP::e::SampleType::ST_uchar: { + uint8_t *temp8; + + temp8=(uint8_t *)(wave_in_raw_buffer.data()); + for (ind=0; ind<InBufferLen; ind++) + { + *Sample = (DSP::Float)(*temp8 - 128) / 128; + Sample++; + temp8++; + } + } + break; + + default: + #ifdef __DEBUG__ + DSP::log << "DSP::u::AudioInput::waveInProc_short" << DSP::e::LogMode::second << "Unsupported Current->InSampleType" << endl; + #endif + break; + } + EmptyBufferIndex++; EmptyBufferIndex %= DSP::NoOfAudioInputBuffers; + + return true; + } + else { + return false; + } + return false; +} /* Inputs and Outputs names: * - Output: @@ -4009,19 +4058,19 @@ void DSP::u::AudioInput::Init(DSP::Clock_ptr ParentClock, unsigned long ind; string temp; - #ifdef WINMMAPI - MMRESULT result; - DWORD_PTR Callback; - //Rezerwacja pamici dla formatu WAVE - // WAVEFORMATEX wfx; //to wymaga korekty - PCMWAVEFORMAT wfx; - #elif defined(ALSA_support_H) - UNUSED_ARGUMENT(WaveInDevNo); - ALSA_object_t ALSA_object; + // #ifdef WINMMAPI + // MMRESULT result; + // DWORD_PTR Callback; + // //Rezerwacja pamici dla formatu WAVE + // // WAVEFORMATEX wfx; //to wymaga korekty + // PCMWAVEFORMAT wfx; + // #elif defined(ALSA_support_H) + // UNUSED_ARGUMENT(WaveInDevNo); + // ALSA_object_t ALSA_object; - #else - UNUSED_ARGUMENT(WaveInDevNo); - #endif + // #else + // UNUSED_ARGUMENT(WaveInDevNo); + // #endif SetNoOfOutputs(OutputsNo); SetName("AudioInput", false); @@ -4046,117 +4095,53 @@ void DSP::u::AudioInput::Init(DSP::Clock_ptr ParentClock, RegisterOutputClock(ParentClock); my_clock = ParentClock; - Current_CallbackInstance=Next_CallbackInstance; - Next_CallbackInstance++; - AudioObjects.resize(Current_CallbackInstance+1); - AudioObjects[Current_CallbackInstance]=this; - StopRecording = false; + // Current_CallbackInstance=Next_CallbackInstance; + // Next_CallbackInstance++; + // AudioObjects.resize(Current_CallbackInstance+1); + // AudioObjects[Current_CallbackInstance]=this; + // StopRecording = false; - switch (BitPrec) - { - case 8: - InSampleType=DSP::e::SampleType::ST_uchar; - #ifdef WINMMAPI - Callback = (DWORD_PTR)(&DSP::u::AudioInput::waveInProc_uchar); - #endif - break; - case 16: - InSampleType=DSP::e::SampleType::ST_short; - #ifdef WINMMAPI - Callback = (DWORD_PTR)(&DSP::u::AudioInput::waveInProc_short); - #endif - break; - default: - InSampleType=DSP::e::SampleType::ST_short; - #ifdef WINMMAPI - Callback = (DWORD_PTR)(&DSP::u::AudioInput::waveInProc_short); - #endif - BitPrec=16; - break; - } + // switch (BitPrec) + // { + // case 8: + // InSampleType=DSP::e::SampleType::ST_uchar; + // #ifdef WINMMAPI + // Callback = (DWORD_PTR)(&DSP::u::AudioInput::waveInProc_uchar); + // #endif + // break; + // case 16: + // InSampleType=DSP::e::SampleType::ST_short; + // #ifdef WINMMAPI + // Callback = (DWORD_PTR)(&DSP::u::AudioInput::waveInProc_short); + // #endif + // break; + // default: + // InSampleType=DSP::e::SampleType::ST_short; + // #ifdef WINMMAPI + // Callback = (DWORD_PTR)(&DSP::u::AudioInput::waveInProc_short); + // #endif + // BitPrec=16; + // break; + // } audio_inbuffer_size = DSP::f::GetAudioBufferSize(SamplingFreq, DSP::e::AudioBufferType::input); - #ifdef WINMMAPI - //Wypeniamy struktur wfx - wfx.wf.wFormatTag=WAVE_FORMAT_PCM; - wfx.wf.nChannels=(uint16_t)NoOfOutputs; - 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)); - - if (waveInGetNumDevs() <= WaveInDevNo) - result=waveInOpen(&hWaveIn, - WAVE_MAPPER, //&DeviceID, - (WAVEFORMATEX *)(&wfx), - Callback, - Current_CallbackInstance, //CallbackInstance, - CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL - ); - else - result=waveInOpen(&hWaveIn, - WaveInDevNo, //&DeviceID, - (WAVEFORMATEX *)(&wfx), - Callback, - Current_CallbackInstance, //CallbackInstance, - CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT //| WAVE_MAPPED //CALLBACK_NULL - ); - if (DSP::f::AudioCheckError(result) == false) - { // no errors - waveHeaderIn.resize(2); - WaveInBufferLen=wfx.wf.nBlockAlign*audio_inbuffer_size; - WaveInBuffers.resize(2); - /*! \bug <b>2006.08.13</b> when 8bit audio stream is created initial values should be 0x80 or 0x79 not 0x00 - */ - WaveInBuffers[0].clear(); WaveInBuffers[0].resize(WaveInBufferLen, 0); - WaveInBuffers[1].clear(); WaveInBuffers[1].resize(WaveInBufferLen, 0); - - InBufferLen=NoOfOutputs*audio_inbuffer_size; - for (ind = 0; ind < DSP::NoOfAudioInputBuffers; ind++) - { - InBuffers[ind].clear(); - InBuffers[ind].resize(InBufferLen); - } - EmptyBufferIndex=0; - CurrentBufferIndex=DSP::NoOfAudioInputBuffers-1; - BufferIndex=InBufferLen; - - waveHeaderIn[0].lpData=(char *)(WaveInBuffers[0].data()); - waveHeaderIn[0].dwBufferLength=InBufferLen*(BitPrec/8); //sizeof(short); - waveHeaderIn[0].dwFlags= 0; // WHDR_BEGINLOOP | WHDR_ENDLOOP; - waveHeaderIn[0].dwLoops=0; - - result=waveInPrepareHeader(hWaveIn, - &(waveHeaderIn[0]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - // waveHeaderIn[0].dwFlags= WHDR_DONE; // WHDR_BEGINLOOP | WHDR_ENDLOOP; - - waveHeaderIn[1].lpData=(char *)(WaveInBuffers[1].data()); - waveHeaderIn[1].dwBufferLength=InBufferLen*(BitPrec/8); //sizeof(short); - waveHeaderIn[1].dwFlags= 0; // WHDR_BEGINLOOP | WHDR_ENDLOOP; - waveHeaderIn[1].dwLoops=0; - - result=waveInPrepareHeader(hWaveIn, - &(waveHeaderIn[1]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - // waveHeaderIn[1].dwFlags= WHDR_DONE; // WHDR_BEGINLOOP | WHDR_ENDLOOP; - } - else - { // error creating audio object - waveHeaderIn.clear(); WaveInBufferLen=0; - WaveInBuffers.clear(); - - InBufferLen=0; - for (ind = 0; ind < DSP::NoOfAudioInputBuffers; ind++) - { - InBuffers[ind].clear(); - } - EmptyBufferIndex=0; CurrentBufferIndex=0; - BufferIndex=0; + snd_object.select_input_device_by_number(WaveInDevNo); // use default device + snd_object.register_input_callback_object(this, SOUND_object_callback); // 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++) + { + InBuffers[ind].clear(); + InBuffers[ind].resize(InBufferLen); } + EmptyBufferIndex=0; + CurrentBufferIndex=DSP::NoOfAudioInputBuffers-1; + BufferIndex=InBufferLen; - #else + } + else + { // error creating audio object InBufferLen=0; for (ind = 0; ind < DSP::NoOfAudioInputBuffers; ind++) @@ -4165,12 +4150,7 @@ void DSP::u::AudioInput::Init(DSP::Clock_ptr ParentClock, } EmptyBufferIndex=0; CurrentBufferIndex=0; BufferIndex=0; - - #endif - - IsRecordingNow = false; //wait until data requested - - NextBufferInd=0; //its overridden in Execute() + } } @@ -4183,9 +4163,9 @@ DSP::u::AudioOutput::~AudioOutput() if (OutBufferLen != 0) { // if device was opened successfully - StopPlaying=true; + snd_object.stop_playback(); - snd_object.close_PCM_device(); + snd_object.close_PCM_device_output(); // #ifdef WINMMAPI // result = waveOutReset(hWaveOut); @@ -4229,60 +4209,23 @@ DSP::u::AudioOutput::~AudioOutput() // *************************** // // Free local resourses // 3) remove this audio object from the list - if (AudioObjects.size() > 0) - { - AudioObjects.erase(AudioObjects.begin() + Current_CallbackInstance); - } - Next_CallbackInstance--; + // if (AudioObjects.size() > 0) + // { + // AudioObjects.erase(AudioObjects.begin() + Current_CallbackInstance); + // } + // Next_CallbackInstance--; } DSP::u::AudioInput::~AudioInput() { - #ifdef WINMMAPI - MMRESULT result; - #endif unsigned long ind; if (InBufferLen != 0) { // if device was opened successfully - StopRecording=true; - - #ifdef WINMMAPI - result = waveInReset(hWaveIn); - DSP::f::AudioCheckError(result); - result=waveInUnprepareHeader(hWaveIn, - &(waveHeaderIn[0]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - result=waveInUnprepareHeader(hWaveIn, - &(waveHeaderIn[1]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput" << DSP::e::LogMode::second << "Closing DSP::u::AudioInput" << endl; - #endif - result=waveInClose(hWaveIn); - while (result==WAVERR_STILLPLAYING) - { - // #ifdef WINBASEAPI - DSP::f::Sleep(100); - // #else - // sleep(100); - // #endif - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput" << DSP::e::LogMode::second << "Closing DSP::u::AudioInput" << endl; - #endif - result=waveInClose(hWaveIn); - } - DSP::f::AudioCheckError(result); - #endif + // StopRecording=true; + snd_object.stop_recording(); - // 2) Free buffers - WaveInBuffers[0].clear(); - WaveInBuffers[1].clear(); - WaveInBuffers.clear(); - #ifdef WINMMAPI - waveHeaderIn.clear(); - #endif + snd_object.close_PCM_device_input(); for (ind=0; ind<DSP::NoOfAudioInputBuffers; ind++) InBuffers[ind].clear(); @@ -4291,11 +4234,11 @@ DSP::u::AudioInput::~AudioInput() // *************************** // // Free local resourses // 3) remove this audio object from the list - if (AudioObjects.size() > 0) - { - AudioObjects.erase(AudioObjects.begin() + Current_CallbackInstance); - } - Next_CallbackInstance--; + // if (AudioObjects.size() > 0) + // { + // AudioObjects.erase(AudioObjects.begin() + Current_CallbackInstance); + // } + // Next_CallbackInstance--; } void DSP::u::AudioOutput::FlushBuffer(void) @@ -4473,10 +4416,7 @@ bool DSP::u::AudioInput::OutputExecute(OUTPUT_EXECUTE_ARGS) { UNUSED_DEBUG_ARGUMENT(clock); - #ifdef WINMMAPI - MMRESULT result; - #endif - unsigned int ind; + unsigned int ind; if (DSP_THIS->InBufferLen == 0) { // no audio device opened @@ -4498,7 +4438,7 @@ bool DSP::u::AudioInput::OutputExecute(OUTPUT_EXECUTE_ARGS) // if no input buffer is ready return false (system will later return here) - if (DSP_THIS->IsRecordingNow == true) + if (DSP_THIS->snd_object.is_device_recording() == true) { // but must check if data ready if ((((DSP_THIS->CurrentBufferIndex + 1) % DSP::NoOfAudioInputBuffers) == DSP_THIS->EmptyBufferIndex) && (DSP_THIS->BufferIndex == DSP_THIS->InBufferLen)) @@ -4553,39 +4493,22 @@ bool DSP::u::AudioInput::OutputExecute(OUTPUT_EXECUTE_ARGS) else { // starts recording // using both buffers - #ifdef WINMMAPI - #ifdef AUDIO_DEBUG_MESSAGES_ON - DSP::log << "DSP::u::AudioInput::Execute" << DSP::e::LogMode::second << "Starting recording using two wave buffers" << endl; - #endif + DSP_THIS->snd_object.start_recording(); - result=waveInAddBuffer(DSP_THIS->hWaveIn, - &(DSP_THIS->waveHeaderIn[0]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - result=waveInAddBuffer(DSP_THIS->hWaveIn, - &(DSP_THIS->waveHeaderIn[1]), sizeof(WAVEHDR)); - DSP::f::AudioCheckError(result); - - DSP_THIS->NextBufferInd = 0; //first buffer first - DSP_THIS->EmptyBufferIndex = 2; //simulate two full buffers - for (ind = 0; ind < DSP_THIS->EmptyBufferIndex; ind++) { - memset(DSP_THIS->InBuffers[ind].data(), 0, DSP_THIS->InBufferLen*sizeof(DSP::Float)); - } - DSP_THIS->BufferIndex = 0; - - result=waveInStart(DSP_THIS->hWaveIn); - DSP::f::AudioCheckError(result); - DSP_THIS->IsRecordingNow = true; - //now just wait for buffer to fill up - // which should call waveInProc - - - //We cannot wait until input buffers fill-up, some other processing - // blocks like DSP::u::AudioOutput might wait for their time - /*! _bug if there are no DSP::u::AudioOutput blocks nothing - * will stop boost in processing speed - * - * we might want to simulated two full input buffers - */ + //DSP_THIS->NextBufferInd = 0; //first buffer first + DSP_THIS->EmptyBufferIndex = 2; //simulate two full buffers + for (ind = 0; ind < DSP_THIS->EmptyBufferIndex; ind++) { + memset(DSP_THIS->InBuffers[ind].data(), 0, DSP_THIS->InBufferLen*sizeof(DSP::Float)); + } + DSP_THIS->BufferIndex = 0; + + //We cannot wait until input buffers fill-up, some other processing + // blocks like DSP::u::AudioOutput might wait for their time + /*! _bug if there are no DSP::u::AudioOutput blocks nothing + * will stop boost in processing speed + * + * we might want to simulated two full input buffers + */ // #ifdef AUDIO_DEBUG_MESSAGES_ON // DSP::log << "DSP::u::AudioInput::Execute", "Audio recording started !!!"); // #endif @@ -4598,8 +4521,6 @@ bool DSP::u::AudioInput::OutputExecute(OUTPUT_EXECUTE_ARGS) // } // return true; - #endif - // program will return to this function and then output should be dealt with DSP::Clock::InputNeedsMoreTime[DSP_THIS->my_clock->MasterClockIndex] = true; return false; @@ -5872,3 +5793,76 @@ bool DSP::f::SaveVector(const string &filename, const DSP::Complex_vector &vecto } +//unsigned long DSP::WMM_object_t::Next_CallbackInstance=0; +std::vector<DSP::SOUND_object_t *> DSP::SOUND_object_t::CallbackSoundObjects; + +const DSP::SOUND_object_t * DSP::SOUND_object_t::get_CallbackSoundObject(const long int &instance_number) { + return (CallbackSoundObjects[instance_number]); +} + +DSP::SOUND_object_t::SOUND_object_t() { + AudioOutput_object = NULL; + AudioInput_object = NULL; + + Current_CallbackInstance=get_free_CallbackInstance(); + CallbackSoundObjects[Current_CallbackInstance]=this; +} + +DSP::u::AudioInput *DSP::SOUND_object_t::get_input_callback_object() { + return AudioInput_object; +} + +bool DSP::SOUND_object_t::input_callback_call(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer) { + return (AudioInput_object->*AudioInput_callback)(InSampleType, wave_in_raw_buffer); +} + +unsigned long DSP::SOUND_object_t::get_free_CallbackInstance(void) { + bool is_free_slot_available = false; + unsigned long free_slot_index; + + for (unsigned int ind = 0; ind < CallbackSoundObjects.size(); ind++) { + if (CallbackSoundObjects[ind] == NULL) { + is_free_slot_available = true; + free_slot_index = ind; + break; + } + } + + if (is_free_slot_available == false) { + CallbackSoundObjects.push_back(NULL); + free_slot_index = (unsigned long)(CallbackSoundObjects.size()-1); + } + + return free_slot_index; +} + + +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::register_input_callback_object(DSP::u::AudioInput *callback_object, bool(DSP::u::AudioInput::*cp)(const DSP::e::SampleType &, const std::vector<char> &)) { + if (is_input_callback_supported() == true) { + AudioInput_object = callback_object; + AudioInput_callback = cp; + return true; + } + return false; +} + +long int DSP::SOUND_object_t::get_current_CallbackInstance() { + return Current_CallbackInstance; +} + +DSP::SOUND_object_t::~SOUND_object_t() { + if (CallbackSoundObjects.size() > 0) + { + //CallbackObjects.erase(CallbackObjects.begin() + Current_CallbackInstance); + CallbackSoundObjects[Current_CallbackInstance] = NULL; + } +} + diff --git a/src/cpp/WMM_support.cpp b/src/cpp/WMM_support.cpp index f53a2bc1bace805fe4288b6ca7d4d80facd1b4a7..75d984294fb6492627864868da865f15538d5b18 100644 --- a/src/cpp/WMM_support.cpp +++ b/src/cpp/WMM_support.cpp @@ -8,19 +8,31 @@ #include <DSP_lib.h> // for logging -DSP::WMM_object_t::WMM_object_t() +DSP::WMM_object_t::WMM_object_t() : DSP::SOUND_object_t() { - is_device_openned = false; + is_device_input_open = false; + WaveInDevNo = UINT_MAX; + is_device_output_open = false; WaveOutDevNo = UINT_MAX; - NextBufferInd=0; + NextBufferOutInd=0; + StopPlayback = false; IsPlayingNow = false; + + NextBufferOutInd = 0; + StopRecording = false; + IsRecordingNow = false; }; + DSP::WMM_object_t::~WMM_object_t() { - if (is_device_openned) { - close_PCM_device(); + if (is_device_input_open) { + close_PCM_device_input(); + } + if (is_device_output_open) { + close_PCM_device_output(); } + } void CALLBACK DSP::WMM_object_t::waveOutProc(HWAVEOUT hwo, UINT uMsg, @@ -44,20 +56,20 @@ void CALLBACK DSP::WMM_object_t::waveOutProc(HWAVEOUT hwo, UINT uMsg, switch (uMsg) { case WOM_OPEN: - DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second + DSP::log << "DSP::WMM_object_t::waveOutProc" << DSP::e::LogMode::second << "WOM_OPEN(" << (int)dwInstance << ")" << endl; break; case WOM_CLOSE: - DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second + DSP::log << "DSP::WMM_object_t::waveOutProc" << DSP::e::LogMode::second << "WOM_CLOSE(" << (int)dwInstance << ")" << endl; break; case WOM_DONE: - DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second + DSP::log << "DSP::WMM_object_t::waveOutProc" << DSP::e::LogMode::second << "WOM_DONE(" << (int)dwInstance << ")" << endl; - if (Current->StopPlaying) + if (Current->StopPlayback) { - DSP::log << "DSP::u::AudioOutput::waveOutProc" << DSP::e::LogMode::second << "StopPlaying is set" << endl; + DSP::log << "DSP::WMM_object_t::waveOutProc" << DSP::e::LogMode::second << "StopPlayback is set" << endl; return; } else @@ -66,7 +78,7 @@ void CALLBACK DSP::WMM_object_t::waveOutProc(HWAVEOUT hwo, UINT uMsg, 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; + DSP::log << "DSP::WMM_object_t::waveOutProc" << DSP::e::LogMode::second << "All buffers had been used - nothing to play" << endl; } break; } @@ -113,21 +125,138 @@ void DSP::WMM_object_t::log_driver_data() { // Callback = (DWORD_PTR)(&DSP::u::AudioOutput::waveOutProc); -bool DSP::WMM_object_t::select_device_by_number(const unsigned int &device_number) { +unsigned int DSP::WMM_object_t::select_output_device_by_number(const unsigned int &device_number) { WaveOutDevNo = device_number; return WaveOutDevNo; } +unsigned int DSP::WMM_object_t::select_input_device_by_number(const unsigned int &device_number) { + WaveInDevNo = device_number; + + return WaveInDevNo; +} + +bool DSP::WMM_object_t::stop_playback(void) { + StopPlayback = true; + //! \TODO can we do more ? + + return true; +} + +bool DSP::WMM_object_t::stop_recording(void) { + StopRecording = true; + //! \TODO can we do more ? + + return true; +} + bool DSP::WMM_object_t::is_device_playing(void) { return IsPlayingNow; } +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) { + 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; + close_PCM_device_input(); + } + + DWORD_PTR Callback; + switch (no_of_bits) + { + case 8: + InSampleType=DSP::e::SampleType::ST_uchar; + break; + case 16: + InSampleType=DSP::e::SampleType::ST_short; + break; + default: + InSampleType=DSP::e::SampleType::ST_short; + no_of_bits=16; + break; + } + Callback = (DWORD_PTR)(&DSP::WMM_object_t::waveInProc); + + //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 (waveInGetNumDevs() <= WaveInDevNo) + result=waveInOpen(&hWaveIn, + WAVE_MAPPER, //&DeviceID, + (WAVEFORMATEX *)(&wfx), + Callback, + get_current_CallbackInstance(), //CallbackInstance, + CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT //| 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 + ); + + if (DSP::f::AudioCheckError(result) == false) + { // no errors + is_device_input_open = true; + + waveHeaderIn.resize(2); + WaveInBufferLen=wfx.wf.nBlockAlign*audio_inbuffer_size; + WaveInBuffers.resize(2); + /*! \bug <b>2006.08.13</b> when 8bit audio stream is created initial values should be 0x80 or 0x79 not 0x00 + */ + WaveInBuffers[0].clear(); WaveInBuffers[0].resize(WaveInBufferLen, 0); + WaveInBuffers[1].clear(); WaveInBuffers[1].resize(WaveInBufferLen, 0); + + waveHeaderIn[0].lpData=(char *)(WaveInBuffers[0].data()); + waveHeaderIn[0].dwBufferLength=no_of_channels*audio_inbuffer_size*(no_of_bits/8); //sizeof(short); + waveHeaderIn[0].dwFlags= 0; // WHDR_BEGINLOOP | WHDR_ENDLOOP; + waveHeaderIn[0].dwLoops=0; + + result=waveInPrepareHeader(hWaveIn, + &(waveHeaderIn[0]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + // waveHeaderIn[0].dwFlags= WHDR_DONE; // WHDR_BEGINLOOP | WHDR_ENDLOOP; + + waveHeaderIn[1].lpData=(char *)(WaveInBuffers[1].data()); + waveHeaderIn[1].dwBufferLength=no_of_channels*audio_inbuffer_size*(no_of_bits/8); //sizeof(short); + waveHeaderIn[1].dwFlags= 0; // WHDR_BEGINLOOP | WHDR_ENDLOOP; + waveHeaderIn[1].dwLoops=0; + + result=waveInPrepareHeader(hWaveIn, + &(waveHeaderIn[1]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + // waveHeaderIn[1].dwFlags= WHDR_DONE; // WHDR_BEGINLOOP | WHDR_ENDLOOP; + + IsRecordingNow = false; + NextBufferInInd = 0; + + return 1; //! \TODO check this also foroutput + } + + // error creating audio object + waveHeaderIn.clear(); WaveInBufferLen=0; + WaveInBuffers.clear(); + + 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) { - if (is_device_openned) + 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(); + close_PCM_device_output(); } switch (no_of_bits) @@ -173,6 +302,8 @@ long DSP::WMM_object_t::open_PCM_device_4_output(const int &no_of_channels, int if (DSP::f::AudioCheckError(result) == false) { // everything is ok + is_device_output_open = true; + waveHeaderOut.resize(DSP::NoOfAudioOutputBuffers); WaveOutBufferLen=wfx.wf.nBlockAlign*audio_outbuffer_size; WaveOutBuffers.resize(DSP::NoOfAudioOutputBuffers); @@ -206,12 +337,47 @@ long DSP::WMM_object_t::open_PCM_device_4_output(const int &no_of_channels, int 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_input(void) { + result = waveInReset(hWaveIn); + DSP::f::AudioCheckError(result); + result=waveInUnprepareHeader(hWaveIn, + &(waveHeaderIn[0]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + result=waveInUnprepareHeader(hWaveIn, + &(waveHeaderIn[1]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + + #ifdef AUDIO_DEBUG_MESSAGES_ON + DSP::log << "DSP::u::AudioInput" << DSP::e::LogMode::second << "Closing DSP::u::AudioInput" << endl; + #endif + result=waveInClose(hWaveIn); + while (result==WAVERR_STILLPLAYING) + { + // #ifdef WINBASEAPI + DSP::f::Sleep(100); + // #else + // sleep(100); + // #endif + #ifdef AUDIO_DEBUG_MESSAGES_ON + DSP::log << "DSP::u::AudioInput" << DSP::e::LogMode::second << "Closing DSP::u::AudioInput" << endl; + #endif + result=waveInClose(hWaveIn); + } + DSP::f::AudioCheckError(result); + is_device_input_open = false; -bool DSP::WMM_object_t::close_PCM_device(void) { + // 2) Free buffers + WaveInBuffers[0].clear(); + WaveInBuffers[1].clear(); + WaveInBuffers.clear(); + + waveHeaderIn.clear(); + + return true; +} + +bool DSP::WMM_object_t::close_PCM_device_output(void) { result = waveOutReset(hWaveOut); DSP::f::AudioCheckError(result); @@ -236,6 +402,8 @@ bool DSP::WMM_object_t::close_PCM_device(void) { } DSP::f::AudioCheckError(result); + is_device_output_open = false; + // 2) Free buffers WaveOutBuffers.clear(); #ifdef WINMMAPI @@ -246,9 +414,47 @@ bool DSP::WMM_object_t::close_PCM_device(void) { DSP::log << "WMM PCM sound closed" << endl; #endif + is_device_input_open = false; + NextBufferOutInd=0; + StopPlayback = false; + IsPlayingNow = false; + return true; // device has been closed } +bool DSP::WMM_object_t::start_recording(void) { + #ifdef AUDIO_DEBUG_MESSAGES_ON + 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; + } + + result=waveInAddBuffer(hWaveIn, &(waveHeaderIn[0]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + result=waveInAddBuffer(hWaveIn, &(waveHeaderIn[1]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + NextBufferInInd = 0; + + result=waveInStart(hWaveIn); + DSP::f::AudioCheckError(result); + IsRecordingNow = true; + //now just wait for buffer to fill up + // which should call waveInProc + + return true; +} + +bool DSP::WMM_object_t::is_input_callback_supported(void) { + return true; +} + +bool DSP::WMM_object_t::is_output_callback_supported(void) { + return false; +} + long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) { uint8_t *temp8; @@ -265,10 +471,10 @@ long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) while (1) { - if (waveHeaderOut[NextBufferInd].dwFlags & WHDR_DONE) + if (waveHeaderOut[NextBufferOutInd].dwFlags & WHDR_DONE) { result=waveOutUnprepareHeader(hWaveOut, - &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR)); + &(waveHeaderOut[NextBufferOutInd]), sizeof(WAVEHDR)); DSP::f::AudioCheckError(result); DSP::Float_ptr Sample=float_buffer.data(); @@ -277,7 +483,7 @@ long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) switch (OutSampleType) { case DSP::e::SampleType::ST_uchar: - temp8=(uint8_t *)(WaveOutBuffers[NextBufferInd].data()); + temp8=(uint8_t *)(WaveOutBuffers[NextBufferOutInd].data()); for (ind=0; ind<float_buffer.size(); ind++) { if (*Sample < 0) @@ -296,7 +502,7 @@ long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) } break; case DSP::e::SampleType::ST_short: - temp16=(short *)(WaveOutBuffers[NextBufferInd].data()); + temp16=(short *)(WaveOutBuffers[NextBufferOutInd].data()); for (ind=0; ind<float_buffer.size(); ind++) { if (*Sample < 0) @@ -318,12 +524,12 @@ long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) } result=waveOutPrepareHeader(hWaveOut, - &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR)); + &(waveHeaderOut[NextBufferOutInd]), sizeof(WAVEHDR)); DSP::f::AudioCheckError(result); if (IsPlayingNow == false) { - if (NextBufferInd == 1) + if (NextBufferOutInd == 1) { for (ind=0; ind < DSP::NoOfAudioOutputBuffers-1; ind++) //one spare buffer { @@ -338,11 +544,11 @@ long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) else { result=waveOutWrite(hWaveOut, - &(waveHeaderOut[NextBufferInd]), sizeof(WAVEHDR)); + &(waveHeaderOut[NextBufferOutInd]), sizeof(WAVEHDR)); DSP::f::AudioCheckError(result); } - NextBufferInd++; - NextBufferInd %= DSP::NoOfAudioOutputBuffers; + NextBufferOutInd++; + NextBufferOutInd %= DSP::NoOfAudioOutputBuffers; break; } @@ -357,4 +563,93 @@ long DSP::WMM_object_t::append_playback_buffer(DSP::Float_vector &float_buffer) } return long(float_buffer.size()); -} \ No newline at end of file +} + + +//! \bug allow user to select number of internal buffers +void CALLBACK DSP::WMM_object_t::waveInProc(HWAVEIN hwi, UINT uMsg, + uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2) +{ + UNUSED_ARGUMENT(hwi); + UNUSED_ARGUMENT(dwParam1); + UNUSED_ARGUMENT(dwParam2); + + MMRESULT result; +// DSP::u::AudioInput *Current; + DSP::WMM_object_t *Current; +#ifdef __DEBUG__ + #ifdef AUDIO_DEBUG_MESSAGES_ON + stringstream tekst; + #endif +#endif + +// Current = CallbackObjects[dwInstance]->AudioInput_object; + Current = (DSP::WMM_object_t *)(DSP::SOUND_object_t::get_CallbackSoundObject(dwInstance)); + assert(Current); + + switch (uMsg) + { +#ifdef __DEBUG__ +#ifdef AUDIO_DEBUG_MESSAGES_ON + case WIM_OPEN: + DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + << "WIM_OPEN(" << (int)dwInstance << ")" << endl; + break; + case WIM_CLOSE: + DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + << "WIM_CLOSE(" << (int)dwInstance << ")" << endl; + break; +#endif +#endif + + case WIM_DATA: +#ifdef __DEBUG__ +#ifdef AUDIO_DEBUG_MESSAGES_ON + DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second + << "WIM_DATA(" << (int)dwInstance << ")" << endl; +#endif +#endif + if (Current->StopRecording) + return; + else + { + if (Current->waveHeaderIn[Current->NextBufferInInd].dwFlags & WHDR_DONE) + { + result=waveInUnprepareHeader(Current->hWaveIn, + &(Current->waveHeaderIn[Current->NextBufferInInd]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + + if (Current->input_callback_call(Current->InSampleType, Current->WaveInBuffers[Current->NextBufferInInd]) == false) + //if (Current->EmptyBufferIndex == Current->CurrentBufferIndex) + { + // ignore data +#ifdef __DEBUG__ +#ifdef AUDIO_DEBUG_MESSAGES_ON + DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "All buffers had been used - skipping input audio frame" << endl; +#endif +#endif + } + + //add put back into recording queue + result=waveInPrepareHeader(Current->hWaveIn, + &(Current->waveHeaderIn[Current->NextBufferInInd]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + result=waveInAddBuffer(Current->hWaveIn, + &(Current->waveHeaderIn[Current->NextBufferInInd]), sizeof(WAVEHDR)); + DSP::f::AudioCheckError(result); + + Current->NextBufferInInd++; Current->NextBufferInInd %= 2; //just two buffers + } + else + { +#ifdef __DEBUG__ +#ifdef AUDIO_DEBUG_MESSAGES_ON + DSP::log << "DSP::u::AudioInput::waveInProc" << DSP::e::LogMode::second << "Wrong audio frame ready or other unexpected error" << endl; +#endif +#endif + } + } + break; // WIM_DATA + } +} + diff --git a/src/include/DSP_IO.h b/src/include/DSP_IO.h index 76cb695a23034dd8da0476a1e82c740607f016f6..faf93e23f0ae6fa898cdf53729cc9efdf786ac11 100644 --- a/src/include/DSP_IO.h +++ b/src/include/DSP_IO.h @@ -717,19 +717,23 @@ class DSP::u::AudioInput : public DSP::Source private: DSP::T_WAVEchunk WAVEchunk; #ifdef WINMMAPI - HWAVEIN hWaveIn; + // HWAVEIN hWaveIn; + DSP::WMM_object_t snd_object; #endif - //! Index of the buffer which is expected to filled next - short NextBufferInd; - //! Type of samples in WaveInBuffers - DSP::e::SampleType InSampleType; - #ifdef WINMMAPI - std::vector<WAVEHDR> waveHeaderIn; - #endif - uint32_t WaveInBufferLen; // in bytes - //! Buffers for audio samples prepared for playing - std::vector<std::vector<char>> WaveInBuffers; + //! Called by SOUND_object_t when new data buffer is ready + bool SOUND_object_callback(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer); + + // //! Index of the buffer which is expected to filled next + // short NextBufferInd; + // //! Type of samples in WaveInBuffers + // DSP::e::SampleType InSampleType; + // #ifdef WINMMAPI + // std::vector<WAVEHDR> waveHeaderIn; + // #endif + // uint32_t WaveInBufferLen; // in bytes + // //! Buffers for audio samples prepared for playing + // std::vector<std::vector<char>> WaveInBuffers; //! size of the buffers used internally with WMM driver uint32_t audio_inbuffer_size; @@ -764,28 +768,28 @@ class DSP::u::AudioInput : public DSP::Source char BitPrec=16, unsigned int WaveInDevNo=UINT_MAX); // use WAVE_MAPPER - // indicates whether the recording started yet - bool IsRecordingNow; + // // indicates whether the recording started yet + // bool IsRecordingNow; - bool StartAudio(void); - bool StopAudio(void); - bool StopRecording; + // bool StartAudio(void); + // bool StopAudio(void); + // bool StopRecording; //! (returns number of samples read per channel) uint32_t GetAudioSegment(void); - static unsigned long Next_CallbackInstance; - unsigned long Current_CallbackInstance; - //! Addresses of audio object connected with CallbackInstances; - /*! Current callback instanse is also the index to this array - */ - static std::vector<DSP::u::AudioInput *> AudioObjects; + // static unsigned long Next_CallbackInstance; + // unsigned long Current_CallbackInstance; + // //! Addresses of audio object connected with CallbackInstances; + // /*! Current callback instance is also the index to this array + // */ + // static std::vector<DSP::u::AudioInput *> AudioObjects; - #ifdef WINMMAPI - static void CALLBACK waveInProc_uchar(HWAVEIN hwi, UINT uMsg, - uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2); - static void CALLBACK waveInProc_short(HWAVEIN hwi, UINT uMsg, - uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2); - #endif + // #ifdef WINMMAPI + // static void CALLBACK waveInProc_uchar(HWAVEIN hwi, UINT uMsg, + // uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2); + // static void CALLBACK waveInProc_short(HWAVEIN hwi, UINT uMsg, + // uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2); + // #endif static bool OutputExecute(OUTPUT_EXECUTE_ARGS); @@ -863,16 +867,16 @@ class DSP::u::AudioOutput : public DSP::Block //bool IsPlayingNow; - bool StartAudio(void); - bool StopAudio(void); - bool StopPlaying; + // bool StartAudio(void); + // bool StopAudio(void); + // bool StopPlaying; - static unsigned long Next_CallbackInstance; - unsigned long Current_CallbackInstance; - //! Addresses of audio object connected with CallbackInstances; - /*! Current callback instanse is also the index to this array - */ - static std::vector<DSP::u::AudioOutput *> AudioObjects; + // static unsigned long Next_CallbackInstance; + // unsigned long Current_CallbackInstance; + // //! Addresses of audio object connected with CallbackInstances; + // /*! Current callback instanse is also the index to this array + // */ + //static std::vector<DSP::u::AudioOutput *> AudioObjects; //! (returns number of samples read per channel) uint32_t GetAudioSegment(void); diff --git a/src/include/DSP_lib.h b/src/include/DSP_lib.h index d89b1f4e1ca42b3fc9c7f767cca699242e4cf1bc..5b12ff075154758f898a4e8fcf477d9eb941b4b4 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 5 // !!! without zeroes before, else this will be treated as octal number +#define DSP_VER_BUILD 6 // !!! 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 c6b5e3d859e9efccf2c2f50bf2ba3d04868da90f..76880e79d3ac8b2929e54c6cf604f099b6cb934d 100644 --- a/src/include/DSP_types.h +++ b/src/include/DSP_types.h @@ -529,28 +529,79 @@ namespace DSP { namespace DSP { + namespace u { + class AudioInput; + class AudioOutput; + } + //! 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 { + 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); + DSP::u::AudioOutput * AudioOutput_object; + bool (DSP::u::AudioOutput::*AudioOutput_callback)(void); + + //static unsigned long Next_CallbackInstance; + unsigned long Current_CallbackInstance; + static std::vector<DSP::SOUND_object_t *> CallbackSoundObjects; + static unsigned long get_free_CallbackInstance(void); public: virtual void log_driver_data() = 0; - virtual bool select_device_by_number(const unsigned int &device_number=UINT_MAX) = 0; + 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 bool close_PCM_device(void) = 0; + virtual bool close_PCM_device_input(void) = 0; + virtual bool close_PCM_device_output(void) = 0; //! returns true is the playback is on virtual bool is_device_playing(void) = 0; + //! initializes playback stopping + 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 - long append_playback_buffer(DSP::Float_vector &float_buffer); - - virtual ~SOUND_object_t() {}; - }; + virtual long append_playback_buffer(DSP::Float_vector &float_buffer)=0; + //! Starts sound capture + 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 + */ + 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> &)); + DSP::u::AudioInput *get_input_callback_object(); + bool input_callback_call(const DSP::e::SampleType &InSampleType, const std::vector<char> &wave_in_raw_buffer); + + /*! Returns false if callbacks are not supported of 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? + */ + bool register_output_callback_object(DSP::u::AudioOutput *callback_object, bool(DSP::u::AudioOutput::*cp)()); + DSP::u::AudioOutput *get_output_callback_object(); + bool output_callback_call(); + + SOUND_object_t(); + virtual ~SOUND_object_t(); + }; } diff --git a/src/include/WMM_support.h b/src/include/WMM_support.h index 5706e99e88c2c54ebeaef4e4d21d3bce2bab37d0..c16f8c0bc331f390daba0057dbd8c441c114ce19 100644 --- a/src/include/WMM_support.h +++ b/src/include/WMM_support.h @@ -22,12 +22,13 @@ namespace DSP { class WMM_object_t : public DSP::SOUND_object_t { private: - bool is_device_openned; + bool is_device_input_open; + bool is_device_output_open; + HWAVEIN hWaveIn; HWAVEOUT hWaveOut; MMRESULT result; - DWORD_PTR Callback; //Rezerwacja pamiÄci dla formatu WAVE // WAVEFORMATEX wfx; //to wymaga korekty @@ -42,36 +43,64 @@ namespace DSP { //! Type of samples in WaveOutBuffers DSP::e::SampleType OutSampleType; //! Index of the buffer which must be used next time - unsigned long NextBufferInd; - + unsigned long NextBufferOutInd; + + bool StopPlayback; bool IsPlayingNow; static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2); + unsigned int WaveInDevNo; // device numer used in next open operations + + //! Index of the buffer which is expected to filled next + short NextBufferInInd; + //! Type of samples in WaveInBuffers + DSP::e::SampleType InSampleType; + std::vector<WAVEHDR> waveHeaderIn; + uint32_t WaveInBufferLen; // in bytes + //! Buffers for audio samples prepared for playing + std::vector<std::vector<char>> WaveInBuffers; + + static void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, uint32_t dwInstance, uint32_t dwParam1, uint32_t dwParam2); + + bool StopRecording; + // indicates whether the recording started yet + bool IsRecordingNow; + 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); + 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); //! 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); + long open_PCM_device_4_input(const int &no_of_channels, int no_of_bits, const long &sampling_rate, const long &audio_inbuffer_size); - bool close_PCM_device(void); + bool close_PCM_device_input(void); + bool close_PCM_device_output(void); + bool stop_playback(void); + bool stop_recording(void); //! returns true is the playback is on bool is_device_playing(void); + //! returns true is the playback is on + bool is_device_recording(void); + + bool is_input_callback_supported(void); + bool is_output_callback_supported(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); + bool start_recording(void); //! object constructor \TODO check use of virtual in constructor and destructor WMM_object_t();