2 Commits

Author SHA1 Message Date
87da47f53d added new files 2023-03-27 01:50:48 +02:00
75050347de noise reduction work 2023-03-27 01:50:34 +02:00
69 changed files with 484 additions and 4592 deletions

View File

@ -34,10 +34,10 @@ jobs:
- name: Patch Pothos with earlier libusb version - name: Patch Pothos with earlier libusb version
working-directory: ${{runner.workspace}} working-directory: ${{runner.workspace}}
run: 7z x libusb.7z -olibusb_old ; rm "C:/Program Files/PothosSDR/bin/libusb-1.0.dll" ; cp "libusb_old/MS64/dll/libusb-1.0.dll" "C:/Program Files/PothosSDR/bin/" ; rm "C:/Program Files/PothosSDR/lib/libusb-1.0.lib" ; cp "libusb_old/MS64/dll/libusb-1.0.lib" "C:/Program Files/PothosSDR/lib/" run: 7z x libusb.7z -olibusb_old ; rm "C:/Program Files/PothosSDR/bin/libusb-1.0.dll" ; cp "libusb_old/MS64/dll/libusb-1.0.dll" "C:/Program Files/PothosSDR/bin/"
- name: Download SDRPlay API - name: Download SDRPlay API
run: Invoke-WebRequest -Uri "https://drive.google.com/uc?id=12UHPMwkfa67A11QZDmpCT4iwHnyJHWuu&confirm=t" -OutFile ${{runner.workspace}}/SDRPlay.zip run: Invoke-WebRequest -Uri "https://drive.google.com/uc?id=12UHPMwkfa67A11QZDmpCT4iwHnyJHWuu" -OutFile ${{runner.workspace}}/SDRPlay.zip
- name: Install SDRPlay API - name: Install SDRPlay API
run: 7z x ${{runner.workspace}}/SDRPlay.zip -o"C:/Program Files/" run: 7z x ${{runner.workspace}}/SDRPlay.zip -o"C:/Program Files/"
@ -58,17 +58,14 @@ jobs:
run: mkdir "C:/Program Files/codec2" ; mkdir "C:/Program Files/codec2/include" ; mkdir "C:/Program Files/codec2/include/codec2" ; mkdir "C:/Program Files/codec2/lib" ; cd "codec2" ; xcopy "src" "C:/Program Files/codec2/include" ; cd "build" ; xcopy "src" "C:/Program Files/codec2/lib" ; xcopy "codec2" "C:/Program Files/codec2/include/codec2" run: mkdir "C:/Program Files/codec2" ; mkdir "C:/Program Files/codec2/include" ; mkdir "C:/Program Files/codec2/include/codec2" ; mkdir "C:/Program Files/codec2/lib" ; cd "codec2" ; xcopy "src" "C:/Program Files/codec2/include" ; cd "build" ; xcopy "src" "C:/Program Files/codec2/lib" ; xcopy "codec2" "C:/Program Files/codec2/include/codec2"
- name: Install vcpkg dependencies - name: Install vcpkg dependencies
run: vcpkg install fftw3:x64-windows glfw3:x64-windows portaudio:x64-windows zstd:x64-windows libusb:x64-windows run: vcpkg install fftw3:x64-windows glfw3:x64-windows portaudio:x64-windows zstd:x64-windows
- name: Install rtaudio - name: Install rtaudio
run: git clone https://github.com/thestk/rtaudio ; cd rtaudio ; git checkout 2f2fca4502d506abc50f6d4473b2836d24cfb1e3 ; mkdir build ; cd build ; cmake .. ; cmake --build . --config Release ; cmake --install . run: git clone https://github.com/thestk/rtaudio ; cd rtaudio ; git checkout 2f2fca4502d506abc50f6d4473b2836d24cfb1e3 ; mkdir build ; cd build ; cmake .. ; cmake --build . --config Release ; cmake --install .
- name: Install libperseus-sdr
run: git clone https://github.com/AlexandreRouma/libperseus-sdr ; cd libperseus-sdr ; mkdir build ; cd build ; cmake "-DLIBUSB_LIBRARIES=C:/Program Files/PothosSDR/lib/libusb-1.0.lib" "-DLIBUSB_INCLUDE_DIRS=C:/Program Files/PothosSDR/include/libusb-1.0" .. "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ; cmake --build . --config Release ; mkdir "C:/Program Files/PothosSDR/include/perseus-sdr" ; cp Release/perseus-sdr.dll "C:/Program Files/PothosSDR/bin" ; cp Release/perseus-sdr.lib "C:/Program Files/PothosSDR/bin" ; cd .. ; xcopy "src" "C:/Program Files/PothosSDR/include/perseus-sdr"
- name: Prepare CMake - name: Prepare CMake
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: cmake "$Env:GITHUB_WORKSPACE" "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON run: cmake "$Env:GITHUB_WORKSPACE" "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON
- name: Build - name: Build
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
@ -96,8 +93,11 @@ jobs:
- name: Update brew repositories - name: Update brew repositories
run: brew update run: brew update
- name: Fix stuff
run: rm -f /usr/local/bin/2to3* /usr/local/bin/idle3* /usr/local/bin/pydoc3* /usr/local/bin/python3* /usr/local/bin/python3-config* && brew reinstall gettext
- name: Install dependencies - name: Install dependencies
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool && pip3 install mako run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf rtl-sdr libbladerf codec2 zstd && pip3 install mako
- name: Install volk - name: Install volk
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../ run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
@ -106,7 +106,7 @@ jobs:
run: wget https://www.sdrplay.com/software/SDRplay_RSP_API-MacOSX-3.07.3.pkg && sudo installer -pkg SDRplay_RSP_API-MacOSX-3.07.3.pkg -target / run: wget https://www.sdrplay.com/software/SDRplay_RSP_API-MacOSX-3.07.3.pkg && sudo installer -pkg SDRplay_RSP_API-MacOSX-3.07.3.pkg -target /
- name: Install libiio - name: Install libiio
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../ run: git clone https://github.com/analogdevicesinc/libiio && cd libiio && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install libad9361 - name: Install libad9361
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../ run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
@ -114,15 +114,9 @@ jobs:
- name: Install LimeSuite - name: Install LimeSuite
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../ run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install libperseus
run: git clone https://github.com/Microtelecom/libperseus-sdr && cd libperseus-sdr && autoreconf -i && ./configure --prefix=/usr/local && make && make install && cd ..
- name: Install more recent librtlsdr
run: git clone https://github.com/osmocom/rtl-sdr && cd rtl-sdr && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 LIBRARY_PATH=$(pkg-config --libs-only-L libusb-1.0 | sed 's/\-L//') && sudo make install && cd ../../
- name: Prepare CMake - name: Prepare CMake
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_AUDIO_SOURCE=OFF -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_AUDIO_SOURCE=OFF -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
- name: Build - name: Build
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
@ -182,28 +176,6 @@ jobs:
name: sdrpp_debian_bullseye_amd64 name: sdrpp_debian_bullseye_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_debian_bookworm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/debian_bookworm && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v3
with:
name: sdrpp_debian_bookworm_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_debian_sid: build_debian_sid:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -226,6 +198,28 @@ jobs:
name: sdrpp_debian_sid_amd64 name: sdrpp_debian_sid_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
# build_ubuntu_bionic:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v3
# - name: Create Docker Image
# run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_bionic && docker build . --tag sdrpp_build
# - name: Run Container
# run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
# - name: Recover Deb Archive
# working-directory: ${{runner.workspace}}
# run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
# - name: Save Deb Archive
# uses: actions/upload-artifact@v3
# with:
# name: sdrpp_ubuntu_bionic_amd64
# path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_ubuntu_focal: build_ubuntu_focal:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -281,7 +275,7 @@ jobs:
- name: Prepare CMake - name: Prepare CMake
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_USRP_SOURCE=ON -DOPT_BUILD_PERSEUS_SOURCE=ON run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_USRP_SOURCE=ON
- name: Build - name: Build
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
@ -325,7 +319,7 @@ jobs:
path: ${{runner.workspace}}/sdrpp.apk path: ${{runner.workspace}}/sdrpp.apk
create_full_archive: create_full_archive:
needs: ['build_windows', 'build_macos', 'build_debian_buster', 'build_debian_bullseye', 'build_debian_bookworm', 'build_debian_sid', 'build_ubuntu_focal', 'build_ubuntu_jammy', 'build_raspios_bullseye_armhf', 'build_android'] needs: ['build_windows', 'build_macos', 'build_debian_buster', 'build_debian_bullseye', 'build_debian_sid', 'build_ubuntu_focal', 'build_ubuntu_jammy', 'build_raspios_bullseye_armhf', 'build_android']
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -339,7 +333,6 @@ jobs:
mv sdrpp_macos_intel/sdrpp_macos_intel.zip sdrpp_all/ && mv sdrpp_macos_intel/sdrpp_macos_intel.zip sdrpp_all/ &&
mv sdrpp_debian_buster_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_buster_amd64.deb && mv sdrpp_debian_buster_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_buster_amd64.deb &&
mv sdrpp_debian_bullseye_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bullseye_amd64.deb && mv sdrpp_debian_bullseye_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bullseye_amd64.deb &&
mv sdrpp_debian_bookworm_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bookworm_amd64.deb &&
mv sdrpp_debian_sid_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_sid_amd64.deb && mv sdrpp_debian_sid_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_sid_amd64.deb &&
mv sdrpp_ubuntu_focal_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_focal_amd64.deb && mv sdrpp_ubuntu_focal_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_focal_amd64.deb &&
mv sdrpp_ubuntu_jammy_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_jammy_amd64.deb && mv sdrpp_ubuntu_jammy_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_jammy_amd64.deb &&

View File

@ -17,25 +17,24 @@ option(OPT_BUILD_FILE_SOURCE "Wav file source" ON)
option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON) option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON)
option(OPT_BUILD_HERMES_SOURCE "Build Hermes Source Module (no dependencies required)" ON) option(OPT_BUILD_HERMES_SOURCE "Build Hermes Source Module (no dependencies required)" ON)
option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF) option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF)
option(OPT_BUILD_PERSEUS_SOURCE "Build Perseus Source Module (Dependencies: libperseus-sdr)" OFF) option(OPT_BUILD_SDRPP_SERVER_SOURCE "Build SDR++ Server Source Module (no dependencies required)" ON)
option(OPT_BUILD_PLUTOSDR_SOURCE "Build PlutoSDR Source Module (Dependencies: libiio, libad9361)" ON)
option(OPT_BUILD_RFSPACE_SOURCE "Build RFspace Source Module (no dependencies required)" ON) option(OPT_BUILD_RFSPACE_SOURCE "Build RFspace Source Module (no dependencies required)" ON)
option(OPT_BUILD_RTL_SDR_SOURCE "Build RTL-SDR Source Module (Dependencies: librtlsdr)" ON) option(OPT_BUILD_RTL_SDR_SOURCE "Build RTL-SDR Source Module (Dependencies: librtlsdr)" ON)
option(OPT_BUILD_RTL_TCP_SOURCE "Build RTL-TCP Source Module (no dependencies required)" ON) option(OPT_BUILD_RTL_TCP_SOURCE "Build RTL-TCP Source Module (no dependencies required)" ON)
option(OPT_BUILD_SDRPP_SERVER_SOURCE "Build SDR++ Server Source Module (no dependencies required)" ON)
option(OPT_BUILD_SDRPLAY_SOURCE "Build SDRplay Source Module (Dependencies: libsdrplay)" OFF) option(OPT_BUILD_SDRPLAY_SOURCE "Build SDRplay Source Module (Dependencies: libsdrplay)" OFF)
option(OPT_BUILD_SOAPY_SOURCE "Build SoapySDR Source Module (Dependencies: soapysdr)" ON) option(OPT_BUILD_SOAPY_SOURCE "Build SoapySDR Source Module (Dependencies: soapysdr)" ON)
option(OPT_BUILD_SPECTRAN_SOURCE "Build Spectran Source Module (Dependencies: Aaronia RTSA Suite)" OFF) option(OPT_BUILD_SPECTRAN_SOURCE "Build Spectran Source Module (Dependencies: Aaronia RTSA Suite)" OFF)
option(OPT_BUILD_SPECTRAN_HTTP_SOURCE "Build Spectran HTTP Source Module (no dependencies required)" ON) option(OPT_BUILD_SPECTRAN_HTTP_SOURCE "Build Spectran HTTP Source Module (no dependencies required)" ON)
option(OPT_BUILD_SPYSERVER_SOURCE "Build SpyServer Source Module (no dependencies required)" ON) option(OPT_BUILD_SPYSERVER_SOURCE "Build SpyServer Source Module (no dependencies required)" ON)
option(OPT_BUILD_PLUTOSDR_SOURCE "Build PlutoSDR Source Module (Dependencies: libiio, libad9361)" ON)
option(OPT_BUILD_USRP_SOURCE "Build USRP Source Module (libuhd)" OFF) option(OPT_BUILD_USRP_SOURCE "Build USRP Source Module (libuhd)" OFF)
# Sinks # Sinks
option(OPT_BUILD_ANDROID_AUDIO_SINK "Build Android Audio Sink Module (Dependencies: AAudio, only for android)" OFF) option(OPT_BUILD_ANDROID_AUDIO_SINK "Build Android Audio Sink Module (Dependencies: AAudio, only for android)" OFF)
option(OPT_BUILD_AUDIO_SINK "Build Audio Sink Module (Dependencies: rtaudio)" ON) option(OPT_BUILD_AUDIO_SINK "Build Audio Sink Module (Dependencies: rtaudio)" ON)
option(OPT_BUILD_PORTAUDIO_SINK "Build PortAudio Sink Module (Dependencies: portaudio)" OFF)
option(OPT_BUILD_NETWORK_SINK "Build Audio Sink Module (no dependencies required)" ON) option(OPT_BUILD_NETWORK_SINK "Build Audio Sink Module (no dependencies required)" ON)
option(OPT_BUILD_NEW_PORTAUDIO_SINK "Build the new PortAudio Sink Module (Dependencies: portaudio)" OFF) option(OPT_BUILD_NEW_PORTAUDIO_SINK "Build the new PortAudio Sink Module (Dependencies: portaudio)" OFF)
option(OPT_BUILD_PORTAUDIO_SINK "Build PortAudio Sink Module (Dependencies: portaudio)" OFF)
# Decoders # Decoders
option(OPT_BUILD_ATV_DECODER "Build ATV decoder (no dependencies required)" OFF) option(OPT_BUILD_ATV_DECODER "Build ATV decoder (no dependencies required)" OFF)
@ -142,13 +141,9 @@ if (OPT_BUILD_LIMESDR_SOURCE)
add_subdirectory("source_modules/limesdr_source") add_subdirectory("source_modules/limesdr_source")
endif (OPT_BUILD_LIMESDR_SOURCE) endif (OPT_BUILD_LIMESDR_SOURCE)
if (OPT_BUILD_PERSEUS_SOURCE) if (OPT_BUILD_SDRPP_SERVER_SOURCE)
add_subdirectory("source_modules/perseus_source") add_subdirectory("source_modules/sdrpp_server_source")
endif (OPT_BUILD_PERSEUS_SOURCE) endif (OPT_BUILD_SDRPP_SERVER_SOURCE)
if (OPT_BUILD_PLUTOSDR_SOURCE)
add_subdirectory("source_modules/plutosdr_source")
endif (OPT_BUILD_PLUTOSDR_SOURCE)
if (OPT_BUILD_RFSPACE_SOURCE) if (OPT_BUILD_RFSPACE_SOURCE)
add_subdirectory("source_modules/rfspace_source") add_subdirectory("source_modules/rfspace_source")
@ -162,10 +157,6 @@ if (OPT_BUILD_RTL_TCP_SOURCE)
add_subdirectory("source_modules/rtl_tcp_source") add_subdirectory("source_modules/rtl_tcp_source")
endif (OPT_BUILD_RTL_TCP_SOURCE) endif (OPT_BUILD_RTL_TCP_SOURCE)
if (OPT_BUILD_SDRPP_SERVER_SOURCE)
add_subdirectory("source_modules/sdrpp_server_source")
endif (OPT_BUILD_SDRPP_SERVER_SOURCE)
if (OPT_BUILD_SDRPLAY_SOURCE) if (OPT_BUILD_SDRPLAY_SOURCE)
add_subdirectory("source_modules/sdrplay_source") add_subdirectory("source_modules/sdrplay_source")
endif (OPT_BUILD_SDRPLAY_SOURCE) endif (OPT_BUILD_SDRPLAY_SOURCE)
@ -186,6 +177,10 @@ if (OPT_BUILD_SPYSERVER_SOURCE)
add_subdirectory("source_modules/spyserver_source") add_subdirectory("source_modules/spyserver_source")
endif (OPT_BUILD_SPYSERVER_SOURCE) endif (OPT_BUILD_SPYSERVER_SOURCE)
if (OPT_BUILD_PLUTOSDR_SOURCE)
add_subdirectory("source_modules/plutosdr_source")
endif (OPT_BUILD_PLUTOSDR_SOURCE)
if (OPT_BUILD_USRP_SOURCE) if (OPT_BUILD_USRP_SOURCE)
add_subdirectory("source_modules/usrp_source") add_subdirectory("source_modules/usrp_source")
endif (OPT_BUILD_USRP_SOURCE) endif (OPT_BUILD_USRP_SOURCE)

