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 commitpull/894/head69689bb927
. * 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 commitfc6a9f8797
. * 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 commitabe816d00b
. * 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.
parent
919bba2c14
commit
30c9e5b9c6
|
@ -59,7 +59,7 @@ jobs:
|
||||||
working-directory: ${{github.workspace}}
|
working-directory: ${{github.workspace}}
|
||||||
run: |
|
run: |
|
||||||
. ./rade-venv/bin/activate
|
. ./rade-venv/bin/activate
|
||||||
UT_ENABLE=1 ./build_linux.sh
|
BUILD_TYPE=RelWithDebInfo UT_ENABLE=1 ./build_linux.sh
|
||||||
|
|
||||||
- name: Execute unit tests
|
- name: Execute unit tests
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -83,3 +83,18 @@ jobs:
|
||||||
. ../rade-venv/bin/activate
|
. ../rade-venv/bin/activate
|
||||||
PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V
|
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"
|
||||||
|
|
|
@ -61,7 +61,7 @@ jobs:
|
||||||
- name: Build freedv-gui
|
- name: Build freedv-gui
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ${{github.workspace}}
|
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
|
- name: Workaround macOS permission issues
|
||||||
if: ${{ matrix.os == 'macos-13' }}
|
if: ${{ matrix.os == 'macos-13' }}
|
||||||
|
@ -81,6 +81,20 @@ jobs:
|
||||||
run: |
|
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
|
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
|
# 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.
|
# x86 and ARM. No point in doing so if there's a failure on either.
|
||||||
dist:
|
dist:
|
||||||
|
|
|
@ -66,7 +66,7 @@ jobs:
|
||||||
export PATH=${{github.workspace}}/llvm-mingw-20250430-ucrt-ubuntu-22.04-x86_64/bin:$PATH
|
export PATH=${{github.workspace}}/llvm-mingw-20250430-ucrt-ubuntu-22.04-x86_64/bin:$PATH
|
||||||
mkdir build_windows
|
mkdir build_windows
|
||||||
cd 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
|
- name: Build freedv-gui
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
@ -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(CMAKE_EXPORT_COMPILE_COMMANDS TRUE CACHE BOOL "Enable IDE features.")
|
||||||
set(USE_INTERNAL_CODEC2 FALSE CACHE BOOL
|
set(USE_INTERNAL_CODEC2 FALSE CACHE BOOL
|
||||||
"Download and build codec2 instead of using the system library.")
|
"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
|
set(USE_STATIC_DEPS FALSE CACHE BOOL
|
||||||
"Download and build static libraries instead of system libraries.")
|
"Download and build static libraries instead of system libraries.")
|
||||||
set(USE_STATIC_PORTAUDIO FALSE CACHE BOOL
|
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.")
|
"Use native audio code instead of PortAudio for audio I/O. Defaults to true.")
|
||||||
set(SIGN_WINDOWS_BINARIES FALSE CACHE BOOL
|
set(SIGN_WINDOWS_BINARIES FALSE CACHE BOOL
|
||||||
"Enable signing of Windows binaries. See CODE_SIGNING.md for info.")
|
"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(SIGN_WINDOWS_BINARIES)
|
||||||
if(NOT WIN32 AND NOT MINGW)
|
if(NOT WIN32 AND NOT MINGW)
|
||||||
|
@ -353,7 +359,7 @@ message(STATUS "Threads library flags: ${CMAKE_THREAD_LIBS_INIT}")
|
||||||
include(cmake/BuildRADE.cmake)
|
include(cmake/BuildRADE.cmake)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Find codec2 and lpcnetfreedv
|
# Find codec2
|
||||||
#
|
#
|
||||||
if(CODEC2_BUILD_DIR)
|
if(CODEC2_BUILD_DIR)
|
||||||
if(USE_INTERNAL_CODEC2)
|
if(USE_INTERNAL_CODEC2)
|
||||||
|
@ -373,20 +379,8 @@ if(CODEC2_BUILD_DIR)
|
||||||
CONFIGS codec2.cmake
|
CONFIGS codec2.cmake
|
||||||
)
|
)
|
||||||
get_target_property(CODEC2_INCLUDE_DIRS codec2 INTERFACE_INCLUDE_DIRECTORIES)
|
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)
|
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)
|
include(cmake/BuildCodec2.cmake)
|
||||||
else(CODEC2_BUILD_DIR)
|
else(CODEC2_BUILD_DIR)
|
||||||
message(STATUS "Looking for codec2...")
|
message(STATUS "Looking for codec2...")
|
||||||
|
@ -398,7 +392,6 @@ else(CODEC2_BUILD_DIR)
|
||||||
get_target_property(CODEC2_INCLUDE_DIRS codec2 INTERFACE_INCLUDE_DIRECTORIES)
|
get_target_property(CODEC2_INCLUDE_DIRS codec2 INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
message(STATUS " codec2 library: ${CODEC2_LIBRARY}")
|
message(STATUS " codec2 library: ${CODEC2_LIBRARY}")
|
||||||
message(STATUS " codec2 headers: ${CODEC2_INCLUDE_DIRS}")
|
message(STATUS " codec2 headers: ${CODEC2_INCLUDE_DIRS}")
|
||||||
find_package(lpcnetfreedv REQUIRED)
|
|
||||||
else()
|
else()
|
||||||
# Try to find manually
|
# Try to find manually
|
||||||
find_path(CODEC2_INCLUDE_DIRS codec2.h
|
find_path(CODEC2_INCLUDE_DIRS codec2.h
|
||||||
|
@ -410,7 +403,7 @@ else(CODEC2_BUILD_DIR)
|
||||||
list(APPEND FREEDV_LINK_LIBS ${CODEC2_LIBRARY})
|
list(APPEND FREEDV_LINK_LIBS ${CODEC2_LIBRARY})
|
||||||
include_directories(${CODEC2_INCLUDE_DIRS})
|
include_directories(${CODEC2_INCLUDE_DIRS})
|
||||||
else()
|
else()
|
||||||
message(STATUS "Will attempt internal build of codec2 and lpcnetfreedv.")
|
message(STATUS "Will attempt internal build of codec2.")
|
||||||
include(cmake/BuildCodec2.cmake)
|
include(cmake/BuildCodec2.cmake)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
@ -728,9 +721,9 @@ elseif(UNIX AND NOT APPLE)
|
||||||
SET(CPACK_GENERATOR "DEB")
|
SET(CPACK_GENERATOR "DEB")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mooneer Salem <mooneer@gmail.com>") #required
|
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mooneer Salem <mooneer@gmail.com>") #required
|
||||||
if(USE_NATIVE_AUDIO)
|
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)
|
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)
|
endif(USE_NATIVE_AUDIO)
|
||||||
|
|
||||||
SET(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
|
SET(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
|
||||||
|
@ -744,14 +737,18 @@ if(UNITTEST)
|
||||||
macro(DefineAudioTest utName)
|
macro(DefineAudioTest utName)
|
||||||
add_test(NAME fullduplex_${utName}
|
add_test(NAME fullduplex_${utName}
|
||||||
COMMAND sh -c "${CMAKE_CURRENT_SOURCE_DIR}/test/test_zeros.sh txrx ${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")
|
set_tests_properties(fullduplex_${utName} PROPERTIES FAIL_REGULAR_EXPRESSION "Sync changed from 1 to 0")
|
||||||
|
endif(NOT ENABLE_ASAN)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
DefineAudioTest(RADEV1)
|
DefineAudioTest(RADEV1)
|
||||||
|
|
||||||
add_test(NAME fullduplex_RADEV1_repeated
|
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")
|
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")
|
||||||
|
if(NOT ENABLE_ASAN)
|
||||||
set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES FAIL_REGULAR_EXPRESSION "Sync changed from 1 to 0")
|
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 DISABLED TRUE)
|
||||||
set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES LABELS stress_test)
|
set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES LABELS stress_test)
|
||||||
|
|
||||||
|
@ -760,12 +757,18 @@ DefineAudioTest(700E)
|
||||||
DefineAudioTest(1600)
|
DefineAudioTest(1600)
|
||||||
|
|
||||||
add_test(NAME rade_reporting_clean COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test/test_rade_reporting.sh)
|
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")
|
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)
|
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")
|
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)
|
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")
|
set_tests_properties(rade_reporting_mpp PROPERTIES PASS_REGULAR_EXPRESSION "Reporting callsign ZZ0ZZZ @ SNR")
|
||||||
|
endif(NOT ENABLE_ASAN)
|
||||||
|
|
||||||
endif(UNITTEST)
|
endif(UNITTEST)
|
||||||
|
|
|
@ -927,6 +927,7 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
|
||||||
4. Miscellaneous:
|
4. Miscellaneous:
|
||||||
* Add issue template for SW bugs. (PR #759)
|
* Add issue template for SW bugs. (PR #759)
|
||||||
* Fix typos in user manual and code. (PR #859; thanks @dforsi)
|
* 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
|
## V1.9.9.2 June 2024
|
||||||
|
|
||||||
|
|
|
@ -8,44 +8,15 @@
|
||||||
set -x -e
|
set -x -e
|
||||||
|
|
||||||
UT_ENABLE=${UT_ENABLE:-0}
|
UT_ENABLE=${UT_ENABLE:-0}
|
||||||
LPCNET_DISABLE=${LPCNET_DISABLE:-1}
|
|
||||||
USE_NATIVE_AUDIO=${USE_NATIVE_AUDIO:-1}
|
USE_NATIVE_AUDIO=${USE_NATIVE_AUDIO:-1}
|
||||||
|
BUILD_TYPE=${BUILD_TYPE:-Debug}
|
||||||
|
WITH_ASAN=${WITH_ASAN:-0}
|
||||||
|
|
||||||
export FREEDVGUIDIR=${PWD}
|
export FREEDVGUIDIR=${PWD}
|
||||||
export CODEC2DIR=$FREEDVGUIDIR/codec2
|
export CODEC2DIR=$FREEDVGUIDIR/codec2
|
||||||
export LPCNETDIR=$FREEDVGUIDIR/LPCNet
|
|
||||||
|
|
||||||
# change this when working on combined codec2/freedv-gui changes
|
# change this when working on combined codec2/freedv-gui changes
|
||||||
CODEC2_BRANCH=1.2.0
|
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
|
# First build and install vanilla codec2 as we need -lcodec2 to build LPCNet
|
||||||
cd $FREEDVGUIDIR
|
cd $FREEDVGUIDIR
|
||||||
|
@ -53,13 +24,7 @@ if [ ! -d codec2 ]; then
|
||||||
git clone https://github.com/drowe67/codec2.git
|
git clone https://github.com/drowe67/codec2.git
|
||||||
fi
|
fi
|
||||||
cd codec2 && git switch main && git pull && git checkout $CODEC2_BRANCH
|
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)
|
mkdir -p build_linux && cd build_linux && rm -Rf * && cmake .. && 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
|
|
||||||
|
|
||||||
# Finally, build freedv-gui
|
# Finally, build freedv-gui
|
||||||
cd $FREEDVGUIDIR
|
cd $FREEDVGUIDIR
|
||||||
|
@ -67,5 +32,5 @@ if [ -d .git ]; then
|
||||||
git pull
|
git pull
|
||||||
fi
|
fi
|
||||||
mkdir -p build_linux && cd build_linux && rm -Rf *
|
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)
|
make VERBOSE=1 -j$(nproc)
|
||||||
|
|
45
build_osx.sh
45
build_osx.sh
|
@ -6,16 +6,14 @@
|
||||||
|
|
||||||
export FREEDVGUIDIR=${PWD}
|
export FREEDVGUIDIR=${PWD}
|
||||||
export CODEC2DIR=$FREEDVGUIDIR/codec2
|
export CODEC2DIR=$FREEDVGUIDIR/codec2
|
||||||
export LPCNETDIR=$FREEDVGUIDIR/LPCNet
|
|
||||||
export HAMLIBDIR=$FREEDVGUIDIR/hamlib
|
export HAMLIBDIR=$FREEDVGUIDIR/hamlib
|
||||||
export CODEC2_BRANCH=1.2.0
|
export CODEC2_BRANCH=1.2.0
|
||||||
export LPCNET_BRANCH=v0.5
|
|
||||||
export UT_ENABLE=${UT_ENABLE:-0}
|
export UT_ENABLE=${UT_ENABLE:-0}
|
||||||
export LPCNET_DISABLE=${LPCNET_DISABLE:-1}
|
|
||||||
export UNIV_BUILD=${UNIV_BUILD:-1}
|
export UNIV_BUILD=${UNIV_BUILD:-1}
|
||||||
export CODESIGN_IDENTITY=${CODESIGN_IDENTITY:--}
|
export CODESIGN_IDENTITY=${CODESIGN_IDENTITY:--}
|
||||||
export BUILD_DEPS=${BUILD_DEPS:-1}
|
export BUILD_DEPS=${BUILD_DEPS:-1}
|
||||||
export USE_NATIVE_AUDIO=${USE_NATIVE_AUDIO:-1}
|
export USE_NATIVE_AUDIO=${USE_NATIVE_AUDIO:-1}
|
||||||
|
export BUILD_TYPE=${BUILD_TYPE:-Debug}
|
||||||
|
|
||||||
# Prerequisite: build dylibbundler
|
# Prerequisite: build dylibbundler
|
||||||
if [ ! -d macdylibbundler ]; then
|
if [ ! -d macdylibbundler ]; then
|
||||||
|
@ -56,46 +54,13 @@ if [ $BUILD_DEPS == 1 ]; then
|
||||||
make install
|
make install
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# OK, build and test LPCNet
|
# Build codec2
|
||||||
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
|
|
||||||
cd $FREEDVGUIDIR
|
cd $FREEDVGUIDIR
|
||||||
if [ ! -d codec2 ]; then
|
if [ ! -d codec2 ]; then
|
||||||
git clone https://github.com/drowe67/codec2-new.git codec2
|
git clone https://github.com/drowe67/codec2-new.git codec2
|
||||||
fi
|
fi
|
||||||
cd codec2 && git switch main && git pull && git checkout $CODEC2_BRANCH
|
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)
|
mkdir -p build_osx && cd build_osx && rm -Rf * && cmake -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
|
|
||||||
|
|
||||||
# Finally, build freedv-gui
|
# Finally, build freedv-gui
|
||||||
cd $FREEDVGUIDIR
|
cd $FREEDVGUIDIR
|
||||||
|
@ -109,9 +74,9 @@ if [ "$CODESIGN_KEYCHAIN_PROFILE" != "" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $BUILD_DEPS == 1 ]; then
|
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
|
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
|
fi
|
||||||
|
|
||||||
make VERBOSE=1 -j$(sysctl -n hw.logicalcpu)
|
make VERBOSE=1 -j$(sysctl -n hw.logicalcpu)
|
||||||
|
|
|
@ -42,7 +42,7 @@ for arch in x86_64; do
|
||||||
cd $BUILD_ARCH_DIR
|
cd $BUILD_ARCH_DIR
|
||||||
|
|
||||||
# Kick off new build with the given architecture
|
# 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
|
make -j$(nproc) package
|
||||||
cp FreeDV-*.exe $WIN_BUILD_DIR
|
cp FreeDV-*.exe $WIN_BUILD_DIR
|
||||||
cd $WIN_BUILD_DIR
|
cd $WIN_BUILD_DIR
|
||||||
|
|
|
@ -8,15 +8,6 @@ if(BUILD_OSX_UNIVERSAL)
|
||||||
set(CODEC2_CMAKE_ARGS ${CODEC2_CMAKE_ARGS} -DBUILD_OSX_UNIVERSAL=1)
|
set(CODEC2_CMAKE_ARGS ${CODEC2_CMAKE_ARGS} -DBUILD_OSX_UNIVERSAL=1)
|
||||||
endif(BUILD_OSX_UNIVERSAL)
|
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
|
# Build codec2 library with lpcnetfreedv
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(build_codec2
|
ExternalProject_Add(build_codec2
|
||||||
|
@ -40,9 +31,5 @@ set_target_properties(codec2 PROPERTIES
|
||||||
|
|
||||||
set(CODEC2_BUILD_DIR ${BINARY_DIR})
|
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)
|
set(CODEC2_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/codec2_src/src ${CMAKE_BINARY_DIR}/codec2_build)
|
||||||
include_directories(${CODEC2_INCLUDE_DIRS})
|
include_directories(${CODEC2_INCLUDE_DIRS})
|
||||||
|
|
|
@ -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)
|
|
|
@ -10,17 +10,10 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES @CMAKE_FIND_LIBRARY_SUFFIXES@)
|
||||||
set(CMAKE_FIND_LIBRARY_PREFIXES @CMAKE_FIND_LIBRARY_PREFIXES@)
|
set(CMAKE_FIND_LIBRARY_PREFIXES @CMAKE_FIND_LIBRARY_PREFIXES@)
|
||||||
set(CMAKE_SYSTEM_LIBRARY_PATH @CMAKE_SYSTEM_LIBRARY_PATH@)
|
set(CMAKE_SYSTEM_LIBRARY_PATH @CMAKE_SYSTEM_LIBRARY_PATH@)
|
||||||
set(CMAKE_FIND_ROOT_PATH @CMAKE_FIND_ROOT_PATH@)
|
set(CMAKE_FIND_ROOT_PATH @CMAKE_FIND_ROOT_PATH@)
|
||||||
set(LPCNET_DISABLED @LPCNET_DISABLED@)
|
|
||||||
if(USE_INTERNAL_CODEC2)
|
if(USE_INTERNAL_CODEC2)
|
||||||
set(CODEC2_BUILD_DIR ${CMAKE_BINARY_DIR}/codec2_build)
|
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()
|
else()
|
||||||
set(CODEC2_BUILD_DIR @CODEC2_BUILD_DIR@)
|
set(CODEC2_BUILD_DIR @CODEC2_BUILD_DIR@)
|
||||||
if(NOT LPCNET_DISABLED)
|
|
||||||
set(LPCNET_BUILD_DIR @LPCNET_BUILD_DIR@)
|
|
||||||
endif(NOT LPCNET_DISABLED)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,17 +133,6 @@ if(CODEC2_BUILD_DIR)
|
||||||
|
|
||||||
freedv_sign_dependency(${CODEC2_FINAL} ${CMAKE_INSTALL_PREFIX}/bin/libcodec2.dll)
|
freedv_sign_dependency(${CODEC2_FINAL} ${CMAKE_INSTALL_PREFIX}/bin/libcodec2.dll)
|
||||||
endif()
|
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)
|
if(FREEDV_USING_LLVM_MINGW)
|
||||||
# Use the bin/ folder for the platform as an additional
|
# Use the bin/ folder for the platform as an additional
|
||||||
|
|
|
@ -53,18 +53,11 @@ else()
|
||||||
add_executable(freedv WIN32 ${FREEDV_SOURCES} ${RES_FILES})
|
add_executable(freedv WIN32 ${FREEDV_SOURCES} ${RES_FILES})
|
||||||
endif(APPLE)
|
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)
|
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)
|
add_dependencies(FreeDV build_rade)
|
||||||
else(APPLE)
|
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)
|
add_dependencies(freedv build_rade)
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
|
@ -141,11 +134,6 @@ endif(APPLE)
|
||||||
|
|
||||||
# Custom commands to build OSX images.
|
# Custom commands to build OSX images.
|
||||||
if(APPLE)
|
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)
|
if(NOT MACOS_CODESIGN_IDENTITY)
|
||||||
set(MACOS_CODESIGN_IDENTITY -)
|
set(MACOS_CODESIGN_IDENTITY -)
|
||||||
endif(NOT MACOS_CODESIGN_IDENTITY)
|
endif(NOT MACOS_CODESIGN_IDENTITY)
|
||||||
|
@ -158,7 +146,7 @@ if(APPLE)
|
||||||
TARGET FreeDV
|
TARGET FreeDV
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND rm -rf dist_tmp FreeDV.dmg || true
|
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 cp ARGS ${CMAKE_CURRENT_SOURCE_DIR}/freedv.icns FreeDV.app/Contents/Resources
|
||||||
COMMAND rm ARGS -rf FreeDV.app/Contents/Frameworks
|
COMMAND rm ARGS -rf FreeDV.app/Contents/Frameworks
|
||||||
COMMAND mkdir ARGS FreeDV.app/Contents/Frameworks
|
COMMAND mkdir ARGS FreeDV.app/Contents/Frameworks
|
||||||
|
|
|
@ -154,17 +154,18 @@ void PulseAudioDevice::stop()
|
||||||
{
|
{
|
||||||
if (stream_ != nullptr)
|
if (stream_ != nullptr)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(streamStateMutex_);
|
|
||||||
|
|
||||||
pa_threaded_mainloop_lock(mainloop_);
|
pa_threaded_mainloop_lock(mainloop_);
|
||||||
|
|
||||||
|
// Disconnect stream and wait for response from mainloop.
|
||||||
pa_stream_disconnect(stream_);
|
pa_stream_disconnect(stream_);
|
||||||
|
pa_threaded_mainloop_wait(mainloop_);
|
||||||
|
|
||||||
|
// Deallocate stream.
|
||||||
|
pa_stream_unref(stream_);
|
||||||
|
stream_ = nullptr;
|
||||||
|
|
||||||
pa_threaded_mainloop_unlock(mainloop_);
|
pa_threaded_mainloop_unlock(mainloop_);
|
||||||
|
|
||||||
streamStateCondVar_.wait(lk);
|
|
||||||
|
|
||||||
pa_stream_unref(stream_);
|
|
||||||
|
|
||||||
stream_ = nullptr;
|
|
||||||
sem_destroy(&sem_);
|
sem_destroy(&sem_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,8 +176,7 @@ int PulseAudioDevice::getLatencyInMicroseconds()
|
||||||
pa_usec_t latency = 0;
|
pa_usec_t latency = 0;
|
||||||
if (stream_ != nullptr)
|
if (stream_ != nullptr)
|
||||||
{
|
{
|
||||||
int neg = 0;
|
pa_stream_get_latency(stream_, &latency, nullptr); // ignore error and assume 0
|
||||||
pa_stream_get_latency(stream_, &latency, &neg); // ignore error and assume 0
|
|
||||||
}
|
}
|
||||||
pa_threaded_mainloop_unlock(mainloop_);
|
pa_threaded_mainloop_unlock(mainloop_);
|
||||||
return (int)latency;
|
return (int)latency;
|
||||||
|
@ -245,6 +245,35 @@ void PulseAudioDevice::setHelperRealTime()
|
||||||
sigaddset(&signal_set, SIGXCPU);
|
sigaddset(&signal_set, SIGXCPU);
|
||||||
sigprocmask(SIG_UNBLOCK, &signal_set, NULL);
|
sigprocmask(SIG_UNBLOCK, &signal_set, NULL);
|
||||||
#endif // 0
|
#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()
|
void PulseAudioDevice::startRealTimeWork()
|
||||||
|
@ -356,8 +385,7 @@ void PulseAudioDevice::StreamStateCallback_(pa_stream *p, void *userdata)
|
||||||
// does not accidentally refer to already freed memory.
|
// does not accidentally refer to already freed memory.
|
||||||
if (pa_stream_get_state(p) == PA_STREAM_TERMINATED)
|
if (pa_stream_get_state(p) == PA_STREAM_TERMINATED)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(thisObj->streamStateMutex_);
|
pa_threaded_mainloop_signal(thisObj->mainloop_, 0);
|
||||||
thisObj->streamStateCondVar_.notify_all();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,6 @@ private:
|
||||||
IAudioEngine::AudioDirection direction_;
|
IAudioEngine::AudioDirection direction_;
|
||||||
int sampleRate_;
|
int sampleRate_;
|
||||||
int numChannels_;
|
int numChannels_;
|
||||||
std::mutex streamStateMutex_;
|
|
||||||
std::condition_variable streamStateCondVar_;
|
|
||||||
|
|
||||||
thread_local static std::chrono::high_resolution_clock::time_point StartTime_;
|
thread_local static std::chrono::high_resolution_clock::time_point StartTime_;
|
||||||
thread_local static bool MustStopWork_;
|
thread_local static bool MustStopWork_;
|
||||||
|
|
|
@ -420,6 +420,26 @@ AudioDeviceSpecification WASAPIAudioEngine::getDeviceSpecification_(IMMDevice* d
|
||||||
spec.maxChannels = streamFormat->nChannels;
|
spec.maxChannels = streamFormat->nChannels;
|
||||||
spec.minChannels = 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);
|
CoTaskMemFree(streamFormat);
|
||||||
audioClient->Release();
|
audioClient->Release();
|
||||||
PropVariantClear(&friendlyName);
|
PropVariantClear(&friendlyName);
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
FreeDVConfiguration::FreeDVConfiguration()
|
FreeDVConfiguration::FreeDVConfiguration()
|
||||||
/* First time configuration options */
|
/* First time configuration options */
|
||||||
: firstTimeUse("/FirstTimeUse", true)
|
: firstTimeUse("/FirstTimeUse", true)
|
||||||
, freedv2020Allowed("/FreeDV2020/Allowed", false)
|
|
||||||
, freedvAVXSupported("/FreeDV2020/AVXSupported", false)
|
|
||||||
|
|
||||||
/* Position and size of main window */
|
/* Position and size of main window */
|
||||||
, mainWindowLeft("/MainFrame/left", 20)
|
, mainWindowLeft("/MainFrame/left", 20)
|
||||||
|
@ -127,7 +125,6 @@ void FreeDVConfiguration::load(wxConfigBase* config)
|
||||||
reportingConfiguration.load(config);
|
reportingConfiguration.load(config);
|
||||||
|
|
||||||
load_(config, firstTimeUse);
|
load_(config, firstTimeUse);
|
||||||
load_(config, freedv2020Allowed);
|
|
||||||
|
|
||||||
load_(config, mainWindowLeft);
|
load_(config, mainWindowLeft);
|
||||||
load_(config, mainWindowTop);
|
load_(config, mainWindowTop);
|
||||||
|
@ -252,7 +249,6 @@ void FreeDVConfiguration::save(wxConfigBase* config)
|
||||||
reportingConfiguration.save(config);
|
reportingConfiguration.save(config);
|
||||||
|
|
||||||
save_(config, firstTimeUse);
|
save_(config, firstTimeUse);
|
||||||
save_(config, freedv2020Allowed);
|
|
||||||
|
|
||||||
save_(config, mainWindowLeft);
|
save_(config, mainWindowLeft);
|
||||||
save_(config, mainWindowTop);
|
save_(config, mainWindowTop);
|
||||||
|
|
|
@ -42,12 +42,6 @@ public:
|
||||||
ReportingConfiguration reportingConfiguration;
|
ReportingConfiguration reportingConfiguration;
|
||||||
|
|
||||||
ConfigurationDataElement<bool> firstTimeUse;
|
ConfigurationDataElement<bool> firstTimeUse;
|
||||||
ConfigurationDataElement<bool> 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<bool> freedvAVXSupported;
|
|
||||||
|
|
||||||
ConfigurationDataElement<long> mainWindowLeft;
|
ConfigurationDataElement<long> mainWindowLeft;
|
||||||
ConfigurationDataElement<long> mainWindowTop;
|
ConfigurationDataElement<long> mainWindowTop;
|
||||||
|
|
|
@ -41,22 +41,12 @@ static const char* GetCurrentModeStrImpl_(int mode)
|
||||||
{
|
{
|
||||||
switch(mode)
|
switch(mode)
|
||||||
{
|
{
|
||||||
case FREEDV_MODE_700C:
|
|
||||||
return "700C";
|
|
||||||
case FREEDV_MODE_700D:
|
case FREEDV_MODE_700D:
|
||||||
return "700D";
|
return "700D";
|
||||||
case FREEDV_MODE_700E:
|
case FREEDV_MODE_700E:
|
||||||
return "700E";
|
return "700E";
|
||||||
case FREEDV_MODE_1600:
|
case FREEDV_MODE_1600:
|
||||||
return "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:
|
case FREEDV_MODE_RADE:
|
||||||
return "RADEV1";
|
return "RADEV1";
|
||||||
default:
|
default:
|
||||||
|
@ -126,18 +116,12 @@ float FreeDVInterface::GetMinimumSNR_(int mode)
|
||||||
{
|
{
|
||||||
switch(mode)
|
switch(mode)
|
||||||
{
|
{
|
||||||
case FREEDV_MODE_700C:
|
|
||||||
return 2.0;
|
|
||||||
case FREEDV_MODE_700D:
|
case FREEDV_MODE_700D:
|
||||||
return -2.0f;
|
return -2.0f;
|
||||||
case FREEDV_MODE_700E:
|
case FREEDV_MODE_700E:
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
case FREEDV_MODE_1600:
|
case FREEDV_MODE_1600:
|
||||||
return 4.0f;
|
return 4.0f;
|
||||||
case FREEDV_MODE_2020:
|
|
||||||
return 2.0f;
|
|
||||||
case FREEDV_MODE_800XA:
|
|
||||||
return 2.0f;
|
|
||||||
default:
|
default:
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
@ -552,7 +536,8 @@ int FreeDVInterface::getTxNNomModemSamples() const
|
||||||
{
|
{
|
||||||
if (txMode_ >= FREEDV_MODE_RADE)
|
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);
|
assert(currentTxMode_ != nullptr);
|
||||||
|
@ -719,7 +704,11 @@ float FreeDVInterface::getSNREstimate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPipelineStep* FreeDVInterface::createTransmitPipeline(int inputSampleRate, int outputSampleRate, std::function<float()> getFreqOffsetFn)
|
IPipelineStep* FreeDVInterface::createTransmitPipeline(
|
||||||
|
int inputSampleRate,
|
||||||
|
int outputSampleRate,
|
||||||
|
std::function<float()> getFreqOffsetFn,
|
||||||
|
std::shared_ptr<IRealtimeHelper> realtimeHelper)
|
||||||
{
|
{
|
||||||
std::vector<IPipelineStep*> parallelSteps;
|
std::vector<IPipelineStep*> parallelSteps;
|
||||||
|
|
||||||
|
@ -739,12 +728,15 @@ IPipelineStep* FreeDVInterface::createTransmitPipeline(int inputSampleRate, int
|
||||||
[&](ParallelStep*) {
|
[&](ParallelStep*) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
|
auto currentTxMode = currentTxMode_;
|
||||||
|
auto txModeInt = txMode_;
|
||||||
|
|
||||||
// Special handling for RADE.
|
// Special handling for RADE.
|
||||||
if (txMode_ >= FREEDV_MODE_RADE) return 0;
|
if (txModeInt >= FREEDV_MODE_RADE) return 0;
|
||||||
|
|
||||||
for (auto& dv : dvObjects_)
|
for (auto& dv : dvObjects_)
|
||||||
{
|
{
|
||||||
if (dv == currentTxMode_) return index;
|
if (dv == currentTxMode) return index;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -758,7 +750,7 @@ IPipelineStep* FreeDVInterface::createTransmitPipeline(int inputSampleRate, int
|
||||||
modeFn,
|
modeFn,
|
||||||
parallelSteps,
|
parallelSteps,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr
|
realtimeHelper
|
||||||
);
|
);
|
||||||
|
|
||||||
return parallelStep;
|
return parallelStep;
|
||||||
|
|
|
@ -126,7 +126,11 @@ public:
|
||||||
const char* getReliableText();
|
const char* getReliableText();
|
||||||
void setReliableText(const char* callsign);
|
void setReliableText(const char* callsign);
|
||||||
|
|
||||||
IPipelineStep* createTransmitPipeline(int inputSampleRate, int outputSampleRate, std::function<float()> getFreqOffsetFn);
|
IPipelineStep* createTransmitPipeline(
|
||||||
|
int inputSampleRate,
|
||||||
|
int outputSampleRate,
|
||||||
|
std::function<float()> getFreqOffsetFn,
|
||||||
|
std::shared_ptr<IRealtimeHelper> realtimeHelper);
|
||||||
IPipelineStep* createReceivePipeline(
|
IPipelineStep* createReceivePipeline(
|
||||||
int inputSampleRate, int outputSampleRate,
|
int inputSampleRate, int outputSampleRate,
|
||||||
std::function<int*()> getRxStateFn,
|
std::function<int*()> getRxStateFn,
|
||||||
|
|
|
@ -44,10 +44,10 @@
|
||||||
#define wxUSE_LIBTIFF 1
|
#define wxUSE_LIBTIFF 1
|
||||||
|
|
||||||
#define PLOT_BORDER 12
|
#define PLOT_BORDER 12
|
||||||
#define XLEFT_OFFSET 40
|
#define XLEFT_OFFSET 50
|
||||||
#define XLEFT_TEXT_OFFSET 6
|
#define XLEFT_TEXT_OFFSET 6
|
||||||
#define YBOTTOM_OFFSET 20
|
#define YBOTTOM_OFFSET 20
|
||||||
#define YBOTTOM_TEXT_OFFSET 15
|
#define YBOTTOM_TEXT_OFFSET 5
|
||||||
#define GRID_INCREMENT 50
|
#define GRID_INCREMENT 50
|
||||||
|
|
||||||
#define BLACK_COLOR wxColor(0x00, 0x00, 0x00)
|
#define BLACK_COLOR wxColor(0x00, 0x00, 0x00)
|
||||||
|
|
|
@ -104,9 +104,9 @@ FilterDlg::FilterDlg(wxWindow* parent, bool running, bool *newMicInFilter, bool
|
||||||
sbSizer_speexpp->Add(m_ckboxSpeexpp, 0, wxALL | wxALIGN_LEFT, 5);
|
sbSizer_speexpp->Add(m_ckboxSpeexpp, 0, wxALL | wxALIGN_LEFT, 5);
|
||||||
m_ckboxSpeexpp->SetToolTip(_("Enable noise suppression, dereverberation, AGC of mic signal"));
|
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);
|
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);
|
bSizer30->Add(sbSizer_speexpp, 0, wxALL | wxEXPAND, 5);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
m_ckboxFreeDV700txClip = new wxCheckBox(m_modemTab, wxID_ANY, _("Clipping"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
|
||||||
sbSizer_freedv700->Add(m_ckboxFreeDV700txClip, 0, wxALL | wxALIGN_LEFT, 5);
|
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);
|
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);
|
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_buttonChooseVoiceKeyerWaveFilePath->MoveBeforeInTabOrder(m_txtCtrlVoiceKeyerRxPause);
|
||||||
m_txtCtrlVoiceKeyerRxPause->MoveBeforeInTabOrder(m_txtCtrlVoiceKeyerRepeats);
|
m_txtCtrlVoiceKeyerRxPause->MoveBeforeInTabOrder(m_txtCtrlVoiceKeyerRepeats);
|
||||||
|
|
||||||
m_ckboxFreeDV700txClip->MoveBeforeInTabOrder(m_ckboxFreeDV700Combine);
|
m_ckboxFreeDV700txClip->MoveBeforeInTabOrder(m_ckboxFreeDV700txBPF);
|
||||||
m_ckboxFreeDV700Combine->MoveBeforeInTabOrder(m_ckboxFreeDV700txBPF);
|
|
||||||
m_ckboxFreeDV700txBPF->MoveBeforeInTabOrder(m_ckHalfDuplex);
|
m_ckboxFreeDV700txBPF->MoveBeforeInTabOrder(m_ckHalfDuplex);
|
||||||
m_ckHalfDuplex->MoveBeforeInTabOrder(m_ckboxMultipleRx);
|
m_ckHalfDuplex->MoveBeforeInTabOrder(m_ckboxMultipleRx);
|
||||||
m_ckboxMultipleRx->MoveBeforeInTabOrder(m_ckboxSingleRxThread);
|
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_ckboxTestFrame->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnTestFrame), NULL, this);
|
||||||
m_ckboxChannelNoise->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnChannelNoise), 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_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__
|
#ifdef __WXMSW__
|
||||||
m_ckboxDebugConsole->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnDebugConsole), NULL, this);
|
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_ckboxTestFrame->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnTestFrame), NULL, this);
|
||||||
m_ckboxChannelNoise->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnChannelNoise), 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_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_buttonChooseVoiceKeyerWaveFilePath->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnChooseVoiceKeyerWaveFilePath), NULL, this);
|
||||||
m_buttonChooseQuickRecordPath->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnChooseQuickRecordPath), 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_ckboxFreeDV700txClip->SetValue(wxGetApp().appConfiguration.freedv700Clip);
|
||||||
m_ckboxFreeDV700txBPF->SetValue(wxGetApp().appConfiguration.freedv700TxBPF);
|
m_ckboxFreeDV700txBPF->SetValue(wxGetApp().appConfiguration.freedv700TxBPF);
|
||||||
m_ckboxFreeDV700Combine->SetValue(wxGetApp().m_FreeDV700Combine);
|
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
m_ckboxDebugConsole->SetValue(wxGetApp().appConfiguration.debugConsoleEnabled);
|
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.freedv700Clip = m_ckboxFreeDV700txClip->GetValue();
|
||||||
wxGetApp().appConfiguration.freedv700TxBPF = m_ckboxFreeDV700txBPF->GetValue();
|
wxGetApp().appConfiguration.freedv700TxBPF = m_ckboxFreeDV700txBPF->GetValue();
|
||||||
wxGetApp().m_FreeDV700Combine = m_ckboxFreeDV700Combine->GetValue();
|
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
wxGetApp().appConfiguration.debugConsoleEnabled = m_ckboxDebugConsole->GetValue();
|
wxGetApp().appConfiguration.debugConsoleEnabled = m_ckboxDebugConsole->GetValue();
|
||||||
|
@ -1232,46 +1222,10 @@ void OptionsDlg::OnChooseQuickRecordPath(wxCommandEvent& event) {
|
||||||
m_txtCtrlQuickRecordPath->SetValue(pathDialog.GetPath());
|
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) {
|
void OptionsDlg::OnFreeDV700txClip(wxScrollEvent& event) {
|
||||||
wxGetApp().appConfiguration.freedv700Clip = m_ckboxFreeDV700txClip->GetValue();
|
wxGetApp().appConfiguration.freedv700Clip = m_ckboxFreeDV700txClip->GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionsDlg::OnFreeDV700Combine(wxScrollEvent& event) {
|
|
||||||
wxGetApp().m_FreeDV700Combine = m_ckboxFreeDV700Combine->GetValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OptionsDlg::OnDebugConsole(wxScrollEvent& event) {
|
void OptionsDlg::OnDebugConsole(wxScrollEvent& event) {
|
||||||
wxGetApp().appConfiguration.debugConsoleEnabled = m_ckboxDebugConsole->GetValue();
|
wxGetApp().appConfiguration.debugConsoleEnabled = m_ckboxDebugConsole->GetValue();
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
|
|
|
@ -63,9 +63,7 @@ class OptionsDlg : public wxDialog
|
||||||
|
|
||||||
void OnTestFrame(wxScrollEvent& event);
|
void OnTestFrame(wxScrollEvent& event);
|
||||||
void OnChannelNoise(wxScrollEvent& event);
|
void OnChannelNoise(wxScrollEvent& event);
|
||||||
void OnAttnCarrierEn(wxScrollEvent& event);
|
|
||||||
void OnFreeDV700txClip(wxScrollEvent& event);
|
void OnFreeDV700txClip(wxScrollEvent& event);
|
||||||
void OnFreeDV700Combine(wxScrollEvent& event);
|
|
||||||
void OnDebugConsole(wxScrollEvent& event);
|
void OnDebugConsole(wxScrollEvent& event);
|
||||||
|
|
||||||
void OnFifoReset(wxCommandEvent& event);
|
void OnFifoReset(wxCommandEvent& event);
|
||||||
|
@ -135,7 +133,6 @@ class OptionsDlg : public wxDialog
|
||||||
|
|
||||||
wxCheckBox *m_ckboxFreeDV700txClip;
|
wxCheckBox *m_ckboxFreeDV700txClip;
|
||||||
wxCheckBox *m_ckboxFreeDV700txBPF;
|
wxCheckBox *m_ckboxFreeDV700txBPF;
|
||||||
wxCheckBox *m_ckboxFreeDV700Combine;
|
|
||||||
|
|
||||||
wxRadioButton *m_rb_textEncoding1;
|
wxRadioButton *m_rb_textEncoding1;
|
||||||
wxRadioButton *m_rb_textEncoding2;
|
wxRadioButton *m_rb_textEncoding2;
|
||||||
|
|
426
src/main.cpp
426
src/main.cpp
|
@ -241,16 +241,12 @@ void MainApp::UnitTest_()
|
||||||
// Wait 100ms for FreeDV to come to foreground
|
// Wait 100ms for FreeDV to come to foreground
|
||||||
std::this_thread::sleep_for(100ms);
|
std::this_thread::sleep_for(100ms);
|
||||||
|
|
||||||
// Select FreeDV mode. Note, 2020 is deprecated so not testable here.
|
// Select FreeDV mode.
|
||||||
wxRadioButton* modeBtn = nullptr;
|
wxRadioButton* modeBtn = nullptr;
|
||||||
if (utFreeDVMode == "RADEV1")
|
if (utFreeDVMode == "RADEV1")
|
||||||
{
|
{
|
||||||
modeBtn = frame->m_rbRADE;
|
modeBtn = frame->m_rbRADE;
|
||||||
}
|
}
|
||||||
/*else if (utFreeDVMode == "700C")
|
|
||||||
{
|
|
||||||
modeBtn = frame->m_rb700c;
|
|
||||||
}*/
|
|
||||||
else if (utFreeDVMode == "700D")
|
else if (utFreeDVMode == "700D")
|
||||||
{
|
{
|
||||||
modeBtn = frame->m_rb700d;
|
modeBtn = frame->m_rb700d;
|
||||||
|
@ -259,10 +255,6 @@ void MainApp::UnitTest_()
|
||||||
{
|
{
|
||||||
modeBtn = frame->m_rb700e;
|
modeBtn = frame->m_rb700e;
|
||||||
}
|
}
|
||||||
/*else if (utFreeDVMode == "800XA")
|
|
||||||
{
|
|
||||||
modeBtn = frame->m_rb800xa;
|
|
||||||
}*/
|
|
||||||
else if (utFreeDVMode == "1600")
|
else if (utFreeDVMode == "1600")
|
||||||
{
|
{
|
||||||
modeBtn = frame->m_rb1600;
|
modeBtn = frame->m_rb1600;
|
||||||
|
@ -548,6 +540,11 @@ bool MainApp::OnInit()
|
||||||
wxString appPath(f.GetPath());
|
wxString appPath(f.GetPath());
|
||||||
wxSetWorkingDirectory(appPath);
|
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__
|
#if __APPLE__
|
||||||
// Set PYTHONPATH accordingly. We mainly want to be able to access
|
// Set PYTHONPATH accordingly. We mainly want to be able to access
|
||||||
// the model (,pth) as well as the RADE Python code.
|
// the model (,pth) as well as the RADE Python code.
|
||||||
|
@ -615,126 +612,6 @@ int MainApp::OnExit()
|
||||||
return 0;
|
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<nin; i++)
|
|
||||||
{
|
|
||||||
rx_fdm[i].real = (float)inputBuf[i];
|
|
||||||
rx_fdm[i].imag = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
freedv_comprx(fdv, outputBuf, rx_fdm);
|
|
||||||
}
|
|
||||||
auto endTime = systemClock.now();
|
|
||||||
auto timeTaken = std::chrono::duration_cast<std::chrono::milliseconds>(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.
|
// loadConfiguration_(): Loads or sets default configuration options.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
@ -873,10 +750,6 @@ setDefaultMode:
|
||||||
{
|
{
|
||||||
m_rb1600->SetValue(1);
|
m_rb1600->SetValue(1);
|
||||||
}
|
}
|
||||||
else if (mode == 3)
|
|
||||||
{
|
|
||||||
m_rb700c->SetValue(1);
|
|
||||||
}
|
|
||||||
else if (mode == 4)
|
else if (mode == 4)
|
||||||
{
|
{
|
||||||
m_rb700d->SetValue(1);
|
m_rb700d->SetValue(1);
|
||||||
|
@ -885,25 +758,10 @@ setDefaultMode:
|
||||||
{
|
{
|
||||||
m_rb700e->SetValue(1);
|
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)
|
else if (mode == FREEDV_MODE_RADE)
|
||||||
{
|
{
|
||||||
m_rbRADE->SetValue(1);
|
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
|
else
|
||||||
{
|
{
|
||||||
// Default to RADE otherwise
|
// Default to RADE otherwise
|
||||||
|
@ -912,21 +770,6 @@ setDefaultMode:
|
||||||
}
|
}
|
||||||
pConfig->SetPath(wxT("/"));
|
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_togBtnAnalog->Disable();
|
||||||
m_btnTogPTT->Disable();
|
m_btnTogPTT->Disable();
|
||||||
m_togBtnVoiceKeyer->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.
|
// Print RADE API version. This also forces the RADE library to be linked.
|
||||||
log_info("Using RADE API version %d", rade_version());
|
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)
|
if (wxGetApp().appConfiguration.firstTimeUse)
|
||||||
{
|
{
|
||||||
// Initial setup. Display Easy Setup dialog.
|
// Initial setup. Display Easy Setup dialog.
|
||||||
|
@ -1415,22 +1235,12 @@ MainFrame::~MainFrame()
|
||||||
int mode;
|
int mode;
|
||||||
if (m_rb1600->GetValue())
|
if (m_rb1600->GetValue())
|
||||||
mode = 0;
|
mode = 0;
|
||||||
if (m_rb700c->GetValue())
|
|
||||||
mode = 3;
|
|
||||||
if (m_rb700d->GetValue())
|
if (m_rb700d->GetValue())
|
||||||
mode = 4;
|
mode = 4;
|
||||||
if (m_rb700e->GetValue())
|
if (m_rb700e->GetValue())
|
||||||
mode = 5;
|
mode = 5;
|
||||||
if (m_rb800xa->GetValue())
|
|
||||||
mode = 6;
|
|
||||||
if (m_rb2020->GetValue())
|
|
||||||
mode = 9;
|
|
||||||
if (m_rbRADE->GetValue())
|
if (m_rbRADE->GetValue())
|
||||||
mode = FREEDV_MODE_RADE;
|
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.currentFreeDVMode = mode;
|
||||||
wxGetApp().appConfiguration.save(pConfig);
|
wxGetApp().appConfiguration.save(pConfig);
|
||||||
|
@ -1539,7 +1349,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int r,c;
|
int r;
|
||||||
|
|
||||||
if (m_panelWaterfall->checkDT()) {
|
if (m_panelWaterfall->checkDT()) {
|
||||||
m_panelWaterfall->setRxFreq(FDMDV_FCENTRE - g_RxFreqOffsetHz);
|
m_panelWaterfall->setRxFreq(FDMDV_FCENTRE - g_RxFreqOffsetHz);
|
||||||
|
@ -1575,18 +1385,6 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
||||||
}
|
}
|
||||||
wxGetApp().m_prevMode = currentMode;
|
wxGetApp().m_prevMode = currentMode;
|
||||||
|
|
||||||
if (currentMode == FREEDV_MODE_800XA) {
|
|
||||||
|
|
||||||
/* FSK Mode - eye diagram ---------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* add samples row by row */
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i=0; i<freedvInterface.getCurrentRxModemStats()->neyetr; i++) {
|
|
||||||
m_panelScatter->add_new_samples_eye(&freedvInterface.getCurrentRxModemStats()->rx_eye[i][0], freedvInterface.getCurrentRxModemStats()->neyesamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Reset g_Nc accordingly.
|
// Reset g_Nc accordingly.
|
||||||
switch(currentMode)
|
switch(currentMode)
|
||||||
{
|
{
|
||||||
|
@ -1594,28 +1392,11 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
||||||
g_Nc = 16;
|
g_Nc = 16;
|
||||||
m_panelScatter->setNc(g_Nc+1); /* +1 for BPSK pilot */
|
m_panelScatter->setNc(g_Nc+1); /* +1 for BPSK pilot */
|
||||||
break;
|
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_700D:
|
||||||
case FREEDV_MODE_700E:
|
case FREEDV_MODE_700E:
|
||||||
g_Nc = 17;
|
g_Nc = 17;
|
||||||
m_panelScatter->setNc(g_Nc);
|
m_panelScatter->setNc(g_Nc);
|
||||||
break;
|
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 -------------------------------------------------------*/
|
/* PSK Modes - scatter plot -------------------------------------------------------*/
|
||||||
|
@ -1623,44 +1404,11 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
||||||
|
|
||||||
if ((currentMode == FREEDV_MODE_1600) ||
|
if ((currentMode == FREEDV_MODE_1600) ||
|
||||||
(currentMode == FREEDV_MODE_700D) ||
|
(currentMode == FREEDV_MODE_700D) ||
|
||||||
(currentMode == FREEDV_MODE_700E) ||
|
(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]);
|
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; c<g_Nc/2; c++)
|
|
||||||
rx_symbols_copy[c] = fcmult(0.5, cadd(freedvInterface.getCurrentRxModemStats()->rx_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);
|
snprintf(syncmetric, STR_LENGTH, "Sync: %3.2f", freedvInterface.getCurrentRxModemStats()->sync_metric);
|
||||||
wxString syncmetric_string(syncmetric); m_textSyncMetric->SetLabel(syncmetric_string);
|
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();
|
auto var = freedvInterface.getVariance();
|
||||||
char var_str[STR_LENGTH]; snprintf(var_str, STR_LENGTH, "Var: %4.1f", var);
|
char var_str[STR_LENGTH]; snprintf(var_str, STR_LENGTH, "Var: %4.1f", var);
|
||||||
wxString var_string(var_str); m_textCodec2Var->SetLabel(var_string);
|
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);
|
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; i<sz_error_pattern; i++) {
|
|
||||||
/* maps to IQ bits from each symbol to a "carrier" (actually one line for each IQ bit in carrier order) */
|
|
||||||
c = floor(i/4);
|
|
||||||
/* this will clock in 4 bits/carrier to plot */
|
|
||||||
m_panelTestFrameErrors->add_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; b<hist_Nc; b++) {
|
|
||||||
ber[b+1] = (float)g_error_hist[b]/g_error_histn[b];
|
|
||||||
}
|
|
||||||
assert(hist_Nc <= 2*MODEM_STATS_NC_MAX);
|
|
||||||
m_panelTestFrameErrorsHist->add_new_samples(0, ber, 2*MODEM_STATS_NC_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_panelTestFrameErrors->Refresh();
|
m_panelTestFrameErrors->Refresh();
|
||||||
m_panelTestFrameErrorsHist->Refresh();
|
m_panelTestFrameErrorsHist->Refresh();
|
||||||
|
|
||||||
|
@ -2253,50 +1960,13 @@ void MainFrame::OnExit(wxCommandEvent& event)
|
||||||
|
|
||||||
void MainFrame::OnChangeTxMode( wxCommandEvent& event )
|
void MainFrame::OnChangeTxMode( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
wxRadioButton* hiddenModeToSet = nullptr;
|
|
||||||
std::vector<wxRadioButton*> 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();
|
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();
|
txModeChangeMutex.Lock();
|
||||||
|
|
||||||
if (eventObject == m_rb1600 || (eventObject == nullptr && m_rb1600->GetValue()))
|
if (eventObject == m_rb1600 || (eventObject == nullptr && m_rb1600->GetValue()))
|
||||||
{
|
{
|
||||||
g_mode = FREEDV_MODE_1600;
|
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()))
|
else if (eventObject == m_rbRADE || (eventObject == nullptr && m_rbRADE->GetValue()))
|
||||||
{
|
{
|
||||||
g_mode = FREEDV_MODE_RADE;
|
g_mode = FREEDV_MODE_RADE;
|
||||||
|
@ -2309,24 +1979,6 @@ void MainFrame::OnChangeTxMode( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
g_mode = FREEDV_MODE_700E;
|
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())
|
if (freedvInterface.isRunning())
|
||||||
{
|
{
|
||||||
|
@ -2340,21 +1992,6 @@ void MainFrame::OnChangeTxMode( wxCommandEvent& event )
|
||||||
|
|
||||||
txModeChangeMutex.Unlock();
|
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
|
// Report TX change to registered reporters
|
||||||
for (auto& obj : wxGetApp().m_reporters)
|
for (auto& obj : wxGetApp().m_reporters)
|
||||||
{
|
{
|
||||||
|
@ -2404,34 +2041,18 @@ void MainFrame::performFreeDVOn_()
|
||||||
{
|
{
|
||||||
m_rb1600->Disable();
|
m_rb1600->Disable();
|
||||||
m_rbRADE->Disable();
|
m_rbRADE->Disable();
|
||||||
m_rb700c->Disable();
|
|
||||||
m_rb700d->Disable();
|
m_rb700d->Disable();
|
||||||
m_rb700e->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);
|
freedvInterface.addRxMode(g_mode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_rbRADE->Disable();
|
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[] = {
|
int rxModes[] = {
|
||||||
FREEDV_MODE_1600,
|
FREEDV_MODE_1600,
|
||||||
FREEDV_MODE_700E,
|
FREEDV_MODE_700E,
|
||||||
FREEDV_MODE_700C,
|
|
||||||
FREEDV_MODE_700D,
|
FREEDV_MODE_700D,
|
||||||
FREEDV_MODE_800XA
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto& mode : rxModes)
|
for (auto& mode : rxModes)
|
||||||
|
@ -2444,14 +2065,8 @@ void MainFrame::performFreeDVOn_()
|
||||||
{
|
{
|
||||||
m_rb1600->Disable();
|
m_rb1600->Disable();
|
||||||
m_rbRADE->Disable();
|
m_rbRADE->Disable();
|
||||||
m_rb700c->Disable();
|
|
||||||
m_rb700d->Disable();
|
m_rb700d->Disable();
|
||||||
m_rb700e->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)
|
if (!wxGetApp().appConfiguration.reportingConfiguration.reportingEnabled)
|
||||||
freedvInterface.setTextVaricodeNum(1);
|
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;
|
g_State = g_prev_State = 0;
|
||||||
|
@ -2738,17 +2347,8 @@ void MainFrame::performFreeDVOff_()
|
||||||
|
|
||||||
m_rbRADE->Enable();
|
m_rbRADE->Enable();
|
||||||
m_rb1600->Enable();
|
m_rb1600->Enable();
|
||||||
m_rb700c->Enable();
|
|
||||||
m_rb700d->Enable();
|
m_rb700d->Enable();
|
||||||
m_rb700e->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.
|
// Make sure QSY button becomes disabled after stop.
|
||||||
if (m_reporterDialog != nullptr)
|
if (m_reporterDialog != nullptr)
|
||||||
|
@ -3158,7 +2758,7 @@ void MainFrame::startRxStream()
|
||||||
// stats for spectral plots, and transmit processng are all performed
|
// stats for spectral plots, and transmit processng are all performed
|
||||||
// in the tx/rxProcessing loop.
|
// 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
|
// the other FIFO sizes. This is to better handle PulseAudio/pipewire
|
||||||
// behavior on some devices, where the system sends multiple *seconds*
|
// behavior on some devices, where the system sends multiple *seconds*
|
||||||
// of audio samples at once followed by long periods with no samples at
|
// of audio samples at once followed by long periods with no samples at
|
||||||
|
@ -3171,7 +2771,7 @@ void MainFrame::startRxStream()
|
||||||
|
|
||||||
if (txInSoundDevice && txOutSoundDevice)
|
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;
|
int soundCard2OutFifoSizeSamples = m_fifoSize_ms*wxGetApp().appConfiguration.audioConfiguration.soundCard2Out.sampleRate / 1000;
|
||||||
g_rxUserdata->outfifo1 = codec2_fifo_create(soundCard1OutFifoSizeSamples);
|
g_rxUserdata->outfifo1 = codec2_fifo_create(soundCard1OutFifoSizeSamples);
|
||||||
g_rxUserdata->infifo2 = codec2_fifo_create(soundCard2InFifoSizeSamples);
|
g_rxUserdata->infifo2 = codec2_fifo_create(soundCard2InFifoSizeSamples);
|
||||||
|
@ -3447,7 +3047,7 @@ void MainFrame::startRxStream()
|
||||||
// start tx/rx processing thread
|
// start tx/rx processing thread
|
||||||
if (txInSoundDevice && txOutSoundDevice)
|
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 )
|
if ( m_txThread->Create() != wxTHREAD_NO_ERROR )
|
||||||
{
|
{
|
||||||
wxLogError(wxT("Can't create TX thread!"));
|
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 )
|
if ( m_rxThread->Create() != wxTHREAD_NO_ERROR )
|
||||||
{
|
{
|
||||||
wxLogError(wxT("Can't create RX thread!"));
|
wxLogError(wxT("Can't create RX thread!"));
|
||||||
|
|
|
@ -506,11 +506,6 @@ class MainFrame : public TopFrame
|
||||||
|
|
||||||
HamlibRigController::Mode getCurrentMode_();
|
HamlibRigController::Mode getCurrentMode_();
|
||||||
|
|
||||||
#if defined(FREEDV_MODE_2020)
|
|
||||||
void test2020Mode_();
|
|
||||||
bool test2020HWAllowed_();
|
|
||||||
#endif // defined(FREEDV_MODE_2020)
|
|
||||||
|
|
||||||
void performFreeDVOn_();
|
void performFreeDVOn_();
|
||||||
void performFreeDVOff_();
|
void performFreeDVOff_();
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,6 @@
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
|
||||||
#include "main.h"
|
#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_easy_setup.h"
|
||||||
#include "gui/dialogs/dlg_filter.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 version: %s\n")
|
||||||
wxT("freedv-gui git hash: %s\n")
|
wxT("freedv-gui git hash: %s\n")
|
||||||
wxT("codec2 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()
|
, 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);
|
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
|
// Works around issues on wxWidgets with certain controls not changing backgrounds
|
||||||
// when the user switches between light and dark mode.
|
// when the user switches between light and dark mode.
|
||||||
wxColour currentControlBackground = wxTransparentColour;
|
wxColour currentControlBackground = wxTransparentColour;
|
||||||
|
|
||||||
m_collpane->SetBackgroundColour(currentControlBackground);
|
|
||||||
m_collpane->GetPane()->SetBackgroundColour(currentControlBackground);
|
|
||||||
TopFrame::OnSystemColorChanged(event);
|
TopFrame::OnSystemColorChanged(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,10 +65,11 @@ FreeDVReceiveStep::~FreeDVReceiveStep()
|
||||||
delete[] inputBuf_;
|
delete[] inputBuf_;
|
||||||
delete[] rxFdm_;
|
delete[] rxFdm_;
|
||||||
delete[] rxFdmOffset_;
|
delete[] rxFdmOffset_;
|
||||||
|
outputSamples_ = nullptr;
|
||||||
|
|
||||||
if (inputSampleFifo_ != nullptr)
|
if (inputSampleFifo_ != nullptr)
|
||||||
{
|
{
|
||||||
codec2_fifo_free(inputSampleFifo_);
|
codec2_fifo_destroy(inputSampleFifo_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +85,8 @@ int FreeDVReceiveStep::getOutputSampleRate() const
|
||||||
|
|
||||||
std::shared_ptr<short> FreeDVReceiveStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
std::shared_ptr<short> FreeDVReceiveStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
||||||
{
|
{
|
||||||
|
auto maxSamples = std::max(getInputSampleRate(), getOutputSampleRate());
|
||||||
|
auto maxSpeechSamples = freedv_get_n_max_speech_samples(dv_);
|
||||||
*numOutputSamples = 0;
|
*numOutputSamples = 0;
|
||||||
|
|
||||||
short* inputPtr = inputSamples.get();
|
short* inputPtr = inputSamples.get();
|
||||||
|
@ -94,7 +97,7 @@ std::shared_ptr<short> FreeDVReceiveStep::execute(std::shared_ptr<short> inputSa
|
||||||
|
|
||||||
int nin = freedv_nin(dv_);
|
int nin = freedv_nin(dv_);
|
||||||
int nout = 0;
|
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_));
|
assert(nin <= freedv_get_n_max_modem_samples(dv_));
|
||||||
|
|
||||||
|
|
|
@ -68,10 +68,11 @@ FreeDVTransmitStep::~FreeDVTransmitStep()
|
||||||
delete[] codecInput_;
|
delete[] codecInput_;
|
||||||
delete[] txFdm_;
|
delete[] txFdm_;
|
||||||
delete[] txFdmOffset_;
|
delete[] txFdmOffset_;
|
||||||
|
delete[] tmpOutput_;
|
||||||
|
|
||||||
if (inputSampleFifo_ != nullptr)
|
if (inputSampleFifo_ != nullptr)
|
||||||
{
|
{
|
||||||
codec2_fifo_free(inputSampleFifo_);
|
codec2_fifo_destroy(inputSampleFifo_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@ int FreeDVTransmitStep::getOutputSampleRate() const
|
||||||
|
|
||||||
std::shared_ptr<short> FreeDVTransmitStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
std::shared_ptr<short> FreeDVTransmitStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
||||||
{
|
{
|
||||||
|
auto maxSamples = std::max(getInputSampleRate(), getOutputSampleRate());
|
||||||
int mode = freedv_get_mode(dv_);
|
int mode = freedv_get_mode(dv_);
|
||||||
int samplesUsedForFifo = freedv_get_n_speech_samples(dv_);
|
int samplesUsedForFifo = freedv_get_n_speech_samples(dv_);
|
||||||
int nfreedv = freedv_get_n_nom_modem_samples(dv_);
|
int nfreedv = freedv_get_n_nom_modem_samples(dv_);
|
||||||
|
@ -99,7 +101,7 @@ std::shared_ptr<short> FreeDVTransmitStep::execute(std::shared_ptr<short> inputS
|
||||||
codec2_fifo_write(inputSampleFifo_, inputPtr++, 1);
|
codec2_fifo_write(inputSampleFifo_, inputPtr++, 1);
|
||||||
numInputSamples--;
|
numInputSamples--;
|
||||||
|
|
||||||
if (codec2_fifo_used(inputSampleFifo_) >= samplesUsedForFifo)
|
if ((*numOutputSamples + nfreedv) < maxSamples && codec2_fifo_used(inputSampleFifo_) >= samplesUsedForFifo)
|
||||||
{
|
{
|
||||||
codec2_fifo_read(inputSampleFifo_, codecInput_, samplesUsedForFifo);
|
codec2_fifo_read(inputSampleFifo_, codecInput_, samplesUsedForFifo);
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,11 @@ LinkStep::~LinkStep()
|
||||||
|
|
||||||
void LinkStep::clearFifo()
|
void LinkStep::clearFifo()
|
||||||
{
|
{
|
||||||
int numUsed = codec2_fifo_used(fifo_);
|
|
||||||
|
|
||||||
// Read data and then promptly throw it out.
|
// 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<short> LinkStep::InputStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
std::shared_ptr<short> LinkStep::InputStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "../defines.h"
|
||||||
#include "ParallelStep.h"
|
#include "ParallelStep.h"
|
||||||
#include "AudioPipeline.h"
|
#include "AudioPipeline.h"
|
||||||
#include "../util/logging/ulog.h"
|
#include "../util/logging/ulog.h"
|
||||||
|
@ -132,7 +133,7 @@ ParallelStep::ParallelStep(
|
||||||
|
|
||||||
if (fallbackToSleep)
|
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->inputFifo);
|
||||||
codec2_fifo_destroy(taskThread->outputFifo);
|
codec2_fifo_destroy(taskThread->outputFifo);
|
||||||
|
taskThread->step = nullptr;
|
||||||
|
taskThread->tempInput = nullptr;
|
||||||
|
taskThread->tempOutput = nullptr;
|
||||||
delete taskThread;
|
delete taskThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force immediate memory clear
|
||||||
|
parallelSteps_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ParallelStep::getInputSampleRate() const
|
int ParallelStep::getInputSampleRate() const
|
||||||
|
@ -239,7 +246,6 @@ std::shared_ptr<short> ParallelStep::execute(std::shared_ptr<short> inputSamples
|
||||||
assert(stepToOutput >= 0 && (size_t)stepToOutput < parallelSteps_.size());
|
assert(stepToOutput >= 0 && (size_t)stepToOutput < parallelSteps_.size());
|
||||||
|
|
||||||
ThreadInfo* outputTask = threads_[stepToOutput];
|
ThreadInfo* outputTask = threads_[stepToOutput];
|
||||||
|
|
||||||
*numOutputSamples = codec2_fifo_used(outputTask->outputFifo);
|
*numOutputSamples = codec2_fifo_used(outputTask->outputFifo);
|
||||||
codec2_fifo_read(outputTask->outputFifo, outputTask->tempOutput.get(), *numOutputSamples);
|
codec2_fifo_read(outputTask->outputFifo, outputTask->tempOutput.get(), *numOutputSamples);
|
||||||
return outputTask->tempOutput;
|
return outputTask->tempOutput;
|
||||||
|
|
|
@ -77,6 +77,7 @@ RADEReceiveStep::~RADEReceiveStep()
|
||||||
delete[] inputBufCplx_;
|
delete[] inputBufCplx_;
|
||||||
delete[] featuresOut_;
|
delete[] featuresOut_;
|
||||||
delete[] eooOut_;
|
delete[] eooOut_;
|
||||||
|
outputSamples_ = nullptr;
|
||||||
|
|
||||||
if (featuresFile_ != nullptr)
|
if (featuresFile_ != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -85,12 +86,12 @@ RADEReceiveStep::~RADEReceiveStep()
|
||||||
|
|
||||||
if (inputSampleFifo_ != nullptr)
|
if (inputSampleFifo_ != nullptr)
|
||||||
{
|
{
|
||||||
codec2_fifo_free(inputSampleFifo_);
|
codec2_fifo_destroy(inputSampleFifo_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputSampleFifo_ != nullptr)
|
if (outputSampleFifo_ != nullptr)
|
||||||
{
|
{
|
||||||
codec2_fifo_free(outputSampleFifo_);
|
codec2_fifo_destroy(outputSampleFifo_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +107,7 @@ int RADEReceiveStep::getOutputSampleRate() const
|
||||||
|
|
||||||
std::shared_ptr<short> RADEReceiveStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
std::shared_ptr<short> RADEReceiveStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
||||||
{
|
{
|
||||||
|
auto maxSamples = std::max(getInputSampleRate(), getOutputSampleRate());
|
||||||
*numOutputSamples = 0;
|
*numOutputSamples = 0;
|
||||||
|
|
||||||
short* inputPtr = inputSamples.get();
|
short* inputPtr = inputSamples.get();
|
||||||
|
@ -116,7 +118,7 @@ std::shared_ptr<short> RADEReceiveStep::execute(std::shared_ptr<short> inputSamp
|
||||||
|
|
||||||
int nin = rade_nin(dv_);
|
int nin = rade_nin(dv_);
|
||||||
int nout = 0;
|
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_));
|
assert(nin <= rade_nin_max(dv_));
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ RADETransmitStep::~RADETransmitStep()
|
||||||
delete[] radeOutShort_;
|
delete[] radeOutShort_;
|
||||||
delete[] eooOut_;
|
delete[] eooOut_;
|
||||||
delete[] eooOutShort_;
|
delete[] eooOutShort_;
|
||||||
|
outputSamples_ = nullptr;
|
||||||
|
|
||||||
if (featuresFile_ != nullptr)
|
if (featuresFile_ != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -90,12 +91,12 @@ RADETransmitStep::~RADETransmitStep()
|
||||||
|
|
||||||
if (inputSampleFifo_ != nullptr)
|
if (inputSampleFifo_ != nullptr)
|
||||||
{
|
{
|
||||||
codec2_fifo_free(inputSampleFifo_);
|
codec2_fifo_destroy(inputSampleFifo_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputSampleFifo_ != nullptr)
|
if (outputSampleFifo_ != nullptr)
|
||||||
{
|
{
|
||||||
codec2_fifo_free(inputSampleFifo_);
|
codec2_fifo_destroy(outputSampleFifo_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,16 +112,18 @@ int RADETransmitStep::getOutputSampleRate() const
|
||||||
|
|
||||||
std::shared_ptr<short> RADETransmitStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
std::shared_ptr<short> RADETransmitStep::execute(std::shared_ptr<short> inputSamples, int numInputSamples, int* numOutputSamples)
|
||||||
{
|
{
|
||||||
|
auto maxSamples = std::max(getInputSampleRate(), getOutputSampleRate());
|
||||||
|
int numSamplesPerTx = rade_n_tx_out(dv_);
|
||||||
|
|
||||||
*numOutputSamples = 0;
|
*numOutputSamples = 0;
|
||||||
|
|
||||||
if (numInputSamples == 0)
|
if (numInputSamples == 0)
|
||||||
{
|
{
|
||||||
// Special case logic for EOO -- make sure we only send 20ms worth at a time
|
// Special case logic for EOO
|
||||||
*numOutputSamples = std::min(codec2_fifo_used(outputSampleFifo_), (int)(RADE_MODEM_SAMPLE_RATE * .02));
|
*numOutputSamples = codec2_fifo_used(outputSampleFifo_);
|
||||||
if (*numOutputSamples > 0)
|
if (*numOutputSamples > 0)
|
||||||
{
|
{
|
||||||
codec2_fifo_read(outputSampleFifo_, outputSamples_.get(), *numOutputSamples);
|
codec2_fifo_read(outputSampleFifo_, outputSamples_.get(), *numOutputSamples);
|
||||||
|
|
||||||
log_info("Returning %d EOO samples (remaining in FIFO: %d)", *numOutputSamples, codec2_fifo_used(outputSampleFifo_));
|
log_info("Returning %d EOO samples (remaining in FIFO: %d)", *numOutputSamples, codec2_fifo_used(outputSampleFifo_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,10 +136,9 @@ std::shared_ptr<short> RADETransmitStep::execute(std::shared_ptr<short> inputSam
|
||||||
codec2_fifo_write(inputSampleFifo_, inputPtr++, 1);
|
codec2_fifo_write(inputSampleFifo_, inputPtr++, 1);
|
||||||
numInputSamples--;
|
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_);
|
unsigned int numRequiredFeaturesForRADE = rade_n_features_in_out(dv_);
|
||||||
int numOutputSamples = rade_n_tx_out(dv_);
|
|
||||||
short pcm[LPCNET_FRAME_SIZE];
|
short pcm[LPCNET_FRAME_SIZE];
|
||||||
float features[NB_TOTAL_FEATURES];
|
float features[NB_TOTAL_FEATURES];
|
||||||
|
|
||||||
|
@ -164,12 +166,12 @@ std::shared_ptr<short> RADETransmitStep::execute(std::shared_ptr<short> inputSam
|
||||||
{
|
{
|
||||||
featureList_.erase(featureList_.begin());
|
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.
|
// We only need the real component for TX.
|
||||||
radeOutShort_[index] = radeOut_[index].real * RADE_SCALING_FACTOR;
|
radeOutShort_[index] = radeOut_[index].real * RADE_SCALING_FACTOR;
|
||||||
}
|
}
|
||||||
codec2_fifo_write(outputSampleFifo_, radeOutShort_, numOutputSamples);
|
codec2_fifo_write(outputSampleFifo_, radeOutShort_, numSamplesPerTx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,9 @@ SpeexStep::SpeexStep(int sampleRate)
|
||||||
|
|
||||||
SpeexStep::~SpeexStep()
|
SpeexStep::~SpeexStep()
|
||||||
{
|
{
|
||||||
|
outputSamples_ = nullptr;
|
||||||
speex_preprocess_state_destroy(speexStateObj_);
|
speex_preprocess_state_destroy(speexStateObj_);
|
||||||
codec2_fifo_free(inputSampleFifo_);
|
codec2_fifo_destroy(inputSampleFifo_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SpeexStep::getInputSampleRate() const
|
int SpeexStep::getInputSampleRate() const
|
||||||
|
|
|
@ -96,7 +96,6 @@ extern FreeDVInterface freedvInterface;
|
||||||
|
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
extern wxMutex txModeChangeMutex;
|
|
||||||
extern wxWindow* g_parent;
|
extern wxWindow* g_parent;
|
||||||
|
|
||||||
#include <sndfile.h>
|
#include <sndfile.h>
|
||||||
|
@ -218,7 +217,11 @@ void TxRxThread::initializePipeline_()
|
||||||
auto analogTxPipeline = new AudioPipeline(inputSampleRate_, outputSampleRate_);
|
auto analogTxPipeline = new AudioPipeline(inputSampleRate_, outputSampleRate_);
|
||||||
analogTxPipeline->appendPipelineStep(std::shared_ptr<IPipelineStep>(doubleLevelStep));
|
analogTxPipeline->appendPipelineStep(std::shared_ptr<IPipelineStep>(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_);
|
auto digitalTxPipeline = new AudioPipeline(inputSampleRate_, outputSampleRate_);
|
||||||
digitalTxPipeline->appendPipelineStep(std::shared_ptr<IPipelineStep>(digitalTxStep));
|
digitalTxPipeline->appendPipelineStep(std::shared_ptr<IPipelineStep>(digitalTxStep));
|
||||||
|
|
||||||
|
@ -460,16 +463,6 @@ void* TxRxThread::Entry()
|
||||||
pthread_setname_np(pthread_self(), threadName);
|
pthread_setname_np(pthread_self(), threadName);
|
||||||
#endif // defined(__linux__)
|
#endif // defined(__linux__)
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> 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;
|
if (!m_run) break;
|
||||||
|
|
||||||
//log_info("thread woken up: m_tx=%d", (int)m_tx);
|
//log_info("thread woken up: m_tx=%d", (int)m_tx);
|
||||||
|
@ -492,8 +485,7 @@ void* TxRxThread::Entry()
|
||||||
|
|
||||||
void TxRxThread::OnExit()
|
void TxRxThread::OnExit()
|
||||||
{
|
{
|
||||||
// Free allocated buffer.
|
// empty
|
||||||
inputSamples_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TxRxThread::terminateThread()
|
void TxRxThread::terminateThread()
|
||||||
|
@ -504,10 +496,7 @@ void TxRxThread::terminateThread()
|
||||||
|
|
||||||
void TxRxThread::notify()
|
void TxRxThread::notify()
|
||||||
{
|
{
|
||||||
#if 0
|
// empty
|
||||||
std::unique_lock<std::mutex> lk(m_processingMutex);
|
|
||||||
m_processingCondVar.notify_all();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TxRxThread::clearFifos_()
|
void TxRxThread::clearFifos_()
|
||||||
|
@ -521,31 +510,27 @@ void TxRxThread::clearFifos_()
|
||||||
|
|
||||||
if (m_tx)
|
if (m_tx)
|
||||||
{
|
{
|
||||||
auto used = codec2_fifo_used(cbData->outfifo1);
|
while (codec2_fifo_used(cbData->outfifo1) > 0)
|
||||||
if (used > 0)
|
|
||||||
{
|
{
|
||||||
codec2_fifo_read(cbData->outfifo1, inputSamples_.get(), used);
|
codec2_fifo_read(cbData->outfifo1, inputSamples_.get(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
used = codec2_fifo_used(cbData->infifo2);
|
while (codec2_fifo_used(cbData->infifo2) > 0)
|
||||||
if (used > 0)
|
|
||||||
{
|
{
|
||||||
codec2_fifo_read(cbData->infifo2, inputSamples_.get(), used);
|
codec2_fifo_read(cbData->infifo2, inputSamples_.get(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto used = codec2_fifo_used(cbData->infifo1);
|
while (codec2_fifo_used(cbData->infifo1) > 0)
|
||||||
if (used > 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;
|
auto outFifo = (g_nSoundCards == 1) ? cbData->outfifo1 : cbData->outfifo2;
|
||||||
used = codec2_fifo_used(outFifo);
|
while (codec2_fifo_used(outFifo) > 0)
|
||||||
if (used > 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))) {
|
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)
|
if (pipeline_ == nullptr)
|
||||||
{
|
{
|
||||||
initializePipeline_();
|
initializePipeline_();
|
||||||
|
@ -637,7 +619,7 @@ void TxRxThread::txProcessing_()
|
||||||
log_debug("Injecting %d samples of resampled EOO into TX stream", nout);
|
log_debug("Injecting %d samples of resampled EOO into TX stream", nout);
|
||||||
if (codec2_fifo_write(cbData->outfifo1, outputSamples.get(), nout) != 0)
|
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
|
else
|
||||||
|
@ -664,8 +646,6 @@ void TxRxThread::txProcessing_()
|
||||||
codec2_fifo_write(cbData->outfifo1, outputSamples.get(), nout);
|
codec2_fifo_write(cbData->outfifo1, outputSamples.get(), nout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
txModeChangeMutex.Unlock();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,7 @@ class LinkStep;
|
||||||
class TxRxThread : public wxThread
|
class TxRxThread : public wxThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TxRxThread(bool tx, int inputSampleRate, int outputSampleRate, LinkStep* micAudioLink, std::shared_ptr<IRealtimeHelper> helper)
|
TxRxThread(bool tx, int inputSampleRate, int outputSampleRate, std::shared_ptr<LinkStep> micAudioLink, std::shared_ptr<IRealtimeHelper> helper)
|
||||||
: wxThread(wxTHREAD_JOINABLE)
|
: wxThread(wxTHREAD_JOINABLE)
|
||||||
, m_tx(tx)
|
, m_tx(tx)
|
||||||
, m_run(1)
|
, m_run(1)
|
||||||
|
@ -75,16 +75,13 @@ public:
|
||||||
void terminateThread();
|
void terminateThread();
|
||||||
void notify();
|
void notify();
|
||||||
|
|
||||||
std::mutex m_processingMutex;
|
|
||||||
std::condition_variable m_processingCondVar;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_tx;
|
bool m_tx;
|
||||||
bool m_run;
|
bool m_run;
|
||||||
std::shared_ptr<AudioPipeline> pipeline_;
|
std::shared_ptr<AudioPipeline> pipeline_;
|
||||||
int inputSampleRate_;
|
int inputSampleRate_;
|
||||||
int outputSampleRate_;
|
int outputSampleRate_;
|
||||||
LinkStep* equalizedMicAudioLink_;
|
std::shared_ptr<LinkStep> equalizedMicAudioLink_;
|
||||||
bool hasEooBeenSent_;
|
bool hasEooBeenSent_;
|
||||||
std::shared_ptr<IRealtimeHelper> helper_;
|
std::shared_ptr<IRealtimeHelper> helper_;
|
||||||
std::shared_ptr<short> inputSamples_;
|
std::shared_ptr<short> inputSamples_;
|
||||||
|
|
|
@ -15,7 +15,7 @@ std::uniform_real_distribution<double> distribution(-0.789, 0.789);
|
||||||
|
|
||||||
void OnRadeTextRx(rade_text_t rt, const char* txt_ptr, int length, void* state)
|
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);
|
testPassed = !strncmp(txt_ptr, "K6AQ", length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,14 @@ int main()
|
||||||
// Send silence through to RX step to trigger EOO processing
|
// Send silence through to RX step to trigger EOO processing
|
||||||
recvStep->execute(inputSamplesPtr, 16384, &noutRx);
|
recvStep->execute(inputSamplesPtr, 16384, &noutRx);
|
||||||
|
|
||||||
|
delete recvStep;
|
||||||
|
delete txStep;
|
||||||
|
|
||||||
rade_close(rade);
|
rade_close(rade);
|
||||||
rade_finalize();
|
rade_finalize();
|
||||||
|
|
||||||
|
rade_text_destroy(txt);
|
||||||
|
lpcnet_encoder_destroy(encState);
|
||||||
|
|
||||||
return testPassed ? 0 : 1;
|
return testPassed ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -680,36 +680,6 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const
|
||||||
sbSizer_mode->Add(m_rb700e, 0, wxALIGN_LEFT|wxALL, 1);
|
sbSizer_mode->Add(m_rb700e, 0, wxALIGN_LEFT|wxALL, 1);
|
||||||
m_rb1600 = new wxRadioButton( modeBox, wxID_ANY, wxT("1600"), wxDefaultPosition, wxDefaultSize, 0);
|
m_rb1600 = new wxRadioButton( modeBox, wxID_ANY, wxT("1600"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
sbSizer_mode->Add(m_rb1600, 0, wxALIGN_LEFT|wxALL, 1);
|
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);
|
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_auiNbookCtrl->MoveBeforeInTabOrder(m_BtnCallSignReset);
|
||||||
m_sliderSQ->MoveBeforeInTabOrder(m_ckboxSQ);
|
m_sliderSQ->MoveBeforeInTabOrder(m_ckboxSQ);
|
||||||
|
m_rbRADE->MoveBeforeInTabOrder(m_rb700d);
|
||||||
m_rb700d->MoveBeforeInTabOrder(m_rb700e);
|
m_rb700d->MoveBeforeInTabOrder(m_rb700e);
|
||||||
m_rb700e->MoveBeforeInTabOrder(m_rb1600);
|
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_togBtnOnOff->MoveBeforeInTabOrder(m_togBtnAnalog);
|
||||||
m_togBtnAnalog->MoveBeforeInTabOrder(m_togBtnVoiceKeyer);
|
m_togBtnAnalog->MoveBeforeInTabOrder(m_togBtnVoiceKeyer);
|
||||||
m_togBtnVoiceKeyer->MoveBeforeInTabOrder(m_btnTogPTT);
|
m_togBtnVoiceKeyer->MoveBeforeInTabOrder(m_btnTogPTT);
|
||||||
|
@ -854,17 +820,9 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const
|
||||||
m_btnCenterRx->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnCenterRx), NULL, this);
|
m_btnCenterRx->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnCenterRx), NULL, this);
|
||||||
|
|
||||||
m_rbRADE->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), 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_rb700d->Connect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this);
|
||||||
m_rb700e->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_TOP, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this);
|
||||||
m_sliderTxLevel->Connect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this);
|
m_sliderTxLevel->Connect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this);
|
||||||
|
@ -938,17 +896,9 @@ TopFrame::~TopFrame()
|
||||||
m_audioRecord->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnRecord), NULL, this);
|
m_audioRecord->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnRecord), NULL, this);
|
||||||
|
|
||||||
m_rbRADE->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), 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_rb700d->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(TopFrame::OnChangeTxMode), NULL, this);
|
||||||
m_rb700e->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_TOP, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this);
|
||||||
m_sliderTxLevel->Disconnect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this);
|
m_sliderTxLevel->Disconnect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnChangeTxLevel), NULL, this);
|
||||||
|
@ -968,15 +918,6 @@ TopFrame::~TopFrame()
|
||||||
m_cboReportFrequency->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(TopFrame::OnReportFrequencyKillFocus), NULL, this);
|
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)
|
void TopFrame::setVoiceKeyerButtonLabel_(wxString filename)
|
||||||
{
|
{
|
||||||
wxString vkLabel = _("Voice Keyer");
|
wxString vkLabel = _("Voice Keyer");
|
||||||
|
|
|
@ -130,22 +130,12 @@ class TopFrame : public wxFrame
|
||||||
wxToggleButton *m_audioRecord;
|
wxToggleButton *m_audioRecord;
|
||||||
|
|
||||||
wxRadioButton *m_rbRADE;
|
wxRadioButton *m_rbRADE;
|
||||||
wxRadioButton *m_rb700c;
|
|
||||||
wxRadioButton *m_rb700d;
|
wxRadioButton *m_rb700d;
|
||||||
wxRadioButton *m_rb700e;
|
wxRadioButton *m_rb700e;
|
||||||
wxRadioButton *m_rb800xa;
|
|
||||||
wxRadioButton *m_rb1600;
|
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;
|
wxSizer* rightSizer;
|
||||||
|
|
||||||
wxCollapsiblePane *m_collpane;
|
|
||||||
wxStaticBox* modeBox;
|
wxStaticBox* modeBox;
|
||||||
wxStaticBoxSizer* sbSizer_mode;
|
wxStaticBoxSizer* sbSizer_mode;
|
||||||
|
|
||||||
|
@ -217,8 +207,6 @@ class TopFrame : public wxFrame
|
||||||
virtual void OnChangeReportFrequency( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnChangeReportFrequency( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnChangeReportFrequencyVerify( 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 OnReportFrequencySetFocus(wxFocusEvent& event) { event.Skip(); }
|
||||||
virtual void OnReportFrequencyKillFocus(wxFocusEvent& event) { event.Skip(); }
|
virtual void OnReportFrequencyKillFocus(wxFocusEvent& event) { event.Skip(); }
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ void MainFrame::OpenPTTInPort(void)
|
||||||
wxGetApp().m_pttInSerialPort->onPttChange += [&](IRigController*, bool pttState)
|
wxGetApp().m_pttInSerialPort->onPttChange += [&](IRigController*, bool pttState)
|
||||||
{
|
{
|
||||||
log_info("PTT input state is now %d", pttState);
|
log_info("PTT input state is now %d", pttState);
|
||||||
GetEventHandler()->CallAfter([&]() {
|
GetEventHandler()->CallAfter([this, pttState]() {
|
||||||
if (pttState != m_btnTogPTT->GetValue())
|
if (pttState != m_btnTogPTT->GetValue())
|
||||||
{
|
{
|
||||||
m_btnTogPTT->SetValue(pttState);
|
m_btnTogPTT->SetValue(pttState);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
interceptor_via_lib:hamlib
|
|
@ -107,7 +107,7 @@ ManualFrequencyReporting=1
|
||||||
DirectionAsCardinal=0
|
DirectionAsCardinal=0
|
||||||
Frequency=14236000
|
Frequency=14236000
|
||||||
[Reporting/PSKReporter]
|
[Reporting/PSKReporter]
|
||||||
Enable=1
|
Enable=0
|
||||||
[Reporting/FreeDV]
|
[Reporting/FreeDV]
|
||||||
Enable=1
|
Enable=1
|
||||||
Hostname=qso.freedv.org
|
Hostname=qso.freedv.org
|
||||||
|
|
|
@ -108,7 +108,7 @@ ManualFrequencyReporting=1
|
||||||
DirectionAsCardinal=0
|
DirectionAsCardinal=0
|
||||||
Frequency=14236000
|
Frequency=14236000
|
||||||
[Reporting/PSKReporter]
|
[Reporting/PSKReporter]
|
||||||
Enable=1
|
Enable=0
|
||||||
[Reporting/FreeDV]
|
[Reporting/FreeDV]
|
||||||
Enable=1
|
Enable=1
|
||||||
Hostname=qso.freedv.org
|
Hostname=qso.freedv.org
|
||||||
|
|
|
@ -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
|
|
@ -80,14 +80,20 @@ if [ "$2" == "mpp" ]; then
|
||||||
else
|
else
|
||||||
TX_ARGS="-txtime 5 "
|
TX_ARGS="-txtime 5 "
|
||||||
fi
|
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=$!
|
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
|
#sleep 30
|
||||||
#screencapture ../screenshot.png
|
#screencapture ../screenshot.png
|
||||||
#wpctl status
|
#wpctl status
|
||||||
#pw-top -b -n 5
|
#pw-top -b -n 5
|
||||||
#wait $FDV_PID
|
wait $FDV_PID
|
||||||
|
cat tmp.log
|
||||||
|
|
||||||
# Stop recording, play back in RX mode
|
# Stop recording, play back in RX mode
|
||||||
kill $RECORD_PID
|
kill $RECORD_PID
|
||||||
|
@ -107,7 +113,15 @@ if [ "$1" != "" ]; then
|
||||||
mv $(pwd)/testwithnoise.wav $(pwd)/test.wav
|
mv $(pwd)/testwithnoise.wav $(pwd)/test.wav
|
||||||
fi
|
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
|
# Clean up PulseAudio virtual devices
|
||||||
if [ "$OPERATING_SYSTEM" == "Linux" ]; then
|
if [ "$OPERATING_SYSTEM" == "Linux" ]; then
|
||||||
|
@ -120,3 +134,5 @@ fi
|
||||||
|
|
||||||
# End radio process as it's no longer needed
|
# End radio process as it's no longer needed
|
||||||
kill $RADIO_PID
|
kill $RADIO_PID
|
||||||
|
|
||||||
|
exit $FREEDV_EXIT_CODE
|
||||||
|
|
|
@ -93,14 +93,21 @@ if [ "$FREEDV_TEST" == "tx" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Start FreeDV in test mode
|
# 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=$!
|
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
|
#sleep 30
|
||||||
#screencapture ../screenshot.png
|
#screencapture ../screenshot.png
|
||||||
#wpctl status
|
#wpctl status
|
||||||
#pw-top -b -n 5
|
#pw-top -b -n 5
|
||||||
#wait $FDV_PID
|
wait $FDV_PID
|
||||||
|
FREEDV_EXIT_STATUS=$?
|
||||||
|
cat tmp.log
|
||||||
|
|
||||||
# Stop recording/playback and process data
|
# Stop recording/playback and process data
|
||||||
if [ "$FREEDV_TEST" == "rx" ]; then
|
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_COMPUTER_TO_RADIO
|
||||||
pactl unload-module $DRIVER_INDEX_FREEDV_MICROPHONE_TO_COMPUTER
|
pactl unload-module $DRIVER_INDEX_FREEDV_MICROPHONE_TO_COMPUTER
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
exit $FREEDV_EXIT_STATUS
|
||||||
|
|
Loading…
Reference in New Issue