Remove 800XA, 700C, 2020 and 2020B. (#889)

* Remove 800XA, 700C, 2020 and 2020B from UI,

* Remove additional 700C references in UI.

* Remove 2020/AVX detection logic from codebase.

* Remove LPCNet from build scripts.

* Add PR #889 to changelog.

* Forgot to remove LPCNet from Windows installer generation.

* Generate Release build for GH workflows.

* Disable PSK Reporter reporting during test execution as invalid callsigns are used.

* Build type was being overwritten.

* Missed mutex removal.

* Temporarily use Instruments to trace macOS CI execution.

* Minor update.

* Use 2 minute window in xctrace to actually capture wanted events.

* Disable xctrace execution but keep in tests just in case.

* Hide main window during tests to prevent GUI from interfering.

* Experiment: set infifo2 max length to 30 seconds

* Oops, forgot to remove division from previous commit.

* Deallocation of PulseAudio stream should occur while mainloop is locked.

* Revert "Hide main window during tests to prevent GUI from interfering."

This reverts commit 69689bb927.

* Based on online code snippets nullptr for neg is fine.

* Clear PYTHONHOME if set on the user's system (Windows/macOS only).

* Bring back locking in TxRxThread just in case.

* Remove unneeded backslash.

* Revert "Bring back locking in TxRxThread just in case."

This reverts commit fc6a9f8797.

* Manually back out the changes instead of using git checkout.

* Use shared_ptr for LinkStep.

* Try removing the TX mode change mutex again.

* Try moving actual codec activity out of RT context.

* Fix compiler error.

* Fix issue preventing legacy modes from transmitting.

* Another attempt at preventing RX dropouts.

* Try putting mode TX into separate threads again.

* Only limit output samples if input samples were provided.

* Put codec RX back into RT context.

* Put TX on RT context.

* Remove unused code.

* Deallocation should occur only in the destructor.

* Fix Windows spectrum plot formatting issues.

* Prevent buffer overflow during TX/RX processing.

* Bring FRAME_DURATION back down to 10ms.

* We want to feed samples into the RADE/FreeDV TX/RX FIFOs regardless of whether there's room in the output.

* ParallelStep should only feed FRAME_DURATION ms worth of samples at a time.

* Sleep fallback should track FRAME_DURATION.

* Don't execute the parallel steps if there isn't enough room in the output FIFO.

* We really can only inject a portion of EOO samples at a time.

* Queue EOO as a single unit to ensure it gets transmitted as a unit.

* Allow ParallelStep to provide up to 4x the number of input samples as output.

* Back to processing 20ms frames.

* Run GH Linux tests using asan enabled.

* Suppress Python related memory leaks and Hamlib related invalid memory accesses.

* Forgot suppressions= in test execution.

* Add more leak suppressions based on GH output.

* Resolve memory leaks.

* Fix broken RadeTextTest.

* Additional suppressions from GH.

* Go back to processing TxNumSpeechSamples every TX cycle.

* Revert "Go back to processing TxNumSpeechSamples every TX cycle."

This reverts commit abe816d00b.

* 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.
pull/894/head
Mooneer Salem 2025-05-26 12:29:47 -07:00 committed by GitHub
parent 919bba2c14
commit 30c9e5b9c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 308 additions and 882 deletions

View File

@ -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"

View File

@ -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:

View File

@ -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

View File

@ -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")
set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES FAIL_REGULAR_EXPRESSION "Sync changed from 1 to 0") if(NOT ENABLE_ASAN)
set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES FAIL_REGULAR_EXPRESSION "Sync changed from 1 to 0")
endif(NOT ENABLE_ASAN)
set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES DISABLED TRUE) set_tests_properties(fullduplex_RADEV1_repeated PROPERTIES 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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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})

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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();
} }
} }

View File

@ -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_;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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__

View File

@ -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;

View File