View File

@ -1,7 +1,6 @@
# Pull Requests # Pull Requests
**I DO NOT ACCEPT PULL-REQUEST FOR FEATURES OR BUGFIXES REQUIRING SIGNIFICANT CODE/STRUCTURE CHANGES.** TODO
**SUCH PULL REQUESTS WILL BE CLOSED AUTOMATICALLY. OPEN AN ISSUE DETAILING FEATURE REQUESTS OR POTENTIAL BUGFIX INSTEAD.**
# Code Style # Code Style

View File

@ -108,6 +108,7 @@ elseif (ANDROID)
) )
target_link_libraries(sdrpp_core PUBLIC target_link_libraries(sdrpp_core PUBLIC
/sdr-kit/${ANDROID_ABI}/lib/libcpu_features.a
/sdr-kit/${ANDROID_ABI}/lib/libvolk.so /sdr-kit/${ANDROID_ABI}/lib/libvolk.so
/sdr-kit/${ANDROID_ABI}/lib/libfftw3f.so /sdr-kit/${ANDROID_ABI}/lib/libfftw3f.so
/sdr-kit/${ANDROID_ABI}/lib/libzstd.so /sdr-kit/${ANDROID_ABI}/lib/libzstd.so

View File

@ -117,10 +117,6 @@ int sdrpp_main(int argc, char* argv[]) {
defConfig["colorMap"] = "Classic"; defConfig["colorMap"] = "Classic";
defConfig["fftHold"] = false; defConfig["fftHold"] = false;
defConfig["fftHoldSpeed"] = 60; defConfig["fftHoldSpeed"] = 60;
defConfig["fftSmoothing"] = false;
defConfig["fftSmoothingSpeed"] = 100;
defConfig["snrSmoothing"] = false;
defConfig["snrSmoothingSpeed"] = 20;
defConfig["fastFFT"] = false; defConfig["fastFFT"] = false;
defConfig["fftHeight"] = 300; defConfig["fftHeight"] = 300;
defConfig["fftRate"] = 20; defConfig["fftRate"] = 20;
@ -181,8 +177,6 @@ int sdrpp_main(int argc, char* argv[]) {
defConfig["moduleInstances"]["LimeSDR Source"]["enabled"] = true; defConfig["moduleInstances"]["LimeSDR Source"]["enabled"] = true;
defConfig["moduleInstances"]["PlutoSDR Source"]["module"] = "plutosdr_source"; defConfig["moduleInstances"]["PlutoSDR Source"]["module"] = "plutosdr_source";
defConfig["moduleInstances"]["PlutoSDR Source"]["enabled"] = true; defConfig["moduleInstances"]["PlutoSDR Source"]["enabled"] = true;
defConfig["moduleInstances"]["PerseusSDR Source"]["module"] = "perseus_source";
defConfig["moduleInstances"]["PerseusSDR Source"]["enabled"] = true;
defConfig["moduleInstances"]["RFspace Source"]["module"] = "rfspace_source"; defConfig["moduleInstances"]["RFspace Source"]["module"] = "rfspace_source";
defConfig["moduleInstances"]["RFspace Source"]["enabled"] = true; defConfig["moduleInstances"]["RFspace Source"]["enabled"] = true;
defConfig["moduleInstances"]["RTL-SDR Source"]["module"] = "rtl_sdr_source"; defConfig["moduleInstances"]["RTL-SDR Source"]["module"] = "rtl_sdr_source";

View File

@ -12,7 +12,6 @@ namespace sdrpp_credits {
"Howard0su", "Howard0su",
"John Donkersley", "John Donkersley",
"Joshua Kimsey", "Joshua Kimsey",
"Manawyrm",
"Martin Hauke", "Martin Hauke",
"Marvin Sinister", "Marvin Sinister",
"Maxime Biette", "Maxime Biette",
@ -22,6 +21,7 @@ namespace sdrpp_credits {
"Shuyuan Liu", "Shuyuan Liu",
"Syne Ardwin (WI9SYN)", "Syne Ardwin (WI9SYN)",
"Szymon Zakrent", "Szymon Zakrent",
"Tobias Mädel",
"Youssef Touil", "Youssef Touil",
"Zimm" "Zimm"
}; };

View File

@ -9,7 +9,7 @@ namespace dsp::convert {
StereoToMono(stream<stereo_t>* in) { base_type::init(in); } StereoToMono(stream<stereo_t>* in) { base_type::init(in); }
inline int process(int count, const stereo_t* in, float* out) { static inline int process(int count, const stereo_t* in, float* out) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
out[i] = (in[i].l + in[i].r) / 2.0f; out[i] = (in[i].l + in[i].r) / 2.0f;
} }

View File

@ -0,0 +1,183 @@
#pragma once
#include "../processor.h"
#include "../window/nuttall.h"
#include <fftw3.h>
#include "../convert/stereo_to_mono.h"
namespace dsp::noise_reduction {
class Audio : public Processor<stereo_t, stereo_t> {
using base_type = Processor<stereo_t, stereo_t>;
public:
Audio() {}
Audio(stream<stereo_t>* in, int bins) { init(in, bins); }
~Audio() {
if (!base_type::_block_init) { return; }
base_type::stop();
destroyBuffers();
}
void init(stream<stereo_t>* in, int bins) {
_bins = bins;
complexBins = (bins / 2) + 1;
normFactor = 1.0f / (float)_bins;
initBuffers();
base_type::init(in);
}
void setBins(int bins) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_bins = bins;
complexBins = (bins / 2) + 1;
normFactor = 1.0f / (float)_bins;
destroyBuffers();
initBuffers();
base_type::tempStart();
}
void setLevel(float level) {
_level = powf(10.0f, level * 0.1f);
}
void reset() {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
buffer::clear(buffer, _bins - 1);
buffer::clear(backFFTIn, _bins);
buffer::clear(noisePrint, _bins);
base_type::tempStart();
}
int process(int count, const stereo_t* in, stereo_t* out) {
// Write new input data to buffer
convert::StereoToMono::process(count, in, bufferStart);
// Iterate the FFT
for (int i = 0; i < count; i++) {
// Apply windows
volk_32f_x2_multiply_32f(forwFFTIn, &buffer[i], fftWin, _bins);
// Do forward FFT
fftwf_execute(forwardPlan);
// Get bin amplitude and square to get power
volk_32fc_magnitude_32f(ampBuf, (lv_32fc_t*)forwFFTOut, complexBins);
// Update noise print using a running average
volk_32f_s32f_multiply_32f(scaledAmps, ampBuf, alpha, complexBins);
volk_32f_s32f_multiply_32f(noisePrint, noisePrint, beta, complexBins);
volk_32f_x2_add_32f(noisePrint, noisePrint, scaledAmps, complexBins);
// Clamp amplitudes
volk_32f_x2_max_32f(ampBuf, ampBuf, noisePrint, complexBins);
// Compute Wiener (funny) filter
volk_32f_x2_subtract_32f(scaledAmps, ampBuf, noisePrint, complexBins);
volk_32f_x2_divide_32f(scaledAmps, scaledAmps, ampBuf, complexBins);
// Apply wiener filter to bins
volk_32fc_32f_multiply_32fc((lv_32fc_t*)backFFTIn, (lv_32fc_t*)forwFFTOut, scaledAmps, complexBins);
// Do reverse FFT and get first element
fftwf_execute(backwardPlan);
out[i].l = backFFTOut[_bins / 2];
out[i].r = backFFTOut[_bins / 2];
}
// Correct amplitude
volk_32f_s32f_multiply_32f((float*)out, (float*)out, normFactor, count*2);
// Move buffer buffer
memmove(buffer, &buffer[count], (_bins - 1) * sizeof(float));
return count;
}
int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
process(count, base_type::_in->readBuf, base_type::out.writeBuf);
// Swap if some data was generated
base_type::_in->flush();
if (!base_type::out.swap(count)) { return -1; }
return count;
}
protected:
void initBuffers() {
// Allocate FFT buffers
forwFFTIn = (float*)fftwf_malloc(_bins * sizeof(float));
forwFFTOut = (complex_t*)fftwf_malloc(_bins * sizeof(complex_t));
backFFTIn = (complex_t*)fftwf_malloc(_bins * sizeof(complex_t));
backFFTOut = (float*)fftwf_malloc(_bins * sizeof(float));
// Allocate and clear delay buffer
buffer = buffer::alloc<float>(STREAM_BUFFER_SIZE + 64000);
bufferStart = &buffer[_bins - 1];
buffer::clear(buffer, _bins - 1);
// Clear backward FFT input
buffer::clear(backFFTIn, _bins);
// Allocate amplitude buffer
ampBuf = buffer::alloc<float>(_bins);
scaledAmps = buffer::alloc<float>(_bins);
noisePrint = buffer::alloc<float>(_bins);
buffer::clear(noisePrint, _bins);
// Allocate and generate Window
fftWin = buffer::alloc<float>(_bins);
for (int i = 0; i < _bins; i++) { fftWin[i] = window::nuttall(i, _bins - 1); }
// Plan FFTs
forwardPlan = fftwf_plan_dft_r2c_1d(_bins, forwFFTIn, (fftwf_complex*)forwFFTOut, FFTW_ESTIMATE);
backwardPlan = fftwf_plan_dft_c2r_1d(_bins, (fftwf_complex*)backFFTIn, backFFTOut, FFTW_ESTIMATE);
}
void destroyBuffers() {
fftwf_destroy_plan(forwardPlan);
fftwf_destroy_plan(backwardPlan);
fftwf_free(forwFFTIn);
fftwf_free(forwFFTOut);
fftwf_free(backFFTIn);
fftwf_free(backFFTOut);
buffer::free(buffer);
buffer::free(ampBuf);
buffer::free(scaledAmps);
buffer::free(noisePrint);
buffer::free(fftWin);
}
float _level = 0.0f;
float* forwFFTIn;
complex_t* forwFFTOut;
complex_t* backFFTIn;
float* backFFTOut;
fftwf_plan forwardPlan;
fftwf_plan backwardPlan;
float* buffer;
float* bufferStart;
float* fftWin;
float* ampBuf;
float* scaledAmps;
float* noisePrint;
int _bins;
int complexBins;
float normFactor = 1.0f;
float alpha = 0.0001f;
float beta = 0.9999f;
};
}

View File

@ -37,21 +37,17 @@ namespace dsp::noise_reduction {
inline int process(int count, complex_t* in, complex_t* out) { inline int process(int count, complex_t* in, complex_t* out) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
// Get signal amplitude // Get signal amplitude and pass value if null
float inAmp = in[i].amplitude(); float inAmp = in[i].amplitude();
if (!inAmp) {
// Update average amplitude out[i] = in[i];
float gain = 1.0f;
if (inAmp != 0.0f) {
amp = (amp * _invRate) + (inAmp * _rate);
float excess = inAmp / amp;
if (excess > _level) {
gain = 1.0f / excess;
}
} }
// Scale output by gain // Update running average of amplitude
out[i] = in[i] * gain; amp = (_rate*inAmp) + (_invRate*amp);
// Null out if spike (Note: ideally, it should try to guess the real data)
out[i] = (inAmp > _level*amp) ? complex_t{0.0f,0.0f} : in[i];
} }
return count; return count;
} }

View File

