From 30c9e5b9c64501b06e0cb8eba278e2af69d17648 Mon Sep 17 00:00:00 2001 From: Mooneer Salem Date: Mon, 26 May 2025 12:29:47 -0700 Subject: [PATCH] Remove 800XA, 700C, 2020 and 2020B. (#889) * Remove 800XA, 700C, 2020 and 2020B from UI, * Remove additional 700C references in UI. * Remove 2020/AVX detection logic from codebase. * Remove LPCNet from build scripts. * Add PR #889 to changelog. * Forgot to remove LPCNet from Windows installer generation. * Generate Release build for GH workflows. * Disable PSK Reporter reporting during test execution as invalid callsigns are used. * Build type was being overwritten. * Missed mutex removal. * Temporarily use Instruments to trace macOS CI execution. * Minor update. * Use 2 minute window in xctrace to actually capture wanted events. * Disable xctrace execution but keep in tests just in case. * Hide main window during tests to prevent GUI from interfering. * Experiment: set infifo2 max length to 30 seconds * Oops, forgot to remove division from previous commit. * Deallocation of PulseAudio stream should occur while mainloop is locked. * Revert "Hide main window during tests to prevent GUI from interfering." This reverts commit 69689bb9274de36fc2706bb62bc2a05ec3ee4fcb. * Based on online code snippets nullptr for neg is fine. * Clear PYTHONHOME if set on the user's system (Windows/macOS only). * Bring back locking in TxRxThread just in case. * Remove unneeded backslash. * Revert "Bring back locking in TxRxThread just in case." This reverts commit fc6a9f87979153ae21251dd3d9a018af07fb96f0. * Manually back out the changes instead of using git checkout. * Use shared_ptr for LinkStep. * Try removing the TX mode change mutex again. * Try moving actual codec activity out of RT context. * Fix compiler error. * Fix issue preventing legacy modes from transmitting. * Another attempt at preventing RX dropouts. * Try putting mode TX into separate threads again. * Only limit output samples if input samples were provided. * Put codec RX back into RT context. * Put TX on RT context. * Remove unused code. * Deallocation should occur only in the destructor. * Fix Windows spectrum plot formatting issues. * Prevent buffer overflow during TX/RX processing. * Bring FRAME_DURATION back down to 10ms. * We want to feed samples into the RADE/FreeDV TX/RX FIFOs regardless of whether there's room in the output. * ParallelStep should only feed FRAME_DURATION ms worth of samples at a time. * Sleep fallback should track FRAME_DURATION. * Don't execute the parallel steps if there isn't enough room in the output FIFO. * We really can only inject a portion of EOO samples at a time. * Queue EOO as a single unit to ensure it gets transmitted as a unit. * Allow ParallelStep to provide up to 4x the number of input samples as output. * Back to processing 20ms frames. * Run GH Linux tests using asan enabled. * Suppress Python related memory leaks and Hamlib related invalid memory accesses. * Forgot suppressions= in test execution. * Add more leak suppressions based on GH output. * Resolve memory leaks. * Fix broken RadeTextTest. * Additional suppressions from GH. * Go back to processing TxNumSpeechSamples every TX cycle. * Revert "Go back to processing TxNumSpeechSamples every TX cycle." This reverts commit abe816d00b9fb320f3996d285e645ec90e8359c7. * Fix 1600 mode dropouts. * Make TX single-threaded again. * Revert back to last working pipeline logic (for fullduplex_* anyway). * Revert most EOO behavior. * Run AddressSanitizer tests separately as they interfere with real time audio. * Need to start Xvfb etc. before asan tests. * Only a subset of tests need to run with asan enabled. * Fix issue causing PTT input not to work. * Maybe we don't need to restart servers after all. * Try using rtkit to ask for high priority instead of RT. * Clear FIFOs a different way. * Windows: determine minimum number of audio channels supported. --- .github/workflows/cmake-linux.yml | 17 +- .github/workflows/cmake-macos.yml | 16 +- .github/workflows/cmake-windows.yml | 2 +- CMakeLists.txt | 45 ++- USER_MANUAL.md | 1 + build_linux.sh | 43 +- build_osx.sh | 45 +-- build_signed_windows_release.sh | 2 +- cmake/BuildCodec2.cmake | 13 - cmake/BuildLPCNet.cmake | 29 -- cmake/GetDependencies.cmake.in | 18 - src/CMakeLists.txt | 18 +- src/audio/PulseAudioDevice.cpp | 50 ++- src/audio/PulseAudioDevice.h | 2 - src/audio/WASAPIAudioEngine.cpp | 20 + src/config/FreeDVConfiguration.cpp | 4 - src/config/FreeDVConfiguration.h | 6 - src/freedv_interface.cpp | 36 +- src/freedv_interface.h | 6 +- src/gui/controls/plot.h | 4 +- src/gui/dialogs/dlg_filter.cpp | 4 +- src/gui/dialogs/dlg_options.cpp | 48 +-- src/gui/dialogs/dlg_options.h | 3 - src/main.cpp | 470 ++-------------------- src/main.h | 5 - src/ongui.cpp | 12 - src/pipeline/FreeDVReceiveStep.cpp | 7 +- src/pipeline/FreeDVTransmitStep.cpp | 6 +- src/pipeline/LinkStep.cpp | 9 +- src/pipeline/ParallelStep.cpp | 12 +- src/pipeline/RADEReceiveStep.cpp | 8 +- src/pipeline/RADETransmitStep.cpp | 20 +- src/pipeline/SpeexStep.cpp | 3 +- src/pipeline/TxRxThread.cpp | 52 +-- src/pipeline/TxRxThread.h | 7 +- src/pipeline/test/RadeTextTest.cpp | 9 +- src/topFrame.cpp | 69 +--- src/topFrame.h | 14 +- src/util.cpp | 2 +- test/asan_suppressions.txt | 1 + test/freedv-ctest-reporting-mpp.conf.tmpl | 2 +- test/freedv-ctest-reporting.conf.tmpl | 2 +- test/lsan_suppressions.txt | 13 + test/test_rade_reporting.sh | 22 +- test/test_zeros.sh | 13 +- 45 files changed, 308 insertions(+), 882 deletions(-) delete mode 100644 cmake/BuildLPCNet.cmake create mode 100644 test/asan_suppressions.txt create mode 100644 test/lsan_suppressions.txt diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index df8de355..d9578818 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -59,7 +59,7 @@ jobs: working-directory: ${{github.workspace}} run: | . ./rade-venv/bin/activate - UT_ENABLE=1 ./build_linux.sh + BUILD_TYPE=RelWithDebInfo UT_ENABLE=1 ./build_linux.sh - name: Execute unit tests shell: bash @@ -83,3 +83,18 @@ jobs: . ../rade-venv/bin/activate PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V + - name: Instrument AddressSanitizer + shell: bash + working-directory: ${{github.workspace}} + run: | + . ./rade-venv/bin/activate + BUILD_TYPE=RelWithDebInfo WITH_ASAN=1 UT_ENABLE=1 ./build_linux.sh + + - name: Check for memory leaks + shell: bash + working-directory: ${{github.workspace}}/build_linux + run: | + export DISPLAY=:99.0 + export XDG_RUNTIME_DIR=/run/user/$(id -u) + . ../rade-venv/bin/activate + ASAN_OPTIONS=suppressions=${{github.workspace}}/test/asan_suppressions.txt LSAN_OPTIONS=suppressions=${{github.workspace}}/test/lsan_suppressions.txt PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V -R "fullduplex_(RADE|700D)|rade_reporting_clean" diff --git a/.github/workflows/cmake-macos.yml b/.github/workflows/cmake-macos.yml index 0cdfa5e2..55e52066 100644 --- a/.github/workflows/cmake-macos.yml +++ b/.github/workflows/cmake-macos.yml @@ -61,7 +61,7 @@ jobs: - name: Build freedv-gui shell: bash working-directory: ${{github.workspace}} - run: UT_ENABLE=1 UNIV_BUILD=0 BUILD_DEPS=0 ./build_osx.sh + run: BUILD_TYPE=RelWithDebInfo UT_ENABLE=1 UNIV_BUILD=0 BUILD_DEPS=0 ./build_osx.sh - name: Workaround macOS permission issues if: ${{ matrix.os == 'macos-13' }} @@ -81,6 +81,20 @@ jobs: run: | FREEDV_COMPUTER_TO_RADIO_DEVICE="VB-Cable" FREEDV_RADIO_TO_COMPUTER_DEVICE="VB-Cable" FREEDV_COMPUTER_TO_SPEAKER_DEVICE="BlackHole1 2ch" FREEDV_MICROPHONE_TO_COMPUTER_DEVICE="BlackHole2 2ch" ctest -V + #- name: Zip up traces + # shell: bash + # working-directory: ${{github.workspace}}/build_osx + # if: ${{ !cancelled() }} + # run: | + # zip -r InstrumentsTraces.zip instruments_trace_* + + #- name: Stash instrumented results + # uses: actions/upload-artifact@v4 + # if: ${{ !cancelled() }} + # with: + # name: InstrumentsTraces-${{matrix.os}} + # path: ${{github.workspace}}/build_osx/InstrumentsTraces.zip + # Only build and publish universal binary after making sure code works properly on both # x86 and ARM. No point in doing so if there's a failure on either. dist: diff --git a/.github/workflows/cmake-windows.yml b/.github/workflows/cmake-windows.yml index 67e7e99d..c6c11e8b 100644 --- a/.github/workflows/cmake-windows.yml +++ b/.github/workflows/cmake-windows.yml @@ -66,7 +66,7 @@ jobs: export PATH=${{github.workspace}}/llvm-mingw-20250430-ucrt-ubuntu-22.04-x86_64/bin:$PATH mkdir build_windows cd build_windows - cmake -DLPCNET_DISABLE=1 -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/cross-compile/freedv-mingw-llvm-x86_64.cmake -DPython3_ROOT_DIR=$WINEPREFIX/drive_c/Program\ Files/Python312 .. + cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/cross-compile/freedv-mingw-llvm-x86_64.cmake -DPython3_ROOT_DIR=$WINEPREFIX/drive_c/Program\ Files/Python312 .. - name: Build freedv-gui shell: bash diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d362936..ce5b9ddd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,8 +139,6 @@ set(CMAKE_VERBOSE_MAKEFILE TRUE CACHE BOOL "Verbose makefile.") set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE CACHE BOOL "Enable IDE features.") set(USE_INTERNAL_CODEC2 FALSE CACHE BOOL "Download and build codec2 instead of using the system library.") -set(BOOTSTRAP_LPCNET FALSE CACHE BOOL - "Download and build LPCNet instead of using the system library.") set(USE_STATIC_DEPS FALSE CACHE BOOL "Download and build static libraries instead of system libraries.") set(USE_STATIC_PORTAUDIO FALSE CACHE BOOL @@ -157,6 +155,14 @@ set(USE_NATIVE_AUDIO TRUE CACHE BOOL "Use native audio code instead of PortAudio for audio I/O. Defaults to true.") set(SIGN_WINDOWS_BINARIES FALSE CACHE BOOL "Enable signing of Windows binaries. See CODE_SIGNING.md for info.") +set(ENABLE_ASAN FALSE CACHE BOOL + "Instruments the build with AddressSanitizer for memory checks.") + +if(ENABLE_ASAN) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + set(CMAKE_OBJCXX_FLAGS "${CMAKE_OBJCXX_FLAGS} -fsanitize=address") +endif(ENABLE_ASAN) if(SIGN_WINDOWS_BINARIES) if(NOT WIN32 AND NOT MINGW) @@ -353,7 +359,7 @@ message(STATUS "Threads library flags: ${CMAKE_THREAD_LIBS_INIT}") include(cmake/BuildRADE.cmake) # -# Find codec2 and lpcnetfreedv +# Find codec2 # if(CODEC2_BUILD_DIR) if(USE_INTERNAL_CODEC2) @@ -373,20 +379,8 @@ if(CODEC2_BUILD_DIR) CONFIGS codec2.cmake ) get_target_property(CODEC2_INCLUDE_DIRS codec2 INTERFACE_INCLUDE_DIRECTORIES) - if(LPCNET_BUILD_DIR) - message(STATUS "Using LPCNet from build directory...") - set(lpcnet_DIR ${LPCNET_BUILD_DIR}) - find_package(lpcnet REQUIRED - NO_DEFAULT_PATH - PATHS ${LPCNET_BUILD_DIR} - CONFIGS lpcnetfreedv.cmake - ) - else() - set(LPCNET_DISABLED YES) - add_definitions(-DLPCNET_DISABLED) - endif() elseif(USE_INTERNAL_CODEC2) - message(STATUS "Will attempt internal build of codec2 and lpcnetfreedv.") + message(STATUS "Will attempt internal build of codec2.") include(cmake/BuildCodec2.cmake) else(CODEC2_BUILD_DIR) message(STATUS "Looking for codec2...") @@ -398,7 +392,6 @@ else(CODEC2_BUILD_DIR) get_target_property(CODEC2_INCLUDE_DIRS codec2 INTERFACE_INCLUDE_DIRECTORIES) message(STATUS " codec2 library: ${CODEC2_LIBRARY}") message(STATUS " codec2 headers: ${CODEC2_INCLUDE_DIRS}") - find_package(lpcnetfreedv REQUIRED) else() # Try to find manually find_path(CODEC2_INCLUDE_DIRS codec2.h @@ -410,7 +403,7 @@ else(CODEC2_BUILD_DIR) list(APPEND FREEDV_LINK_LIBS ${CODEC2_LIBRARY}) include_directories(${CODEC2_INCLUDE_DIRS}) else() - message(STATUS "Will attempt internal build of codec2 and lpcnetfreedv.") + message(STATUS "Will attempt internal build of codec2.") include(cmake/BuildCodec2.cmake) endif() endif() @@ -728,9 +721,9 @@ elseif(UNIX AND NOT APPLE) SET(CPACK_GENERATOR "DEB") SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mooneer Salem ") #required if(USE_NATIVE_AUDIO) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "codec2 (>= 1.1.1), lpcnet (>= 0.5.0), libspeexdsp1 (>= 1.2~rc1.2-1+b2), libsamplerate0 (>= 0.1.9-2), libwxgtk3.0-gtk3-0v5 (>= 3.0.4+dfsg-3), libpulse0 (>= 14.2-2), libhamlib2 (>= 3.3-10build1), libasound2 (>= 1.1.8-1), libao4 (>= 1.2.2+20180113-1), libgsm1 (>= 1.0.18-2), libsndfile1 (>= 1.0.28-6)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "codec2 (>= 1.1.1), libspeexdsp1 (>= 1.2~rc1.2-1+b2), libsamplerate0 (>= 0.1.9-2), libwxgtk3.0-gtk3-0v5 (>= 3.0.4+dfsg-3), libpulse0 (>= 14.2-2), libhamlib2 (>= 3.3-10build1), libasound2 (>= 1.1.8-1), libao4 (>= 1.2.2+20180113-1), libgsm1 (>= 1.0.18-2), libsndfile1 (>= 1.0.28-6)") else(USE_NATIVE_AUDIO) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "codec2 (>= 1.1.1), lpcnet (>= 0.5.0), libspeexdsp1 (>= 1.2~rc1.2-1+b2), libsamplerate0 (>= 0.1.9-2), libwxgtk3.0-gtk3-0v5 (>= 3.0.4+dfsg-3), libportaudio2 (>= 19.6.0-1build1), libhamlib2 (>= 3.3-10build1), libasound2 (>= 1.1.8-1), libao4 (>= 1.2.2+20180113-1), libgsm1 (>= 1.0.18-2), libsndfile1 (>= 1.0.28-6)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "codec2 (>= 1.1.1), libspeexdsp1 (>= 1.2~rc1.2-1+b2), libsamplerate0 (>= 0.1.9-2), libwxgtk3.0-gtk3-0v5 (>= 3.0.4+dfsg-3), libportaudio2 (>= 19.6.0-1build1), libhamlib2 (>= 3.3-10build1), libasound2 (>= 1.1.8-1), libao4 (>= 1.2.2+20180113-1), libgsm1 (>= 1.0.18-2), libsndfile1 (>= 1.0.28-6)") endif(USE_NATIVE_AUDIO) SET(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) @@ -744,14 +737,18 @@ if(UNITTEST) macro(DefineAudioTest utName) add_test(NAME fullduplex_${utName} COMMAND sh -c "${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx ${utName}") + if(NOT ENABLE_ASAN) set_tests_properties(fullduplex_${utName} PROPERTIES FAIL_REGULAR_EXPRESSION "Sync changed from 1 to 0") + endif(NOT ENABLE_ASAN) endmacro() DefineAudioTest(RADEV1) add_test(NAME fullduplex_RADEV1_repeated COMMAND sh -c " ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1 && ${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx RADEV1") -set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES FAIL_REGULAR_EXPRESSION "Sync changed from 1 to 0") +if(NOT ENABLE_ASAN) + set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES FAIL_REGULAR_EXPRESSION "Sync changed from 1 to 0") +endif(NOT ENABLE_ASAN) set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES DISABLED TRUE) set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES LABELS stress_test) @@ -760,12 +757,18 @@ DefineAudioTest(700E) DefineAudioTest(1600) add_test(NAME rade_reporting_clean COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test/test_rade_reporting.sh) +if(NOT ENABLE_ASAN) set_tests_properties(rade_reporting_clean PROPERTIES PASS_REGULAR_EXPRESSION "Reporting callsign ZZ0ZZZ @ SNR") +endif(NOT ENABLE_ASAN) add_test(NAME rade_reporting_awgn COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test/test_rade_reporting.sh ${CODEC2_BUILD_DIR} awgn) +if(NOT ENABLE_ASAN) set_tests_properties(rade_reporting_awgn PROPERTIES PASS_REGULAR_EXPRESSION "Reporting callsign ZZ0ZZZ @ SNR") +endif(NOT ENABLE_ASAN) add_test(NAME rade_reporting_mpp COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test/test_rade_reporting.sh ${CODEC2_BUILD_DIR} mpp) +if(NOT ENABLE_ASAN) set_tests_properties(rade_reporting_mpp PROPERTIES PASS_REGULAR_EXPRESSION "Reporting callsign ZZ0ZZZ @ SNR") +endif(NOT ENABLE_ASAN) endif(UNITTEST) diff --git a/USER_MANUAL.md b/USER_MANUAL.md index 659a01c6..4a26d45d 100644 --- a/USER_MANUAL.md +++ b/USER_MANUAL.md @@ -927,6 +927,7 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes 4. Miscellaneous: * Add issue template for SW bugs. (PR #759) * Fix typos in user manual and code. (PR #859; thanks @dforsi) + * Removed deprecated modes: 700C, 800XA, 2020, 2020B (PR #889) ## V1.9.9.2 June 2024 diff --git a/build_linux.sh b/build_linux.sh index 0b35d8de..2e571f6d 100755 --- a/build_linux.sh +++ b/build_linux.sh @@ -8,44 +8,15 @@ set -x -e UT_ENABLE=${UT_ENABLE:-0} -LPCNET_DISABLE=${LPCNET_DISABLE:-1} USE_NATIVE_AUDIO=${USE_NATIVE_AUDIO:-1} +BUILD_TYPE=${BUILD_TYPE:-Debug} +WITH_ASAN=${WITH_ASAN:-0} export FREEDVGUIDIR=${PWD} export CODEC2DIR=$FREEDVGUIDIR/codec2 -export LPCNETDIR=$FREEDVGUIDIR/LPCNet # change this when working on combined codec2/freedv-gui changes CODEC2_BRANCH=1.2.0 -LPCNET_BRANCH=v0.5 - -# OK, build and test LPCNet -cd $FREEDVGUIDIR -if [ $LPCNET_DISABLE == 0 ]; then - if [ ! -d LPCNet ]; then - git clone https://github.com/drowe67/LPCNet.git - fi - cd $LPCNETDIR && git switch master && git pull && git checkout $LPCNET_BRANCH - mkdir -p build_linux && cd build_linux && rm -Rf * - cmake .. - if [ $? == 0 ]; then - make -j$(nproc) - if [ $? == 0 ]; then - # sanity check test - cd src && sox ../../wav/wia.wav -t raw -r 16000 - | ./lpcnet_enc -s | ./lpcnet_dec -s > /dev/null - else - echo "Warning: LPCNet build failed, disabling" - LPCNET_DISABLE=1 - fi - else - echo "Warning: LPCNet build failed, disabling" - LPCNET_DISABLE=1 - fi -fi - -if [ $LPCNET_DISABLE == 0 ]; then - LPCNET_CMAKE_CMD="-DLPCNET_BUILD_DIR=$LPCNETDIR/build_linux" -fi # First build and install vanilla codec2 as we need -lcodec2 to build LPCNet cd $FREEDVGUIDIR @@ -53,13 +24,7 @@ if [ ! -d codec2 ]; then git clone https://github.com/drowe67/codec2.git fi cd codec2 && git switch main && git pull && git checkout $CODEC2_BRANCH -mkdir -p build_linux && cd build_linux && rm -Rf * && cmake $LPCNET_CMAKE_CMD .. && make VERBOSE=1 -j$(nproc) -if [ $LPCNET_DISABLE == 0 ]; then - # sanity check test - cd src - export LD_LIBRARY_PATH=$LPCNETDIR/build_linux/src - ./freedv_tx 2020 $LPCNETDIR/wav/wia.wav - | ./freedv_rx 2020 - /dev/null -fi +mkdir -p build_linux && cd build_linux && rm -Rf * && cmake .. && make VERBOSE=1 -j$(nproc) # Finally, build freedv-gui cd $FREEDVGUIDIR @@ -67,5 +32,5 @@ if [ -d .git ]; then git pull fi mkdir -p build_linux && cd build_linux && rm -Rf * -cmake -DUSE_NATIVE_AUDIO=$USE_NATIVE_AUDIO -DUNITTEST=$UT_ENABLE -DCMAKE_BUILD_TYPE=Debug -DCODEC2_BUILD_DIR=$CODEC2DIR/build_linux $LPCNET_CMAKE_CMD .. +cmake -DENABLE_ASAN=${WITH_ASAN} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DUSE_NATIVE_AUDIO=$USE_NATIVE_AUDIO -DUNITTEST=$UT_ENABLE -DCODEC2_BUILD_DIR=$CODEC2DIR/build_linux .. make VERBOSE=1 -j$(nproc) diff --git a/build_osx.sh b/build_osx.sh index e9076b6e..09f45c99 100755 --- a/build_osx.sh +++ b/build_osx.sh @@ -6,16 +6,14 @@ export FREEDVGUIDIR=${PWD} export CODEC2DIR=$FREEDVGUIDIR/codec2 -export LPCNETDIR=$FREEDVGUIDIR/LPCNet export HAMLIBDIR=$FREEDVGUIDIR/hamlib export CODEC2_BRANCH=1.2.0 -export LPCNET_BRANCH=v0.5 export UT_ENABLE=${UT_ENABLE:-0} -export LPCNET_DISABLE=${LPCNET_DISABLE:-1} export UNIV_BUILD=${UNIV_BUILD:-1} export CODESIGN_IDENTITY=${CODESIGN_IDENTITY:--} export BUILD_DEPS=${BUILD_DEPS:-1} export USE_NATIVE_AUDIO=${USE_NATIVE_AUDIO:-1} +export BUILD_TYPE=${BUILD_TYPE:-Debug} # Prerequisite: build dylibbundler if [ ! -d macdylibbundler ]; then @@ -56,46 +54,13 @@ if [ $BUILD_DEPS == 1 ]; then make install fi -# OK, build and test LPCNet -cd $FREEDVGUIDIR -if [ $LPCNET_DISABLE == 0 ]; then - if [ ! -d LPCNet ]; then - git clone https://github.com/drowe67/LPCNet.git - fi - cd $LPCNETDIR && git checkout master && git pull && git checkout $LPCNET_BRANCH - mkdir -p build_osx && cd build_osx && rm -Rf * - cmake -DBUILD_OSX_UNIVERSAL=${UNIV_BUILD} .. - if [ $? == 0 ]; then - make -j$(sysctl -n hw.logicalcpu) - if [ $? == 0 ]; then - # sanity check test - cd src && sox ../../wav/wia.wav -t raw -r 16000 - | ./lpcnet_enc -s | ./lpcnet_dec -s > /dev/null - else - echo "Warning: LPCNet build failed, disabling" - LPCNET_DISABLE=1 - fi - else - echo "Warning: LPCNet build failed, disabling" - LPCNET_DISABLE=1 - fi -fi - -if [ $LPCNET_DISABLE == 0 ]; then - LPCNET_CMAKE_CMD="-DLPCNET_BUILD_DIR=$LPCNETDIR/build_osx" -fi - -# Build codec2 with LPCNet and test FreeDV 2020 support +# Build codec2 cd $FREEDVGUIDIR if [ ! -d codec2 ]; then git clone https://github.com/drowe67/codec2-new.git codec2 fi cd codec2 && git switch main && git pull && git checkout $CODEC2_BRANCH -mkdir -p build_osx && cd build_osx && rm -Rf * && cmake ${LPCNET_CMAKE_CMD} -DBUILD_OSX_UNIVERSAL=${UNIV_BUILD} .. && make VERBOSE=1 -j$(sysctl -n hw.logicalcpu) - -# sanity check test -cd src -export LD_LIBRARY_PATH=$LPCNETDIR/build_osx/src -./freedv_tx 2020 $LPCNETDIR/wav/wia.wav - | ./freedv_rx 2020 - /dev/null +mkdir -p build_osx && cd build_osx && rm -Rf * && cmake -DBUILD_OSX_UNIVERSAL=${UNIV_BUILD} .. && make VERBOSE=1 -j$(sysctl -n hw.logicalcpu) # Finally, build freedv-gui cd $FREEDVGUIDIR @@ -109,9 +74,9 @@ if [ "$CODESIGN_KEYCHAIN_PROFILE" != "" ]; then fi if [ $BUILD_DEPS == 1 ]; then - cmake -DUSE_NATIVE_AUDIO=$USE_NATIVE_AUDIO -DPython3_ROOT_DIR=$PWD/../Python.framework/Versions/3.12 -DBUILD_OSX_UNIVERSAL=${UNIV_BUILD} -DUNITTEST=$UT_ENABLE -DCMAKE_BUILD_TYPE=Debug -DBOOTSTRAP_WXWIDGETS=1 -DUSE_STATIC_SPEEXDSP=1 -DUSE_STATIC_PORTAUDIO=1 -DUSE_STATIC_SAMPLERATE=1 -DUSE_STATIC_SNDFILE=1 -DHAMLIB_INCLUDE_DIR=${HAMLIBDIR}/include -DHAMLIB_LIBRARY=${HAMLIBDIR}/lib/libhamlib.dylib -DCODEC2_BUILD_DIR=$CODEC2DIR/build_osx ${LPCNET_CMAKE_CMD} -DMACOS_CODESIGN_IDENTITY=${CODESIGN_IDENTITY} ${CODESIGN_KEYCHAIN_PROFILE_ARG} .. + cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DUSE_NATIVE_AUDIO=$USE_NATIVE_AUDIO -DPython3_ROOT_DIR=$PWD/../Python.framework/Versions/3.12 -DBUILD_OSX_UNIVERSAL=${UNIV_BUILD} -DUNITTEST=$UT_ENABLE -DBOOTSTRAP_WXWIDGETS=1 -DUSE_STATIC_SPEEXDSP=1 -DUSE_STATIC_PORTAUDIO=1 -DUSE_STATIC_SAMPLERATE=1 -DUSE_STATIC_SNDFILE=1 -DHAMLIB_INCLUDE_DIR=${HAMLIBDIR}/include -DHAMLIB_LIBRARY=${HAMLIBDIR}/lib/libhamlib.dylib -DCODEC2_BUILD_DIR=$CODEC2DIR/build_osx -DMACOS_CODESIGN_IDENTITY=${CODESIGN_IDENTITY} ${CODESIGN_KEYCHAIN_PROFILE_ARG} .. else - cmake -DUSE_NATIVE_AUDIO=$USE_NATIVE_AUDIO -DPython3_ROOT_DIR=$PWD/../Python.framework/Versions/3.12 -DBUILD_OSX_UNIVERSAL=${UNIV_BUILD} -DUNITTEST=$UT_ENABLE -DCMAKE_BUILD_TYPE=Debug -DCODEC2_BUILD_DIR=$CODEC2DIR/build_osx ${LPCNET_CMAKE_CMD} -DMACOS_CODESIGN_IDENTITY=${CODESIGN_IDENTITY} ${CODESIGN_KEYCHAIN_PROFILE_ARG} .. + cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DUSE_NATIVE_AUDIO=$USE_NATIVE_AUDIO -DPython3_ROOT_DIR=$PWD/../Python.framework/Versions/3.12 -DBUILD_OSX_UNIVERSAL=${UNIV_BUILD} -DUNITTEST=$UT_ENABLE -DCODEC2_BUILD_DIR=$CODEC2DIR/build_osx -DMACOS_CODESIGN_IDENTITY=${CODESIGN_IDENTITY} ${CODESIGN_KEYCHAIN_PROFILE_ARG} .. fi make VERBOSE=1 -j$(sysctl -n hw.logicalcpu) diff --git a/build_signed_windows_release.sh b/build_signed_windows_release.sh index acbda1e0..56fe2f72 100755 --- a/build_signed_windows_release.sh +++ b/build_signed_windows_release.sh @@ -42,7 +42,7 @@ for arch in x86_64; do cd $BUILD_ARCH_DIR # Kick off new build with the given architecture - cmake -DLPCNET_DISABLE=1 -DPython3_ROOT_DIR=`pwd`/../wine-env/drive_c/Program\ Files/Python312 -DSIGN_WINDOWS_BINARIES=1 -DPKCS11_CERTIFICATE_FILE=$CERT_URL_FILE -DPKCS11_KEY_FILE=$KEY_URL_FILE -DINTERMEDIATE_CERT_FILE=$INTERMEDIATE_CERT_FILE -DCMAKE_TOOLCHAIN_FILE=$SCRIPT_DIR/cross-compile/freedv-mingw-llvm-$arch.cmake $SCRIPT_DIR + cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPython3_ROOT_DIR=`pwd`/../wine-env/drive_c/Program\ Files/Python312 -DSIGN_WINDOWS_BINARIES=1 -DPKCS11_CERTIFICATE_FILE=$CERT_URL_FILE -DPKCS11_KEY_FILE=$KEY_URL_FILE -DINTERMEDIATE_CERT_FILE=$INTERMEDIATE_CERT_FILE -DCMAKE_TOOLCHAIN_FILE=$SCRIPT_DIR/cross-compile/freedv-mingw-llvm-$arch.cmake $SCRIPT_DIR make -j$(nproc) package cp FreeDV-*.exe $WIN_BUILD_DIR cd $WIN_BUILD_DIR diff --git a/cmake/BuildCodec2.cmake b/cmake/BuildCodec2.cmake index 3bb00152..e36057ae 100644 --- a/cmake/BuildCodec2.cmake +++ b/cmake/BuildCodec2.cmake @@ -8,15 +8,6 @@ if(BUILD_OSX_UNIVERSAL) set(CODEC2_CMAKE_ARGS ${CODEC2_CMAKE_ARGS} -DBUILD_OSX_UNIVERSAL=1) endif(BUILD_OSX_UNIVERSAL) -# Bootstrap lpcnetfreedv library -if(BOOTSTRAP_LPCNET) - include(cmake/BuildLPCNet.cmake) - set(CODEC2_CMAKE_ARGS ${CODEC2_CMAKE_ARGS} -DLPCNET_BUILD_DIR=${CMAKE_BINARY_DIR}/LPCNet_build) -else(BOOTSTRAP_LPCNET) - add_definitions(-DLPCNET_DISABLED) - set(LPCNET_DISABLED YES) -endif(BOOTSTRAP_LPCNET) - # Build codec2 library with lpcnetfreedv include(ExternalProject) ExternalProject_Add(build_codec2 @@ -40,9 +31,5 @@ set_target_properties(codec2 PROPERTIES set(CODEC2_BUILD_DIR ${BINARY_DIR}) -if(BOOTSTRAP_LPCNET) -add_dependencies(build_codec2 build_lpcnetfreedv) -endif(BOOTSTRAP_LPCNET) - set(CODEC2_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/codec2_src/src ${CMAKE_BINARY_DIR}/codec2_build) include_directories(${CODEC2_INCLUDE_DIRS}) diff --git a/cmake/BuildLPCNet.cmake b/cmake/BuildLPCNet.cmake deleted file mode 100644 index e9769cd7..00000000 --- a/cmake/BuildLPCNet.cmake +++ /dev/null @@ -1,29 +0,0 @@ -if(CMAKE_CROSSCOMPILING) - set(LPCNET_CMAKE_ARGS ${LPCNET_CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}) -endif() - -if(BUILD_OSX_UNIVERSAL) - set(LPCNET_CMAKE_ARGS ${LPCNET_CMAKE_ARGS} -DBUILD_OSX_UNIVERSAL=1) -endif(BUILD_OSX_UNIVERSAL) - -include(ExternalProject) -ExternalProject_Add(build_lpcnetfreedv - SOURCE_DIR LPCNet_src - BINARY_DIR LPCNet_build - GIT_REPOSITORY https://github.com/drowe67/LPCNet.git - GIT_TAG v0.5 - CMAKE_ARGS ${LPCNET_CMAKE_ARGS} - CMAKE_CACHE_ARGS -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} - INSTALL_COMMAND "" -) - -ExternalProject_Get_Property(build_lpcnetfreedv BINARY_DIR) -ExternalProject_Get_Property(build_lpcnetfreedv SOURCE_DIR) -add_library(lpcnetfreedv SHARED IMPORTED) - -set_target_properties(lpcnetfreedv PROPERTIES - IMPORTED_LOCATION "${BINARY_DIR}/src/liblpcnetfreedv${CMAKE_SHARED_LIBRARY_SUFFIX}" - IMPORTED_IMPLIB "${BINARY_DIR}/src/liblpcnetfreedv${CMAKE_IMPORT_LIBRARY_SUFFIX}" -) - -include_directories(${SOURCE_DIR}/src) diff --git a/cmake/GetDependencies.cmake.in b/cmake/GetDependencies.cmake.in index eb5f9121..12fac76e 100644 --- a/cmake/GetDependencies.cmake.in +++ b/cmake/GetDependencies.cmake.in @@ -10,17 +10,10 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES @CMAKE_FIND_LIBRARY_SUFFIXES@) set(CMAKE_FIND_LIBRARY_PREFIXES @CMAKE_FIND_LIBRARY_PREFIXES@) set(CMAKE_SYSTEM_LIBRARY_PATH @CMAKE_SYSTEM_LIBRARY_PATH@) set(CMAKE_FIND_ROOT_PATH @CMAKE_FIND_ROOT_PATH@) -set(LPCNET_DISABLED @LPCNET_DISABLED@) if(USE_INTERNAL_CODEC2) set(CODEC2_BUILD_DIR ${CMAKE_BINARY_DIR}/codec2_build) - if(NOT LPCNET_DISABLED) - set(LPCNET_BUILD_DIR ${CMAKE_BINARY_DIR}/LPCNet_build) - endif(NOT LPCNET_DISABLED) else() set(CODEC2_BUILD_DIR @CODEC2_BUILD_DIR@) - if(NOT LPCNET_DISABLED) - set(LPCNET_BUILD_DIR @LPCNET_BUILD_DIR@) - endif(NOT LPCNET_DISABLED) endif() @@ -140,17 +133,6 @@ if(CODEC2_BUILD_DIR) freedv_sign_dependency(${CODEC2_FINAL} ${CMAKE_INSTALL_PREFIX}/bin/libcodec2.dll) endif() -if(LPCNET_BUILD_DIR) - list(REMOVE_ITEM _deps liblpcnetfreedv.dll) - find_library(LPCNET lpcnetfreedv NO_DEFAULT_PATH PATHS ${LPCNET_BUILD_DIR}/src REQUIRED) - string(REPLACE ".a" "" LPCNET_FINAL ${LPCNET}) - - message("Found: liblpcnetfreedv.dll") - #file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" - # TYPE EXECUTABLE FILES ${LPCNET_FINAL}) - - freedv_sign_dependency(${LPCNET_FINAL} ${CMAKE_INSTALL_PREFIX}/bin/liblpcnetfreedv.dll) -endif() if(FREEDV_USING_LLVM_MINGW) # Use the bin/ folder for the platform as an additional diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be90f311..38b3b262 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,18 +53,11 @@ else() add_executable(freedv WIN32 ${FREEDV_SOURCES} ${RES_FILES}) endif(APPLE) -# Link imported or build tree targets. -if(NOT LPCNET_DISABLED) -set(LPCNET_LIB_NAME lpcnetfreedv) -else(NOT LPCNET_DISABLED) -set(LPCNET_LIB_NAME ) -endif(NOT LPCNET_DISABLED) - if(APPLE) -target_link_libraries(FreeDV fdv_audio fdv_audio_pipeline fdv_config fdv_gui_controls fdv_gui_dialogs fdv_gui_util fdv_os_wrapper fdv_rig_control fdv_reporting fdv_sox fdv_util ${LPCNET_LIB_NAME} codec2 rade opus) +target_link_libraries(FreeDV fdv_audio fdv_audio_pipeline fdv_config fdv_gui_controls fdv_gui_dialogs fdv_gui_util fdv_os_wrapper fdv_rig_control fdv_reporting fdv_sox fdv_util codec2 rade opus) add_dependencies(FreeDV build_rade) else(APPLE) -target_link_libraries(freedv fdv_audio fdv_audio_pipeline fdv_config fdv_gui_controls fdv_gui_dialogs fdv_gui_util fdv_os_wrapper fdv_rig_control fdv_reporting fdv_sox fdv_util ${LPCNET_LIB_NAME} codec2 rade opus) +target_link_libraries(freedv fdv_audio fdv_audio_pipeline fdv_config fdv_gui_controls fdv_gui_dialogs fdv_gui_util fdv_os_wrapper fdv_rig_control fdv_reporting fdv_sox fdv_util codec2 rade opus) add_dependencies(freedv build_rade) endif(APPLE) @@ -141,11 +134,6 @@ endif(APPLE) # Custom commands to build OSX images. if(APPLE) - if(NOT LPCNET_DISABLE) - set(LPCNET_DYLIBBUNDLER_PATH ${LPCNET_BUILD_DIR}/src:) - set(LPCNET_DYLIBBUNDLER_ARG -s ${LPCNET_BUILD_DIR}/src) - endif(NOT LPCNET_DISABLE) - if(NOT MACOS_CODESIGN_IDENTITY) set(MACOS_CODESIGN_IDENTITY -) endif(NOT MACOS_CODESIGN_IDENTITY) @@ -158,7 +146,7 @@ if(APPLE) TARGET FreeDV POST_BUILD COMMAND rm -rf dist_tmp FreeDV.dmg || true - COMMAND DYLD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src:${LPCNET_DYLIBBUNDLER_PATH}${portaudio_BINARY_DIR}:${samplerate_BINARY_DIR}/src:${Python3_ROOT_DIR}:${DYLD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/macdylibbundler/dylibbundler ARGS -od -b -x FreeDV.app/Contents/MacOS/FreeDV -d FreeDV.app/Contents/libs -p @loader_path/../libs/ -i /usr/lib ${LPCNET_DYLIBBUNDLER_ARG} -s ${CODEC2_BUILD_DIR}/src -s ${CMAKE_BINARY_DIR}/LPCNet_build/src -s ${CMAKE_BINARY_DIR}/codec2_build/src ${PORTAUDIO_BUNDLE_ARG} -s ${samplerate_BINARY_DIR}/src -s ${rade_BINARY_DIR}/src -s ${Python3_ROOT_DIR} + COMMAND DYLD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src:${portaudio_BINARY_DIR}:${samplerate_BINARY_DIR}/src:${Python3_ROOT_DIR}:${DYLD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/macdylibbundler/dylibbundler ARGS -od -b -x FreeDV.app/Contents/MacOS/FreeDV -d FreeDV.app/Contents/libs -p @loader_path/../libs/ -i /usr/lib -s ${CODEC2_BUILD_DIR}/src -s ${CMAKE_BINARY_DIR}/codec2_build/src ${PORTAUDIO_BUNDLE_ARG} -s ${samplerate_BINARY_DIR}/src -s ${rade_BINARY_DIR}/src -s ${Python3_ROOT_DIR} COMMAND cp ARGS ${CMAKE_CURRENT_SOURCE_DIR}/freedv.icns FreeDV.app/Contents/Resources COMMAND rm ARGS -rf FreeDV.app/Contents/Frameworks COMMAND mkdir ARGS FreeDV.app/Contents/Frameworks diff --git a/src/audio/PulseAudioDevice.cpp b/src/audio/PulseAudioDevice.cpp index eb606e71..1458ccc4 100644 --- a/src/audio/PulseAudioDevice.cpp +++ b/src/audio/PulseAudioDevice.cpp @@ -154,17 +154,18 @@ void PulseAudioDevice::stop() { if (stream_ != nullptr) { - std::unique_lock lk(streamStateMutex_); - pa_threaded_mainloop_lock(mainloop_); + + // Disconnect stream and wait for response from mainloop. pa_stream_disconnect(stream_); + pa_threaded_mainloop_wait(mainloop_); + + // Deallocate stream. + pa_stream_unref(stream_); + stream_ = nullptr; + pa_threaded_mainloop_unlock(mainloop_); - streamStateCondVar_.wait(lk); - - pa_stream_unref(stream_); - - stream_ = nullptr; sem_destroy(&sem_); } } @@ -175,8 +176,7 @@ int PulseAudioDevice::getLatencyInMicroseconds() pa_usec_t latency = 0; if (stream_ != nullptr) { - int neg = 0; - pa_stream_get_latency(stream_, &latency, &neg); // ignore error and assume 0 + pa_stream_get_latency(stream_, &latency, nullptr); // ignore error and assume 0 } pa_threaded_mainloop_unlock(mainloop_); return (int)latency; @@ -245,6 +245,35 @@ void PulseAudioDevice::setHelperRealTime() sigaddset(&signal_set, SIGXCPU); sigprocmask(SIG_UNBLOCK, &signal_set, NULL); #endif // 0 + +#if defined(USE_RTKIT) + DBusError error; + DBusConnection* bus = nullptr; + int result = 0; + + dbus_error_init(&error); + if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) + { + log_warn("Could not connect to system bus: %s", error.message); + } + else + { + int minNiceLevel = 0; + if ((result = rtkit_get_min_nice_level(bus, &minNiceLevel)) < 0) + { + log_warn("rtkit could not get minimum nice level: %s", strerror(-result)); + } + else if ((result = rtkit_make_high_priority(bus, 0, minNiceLevel)) < 0) + { + log_warn("rtkit could not make high priority: %s", strerror(-result)); + } + } + + if (bus != nullptr) + { + dbus_connection_unref(bus); + } +#endif // defined(USE_RTKIT) } void PulseAudioDevice::startRealTimeWork() @@ -356,8 +385,7 @@ void PulseAudioDevice::StreamStateCallback_(pa_stream *p, void *userdata) // does not accidentally refer to already freed memory. if (pa_stream_get_state(p) == PA_STREAM_TERMINATED) { - std::unique_lock lk(thisObj->streamStateMutex_); - thisObj->streamStateCondVar_.notify_all(); + pa_threaded_mainloop_signal(thisObj->mainloop_, 0); } } diff --git a/src/audio/PulseAudioDevice.h b/src/audio/PulseAudioDevice.h index 5d1c9e59..c680ecc2 100644 --- a/src/audio/PulseAudioDevice.h +++ b/src/audio/PulseAudioDevice.h @@ -81,8 +81,6 @@ private: IAudioEngine::AudioDirection direction_; int sampleRate_; int numChannels_; - std::mutex streamStateMutex_; - std::condition_variable streamStateCondVar_; thread_local static std::chrono::high_resolution_clock::time_point StartTime_; thread_local static bool MustStopWork_; diff --git a/src/audio/WASAPIAudioEngine.cpp b/src/audio/WASAPIAudioEngine.cpp index 647a0378..7960331b 100644 --- a/src/audio/WASAPIAudioEngine.cpp +++ b/src/audio/WASAPIAudioEngine.cpp @@ -419,6 +419,26 @@ AudioDeviceSpecification WASAPIAudioEngine::getDeviceSpecification_(IMMDevice* d spec.defaultSampleRate = streamFormat->nSamplesPerSec; spec.maxChannels = streamFormat->nChannels; spec.minChannels = streamFormat->nChannels; + + // Determine minimum number of channels supported. + for (int channel = spec.maxChannels - 1; channel >= 1; channel--) + { + WAVEFORMATEX* closestFormat = nullptr; + streamFormat->nChannels = channel; + if (audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, streamFormat, &closestFormat) == S_OK) + { + spec.minChannels = channel; + } + if (closestFormat != nullptr) + { + CoTaskMemFree(closestFormat); + } + + if (spec.minChannels != channel) + { + break; + } + } CoTaskMemFree(streamFormat); audioClient->Release(); diff --git a/src/config/FreeDVConfiguration.cpp b/src/config/FreeDVConfiguration.cpp index b0858478..d9628546 100644 --- a/src/config/FreeDVConfiguration.cpp +++ b/src/config/FreeDVConfiguration.cpp @@ -29,8 +29,6 @@ FreeDVConfiguration::FreeDVConfiguration() /* First time configuration options */ : firstTimeUse("/FirstTimeUse", true) - , freedv2020Allowed("/FreeDV2020/Allowed", false) - , freedvAVXSupported("/FreeDV2020/AVXSupported", false) /* Position and size of main window */ , mainWindowLeft("/MainFrame/left", 20) @@ -127,7 +125,6 @@ void FreeDVConfiguration::load(wxConfigBase* config) reportingConfiguration.load(config); load_(config, firstTimeUse); - load_(config, freedv2020Allowed); load_(config, mainWindowLeft); load_(config, mainWindowTop); @@ -252,7 +249,6 @@ void FreeDVConfiguration::save(wxConfigBase* config) reportingConfiguration.save(config); save_(config, firstTimeUse); - save_(config, freedv2020Allowed); save_(config, mainWindowLeft); save_(config, mainWindowTop); diff --git a/src/config/FreeDVConfiguration.h b/src/config/FreeDVConfiguration.h index e9fb48d8..3dce43cd 100644 --- a/src/config/FreeDVConfiguration.h +++ b/src/config/FreeDVConfiguration.h @@ -42,12 +42,6 @@ public: ReportingConfiguration reportingConfiguration; ConfigurationDataElement firstTimeUse; - ConfigurationDataElement freedv2020Allowed; - - // Note: this isn't loaded/saved in persistent storage since it's - // possible for the hardware to change since the first run (i.e. if - // the hard drive is moved to a new machine or a previous backup is restored.) - ConfigurationDataElement freedvAVXSupported; ConfigurationDataElement mainWindowLeft; ConfigurationDataElement mainWindowTop; diff --git a/src/freedv_interface.cpp b/src/freedv_interface.cpp index 5c495ad0..119aaa2e 100644 --- a/src/freedv_interface.cpp +++ b/src/freedv_interface.cpp @@ -41,22 +41,12 @@ static const char* GetCurrentModeStrImpl_(int mode) { switch(mode) { - case FREEDV_MODE_700C: - return "700C"; case FREEDV_MODE_700D: return "700D"; case FREEDV_MODE_700E: return "700E"; case FREEDV_MODE_1600: return "1600"; - case FREEDV_MODE_2020: - return "2020"; -#if defined(FREEDV_MODE_2020B) - case FREEDV_MODE_2020B: - return "2020B"; -#endif // FREEDV_MODE_2020B - case FREEDV_MODE_800XA: - return "800XA"; case FREEDV_MODE_RADE: return "RADEV1"; default: @@ -126,18 +116,12 @@ float FreeDVInterface::GetMinimumSNR_(int mode) { switch(mode) { - case FREEDV_MODE_700C: - return 2.0; case FREEDV_MODE_700D: return -2.0f; case FREEDV_MODE_700E: return 1.0f; case FREEDV_MODE_1600: return 4.0f; - case FREEDV_MODE_2020: - return 2.0f; - case FREEDV_MODE_800XA: - return 2.0f; default: return 0.0f; } @@ -552,7 +536,8 @@ int FreeDVInterface::getTxNNomModemSamples() const { if (txMode_ >= FREEDV_MODE_RADE) { - return rade_n_tx_out(rade_); + const int NUM_SAMPLES_SILENCE = 60 * RADE_MODEM_SAMPLE_RATE / 1000; + return std::max(rade_n_tx_out(rade_), rade_n_tx_eoo_out(rade_) + NUM_SAMPLES_SILENCE); } assert(currentTxMode_ != nullptr); @@ -719,7 +704,11 @@ float FreeDVInterface::getSNREstimate() } } -IPipelineStep* FreeDVInterface::createTransmitPipeline(int inputSampleRate, int outputSampleRate, std::function getFreqOffsetFn) +IPipelineStep* FreeDVInterface::createTransmitPipeline( + int inputSampleRate, + int outputSampleRate, + std::function getFreqOffsetFn, + std::shared_ptr realtimeHelper) { std::vector parallelSteps; @@ -738,13 +727,16 @@ IPipelineStep* FreeDVInterface::createTransmitPipeline(int inputSampleRate, int std::function modeFn = [&](ParallelStep*) { int index = 0; - + + auto currentTxMode = currentTxMode_; + auto txModeInt = txMode_; + // Special handling for RADE. - if (txMode_ >= FREEDV_MODE_RADE) return 0; + if (txModeInt >= FREEDV_MODE_RADE) return 0; for (auto& dv : dvObjects_) { - if (dv == currentTxMode_) return index; + if (dv == currentTxMode) return index; index++; } return -1; @@ -758,7 +750,7 @@ IPipelineStep* FreeDVInterface::createTransmitPipeline(int inputSampleRate, int modeFn, parallelSteps, nullptr, - nullptr + realtimeHelper ); return parallelStep; diff --git a/src/freedv_interface.h b/src/freedv_interface.h index 2f527d4e..36530691 100644 --- a/src/freedv_interface.h +++ b/src/freedv_interface.h @@ -126,7 +126,11 @@ public: const char* getReliableText(); void setReliableText(const char* callsign); - IPipelineStep* createTransmitPipeline(int inputSampleRate, int outputSampleRate, std::function getFreqOffsetFn); + IPipelineStep* createTransmitPipeline( + int inputSampleRate, + int outputSampleRate, + std::function getFreqOffsetFn, + std::shared_ptr realtimeHelper); IPipelineStep* createReceivePipeline( int inputSampleRate, int outputSampleRate, std::function getRxStateFn, diff --git a/src/gui/controls/plot.h b/src/gui/controls/plot.h index 2052ede1..d95a0e68 100644 --- a/src/gui/controls/plot.h +++ b/src/gui/controls/plot.h @@ -44,10 +44,10 @@ #define wxUSE_LIBTIFF 1 #define PLOT_BORDER 12 -#define XLEFT_OFFSET 40 +#define XLEFT_OFFSET 50 #define XLEFT_TEXT_OFFSET 6 #define YBOTTOM_OFFSET 20 -#define YBOTTOM_TEXT_OFFSET 15 +#define YBOTTOM_TEXT_OFFSET 5 #define GRID_INCREMENT 50 #define BLACK_COLOR wxColor(0x00, 0x00, 0x00) diff --git a/src/gui/dialogs/dlg_filter.cpp b/src/gui/dialogs/dlg_filter.cpp index 2b980417..9a8e1195 100644 --- a/src/gui/dialogs/dlg_filter.cpp +++ b/src/gui/dialogs/dlg_filter.cpp @@ -104,9 +104,9 @@ FilterDlg::FilterDlg(wxWindow* parent, bool running, bool *newMicInFilter, bool sbSizer_speexpp->Add(m_ckboxSpeexpp, 0, wxALL | wxALIGN_LEFT, 5); m_ckboxSpeexpp->SetToolTip(_("Enable noise suppression, dereverberation, AGC of mic signal")); - m_ckbox700C_EQ = new wxCheckBox(sb_speexpp, wxID_ANY, _("700C/700D/700E/800XA Auto EQ"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); + m_ckbox700C_EQ = new wxCheckBox(sb_speexpp, wxID_ANY, _("700D/700E Auto EQ"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); sbSizer_speexpp->Add(m_ckbox700C_EQ, 0, wxALL | wxALIGN_LEFT, 5); - m_ckbox700C_EQ->SetToolTip(_("Automatic equalisation for FreeDV 700C/700D/700E Codec input audio")); + m_ckbox700C_EQ->SetToolTip(_("Automatic equalisation for FreeDV 700D/700E Codec input audio")); bSizer30->Add(sbSizer_speexpp, 0, wxALL | wxEXPAND, 5); diff --git a/src/gui/dialogs/dlg_options.cpp b/src/gui/dialogs/dlg_options.cpp index c4403e95..8a159565 100644 --- a/src/gui/dialogs/dlg_options.cpp +++ b/src/gui/dialogs/dlg_options.cpp @@ -420,9 +420,6 @@ OptionsDlg::OptionsDlg(wxWindow* parent, wxWindowID id, const wxString& title, c m_ckboxFreeDV700txClip = new wxCheckBox(m_modemTab, wxID_ANY, _("Clipping"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); sbSizer_freedv700->Add(m_ckboxFreeDV700txClip, 0, wxALL | wxALIGN_LEFT, 5); - m_ckboxFreeDV700Combine = new wxCheckBox(m_modemTab, wxID_ANY, _("700C Diversity Combine"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); - sbSizer_freedv700->Add(m_ckboxFreeDV700Combine, 0, wxALL | wxALIGN_LEFT, 5); - m_ckboxFreeDV700txBPF = new wxCheckBox(m_modemTab, wxID_ANY, _("TX Band Pass Filter"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); sbSizer_freedv700->Add(m_ckboxFreeDV700txBPF, 0, wxALL | wxALIGN_LEFT, 5); @@ -672,8 +669,7 @@ OptionsDlg::OptionsDlg(wxWindow* parent, wxWindowID id, const wxString& title, c m_buttonChooseVoiceKeyerWaveFilePath->MoveBeforeInTabOrder(m_txtCtrlVoiceKeyerRxPause); m_txtCtrlVoiceKeyerRxPause->MoveBeforeInTabOrder(m_txtCtrlVoiceKeyerRepeats); - m_ckboxFreeDV700txClip->MoveBeforeInTabOrder(m_ckboxFreeDV700Combine); - m_ckboxFreeDV700Combine->MoveBeforeInTabOrder(m_ckboxFreeDV700txBPF); + m_ckboxFreeDV700txClip->MoveBeforeInTabOrder(m_ckboxFreeDV700txBPF); m_ckboxFreeDV700txBPF->MoveBeforeInTabOrder(m_ckHalfDuplex); m_ckHalfDuplex->MoveBeforeInTabOrder(m_ckboxMultipleRx); m_ckboxMultipleRx->MoveBeforeInTabOrder(m_ckboxSingleRxThread); @@ -725,10 +721,8 @@ OptionsDlg::OptionsDlg(wxWindow* parent, wxWindowID id, const wxString& title, c m_ckboxTestFrame->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnTestFrame), NULL, this); m_ckboxChannelNoise->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnChannelNoise), NULL, this); - m_ckboxAttnCarrierEn->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnAttnCarrierEn), NULL, this); m_ckboxFreeDV700txClip->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700txClip), NULL, this); - m_ckboxFreeDV700Combine->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700Combine), NULL, this); #ifdef __WXMSW__ m_ckboxDebugConsole->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnDebugConsole), NULL, this); @@ -777,10 +771,8 @@ OptionsDlg::~OptionsDlg() m_ckboxTestFrame->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnTestFrame), NULL, this); m_ckboxChannelNoise->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnChannelNoise), NULL, this); - m_ckboxAttnCarrierEn->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnAttnCarrierEn), NULL, this); m_ckboxFreeDV700txClip->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700txClip), NULL, this); - m_ckboxFreeDV700Combine->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700Combine), NULL, this); m_buttonChooseVoiceKeyerWaveFilePath->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnChooseVoiceKeyerWaveFilePath), NULL, this); m_buttonChooseQuickRecordPath->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnChooseQuickRecordPath), NULL, this); @@ -884,7 +876,6 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) m_ckboxFreeDV700txClip->SetValue(wxGetApp().appConfiguration.freedv700Clip); m_ckboxFreeDV700txBPF->SetValue(wxGetApp().appConfiguration.freedv700TxBPF); - m_ckboxFreeDV700Combine->SetValue(wxGetApp().m_FreeDV700Combine); #ifdef __WXMSW__ m_ckboxDebugConsole->SetValue(wxGetApp().appConfiguration.debugConsoleEnabled); @@ -1062,7 +1053,6 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) wxGetApp().appConfiguration.freedv700Clip = m_ckboxFreeDV700txClip->GetValue(); wxGetApp().appConfiguration.freedv700TxBPF = m_ckboxFreeDV700txBPF->GetValue(); - wxGetApp().m_FreeDV700Combine = m_ckboxFreeDV700Combine->GetValue(); #ifdef __WXMSW__ wxGetApp().appConfiguration.debugConsoleEnabled = m_ckboxDebugConsole->GetValue(); @@ -1232,46 +1222,10 @@ void OptionsDlg::OnChooseQuickRecordPath(wxCommandEvent& event) { m_txtCtrlQuickRecordPath->SetValue(pathDialog.GetPath()); } -// Run time update of carrier amplitude attenuation - -void OptionsDlg::OnAttnCarrierEn(wxScrollEvent& event) { - if (freedvInterface.isRunning()) - { - long attn_carrier; - m_txtAttnCarrier->GetValue().ToLong(&attn_carrier); - wxGetApp().m_attn_carrier = (int)attn_carrier; - - /* uncheck -> checked, attenuate selected carrier */ - - if (m_ckboxAttnCarrierEn->GetValue() && !wxGetApp().m_attn_carrier_en) { - if (freedvInterface.isModeActive(FREEDV_MODE_700C)) { - freedvInterface.setCarrierAmplitude(wxGetApp().m_attn_carrier, 0.25); - } else { - wxMessageBox("Carrier attenuation feature only works on 700C", wxT("Warning"), wxOK | wxICON_WARNING, this); - } - } - - /* checked -> unchecked, reset selected carrier */ - - if (!m_ckboxAttnCarrierEn->GetValue() && wxGetApp().m_attn_carrier_en) { - if (freedvInterface.isModeActive(FREEDV_MODE_700C)) { - freedvInterface.setCarrierAmplitude(wxGetApp().m_attn_carrier, 1.0); - } - } - } - - wxGetApp().m_attn_carrier_en = m_ckboxAttnCarrierEn->GetValue(); - updateAttnCarrierState(); -} - void OptionsDlg::OnFreeDV700txClip(wxScrollEvent& event) { wxGetApp().appConfiguration.freedv700Clip = m_ckboxFreeDV700txClip->GetValue(); } -void OptionsDlg::OnFreeDV700Combine(wxScrollEvent& event) { - wxGetApp().m_FreeDV700Combine = m_ckboxFreeDV700Combine->GetValue(); -} - void OptionsDlg::OnDebugConsole(wxScrollEvent& event) { wxGetApp().appConfiguration.debugConsoleEnabled = m_ckboxDebugConsole->GetValue(); #ifdef __WXMSW__ diff --git a/src/gui/dialogs/dlg_options.h b/src/gui/dialogs/dlg_options.h index 2ad17b3e..bc851ecd 100644 --- a/src/gui/dialogs/dlg_options.h +++ b/src/gui/dialogs/dlg_options.h @@ -63,9 +63,7 @@ class OptionsDlg : public wxDialog void OnTestFrame(wxScrollEvent& event); void OnChannelNoise(wxScrollEvent& event); - void OnAttnCarrierEn(wxScrollEvent& event); void OnFreeDV700txClip(wxScrollEvent& event); - void OnFreeDV700Combine(wxScrollEvent& event); void OnDebugConsole(wxScrollEvent& event); void OnFifoReset(wxCommandEvent& event); @@ -135,7 +133,6 @@ class OptionsDlg : public wxDialog wxCheckBox *m_ckboxFreeDV700txClip; wxCheckBox *m_ckboxFreeDV700txBPF; - wxCheckBox *m_ckboxFreeDV700Combine; wxRadioButton *m_rb_textEncoding1; wxRadioButton *m_rb_textEncoding2; diff --git a/src/main.cpp b/src/main.cpp index d79c32d6..a9492877 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -241,16 +241,12 @@ void MainApp::UnitTest_() // Wait 100ms for FreeDV to come to foreground std::this_thread::sleep_for(100ms); - // Select FreeDV mode. Note, 2020 is deprecated so not testable here. + // Select FreeDV mode. wxRadioButton* modeBtn = nullptr; if (utFreeDVMode == "RADEV1") { modeBtn = frame->m_rbRADE; } - /*else if (utFreeDVMode == "700C") - { - modeBtn = frame->m_rb700c; - }*/ else if (utFreeDVMode == "700D") { modeBtn = frame->m_rb700d; @@ -259,10 +255,6 @@ void MainApp::UnitTest_() { modeBtn = frame->m_rb700e; } - /*else if (utFreeDVMode == "800XA") - { - modeBtn = frame->m_rb800xa; - }*/ else if (utFreeDVMode == "1600") { modeBtn = frame->m_rb1600; @@ -548,6 +540,11 @@ bool MainApp::OnInit() wxString appPath(f.GetPath()); wxSetWorkingDirectory(appPath); + // Make sure PYTHONHOME is not set. If it is, it may use the user's + // local Python installation for stuff like torch/torchaudio, causing + // problems running RADE. + wxUnsetEnv("PYTHONHOME"); + #if __APPLE__ // Set PYTHONPATH accordingly. We mainly want to be able to access // the model (,pth) as well as the RADE Python code. @@ -615,126 +612,6 @@ int MainApp::OnExit() return 0; } -#if defined(FREEDV_MODE_2020) -bool MainFrame::test2020HWAllowed_() -{ - bool allowed = true; - -#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) - // AVX checking code on x86 is here due to LPCNet in binary builds being - // compiled to use it. Running the sanity check below could potentially - // cause crashes. - uint32_t eax, ebx, ecx, edx; - eax = ebx = ecx = edx = 0; - __cpuid(1, eax, ebx, ecx, edx); - - if (ecx & (1<<27) && ecx & (1<<28)) { - // CPU supports XSAVE and AVX - uint32_t xcr0, xcr0_high; - asm("xgetbv" : "=a" (xcr0), "=d" (xcr0_high) : "c" (0)); - allowed = (xcr0 & 6) == 6; // AVX state saving enabled? - } else { - allowed = false; - } -#endif // defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) - - return allowed; -} - -//------------------------------------------------------------------------- -// test2020Mode_(): Makes sure that 2020 mode will work -//------------------------------------------------------------------------- -void MainFrame::test2020Mode_() -{ - log_info("Making sure your machine can handle 2020 mode..."); - - bool allowed = false; - -#if !defined(LPCNET_DISABLED) - allowed = test2020HWAllowed_(); - wxGetApp().appConfiguration.freedvAVXSupported = allowed; - - if (!allowed) - { - log_warn("Warning: AVX support not found!"); - } - else - { - // Sanity check: encode 1 second of 16 kHz white noise and then try to - // decode it. If it takes longer than 0.5 seconds, it's unlikely that - // 2020/2020B will work properly on this machine. - log_info("Generating test audio..."); - struct FIFO* inFifo = codec2_fifo_create(24000); - assert(inFifo != nullptr); - - struct freedv* fdv = freedv_open(FREEDV_MODE_2020); - assert(fdv != nullptr); - - int numInSamples = 0; - int samplesToGenerate = freedv_get_n_speech_samples(fdv); - int samplesGenerated = freedv_get_n_nom_modem_samples(fdv); - - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> distrib(SHRT_MIN, SHRT_MAX); - - while (numInSamples < 16000) - { - short inSamples[samplesToGenerate]; - COMP outSamples[samplesGenerated]; - for (int index = 0; index < samplesToGenerate; index++) - { - inSamples[index] = distrib(gen); - } - - freedv_comptx(fdv, outSamples, inSamples); - - for (int index = 0; index < samplesGenerated; index++) - { - short realVal = outSamples[index].real; - codec2_fifo_write(inFifo, &realVal, 1); - } - - numInSamples += samplesToGenerate; - } - - log_info("Decoding modulated audio..."); - - std::chrono::high_resolution_clock systemClock; - auto startTime = systemClock.now(); - - int nin = freedv_nin(fdv); - short inputBuf[freedv_get_n_max_modem_samples(fdv)]; - short outputBuf[freedv_get_n_speech_samples(fdv)]; - COMP rx_fdm[freedv_get_n_max_modem_samples(fdv)]; - while(codec2_fifo_read(inFifo, inputBuf, nin) == 0) - { - for(int i=0; i(endTime - startTime); - if (timeTaken > std::chrono::milliseconds(600)) - { - allowed = false; - } - - log_info("One second of 2020 decoded in %d ms", (int)timeTaken.count()); - } -#endif // !defined(LPCNET_DISABLED) - - log_info("2020 allowed: %d", (int)allowed); - - // Save results to configuration. - wxGetApp().appConfiguration.freedv2020Allowed = allowed; -} -#endif // defined(FREEDV_MODE_2020) - //------------------------------------------------------------------------- // loadConfiguration_(): Loads or sets default configuration options. //------------------------------------------------------------------------- @@ -873,10 +750,6 @@ setDefaultMode: { m_rb1600->SetValue(1); } - else if (mode == 3) - { - m_rb700c->SetValue(1); - } else if (mode == 4) { m_rb700d->SetValue(1); @@ -885,25 +758,10 @@ setDefaultMode: { m_rb700e->SetValue(1); } - else if (mode == 6) - { - m_rb800xa->SetValue(1); - } - // mode 7 was the former 2400B mode, now removed. - else if ((mode == 9) && wxGetApp().appConfiguration.freedv2020Allowed && wxGetApp().appConfiguration.freedvAVXSupported) - { - m_rb2020->SetValue(1); - } else if (mode == FREEDV_MODE_RADE) { m_rbRADE->SetValue(1); } -#if defined(FREEDV_MODE_2020B) - else if ((mode == 10) && wxGetApp().appConfiguration.freedv2020Allowed && wxGetApp().appConfiguration.freedvAVXSupported) - { - m_rb2020b->SetValue(1); - } -#endif // defined(FREEDV_MODE_2020B) else { // Default to RADE otherwise @@ -912,21 +770,6 @@ setDefaultMode: } pConfig->SetPath(wxT("/")); - // Set initial state of additional modes. - switch(mode) - { - case 0: - case 4: - case 5: - // 700D/E and 1600; don't expand additional modes - break; - default: - m_collpane->Collapse(false); - wxCollapsiblePaneEvent evt; - OnChangeCollapseState(evt); - break; - } - m_togBtnAnalog->Disable(); m_btnTogPTT->Disable(); m_togBtnVoiceKeyer->Disable(); @@ -1287,29 +1130,6 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent, wxID_ANY, _("FreeDV ") // Print RADE API version. This also forces the RADE library to be linked. log_info("Using RADE API version %d", rade_version()); -#if defined(FREEDV_MODE_2020) && !defined(LPCNET_DISABLED) - // First time use: make sure 2020 mode will actually work on this machine. - if (wxGetApp().appConfiguration.firstTimeUse) - { - test2020Mode_(); - } - else - { - wxGetApp().appConfiguration.freedvAVXSupported = test2020HWAllowed_(); - } -#else - // Disable LPCNet if not compiled in. - wxGetApp().appConfiguration.freedv2020Allowed = false; -#endif // defined(FREEDV_MODE_2020) && !defined(LPCNET_DISABLED) - - if(!wxGetApp().appConfiguration.freedv2020Allowed || !wxGetApp().appConfiguration.freedvAVXSupported) - { - m_rb2020->Disable(); -#if defined(FREEDV_MODE_2020B) - m_rb2020b->Disable(); -#endif // FREEDV_MODE_2020B - } - if (wxGetApp().appConfiguration.firstTimeUse) { // Initial setup. Display Easy Setup dialog. @@ -1415,22 +1235,12 @@ MainFrame::~MainFrame() int mode; if (m_rb1600->GetValue()) mode = 0; - if (m_rb700c->GetValue()) - mode = 3; if (m_rb700d->GetValue()) mode = 4; if (m_rb700e->GetValue()) mode = 5; - if (m_rb800xa->GetValue()) - mode = 6; - if (m_rb2020->GetValue()) - mode = 9; if (m_rbRADE->GetValue()) mode = FREEDV_MODE_RADE; -#if defined(FREEDV_MODE_2020B) - if (m_rb2020b->GetValue()) - mode = 10; -#endif // defined(FREEDV_MODE_2020B) wxGetApp().appConfiguration.currentFreeDVMode = mode; wxGetApp().appConfiguration.save(pConfig); @@ -1539,7 +1349,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt) } else { - int r,c; + int r; if (m_panelWaterfall->checkDT()) { m_panelWaterfall->setRxFreq(FDMDV_FCENTRE - g_RxFreqOffsetHz); @@ -1575,92 +1385,30 @@ void MainFrame::OnTimer(wxTimerEvent &evt) } wxGetApp().m_prevMode = currentMode; - if (currentMode == FREEDV_MODE_800XA) { - - /* FSK Mode - eye diagram ---------------------------------------------------------*/ - - /* add samples row by row */ - - int i; - for (i=0; ineyetr; i++) { - m_panelScatter->add_new_samples_eye(&freedvInterface.getCurrentRxModemStats()->rx_eye[i][0], freedvInterface.getCurrentRxModemStats()->neyesamp); - } + // Reset g_Nc accordingly. + switch(currentMode) + { + case FREEDV_MODE_1600: + g_Nc = 16; + m_panelScatter->setNc(g_Nc+1); /* +1 for BPSK pilot */ + break; + case FREEDV_MODE_700D: + case FREEDV_MODE_700E: + g_Nc = 17; + m_panelScatter->setNc(g_Nc); + break; } - else { - // Reset g_Nc accordingly. - switch(currentMode) - { - case FREEDV_MODE_1600: - g_Nc = 16; - m_panelScatter->setNc(g_Nc+1); /* +1 for BPSK pilot */ - break; - case FREEDV_MODE_700C: - /* m_FreeDV700Combine may have changed at run time */ - g_Nc = 14; - if (wxGetApp().m_FreeDV700Combine) { - m_panelScatter->setNc(g_Nc/2); /* diversity combnation */ - } - else { - m_panelScatter->setNc(g_Nc); - } - break; - case FREEDV_MODE_700D: - case FREEDV_MODE_700E: - g_Nc = 17; - m_panelScatter->setNc(g_Nc); - break; - case FREEDV_MODE_2020: - #if defined(FREEDV_MODE_2020B) - case FREEDV_MODE_2020B: - #endif // FREEDV_MODE_2020B - g_Nc = 31; - m_panelScatter->setNc(g_Nc); - break; + + /* PSK Modes - scatter plot -------------------------------------------------------*/ + for (r=0; rnr; r++) { + + if ((currentMode == FREEDV_MODE_1600) || + (currentMode == FREEDV_MODE_700D) || + (currentMode == FREEDV_MODE_700E) + ) { + m_panelScatter->add_new_samples_scatter(&freedvInterface.getCurrentRxModemStats()->rx_symbols[r][0]); } - - /* PSK Modes - scatter plot -------------------------------------------------------*/ - for (r=0; rnr; r++) { - if ((currentMode == FREEDV_MODE_1600) || - (currentMode == FREEDV_MODE_700D) || - (currentMode == FREEDV_MODE_700E) || - (currentMode == FREEDV_MODE_2020) - #if defined(FREEDV_MODE_2020B) - || (currentMode == FREEDV_MODE_2020B) - #endif // FREEDV_MODE_2020B - ) { - m_panelScatter->add_new_samples_scatter(&freedvInterface.getCurrentRxModemStats()->rx_symbols[r][0]); - } - else if (currentMode == FREEDV_MODE_700C) { - - if (wxGetApp().m_FreeDV700Combine) { - /* - FreeDV 700C uses diversity, so optionally combine - symbols for scatter plot, as combined symbols are - used for demodulation. Note we need to use a copy - of the symbols, as we are not sure when the stats - will be updated. - */ - - COMP* rx_symbols_copy = new COMP[g_Nc/2]; - assert(rx_symbols_copy != nullptr); - - for(c=0; crx_symbols[r][c], freedvInterface.getCurrentRxModemStats()->rx_symbols[r][c+g_Nc/2])); - m_panelScatter->add_new_samples_scatter(rx_symbols_copy); - - delete[] rx_symbols_copy; - } - else { - /* - Sometimes useful to plot carriers separately, e.g. to determine if tx carrier power is constant - across carriers. - */ - m_panelScatter->add_new_samples_scatter(&freedvInterface.getCurrentRxModemStats()->rx_symbols[r][0]); - } - } - - } } } @@ -2090,7 +1838,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt) snprintf(syncmetric, STR_LENGTH, "Sync: %3.2f", freedvInterface.getCurrentRxModemStats()->sync_metric); wxString syncmetric_string(syncmetric); m_textSyncMetric->SetLabel(syncmetric_string); - // Codec 2 700C/D/E & 800XA VQ "auto EQ" equaliser variance + // Codec 2 700D/E "auto EQ" equaliser variance auto var = freedvInterface.getVariance(); char var_str[STR_LENGTH]; snprintf(var_str, STR_LENGTH, "Var: %4.1f", var); wxString var_string(var_str); m_textCodec2Var->SetLabel(var_string); @@ -2132,47 +1880,6 @@ void MainFrame::OnTimer(wxTimerEvent &evt) m_panelTestFrameErrorsHist->add_new_samples(0, ber, 2*MODEM_STATS_NC_MAX); } - if ((freedvInterface.getCurrentMode() == FREEDV_MODE_700C)) { - int c; - - /* - FreeDV 700 mapping from error pattern to bit on each carrier, see - data bit to carrier mapping in: - - codec2-dev/octave/cohpsk_frame_design.ods - - We can plot a histogram of the errors/carrier before or after diversity - recombination. Actually one bar for each IQ bit in carrier order. - */ - - int hist_Nc = sz_error_pattern/4; - - for(i=0; iadd_new_sample(c, c + 0.8*error_pattern[i]); - g_error_hist[c] += error_pattern[i]; - g_error_histn[c]++; - } - for(; i<2*MODEM_STATS_NC_MAX*4; i++) { - c = floor(i/4); - m_panelTestFrameErrors->add_new_sample(c, c); - } - - /* calculate BERs and send to plot */ - - float ber[2*MODEM_STATS_NC_MAX]; - for(b=0; b<2*MODEM_STATS_NC_MAX; b++) { - ber[b] = 0.0; - } - for(b=0; badd_new_samples(0, ber, 2*MODEM_STATS_NC_MAX); - } - m_panelTestFrameErrors->Refresh(); m_panelTestFrameErrorsHist->Refresh(); @@ -2253,50 +1960,13 @@ void MainFrame::OnExit(wxCommandEvent& event) void MainFrame::OnChangeTxMode( wxCommandEvent& event ) { - wxRadioButton* hiddenModeToSet = nullptr; - std::vector buttonsToClear - { - m_hiddenMode1, - m_hiddenMode2, - - m_rbRADE, - m_rb700c, - m_rb700d, - m_rb700e, - m_rb800xa, - m_rb1600, - m_rb2020, -#if defined(FREEDV_MODE_2020B) - m_rb2020b, -#endif // FREEDV_MODE_2020B - }; - auto eventObject = (wxRadioButton*)event.GetEventObject(); - if (eventObject != nullptr) - { - std::string label = (const char*)eventObject->GetLabel().ToUTF8(); - if (label == "700D" || label == "700E" || label == "1600" || label == "RADEV1") - { - hiddenModeToSet = m_hiddenMode2; - } - else - { - hiddenModeToSet = m_hiddenMode1; - } - - buttonsToClear.erase(std::find(buttonsToClear.begin(), buttonsToClear.end(), (wxRadioButton*)eventObject)); - } - txModeChangeMutex.Lock(); if (eventObject == m_rb1600 || (eventObject == nullptr && m_rb1600->GetValue())) { g_mode = FREEDV_MODE_1600; } - else if (eventObject == m_rb700c || (eventObject == nullptr && m_rb700c->GetValue())) - { - g_mode = FREEDV_MODE_700C; - } else if (eventObject == m_rbRADE || (eventObject == nullptr && m_rbRADE->GetValue())) { g_mode = FREEDV_MODE_RADE; @@ -2309,24 +1979,6 @@ void MainFrame::OnChangeTxMode( wxCommandEvent& event ) { g_mode = FREEDV_MODE_700E; } - else if (eventObject == m_rb800xa || (eventObject == nullptr && m_rb800xa->GetValue())) - { - g_mode = FREEDV_MODE_800XA; - } - else if (eventObject == m_rb2020 || (eventObject == nullptr && m_rb2020->GetValue())) - { - assert(wxGetApp().appConfiguration.freedv2020Allowed && wxGetApp().appConfiguration.freedvAVXSupported); - - g_mode = FREEDV_MODE_2020; - } -#if defined(FREEDV_MODE_2020B) - else if (eventObject == m_rb2020b || (eventObject == nullptr && m_rb2020b->GetValue())) - { - assert(wxGetApp().appConfiguration.freedv2020Allowed && wxGetApp().appConfiguration.freedvAVXSupported); - - g_mode = FREEDV_MODE_2020B; - } -#endif // FREEDV_MODE_2020B if (freedvInterface.isRunning()) { @@ -2340,21 +1992,6 @@ void MainFrame::OnChangeTxMode( wxCommandEvent& event ) txModeChangeMutex.Unlock(); - // Manually implement mutually exclusive behavior as - // we can't rely on wxWidgets doing it on account of - // how we're splitting the modes. - if (eventObject != nullptr) - { - buttonsToClear.erase(std::find(buttonsToClear.begin(), buttonsToClear.end(), hiddenModeToSet)); - - for (auto& var : buttonsToClear) - { - var->SetValue(false); - } - - hiddenModeToSet->SetValue(true); - } - // Report TX change to registered reporters for (auto& obj : wxGetApp().m_reporters) { @@ -2404,34 +2041,18 @@ void MainFrame::performFreeDVOn_() { m_rb1600->Disable(); m_rbRADE->Disable(); - m_rb700c->Disable(); m_rb700d->Disable(); m_rb700e->Disable(); - m_rb800xa->Disable(); - m_rb2020->Disable(); - #if defined(FREEDV_MODE_2020B) - m_rb2020b->Disable(); - #endif // FREEDV_MODE_2020B freedvInterface.addRxMode(g_mode); } else { m_rbRADE->Disable(); - - if(wxGetApp().appConfiguration.freedv2020Allowed && wxGetApp().appConfiguration.freedvAVXSupported) - { - freedvInterface.addRxMode(FREEDV_MODE_2020); - #if defined(FREEDV_MODE_2020B) - freedvInterface.addRxMode(FREEDV_MODE_2020B); - #endif // FREEDV_MODE_2020B - } - + int rxModes[] = { FREEDV_MODE_1600, FREEDV_MODE_700E, - FREEDV_MODE_700C, FREEDV_MODE_700D, - FREEDV_MODE_800XA }; for (auto& mode : rxModes) @@ -2444,14 +2065,8 @@ void MainFrame::performFreeDVOn_() { m_rb1600->Disable(); m_rbRADE->Disable(); - m_rb700c->Disable(); m_rb700d->Disable(); m_rb700e->Disable(); - m_rb800xa->Disable(); - m_rb2020->Disable(); - #if defined(FREEDV_MODE_2020B) - m_rb2020b->Disable(); - #endif // FREEDV_MODE_2020B } } @@ -2511,13 +2126,7 @@ void MainFrame::performFreeDVOn_() if (!wxGetApp().appConfiguration.reportingConfiguration.reportingEnabled) freedvInterface.setTextVaricodeNum(1); - // scatter plot (PSK) or Eye (FSK) mode - if (g_mode == FREEDV_MODE_800XA) { - m_panelScatter->setEyeScatter(PLOT_SCATTER_MODE_EYE); - } - else { - m_panelScatter->setEyeScatter(PLOT_SCATTER_MODE_SCATTER); - } + m_panelScatter->setEyeScatter(PLOT_SCATTER_MODE_SCATTER); }); g_State = g_prev_State = 0; @@ -2738,17 +2347,8 @@ void MainFrame::performFreeDVOff_() m_rbRADE->Enable(); m_rb1600->Enable(); - m_rb700c->Enable(); m_rb700d->Enable(); m_rb700e->Enable(); - m_rb800xa->Enable(); - if(wxGetApp().appConfiguration.freedv2020Allowed && wxGetApp().appConfiguration.freedvAVXSupported) - { - m_rb2020->Enable(); - #if defined(FREEDV_MODE_2020B) - m_rb2020b->Enable(); - #endif // FREEDV_MODE_2020B - } // Make sure QSY button becomes disabled after stop. if (m_reporterDialog != nullptr) @@ -3158,7 +2758,7 @@ void MainFrame::startRxStream() // stats for spectral plots, and transmit processng are all performed // in the tx/rxProcessing loop. // - // Note that soundCard1InFifoSizeSamples is significantly larger than + // Note that soundCard[12]InFifoSizeSamples are significantly larger than // the other FIFO sizes. This is to better handle PulseAudio/pipewire // behavior on some devices, where the system sends multiple *seconds* // of audio samples at once followed by long periods with no samples at @@ -3171,7 +2771,7 @@ void MainFrame::startRxStream() if (txInSoundDevice && txOutSoundDevice) { - int soundCard2InFifoSizeSamples = m_fifoSize_ms*wxGetApp().appConfiguration.audioConfiguration.soundCard2In.sampleRate / 1000; + int soundCard2InFifoSizeSamples = 30*wxGetApp().appConfiguration.audioConfiguration.soundCard2In.sampleRate; int soundCard2OutFifoSizeSamples = m_fifoSize_ms*wxGetApp().appConfiguration.audioConfiguration.soundCard2Out.sampleRate / 1000; g_rxUserdata->outfifo1 = codec2_fifo_create(soundCard1OutFifoSizeSamples); g_rxUserdata->infifo2 = codec2_fifo_create(soundCard2InFifoSizeSamples); @@ -3447,7 +3047,7 @@ void MainFrame::startRxStream() // start tx/rx processing thread if (txInSoundDevice && txOutSoundDevice) { - m_txThread = new TxRxThread(true, txInSoundDevice->getSampleRate(), txOutSoundDevice->getSampleRate(), wxGetApp().linkStep.get(), txInSoundDevice); + m_txThread = new TxRxThread(true, txInSoundDevice->getSampleRate(), txOutSoundDevice->getSampleRate(), wxGetApp().linkStep, txInSoundDevice); if ( m_txThread->Create() != wxTHREAD_NO_ERROR ) { wxLogError(wxT("Can't create TX thread!")); @@ -3486,7 +3086,7 @@ void MainFrame::startRxStream() } } - m_rxThread = new TxRxThread(false, rxInSoundDevice->getSampleRate(), rxOutSoundDevice->getSampleRate(), wxGetApp().linkStep.get(), rxInSoundDevice); + m_rxThread = new TxRxThread(false, rxInSoundDevice->getSampleRate(), rxOutSoundDevice->getSampleRate(), wxGetApp().linkStep, rxInSoundDevice); if ( m_rxThread->Create() != wxTHREAD_NO_ERROR ) { wxLogError(wxT("Can't create RX thread!")); diff --git a/src/main.h b/src/main.h index df81502c..ab840581 100644 --- a/src/main.h +++ b/src/main.h @@ -505,11 +505,6 @@ class MainFrame : public TopFrame void resetStats_(); HamlibRigController::Mode getCurrentMode_(); - -#if defined(FREEDV_MODE_2020) - void test2020Mode_(); - bool test2020HWAllowed_(); -#endif // defined(FREEDV_MODE_2020) void performFreeDVOn_(); void performFreeDVOff_(); diff --git a/src/ongui.cpp b/src/ongui.cpp index 4d22fbda..9fbdf7dc 100644 --- a/src/ongui.cpp +++ b/src/ongui.cpp @@ -9,9 +9,6 @@ #include #include "main.h" -#if !defined(LPCNET_DISABLED) -#include "lpcnet_freedv.h" -#endif // defined(LPCNET_DISABLED) #include "gui/dialogs/dlg_easy_setup.h" #include "gui/dialogs/dlg_filter.h" @@ -363,13 +360,7 @@ void MainFrame::OnHelpAbout(wxCommandEvent& event) wxT("freedv-gui version: %s\n") wxT("freedv-gui git hash: %s\n") wxT("codec2 git hash: %s\n") -#if !defined(LPCNET_DISABLED) - wxT("lpcnet git hash: %s\n") -#endif // !defined(LPCNET_DISABLED) , FREEDV_VERSION, FREEDV_VERSION, GIT_HASH, freedv_get_hash() -#if !defined(LPCNET_DISABLED) - , lpcnet_get_hash() -#endif // !defined(LPCNET_DISABLED) ); wxMessageBox(msg, wxT("About"), wxOK | wxICON_INFORMATION, this); @@ -1303,9 +1294,6 @@ void MainFrame::OnSystemColorChanged(wxSysColourChangedEvent& event) // Works around issues on wxWidgets with certain controls not changing backgrounds // when the user switches between light and dark mode. wxColour currentControlBackground = wxTransparentColour; - - m_collpane->SetBackgroundColour(currentControlBackground); - m_collpane->GetPane()->SetBackgroundColour(currentControlBackground); TopFrame::OnSystemColorChanged(event); } diff --git a/src/pipeline/FreeDVReceiveStep.cpp b/src/pipeline/FreeDVReceiveStep.cpp index e3b1586f..d7c9d6ef 100644 --- a/src/pipeline/FreeDVReceiveStep.cpp +++ b/src/pipeline/FreeDVReceiveStep.cpp @@ -65,10 +65,11 @@ FreeDVReceiveStep::~FreeDVReceiveStep() delete[] inputBuf_; delete[] rxFdm_; delete[] rxFdmOffset_; + outputSamples_ = nullptr; if (inputSampleFifo_ != nullptr) { - codec2_fifo_free(inputSampleFifo_); + codec2_fifo_destroy(inputSampleFifo_); } } @@ -84,6 +85,8 @@ int FreeDVReceiveStep::getOutputSampleRate() const std::shared_ptr FreeDVReceiveStep::execute(std::shared_ptr inputSamples, int numInputSamples, int* numOutputSamples) { + auto maxSamples = std::max(getInputSampleRate(), getOutputSampleRate()); + auto maxSpeechSamples = freedv_get_n_max_speech_samples(dv_); *numOutputSamples = 0; short* inputPtr = inputSamples.get(); @@ -94,7 +97,7 @@ std::shared_ptr FreeDVReceiveStep::execute(std::shared_ptr inputSa int nin = freedv_nin(dv_); int nout = 0; - while (codec2_fifo_read(inputSampleFifo_, inputBuf_, nin) == 0) + while ((*numOutputSamples + maxSpeechSamples) < maxSamples && codec2_fifo_read(inputSampleFifo_, inputBuf_, nin) == 0) { assert(nin <= freedv_get_n_max_modem_samples(dv_)); diff --git a/src/pipeline/FreeDVTransmitStep.cpp b/src/pipeline/FreeDVTransmitStep.cpp index 06452da7..1f234803 100644 --- a/src/pipeline/FreeDVTransmitStep.cpp +++ b/src/pipeline/FreeDVTransmitStep.cpp @@ -68,10 +68,11 @@ FreeDVTransmitStep::~FreeDVTransmitStep() delete[] codecInput_; delete[] txFdm_; delete[] txFdmOffset_; + delete[] tmpOutput_; if (inputSampleFifo_ != nullptr) { - codec2_fifo_free(inputSampleFifo_); + codec2_fifo_destroy(inputSampleFifo_); } } @@ -87,6 +88,7 @@ int FreeDVTransmitStep::getOutputSampleRate() const std::shared_ptr FreeDVTransmitStep::execute(std::shared_ptr inputSamples, int numInputSamples, int* numOutputSamples) { + auto maxSamples = std::max(getInputSampleRate(), getOutputSampleRate()); int mode = freedv_get_mode(dv_); int samplesUsedForFifo = freedv_get_n_speech_samples(dv_); int nfreedv = freedv_get_n_nom_modem_samples(dv_); @@ -99,7 +101,7 @@ std::shared_ptr FreeDVTransmitStep::execute(std::shared_ptr inputS codec2_fifo_write(inputSampleFifo_, inputPtr++, 1); numInputSamples--; - if (codec2_fifo_used(inputSampleFifo_) >= samplesUsedForFifo) + if ((*numOutputSamples + nfreedv) < maxSamples && codec2_fifo_used(inputSampleFifo_) >= samplesUsedForFifo) { codec2_fifo_read(inputSampleFifo_, codecInput_, samplesUsedForFifo); diff --git a/src/pipeline/LinkStep.cpp b/src/pipeline/LinkStep.cpp index da096cea..ae92a660 100644 --- a/src/pipeline/LinkStep.cpp +++ b/src/pipeline/LinkStep.cpp @@ -47,11 +47,12 @@ LinkStep::~LinkStep() } void LinkStep::clearFifo() -{ - int numUsed = codec2_fifo_used(fifo_); - +{ // Read data and then promptly throw it out. - codec2_fifo_read(fifo_, tmpBuffer_, numUsed); + while (codec2_fifo_used(fifo_) > 0) + { + codec2_fifo_read(fifo_, tmpBuffer_, 1); + } } std::shared_ptr LinkStep::InputStep::execute(std::shared_ptr inputSamples, int numInputSamples, int* numOutputSamples) diff --git a/src/pipeline/ParallelStep.cpp b/src/pipeline/ParallelStep.cpp index 5c8636dd..c5273b99 100644 --- a/src/pipeline/ParallelStep.cpp +++ b/src/pipeline/ParallelStep.cpp @@ -24,6 +24,7 @@ #include #include #include +#include "../defines.h" #include "ParallelStep.h" #include "AudioPipeline.h" #include "../util/logging/ulog.h" @@ -108,7 +109,7 @@ ParallelStep::ParallelStep( #endif // defined(_WIN32) || defined(__APPLE__) executeRunnerThread_(s); - + if (!fallbackToSleep) { #if defined(_WIN32) @@ -132,7 +133,7 @@ ParallelStep::ParallelStep( if (fallbackToSleep) { - std::this_thread::sleep_until(beginTime + 10ms); + std::this_thread::sleep_until(beginTime + std::chrono::milliseconds((int)(1000 * FRAME_DURATION))); } } @@ -179,8 +180,14 @@ ParallelStep::~ParallelStep() codec2_fifo_destroy(taskThread->inputFifo); codec2_fifo_destroy(taskThread->outputFifo); + taskThread->step = nullptr; + taskThread->tempInput = nullptr; + taskThread->tempOutput = nullptr; delete taskThread; } + + // Force immediate memory clear + parallelSteps_.clear(); } int ParallelStep::getInputSampleRate() const @@ -239,7 +246,6 @@ std::shared_ptr ParallelStep::execute(std::shared_ptr inputSamples assert(stepToOutput >= 0 && (size_t)stepToOutput < parallelSteps_.size()); ThreadInfo* outputTask = threads_[stepToOutput]; - *numOutputSamples = codec2_fifo_used(outputTask->outputFifo); codec2_fifo_read(outputTask->outputFifo, outputTask->tempOutput.get(), *numOutputSamples); return outputTask->tempOutput; diff --git a/src/pipeline/RADEReceiveStep.cpp b/src/pipeline/RADEReceiveStep.cpp index 0f71fbd2..407d579b 100644 --- a/src/pipeline/RADEReceiveStep.cpp +++ b/src/pipeline/RADEReceiveStep.cpp @@ -77,6 +77,7 @@ RADEReceiveStep::~RADEReceiveStep() delete[] inputBufCplx_; delete[] featuresOut_; delete[] eooOut_; + outputSamples_ = nullptr; if (featuresFile_ != nullptr) { @@ -85,12 +86,12 @@ RADEReceiveStep::~RADEReceiveStep() if (inputSampleFifo_ != nullptr) { - codec2_fifo_free(inputSampleFifo_); + codec2_fifo_destroy(inputSampleFifo_); } if (outputSampleFifo_ != nullptr) { - codec2_fifo_free(outputSampleFifo_); + codec2_fifo_destroy(outputSampleFifo_); } } @@ -106,6 +107,7 @@ int RADEReceiveStep::getOutputSampleRate() const std::shared_ptr RADEReceiveStep::execute(std::shared_ptr inputSamples, int numInputSamples, int* numOutputSamples) { + auto maxSamples = std::max(getInputSampleRate(), getOutputSampleRate()); *numOutputSamples = 0; short* inputPtr = inputSamples.get(); @@ -116,7 +118,7 @@ std::shared_ptr RADEReceiveStep::execute(std::shared_ptr inputSamp int nin = rade_nin(dv_); int nout = 0; - while (codec2_fifo_read(inputSampleFifo_, inputBuf_, nin) == 0) + while ((*numOutputSamples + LPCNET_FRAME_SIZE) < maxSamples && codec2_fifo_read(inputSampleFifo_, inputBuf_, nin) == 0) { assert(nin <= rade_nin_max(dv_)); diff --git a/src/pipeline/RADETransmitStep.cpp b/src/pipeline/RADETransmitStep.cpp index 48e2198f..2635c2e9 100644 --- a/src/pipeline/RADETransmitStep.cpp +++ b/src/pipeline/RADETransmitStep.cpp @@ -82,6 +82,7 @@ RADETransmitStep::~RADETransmitStep() delete[] radeOutShort_; delete[] eooOut_; delete[] eooOutShort_; + outputSamples_ = nullptr; if (featuresFile_ != nullptr) { @@ -90,12 +91,12 @@ RADETransmitStep::~RADETransmitStep() if (inputSampleFifo_ != nullptr) { - codec2_fifo_free(inputSampleFifo_); + codec2_fifo_destroy(inputSampleFifo_); } if (outputSampleFifo_ != nullptr) { - codec2_fifo_free(inputSampleFifo_); + codec2_fifo_destroy(outputSampleFifo_); } } @@ -111,16 +112,18 @@ int RADETransmitStep::getOutputSampleRate() const std::shared_ptr RADETransmitStep::execute(std::shared_ptr inputSamples, int numInputSamples, int* numOutputSamples) { + auto maxSamples = std::max(getInputSampleRate(), getOutputSampleRate()); + int numSamplesPerTx = rade_n_tx_out(dv_); + *numOutputSamples = 0; if (numInputSamples == 0) { - // Special case logic for EOO -- make sure we only send 20ms worth at a time - *numOutputSamples = std::min(codec2_fifo_used(outputSampleFifo_), (int)(RADE_MODEM_SAMPLE_RATE * .02)); + // Special case logic for EOO + *numOutputSamples = codec2_fifo_used(outputSampleFifo_); if (*numOutputSamples > 0) { codec2_fifo_read(outputSampleFifo_, outputSamples_.get(), *numOutputSamples); - log_info("Returning %d EOO samples (remaining in FIFO: %d)", *numOutputSamples, codec2_fifo_used(outputSampleFifo_)); } @@ -133,10 +136,9 @@ std::shared_ptr RADETransmitStep::execute(std::shared_ptr inputSam codec2_fifo_write(inputSampleFifo_, inputPtr++, 1); numInputSamples--; - if (codec2_fifo_used(inputSampleFifo_) >= LPCNET_FRAME_SIZE) + if ((*numOutputSamples + numSamplesPerTx) < maxSamples && codec2_fifo_used(inputSampleFifo_) >= LPCNET_FRAME_SIZE) { unsigned int numRequiredFeaturesForRADE = rade_n_features_in_out(dv_); - int numOutputSamples = rade_n_tx_out(dv_); short pcm[LPCNET_FRAME_SIZE]; float features[NB_TOTAL_FEATURES]; @@ -164,12 +166,12 @@ std::shared_ptr RADETransmitStep::execute(std::shared_ptr inputSam { featureList_.erase(featureList_.begin()); } - for (int index = 0; index < numOutputSamples; index++) + for (int index = 0; index < numSamplesPerTx; index++) { // We only need the real component for TX. radeOutShort_[index] = radeOut_[index].real * RADE_SCALING_FACTOR; } - codec2_fifo_write(outputSampleFifo_, radeOutShort_, numOutputSamples); + codec2_fifo_write(outputSampleFifo_, radeOutShort_, numSamplesPerTx); } } } diff --git a/src/pipeline/SpeexStep.cpp b/src/pipeline/SpeexStep.cpp index 6fd99671..c5069814 100644 --- a/src/pipeline/SpeexStep.cpp +++ b/src/pipeline/SpeexStep.cpp @@ -52,8 +52,9 @@ SpeexStep::SpeexStep(int sampleRate) SpeexStep::~SpeexStep() { + outputSamples_ = nullptr; speex_preprocess_state_destroy(speexStateObj_); - codec2_fifo_free(inputSampleFifo_); + codec2_fifo_destroy(inputSampleFifo_); } int SpeexStep::getInputSampleRate() const diff --git a/src/pipeline/TxRxThread.cpp b/src/pipeline/TxRxThread.cpp index a02ca16b..9892d248 100644 --- a/src/pipeline/TxRxThread.cpp +++ b/src/pipeline/TxRxThread.cpp @@ -96,7 +96,6 @@ extern FreeDVInterface freedvInterface; #include #include "../main.h" -extern wxMutex txModeChangeMutex; extern wxWindow* g_parent; #include @@ -218,7 +217,11 @@ void TxRxThread::initializePipeline_() auto analogTxPipeline = new AudioPipeline(inputSampleRate_, outputSampleRate_); analogTxPipeline->appendPipelineStep(std::shared_ptr(doubleLevelStep)); - auto digitalTxStep = freedvInterface.createTransmitPipeline(inputSampleRate_, outputSampleRate_, []() { return g_TxFreqOffsetHz; }); + auto digitalTxStep = freedvInterface.createTransmitPipeline( + inputSampleRate_, + outputSampleRate_, + []() { return g_TxFreqOffsetHz; }, + helper_); auto digitalTxPipeline = new AudioPipeline(inputSampleRate_, outputSampleRate_); digitalTxPipeline->appendPipelineStep(std::shared_ptr(digitalTxStep)); @@ -460,16 +463,6 @@ void* TxRxThread::Entry() pthread_setname_np(pthread_self(), threadName); #endif // defined(__linux__) -#if 0 - { - std::unique_lock lk(m_processingMutex); - if (m_processingCondVar.wait_for(lk, std::chrono::milliseconds(100)) == std::cv_status::timeout) - { - log_warn("txRxThread: timeout while waiting for CV, tx = %d", m_tx); - } - } -#endif - if (!m_run) break; //log_info("thread woken up: m_tx=%d", (int)m_tx); @@ -492,8 +485,7 @@ void* TxRxThread::Entry() void TxRxThread::OnExit() { - // Free allocated buffer. - inputSamples_ = nullptr; + // empty } void TxRxThread::terminateThread() @@ -504,10 +496,7 @@ void TxRxThread::terminateThread() void TxRxThread::notify() { -#if 0 - std::unique_lock lk(m_processingMutex); - m_processingCondVar.notify_all(); -#endif + // empty } void TxRxThread::clearFifos_() @@ -521,31 +510,27 @@ void TxRxThread::clearFifos_() if (m_tx) { - auto used = codec2_fifo_used(cbData->outfifo1); - if (used > 0) + while (codec2_fifo_used(cbData->outfifo1) > 0) { - codec2_fifo_read(cbData->outfifo1, inputSamples_.get(), used); + codec2_fifo_read(cbData->outfifo1, inputSamples_.get(), 1); } - used = codec2_fifo_used(cbData->infifo2); - if (used > 0) + while (codec2_fifo_used(cbData->infifo2) > 0) { - codec2_fifo_read(cbData->infifo2, inputSamples_.get(), used); + codec2_fifo_read(cbData->infifo2, inputSamples_.get(), 1); } } else { - auto used = codec2_fifo_used(cbData->infifo1); - if (used > 0) + while (codec2_fifo_used(cbData->infifo1) > 0) { - codec2_fifo_read(cbData->infifo1, inputSamples_.get(), used); + codec2_fifo_read(cbData->infifo1, inputSamples_.get(), 1); } auto outFifo = (g_nSoundCards == 1) ? cbData->outfifo1 : cbData->outfifo2; - used = codec2_fifo_used(outFifo); - if (used > 0) + while (codec2_fifo_used(outFifo) > 0) { - codec2_fifo_read(outFifo, inputSamples_.get(), used); + codec2_fifo_read(outFifo, inputSamples_.get(), 1); } } } @@ -569,9 +554,6 @@ void TxRxThread::txProcessing_() // if (((g_nSoundCards == 2) && ((g_half_duplex && g_tx) || !g_half_duplex || g_voice_keyer_tx || g_recVoiceKeyerFile || g_recFileFromMic))) { - // Lock the mode mutex so that TX state doesn't change on us during processing. - txModeChangeMutex.Lock(); - if (pipeline_ == nullptr) { initializePipeline_(); @@ -637,7 +619,7 @@ void TxRxThread::txProcessing_() log_debug("Injecting %d samples of resampled EOO into TX stream", nout); if (codec2_fifo_write(cbData->outfifo1, outputSamples.get(), nout) != 0) { - log_warn("Could not inject resampled EOO samples (space remaining in FIFO = %d)", cbData->outfifo1); + log_warn("Could not inject resampled EOO samples (space remaining in FIFO = %d)", codec2_fifo_free(cbData->outfifo1)); } } else @@ -664,8 +646,6 @@ void TxRxThread::txProcessing_() codec2_fifo_write(cbData->outfifo1, outputSamples.get(), nout); } } - - txModeChangeMutex.Unlock(); } else { diff --git a/src/pipeline/TxRxThread.h b/src/pipeline/TxRxThread.h index 39a23a9a..a1876ec2 100644 --- a/src/pipeline/TxRxThread.h +++ b/src/pipeline/TxRxThread.h @@ -40,7 +40,7 @@ class LinkStep; class TxRxThread : public wxThread { public: - TxRxThread(bool tx, int inputSampleRate, int outputSampleRate, LinkStep* micAudioLink, std::shared_ptr helper) + TxRxThread(bool tx, int inputSampleRate, int outputSampleRate, std::shared_ptr micAudioLink, std::shared_ptr helper) : wxThread(wxTHREAD_JOINABLE) , m_tx(tx) , m_run(1) @@ -75,16 +75,13 @@ public: void terminateThread(); void notify(); - std::mutex m_processingMutex; - std::condition_variable m_processingCondVar; - private: bool m_tx; bool m_run; std::shared_ptr pipeline_; int inputSampleRate_; int outputSampleRate_; - LinkStep* equalizedMicAudioLink_; + std::shared_ptr equalizedMicAudioLink_; bool hasEooBeenSent_; std::shared_ptr helper_; std::shared_ptr inputSamples_; diff --git a/src/pipeline/test/RadeTextTest.cpp b/src/pipeline/test/RadeTextTest.cpp index a5fae469..44efd7df 100644 --- a/src/pipeline/test/RadeTextTest.cpp +++ b/src/pipeline/test/RadeTextTest.cpp @@ -15,7 +15,7 @@ std::uniform_real_distribution distribution(-0.789, 0.789); void OnRadeTextRx(rade_text_t rt, const char* txt_ptr, int length, void* state) { - log_info("Callsign received: %s", txt_ptr); + log_info("Callsign received: %s, length = %d", txt_ptr, length); testPassed = !strncmp(txt_ptr, "K6AQ", length); } @@ -86,7 +86,14 @@ int main() // Send silence through to RX step to trigger EOO processing recvStep->execute(inputSamplesPtr, 16384, &noutRx); + delete recvStep; + delete txStep; + rade_close(rade); rade_finalize(); + + rade_text_destroy(txt); + lpcnet_encoder_destroy(encState); + return testPassed ? 0 : 1; } diff --git a/src/topFrame.cpp b/src/topFrame.cpp index de6e5109..cf117559 100644 --- a/src/topFrame.cpp +++ b/src/topFrame.cpp @@ -680,36 +680,6 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const sbSizer_mode->Add(m_rb700e, 0, wxALIGN_LEFT|wxALL, 1); m_rb1600 = new wxRadioButton( modeBox, wxID_ANY, wxT("1600"), wxDefaultPosition, wxDefaultSize, 0); sbSizer_mode->Add(m_rb1600, 0, wxALIGN_LEFT|wxALL, 1); - m_hiddenMode1 = new wxRadioButton( modeBox, wxID_ANY, wxT("hidden2"), wxDefaultPosition, wxDefaultSize, 0); - sbSizer_mode->Add(m_hiddenMode1, 0, wxALIGN_LEFT|wxALL, 1); - m_hiddenMode1->Show(false); - - m_collpane = new wxCollapsiblePane(modeBox, ID_MODE_COLLAPSE, "Others:"); - sbSizer_mode->Add(m_collpane, 0, wxGROW|wxALL, 5); - - wxWindow *otherModeWin = m_collpane->GetPane(); - wxSizer *otherModeSizer = new wxBoxSizer(wxVERTICAL); - - m_rb700c = new wxRadioButton( otherModeWin, wxID_ANY, wxT("700C"), wxDefaultPosition, wxDefaultSize, 0); - otherModeSizer->Add(m_rb700c, 1, wxALIGN_LEFT|wxALL|wxEXPAND, 1); - m_rb800xa = new wxRadioButton( otherModeWin, wxID_ANY, wxT("800XA"), wxDefaultPosition, wxDefaultSize, 0); - otherModeSizer->Add(m_rb800xa, 1, wxALIGN_LEFT|wxALL|wxEXPAND, 1); - m_rb2020 = new wxRadioButton( otherModeWin, wxID_ANY, wxT("2020"), wxDefaultPosition, wxDefaultSize, 0); - otherModeSizer->Add(m_rb2020, 1, wxALIGN_LEFT|wxALL|wxEXPAND, 1); -#if defined(FREEDV_MODE_2020B) - m_rb2020b = new wxRadioButton( otherModeWin, wxID_ANY, wxT("2020B"), wxDefaultPosition, wxDefaultSize, 0); - otherModeSizer->Add(m_rb2020b, 1, wxALIGN_LEFT|wxALL|wxEXPAND, 1); -#endif // FREEDV_MODE_2020B - m_hiddenMode2 = new wxRadioButton( otherModeWin, wxID_ANY, wxT("hidden2"), wxDefaultPosition, wxDefaultSize, 0); - otherModeSizer->Add(m_hiddenMode2, 0, wxALIGN_LEFT|wxALL, 1); - m_hiddenMode2->Show(false); - - m_hiddenMode1->SetValue(true); - m_hiddenMode2->SetValue(true); - - sbSizer_mode->SetMinSize(wxSize(75,225)); - otherModeWin->SetSizer(otherModeSizer); - otherModeSizer->SetSizeHints(otherModeWin); rightSizer->Add(sbSizer_mode,0, wxALL | wxEXPAND, 2); @@ -783,14 +753,10 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const //------------------- m_auiNbookCtrl->MoveBeforeInTabOrder(m_BtnCallSignReset); m_sliderSQ->MoveBeforeInTabOrder(m_ckboxSQ); + m_rbRADE->MoveBeforeInTabOrder(m_rb700d); m_rb700d->MoveBeforeInTabOrder(m_rb700e); m_rb700e->MoveBeforeInTabOrder(m_rb1600); - m_rb700c->MoveBeforeInTabOrder(m_rb800xa); - m_rb800xa->MoveBeforeInTabOrder(m_rb2020); -#if defined(FREEDV_MODE_2020B) - m_rb2020->MoveBeforeInTabOrder(m_rb2020b); -#endif // FREEDV_MODE_2020B m_togBtnOnOff->MoveBeforeInTabOrder(m_togBtnAnalog); m_togBtnAnalog->MoveBeforeInTabOrder(m_togBtnVoiceKeyer); m_togBtnVoiceKeyer->MoveBeforeInTabOrder(m_btnTogPTT); @@ -854,18 +820,10 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const m_btnCenterRx->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnCenterRx), NULL, this); m_rbRADE->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); - m_rb700c->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); + m_rb1600->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); m_rb700d->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); m_rb700e->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); - m_rb800xa->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); - m_rb1600->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); - m_rb2020->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); -#if defined(FREEDV_MODE_2020B) - m_rb2020b->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); -#endif // FREEDV_MODE_2020B - - m_collpane->Connect(wxEVT_COLLAPSIBLEPANE_CHANGED, wxCollapsiblePaneEventHandler(TopFrame::OnChangeCollapseState), NULL, this); - + m_sliderTxLevel->Connect(wxEVT_SCROLL_TOP, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this); m_sliderTxLevel->Connect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this); m_sliderTxLevel->Connect(wxEVT_SCROLL_LINEUP, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this); @@ -938,18 +896,10 @@ TopFrame::~TopFrame() m_audioRecord->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnRecord), NULL, this); m_rbRADE->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); - m_rb700c->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); + m_rb1600->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); m_rb700d->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); m_rb700e->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); - m_rb800xa->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); - m_rb1600->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); - m_rb2020->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); -#if defined(FREEDV_MODE_2020B) - m_rb2020b->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this); -#endif // FREEDV_MODE_2020B - - m_collpane->Disconnect(wxEVT_COLLAPSIBLEPANE_CHANGED, wxCollapsiblePaneEventHandler(TopFrame::OnChangeCollapseState), NULL, this); - + m_sliderTxLevel->Disconnect(wxEVT_SCROLL_TOP, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this); m_sliderTxLevel->Disconnect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this); m_sliderTxLevel->Disconnect(wxEVT_SCROLL_LINEUP, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this); @@ -968,15 +918,6 @@ TopFrame::~TopFrame() m_cboReportFrequency->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(TopFrame::OnReportFrequencyKillFocus), NULL, this); } -void TopFrame::OnChangeCollapseState(wxCollapsiblePaneEvent& event) -{ - auto bestSize = modeBox->GetBestSize(); - auto curSize = modeBox->GetSize(); - - modeBox->SetSize(wxSize(curSize.GetWidth(), bestSize.GetHeight())); - rightSizer->Layout(); -} - void TopFrame::setVoiceKeyerButtonLabel_(wxString filename) { wxString vkLabel = _("Voice Keyer"); diff --git a/src/topFrame.h b/src/topFrame.h index d78123f2..ac85e909 100644 --- a/src/topFrame.h +++ b/src/topFrame.h @@ -130,22 +130,12 @@ class TopFrame : public wxFrame wxToggleButton *m_audioRecord; wxRadioButton *m_rbRADE; - wxRadioButton *m_rb700c; wxRadioButton *m_rb700d; wxRadioButton *m_rb700e; - wxRadioButton *m_rb800xa; wxRadioButton *m_rb1600; - wxRadioButton *m_rb2020; -#if defined(FREEDV_MODE_2020B) - wxRadioButton *m_rb2020b; -#endif // FREEDV_MODE_2020B - - wxRadioButton* m_hiddenMode1; - wxRadioButton* m_hiddenMode2; wxSizer* rightSizer; - wxCollapsiblePane *m_collpane; wxStaticBox* modeBox; wxStaticBoxSizer* sbSizer_mode; @@ -216,9 +206,7 @@ class TopFrame : public wxFrame virtual void OnChangeReportFrequency( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeReportFrequencyVerify( wxCommandEvent& event ) { event.Skip(); } - - virtual void OnChangeCollapseState(wxCollapsiblePaneEvent& event); - + virtual void OnReportFrequencySetFocus(wxFocusEvent& event) { event.Skip(); } virtual void OnReportFrequencyKillFocus(wxFocusEvent& event) { event.Skip(); } diff --git a/src/util.cpp b/src/util.cpp index 65421aab..8ea66f9c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -180,7 +180,7 @@ void MainFrame::OpenPTTInPort(void) wxGetApp().m_pttInSerialPort->onPttChange += [&](IRigController*, bool pttState) { log_info("PTT input state is now %d", pttState); - GetEventHandler()->CallAfter([&]() { + GetEventHandler()->CallAfter([this, pttState]() { if (pttState != m_btnTogPTT->GetValue()) { m_btnTogPTT->SetValue(pttState); diff --git a/test/asan_suppressions.txt b/test/asan_suppressions.txt new file mode 100644 index 00000000..6a6e4072 --- /dev/null +++ b/test/asan_suppressions.txt @@ -0,0 +1 @@ +interceptor_via_lib:hamlib diff --git a/test/freedv-ctest-reporting-mpp.conf.tmpl b/test/freedv-ctest-reporting-mpp.conf.tmpl index 89bcc383..7a9b057b 100644 --- a/test/freedv-ctest-reporting-mpp.conf.tmpl +++ b/test/freedv-ctest-reporting-mpp.conf.tmpl @@ -107,7 +107,7 @@ ManualFrequencyReporting=1 DirectionAsCardinal=0 Frequency=14236000 [Reporting/PSKReporter] -Enable=1 +Enable=0 [Reporting/FreeDV] Enable=1 Hostname=qso.freedv.org diff --git a/test/freedv-ctest-reporting.conf.tmpl b/test/freedv-ctest-reporting.conf.tmpl index 09d4696f..64be0695 100644 --- a/test/freedv-ctest-reporting.conf.tmpl +++ b/test/freedv-ctest-reporting.conf.tmpl @@ -108,7 +108,7 @@ ManualFrequencyReporting=1 DirectionAsCardinal=0 Frequency=14236000 [Reporting/PSKReporter] -Enable=1 +Enable=0 [Reporting/FreeDV] Enable=1 Hostname=qso.freedv.org diff --git a/test/lsan_suppressions.txt b/test/lsan_suppressions.txt new file mode 100644 index 00000000..1d0b343e --- /dev/null +++ b/test/lsan_suppressions.txt @@ -0,0 +1,13 @@ +leak:_Py +leak:pybind11 +leak:Fc +leak:gtk_ +leak:g_ +leak:Py +leak:torch +leak:wx +leak:rade_open +leak:__py +leak:default_malloc +leak:dtypemeta_wrap_legacy_descriptor +leak:initialize_and_map_pytypes_to_dtypes diff --git a/test/test_rade_reporting.sh b/test/test_rade_reporting.sh index bac5170f..171d5629 100755 --- a/test/test_rade_reporting.sh +++ b/test/test_rade_reporting.sh @@ -80,14 +80,20 @@ if [ "$2" == "mpp" ]; then else TX_ARGS="-txtime 5 " fi -$FREEDV_BINARY -f $(pwd)/$FREEDV_CONF_FILE -ut tx -utmode RADE $TX_ARGS +$FREEDV_BINARY -f $(pwd)/$FREEDV_CONF_FILE -ut tx -utmode RADE $TX_ARGS >tmp.log 2>&1 & FDV_PID=$! + +#if [ "$OPERATING_SYSTEM" != "Linux" ]; then +# xctrace record --template "Audio System Trace" --window 2m --output "instruments_trace_${FDV_PID}.trace" --attach $FDV_PID +#fi + #sleep 30 #screencapture ../screenshot.png #wpctl status #pw-top -b -n 5 -#wait $FDV_PID +wait $FDV_PID +cat tmp.log # Stop recording, play back in RX mode kill $RECORD_PID @@ -107,7 +113,15 @@ if [ "$1" != "" ]; then mv $(pwd)/testwithnoise.wav $(pwd)/test.wav fi -$FREEDV_BINARY -f $(pwd)/$FREEDV_CONF_FILE -ut rx -utmode RADE -rxfile $(pwd)/test.wav +$FREEDV_BINARY -f $(pwd)/$FREEDV_CONF_FILE -ut rx -utmode RADE -rxfile $(pwd)/test.wav >tmp.log 2>&1 & +FDV_PID=$! + +#if [ "$OPERATING_SYSTEM" != "Linux" ]; then +# xctrace record --template "Audio System Trace" --window 2m --output "instruments_trace_${FDV_PID}.trace" --attach $FDV_PID +#fi +wait $FDV_PID +FREEDV_EXIT_CODE=$? +cat tmp.log # Clean up PulseAudio virtual devices if [ "$OPERATING_SYSTEM" == "Linux" ]; then @@ -120,3 +134,5 @@ fi # End radio process as it's no longer needed kill $RADIO_PID + +exit $FREEDV_EXIT_CODE diff --git a/test/test_zeros.sh b/test/test_zeros.sh index 69797e83..dd084acf 100755 --- a/test/test_zeros.sh +++ b/test/test_zeros.sh @@ -93,14 +93,21 @@ if [ "$FREEDV_TEST" == "tx" ]; then fi # Start FreeDV in test mode -$FREEDV_BINARY -f $(pwd)/$FREEDV_CONF_FILE -ut $FREEDV_TEST -utmode $FREEDV_MODE 2>&1 | tee tmp.log +$FREEDV_BINARY -f $(pwd)/$FREEDV_CONF_FILE -ut $FREEDV_TEST -utmode $FREEDV_MODE >tmp.log 2>&1 & #| tee tmp.log FDV_PID=$! + +#if [ "$OPERATING_SYSTEM" != "Linux" ]; then +# xctrace record --window 2m --template "Audio System Trace" --output "instruments_trace_${FDV_PID}.trace" --attach $FDV_PID +#fi + #sleep 30 #screencapture ../screenshot.png #wpctl status #pw-top -b -n 5 -#wait $FDV_PID +wait $FDV_PID +FREEDV_EXIT_STATUS=$? +cat tmp.log # Stop recording/playback and process data if [ "$FREEDV_TEST" == "rx" ]; then @@ -121,3 +128,5 @@ if [ "$OPERATING_SYSTEM" == "Linux" ]; then pactl unload-module $DRIVER_INDEX_FREEDV_COMPUTER_TO_RADIO pactl unload-module $DRIVER_INDEX_FREEDV_MICROPHONE_TO_COMPUTER fi + +exit $FREEDV_EXIT_STATUS