@ -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,92 +1385,30 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
} }
wxGetApp().m_prevMode = currentMode; wxGetApp().m_prevMode = currentMode;
if (currentMode == FREEDV_MODE_800XA) { // Reset g_Nc accordingly.
switch(currentMode)
/* FSK Mode - eye diagram ---------------------------------------------------------*/ {
case FREEDV_MODE_1600:
/* add samples row by row */ g_Nc = 16;
m_panelScatter->setNc(g_Nc+1); /* +1 for BPSK pilot */
int i; break;
for (i=0; i<freedvInterface.getCurrentRxModemStats()->neyetr; i++) { case FREEDV_MODE_700D:
m_panelScatter->add_new_samples_eye(&freedvInterface.getCurrentRxModemStats()->rx_eye[i][0], freedvInterface.getCurrentRxModemStats()->neyesamp); case FREEDV_MODE_700E:
} g_Nc = 17;
m_panelScatter->setNc(g_Nc);
break;
} }
else {
// Reset g_Nc accordingly. /* PSK Modes - scatter plot -------------------------------------------------------*/
switch(currentMode) for (r=0; r<freedvInterface.getCurrentRxModemStats()->nr; r++) {
{
case FREEDV_MODE_1600: if ((currentMode == FREEDV_MODE_1600) ||
g_Nc = 16; (currentMode == FREEDV_MODE_700D) ||
m_panelScatter->setNc(g_Nc+1); /* +1 for BPSK pilot */ (currentMode == FREEDV_MODE_700E)
break; ) {
case FREEDV_MODE_700C: m_panelScatter->add_new_samples_scatter(&freedvInterface.getCurrentRxModemStats()->rx_symbols[r][0]);
/* m_FreeDV700Combine may have changed at run time */
g_Nc = 14;
if (wxGetApp().m_FreeDV700Combine) {
m_panelScatter->setNc(g_Nc/2); /* diversity combnation */
}
else {
m_panelScatter->setNc(g_Nc);
}
break;
case FREEDV_MODE_700D:
case FREEDV_MODE_700E:
g_Nc = 17;
m_panelScatter->setNc(g_Nc);
break;
case FREEDV_MODE_2020:
#if defined(FREEDV_MODE_2020B)
case FREEDV_MODE_2020B:
#endif // FREEDV_MODE_2020B
g_Nc = 31;
m_panelScatter->setNc(g_Nc);
break;
} }
/* PSK Modes - scatter plot -------------------------------------------------------*/
for (r=0; r<freedvInterface.getCurrentRxModemStats()->nr; r++) {
if ((currentMode == FREEDV_MODE_1600) ||
(currentMode == FREEDV_MODE_700D) ||
(currentMode == FREEDV_MODE_700E) ||
(currentMode == FREEDV_MODE_2020)
#if defined(FREEDV_MODE_2020B)
|| (currentMode == FREEDV_MODE_2020B)
#endif // FREEDV_MODE_2020B
) {
m_panelScatter->add_new_samples_scatter(&freedvInterface.getCurrentRxModemStats()->rx_symbols[r][0]);
}
else if (currentMode == FREEDV_MODE_700C) {
if (wxGetApp().m_FreeDV700Combine) {
/*
FreeDV 700C uses diversity, so optionally combine
symbols for scatter plot, as combined symbols are
used for demodulation. Note we need to use a copy
of the symbols, as we are not sure when the stats
will be updated.
*/
COMP* rx_symbols_copy = new COMP[g_Nc/2];
assert(rx_symbols_copy != nullptr);
for(c=0; 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 m_panelScatter->setEyeScatter(PLOT_SCATTER_MODE_SCATTER);
if (g_mode == FREEDV_MODE_800XA) {
m_panelScatter->setEyeScatter(PLOT_SCATTER_MODE_EYE);
}
else {
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!"));

View File

@ -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_();

View File

@ -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);
} }

View File

@ -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_));

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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_));

View File

@ -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);
} }
} }
} }

View File

@ -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

View File

@ -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
{ {

View File

@ -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_;

View File

@ -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;
} }

View File

@ -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");

View File

@ -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(); }

View File

@ -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);

View File

@ -0,0 +1 @@
interceptor_via_lib:hamlib

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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