@ -82,7 +82,7 @@ namespace dsp {
inline float fastAmplitude() { inline float fastAmplitude() {
float re_abs = fabsf(re); float re_abs = fabsf(re);
float im_abs = fabsf(im); float im_abs = fabsf(re);
if (re_abs > im_abs) { return re_abs + 0.4f * im_abs; } if (re_abs > im_abs) { return re_abs + 0.4f * im_abs; }
return im_abs + 0.4f * re_abs; return im_abs + 0.4f * re_abs;
} }

View File

@ -574,22 +574,10 @@ void MainWindow::draw() {
// Handle scrollwheel // Handle scrollwheel
int wheel = ImGui::GetIO().MouseWheel; int wheel = ImGui::GetIO().MouseWheel;
if (wheel != 0 && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) { if (wheel != 0 && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) {
// Select factor depending on modifier keys
double interval;
if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
interval = vfo->snapInterval * 10.0;
}
else if (ImGui::IsKeyDown(ImGuiKey_LeftAlt)) {
interval = vfo->snapInterval * 0.1;
}
else {
interval = vfo->snapInterval;
}
double nfreq; double nfreq;
if (vfo != NULL) { if (vfo != NULL) {
nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + (interval * wheel); nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + (vfo->snapInterval * wheel);
nfreq = roundl(nfreq / interval) * interval; nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval;
} }
else { else {
nfreq = gui::waterfall.getCenterFrequency() - (gui::waterfall.getViewBandwidth() * wheel / 20.0); nfreq = gui::waterfall.getCenterFrequency() - (gui::waterfall.getViewBandwidth() * wheel / 20.0);

View File

@ -8,7 +8,6 @@
#include <signal_path/signal_path.h> #include <signal_path/signal_path.h>
#include <gui/style.h> #include <gui/style.h>
#include <utils/optionlist.h> #include <utils/optionlist.h>
#include <algorithm>
namespace displaymenu { namespace displaymenu {
bool showWaterfall; bool showWaterfall;
@ -23,10 +22,6 @@ namespace displaymenu {
bool restartRequired = false; bool restartRequired = false;
bool fftHold = false; bool fftHold = false;
int fftHoldSpeed = 60; int fftHoldSpeed = 60;
bool fftSmoothing = false;
int fftSmoothingSpeed = 100;
bool snrSmoothing = false;
int snrSmoothingSpeed = 20;
OptionList<float, float> uiScales; OptionList<float, float> uiScales;
@ -62,10 +57,8 @@ namespace displaymenu {
IQFrontEnd::FFTWindow::NUTTALL IQFrontEnd::FFTWindow::NUTTALL
}; };
void updateFFTSpeeds() { void updateFFTHoldSpeed() {
gui::waterfall.setFFTHoldSpeed((float)fftHoldSpeed / ((float)fftRate * 10.0f)); gui::waterfall.setFFTHoldSpeed(fftHoldSpeed / (fftRate * 10.0f));
gui::waterfall.setFFTSmoothingSpeed(std::min<float>((float)fftSmoothingSpeed / (float)(fftRate * 10.0f), 1.0f));
gui::waterfall.setSNRSmoothingSpeed(std::min<float>((float)snrSmoothingSpeed / (float)(fftRate * 10.0f), 1.0f));
} }
void init() { void init() {
@ -111,13 +104,7 @@ namespace displaymenu {
fftHold = core::configManager.conf["fftHold"]; fftHold = core::configManager.conf["fftHold"];
fftHoldSpeed = core::configManager.conf["fftHoldSpeed"]; fftHoldSpeed = core::configManager.conf["fftHoldSpeed"];
gui::waterfall.setFFTHold(fftHold); gui::waterfall.setFFTHold(fftHold);
fftSmoothing = core::configManager.conf["fftSmoothing"]; updateFFTHoldSpeed();
fftSmoothingSpeed = core::configManager.conf["fftSmoothingSpeed"];
gui::waterfall.setFFTSmoothing(fftSmoothing);
snrSmoothing = core::configManager.conf["snrSmoothing"];
snrSmoothingSpeed = core::configManager.conf["snrSmoothingSpeed"];
gui::waterfall.setSNRSmoothing(snrSmoothing);
updateFFTSpeeds();
// Define and load UI scales // Define and load UI scales
uiScales.define(1.0f, "100%", 1.0f); uiScales.define(1.0f, "100%", 1.0f);
@ -157,47 +144,16 @@ namespace displaymenu {
core::configManager.conf["fftHold"] = fftHold; core::configManager.conf["fftHold"] = fftHold;
core::configManager.release(true); core::configManager.release(true);
} }
ImGui::SameLine();
ImGui::LeftLabel("FFT Hold Speed");
ImGui::FillWidth(); ImGui::FillWidth();
if (ImGui::InputInt("##sdrpp_fft_hold_speed", &fftHoldSpeed)) { if (ImGui::InputInt("##sdrpp_fft_hold_speed", &fftHoldSpeed)) {
updateFFTSpeeds(); updateFFTHoldSpeed();
core::configManager.acquire(); core::configManager.acquire();
core::configManager.conf["fftHoldSpeed"] = fftHoldSpeed; core::configManager.conf["fftHoldSpeed"] = fftHoldSpeed;
core::configManager.release(true); core::configManager.release(true);
} }
if (ImGui::Checkbox("FFT Smoothing##_sdrpp", &fftSmoothing)) {
gui::waterfall.setFFTSmoothing(fftSmoothing);
core::configManager.acquire();
core::configManager.conf["fftSmoothing"] = fftSmoothing;
core::configManager.release(true);
}
ImGui::SameLine();
ImGui::FillWidth();
if (ImGui::InputInt("##sdrpp_fft_smoothing_speed", &fftSmoothingSpeed)) {
fftSmoothingSpeed = std::max<int>(fftSmoothingSpeed, 1);
updateFFTSpeeds();
core::configManager.acquire();
core::configManager.conf["fftSmoothingSpeed"] = fftSmoothingSpeed;
core::configManager.release(true);
}
if (ImGui::Checkbox("SNR Smoothing##_sdrpp", &snrSmoothing)) {
gui::waterfall.setSNRSmoothing(snrSmoothing);
core::configManager.acquire();
core::configManager.conf["snrSmoothing"] = snrSmoothing;
core::configManager.release(true);
}
ImGui::SameLine();
ImGui::FillWidth();
if (ImGui::InputInt("##sdrpp_snr_smoothing_speed", &snrSmoothingSpeed)) {
snrSmoothingSpeed = std::max<int>(snrSmoothingSpeed, 1);
updateFFTSpeeds();
core::configManager.acquire();
core::configManager.conf["snrSmoothingSpeed"] = snrSmoothingSpeed;
core::configManager.release(true);
}
ImGui::LeftLabel("High-DPI Scaling"); ImGui::LeftLabel("High-DPI Scaling");
ImGui::FillWidth(); ImGui::FillWidth();
if (ImGui::Combo("##sdrpp_ui_scale", &uiScaleId, uiScales.txt)) { if (ImGui::Combo("##sdrpp_ui_scale", &uiScaleId, uiScales.txt)) {
@ -212,7 +168,7 @@ namespace displaymenu {
if (ImGui::InputInt("##sdrpp_fft_rate", &fftRate, 1, 10)) { if (ImGui::InputInt("##sdrpp_fft_rate", &fftRate, 1, 10)) {
fftRate = std::max<int>(1, fftRate); fftRate = std::max<int>(1, fftRate);
sigpath::iqFrontEnd.setFFTRate(fftRate); sigpath::iqFrontEnd.setFFTRate(fftRate);
updateFFTSpeeds(); updateFFTHoldSpeed();
core::configManager.acquire(); core::configManager.acquire();
core::configManager.conf["fftRate"] = fftRate; core::configManager.conf["fftRate"] = fftRate;
core::configManager.release(true); core::configManager.release(true);

View File

@ -1,5 +1,4 @@
#pragma once #pragma once
#include <stdint.h>
#include <imgui.h> #include <imgui.h>
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -689,7 +689,6 @@ namespace ImGui {
void WaterFall::onResize() { void WaterFall::onResize() {
std::lock_guard<std::recursive_mutex> lck(latestFFTMtx); std::lock_guard<std::recursive_mutex> lck(latestFFTMtx);
std::lock_guard<std::mutex> lck2(smoothingBufMtx);
// return if widget is too small // return if widget is too small
if (widgetSize.x < 100 || widgetSize.y < 100) { if (widgetSize.x < 100 || widgetSize.y < 100) {
return; return;
@ -741,23 +740,14 @@ namespace ImGui {
} }
latestFFTHold = new float[dataWidth]; latestFFTHold = new float[dataWidth];
// Reallocate smoothing buffer
if (fftSmoothing) {
if (smoothingBuf) { delete[] smoothingBuf; }
smoothingBuf = new float[dataWidth];
for (int i = 0; i < dataWidth; i++) {
smoothingBuf[i] = -1000.0f;
}
}
if (waterfallVisible) { if (waterfallVisible) {
delete[] waterfallFb; delete[] waterfallFb;
waterfallFb = new uint32_t[dataWidth * waterfallHeight]; waterfallFb = new uint32_t[dataWidth * waterfallHeight];
memset(waterfallFb, 0, dataWidth * waterfallHeight * sizeof(uint32_t)); memset(waterfallFb, 0, dataWidth * waterfallHeight * sizeof(uint32_t));
} }
for (int i = 0; i < dataWidth; i++) { for (int i = 0; i < dataWidth; i++) {
latestFFT[i] = -1000.0f; // Hide everything latestFFT[i] = -1000.0; // Hide everything
latestFFTHold[i] = -1000.0f; latestFFTHold[i] = -1000.0;
} }
fftAreaMin = ImVec2(widgetPos.x + (50.0f * style::uiScale), widgetPos.y + (9.0f * style::uiScale)); fftAreaMin = ImVec2(widgetPos.x + (50.0f * style::uiScale), widgetPos.y + (9.0f * style::uiScale));
@ -883,26 +873,10 @@ namespace ImGui {
fftLines = 1; fftLines = 1;
} }
// Apply smoothing if enabled
if (fftSmoothing && latestFFT != NULL && smoothingBuf != NULL && fftLines != 0) {
std::lock_guard<std::mutex> lck2(smoothingBufMtx);
volk_32f_s32f_multiply_32f(latestFFT, latestFFT, fftSmoothingAlpha, dataWidth);
volk_32f_s32f_multiply_32f(smoothingBuf, smoothingBuf, fftSmoothingBeta, dataWidth);
volk_32f_x2_add_32f(smoothingBuf, latestFFT, smoothingBuf, dataWidth);
memcpy(latestFFT, smoothingBuf, dataWidth * sizeof(float));
}
if (selectedVFO != "" && vfos.size() > 0) { if (selectedVFO != "" && vfos.size() > 0) {
float dummy; float dummy;
if (snrSmoothing) {
float newSNR = 0.0f;
calculateVFOSignalInfo(waterfallVisible ? &rawFFTs[currentFFTLine * rawFFTSize] : rawFFTs, vfos[selectedVFO], dummy, newSNR);
selectedVFOSNR = (snrSmoothingBeta*selectedVFOSNR) + (snrSmoothingAlpha*newSNR);
}
else {
calculateVFOSignalInfo(waterfallVisible ? &rawFFTs[currentFFTLine * rawFFTSize] : rawFFTs, vfos[selectedVFO], dummy, selectedVFOSNR); calculateVFOSignalInfo(waterfallVisible ? &rawFFTs[currentFFTLine * rawFFTSize] : rawFFTs, vfos[selectedVFO], dummy, selectedVFOSNR);
} }
}
// If FFT hold is enabled, update it // If FFT hold is enabled, update it
if (fftHold && latestFFT != NULL && latestFFTHold != NULL && fftLines != 0) { if (fftHold && latestFFT != NULL && latestFFTHold != NULL && fftLines != 0) {
@ -1136,45 +1110,6 @@ namespace ImGui {
fftHoldSpeed = speed; fftHoldSpeed = speed;
} }
void WaterFall::setFFTSmoothing(bool enabled) {
std::lock_guard<std::mutex> lck(smoothingBufMtx);
fftSmoothing = enabled;
// Free buffer if not null
if (smoothingBuf) {delete[] smoothingBuf; }
// If disabled, stop here
if (!enabled) {
smoothingBuf = NULL;
return;
}
// Allocate and copy existing FFT into it
smoothingBuf = new float[dataWidth];
if (latestFFT) {
std::lock_guard<std::recursive_mutex> lck2(latestFFTMtx);
memcpy(smoothingBuf, latestFFT, dataWidth * sizeof(float));
}
else {
memset(smoothingBuf, 0, dataWidth * sizeof(float));
}
}
void WaterFall::setFFTSmoothingSpeed(float speed) {
std::lock_guard<std::mutex> lck(smoothingBufMtx);
fftSmoothingAlpha = speed;
fftSmoothingBeta = 1.0f - speed;
}
void WaterFall::setSNRSmoothing(bool enabled) {
snrSmoothing = enabled;
}
void WaterFall::setSNRSmoothingSpeed(float speed) {
snrSmoothingAlpha = speed;
snrSmoothingBeta = 1.0f - speed;
}
float* WaterFall::acquireLatestFFT(int& width) { float* WaterFall::acquireLatestFFT(int& width) {
latestFFTMtx.lock(); latestFFTMtx.lock();
if (!latestFFT) { if (!latestFFT) {

View File

@ -169,12 +169,6 @@ namespace ImGui {
void setFFTHold(bool hold); void setFFTHold(bool hold);
void setFFTHoldSpeed(float speed); void setFFTHoldSpeed(float speed);
void setFFTSmoothing(bool enabled);
void setFFTSmoothingSpeed(float speed);
void setSNRSmoothing(bool enabled);
void setSNRSmoothingSpeed(float speed);
float* acquireLatestFFT(int& width); float* acquireLatestFFT(int& width);
void releaseLatestFFT(); void releaseLatestFFT();
@ -188,7 +182,7 @@ namespace ImGui {
bool mouseInFFT = false; bool mouseInFFT = false;
bool mouseInWaterfall = false; bool mouseInWaterfall = false;
float selectedVFOSNR = 0.0f; float selectedVFOSNR = NAN;
bool centerFrequencyLocked = false; bool centerFrequencyLocked = false;
@ -276,7 +270,6 @@ namespace ImGui {
std::recursive_mutex buf_mtx; std::recursive_mutex buf_mtx;
std::recursive_mutex latestFFTMtx; std::recursive_mutex latestFFTMtx;
std::mutex texMtx; std::mutex texMtx;
std::mutex smoothingBufMtx;
float vRange; float vRange;
@ -311,9 +304,8 @@ namespace ImGui {
//std::vector<std::vector<float>> rawFFTs; //std::vector<std::vector<float>> rawFFTs;
int rawFFTSize; int rawFFTSize;
float* rawFFTs = NULL; float* rawFFTs = NULL;
float* latestFFT = NULL; float* latestFFT;
float* latestFFTHold = NULL; float* latestFFTHold;
float* smoothingBuf = NULL;
int currentFFTLine = 0; int currentFFTLine = 0;
int fftLines = 0; int fftLines = 0;
@ -333,14 +325,6 @@ namespace ImGui {
bool fftHold = false; bool fftHold = false;
float fftHoldSpeed = 0.3f; float fftHoldSpeed = 0.3f;
bool fftSmoothing = false;
float fftSmoothingAlpha = 0.5;
float fftSmoothingBeta = 0.5;
bool snrSmoothing = false;
float snrSmoothingAlpha = 0.5;
float snrSmoothingBeta = 0.5;
// UI Select elements // UI Select elements
bool fftResizeSelect = false; bool fftResizeSelect = false;
bool freqScaleSelect = false; bool freqScaleSelect = false;

View File

@ -33,7 +33,7 @@ ModuleManager::Module_t ModuleManager::loadModule(std::string path) {
#else #else
mod.handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); mod.handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (mod.handle == NULL) { if (mod.handle == NULL) {
flog::error("Couldn't load {0}: {1}", path, dlerror()); flog::error("Couldn't load {0}.", path);
mod.handle = NULL; mod.handle = NULL;
return mod; return mod;
} }

View File

@ -2,7 +2,7 @@
#include <utils/flog.h> #include <utils/flog.h>
bool ModuleComManager::registerInterface(std::string moduleName, std::string name, void (*handler)(int code, void* in, void* out, void* ctx), void* ctx) { bool ModuleComManager::registerInterface(std::string moduleName, std::string name, void (*handler)(int code, void* in, void* out, void* ctx), void* ctx) {
std::lock_guard<std::recursive_mutex> lck(mtx); std::lock_guard<std::mutex> lck(mtx);
if (interfaces.find(name) != interfaces.end()) { if (interfaces.find(name) != interfaces.end()) {
flog::error("Tried creating module interface with an existing name: {0}", name); flog::error("Tried creating module interface with an existing name: {0}", name);
return false; return false;
@ -16,7 +16,7 @@ bool ModuleComManager::registerInterface(std::string moduleName, std::string nam
} }
bool ModuleComManager::unregisterInterface(std::string name) { bool ModuleComManager::unregisterInterface(std::string name) {
std::lock_guard<std::recursive_mutex> lck(mtx); std::lock_guard<std::mutex> lck(mtx);
if (interfaces.find(name) == interfaces.end()) { if (interfaces.find(name) == interfaces.end()) {
flog::error("Tried to erase module interface with unknown name: {0}", name); flog::error("Tried to erase module interface with unknown name: {0}", name);
return false; return false;
@ -26,13 +26,13 @@ bool ModuleComManager::unregisterInterface(std::string name) {
} }
bool ModuleComManager::interfaceExists(std::string name) { bool ModuleComManager::interfaceExists(std::string name) {
std::lock_guard<std::recursive_mutex> lck(mtx); std::lock_guard<std::mutex> lck(mtx);
if (interfaces.find(name) == interfaces.end()) { return false; } if (interfaces.find(name) == interfaces.end()) { return false; }
return true; return true;
} }
std::string ModuleComManager::getModuleName(std::string name) { std::string ModuleComManager::getModuleName(std::string name) {
std::lock_guard<std::recursive_mutex> lck(mtx); std::lock_guard<std::mutex> lck(mtx);
if (interfaces.find(name) == interfaces.end()) { if (interfaces.find(name) == interfaces.end()) {
flog::error("Tried to call unknown module interface: {0}", name); flog::error("Tried to call unknown module interface: {0}", name);
return ""; return "";
@ -41,7 +41,7 @@ std::string ModuleComManager::getModuleName(std::string name) {
} }
bool ModuleComManager::callInterface(std::string name, int code, void* in, void* out) { bool ModuleComManager::callInterface(std::string name, int code, void* in, void* out) {
std::lock_guard<std::recursive_mutex> lck(mtx); std::lock_guard<std::mutex> lck(mtx);
if (interfaces.find(name) == interfaces.end()) { if (interfaces.find(name) == interfaces.end()) {
flog::error("Tried to call unknown module interface: {0}", name); flog::error("Tried to call unknown module interface: {0}", name);
return false; return false;

View File

@ -18,6 +18,6 @@ public:
bool callInterface(std::string name, int code, void* in, void* out); bool callInterface(std::string name, int code, void* in, void* out);
private: private:
std::recursive_mutex mtx; std::mutex mtx;
std::map<std::string, ModuleComInterface> interfaces; std::map<std::string, ModuleComInterface> interfaces;
}; };

View File

@ -1,7 +1,6 @@
#include "net.h" #include "net.h"
#include <string.h> #include <string.h>
#include <codecvt> #include <codecvt>
#include <stdexcept>
#ifdef _WIN32 #ifdef _WIN32
#define WOULD_BLOCK (WSAGetLastError() == WSAEWOULDBLOCK) #define WOULD_BLOCK (WSAGetLastError() == WSAEWOULDBLOCK)

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <string>
#include <mutex> #include <mutex>
#include <memory> #include <memory>
#include <map> #include <map>

View File

@ -1,52 +0,0 @@
#pragma once
#include <functional>
#include <stdexcept>
#include <mutex>
#include <map>
typedef int HandlerID;
template <typename... Args>
class NewEvent {
public:
using Handler = std::function<void(Args...)>;
HandlerID bind(const Handler& handler) {
std::lock_guard<std::mutex> lck(mtx);
HandlerID id = genID();
handlers[id] = handler;
return id;
}
template<typename MHandler, class T>
HandlerID bind(MHandler handler, T* ctx) {
return bind([=](Args... args){
(ctx->*handler)(args...);
});
}
void unbind(HandlerID id) {
std::lock_guard<std::mutex> lck(mtx);
if (handlers.find(id) == handlers.end()) {
throw std::runtime_error("Could not unbind handler, unknown ID");
}
handlers.erase(id);
}
void operator()(Args... args) {
std::lock_guard<std::mutex> lck(mtx);
for (const auto& [desc, handler] : handlers) {
handler(args...);
}
}
private:
HandlerID genID() {
int id;
for (id = 1; handlers.find(id) != handlers.end(); id++);
return id;
}
std::map<HandlerID, Handler> handlers;
std::mutex mtx;
};

View File

@ -91,9 +91,9 @@ namespace riff {
file.write((char*)&desc.hdr.size, sizeof(desc.hdr.size)); file.write((char*)&desc.hdr.size, sizeof(desc.hdr.size));
file.seekp(pos); file.seekp(pos);
// If parent chunk, increment its size by the size of the sub-chunk plus the size of its header) // If parent chunk, increment its size
if (!chunks.empty()) { if (!chunks.empty()) {
chunks.top().hdr.size += desc.hdr.size + sizeof(ChunkHeader); chunks.top().hdr.size += desc.hdr.size;
} }
} }

View File

@ -57,13 +57,10 @@ public:
if (config.conf[name].contains("brokenModulation")) { if (config.conf[name].contains("brokenModulation")) {
brokenModulation = config.conf[name]["brokenModulation"]; brokenModulation = config.conf[name]["brokenModulation"];
} }
if (config.conf[name].contains("oqpsk")) {
oqpsk = config.conf[name]["oqpsk"];
}
config.release(); config.release();
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, INPUT_SAMPLE_RATE, true); vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 150000, INPUT_SAMPLE_RATE, 150000, 150000, true);
demod.init(vfo->output, 72000.0f, INPUT_SAMPLE_RATE, 33, 0.6f, 0.1f, 0.005f, brokenModulation, oqpsk, 1e-6, 0.01); demod.init(vfo->output, 72000.0f, INPUT_SAMPLE_RATE, 33, 0.6f, 0.1f, 0.005f, brokenModulation, 1e-6, 0.01);
split.init(&demod.out); split.init(&demod.out);
split.bindStream(&symSinkStream); split.bindStream(&symSinkStream);
split.bindStream(&sinkStream); split.bindStream(&sinkStream);
@ -102,7 +99,6 @@ public:
double bw = gui::waterfall.getBandwidth(); double bw = gui::waterfall.getBandwidth();
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), 150000, INPUT_SAMPLE_RATE, 150000, 150000, true); vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), 150000, INPUT_SAMPLE_RATE, 150000, 150000, true);
demod.setBrokenModulation(brokenModulation);
demod.setInput(vfo->output); demod.setInput(vfo->output);
demod.start(); demod.start();
@ -155,13 +151,6 @@ private:
config.release(true); config.release(true);
} }
if (ImGui::Checkbox(CONCAT("OQPSK##oqpsk", _this->name), &_this->oqpsk)) {
_this->demod.setOQPSK(_this->oqpsk);
config.acquire();
config.conf[_this->name]["oqpsk"] = _this->oqpsk;
config.release(true);
}
if (!_this->folderSelect.pathIsValid() && _this->enabled) { style::beginDisabled(); } if (!_this->folderSelect.pathIsValid() && _this->enabled) { style::beginDisabled(); }
if (_this->recording) { if (_this->recording) {
@ -256,7 +245,7 @@ private:
uint64_t dataWritten = 0; uint64_t dataWritten = 0;
std::ofstream recFile; std::ofstream recFile;
bool brokenModulation = false; bool brokenModulation = false;
bool oqpsk = false;
int8_t* writeBuffer; int8_t* writeBuffer;
}; };

View File

@ -11,8 +11,8 @@ namespace dsp::demod {
public: public:
Meteor() {} Meteor() {}
Meteor(stream<complex_t>* in, double symbolrate, double samplerate, int rrcTapCount, double rrcBeta, double agcRate, double costasBandwidth, bool brokenModulation, bool oqpsk, double omegaGain, double muGain, double omegaRelLimit = 0.01) { Meteor(stream<complex_t>* in, double symbolrate, double samplerate, int rrcTapCount, double rrcBeta, double agcRate, double costasBandwidth, bool brokenModulation, double omegaGain, double muGain, double omegaRelLimit = 0.01) {
init(in, symbolrate, samplerate, rrcTapCount, rrcBeta, agcRate, costasBandwidth, brokenModulation, oqpsk, omegaGain, muGain); init(in, symbolrate, samplerate, rrcTapCount, rrcBeta, agcRate, costasBandwidth, brokenModulation, omegaGain, muGain);
} }
~Meteor() { ~Meteor() {
@ -21,12 +21,11 @@ namespace dsp::demod {
taps::free(rrcTaps); taps::free(rrcTaps);
} }
void init(stream<complex_t>* in, double symbolrate, double samplerate, int rrcTapCount, double rrcBeta, double agcRate, double costasBandwidth, bool brokenModulation, bool oqpsk, double omegaGain, double muGain, double omegaRelLimit = 0.01) { void init(stream<complex_t>* in, double symbolrate, double samplerate, int rrcTapCount, double rrcBeta, double agcRate, double costasBandwidth, bool brokenModulation, double omegaGain, double muGain, double omegaRelLimit = 0.01) {
_symbolrate = symbolrate; _symbolrate = symbolrate;
_samplerate = samplerate; _samplerate = samplerate;
_rrcTapCount = rrcTapCount; _rrcTapCount = rrcTapCount;
_rrcBeta = rrcBeta; _rrcBeta = rrcBeta;
_oqpsk = oqpsk;
rrcTaps = taps::rootRaisedCosine<float>(_rrcTapCount, _rrcBeta, _symbolrate, _samplerate); rrcTaps = taps::rootRaisedCosine<float>(_rrcTapCount, _rrcBeta, _symbolrate, _samplerate);
rrc.init(NULL, rrcTaps); rrc.init(NULL, rrcTaps);
@ -130,12 +129,6 @@ namespace dsp::demod {
costas.setBrokenModulation(enabled); costas.setBrokenModulation(enabled);
} }
void setOQPSK(bool enabled) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
_oqpsk = enabled;
}
void reset() { void reset() {
assert(base_type::_block_init); assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx); std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
@ -151,18 +144,6 @@ namespace dsp::demod {
rrc.process(count, in, out); rrc.process(count, in, out);
agc.process(count, out, out); agc.process(count, out, out);
costas.process(count, out, out); costas.process(count, out, out);
if (_oqpsk) {
// Single sample delay + deinterleave
for (int i = 0; i < count; i++) {
float tmp = out[i].im;
out[i].im = lastI;
lastI = tmp;
}
// TODO: Additional 1/24th sample delay
}
return recov.process(count, out, out); return recov.process(count, out, out);
} }
@ -185,8 +166,6 @@ namespace dsp::demod {
double _samplerate; double _samplerate;
int _rrcTapCount; int _rrcTapCount;
double _rrcBeta; double _rrcBeta;
float lastI = 0.0f;
bool _oqpsk = false;
tap<float> rrcTaps; tap<float> rrcTaps;
filter::FIR<complex_t, float> rrc; filter::FIR<complex_t, float> rrc;

View File

@ -45,6 +45,7 @@ namespace demod {
virtual int getDefaultDeemphasisMode() = 0; virtual int getDefaultDeemphasisMode() = 0;
virtual bool getFMIFNRAllowed() = 0; virtual bool getFMIFNRAllowed() = 0;
virtual bool getNBAllowed() = 0; virtual bool getNBAllowed() = 0;
virtual bool getAFNRAllowed() = 0;
virtual dsp::stream<dsp::stereo_t>* getOutput() = 0; virtual dsp::stream<dsp::stereo_t>* getOutput() = 0;
}; };
} }

View File

@ -86,6 +86,7 @@ namespace demod {
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
bool getFMIFNRAllowed() { return false; } bool getFMIFNRAllowed() { return false; }
bool getNBAllowed() { return false; } bool getNBAllowed() { return false; }
bool getAFNRAllowed() { return false; }
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; } dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
private: private:

View File

@ -92,6 +92,7 @@ namespace demod {
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
bool getFMIFNRAllowed() { return false; } bool getFMIFNRAllowed() { return false; }
bool getNBAllowed() { return false; } bool getNBAllowed() { return false; }
bool getAFNRAllowed() { return false; }
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; } dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
private: private:

View File

@ -79,6 +79,7 @@ namespace demod {
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
bool getFMIFNRAllowed() { return false; } bool getFMIFNRAllowed() { return false; }
bool getNBAllowed() { return true; } bool getNBAllowed() { return true; }
bool getAFNRAllowed() { return false; }
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; } dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
private: private:

View File

@ -79,6 +79,7 @@ namespace demod {
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
bool getFMIFNRAllowed() { return false; } bool getFMIFNRAllowed() { return false; }
bool getNBAllowed() { return true; } bool getNBAllowed() { return true; }
bool getAFNRAllowed() { return false; }
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; } dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
private: private:

View File

@ -75,6 +75,7 @@ namespace demod {
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
bool getFMIFNRAllowed() { return true; } bool getFMIFNRAllowed() { return true; }
bool getNBAllowed() { return false; } bool getNBAllowed() { return false; }
bool getAFNRAllowed() { return false; }
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; } dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
private: private:

View File

@ -59,6 +59,7 @@ namespace demod {
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
bool getFMIFNRAllowed() { return false; } bool getFMIFNRAllowed() { return false; }
bool getNBAllowed() { return true; } bool getNBAllowed() { return true; }
bool getAFNRAllowed() { return false; }
dsp::stream<dsp::stereo_t>* getOutput() { return &c2s.out; } dsp::stream<dsp::stereo_t>* getOutput() { return &c2s.out; }
private: private:

View File

@ -80,6 +80,7 @@ namespace demod {
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
bool getFMIFNRAllowed() { return false; } bool getFMIFNRAllowed() { return false; }
bool getNBAllowed() { return true; } bool getNBAllowed() { return true; }
bool getAFNRAllowed() { return true; }
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; } dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
private: private:

View File

@ -130,6 +130,7 @@ namespace demod {
int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; } int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; }
bool getFMIFNRAllowed() { return true; } bool getFMIFNRAllowed() { return true; }
bool getNBAllowed() { return false; } bool getNBAllowed() { return false; }
bool getAFNRAllowed() { return false; }
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; } dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
// ============= DEDICATED FUNCTIONS ============= // ============= DEDICATED FUNCTIONS =============

View File

@ -9,6 +9,7 @@
#include <dsp/noise_reduction/noise_blanker.h> #include <dsp/noise_reduction/noise_blanker.h>
#include <dsp/noise_reduction/fm_if.h> #include <dsp/noise_reduction/fm_if.h>
#include <dsp/noise_reduction/squelch.h> #include <dsp/noise_reduction/squelch.h>
#include <dsp/noise_reduction/audio.h>
#include <dsp/multirate/rational_resampler.h> #include <dsp/multirate/rational_resampler.h>
#include <dsp/filter/deephasis.h> #include <dsp/filter/deephasis.h>
#include <core.h> #include <core.h>
@ -83,9 +84,11 @@ public:
resamp.init(NULL, 250000.0, 48000.0); resamp.init(NULL, 250000.0, 48000.0);
deemp.init(NULL, 50e-6, 48000.0); deemp.init(NULL, 50e-6, 48000.0);
afNR.init(NULL, 1024);
afChain.addBlock(&resamp, true); afChain.addBlock(&resamp, true);
afChain.addBlock(&deemp, false); afChain.addBlock(&deemp, false);
afChain.addBlock(&afNR, false);
// Initialize the sink // Initialize the sink
srChangeHandler.ctx = this; srChangeHandler.ctx = this;
@ -247,6 +250,12 @@ private:
if (!_this->nbEnabled && _this->enabled) { style::endDisabled(); } if (!_this->nbEnabled && _this->enabled) { style::endDisabled(); }
} }
// Noise reduction
if (_this->afNRAllowed) {
if (ImGui::Checkbox(("Audio Noise Reduction##_radio_afnr_ena_" + _this->name).c_str(), &_this->afNREnabled)) {
_this->setAFNREnabled(_this->afNREnabled);
}
}
// Squelch // Squelch
if (ImGui::Checkbox(("Squelch##_radio_sqelch_ena_" + _this->name).c_str(), &_this->squelchEnabled)) { if (ImGui::Checkbox(("Squelch##_radio_sqelch_ena_" + _this->name).c_str(), &_this->squelchEnabled)) {
@ -370,6 +379,8 @@ private:
fmIFPresetId = ifnrPresets.valueId(IFNR_PRESET_VOICE); fmIFPresetId = ifnrPresets.valueId(IFNR_PRESET_VOICE);
nbAllowed = selectedDemod->getNBAllowed(); nbAllowed = selectedDemod->getNBAllowed();
nbEnabled = false; nbEnabled = false;
afNRAllowed = selectedDemod->getAFNRAllowed();
afNREnabled = false;
nbLevel = 0.0f; nbLevel = 0.0f;
double ifSamplerate = selectedDemod->getIFSampleRate(); double ifSamplerate = selectedDemod->getIFSampleRate();
config.acquire(); config.acquire();
@ -411,6 +422,9 @@ private:
if (config.conf[name][selectedDemod->getName()].contains("noiseBlankerLevel")) { if (config.conf[name][selectedDemod->getName()].contains("noiseBlankerLevel")) {
nbLevel = config.conf[name][selectedDemod->getName()]["noiseBlankerLevel"]; nbLevel = config.conf[name][selectedDemod->getName()]["noiseBlankerLevel"];
} }
if (config.conf[name][selectedDemod->getName()].contains("audioNoiseReductionEnabled")) {
nbEnabled = config.conf[name][selectedDemod->getName()]["audioNoiseReductionEnabled"];
}
config.release(); config.release();
// Configure VFO // Configure VFO
@ -446,7 +460,10 @@ private:
afChain.enableBlock(&resamp, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); }); afChain.enableBlock(&resamp, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
// Configure deemphasis // Configure deemphasis
setDeemphasisMode(deempModes[deempId]); setDeemphasisMode(deempAllowed ? deempModes[deempId] : DEEMP_MODE_NONE);
// Configure AF NR
setAFNREnabled(afNRAllowed && afNREnabled);
} }
else { else {
// Disable everything if post processing is disabled // Disable everything if post processing is disabled
@ -508,6 +525,17 @@ private:
config.release(true); config.release(true);
} }
void setAFNREnabled(bool enable) {
afNREnabled = enable;
if (!postProcEnabled || !selectedDemod) { return; }
afChain.setBlockEnabled(&afNR, afNREnabled, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
// Save config
config.acquire();
config.conf[name][selectedDemod->getName()]["audioNoiseReductionEnabled"] = nbEnabled;
config.release(true);
}
void setNBEnabled(bool enable) { void setNBEnabled(bool enable) {
nbEnabled = enable; nbEnabled = enable;
if (!selectedDemod) { return; } if (!selectedDemod) { return; }
@ -660,6 +688,7 @@ private:
dsp::chain<dsp::stereo_t> afChain; dsp::chain<dsp::stereo_t> afChain;
dsp::multirate::RationalResampler<dsp::stereo_t> resamp; dsp::multirate::RationalResampler<dsp::stereo_t> resamp;
dsp::filter::Deemphasis<dsp::stereo_t> deemp; dsp::filter::Deemphasis<dsp::stereo_t> deemp;
dsp::noise_reduction::Audio afNR;
SinkManager::Stream stream; SinkManager::Stream stream;
@ -683,6 +712,9 @@ private:
int deempId = 0; int deempId = 0;
bool deempAllowed; bool deempAllowed;
bool afNREnabled = false;
bool afNRAllowed;
bool FMIFNRAllowed; bool FMIFNRAllowed;
bool FMIFNREnabled = false; bool FMIFNREnabled = false;
int fmIFPresetId; int fmIFPresetId;

View File

@ -1,4 +0,0 @@
FROM debian:bookworm
ENV DEBIAN_FRONTEND=noninteractive
COPY do_build.sh /root
RUN chmod +x /root/do_build.sh

View File

@ -1,35 +0,0 @@
#!/bin/bash
set -e
cd /root
# Install dependencies and tools
apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
7z x ./SDRplay_RSP_API-Linux-3.07.1.run
7z x ./SDRplay_RSP_API-Linux-3.07.1
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install libperseus
git clone https://github.com/Microtelecom/libperseus-sdr
cd libperseus-sdr
autoreconf -i
./configure
make
make install
ldconfig
cd ..
cd SDRPlusPlus
mkdir build
cd build
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
make VERBOSE=1 -j2
cd ..
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk2-dev, librtaudio-dev, libzstd-dev'

View File

@ -6,7 +6,7 @@ cd /root
apt update apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \ libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd libcodec2-dev
# Install SDRPlay libraries # Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
@ -15,20 +15,10 @@ wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/ cp inc/* /usr/include/
# Install libperseus
git clone https://github.com/Microtelecom/libperseus-sdr
cd libperseus-sdr
autoreconf -i
./configure
make
make install
ldconfig
cd ..
cd SDRPlusPlus cd SDRPlusPlus
mkdir build mkdir build
cd build cd build
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON
make VERBOSE=1 -j2 make VERBOSE=1 -j2
cd .. cd ..

View File

@ -6,7 +6,7 @@ cd /root
apt update apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \ libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd libcodec2-dev
# Install SDRPlay libraries # Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
@ -15,20 +15,10 @@ wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/ cp inc/* /usr/include/
# Install libperseus
git clone https://github.com/Microtelecom/libperseus-sdr
cd libperseus-sdr
autoreconf -i
./configure
make
make install
ldconfig
cd ..
cd SDRPlusPlus cd SDRPlusPlus
mkdir build mkdir build
cd build cd build
cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON
make VERBOSE=1 -j2 make VERBOSE=1 -j2
cd .. cd ..

View File

@ -4,9 +4,9 @@ cd /root
# Install dependencies and tools # Install dependencies and tools
apt update apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \ libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd libcodec2-dev
# Install SDRPlay libraries # Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
@ -15,21 +15,11 @@ wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/ cp inc/* /usr/include/
# Install libperseus
git clone https://github.com/Microtelecom/libperseus-sdr
cd libperseus-sdr
autoreconf -i
./configure
make
make install
ldconfig
cd ..
cd SDRPlusPlus cd SDRPlusPlus
mkdir build mkdir build
cd build cd build
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON
make VERBOSE=1 -j2 make VERBOSE=1 -j2
cd .. cd ..
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk-dev, librtaudio-dev, libzstd-dev' sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk2-dev, librtaudio-dev, libzstd-dev'

View File

@ -12,7 +12,7 @@ apt update
# Install dependencies and tools # Install dependencies and tools
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libsoapysdr-dev libairspy-dev \ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libsoapysdr-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \ libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev libudev-dev autoconf libtool xxd libcodec2-dev libudev-dev
# Install SDRPlay libraries # Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
@ -41,16 +41,6 @@ make install
ldconfig ldconfig
cd ../../ cd ../../
# Install libperseus
git clone https://github.com/Microtelecom/libperseus-sdr
cd libperseus-sdr
autoreconf -i
./configure
make
make install
ldconfig
cd ..
# Fix missing .pc file for codec2 # Fix missing .pc file for codec2
echo 'prefix=/usr/' >> /usr/share/pkgconfig/codec2.pc echo 'prefix=/usr/' >> /usr/share/pkgconfig/codec2.pc
echo 'libdir=/usr/include/x86_64-linux-gnu/' >> /usr/share/pkgconfig/codec2.pc echo 'libdir=/usr/include/x86_64-linux-gnu/' >> /usr/share/pkgconfig/codec2.pc
@ -66,7 +56,7 @@ echo 'Cflags: -I/usr/include/codec2' >> /usr/share/pkgconfig/codec2.pc
cd SDRPlusPlus cd SDRPlusPlus
mkdir build mkdir build
cd build cd build
cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_OVERRIDE_STD_FILESYSTEM=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_OVERRIDE_STD_FILESYSTEM=ON -DOPT_BUILD_M17_DECODER=ON
make VERBOSE=1 -j2 make VERBOSE=1 -j2
# Generate package # Generate package

View File

@ -6,7 +6,7 @@ cd /root
apt update apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \ libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd libcodec2-dev
# Install SDRPlay libraries # Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
@ -15,20 +15,10 @@ wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/ cp inc/* /usr/include/
# Install libperseus
git clone https://github.com/Microtelecom/libperseus-sdr
cd libperseus-sdr
autoreconf -i
./configure
make
make install
ldconfig
cd ..
cd SDRPlusPlus cd SDRPlusPlus
mkdir build mkdir build
cd build cd build
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON
make VERBOSE=1 -j2 make VERBOSE=1 -j2
cd .. cd ..

View File

@ -6,7 +6,7 @@ cd /root
apt update apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \ libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd libcodec2-dev
# Install SDRPlay libraries # Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
@ -15,20 +15,10 @@ wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/ cp inc/* /usr/include/
# Install libperseus
git clone https://github.com/Microtelecom/libperseus-sdr
cd libperseus-sdr
autoreconf -i
./configure
make
make install
ldconfig
cd ..
cd SDRPlusPlus cd SDRPlusPlus
mkdir build mkdir build
cd build cd build
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON
make VERBOSE=1 -j2 make VERBOSE=1 -j2
cd .. cd ..

View File

@ -81,7 +81,7 @@ bundle_find_full_path() {
# Correct dep path # Correct dep path
echo $RPATH/$RPATH_NEXT echo $RPATH/$RPATH_NEXT
return -1 return
done done
# Search other common paths # Search other common paths

View File

@ -38,7 +38,6 @@ bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hackrf_source/hackrf_source.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hackrf_source/hackrf_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hermes_source/hermes_source.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/hermes_source/hermes_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/limesdr_source/limesdr_source.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/limesdr_source/limesdr_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/perseus_source/perseus_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/plutosdr_source/plutosdr_source.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/plutosdr_source/plutosdr_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rfspace_source/rfspace_source.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rfspace_source/rfspace_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rtl_sdr_source/rtl_sdr_source.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rtl_sdr_source/rtl_sdr_source.dylib
@ -63,7 +62,6 @@ bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/decoder_module
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/discord_integration/discord_integration.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/discord_integration/discord_integration.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/frequency_manager/frequency_manager.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/frequency_manager/frequency_manager.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/recorder/recorder.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/recorder/recorder.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/rigctl_client/rigctl_client.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/rigctl_server/rigctl_server.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/rigctl_server/rigctl_server.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/scanner/scanner.dylib bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/misc_modules/scanner/scanner.dylib

View File

@ -32,9 +32,6 @@ cp $build_dir/source_modules/hermes_source/Release/hermes_source.dll sdrpp_windo
cp $build_dir/source_modules/limesdr_source/Release/limesdr_source.dll sdrpp_windows_x64/modules/ cp $build_dir/source_modules/limesdr_source/Release/limesdr_source.dll sdrpp_windows_x64/modules/
cp 'C:/Program Files/PothosSDR/bin/LimeSuite.dll' sdrpp_windows_x64/ cp 'C:/Program Files/PothosSDR/bin/LimeSuite.dll' sdrpp_windows_x64/
cp $build_dir/source_modules/perseus_source/Release/perseus_source.dll sdrpp_windows_x64/modules/
cp 'C:/Program Files/PothosSDR/bin/perseus-sdr.dll' sdrpp_windows_x64/
cp $build_dir/source_modules/plutosdr_source/Release/plutosdr_source.dll sdrpp_windows_x64/modules/ cp $build_dir/source_modules/plutosdr_source/Release/plutosdr_source.dll sdrpp_windows_x64/modules/
cp 'C:/Program Files/PothosSDR/bin/libiio.dll' sdrpp_windows_x64/ cp 'C:/Program Files/PothosSDR/bin/libiio.dll' sdrpp_windows_x64/
cp 'C:/Program Files/PothosSDR/bin/libad9361.dll' sdrpp_windows_x64/ cp 'C:/Program Files/PothosSDR/bin/libad9361.dll' sdrpp_windows_x64/

View File

@ -6,4 +6,3 @@ file(GLOB SRC "src/*.cpp")
include(${SDRPP_MODULE_CMAKE}) include(${SDRPP_MODULE_CMAKE})
target_include_directories(recorder PRIVATE "src/") target_include_directories(recorder PRIVATE "src/")
target_include_directories(recorder PRIVATE "../../decoder_modules/radio/src")

View File

@ -21,7 +21,6 @@
#include <core.h> #include <core.h>
#include <utils/optionlist.h> #include <utils/optionlist.h>
#include <utils/wav.h> #include <utils/wav.h>
#include <radio_interface.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str()) #define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -169,7 +168,7 @@ public:
// Open file // Open file
std::string type = (recMode == RECORDER_MODE_AUDIO) ? "audio" : "baseband"; std::string type = (recMode == RECORDER_MODE_AUDIO) ? "audio" : "baseband";
std::string vfoName = (recMode == RECORDER_MODE_AUDIO) ? selectedStreamName : ""; std::string vfoName = (recMode == RECORDER_MODE_AUDIO) ? gui::waterfall.selectedVFO : "";
std::string extension = ".wav"; std::string extension = ".wav";
std::string expandedPath = expandString(folderSelect.path + "/" + genFileName(nameTemplate, type, vfoName) + extension); std::string expandedPath = expandString(folderSelect.path + "/" + genFileName(nameTemplate, type, vfoName) + extension);
if (!writer.open(expandedPath)) { if (!writer.open(expandedPath)) {
@ -438,17 +437,6 @@ private:
if (dbLvl.r > lvl.r) { lvl.r = dbLvl.r; } if (dbLvl.r > lvl.r) { lvl.r = dbLvl.r; }
} }
std::map<int, const char*> radioModeToString = {
{ RADIO_IFACE_MODE_NFM, "NFM" },
{ RADIO_IFACE_MODE_WFM, "WFM" },
{ RADIO_IFACE_MODE_AM, "AM" },
{ RADIO_IFACE_MODE_DSB, "DSB" },
{ RADIO_IFACE_MODE_USB, "USB" },
{ RADIO_IFACE_MODE_CW, "CW" },
{ RADIO_IFACE_MODE_LSB, "LSB" },
{ RADIO_IFACE_MODE_RAW, "RAW" }
};
std::string genFileName(std::string templ, std::string type, std::string name) { std::string genFileName(std::string templ, std::string type, std::string name) {
// Get data // Get data
time_t now = time(0); time_t now = time(0);
@ -467,7 +455,6 @@ private:
char dayStr[128]; char dayStr[128];
char monStr[128]; char monStr[128];
char yearStr[128]; char yearStr[128];
const char* modeStr = "Unknown";
sprintf(freqStr, "%.0lfHz", freq); sprintf(freqStr, "%.0lfHz", freq);
sprintf(hourStr, "%02d", ltm->tm_hour); sprintf(hourStr, "%02d", ltm->tm_hour);
sprintf(minStr, "%02d", ltm->tm_min); sprintf(minStr, "%02d", ltm->tm_min);
@ -475,11 +462,6 @@ private:
sprintf(dayStr, "%02d", ltm->tm_mday); sprintf(dayStr, "%02d", ltm->tm_mday);
sprintf(monStr, "%02d", ltm->tm_mon + 1); sprintf(monStr, "%02d", ltm->tm_mon + 1);
sprintf(yearStr, "%02d", ltm->tm_year + 1900); sprintf(yearStr, "%02d", ltm->tm_year + 1900);
if (core::modComManager.getModuleName(name) == "radio") {
int mode;
core::modComManager.callInterface(name, RADIO_IFACE_CMD_GET_MODE, NULL, &mode);
modeStr = radioModeToString[mode];
}
// Replace in template // Replace in template
templ = std::regex_replace(templ, std::regex("\\$t"), type); templ = std::regex_replace(templ, std::regex("\\$t"), type);
@ -490,7 +472,6 @@ private:
templ = std::regex_replace(templ, std::regex("\\$d"), dayStr); templ = std::regex_replace(templ, std::regex("\\$d"), dayStr);
templ = std::regex_replace(templ, std::regex("\\$M"), monStr); templ = std::regex_replace(templ, std::regex("\\$M"), monStr);
templ = std::regex_replace(templ, std::regex("\\$y"), yearStr); templ = std::regex_replace(templ, std::regex("\\$y"), yearStr);
templ = std::regex_replace(templ, std::regex("\\$r"), modeStr);
return templ; return templ;
} }

View File

@ -333,17 +333,6 @@ private:
_this->client->readAsync(1024, _this->dataBuf, dataHandler, _this, false); _this->client->readAsync(1024, _this->dataBuf, dataHandler, _this, false);
} }
std::map<int, const char*> radioModeToString = {
{ RADIO_IFACE_MODE_NFM, "NFM" },
{ RADIO_IFACE_MODE_WFM, "WFM" },
{ RADIO_IFACE_MODE_AM, "AM" },
{ RADIO_IFACE_MODE_DSB, "DSB" },
{ RADIO_IFACE_MODE_USB, "USB" },
{ RADIO_IFACE_MODE_CW, "CW" },
{ RADIO_IFACE_MODE_LSB, "LSB" },
{ RADIO_IFACE_MODE_RAW, "RAW" }
};
void commandHandler(std::string cmd) { void commandHandler(std::string cmd) {
std::string corr = ""; std::string corr = "";
std::vector<std::string> parts; std::vector<std::string> parts;
@ -453,18 +442,38 @@ private:
pos++; pos++;
} }
const std::string& newModeStr = parts[1];
float newBandwidth = std::atoi(parts[2].c_str()); float newBandwidth = std::atoi(parts[2].c_str());
auto it = std::find_if(radioModeToString.begin(), radioModeToString.end(), [&newModeStr](const auto& e) { int newMode;
return e.second == newModeStr; if (parts[1] == "FM") {
}); newMode = RADIO_IFACE_MODE_NFM;
if (it == radioModeToString.end()) { }
else if (parts[1] == "WFM") {
newMode = RADIO_IFACE_MODE_WFM;
}
else if (parts[1] == "AM") {
newMode = RADIO_IFACE_MODE_AM;
}
else if (parts[1] == "DSB") {
newMode = RADIO_IFACE_MODE_DSB;
}
else if (parts[1] == "USB") {
newMode = RADIO_IFACE_MODE_USB;
}
else if (parts[1] == "CW") {
newMode = RADIO_IFACE_MODE_CW;
}
else if (parts[1] == "LSB") {
newMode = RADIO_IFACE_MODE_LSB;
}
else if (parts[1] == "RAW") {
newMode = RADIO_IFACE_MODE_RAW;
}
else {
resp = "RPRT 1\n"; resp = "RPRT 1\n";
client->write(resp.size(), (uint8_t*)resp.c_str()); client->write(resp.size(), (uint8_t*)resp.c_str());
return; return;
} }
int newMode = it->first;
// If tuning is enabled, set the mode and optionally the bandwidth // If tuning is enabled, set the mode and optionally the bandwidth
if (!selectedVfo.empty() && core::modComManager.getModuleName(selectedVfo) == "radio" && tuningEnabled) { if (!selectedVfo.empty() && core::modComManager.getModuleName(selectedVfo) == "radio" && tuningEnabled) {
@ -483,9 +492,31 @@ private:
if (!selectedVfo.empty() && core::modComManager.getModuleName(selectedVfo) == "radio") { if (!selectedVfo.empty() && core::modComManager.getModuleName(selectedVfo) == "radio") {
int mode; int mode;
core::modComManager.callInterface(selectedVfo, RADIO_IFACE_CMD_GET_MODE, NULL, &mode); core::modComManager.callInterface(selectedVfo, RADIO_IFACE_CMD_GET_MODE, NULL, &mode);
resp = std::string(radioModeToString[mode]) + "\n";
if (mode == RADIO_IFACE_MODE_NFM) {
resp = "FM\n";
} }
else if (!selectedVfo.empty()) { else if (mode == RADIO_IFACE_MODE_WFM) {
resp = "WFM\n";
}
else if (mode == RADIO_IFACE_MODE_AM) {
resp = "AM\n";
}
else if (mode == RADIO_IFACE_MODE_DSB) {
resp = "DSB\n";
}
else if (mode == RADIO_IFACE_MODE_USB) {
resp = "USB\n";
}
else if (mode == RADIO_IFACE_MODE_CW) {
resp = "CW\n";
}
else if (mode == RADIO_IFACE_MODE_LSB) {
resp = "LSB\n";
}
}
if (!selectedVfo.empty()) {
resp += std::to_string((int)sigpath::vfoManager.getBandwidth(selectedVfo)) + "\n"; resp += std::to_string((int)sigpath::vfoManager.getBandwidth(selectedVfo)) + "\n";
} }
else { else {
@ -659,11 +690,6 @@ private:
"0\n" /* RIG_PARM_NONE */; "0\n" /* RIG_PARM_NONE */;
client->write(resp.size(), (uint8_t*)resp.c_str()); client->write(resp.size(), (uint8_t*)resp.c_str());
} }
// This get_powerstat stuff is a wordaround for WSJT-X 2.7.0
else if (parts[0] == "\\get_powerstat") {
resp = "1\n";
client->write(resp.size(), (uint8_t*)resp.c_str());
}
else { else {
// If command is not recognized, return error // If command is not recognized, return error
flog::error("Rigctl client sent invalid command: '{0}'", cmd); flog::error("Rigctl client sent invalid command: '{0}'", cmd);

View File

@ -44,7 +44,7 @@ Download the latest release from [the Releases page](https://github.com/Alexandr
Then, run: Then, run:
```sh ```sh
sudo apt install libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libiio-dev libad9361-dev librtaudio-dev libhackrf-dev sudo apt install libfftw3-dev libglfw3-dev libvolk2-dev libsoapysdr-dev libairspyhf-dev libiio-dev libad9361-dev librtaudio-dev libhackrf-dev
sudo dpkg -i sdrpp_debian_amd64.deb sudo dpkg -i sdrpp_debian_amd64.deb
``` ```
@ -52,9 +52,7 @@ If `libvolk2-dev` is not available, use `libvolk1-dev`.
### Arch-based ### Arch-based
Install from source following the instructions below. Install the latest release from the [sdrpp-git](https://aur.archlinux.org/packages/sdrpp-git/) AUR package
**WARNING: The sdrpp-git AUR package is no longer official, it is not recommended to use it.**
### Other ### Other
@ -76,7 +74,7 @@ The preferred IDE is [VS Code](https://code.visualstudio.com/) in order to have
* [cmake](https://cmake.org) * [cmake](https://cmake.org)
* [vcpkg](https://vcpkg.io) * [vcpkg](https://vcpkg.io)
* [PothosSDR](https://github.com/pothosware/PothosSDR) (This will install libraries for most SDRs. You have to install it in `C:/Program Files/PothosSDR`) * [PothosSDR](https://github.com/pothosware/PothosSDR) (This will install libraries for most SDRs)
* [RtAudio](https://www.music.mcgill.ca/~gary/rtaudio/) (You have to build and install it in `C:/Program Files (x86)/RtAudio/`) * [RtAudio](https://www.music.mcgill.ca/~gary/rtaudio/) (You have to build and install it in `C:/Program Files (x86)/RtAudio/`)
After this, install the following dependencies using vcpkg: After this, install the following dependencies using vcpkg:
@ -115,16 +113,16 @@ You will next need to edit the `root_dev/config.json` file to point to the modul
From the top directory, you can simply run: From the top directory, you can simply run:
```bat ```bat
./build/Release/sdrpp.exe -r root_dev -c ./build/Release/sdrpp.exe -r root_dev -s
``` ```
Or, if you wish to run from the build directory e.g. `build/Release` and adapt the relative path to the `root_dev` folder: Or, if you wish to run from the build directory e.g. `build/Release` and adapt the relative path to the `root_dev` folder:
```bat ```bat
./sdrpp.exe -r ../../root_dev -c ./sdrpp.exe -r ../../root_dev -s
``` ```
The optional `-c` argument is for keeping the console active in order to see the error messages. The optional `-s` argument is for keeping the console active in order to see the error messages.
Because all the paths are relative, for the rest of the command line instructions we are going to assume you are running from the top directory using the former command. Because all the paths are relative, for the rest of the command line instructions we are going to assume you are running from the top directory using the former command.
As mentioned previously you need to edit `root_dev/config.json` to add the modules that were built. From the default configuration file you need to add the paths in the `modules` section. Add to this list all the modules you wish to use. As mentioned previously you need to edit `root_dev/config.json` to add the modules that were built. From the default configuration file you need to add the paths in the `modules` section. Add to this list all the modules you wish to use.
@ -304,7 +302,7 @@ Here is an example of build commands that will build almost all modules at the t
```sh ```sh
mkdir build mkdir build
cd build cd build
cmake .. -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_AUDIO_SOURCE=OFF -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release cmake .. -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
make -j<N> make -j<N>
``` ```
@ -329,12 +327,11 @@ Modules in beta are still included in releases for the most part but not enabled
|----------------------|------------|-------------------|--------------------------------|:---------------:|:-----------------------:|:---------------------------:| |----------------------|------------|-------------------|--------------------------------|:---------------:|:-----------------------:|:---------------------------:|
| airspy_source | Working | libairspy | OPT_BUILD_AIRSPY_SOURCE | ✅ | ✅ | ✅ | | airspy_source | Working | libairspy | OPT_BUILD_AIRSPY_SOURCE | ✅ | ✅ | ✅ |
| airspyhf_source | Working | libairspyhf | OPT_BUILD_AIRSPYHF_SOURCE | ✅ | ✅ | ✅ | | airspyhf_source | Working | libairspyhf | OPT_BUILD_AIRSPYHF_SOURCE | ✅ | ✅ | ✅ |
| bladerf_source | Working | libbladeRF | OPT_BUILD_BLADERF_SOURCE | ⛔ | (not Debian Buster) | ✅ | | bladerf_source | Working | libbladeRF | OPT_BUILD_BLADERF_SOURCE | ⛔ | ⚠️ (not Debian Buster) | ✅ |
| file_source | Working | - | OPT_BUILD_FILE_SOURCE | ✅ | ✅ | ✅ | | file_source | Working | - | OPT_BUILD_FILE_SOURCE | ✅ | ✅ | ✅ |
| hackrf_source | Working | libhackrf | OPT_BUILD_HACKRF_SOURCE | ✅ | ✅ | ✅ | | hackrf_source | Working | libhackrf | OPT_BUILD_HACKRF_SOURCE | ✅ | ✅ | ✅ |
| hermes_source | Beta | - | OPT_BUILD_HERMES_SOURCE | ✅ | ✅ | | | hermes_source | Beta | - | OPT_BUILD_HERMES_SOURCE | ✅ | ✅ | |
| limesdr_source | Working | liblimesuite | OPT_BUILD_LIMESDR_SOURCE | ⛔ | ✅ | ✅ | | limesdr_source | Working | liblimesuite | OPT_BUILD_LIMESDR_SOURCE | ⛔ | ✅ | ✅ |
| perseus_source | Beta | libperseus-sdr | OPT_BUILD_PERSEUS_SOURCE | ⛔ | ⛔ | ⛔ |
| plutosdr_source | Working | libiio, libad9361 | OPT_BUILD_PLUTOSDR_SOURCE | ✅ | ✅ | ✅ | | plutosdr_source | Working | libiio, libad9361 | OPT_BUILD_PLUTOSDR_SOURCE | ✅ | ✅ | ✅ |
| rfspace_source | Working | - | OPT_BUILD_RFSPACE_SOURCE | ✅ | ✅ | ✅ | | rfspace_source | Working | - | OPT_BUILD_RFSPACE_SOURCE | ✅ | ✅ | ✅ |
| rtl_sdr_source | Working | librtlsdr | OPT_BUILD_RTL_SDR_SOURCE | ✅ | ✅ | ✅ | | rtl_sdr_source | Working | librtlsdr | OPT_BUILD_RTL_SDR_SOURCE | ✅ | ✅ | ✅ |
@ -351,7 +348,7 @@ Modules in beta are still included in releases for the most part but not enabled
| Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default | | Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default |
|--------------------|------------|--------------|------------------------------|:---------------:|:----------------:|:---------------------------:| |--------------------|------------|--------------|------------------------------|:---------------:|:----------------:|:---------------------------:|
| android_audio_sink | Working | - | OPT_BUILD_ANDROID_AUDIO_SINK | ⛔ | ✅ | ✅ (Android only) | | android_audio_sink | Working | - | OPT_BUILD_ANDROID_AUDIO_SINK | ⛔ | ✅ | |
| audio_sink | Working | rtaudio | OPT_BUILD_AUDIO_SINK | ✅ | ✅ | ✅ | | audio_sink | Working | rtaudio | OPT_BUILD_AUDIO_SINK | ✅ | ✅ | ✅ |
| network_sink | Working | - | OPT_BUILD_NETWORK_SINK | ✅ | ✅ | ✅ | | network_sink | Working | - | OPT_BUILD_NETWORK_SINK | ✅ | ✅ | ✅ |
| new_portaudio_sink | Beta | portaudio | OPT_BUILD_NEW_PORTAUDIO_SINK | ⛔ | ✅ | ⛔ | | new_portaudio_sink | Beta | portaudio | OPT_BUILD_NEW_PORTAUDIO_SINK | ⛔ | ✅ | ⛔ |
@ -377,9 +374,9 @@ Modules in beta are still included in releases for the most part but not enabled
| discord_integration | Working | - | OPT_BUILD_DISCORD_PRESENCE | ✅ | ✅ | ⛔ | | discord_integration | Working | - | OPT_BUILD_DISCORD_PRESENCE | ✅ | ✅ | ⛔ |
| frequency_manager | Working | - | OPT_BUILD_FREQUENCY_MANAGER | ✅ | ✅ | ✅ | | frequency_manager | Working | - | OPT_BUILD_FREQUENCY_MANAGER | ✅ | ✅ | ✅ |
| recorder | Working | - | OPT_BUILD_RECORDER | ✅ | ✅ | ✅ | | recorder | Working | - | OPT_BUILD_RECORDER | ✅ | ✅ | ✅ |
| rigctl_client | Unfinished | - | OPT_BUILD_RIGCTL_CLIENT | | | ⛔ | | rigctl_client | Unfinished | - | OPT_BUILD_RIGCTL_CLIENT | | | ⛔ |
| rigctl_server | Working | - | OPT_BUILD_RIGCTL_SERVER | ✅ | ✅ | ✅ | | rigctl_server | Working | - | OPT_BUILD_RIGCTL_SERVER | ✅ | ✅ | ✅ |
| scanner | Beta | - | OPT_BUILD_SCANNER | ✅ | ✅ | | | scanner | Beta | - | OPT_BUILD_SCANNER | ✅ | ✅ | |
| scheduler | Unfinished | - | OPT_BUILD_SCHEDULER | ⛔ | ⛔ | ⛔ | | scheduler | Unfinished | - | OPT_BUILD_SCHEDULER | ⛔ | ⛔ | ⛔ |
# Troubleshooting # Troubleshooting
@ -473,7 +470,6 @@ I will soon publish a contributing.md listing the code style to use.
* [Howard0su](https://github.com/howard0su) * [Howard0su](https://github.com/howard0su)
* John Donkersley * John Donkersley
* [Joshua Kimsey](https://github.com/JoshuaKimsey) * [Joshua Kimsey](https://github.com/JoshuaKimsey)
* [Manawyrm](https://github.com/Manawyrm)
* [Martin Hauke](https://github.com/mnhauke) * [Martin Hauke](https://github.com/mnhauke)
* [Marvin Sinister](https://github.com/marvin-sinister) * [Marvin Sinister](https://github.com/marvin-sinister)
* [Maxime Biette](https://github.com/mbiette) * [Maxime Biette](https://github.com/mbiette)
@ -483,6 +479,7 @@ I will soon publish a contributing.md listing the code style to use.
* [Shuyuan Liu](https://github.com/shuyuan-liu) * [Shuyuan Liu](https://github.com/shuyuan-liu)
* [Syne Ardwin (WI9SYN)](https://esaille.me/) * [Syne Ardwin (WI9SYN)](https://esaille.me/)
* [Szymon Zakrent](https://github.com/zakrent) * [Szymon Zakrent](https://github.com/zakrent)
* [Tobias Mädel](https://github.com/Manawyrm)
* Youssef Touil * Youssef Touil
* [Zimm](https://github.com/invader-zimm) * [Zimm](https://github.com/invader-zimm)

View File

@ -149,12 +149,6 @@
"start": 28000000, "start": 28000000,
"end": 29700000 "end": 29700000
}, },
{
"name": "8m - Amateur",
"type": "amateur",
"start": 40660000,
"end": 40690000
},
{ {
"name": "6m - Amateur", "name": "6m - Amateur",
"type": "amateur", "type": "amateur",

View File

@ -340,7 +340,7 @@
"name": "11m - CB", "name": "11m - CB",
"type": "amateur", "type": "amateur",
"start": 26960000, "start": 26960000,
"end": 27410000 "end": 27230000
}, },
{ {
"name": "10m - Radioamateur", "name": "10m - Radioamateur",

View File

@ -2,7 +2,7 @@
"name": "Germany", "name": "Germany",
"country_name": "Germany", "country_name": "Germany",
"country_code": "DE", "country_code": "DE",
"author_name": "Manawyrm", "author_name": "Tobias Mädel",
"author_url": "https://tbspace.de", "author_url": "https://tbspace.de",
"bands": [ "bands": [
{ {

File diff suppressed because it is too large Load Diff

View File

@ -529,9 +529,9 @@
}, },
{ {
"name": "Train communications", "name": "Train communications",
"type": "railway", "type": "aviation",
"start": 151712500, "start": 151775000,
"end": 156012500 "end": 151875000
}, },
{ {
"name": "Marine", "name": "Marine",
@ -557,6 +557,12 @@
"start": 270000000, "start": 270000000,
"end": 380000000 "end": 380000000
}, },
{
"name": "Train communications",
"type": "aviation",
"start": 299999000,
"end": 300001000
},
{ {
"name": "70cm", "name": "70cm",
"type": "amateur", "type": "amateur",

View File

@ -5,12 +5,6 @@
"author_name": "John Donkersley", "author_name": "John Donkersley",
"author_url": "", "author_url": "",
"bands": [ "bands": [
{
"name": "2200m Ham Band",
"type": "amateur",
"start": 135700,
"end": 137800
},
{ {
"name": "Long Wave", "name": "Long Wave",
"type": "broadcast", "type": "broadcast",
@ -215,18 +209,18 @@
"start": 15010000, "start": 15010000,
"end": 15100000 "end": 15100000
}, },
{
"name": "19m Broadcast",
"type": "broadcast",
"start": 15100000,
"end": 15800000
},
{ {
"name": "Maritime", "name": "Maritime",
"type": "marine", "type": "marine",
"start": 16360000, "start": 16360000,
"end": 17410000 "end": 17410000
}, },
{
"name": "19m Broadcast",
"type": "broadcast",
"start": 15100000,
"end": 15800000
},
{ {
"name": "16m Broadcast", "name": "16m Broadcast",
"type": "broadcast", "type": "broadcast",
@ -351,7 +345,7 @@
"name": "Air Band TACAN/ILS", "name": "Air Band TACAN/ILS",
"type": "aviation", "type": "aviation",
"start": 108000000, "start": 108000000,
"end": 117975000 "end": 118000000
}, },
{ {
"name": "Air Band Voice", "name": "Air Band Voice",
@ -377,12 +371,6 @@
"start": 147343750, "start": 147343750,
"end": 147500000 "end": 147500000
}, },
{
"name": "Satellites",
"type": "satellite",
"start": 148000000,
"end": 150050000
},
{ {
"name": "Pagers - Flex/POCSAG", "name": "Pagers - Flex/POCSAG",
"type": "PMR", "type": "PMR",
@ -437,18 +425,6 @@
"start": 230000000, "start": 230000000,
"end": 400000000 "end": 400000000
}, },
{
"name": "Satellites",
"type": "satellite",
"start": 399900000,
"end": 401000000
},
{
"name": "Weather Balloons",
"type": "aviation",
"start": 401000000,
"end": 406000000
},
{ {
"name": "Private Mobile Radio inc trams", "name": "Private Mobile Radio inc trams",
"type": "PMR", "type": "PMR",
@ -486,34 +462,22 @@
"end": 455000000 "end": 455000000
}, },
{ {
"name": "Private Mobile Radio inc OB", "name": "Private Mobile Radio",
"type": "PMR", "type": "PMR",
"start": 455000000, "start": 455000000,
"end": 470000000 "end": 467200000
},
{
"name": "Outside Broadcast Talkback",
"type": "PMR",
"start": 467200000,
"end": 468600000
}, },
{ {
"name": "Digital TV Broadcast", "name": "Digital TV Broadcast",
"type": "broadcast", "type": "broadcast",
"start": 470000000, "start": 470000000,
"end": 700000000 "end": 790000000
},
{
"name": "Cell phones",
"type": "cellular",
"start": 703000000,
"end": 788000000
},
{
"name": "Band 20 Cell phone downlink",
"type": "cellular",
"start": 791000000,
"end": 821000000
},
{
"name": "Band 20 Cell phone uplink",
"type": "cellular",
"start": 832000000,
"end": 862000000
}, },
{ {
"name": "Licence Exempt Short Range", "name": "Licence Exempt Short Range",
@ -521,84 +485,12 @@
"start": 862000000, "start": 862000000,
"end": 875800000 "end": 875800000
}, },
{
"name": "Band 8 Cell phone uplink",
"type": "cellular",
"start": 880100000,
"end": 914900000
},
{
"name": "Band 8 Cell phone downlink",
"type": "cellular",
"start": 925100000,
"end": 929500000
},
{ {
"name": "23cm Ham Band", "name": "23cm Ham Band",
"type": "amateur", "type": "amateur",
"start": 1240000000, "start": 1240000000,
"end": 1325000000 "end": 1325000000
}, },
{
"name": "Band 32 Cell phone",
"type": "cellular",
"start": 1452000000,
"end": 1492000000
},
{
"name": "Satellite L-band",
"type": "satellite",
"start": 1518000000,
"end": 1559000000
},
{
"name": "Satellite L-band",
"type": "satellite",
"start": 1626500000,
"end": 1660500000
},
{
"name": "Satellite L-band",
"type": "satellite",
"start": 1668000000,
"end": 1675000000
},
{
"name": "Band 3 Cell phone uplink",
"type": "cellular",
"start": 1710000000,
"end": 1785000000
},
{
"name": "Band 3 Cell phone downlink",
"type": "cellular",
"start": 1805100000,
"end": 1880000000
},
{
"name": "DECT cordless phones",
"type": "cellular",
"start": 1880000000,
"end": 1900000000
},
{
"name": "Band 3 Cell phones",
"type": "cellular",
"start": 1900000000,
"end": 1920000000
},
{
"name": "Band 1 Cell phone uplink",
"type": "cellular",
"start": 1920000000,
"end": 1979700000
},
{
"name": "Band 1 Cell phone downlink",
"type": "cellular",
"start": 2110300000,
"end": 2169700000
},
{ {
"name": "13cm Ham Band", "name": "13cm Ham Band",
"type": "amateur", "type": "amateur",
@ -606,28 +498,10 @@
"end": 2302000000 "end": 2302000000
}, },
{ {
"name": "ISM - wifi and bluettoth", "name": "13cm Ham Band",
"type": "ISM", "type": "amateur",
"start": 2400000000, "start": 2310000000,
"end": 2483000000 "end": 2450000000
},
{
"name": "Band 38 Cell phones",
"type": "cellular",
"start": 2500000000,
"end": 269000000
},
{
"name": "Band 42 5G Cell phones",
"type": "cellular",
"start": 3410000000,
"end": 3720000000
},
{
"name": "ISM - wifi",
"type": "ISM",
"start": 5150000000,
"end": 5850000000
} }
] ]
} }

View File

@ -227,18 +227,6 @@
"start": 144000000, "start": 144000000,
"end": 148000000 "end": 148000000
}, },
{
"name": "MURS (lower)",
"type": "amateur",
"start": 151820000,
"end": 151940000
},
{
"name": "MURS (upper)",
"type": "amateur",
"start": 154570000,
"end": 154600000
},
{ {
"name": "Marine", "name": "Marine",
"type": "marine", "type": "marine",

View File

@ -1,14 +0,0 @@
{
"name": "Smoke",
"author": "Yaroslav Andrianov",
"map": [
"#FFFFFF",
"#EEEEEE",
"#CCCCCC",
"#777777",
"#555555",
"#333333",
"#111111",
"#000000"
]
}

View File

@ -1,28 +0,0 @@
{
"name": "Temper Colors",
"author": "Yaroslav Andrianov",
"map": [
"#000000",
"#05011f",
"#0f0836",
"#2f1436",
"#3d114d",
"#4e186f",
"#592a8f",
"#5e43a5",
"#5f5eb3",
"#6276ba",
"#6b8cbf",
"#7ba1c2",
"#95b5c7",
"#b3c6ce",
"#d4bcac",
"#cca389",
"#c68a6d",
"#be6f5b",
"#b25652",
"#a24050",
"#8e2c50",
"#741e4f"
]
}

View File

@ -1,29 +0,0 @@
{
"name": "Vivid",
"author": "Yaroslav Andrianov",
"map": [
"#000000",
"#06001c",
"#090028",
"#12002c",
"#230039",
"#360143",
"#440154",
"#472c7a",
"#3b518b",
"#2c718e",
"#21908d",
"#27ad81",
"#5cc863",
"#aadc32",
"#f6fd25",
"#fdde17",
"#fecb31",
"#FE9029",
"#F56918",
"#DC3B07",
"#CE2D04",
"#AC1701",
"#980E01"
]
}

22
rpi_install.sh Normal file
View File

@ -0,0 +1,22 @@
#!/bin/sh
set -e
[ $(id -u) = 0 ] && echo "Please do not run this script as root" && exit 100
echo "Installing dependencies"
sudo apt update
sudo apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget
echo "Preparing build"
mkdir -p build
cd build
cmake .. -DOPT_BUILD_LIMESDR_SOURCE=ON
echo "Building"
make
echo "Installing"
sudo make install
echo "Done!"

View File

@ -45,7 +45,6 @@ public:
int count = audio.getDeviceCount(); int count = audio.getDeviceCount();
RtAudio::DeviceInfo info; RtAudio::DeviceInfo info;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
try {
info = audio.getDeviceInfo(i); info = audio.getDeviceInfo(i);
if (!info.probed) { continue; } if (!info.probed) { continue; }
if (info.outputChannels == 0) { continue; } if (info.outputChannels == 0) { continue; }
@ -55,10 +54,7 @@ public:
txtDevList += info.name; txtDevList += info.name;
txtDevList += '\0'; txtDevList += '\0';
} }
catch (std::exception e) {
flog::error("AudioSinkModule Error getting audio device info: {0}", e.what());
}
}
selectByName(device); selectByName(device);
} }

View File

@ -1,4 +1,3 @@
#define NOMINMAX
#include <imgui.h> #include <imgui.h>
#include <utils/flog.h> #include <utils/flog.h>
#include <module.h> #include <module.h>
@ -10,8 +9,6 @@
#include <filesystem> #include <filesystem>
#include <regex> #include <regex>
#include <gui/tuner.h> #include <gui/tuner.h>
#include <algorithm>
#include <stdexcept>
#define CONCAT(a, b) ((std::string(a) + b).c_str()) #define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -124,12 +121,6 @@ private:
} }
try { try {
_this->reader = new WavReader(_this->fileSelect.path); _this->reader = new WavReader(_this->fileSelect.path);
if (_this->reader->getSampleRate() == 0) {
_this->reader->close();
delete _this->reader;
_this->reader = NULL;
throw std::runtime_error("Sample rate may not be zero");
}
_this->sampleRate = _this->reader->getSampleRate(); _this->sampleRate = _this->reader->getSampleRate();
core::setInputSampleRate(_this->sampleRate); core::setInputSampleRate(_this->sampleRate);
std::string filename = std::filesystem::path(_this->fileSelect.path).filename().string(); std::string filename = std::filesystem::path(_this->fileSelect.path).filename().string();
@ -139,7 +130,7 @@ private:
//gui::freqSelect.maxFreq = _this->centerFreq + (_this->sampleRate/2); //gui::freqSelect.maxFreq = _this->centerFreq + (_this->sampleRate/2);
//gui::freqSelect.limitFreq = true; //gui::freqSelect.limitFreq = true;
} }
catch (std::exception& e) { catch (std::exception e) {
flog::error("Error: {0}", e.what()); flog::error("Error: {0}", e.what());
} }
config.acquire(); config.acquire();
@ -153,8 +144,8 @@ private:
static void worker(void* ctx) { static void worker(void* ctx) {
FileSourceModule* _this = (FileSourceModule*)ctx; FileSourceModule* _this = (FileSourceModule*)ctx;
double sampleRate = std::max(_this->reader->getSampleRate(), (uint32_t)1); double sampleRate = _this->reader->getSampleRate();
int blockSize = std::min((int)(sampleRate / 200.0f), (int)STREAM_BUFFER_SIZE); int blockSize = sampleRate / 200.0f;
int16_t* inBuf = new int16_t[blockSize * 2]; int16_t* inBuf = new int16_t[blockSize * 2];
while (true) { while (true) {
@ -168,8 +159,8 @@ private:
static void floatWorker(void* ctx) { static void floatWorker(void* ctx) {
FileSourceModule* _this = (FileSourceModule*)ctx; FileSourceModule* _this = (FileSourceModule*)ctx;
double sampleRate = std::max(_this->reader->getSampleRate(), (uint32_t)1); double sampleRate = _this->reader->getSampleRate();
int blockSize = std::min((int)(sampleRate / 200.0f), (int)STREAM_BUFFER_SIZE); int blockSize = sampleRate / 200.0f;
dsp::complex_t* inBuf = new dsp::complex_t[blockSize]; dsp::complex_t* inBuf = new dsp::complex_t[blockSize];
while (true) { while (true) {

View File

@ -137,10 +137,6 @@ public:
hackrf_device_list_t* _devList = hackrf_device_list(); hackrf_device_list_t* _devList = hackrf_device_list();
for (int i = 0; i < _devList->devicecount; i++) { for (int i = 0; i < _devList->devicecount; i++) {
// Skip devices that are in use
if (_devList->serial_numbers[i] == NULL) { continue; }
// Save the device serial number
devList.push_back(_devList->serial_numbers[i]); devList.push_back(_devList->serial_numbers[i]);
devListTxt += (char*)(_devList->serial_numbers[i] + 16); devListTxt += (char*)(_devList->serial_numbers[i] + 16);
devListTxt += '\0'; devListTxt += '\0';

View File

@ -1,29 +0,0 @@
cmake_minimum_required(VERSION 3.13)
project(perseus_source)
file(GLOB SRC "src/*.cpp")
include(${SDRPP_MODULE_CMAKE})
if (MSVC)
# Lib path
target_link_directories(perseus_source PRIVATE "C:/Program Files/PothosSDR/bin/")
target_include_directories(perseus_source PUBLIC "C:/Program Files/PothosSDR/include/perseus-sdr")
target_link_libraries(perseus_source PRIVATE perseus-sdr)
else (MSVC)
find_package(PkgConfig)
pkg_check_modules(LIBPERSEUSSDR REQUIRED libperseus-sdr)
target_include_directories(perseus_source PRIVATE ${LIBPERSEUSSDR_INCLUDE_DIRS})
target_link_directories(perseus_source PRIVATE ${LIBPERSEUSSDR_LIBRARY_DIRS})
target_link_libraries(perseus_source PRIVATE ${LIBPERSEUSSDR_LIBRARIES})
# Include it because for some reason pkgconfig doesn't look here?
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
target_include_directories(perseus_source PRIVATE "/usr/local/include")
endif()
endif ()

View File

@ -1,468 +0,0 @@
#include <utils/flog.h>
#include <module.h>
#include <gui/gui.h>
#include <signal_path/signal_path.h>
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <gui/smgui.h>
#include <gui/widgets/stepped_slider.h>
#include <perseus-sdr.h>
#include <utils/optionlist.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
SDRPP_MOD_INFO{
/* Name: */ "perseus_source",
/* Description: */ "Perseus SDR source module for SDR++",
/* Author: */ "Ryzerth",
/* Version: */ 0, 1, 0,
/* Max instances */ 1
};
#define MAX_SAMPLERATE_COUNT 128
ConfigManager config;
class PerseusSourceModule : public ModuleManager::Instance {
public:
PerseusSourceModule(std::string name) {
this->name = name;
sampleRate = 768000;
handler.ctx = this;
handler.selectHandler = menuSelected;
handler.deselectHandler = menuDeselected;
handler.menuHandler = menuHandler;
handler.startHandler = start;
handler.stopHandler = stop;
handler.tuneHandler = tune;
handler.stream = &stream;
perseus_set_debug(9);
refresh();
config.acquire();
std::string serial = config.conf["device"];
config.release();
select(serial);
sigpath::sourceManager.registerSource("Perseus", &handler);
}
~PerseusSourceModule() {
stop(this);
sigpath::sourceManager.unregisterSource("Perseus");
if (libInit) { perseus_exit(); }
}
void postInit() {}
void enable() {
enabled = true;
}
void disable() {
enabled = false;
}
bool isEnabled() {
return enabled;
}
void refresh() {
// Re-initialize driver
if (libInit) { perseus_exit(); }
int devCount = perseus_init();
if (devCount < 0) {
libInit = false;
flog::error("Could not initialize libperseus: {}", perseus_errorstr());
return;
}
libInit = true;
// Open each device to get the serial number
for (int i = 0; i < devCount; i++) {
// Open device
perseus_descr* dev = perseus_open(i);
if (!dev) {
flog::error("Failed to open Perseus device with ID {}: {}", i, perseus_errorstr());
continue;
}
// Load firmware
int err = perseus_firmware_download(dev, NULL);
if (err) {
flog::error("Could not upload firmware to device {}: {}", i, perseus_errorstr());
perseus_close(dev);
continue;
}
// Get info
eeprom_prodid prodId;
err = perseus_get_product_id(dev, &prodId);
if (err) {
flog::error("Could not getproduct info from device {}: {}", i, perseus_errorstr());
perseus_close(dev);
continue;
}
// Create entry
char serial[128];
char buf[128];
sprintf(serial, "%05d", (int)prodId.sn);
sprintf(buf, "Perseus %d.%d [%s]", (int)prodId.hwver, (int)prodId.hwrel, serial);
devList.define(serial, buf, i);
// Close device
perseus_close(dev);
}
}
void select(const std::string& serial) {
// If there are no devices, give up
if (devList.empty()) {
selectedSerial.clear();
return;
}
// If the serial number is not available, select first instead
if (!devList.keyExists(serial)) {
select(devList.key(0));
return;
}
// Open device
selectedSerial = serial;
selectedPerseusId = devList.value(devList.keyId(serial));
perseus_descr* dev = perseus_open(selectedPerseusId);
if (!dev) {
flog::error("Failed to open device {}: {}", selectedPerseusId, perseus_errorstr());
selectedSerial.clear();
return;
}
// Load firmware
int err = perseus_firmware_download(dev, NULL);
if (err) {
flog::error("Could not upload firmware to device: {}", perseus_errorstr());
perseus_close(dev);
selectedSerial.clear();
return;
}
// Get info
eeprom_prodid prodId;
err = perseus_get_product_id(dev, &prodId);
if (err) {
flog::error("Could not getproduct info from device: {}", perseus_errorstr());
perseus_close(dev);
selectedSerial.clear();
return;
}
// List samplerates
srList.clear();
int samplerates[MAX_SAMPLERATE_COUNT];
memset(samplerates, 0, sizeof(int)*MAX_SAMPLERATE_COUNT);
err = perseus_get_sampling_rates(dev, samplerates, MAX_SAMPLERATE_COUNT);
if (err) {
flog::error("Could not get samplerate list: {}", perseus_errorstr());
perseus_close(dev);
selectedSerial.clear();
return;
}
for (int i = 0; i < MAX_SAMPLERATE_COUNT; i++) {
if (!samplerates[i]) { break; }
srList.define(samplerates[i], getBandwdithScaled(samplerates[i]), samplerates[i]);
}
// TODO: List attenuator values
// Load options
srId = 0;
dithering = false;
preamp = false;
preselector = true;
atten = 0;
config.acquire();
if (config.conf["devices"][selectedSerial].contains("samplerate")) {
int sr = config.conf["devices"][selectedSerial]["samplerate"];
if (srList.keyExists(sr)) {
srId = srList.keyId(sr);
}
}
if (config.conf["devices"][selectedSerial].contains("dithering")) {
dithering = config.conf["devices"][selectedSerial]["dithering"];
}
if (config.conf["devices"][selectedSerial].contains("preamp")) {
preamp = config.conf["devices"][selectedSerial]["preamp"];
}
if (config.conf["devices"][selectedSerial].contains("preselector")) {
preselector = config.conf["devices"][selectedSerial]["preselector"];
}
if (config.conf["devices"][selectedSerial].contains("attenuation")) {
atten = config.conf["devices"][selectedSerial]["attenuation"];
}
config.release();
// Update samplerate
sampleRate = srList[srId];
core::setInputSampleRate(sampleRate);
// Close device
perseus_close(dev);
}
private:
std::string getBandwdithScaled(double bw) {
char buf[1024];
if (bw >= 1000000.0) {
sprintf(buf, "%.1lfMHz", bw / 1000000.0);
}
else if (bw >= 1000.0) {
sprintf(buf, "%.1lfKHz", bw / 1000.0);
}
else {
sprintf(buf, "%.1lfHz", bw);
}
return std::string(buf);
}
static void menuSelected(void* ctx) {
PerseusSourceModule* _this = (PerseusSourceModule*)ctx;
core::setInputSampleRate(_this->sampleRate);
flog::info("PerseusSourceModule '{0}': Menu Select!", _this->name);
}
static void menuDeselected(void* ctx) {
PerseusSourceModule* _this = (PerseusSourceModule*)ctx;
flog::info("PerseusSourceModule '{0}': Menu Deselect!", _this->name);
}
static void start(void* ctx) {
PerseusSourceModule* _this = (PerseusSourceModule*)ctx;
if (_this->running) { return; }
if (_this->selectedSerial.empty()) {
flog::error("No device is selected");
return;
}
// Open device
_this->openDev = perseus_open(_this->selectedPerseusId);
if (!_this->openDev) {
flog::error("Failed to open device {}: {}", _this->selectedPerseusId, perseus_errorstr());
return;
}
// Load firmware
int err = perseus_firmware_download(_this->openDev, NULL);
if (err) {
flog::error("Could not upload firmware to device: {}", perseus_errorstr());
perseus_close(_this->openDev);
return;
}
// Set samplerate
err = perseus_set_sampling_rate(_this->openDev, _this->sampleRate);
if (err) {
flog::error("Could not set samplerate: {}", perseus_errorstr());
perseus_close(_this->openDev);
return;
}
// Set options
perseus_set_adc(_this->openDev, _this->dithering, _this->preamp);
perseus_set_attenuator_in_db(_this->openDev, _this->atten);
perseus_set_ddc_center_freq(_this->openDev, _this->freq, _this->preselector);
// Start stream
int idealBufferSize = _this->sampleRate / 200;
int multipleOf1024 = std::clamp<int>(idealBufferSize / 1024, 1, 2);
int bufferSize = multipleOf1024 * 1024;
int bufferBytes = bufferSize*6;
err = perseus_start_async_input(_this->openDev, bufferBytes, callback, _this);
if (err) {
flog::error("Could not start stream: {}", perseus_errorstr());
perseus_close(_this->openDev);
return;
}
_this->running = true;
flog::info("PerseusSourceModule '{0}': Start!", _this->name);
}
static void stop(void* ctx) {
PerseusSourceModule* _this = (PerseusSourceModule*)ctx;
if (!_this->running) { return; }
_this->running = false;
// Stop stream
_this->stream.stopWriter();
perseus_stop_async_input(_this->openDev);
_this->stream.clearWriteStop();
// Close device
perseus_close(_this->openDev);
flog::info("PerseusSourceModule '{0}': Stop!", _this->name);
}
static void tune(double freq, void* ctx) {
PerseusSourceModule* _this = (PerseusSourceModule*)ctx;
if (_this->running) {
perseus_set_ddc_center_freq(_this->openDev, freq, _this->preselector);
}
_this->freq = freq;
flog::info("PerseusSourceModule '{0}': Tune: {1}!", _this->name, freq);
}
static void menuHandler(void* ctx) {
PerseusSourceModule* _this = (PerseusSourceModule*)ctx;
if (_this->running) { SmGui::BeginDisabled(); }
SmGui::FillWidth();
SmGui::ForceSync();
if (SmGui::Combo(CONCAT("##_airspyhf_dev_sel_", _this->name), &_this->devId, _this->devList.txt)) {
std::string serial = _this->devList.key(_this->devId);
_this->select(serial);
config.acquire();
config.conf["device"] = serial;
config.release(true);
}
if (SmGui::Combo(CONCAT("##_airspyhf_sr_sel_", _this->name), &_this->srId, _this->srList.txt)) {
_this->sampleRate = _this->srList[_this->srId];
core::setInputSampleRate(_this->sampleRate);
if (!_this->selectedSerial.empty()) {
config.acquire();
config.conf["devices"][_this->selectedSerial]["samplerate"] = _this->sampleRate;
config.release(true);
}
}
SmGui::SameLine();
SmGui::FillWidth();
SmGui::ForceSync();
if (SmGui::Button(CONCAT("Refresh##_airspyhf_refr_", _this->name))) {
_this->refresh();
_this->select(_this->selectedSerial);
core::setInputSampleRate(_this->sampleRate);
}
if (_this->running) { SmGui::EndDisabled(); }
SmGui::LeftLabel("Attenuation");
SmGui::FillWidth();
if (SmGui::SliderFloatWithSteps(CONCAT("##_airspyhf_atten_", _this->name), &_this->atten, 0, 30, 10, SmGui::FMT_STR_FLOAT_DB_NO_DECIMAL)) {
if (_this->running) {
perseus_set_attenuator_in_db(_this->openDev, _this->atten);
}
if (!_this->selectedSerial.empty()) {
config.acquire();
config.conf["devices"][_this->selectedSerial]["attenuation"] = _this->atten;
config.release(true);
}
}
if (SmGui::Checkbox(CONCAT("Preamp##_airspyhf_preamp_", _this->name), &_this->preamp)) {
if (_this->running) {
perseus_set_adc(_this->openDev, _this->dithering, _this->preamp);
}
if (!_this->selectedSerial.empty()) {
config.acquire();
config.conf["devices"][_this->selectedSerial]["preamp"] = _this->preamp;
config.release(true);
}
}
if (SmGui::Checkbox(CONCAT("Dithering##_airspyhf_dither_", _this->name), &_this->dithering)) {
if (_this->running) {
perseus_set_adc(_this->openDev, _this->dithering, _this->preamp);
}
if (!_this->selectedSerial.empty()) {
config.acquire();
config.conf["devices"][_this->selectedSerial]["dithering"] = _this->dithering;
config.release(true);
}
}
if (SmGui::Checkbox(CONCAT("Preselector##_airspyhf_presel_", _this->name), &_this->preselector)) {
if (_this->running) {
perseus_set_ddc_center_freq(_this->openDev, _this->freq, _this->preselector);
}
if (!_this->selectedSerial.empty()) {
config.acquire();
config.conf["devices"][_this->selectedSerial]["preselector"] = _this->preselector;
config.release(true);
}
}
}
static int callback(void* buf, int bufferSize, void* ctx) {
PerseusSourceModule* _this = (PerseusSourceModule*)ctx;
uint8_t* samples = (uint8_t*)buf;
int sampleCount = bufferSize / 6;
for (int i = 0; i < sampleCount; i++) {
int32_t re, im;
re = *(samples++);
re |= *(samples++) << 8;
re |= *(samples++) << 16;
re |= (re >> 23) * (0xFF << 24); // Sign extend
im = *(samples++);
im |= *(samples++) << 8;
im |= *(samples++) << 16;
im |= (im >> 23) * (0xFF << 24); // Sign extend
_this->stream.writeBuf[i].re = ((float)re / (float)0x7FFFFF);
_this->stream.writeBuf[i].im = ((float)im / (float)0x7FFFFF);
}
_this->stream.swap(sampleCount);
return 0;
}
std::string name;
bool enabled = true;
dsp::stream<dsp::complex_t> stream;
int sampleRate;
SourceManager::SourceHandler handler;
bool running = false;
double freq;
int devId = 0;
int srId = 0;
bool libInit = false;
perseus_descr* openDev;
std::string selectedSerial = "";
int selectedPerseusId;
float atten = 0;
bool preamp = false;
bool dithering = false;
bool preselector = true;
OptionList<std::string, int> devList;
OptionList<int, int> srList;
};
MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = "";
config.setPath(core::args["root"].s() + "/perseus_config.json");
config.load(def);
config.enableAutoSave();
}
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
return new PerseusSourceModule(name);
}
MOD_EXPORT void _DELETE_INSTANCE_(ModuleManager::Instance* instance) {
delete (PerseusSourceModule*)instance;
}
MOD_EXPORT void _END_() {
config.disableAutoSave();
config.save();
}

View File

@ -171,7 +171,7 @@ public:
#ifndef __ANDROID__ #ifndef __ANDROID__
int oret = rtlsdr_open(&openDev, id); int oret = rtlsdr_open(&openDev, id);
#else #else
int oret = rtlsdr_open_sys_dev(&openDev, devFd); int oret = rtlsdr_open_fd(&openDev, devFd);
#endif #endif
if (oret < 0) { if (oret < 0) {
@ -285,7 +285,7 @@ private:
#ifndef __ANDROID__ #ifndef __ANDROID__
int oret = rtlsdr_open(&_this->openDev, _this->devId); int oret = rtlsdr_open(&_this->openDev, _this->devId);
#else #else
int oret = rtlsdr_open_sys_dev(&_this->openDev, _this->devFd); int oret = rtlsdr_open_fd(&_this->openDev, _this->devFd);
#endif #endif
if (oret < 0) { if (oret < 0) {
@ -523,8 +523,8 @@ private:
RTLSDRSourceModule* _this = (RTLSDRSourceModule*)ctx; RTLSDRSourceModule* _this = (RTLSDRSourceModule*)ctx;
int sampCount = len / 2; int sampCount = len / 2;
for (int i = 0; i < sampCount; i++) { for (int i = 0; i < sampCount; i++) {
_this->stream.writeBuf[i].re = ((float)buf[i * 2] - 127.4) / 128.0f; _this->stream.writeBuf[i].re = (float)(buf[i * 2] - 127) / 128.0f;
_this->stream.writeBuf[i].im = ((float)buf[(i * 2) + 1] - 127.4) / 128.0f; _this->stream.writeBuf[i].im = (float)(buf[(i * 2) + 1] - 127) / 128.0f;
} }
if (!_this->stream.swap(sampCount)) { return; } if (!_this->stream.swap(sampCount)) { return; }
} }

View File

@ -28,7 +28,7 @@ public:
this->name = name; this->name = name;
strcpy(hostname, "localhost"); strcpy(hostname, "localhost");
sampleRate = 5750000.0; sampleRate = 41000000.0;
handler.ctx = this; handler.ctx = this;
handler.selectHandler = menuSelected; handler.selectHandler = menuSelected;
@ -103,14 +103,8 @@ private:
static void tune(double freq, void* ctx) { static void tune(double freq, void* ctx) {
SpectranHTTPSourceModule* _this = (SpectranHTTPSourceModule*)ctx; SpectranHTTPSourceModule* _this = (SpectranHTTPSourceModule*)ctx;
bool connected = (_this->client && _this->client->isOpen()); if (_this->running) {
if (connected) { // TODO
int64_t newfreq = round(freq);
if (newfreq != _this->lastReportedFreq && _this->gotReport) {
flog::debug("Sending tuning command");
_this->lastReportedFreq = newfreq;
_this->client->setCenterFrequency(newfreq);
}
} }
_this->freq = freq; _this->freq = freq;
flog::info("SpectranHTTPSourceModule '{0}': Tune: {1}!", _this->name, freq); flog::info("SpectranHTTPSourceModule '{0}': Tune: {1}!", _this->name, freq);
@ -144,8 +138,6 @@ private:
_this->tryConnect(); _this->tryConnect();
} }
else if (connected && SmGui::Button("Disconnect##spectran_http_source")) { else if (connected && SmGui::Button("Disconnect##spectran_http_source")) {
_this->client->onCenterFrequencyChanged.unbind(_this->onFreqChangedId);
_this->client->onCenterFrequencyChanged.unbind(_this->onSamplerateChangedId);
_this->client->close(); _this->client->close();
} }
if (_this->running) { style::endDisabled(); } if (_this->running) { style::endDisabled(); }
@ -162,28 +154,13 @@ private:
void tryConnect() { void tryConnect() {
try { try {
gotReport = false;
client = std::make_shared<SpectranHTTPClient>(hostname, port, &stream); client = std::make_shared<SpectranHTTPClient>(hostname, port, &stream);
onFreqChangedId = client->onCenterFrequencyChanged.bind(&SpectranHTTPSourceModule::onFreqChanged, this);
onSamplerateChangedId = client->onSamplerateChanged.bind(&SpectranHTTPSourceModule::onSamplerateChanged, this);
client->startWorker();
} }
catch (std::runtime_error e) { catch (std::runtime_error e) {
flog::error("Could not connect: {0}", e.what()); flog::error("Could not connect: {0}", e.what());
} }
} }
void onFreqChanged(double newFreq) {
if (lastReportedFreq == newFreq) { return; }
lastReportedFreq = newFreq;
tuner::tune(tuner::TUNER_MODE_IQ_ONLY, "", newFreq);
gotReport = true;
}
void onSamplerateChanged(double newSr) {
core::setInputSampleRate(newSr);
}
std::string name; std::string name;
bool enabled = true; bool enabled = true;
double sampleRate; double sampleRate;
@ -191,16 +168,11 @@ private:
bool running = false; bool running = false;
std::shared_ptr<SpectranHTTPClient> client; std::shared_ptr<SpectranHTTPClient> client;
HandlerID onFreqChangedId;
HandlerID onSamplerateChangedId;
double freq; double freq;
int64_t lastReportedFreq = 0;
bool gotReport;
char hostname[1024]; char hostname[1024];
int port = 54664; int port = 80;
dsp::stream<dsp::complex_t> stream; dsp::stream<dsp::complex_t> stream;
}; };

View File

@ -5,8 +5,6 @@ SpectranHTTPClient::SpectranHTTPClient(std::string host, int port, dsp::stream<d
this->stream = stream; this->stream = stream;
// Connect to server // Connect to server
this->host = host;
this->port = port;
sock = net::connect(host, port); sock = net::connect(host, port);
http = net::http::Client(sock); http = net::http::Client(sock);
@ -16,13 +14,6 @@ SpectranHTTPClient::SpectranHTTPClient(std::string host, int port, dsp::stream<d
net::http::ResponseHeader rshdr; net::http::ResponseHeader rshdr;
http.recvResponseHeader(rshdr, 5000); http.recvResponseHeader(rshdr, 5000);
if (rshdr.getStatusCode() != net::http::STATUS_CODE_OK) {
flog::error("HTTP request did not return ok: {}", rshdr.getStatusString());
throw std::runtime_error("HTTP request did not return ok");
}
}
void SpectranHTTPClient::startWorker() {
// Start chunk worker // Start chunk worker
workerThread = std::thread(&SpectranHTTPClient::worker, this); workerThread = std::thread(&SpectranHTTPClient::worker, this);
} }
@ -42,27 +33,6 @@ void SpectranHTTPClient::close() {
stream->clearWriteStop(); stream->clearWriteStop();
} }
void SpectranHTTPClient::setCenterFrequency(uint64_t freq) {
// Connect to control endpoint (TODO: Switch to an always connected endpoint)
auto controlSock = net::connect(host, port);
auto controlHttp = net::http::Client(controlSock);
// Make request
net::http::RequestHeader rqhdr(net::http::METHOD_PUT, "/control", host);
char buf[1024];
sprintf(buf, "{\"frequencyCenter\":%d,\"frequencySpan\":%d,\"type\":\"capture\"}", freq, _samplerate);
std::string data = buf;
char lenBuf[16];
sprintf(lenBuf, "%d", data.size());
rqhdr.setField("Content-Length", lenBuf);
controlHttp.sendRequestHeader(rqhdr);
controlSock->sendstr(data);
net::http::ResponseHeader rshdr;
controlHttp.recvResponseHeader(rshdr, 5000);
flog::debug("Response: {}", rshdr.getStatusString());
}
void SpectranHTTPClient::worker() { void SpectranHTTPClient::worker() {
while (sock->isOpen()) { while (sock->isOpen()) {
// Get chunk header // Get chunk header
@ -82,41 +52,6 @@ void SpectranHTTPClient::worker() {
return; return;
} }
// Decode JSON (yes, this is hacky, but it must be extremely fast)
auto startFreqBegin = jsonData.find("\"startFrequency\":");
auto startFreqEnd = jsonData.find(',', startFreqBegin);
std::string startFreqStr = jsonData.substr(startFreqBegin + 17, startFreqEnd - startFreqBegin - 17);
int64_t startFreq = std::stoll(startFreqStr);
auto endFreqBegin = jsonData.find("\"endFrequency\":");
auto endFreqEnd = jsonData.find(',', endFreqBegin);
std::string endFreqStr = jsonData.substr(endFreqBegin + 15, endFreqEnd - endFreqBegin - 15);
int64_t endFreq = std::stoll(endFreqStr);
auto sampleFreqBegin = jsonData.find("\"sampleFrequency\":");
bool sampleFreqReceived = (sampleFreqBegin != -1);
int64_t sampleFreq;
if (sampleFreqReceived) {
auto sampleFreqEnd = jsonData.find(',', sampleFreqBegin);
std::string sampleFreqStr = jsonData.substr(sampleFreqBegin + 18, sampleFreqEnd - sampleFreqBegin - 18);
sampleFreq = std::stoll(sampleFreqStr);
//flog::debug("{}", jsonData);
}
// Calculate and update center freq
int64_t samplerate = /* sampleFreqReceived ? sampleFreq : */(endFreq - startFreq);
int64_t centerFreq = round(((double)endFreq + (double)startFreq) / 2.0);
if (centerFreq != _centerFreq) {
flog::debug("New center freq: {}", centerFreq);
_centerFreq = centerFreq;
onCenterFrequencyChanged(centerFreq);
}
if (samplerate != _samplerate) {
flog::debug("New samplerate: {}", samplerate);
_samplerate = samplerate;
onSamplerateChanged(samplerate);
}
// Read (and check for) record separator // Read (and check for) record separator
uint8_t rs; uint8_t rs;
int rslen = sock->recv(&rs, 1, true, 5000); int rslen = sock->recv(&rs, 1, true, 5000);
@ -137,11 +72,10 @@ void SpectranHTTPClient::worker() {
i += read; i += read;
sampLen += read; sampLen += read;
} }
int sampCount = sampLen / 8;
// Swap to stream // Swap to stream
if (streamingEnabled) { if (streamingEnabled) {
if (!stream->swap(sampCount)) { return; } if (!stream->swap(sampLen / 8)) { return; }
} }
// Read trailing CRLF // Read trailing CRLF

View File

@ -4,35 +4,22 @@
#include <string> #include <string>
#include <thread> #include <thread>
#include <utils/proto/http.h> #include <utils/proto/http.h>
#include <utils/new_event.h>
#include <stdint.h>
class SpectranHTTPClient { class SpectranHTTPClient {
public: public:
SpectranHTTPClient(std::string host, int port, dsp::stream<dsp::complex_t>* stream); SpectranHTTPClient(std::string host, int port, dsp::stream<dsp::complex_t>* stream);
void startWorker();
void streaming(bool enabled); void streaming(bool enabled);
bool isOpen(); bool isOpen();
void close(); void close();
void setCenterFrequency(uint64_t freq);
NewEvent<uint64_t> onCenterFrequencyChanged;
NewEvent<uint64_t> onSamplerateChanged;
private: private:
void worker(); void worker();
std::string host;
int port;
std::shared_ptr<net::Socket> sock; std::shared_ptr<net::Socket> sock;
net::http::Client http; net::http::Client http;
dsp::stream<dsp::complex_t>* stream; dsp::stream<dsp::complex_t>* stream;
std::thread workerThread; std::thread workerThread;
bool streamingEnabled = false; bool streamingEnabled = false;
int64_t _centerFreq = 0;
uint64_t _samplerate = 0;
}; };