From 968a755ff4a83aaae31fbc93f1cdbb94308164b6 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Wed, 27 Dec 2023 10:22:51 +0900 Subject: [PATCH 01/26] README.md: remove readerwriterqueue --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ae05912..513f239 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,6 @@ airspy-fmradion -m am -t airspyhf -q \ - [RTL-SDR library](http://sdr.osmocom.org/trac/wiki/rtl-sdr) - [sndfile](https://github.com/erikd/libsndfile) - [r8brain-free-src](https://github.com/avaneev/r8brain-free-src), a sample rate converter designed by Aleksey Vaneev of Voxengo - - [readerwriterqueue](https://github.com/cameron314/readerwriterqueue) - [VOLK](https://www.libvolk.org/) - [PortAudio](http://www.portaudio.com) - Tested: Airspy R2, Airspy Mini, Airspy HF+ Dual Port, RTL-SDR V3 @@ -136,7 +135,7 @@ Use the latest HEAD version. #### git submodules -r8brain-free-src and readerwriterqueue are the submodules of this repository. Download the submodule repositories by the following git procedure: +r8brain-free-src is the submodule of this repository. Download the submodule repositories by the following git procedure: - `git submodule update --init --recursive` From c1dbf72e51163a825d75a255455b511443015d89 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Thu, 4 Jan 2024 14:14:18 +0900 Subject: [PATCH 02/26] Use averaging on pilot level threshold detection --- main.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/main.cpp b/main.cpp index 2b9500c..6664ef1 100644 --- a/main.cpp +++ b/main.cpp @@ -812,6 +812,10 @@ int main(int argc, char **argv) { MovingAverage fm_afc_average(fm_afc_average_stages, 0.0f); const unsigned int fm_afc_hz_step = 10; FineTuner fm_afc_finetuner((unsigned int)fm_target_rate / fm_afc_hz_step); + // Initialize moving average object for FM stereo pilot level monitoring. + const unsigned int pilot_level_average_stages = 10; + MovingAverage pilot_level_average(pilot_level_average_stages, 0.0f); + float fm_afc_offset_sum = 0.0; float audio_level = 0; @@ -824,8 +828,7 @@ int main(int argc, char **argv) { float if_level = 0; PilotState pilot_status = PilotState::NotDetected; - double previous_pilot_level = 0.0; - constexpr double pilot_level_threshold = 0.01; + constexpr float pilot_level_threshold = 0.01; /////////////////////////////////////// // NOTE: main processing loop from here @@ -969,9 +972,10 @@ int main(int argc, char **argv) { // Stereo detection display // Use a state machine here if (modtype == ModType::FM) { - double pilot_level = fm.get_pilot_level(); - double pilot_level_diff = - std::abs(pilot_level - previous_pilot_level); + float pilot_level = fm.get_pilot_level(); + float pilot_level_diff = + std::abs(pilot_level - pilot_level_average.average()); + pilot_level_average.feed(pilot_level); bool stereo_status = fm.stereo_detected(); switch (pilot_status) { case PilotState::NotDetected: @@ -979,12 +983,12 @@ int main(int argc, char **argv) { fprintf(stderr, "\ngot stereo signal, pilot level = %.7f\n", pilot_level); pilot_status = PilotState::Detected; + pilot_level_average.fill(0.0f); } break; case PilotState::Detected: if (!stereo_status) { fprintf(stderr, "\nlost stereo signal\n"); - previous_pilot_level = 0.0; pilot_status = PilotState::NotDetected; } else { if (pilot_level_diff < pilot_level_threshold) { @@ -997,7 +1001,6 @@ int main(int argc, char **argv) { case PilotState::Stabilized: if (!stereo_status) { fprintf(stderr, "\nlost stereo signal\n"); - previous_pilot_level = 0.0; pilot_status = PilotState::NotDetected; } else { if (pilot_level_diff >= pilot_level_threshold) { @@ -1008,7 +1011,6 @@ int main(int argc, char **argv) { } break; } - previous_pilot_level = pilot_level; } // Show per-block statistics. // Add 1e-9 to log10() to prevent generating NaN @@ -1016,6 +1018,13 @@ int main(int argc, char **argv) { switch (modtype) { case ModType::FM: + fprintf(stderr, + "\rblk=%11" PRIu64 + ":ppm=%+7.3f:IF=%+6.1fdB:AF=%+6.1fdB:Pilot= %8.6f", + block, ppm_average.average(), if_level_db, audio_level_db, + pilot_level_average.average()); + fflush(stderr); + break; case ModType::NBFM: fprintf(stderr, "\rblk=%11" PRIu64 ":ppm=%+7.3f:IF=%+6.1fdB:AF=%+6.1fdB", From 19797625e9539c674b174c8dbad7858aa0c00566 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Thu, 4 Jan 2024 14:36:46 +0900 Subject: [PATCH 03/26] Raise pilot_level_threshold to 0.02 --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 6664ef1..1a91e27 100644 --- a/main.cpp +++ b/main.cpp @@ -828,7 +828,7 @@ int main(int argc, char **argv) { float if_level = 0; PilotState pilot_status = PilotState::NotDetected; - constexpr float pilot_level_threshold = 0.01; + constexpr float pilot_level_threshold = 0.02; /////////////////////////////////////// // NOTE: main processing loop from here From c25d3abbad3265e89af45706a49e82b97b3ea124 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Fri, 5 Jan 2024 09:56:05 +0900 Subject: [PATCH 04/26] Add cmake-git-version-tracking * See * Using local fork at --- CMakeLists.txt | 13 ++++- include/git.h | 148 +++++++++++++++++++++++++++++++++++++++++++++++++ main.cpp | 14 +++++ 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 include/git.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 263617f..359ed32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # CMake definitions for airspy-fmradion -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.18) project(airspy-fmradion) # Workaround for the compilation warning @@ -8,9 +8,18 @@ if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) +# Use cmake-git-version-tracking +include(FetchContent) +FetchContent_Declare(cmake_git_version_tracking + GIT_REPOSITORY https://github.com/jj1bdx/cmake-git-version-tracking.git + GIT_TAG 9b5fc5088b4089ff2adc20d607976b9923e3d737 +) +FetchContent_MakeAvailable(cmake_git_version_tracking) + # Use pkg-config include(FindPkgConfig) +# Find Threads package find_package(Threads) # Find Volk library. @@ -205,6 +214,7 @@ set(sfmbase_HEADERS include/FineTuner.h include/FmDecode.h include/FourthConverterIQ.h + include/git.h include/IfResampler.h include/IfSimpleAgc.h include/MovingAverage.h @@ -272,6 +282,7 @@ target_link_libraries(airspy-fmradion ${PORTAUDIO_LINK_LIBRARIES} ${VOLK_LIBRARY} ${EXTRA_LIBS} + cmake_git_version_tracking ) target_link_libraries(sfmbase diff --git a/include/git.h b/include/git.h new file mode 100644 index 0000000..9980139 --- /dev/null +++ b/include/git.h @@ -0,0 +1,148 @@ +#pragma once +// git.h +// https://raw.githubusercontent.com/andrew-hardin/cmake-git-version-tracking/master/git.h +// +// Released under the MIT License. +// https://raw.githubusercontent.com/andrew-hardin/cmake-git-version-tracking/master/LICENSE + +#include + +#ifdef __cplusplus +#define GIT_VERSION_TRACKING_EXTERN_C_BEGIN extern "C" { +#define GIT_VERSION_TRACKING_EXTERN_C_END } +#else +#define GIT_VERSION_TRACKING_EXTERN_C_BEGIN +#define GIT_VERSION_TRACKING_EXTERN_C_END +#endif + +// Don't mangle the C function names if included in a CXX file. +GIT_VERSION_TRACKING_EXTERN_C_BEGIN + +/// Is the metadata populated? +// +/// We may not have metadata if there wasn't a .git directory +/// (e.g. downloaded source code without revision history). +bool git_IsPopulated(); + +/// Were there any uncommitted changes that won't be reflected +/// in the CommitID? +bool git_AnyUncommittedChanges(); + +/// The commit author's name. +const char *git_AuthorName(); + +/// The commit author's email. +const char *git_AuthorEmail(); + +/// The commit SHA1. +const char *git_CommitSHA1(); + +/// The ISO8601 commit date. +const char *git_CommitDate(); + +/// The commit subject. +const char *git_CommitSubject(); + +/// The commit body. +const char *git_CommitBody(); + +/// The commit describe. +const char *git_Describe(); + +/// The symbolic reference tied to HEAD. +const char *git_Branch(); + +GIT_VERSION_TRACKING_EXTERN_C_END +#undef GIT_VERSION_TRACKING_EXTERN_C_BEGIN +#undef GIT_VERSION_TRACKING_EXTERN_C_END + +#ifdef __cplusplus + +/// This is a utility extension for C++ projects. +/// It provides a "git" namespace that wraps the +/// C methods in more(?) ergonomic types. +/// +/// This is header-only in an effort to keep the +/// underlying static library C99 compliant. + +// We really want to use std::string_view if it appears +// that the compiler will support it. If that fails, +// revert back to std::string. +#define GIT_VERSION_TRACKING_CPP_17_STANDARD 201703L +#if __cplusplus >= GIT_VERSION_TRACKING_CPP_17_STANDARD +#define GIT_VERSION_USE_STRING_VIEW 1 +#else +#define GIT_VERSION_USE_STRING_VIEW 0 +#endif + +#if GIT_VERSION_USE_STRING_VIEW +#include +#include +#else +#include +#endif + +namespace git { + +#if GIT_VERSION_USE_STRING_VIEW +using StringOrView = std::string_view; +#else +typedef std::string StringOrView; +#endif + +namespace internal { + +/// Short-hand method for initializing a std::string or std::string_view given a +/// C-style const char*. +inline const StringOrView InitString(const char *from_c_interface) { +#if GIT_VERSION_USE_STRING_VIEW + return StringOrView{from_c_interface, std::strlen(from_c_interface)}; +#else + return std::string(from_c_interface); +#endif +} + +} // namespace internal + +inline bool IsPopulated() { return git_IsPopulated(); } +inline bool AnyUncommittedChanges() { return git_AnyUncommittedChanges(); } +inline const StringOrView &AuthorName() { + static const StringOrView kValue = internal::InitString(git_AuthorName()); + return kValue; +} +inline const StringOrView AuthorEmail() { + static const StringOrView kValue = internal::InitString(git_AuthorEmail()); + return kValue; +} +inline const StringOrView CommitSHA1() { + static const StringOrView kValue = internal::InitString(git_CommitSHA1()); + return kValue; +} +inline const StringOrView CommitDate() { + static const StringOrView kValue = internal::InitString(git_CommitDate()); + return kValue; +} +inline const StringOrView CommitSubject() { + static const StringOrView kValue = internal::InitString(git_CommitSubject()); + return kValue; +} +inline const StringOrView CommitBody() { + static const StringOrView kValue = internal::InitString(git_CommitBody()); + return kValue; +} +inline const StringOrView Describe() { + static const StringOrView kValue = internal::InitString(git_Describe()); + return kValue; +} +inline const StringOrView Branch() { + static const StringOrView kValue = internal::InitString(git_Branch()); + return kValue; +} + +} // namespace git + +// Cleanup our defines to avoid polluting. +#undef GIT_VERSION_USE_STRING_VIEW +#undef GIT_VERSION_TRACKING_CPP_17_STANDARD + +#endif // __cplusplus diff --git a/main.cpp b/main.cpp index 1a91e27..6bf75b6 100644 --- a/main.cpp +++ b/main.cpp @@ -47,6 +47,7 @@ #include "RtlSdrSource.h" #include "SoftFM.h" #include "Utility.h" +#include "git.h" // define this for enabling coefficient monitor functions // #undef COEFF_MONITOR @@ -322,6 +323,19 @@ int main(int argc, char **argv) { fprintf(stderr, "airspy-fmradion " AIRSPY_FMRADION_VERSION "\n"); fprintf(stderr, "Software FM/AM radio for "); fprintf(stderr, "Airspy R2, Airspy HF+, and RTL-SDR\n"); + if (git::IsPopulated()) { + fprintf(stderr, "Git Commit SHA1: %.*s", + static_cast(git::CommitSHA1().length()), + git::CommitSHA1().data()); + if (git::AnyUncommittedChanges()) { + fprintf(stderr, " with uncommitted changes"); + } + fprintf(stderr, "\n"); + fprintf(stderr, "Git branch: %.*s\n", + static_cast(git::Branch().length()), git::Branch().data()); + } else { + fprintf(stderr, "Git commit unknown\n"); + } fprintf(stderr, "VOLK_VERSION = %.6o\n", VOLK_VERSION); const struct option longopts[] = { From 421c3bdc7646714dbcbbe2e13c4741d3478c4637 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Fri, 5 Jan 2024 01:18:17 +0000 Subject: [PATCH 05/26] Ignore .cache/ and build/ contents --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 60ea9a4..c3da118 100644 --- a/.gitignore +++ b/.gitignore @@ -145,3 +145,11 @@ _deps *-prefix/ # End of https://www.toptal.com/developers/gitignore/api/cmake + +# clangd + +.cache/ + +# working directory + +build/ From b5c2803c75eeeb962a09c37582b111ef5a419ecd Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Fri, 5 Jan 2024 10:56:23 +0900 Subject: [PATCH 06/26] Add old softfm code sincfilter3.py --- doc/txt-ngsoftfm-jj1bdx/sincfilter3.py | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100755 doc/txt-ngsoftfm-jj1bdx/sincfilter3.py diff --git a/doc/txt-ngsoftfm-jj1bdx/sincfilter3.py b/doc/txt-ngsoftfm-jj1bdx/sincfilter3.py new file mode 100755 index 0000000..c2109e4 --- /dev/null +++ b/doc/txt-ngsoftfm-jj1bdx/sincfilter3.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# Curve-fitting calculation script for sinc compensation + +import math +import csv + +def aperture(x): + if x == 0.0: + return 1.0 + else: + return 2.0 / x * math.sin(x/2.0) + +def mov1(x): + y = math.sin(x/4.0); + if y == 0.0: + return 0.0 + else: + return 0.5 * math.sin(x/2.0) / math.sin (x/4.0) + +# filter model: +# mov1: moving-average filter (stage number: 1) +# mov1[n] = (input[n-1] + input[n]) / 2.0 +# final output: gain-controlled sum of the above two filters +# output[n] = staticgain * input[n] - fitfactor * mov1[n] + +maxfreq = 192000 +staticgain = 1.47112063 +fitfactor = 0.48567701 + +with open('sincfilter3.csv', mode='w') as output_file: + fieldnames = ['freq', 'compensate', 'fitlevel', 'logratio'] + output_writer = csv.DictWriter(output_file, fieldnames=fieldnames) + + output_writer.writeheader() + + for freq in range(50,53100,1000): + theta = 2 * math.pi * freq / maxfreq; + compensate = 1.0 / aperture(theta) + fitlevel = staticgain - (fitfactor * mov1(2 * theta)) + logratio = math.log10(compensate / fitlevel) + output_writer.writerow({ + 'freq': freq, + 'compensate': compensate, + 'fitlevel': fitlevel, + 'logratio': logratio + }) From 5e4050c579b71c14c5b2f5c2d427f37758bac29d Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Fri, 5 Jan 2024 21:39:49 +0900 Subject: [PATCH 07/26] Stop using PilotState::Detected --- include/SoftFM.h | 2 +- main.cpp | 23 +---------------------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/include/SoftFM.h b/include/SoftFM.h index 846bd59..b91c4b9 100644 --- a/include/SoftFM.h +++ b/include/SoftFM.h @@ -53,6 +53,6 @@ enum class OutputMode { WAV_FLOAT32, PORTAUDIO }; -enum class PilotState { NotDetected, Detected, Stabilized }; +enum class PilotState { NotDetected, Detected }; #endif diff --git a/main.cpp b/main.cpp index 6bf75b6..b1dcaeb 100644 --- a/main.cpp +++ b/main.cpp @@ -987,15 +987,12 @@ int main(int argc, char **argv) { // Use a state machine here if (modtype == ModType::FM) { float pilot_level = fm.get_pilot_level(); - float pilot_level_diff = - std::abs(pilot_level - pilot_level_average.average()); pilot_level_average.feed(pilot_level); bool stereo_status = fm.stereo_detected(); switch (pilot_status) { case PilotState::NotDetected: if (stereo_status) { - fprintf(stderr, "\ngot stereo signal, pilot level = %.7f\n", - pilot_level); + fprintf(stderr, "\ngot stereo signal\n"); pilot_status = PilotState::Detected; pilot_level_average.fill(0.0f); } @@ -1004,24 +1001,6 @@ int main(int argc, char **argv) { if (!stereo_status) { fprintf(stderr, "\nlost stereo signal\n"); pilot_status = PilotState::NotDetected; - } else { - if (pilot_level_diff < pilot_level_threshold) { - fprintf(stderr, "\npilot level stabilized to %.7f\n", - pilot_level); - pilot_status = PilotState::Stabilized; - } - } - break; - case PilotState::Stabilized: - if (!stereo_status) { - fprintf(stderr, "\nlost stereo signal\n"); - pilot_status = PilotState::NotDetected; - } else { - if (pilot_level_diff >= pilot_level_threshold) { - fprintf(stderr, "\npilot level destabilized to %.7f\n", - pilot_level); - pilot_status = PilotState::Detected; - } } break; } From be0c6654d200fac5a7aa03918d5760630c8b1599 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Fri, 5 Jan 2024 21:43:09 +0900 Subject: [PATCH 08/26] CMakeLists.txt: add compile_commands.json support * Enable default compile_commands.json support * Disable compile_commands.json for cmake-git-version-tracking code - To prevent unwanted cluttering of clangd --- CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 359ed32..bef50a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,9 @@ if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) +# Enable compile_commands.json as default +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + # Use cmake-git-version-tracking include(FetchContent) FetchContent_Declare(cmake_git_version_tracking @@ -15,6 +18,14 @@ FetchContent_Declare(cmake_git_version_tracking GIT_TAG 9b5fc5088b4089ff2adc20d607976b9923e3d737 ) FetchContent_MakeAvailable(cmake_git_version_tracking) +# EXPORT_COMPILE_COMMANDS is supported for CMake version 3.20 or later only +if (CMAKE_VERSION VERSION_LESS 3.20.0) + message(STATUS "No EXPORT_COMPILE_COMMANDS available") + message(STATUS "Use compdb for proper compile_commands.json handling") +else() + set_target_properties(cmake_git_version_tracking + PROPERTIES EXPORT_COMPILE_COMMANDS OFF) +endif() # Use pkg-config include(FindPkgConfig) From 6d1983939c3a05001756e19c70519897acc5af12 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Fri, 5 Jan 2024 21:58:07 +0900 Subject: [PATCH 09/26] main.cpp: remove pilot_level_threshold --- main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/main.cpp b/main.cpp index b1dcaeb..422a521 100644 --- a/main.cpp +++ b/main.cpp @@ -842,7 +842,6 @@ int main(int argc, char **argv) { float if_level = 0; PilotState pilot_status = PilotState::NotDetected; - constexpr float pilot_level_threshold = 0.02; /////////////////////////////////////// // NOTE: main processing loop from here From 75f47072836c0a18db9f9f511642564a8dbe22ef Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 15:29:00 +0900 Subject: [PATCH 10/26] Airspy{HF}Source.h: add thread header --- include/AirspyHFSource.h | 1 + include/AirspySource.h | 1 + 2 files changed, 2 insertions(+) diff --git a/include/AirspyHFSource.h b/include/AirspyHFSource.h index 224dcf3..cb7290e 100644 --- a/include/AirspyHFSource.h +++ b/include/AirspyHFSource.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "Source.h" diff --git a/include/AirspySource.h b/include/AirspySource.h index e9950ad..2fb4494 100644 --- a/include/AirspySource.h +++ b/include/AirspySource.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "Source.h" From c4ab3c22c7b7a17986ac6fa09acb5db0a1f9f34e Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 15:47:28 +0900 Subject: [PATCH 11/26] Remove unused include directives --- include/AmDecode.h | 2 -- include/AudioOutput.h | 1 - include/MovingAverage.h | 1 - include/NbfmDecode.h | 3 --- include/PilotPhaseLock.h | 5 ----- include/Source.h | 1 - main.cpp | 4 ---- sfmbase/AirspyHFSource.cpp | 1 - sfmbase/AudioOutput.cpp | 1 - sfmbase/FileSource.cpp | 1 - sfmbase/IfSimpleAgc.cpp | 1 - 11 files changed, 21 deletions(-) diff --git a/include/AmDecode.h b/include/AmDecode.h index 0153249..27a1b7d 100644 --- a/include/AmDecode.h +++ b/include/AmDecode.h @@ -21,11 +21,9 @@ #define INCLUDE_AMDECODE_H #include "AfSimpleAgc.h" -#include "AudioResampler.h" #include "Filter.h" #include "FilterParameters.h" #include "FineTuner.h" -#include "FourthConverterIQ.h" #include "IfResampler.h" #include "IfSimpleAgc.h" #include "SoftFM.h" diff --git a/include/AudioOutput.h b/include/AudioOutput.h index 2021caa..6c4b955 100644 --- a/include/AudioOutput.h +++ b/include/AudioOutput.h @@ -20,7 +20,6 @@ #ifndef INCLUDE_AUDIOOUTPUT_H #define INCLUDE_AUDIOOUTPUT_H -#include #include #include "SoftFM.h" diff --git a/include/MovingAverage.h b/include/MovingAverage.h index 880247e..66d6ed3 100644 --- a/include/MovingAverage.h +++ b/include/MovingAverage.h @@ -20,7 +20,6 @@ #ifndef INCLUDE_MOVINGAVERAGE_H #define INCLUDE_MOVINGAVERAGE_H -#include #include template class MovingAverage { diff --git a/include/NbfmDecode.h b/include/NbfmDecode.h index 3b833bf..c34be25 100644 --- a/include/NbfmDecode.h +++ b/include/NbfmDecode.h @@ -19,9 +19,6 @@ #ifndef INCLUDE_NBFMDECODE_H #define INCLUDE_NBFMDECODE_H -#include - -#include "AudioResampler.h" #include "Filter.h" #include "FilterParameters.h" #include "IfSimpleAgc.h" diff --git a/include/PilotPhaseLock.h b/include/PilotPhaseLock.h index 8a132fc..7f0a66a 100644 --- a/include/PilotPhaseLock.h +++ b/include/PilotPhaseLock.h @@ -20,12 +20,7 @@ #ifndef INCLUDE_PILOTPHASELOCK_H #define INCLUDE_PILOTPHASELOCK_H -#include "AudioResampler.h" #include "Filter.h" -#include "FilterParameters.h" -#include "IfSimpleAgc.h" -#include "MultipathFilter.h" -#include "PhaseDiscriminator.h" #include "SoftFM.h" // Phase-locked loop for stereo pilot. diff --git a/include/Source.h b/include/Source.h index 35ea9c1..03c6c15 100644 --- a/include/Source.h +++ b/include/Source.h @@ -21,7 +21,6 @@ #define INCLUDE_SOURCE_H #include -#include #include #include "DataBuffer.h" diff --git a/main.cpp b/main.cpp index 422a521..f4e33a9 100644 --- a/main.cpp +++ b/main.cpp @@ -17,9 +17,7 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html -#include #include -#include #include #include #include @@ -28,7 +26,6 @@ #include #include #include -#include #include #include "AirspyHFSource.h" @@ -37,7 +34,6 @@ #include "AudioOutput.h" #include "DataBuffer.h" #include "FileSource.h" -#include "Filter.h" #include "FilterParameters.h" #include "FineTuner.h" #include "FmDecode.h" diff --git a/sfmbase/AirspyHFSource.cpp b/sfmbase/AirspyHFSource.cpp index 5935b24..e23a679 100644 --- a/sfmbase/AirspyHFSource.cpp +++ b/sfmbase/AirspyHFSource.cpp @@ -17,7 +17,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include #include #include #include diff --git a/sfmbase/AudioOutput.cpp b/sfmbase/AudioOutput.cpp index 3342442..93210d8 100644 --- a/sfmbase/AudioOutput.cpp +++ b/sfmbase/AudioOutput.cpp @@ -20,7 +20,6 @@ #include "sndfile.h" #define _FILE_OFFSET_BITS 64 -#include #include #include #include diff --git a/sfmbase/FileSource.cpp b/sfmbase/FileSource.cpp index 9488785..9cec62b 100644 --- a/sfmbase/FileSource.cpp +++ b/sfmbase/FileSource.cpp @@ -25,7 +25,6 @@ #include "ConfigParser.h" #include "FileSource.h" -#include "Utility.h" FileSource *FileSource::m_this = 0; diff --git a/sfmbase/IfSimpleAgc.cpp b/sfmbase/IfSimpleAgc.cpp index f9af04d..6cc8977 100644 --- a/sfmbase/IfSimpleAgc.cpp +++ b/sfmbase/IfSimpleAgc.cpp @@ -17,7 +17,6 @@ // along with this program. If not, see . #include "IfSimpleAgc.h" -#include "Utility.h" // class IfSimpleAgc From 702d048b264ee51d43be1b2804b615d04a1f364f Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 18:32:06 +0900 Subject: [PATCH 12/26] AirspyHFSource: use Utility::parse_int() instead of atoi() --- sfmbase/AirspyHFSource.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/sfmbase/AirspyHFSource.cpp b/sfmbase/AirspyHFSource.cpp index e23a679..bf1b1c9 100644 --- a/sfmbase/AirspyHFSource.cpp +++ b/sfmbase/AirspyHFSource.cpp @@ -297,10 +297,12 @@ bool AirspyHFSource::configure(std::string configurationStr) { return false; } - m_sampleRate = atoi(m["srate"].c_str()); - + int samplerate; + bool samplerate_ok = + Utility::parse_int(m["srate"].c_str(), samplerate, true); + m_sampleRate = static_cast(samplerate); sampleRateIndex = check_sampleRateIndex(m_sampleRate); - if (sampleRateIndex == -1) { + if (sampleRateIndex == -1 || !samplerate_ok) { m_error = "Invalid sample rate"; m_sampleRate = 0; return false; @@ -311,9 +313,12 @@ bool AirspyHFSource::configure(std::string configurationStr) { #ifdef DEBUG_AIRSPYHFSOURCE std::cerr << "AirspyHFSource::configure: freq: " << m["freq"] << std::endl; #endif - frequency = atoi(m["freq"].c_str()); - if (((frequency > 31000000) && (frequency < 60000000)) || + int freq; + bool freq_ok = Utility::parse_int(m["freq"].c_str(), freq, true); + frequency = static_cast(freq); + + if (!freq_ok || ((frequency > 31000000) && (frequency < 60000000)) || (frequency > 260000000)) { m_error = "Invalid frequency"; return false; @@ -325,9 +330,11 @@ bool AirspyHFSource::configure(std::string configurationStr) { std::cerr << "AirspyHFSource::configure: hf_att: " << m["hf_att"] << std::endl; #endif - hfAttLevel = atoi(m["hf_att"].c_str()); - if ((hfAttLevel > 8) || (hfAttLevel < 0)) { + int attlevel; + bool attlevel_ok = Utility::parse_int(m["hf_att"].c_str(), attlevel); + hfAttLevel = static_cast(attlevel); + if (!attlevel_ok || (hfAttLevel > 8) || (hfAttLevel < 0)) { m_error = "Invalid HF att level"; return false; } From 7bdb4065005c06666a73913a978055502cb49a0b Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 18:34:32 +0900 Subject: [PATCH 13/26] AirspyHFSource: initialize Utility::parse_int() result variables --- sfmbase/AirspyHFSource.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sfmbase/AirspyHFSource.cpp b/sfmbase/AirspyHFSource.cpp index bf1b1c9..df71357 100644 --- a/sfmbase/AirspyHFSource.cpp +++ b/sfmbase/AirspyHFSource.cpp @@ -297,7 +297,7 @@ bool AirspyHFSource::configure(std::string configurationStr) { return false; } - int samplerate; + int samplerate = 0; bool samplerate_ok = Utility::parse_int(m["srate"].c_str(), samplerate, true); m_sampleRate = static_cast(samplerate); @@ -314,7 +314,7 @@ bool AirspyHFSource::configure(std::string configurationStr) { std::cerr << "AirspyHFSource::configure: freq: " << m["freq"] << std::endl; #endif - int freq; + int freq = 0; bool freq_ok = Utility::parse_int(m["freq"].c_str(), freq, true); frequency = static_cast(freq); @@ -331,7 +331,7 @@ bool AirspyHFSource::configure(std::string configurationStr) { << std::endl; #endif - int attlevel; + int attlevel = 0; bool attlevel_ok = Utility::parse_int(m["hf_att"].c_str(), attlevel); hfAttLevel = static_cast(attlevel); if (!attlevel_ok || (hfAttLevel > 8) || (hfAttLevel < 0)) { From 8cd659ee82fd525621bebb77839b97746bb0517d Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 19:51:17 +0900 Subject: [PATCH 14/26] FileSource: use Utility::parse_int() instead of atoi() --- sfmbase/FileSource.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/sfmbase/FileSource.cpp b/sfmbase/FileSource.cpp index 9cec62b..757dc63 100644 --- a/sfmbase/FileSource.cpp +++ b/sfmbase/FileSource.cpp @@ -25,6 +25,7 @@ #include "ConfigParser.h" #include "FileSource.h" +#include "Utility.h" FileSource *FileSource::m_this = 0; @@ -73,20 +74,37 @@ bool FileSource::configure(std::string configurationStr) { // srate if (m.find("srate") != m.end()) { std::cerr << "FileSource::configure: srate: " << m["srate"] << std::endl; - sample_rate = atoi(m["srate"].c_str()); + int samplerate = 0; + bool samplerate_ok = + Utility::parse_int(m["srate"].c_str(), samplerate, true); + sample_rate = static_cast(samplerate); srate_specified = true; + if (!samplerate_ok) { + std::cerr << "FileSource::configure: invalid samplerate" << std::endl; + return false; + } } // freq if (m.find("freq") != m.end()) { std::cerr << "FileSource::configure: freq: " << m["freq"] << std::endl; - frequency = atoi(m["freq"].c_str()); + int freq = 0; + bool freq_ok = Utility::parse_int(m["freq"].c_str(), freq, true); + frequency = static_cast(freq); + if (!freq_ok) { + std::cerr << "FileSource::configure: invalid frequency" << std::endl; + return false; + } } // blklen if (m.find("blklen") != m.end()) { std::cerr << "FileSource::configure: blklen: " << m["blklen"] << std::endl; - block_length = atoi(m["blklen"].c_str()); + bool blklen_ok = Utility::parse_int(m["blklen"].c_str(), block_length); + if (!blklen_ok) { + std::cerr << "FileSource::configure: invalid blklen" << std::endl; + return false; + } } // zero_offset From 6dceb8e18d6253c8ef4135dfe1df6cdadbee8265 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 19:54:25 +0900 Subject: [PATCH 15/26] FileSource: show parsed integers during configuration --- sfmbase/FileSource.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sfmbase/FileSource.cpp b/sfmbase/FileSource.cpp index 757dc63..7c9587c 100644 --- a/sfmbase/FileSource.cpp +++ b/sfmbase/FileSource.cpp @@ -73,7 +73,6 @@ bool FileSource::configure(std::string configurationStr) { // srate if (m.find("srate") != m.end()) { - std::cerr << "FileSource::configure: srate: " << m["srate"] << std::endl; int samplerate = 0; bool samplerate_ok = Utility::parse_int(m["srate"].c_str(), samplerate, true); @@ -83,11 +82,11 @@ bool FileSource::configure(std::string configurationStr) { std::cerr << "FileSource::configure: invalid samplerate" << std::endl; return false; } + std::cerr << "FileSource::configure: srate: " << sample_rate << std::endl; } // freq if (m.find("freq") != m.end()) { - std::cerr << "FileSource::configure: freq: " << m["freq"] << std::endl; int freq = 0; bool freq_ok = Utility::parse_int(m["freq"].c_str(), freq, true); frequency = static_cast(freq); @@ -95,16 +94,17 @@ bool FileSource::configure(std::string configurationStr) { std::cerr << "FileSource::configure: invalid frequency" << std::endl; return false; } + std::cerr << "FileSource::configure: freq: " << frequency << std::endl; } // blklen if (m.find("blklen") != m.end()) { - std::cerr << "FileSource::configure: blklen: " << m["blklen"] << std::endl; bool blklen_ok = Utility::parse_int(m["blklen"].c_str(), block_length); if (!blklen_ok) { std::cerr << "FileSource::configure: invalid blklen" << std::endl; return false; } + std::cerr << "FileSource::configure: blklen: " << block_length << std::endl; } // zero_offset From 6a2d1b70f4f036c6d98191a610b435cfa7e8d2fc Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 20:03:37 +0900 Subject: [PATCH 16/26] main.cpp: check pull_end_reached() in the main loop --- main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/main.cpp b/main.cpp index f4e33a9..0518120 100644 --- a/main.cpp +++ b/main.cpp @@ -844,6 +844,12 @@ int main(int argc, char **argv) { /////////////////////////////////////// for (uint64_t block = 0; !stop_flag.load(); block++) { + // If the end has been reached at the source buffer, + // exit the main processing loop. + if (source_buffer.pull_end_reached()) { + break; + } + // Pull next block from source buffer. IQSampleVector iqsamples = source_buffer.pull(); From 48e7358481982fc508099a9944a6dafce813a4ae Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 20:05:29 +0900 Subject: [PATCH 17/26] fix: clang-format --- include/AirspyHFSource.h | 2 +- include/AirspySource.h | 2 +- sfmbase/FileSource.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/AirspyHFSource.h b/include/AirspyHFSource.h index cb7290e..8bcc0f8 100644 --- a/include/AirspyHFSource.h +++ b/include/AirspyHFSource.h @@ -23,8 +23,8 @@ #include "libairspyhf/airspyhf.h" #include #include -#include #include +#include #include "Source.h" diff --git a/include/AirspySource.h b/include/AirspySource.h index 2fb4494..6d378c4 100644 --- a/include/AirspySource.h +++ b/include/AirspySource.h @@ -23,8 +23,8 @@ #include "libairspy/airspy.h" #include #include -#include #include +#include #include "Source.h" diff --git a/sfmbase/FileSource.cpp b/sfmbase/FileSource.cpp index 7c9587c..bf6cced 100644 --- a/sfmbase/FileSource.cpp +++ b/sfmbase/FileSource.cpp @@ -94,7 +94,7 @@ bool FileSource::configure(std::string configurationStr) { std::cerr << "FileSource::configure: invalid frequency" << std::endl; return false; } - std::cerr << "FileSource::configure: freq: " << frequency << std::endl; + std::cerr << "FileSource::configure: freq: " << frequency << std::endl; } // blklen From 5d1794a8a97cf532dd6c4fa266fb2ed17e3c1033 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 20:18:59 +0900 Subject: [PATCH 18/26] AirspySource: use Utility::parse_int() instead of atoi() --- sfmbase/AirspySource.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/sfmbase/AirspySource.cpp b/sfmbase/AirspySource.cpp index a096421..ef42c24 100644 --- a/sfmbase/AirspySource.cpp +++ b/sfmbase/AirspySource.cpp @@ -330,17 +330,19 @@ bool AirspySource::configure(std::string configurationStr) { return false; } - m_sampleRate = atoi(m["srate"].c_str()); - uint32_t i; + int samplerate = 0; + bool samplerate_ok = + Utility::parse_int(m["srate"].c_str(), samplerate, true); + m_sampleRate = static_cast(samplerate); + uint32_t i; for (i = 0; i < m_srates.size(); i++) { if (m_srates[i] == static_cast(m_sampleRate)) { sampleRateIndex = i; break; } } - - if (i == m_srates.size()) { + if (i == m_srates.size() || !samplerate_ok) { m_error = "Invalid sample rate"; m_sampleRate = 0; return false; @@ -351,9 +353,11 @@ bool AirspySource::configure(std::string configurationStr) { #ifdef DEBUG_AIRSPYSOURCE std::cerr << "AirspySource::configure: freq: " << m["freq"] << std::endl; #endif - frequency = atoi(m["freq"].c_str()); + int freq = 0; + bool freq_ok = Utility::parse_int(m["freq"].c_str(), freq, true); + frequency = static_cast(freq); - if ((frequency < 24000000) || (frequency > 1800000000)) { + if (!freq_ok || (frequency < 24000000) || (frequency > 1800000000)) { m_error = "Invalid frequency"; return false; } @@ -368,9 +372,9 @@ bool AirspySource::configure(std::string configurationStr) { return false; } - lnaGain = atoi(m["lgain"].c_str()); - - if (find(m_lgains.begin(), m_lgains.end(), lnaGain) == m_lgains.end()) { + bool lgain_ok = Utility::parse_int(m["lgain"].c_str(), lnaGain); + if (!lgain_ok || + find(m_lgains.begin(), m_lgains.end(), lnaGain) == m_lgains.end()) { m_error = "LNA gain not supported. Available gains (dB): " + m_lgainsStr; return false; } @@ -385,9 +389,9 @@ bool AirspySource::configure(std::string configurationStr) { return false; } - mixGain = atoi(m["mgain"].c_str()); - - if (find(m_mgains.begin(), m_mgains.end(), mixGain) == m_mgains.end()) { + bool mgain_ok = Utility::parse_int(m["mgain"].c_str(), mixGain); + if (!mgain_ok || + find(m_mgains.begin(), m_mgains.end(), mixGain) == m_mgains.end()) { m_error = "Mixer gain not supported. Available gains (dB): " + m_mgainsStr; return false; @@ -398,14 +402,14 @@ bool AirspySource::configure(std::string configurationStr) { #ifdef DEBUG_AIRSPYSOURCE std::cerr << "AirspySource::configure: vgain: " << m["vgain"] << std::endl; #endif - vgaGain = atoi(m["vgain"].c_str()); - if (strcasecmp(m["vgain"].c_str(), "list") == 0) { m_error = "Available VGA gains (dB): " + m_vgainsStr; return false; } - if (find(m_vgains.begin(), m_vgains.end(), vgaGain) == m_vgains.end()) { + bool vgain_ok = Utility::parse_int(m["vgain"].c_str(), vgaGain); + if (!vgain_ok || + find(m_vgains.begin(), m_vgains.end(), vgaGain) == m_vgains.end()) { m_error = "VGA gain not supported. Available gains (dB): " + m_vgainsStr; return false; } From 18e063dbc364680d6538e1e830884f540f548281 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 20:46:24 +0900 Subject: [PATCH 19/26] RtlSdrSource: use Utility::parse_int() instead of atoi() --- sfmbase/RtlSdrSource.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/sfmbase/RtlSdrSource.cpp b/sfmbase/RtlSdrSource.cpp index 1added6..d740ef0 100644 --- a/sfmbase/RtlSdrSource.cpp +++ b/sfmbase/RtlSdrSource.cpp @@ -88,23 +88,26 @@ bool RtlSdrSource::configure(std::string configurationStr) { cp.parse_config_string(configurationStr, m); if (m.find("srate") != m.end()) { - std::cerr << "RtlSdrSource::configure: srate: " << m["srate"] << std::endl; - sample_rate = atoi(m["srate"].c_str()); - - if ((sample_rate < 900001) || (sample_rate > 3200000)) { + int samplerate = 0; + bool samplerate_ok = + Utility::parse_int(m["srate"].c_str(), samplerate, true); + sample_rate = static_cast(samplerate); + if (!samplerate_ok || (sample_rate < 900001) || (sample_rate > 3200000)) { m_error = "Invalid sample rate"; return false; } + std::cerr << "RtlSdrSource::configure: srate: " << sample_rate << std::endl; } if (m.find("freq") != m.end()) { - std::cerr << "RtlSdrSource::configure: freq: " << m["freq"] << std::endl; - frequency = atoi(m["freq"].c_str()); - - if ((frequency < 10000000) || (frequency > 2200000000)) { + int freq = 0; + bool freq_ok = Utility::parse_int(m["freq"].c_str(), freq, true); + frequency = static_cast(freq); + if (!freq_ok || (frequency < 10000000) || (frequency > 2200000000)) { m_error = "Invalid frequency"; return false; } + std::cerr << "RtlSdrSource::configure: freq: " << frequency << std::endl; } if (m.find("gain") != m.end()) { @@ -142,9 +145,13 @@ bool RtlSdrSource::configure(std::string configurationStr) { } // gain if (m.find("blklen") != m.end()) { - std::cerr << "RtlSdrSource::configure: blklen: " << m["blklen"] + bool blklen_ok = Utility::parse_int(m["blklen"].c_str(), block_length); + if (!blklen_ok) { + std::cerr << "RtlSdrSource::configure: invalid blklen" << std::endl; + return false; + } + std::cerr << "RtlSdrSource::configure: blklen: " << block_length << std::endl; - block_length = atoi(m["blklen"].c_str()); } if (m.find("agc") != m.end()) { From c41bf1e141d0400ee7b6d4f2822bec5d826221ae Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sat, 6 Jan 2024 21:04:29 +0900 Subject: [PATCH 20/26] AudioOutput.cpp: remove offensive and unused _FILE_OFFSET_BITS --- sfmbase/AudioOutput.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/sfmbase/AudioOutput.cpp b/sfmbase/AudioOutput.cpp index 93210d8..cbbd766 100644 --- a/sfmbase/AudioOutput.cpp +++ b/sfmbase/AudioOutput.cpp @@ -18,7 +18,6 @@ // along with this program. If not, see . #include "sndfile.h" -#define _FILE_OFFSET_BITS 64 #include #include From a43ed93c3773185630c0634a8283a055cf8bd0ed Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sun, 7 Jan 2024 00:18:03 +0900 Subject: [PATCH 21/26] main.cpp: set stop_flag when pull_end_reached() --- main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/main.cpp b/main.cpp index 0518120..81587db 100644 --- a/main.cpp +++ b/main.cpp @@ -847,6 +847,7 @@ int main(int argc, char **argv) { // If the end has been reached at the source buffer, // exit the main processing loop. if (source_buffer.pull_end_reached()) { + stop_flag.store(true); break; } From 7ce223b2878bb82b52b81fb37bab61bc13f89231 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sun, 7 Jan 2024 13:04:28 +0900 Subject: [PATCH 22/26] Set RtlSdrSource::default_block_length to 16384 --- include/RtlSdrSource.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/RtlSdrSource.h b/include/RtlSdrSource.h index df27abb..1e60773 100644 --- a/include/RtlSdrSource.h +++ b/include/RtlSdrSource.h @@ -27,7 +27,7 @@ class RtlSdrSource : public Source { public: - static constexpr int default_block_length = 65536; + static constexpr int default_block_length = 16384; /** Open RTL-SDR device. */ RtlSdrSource(int dev_index); From 30e16fbdf028b88fe0283af517b905a663d0930b Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sun, 7 Jan 2024 13:25:34 +0900 Subject: [PATCH 23/26] main.cpp: calculate main.cpp in practical way --- main.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/main.cpp b/main.cpp index 81587db..7c0c60b 100644 --- a/main.cpp +++ b/main.cpp @@ -649,13 +649,19 @@ int main(int argc, char **argv) { if_blocksize = 2048; break; case DevType::RTLSDR: - if_blocksize = 65536; + if_blocksize = 16384; break; case DevType::FileSource: if_blocksize = 2048; break; } + // Status refresh rate. + // TODO: ~0.1sec / display (should be tuned) + unsigned int stat_rate = + (unsigned int)((double)ifrate / (double)if_blocksize / 9.0); + fprintf(stderr, "stat_rate = %u\n", stat_rate); + // IF rate compensation if requested. if (ifrate_offset_enable) { ifrate *= 1.0 + (ifrate_offset_ppm / 1000000.0); @@ -831,10 +837,6 @@ int main(int argc, char **argv) { float audio_level = 0; double block_time = Utility::get_time(); - // TODO: ~0.1sec / display (should be tuned) - unsigned int stat_rate = - lrint(5120 / (if_blocksize / total_decimation_ratio)); - float if_level = 0; PilotState pilot_status = PilotState::NotDetected; From 1c347c42407696191736865bfcf4e6183570c9ba Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sun, 7 Jan 2024 14:07:11 +0900 Subject: [PATCH 24/26] Documentation change for 20240107-0 --- CHANGES.md | 21 +++++++++++++++++++++ README.md | 23 ++++++++++++++--------- main.cpp | 2 +- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0e381ca..272ce66 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,12 @@ The following submodule is required: * [r8brain-free-src](https://github.com/avaneev/r8brain-free-src) +## External version control code required + +The following Git repository is required: + +* [jj1bdx's fork of cmake-git-version-tracking](https://github.com/andrew-hardin/cmake-git-version-tracking) + ## Platforms tested * Mac mini 2023 Apple Silicon (M2 Pro), macOS 14.2.1, Xcode 15.1 Command Line Tools @@ -30,6 +36,21 @@ Intel Mac hardware is no longer supported by airspy-fmradion, although the autho ## Changes (including requirement changes) +* 20240107-0: Made the following changes: + - For broadcasting FM, show stereo 19kHz pilot signal level when detected. + - Remove displaying whether FM stereo pilot signal level is stable or unstable. + - Add Git info into the binary program built, with [cmake-git-version-tracking](https://github.com/andrew-hardin/cmake-git-version-tracking.git) (using jj1bdx's fork). + - Add compile command database support on CMakeLists.txt. + - Cleaned up old documents. + - Fixed the following bugs detected by clang-tidy: + * [ERR34-C. Detect errors when converting a string to a number](https://wiki.sei.cmu.edu/confluence/display/c/ERR34-C.+Detect+errors+when+converting+a+string+to+a+number) + - Use `Utility::parse_int()` instead of raw `atoi()` + * [DCL51-CPP. Do not declare or define a reserved identifier](https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL51-CPP.+Do+not+declare+or+define+a+reserved+identifier) + - Remove unused `_FILE_OFFSET_BITS` + - Fixed the bug of FileSource playback: the code did not terminate after the end of playback. + - main.cpp: add checking pull_end_reached() in the main loop. + - Set RtlSdrSource's default_block_length from 65536 to 16384, to prevent popping cracking sound (observed on Mac mini 2023). + - stat_rate calculation is redesigned by observation of actual SDR units (:i.e., Airspy HF+, Airspy R2, and RTL-SDR). * 20231227-0: Made the following changes: - Split class PilotPhaseLock from FmDecode. - Removed submodule readerwriterqueue. diff --git a/README.md b/README.md index 513f239..7b3bd2b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # airspy-fmradion -* Version 20231227-0 +* Version 20240107-0 * For macOS (Apple Silicon) and Linux ## Contributing @@ -55,11 +55,12 @@ airspy-fmradion -m am -t airspyhf -q \ - [r8brain-free-src](https://github.com/avaneev/r8brain-free-src), a sample rate converter designed by Aleksey Vaneev of Voxengo - [VOLK](https://www.libvolk.org/) - [PortAudio](http://www.portaudio.com) + - [jj1bdx's fork of cmake-git-version-tracking](https://github.com/andrew-hardin/cmake-git-version-tracking) - Tested: Airspy R2, Airspy Mini, Airspy HF+ Dual Port, RTL-SDR V3 - Fast computer - Medium-to-strong radio signals -For the latest version, see https://github.com/jj1bdx/airspy-fmradion +For the latest version, see ### Recommended utilities @@ -146,7 +147,7 @@ r8brain-free-src is the submodule of this repository. Download the submodule rep ```shell /bin/rm -rf build git submodule update --init --recursive -cmake -S . -B build # -DCMAKE_EXPORT_COMPILE_COMMANDS=ON (if needed) +cmake -S . -B build cmake --build build --target all ``` @@ -174,14 +175,20 @@ cmake .. \ PKG_CONFIG_PATH=/path/to/airspy/lib/pkgconfig cmake .. ``` -For using static analyzers such as [OCLint](https://oclint.org) and [Clangd](https://clangd.llvm.org), run the following commands: +### Static analysis of the code + +For using static analyzers such as [OCLint](https://oclint.org) and [Clangd](https://clangd.llvm.org), use the `compile_commands.json` file built in `build/` directory, with the following commands: ``` cd build ln -s `pwd`/compile_commands.json .. -cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. ``` +The following limitation is applicable: + +* For *CMake 3.20 or later*, cmake-git-version-tracking code is intentionally removed from the compile command database. This is not applicable for the older CMake. +* Use [compdb](https://github.com/Sarcasm/compdb.git) for a more precise analysis including all the header files, with the following command: `compdb -p build/ list > compile_commands.json` + ### Compile and install - `make -j4` (for machines with 4 CPUs) @@ -453,13 +460,11 @@ install -o user -m 0700 -c -s build/airspy-fmradion $(HOME)/bin * [Takeru Ohta](https://github.com/sile), for his [Rust implementation](https://github.com/sile/dagc) of [Tisserand-Berviller AGC algorithm](https://hal.univ-lorraine.fr/hal-01397371/document) * [Cameron Desrochers](https://github.com/cameron314), for his [readerwriterqueue](https://github.com/cameron314/readerwriterqueue) implementation of a single-producer-single-consumer lock-free queue for C++ * [Clayton Smith](https://github.com/argilo), for [a bugfix pull request to airspy-fmradion to find an uninitialized variable](https://github.com/jj1bdx/airspy-fmradion/pull/43) and his help during [bug tracking in VOLK](https://github.com/gnuradio/volk/pull/695). +* [Andrew Hardin](https://github.com/andrew-hardin), for [cmake-git-version-tracking](https://github.com/andrew-hardin/cmake-git-version-tracking.git) ## License * As a whole package: GPLv3 (and later). See [LICENSE](LICENSE). * [csdr](https://github.com/simonyiszk/csdr) AGC code: BSD license. -* Some source code files are stating GPL "v2 and later" license. - -## Repository history +* Some source code files are stating GPL "v2 and later" license, and the MIT License. -* This repository is forked from [ngsoftfm-jj1bdx](https://github.com/jj1bdx/ngsoftfm-jj1bdx) 0.1.14 and merged with [airspfhf-fmradion](https://github.com/jj1bdx/airspyhf-fmradion). diff --git a/main.cpp b/main.cpp index 7c0c60b..4c3f6d8 100644 --- a/main.cpp +++ b/main.cpp @@ -48,7 +48,7 @@ // define this for enabling coefficient monitor functions // #undef COEFF_MONITOR -#define AIRSPY_FMRADION_VERSION "20231227-0" +#define AIRSPY_FMRADION_VERSION "20240107-0" // Flag to set graceful termination // in process_signals() From 01e968387718b602d723a22b8fde5b83a6fa9f82 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sun, 7 Jan 2024 14:08:50 +0900 Subject: [PATCH 25/26] CHANGES.md: fix cmake-git-version-tracking URL --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 272ce66..7520939 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,7 +12,7 @@ The following submodule is required: The following Git repository is required: -* [jj1bdx's fork of cmake-git-version-tracking](https://github.com/andrew-hardin/cmake-git-version-tracking) +* [jj1bdx's fork of cmake-git-version-tracking](https://github.com/jj1bdx/cmake-git-version-tracking) ## Platforms tested From 7c83f751c1bb670724d6fe72f120acd68a9462d1 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Sun, 7 Jan 2024 14:11:46 +0900 Subject: [PATCH 26/26] README.md: fix on URL and obsolete master branch --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 7b3bd2b..93a1a14 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ airspy-fmradion -m am -t airspyhf -q \ - [r8brain-free-src](https://github.com/avaneev/r8brain-free-src), a sample rate converter designed by Aleksey Vaneev of Voxengo - [VOLK](https://www.libvolk.org/) - [PortAudio](http://www.portaudio.com) - - [jj1bdx's fork of cmake-git-version-tracking](https://github.com/andrew-hardin/cmake-git-version-tracking) + - [jj1bdx's fork of cmake-git-version-tracking](https://github.com/jj1bdx/cmake-git-version-tracking) - Tested: Airspy R2, Airspy Mini, Airspy HF+ Dual Port, RTL-SDR V3 - Fast computer - Medium-to-strong radio signals @@ -72,7 +72,6 @@ For the latest version, see - _main_ is the "production" branch with the most stable release (often ahead of the latest release though) - _dev_ is the development branch that contains current developments that will be eventually released in the main branch - Other branches are experimental (and presumably abandoned) - - The `master` branch is deprecated and to be deleted. Use _main_ branch. ## Prerequisites