From dad1a8b80644bc848a97175491482b14d64587a7 Mon Sep 17 00:00:00 2001 From: charlie-foxtrot <13514783+charlie-foxtrot@users.noreply.github.com> Date: Sun, 21 Jan 2024 08:31:28 -0800 Subject: [PATCH] build and publish docker containers (#444) * build and publish docker containers * changes to supported `cmake` platforms: * depreciate `rpiv1`, `armv7-generic`, and `armv8-generic` and build platforms * change default build platform to `native` * rename `default` to `generic` * enable a series of compile warnings and cleanup code * remove `SSE` specific code - let the compiler "do the right thing" * remove some no longer supported windows `ifdef`'s * fix CTCSS bug that could miss a tone when multiple tones have the same power (happens with less accurate floating point operations, ie i386) --- .devcontainer/devcontainer.json | 2 +- .github/workflows/build.yml | 5 +- .github/workflows/build_containers.yml | 51 +++++++++ CMakeLists.txt | 4 +- Dockerfile | 100 +++++++++++++++++ src/CMakeLists.txt | 32 +++--- src/config.cpp | 20 ++-- src/config.h.in | 2 +- src/ctcss.cpp | 18 +++- src/input-common.cpp | 3 - src/input-common.h | 14 +-- src/input-helpers.cpp | 5 - src/input-rtlsdr.cpp | 7 +- src/input-soapysdr.cpp | 2 +- src/logging.cpp | 4 +- src/logging.h | 2 +- src/mixer.cpp | 5 +- src/output.cpp | 24 +++-- src/pulse.cpp | 2 +- src/rtl_airband.cpp | 143 ++++++++++--------------- src/rtl_airband.h | 35 +++--- src/rtl_airband_vfp.s | 91 ---------------- src/squelch.cpp | 21 ++-- src/squelch.h | 8 +- src/test_generate_signal.cpp | 4 +- 25 files changed, 317 insertions(+), 287 deletions(-) create mode 100644 .github/workflows/build_containers.yml create mode 100644 Dockerfile delete mode 100644 src/rtl_airband_vfp.s diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 75110e4..580cc00 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -22,7 +22,7 @@ "twxs.cmake", "streetsidesoftware.code-spell-checker", "ms-azuretools.vscode-docker", - "GitHub.vscode-github-actions" + "GitHub.vscode-github-actions" ] } }, diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58313c8..415ecb1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,7 @@ name: Test build on: push: branches: [main, unstable] + tags: ['v*'] pull_request: schedule: - cron: '39 13 * * *' # run daily @@ -18,8 +19,8 @@ jobs: - name: Runner Info run: printenv | sort - - name: Checkout repository - uses: actions/checkout@main + - name: Checkout + uses: actions/checkout@v4 - name: Install packaged dependencies run: .github/install_dependencies diff --git a/.github/workflows/build_containers.yml b/.github/workflows/build_containers.yml new file mode 100644 index 0000000..ecde7f2 --- /dev/null +++ b/.github/workflows/build_containers.yml @@ -0,0 +1,51 @@ +name: Build and Publish Containers + +on: + push: + branches: [main, unstable] + tags: ['v*'] + pull_request: + workflow_dispatch: + schedule: + - cron: '29 13 * * *' # run daily + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Runner Info + run: printenv | sort + + - name: Checkout + uses: actions/checkout@v4 + + - name: Container metadata + id: metadata + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + + # Add support for more platforms with QEMU - https://github.com/docker/setup-qemu-action + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + platforms: linux/amd64, linux/386, linux/arm64, linux/arm/v6, linux/arm/v7 + cache-from: type=gha + cache-to: type=gha,mode=max + push: true + tags: ${{ steps.metadata.outputs.tags }} + labels: ${{ steps.metadata.outputs.labels }} + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 80bf697..f4d3104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,9 @@ if(NOT CMAKE_BUILD_TYPE) message(STATUS "Build type not specified: defaulting to Release") endif(NOT CMAKE_BUILD_TYPE) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") +# TODO: flags to add: -Wfloat-equal -Wconversion -Wstrict-overflow=5 -Waggregate-return -Wpedantic -Wcast-align +# TODO: these could be added except for gtest: -Wswitch-enum -Wundef -Wswitch-default +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -Wdate-time -Wpointer-arith -Wwrite-strings -Wcast-qual -Wunreachable-code -Werror") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -DDEBUG") if(DEBUG_SQUELCH) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bd71d6e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,100 @@ +# build container +FROM debian:bookworm-slim AS build + +# set working dir +WORKDIR /app + +# install build dependencies +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + libmp3lame-dev \ + libshout3-dev \ + libconfig++-dev \ + libfftw3-dev \ + libsoapysdr-dev \ + libpulse-dev \ + \ + git \ + ca-certificates \ + libusb-1.0-0-dev \ + debhelper \ + pkg-config \ + && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# compile / install rtl-sdr-blog version of rtl-sdr for v4 support +RUN git clone https://github.com/rtlsdrblog/rtl-sdr-blog && \ + cd rtl-sdr-blog/ && \ + dpkg-buildpackage -b --no-sign && \ + cd .. && \ + dpkg -i librtlsdr0_*.deb && \ + dpkg -i librtlsdr-dev_*.deb && \ + dpkg -i rtl-sdr_*.deb + + +# TODO: build anything from source? + +# copy in the rtl_airband source +COPY CMakeLists.txt src /app/ + +# configure and build +# TODO: detect platforms +RUN uname -m && \ + echo | gcc -### -v -E - | tee /app/compiler_native_info.txt && \ + cmake -B build_dir -DPLATFORM=generic -DCMAKE_BUILD_TYPE=Release -DNFM=TRUE -DBUILD_UNITTESTS=TRUE && \ + VERBOSE=1 cmake --build build_dir -j4 + +# make sure unit tests pass +RUN ./build_dir/unittests + + +# application container +FROM debian:bookworm-slim + +# set working dir +WORKDIR /app + +# install runtime dependencies +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y --no-install-recommends \ + tini \ + libc6 \ + libmp3lame0 \ + libshout3 \ + libconfig++9v5 \ + libfftw3-single3 \ + libsoapysdr0.8 \ + libpulse0 \ + libusb-1.0-0-dev \ + && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# install (from build container) rtl-sdr-blog version of rtl-sdr for v4 support +COPY --from=build /app/librtlsdr0_*.deb /app/librtlsdr-dev_*.deb /app/rtl-sdr_*.deb ./ +RUN dpkg -i librtlsdr0_*.deb && \ + dpkg -i librtlsdr-dev_*.deb && \ + dpkg -i rtl-sdr_*.deb && \ + rm -rf *.deb && \ + echo '' | tee --append /etc/modprobe.d/rtl_sdr.conf && \ + echo 'blacklist dvb_usb_rtl28xxun' | tee --append /etc/modprobe.d/rtl_sdr.conf && \ + echo 'blacklist rtl2832' | tee --append /etc/modprobe.d/rtl_sdr.conf && \ + echo 'blacklist rtl2830' | tee --append /etc/modprobe.d/rtl_sdr.conf + +# Copy rtl_airband from the build container +COPY LICENSE /opt/rtl_airband/ +COPY --from=build /app/build_dir/unittests /opt/rtl_airband/ +COPY --from=build /app/build_dir/rtl_airband /opt/rtl_airband/ +RUN chmod a+x /opt/rtl_airband/unittests /opt/rtl_airband/rtl_airband + +# make sure unit tests pass +RUN /opt/rtl_airband/unittests + +# Use tini as init and run rtl_airband +ENTRYPOINT ["/usr/bin/tini", "--"] +CMD ["/opt/rtl_airband/rtl_airband", "-F", "-e"] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 55aa3e5..4155a26 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -113,7 +113,7 @@ set(CMAKE_REQUIRED_LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS_SAVE}) option(NFM "Enable support for narrow FM channels" OFF) -set(PLATFORM "default" CACHE STRING "Optimize the build for the given hardware platform") +set(PLATFORM "native" CACHE STRING "Optimize the build for the given hardware platform") option(RTLSDR "Enable RTL-SDR support" ON) set(WITH_RTLSDR FALSE) @@ -192,20 +192,17 @@ endif() option(BCM_VC "Enable Broadcom Videocore 3 support" OFF) set(WITH_BCM_VC FALSE) -if(PLATFORM STREQUAL "rpiv1") - set(BCM_VC ON) - add_compile_options(-march=armv6zk -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfpu=vfp) - enable_language(ASM) - list(APPEND rtl_airband_extra_sources rtl_airband_vfp.s) +# error out on depricated PLATFORM values +if(PLATFORM STREQUAL "rpiv1" OR PLATFORM STREQUAL "armv7-generic" OR PLATFORM STREQUAL "armv8-generic") + message(FATAL_ERROR "platform '${PLATFORM}' has been deprecated, see https://github.com/charlie-foxtrot/RTLSDR-Airband/discussions/447") +# rpiv2 - Raspberry Pi 2 or Raspberry Pi 3 using Broadcom VideoCore IV GPU for FFT +# NOTE: use 'native' to not use the GPU for FFT elseif(PLATFORM STREQUAL "rpiv2") set(BCM_VC ON) add_compile_options(-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard) enable_language(ASM) list(APPEND rtl_airband_extra_sources rtl_airband_neon.s) -elseif(PLATFORM STREQUAL "armv7-generic") - add_compile_options(-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard) -elseif(PLATFORM STREQUAL "armv8-generic") - add_compile_options(-march=armv8-a+crc -mtune=cortex-a53) +# native - let the complier optimize to run on local hardware (default) elseif(PLATFORM STREQUAL "native") CHECK_CXX_COMPILER_FLAG(-march=native CXX_HAS_MARCH_NATIVE) if(CXX_HAS_MARCH_NATIVE) @@ -213,17 +210,12 @@ elseif(PLATFORM STREQUAL "native") else() message(FATAL_ERROR "Cannot build with PLATFORM=native: the compiler does not support -march=native option") endif() - CHECK_CXX_COMPILER_FLAG(-mtune=native CXX_HAS_MTUNE_NATIVE) - if(CXX_HAS_MTUNE_NATIVE) - add_compile_options(-mtune=native) - else() - message(FATAL_ERROR "Cannot build with PLATFORM=native: the compiler does not support -mtune=native option") - endif() -elseif(PLATFORM STREQUAL "default") - # NOOP +# generic - dont add any hardware related flags, used to build a "portable" binary +elseif(PLATFORM STREQUAL "generic") + # NO-OP +# error out on unrecongnnized PLATFORM value else() - message(FATAL_ERROR "Unknown platform '${PLATFORM}'. Valid options are: - rpiv1, rpiv2, armv7-generic, armv8-generic, native, default") + message(FATAL_ERROR "Unknown platform '${PLATFORM}'. Valid options are: rpiv2, native, and generic") endif() # Try using VC GPU if enabled. Fallback to fftw3f if disabled or if VC lib not found diff --git a/src/config.cpp b/src/config.cpp index a7e6a09..7e451c1 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -90,7 +90,7 @@ static int parse_outputs(libconfig::Setting &outs, channel_t *channel, int i, in } else { idata->tls_mode = SHOUT_TLS_DISABLED; } -#endif // LIBSHOUT_HAS_TLS +#endif /* LIBSHOUT_HAS_TLS */ channel->need_mp3 = 1; } else if(!strncmp(outs[o]["type"], "file", 4)) { channel->outputs[oo].data = XCALLOC(1, sizeof(struct file_data)); @@ -255,7 +255,7 @@ static int parse_outputs(libconfig::Setting &outs, channel_t *channel, int i, in snprintf(buf, sizeof(buf), "%.3f MHz", (float)channel->freqlist[0].frequency / 1000000.0f); pdata->stream_name = strdup(buf); } -#endif +#endif /* WITH_PULSEAUDIO */ } else { if(parsing_mixers) { cerr << "Configuration error: mixers.["<pj = 0; channel->prev_waveout = 0.5; channel->alpha = dev->alpha; -#endif +#endif /* NFM */ // Make sure lowpass / highpass aren't flipped. // If lowpass is enabled (greater than zero) it must be larger than highpass @@ -357,7 +357,7 @@ static int parse_channels(libconfig::Setting &chans, device_t *dev, int i) { if(strncmp(chans[j]["modulation"], "nfm", 3) == 0) { channel_modulation = MOD_NFM; } else -#endif +#endif /* NFM */ if(strncmp(chans[j]["modulation"], "am", 2) != 0) { cerr<<"Configuration error: devices.["<freqlist[f].modulation = MOD_NFM; } else -#endif +#endif /* NFM */ if(strncmp(chans[j]["modulations"][f], "am", 2) == 0) { channel->freqlist[f].modulation = MOD_AM; } else { @@ -668,7 +668,7 @@ static int parse_channels(libconfig::Setting &chans, device_t *dev, int i) { if(chans[j].exists("tau")) { channel->alpha = ((int)chans[j]["tau"] == 0 ? 0.0f : exp(-1.0f/(WAVE_RATE * 1e-6 * (int)chans[j]["tau"]))); } -#endif +#endif /* NFM */ libconfig::Setting &outputs = chans[j]["outputs"]; channel->output_count = outputs.getLength(); if(channel->output_count < 1) { @@ -697,7 +697,7 @@ static int parse_channels(libconfig::Setting &chans, device_t *dev, int i) { break; } } -#endif +#endif /* NFM */ if(channel->needs_raw_iq) { // Downmixing is done only for NFM and raw IQ outputs. It's not critical to have some residual @@ -743,7 +743,7 @@ static int parse_channels(libconfig::Setting &chans, device_t *dev, int i) { snprintf(tmp_filepath, sizeof(tmp_filepath), "./squelch_debug-%d-%d.dat", j, f); channel->freqlist[f].squelch.set_debug_file(tmp_filepath); } -#endif +#endif /* DEBUG_SQUELCH */ jj++; } @@ -768,7 +768,7 @@ int parse_devices(libconfig::Setting &devs) { #else cerr<<"Configuration error: devices.["<input != NULL); if(devs[i].exists("sample_rate")) { @@ -800,7 +800,7 @@ int parse_devices(libconfig::Setting &devs) { } else { dev->alpha = alpha; } -#endif +#endif /* NFM */ // Parse hardware-dependent configuration parameters if(input_parse_config(dev->input, devs[i]) < 0) { diff --git a/src/config.h.in b/src/config.h.in index d2db773..088c393 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -33,4 +33,4 @@ #define SHOUT_SET_METADATA @SHOUT_SET_METADATA@ -#endif // !_CONFIG_H +#endif /* _CONFIG_H */ diff --git a/src/ctcss.cpp b/src/ctcss.cpp index dce20db..dee5e57 100644 --- a/src/ctcss.cpp +++ b/src/ctcss.cpp @@ -146,17 +146,25 @@ void CTCSS::process_audio_sample(const float &sample) { enough_samples_ = true; - // if this is sample fills out the window then check if the strongest tone is - // the CTCSS tone we are looking for + // if this is sample fills out the window then check if one of the "strongest" + // tones is the CTCSS tone we are looking for. NOTE: there can be multiple "strongest" + // tones based on floating point math vector tone_powers; float avg_power = powers_.sorted_powers(tone_powers); - if (tone_powers[0].freq == ctcss_freq_ && tone_powers[0].power > avg_power) { + float ctcss_tone_power = 0.0; + for( const auto i:tone_powers) { + if (i.freq == ctcss_freq_) { + ctcss_tone_power = i.power; + break; + } + } + if (ctcss_tone_power == tone_powers[0].power && ctcss_tone_power > avg_power) { debug_print("CTCSS tone of %f Hz detected\n", ctcss_freq_); has_tone_ = true; found_count_++; } else { - debug_print("CTCSS tone of %f Hz not detected - highest power was %f Hz at %f\n", - ctcss_freq_, tone_powers[0].freq, tone_powers[0].power); + debug_print("CTCSS tone of %f Hz not detected - highest power was %f Hz at %f vs %f\n", + ctcss_freq_, tone_powers[0].freq, tone_powers[0].power, ctcss_tone_power); has_tone_ = false; not_found_count_++; } diff --git a/src/input-common.cpp b/src/input-common.cpp index c13fbe7..157fc3b 100644 --- a/src/input-common.cpp +++ b/src/input-common.cpp @@ -18,9 +18,6 @@ * along with this program. If not, see . */ -#ifdef __MINGW32__ -#define _GNU_SOURCE 1 // asprintf -#endif #include #include diff --git a/src/input-common.h b/src/input-common.h index bf294ec..18bc55b 100644 --- a/src/input-common.h +++ b/src/input-common.h @@ -22,15 +22,11 @@ #include #include -#ifdef __MINGW32__ - #define MODULE_EXPORT extern "C" __declspec(dllexport) +#if __GNUC__ >= 4 +#define MODULE_EXPORT extern "C" __attribute__((visibility("default"))) #else - #if __GNUC__ >= 4 - #define MODULE_EXPORT extern "C" __attribute__((visibility("default"))) - #else - #define MODULE_EXPORT extern "C" - #endif -#endif +#define MODULE_EXPORT extern "C" +#endif /* __GNUC__ */ typedef enum { SFMT_UNDEF = 0, @@ -80,4 +76,4 @@ int input_start(input_t * const input); int input_set_centerfreq(input_t * const input, int const centerfreq); int input_stop(input_t * const input); -#endif // _INPUT_COMMON_H +#endif /* _INPUT_COMMON_H */ diff --git a/src/input-helpers.cpp b/src/input-helpers.cpp index 8ce4e5f..0b0757e 100644 --- a/src/input-helpers.cpp +++ b/src/input-helpers.cpp @@ -18,11 +18,6 @@ * along with this program. If not, see . */ -// avoid "unknown conversion type character `z' in format" -#ifdef __MINGW32__ -#define __USE_MINGW_ANSI_STDIO 1 -#endif - #include // cerr #include // memcpy #include // pthread_mutex_lock, unlock diff --git a/src/input-rtlsdr.cpp b/src/input-rtlsdr.cpp index 5619a4e..7a926b2 100644 --- a/src/input-rtlsdr.cpp +++ b/src/input-rtlsdr.cpp @@ -69,13 +69,12 @@ static bool rtlsdr_nearest_gain(rtlsdr_dev_t *dev, int target_gain, int *nearest } static int rtlsdr_find_device_by_serial(char const * const s) { - int device_count; char vendor[256] = {0}, product[256] = {0}, serial[256] = {0}; - device_count = rtlsdr_get_device_count(); - if(device_count < 1) { + int count = rtlsdr_get_device_count(); + if(count < 1) { return -1; } - for(int i = 0; i < device_count; i++) { + for(int i = 0; i < count; i++) { rtlsdr_get_device_usb_strings(i, vendor, product, serial); if (strcmp(s, serial) != 0) { continue; diff --git a/src/input-soapysdr.cpp b/src/input-soapysdr.cpp index ab5a33e..53c1731 100644 --- a/src/input-soapysdr.cpp +++ b/src/input-soapysdr.cpp @@ -314,7 +314,7 @@ void *soapysdr_rx_thread(void *ctx) { #else if((rxStream = SoapySDRDevice_setupStream(sdr, SOAPY_SDR_RX, dev_data->sample_format, &dev_data->channel, 1, NULL)) == NULL) { -#endif +#endif /* SOAPY_SDR_API_VERSION */ log(LOG_ERR, "Failed to set up stream for SoapySDR device '%s': %s\n", dev_data->device_string, SoapySDRDevice_lastError()); input->state = INPUT_FAILED; diff --git a/src/logging.cpp b/src/logging.cpp index 1751973..89f63b7 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -43,14 +43,14 @@ void init_debug (const char *file) { } #else UNUSED(file); -#endif +#endif /* DEBUG */ } void close_debug() { #ifdef DEBUG if(!debugf) return; fclose(debugf); -#endif +#endif /* DEBUG */ } void log(int priority, const char *format, ...) { diff --git a/src/logging.h b/src/logging.h index 5d7b7e7..0bf5feb 100644 --- a/src/logging.h +++ b/src/logging.h @@ -36,7 +36,7 @@ #else #define debug_print(fmt, ...) nop() #define debug_bulk_print(fmt, ...) nop() -#endif +#endif /* DEBUG */ enum LogDestination { SYSLOG, STDERR, NONE}; extern LogDestination log_destination; diff --git a/src/mixer.cpp b/src/mixer.cpp index fd5e1c2..2266ec1 100644 --- a/src/mixer.cpp +++ b/src/mixer.cpp @@ -165,7 +165,7 @@ void *mixer_thread(void *param) { #ifdef DEBUG struct timeval ts, te; gettimeofday(&ts, NULL); -#endif +#endif /* DEBUG */ while(!do_exit) { usleep(interval_usec); if(do_exit) return 0; @@ -242,7 +242,8 @@ void *mixer_thread(void *param) { ts.tv_sec = te.tv_sec; ts.tv_usec = te.tv_usec; -#endif +#endif /* DEBUG */ + channel->state = CH_READY; signal->send(); mixer->interval = MIX_DIVISOR; diff --git a/src/output.cpp b/src/output.cpp index 198e9d9..31d9134 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -28,15 +28,19 @@ #include #include #include + // SHOUTERR_RETRY is available since libshout 2.4.0. // Set it to an impossible value if it's not there. #ifndef SHOUTERR_RETRY #define SHOUTERR_RETRY (-255) -#endif +#endif /* SHOUTERR_RETRY */ + #include + #ifdef WITH_PULSEAUDIO #include -#endif +#endif /* WITH_PULSEAUDIO */ + #include #include #include @@ -69,7 +73,7 @@ void shout_setup(icecast_data *icecast, mix_modes mixmode) { if (shout_set_tls(shouttemp, icecast->tls_mode) != SHOUTERR_SUCCESS) { shout_free(shouttemp); return; } -#endif +#endif /* LIBSHOUT_HAS_TLS */ char mp[100]; sprintf(mp, "/%s", icecast->mountpoint); if (shout_set_mount(shouttemp, mp) != SHOUTERR_SUCCESS) { @@ -85,7 +89,7 @@ void shout_setup(icecast_data *icecast, mix_modes mixmode) { if (shout_set_content_format(shouttemp, SHOUT_FORMAT_MP3, SHOUT_USAGE_AUDIO, NULL) != SHOUTERR_SUCCESS){ #else if (shout_set_format(shouttemp, SHOUT_FORMAT_MP3) != SHOUTERR_SUCCESS){ -#endif +#endif /* LIBSHOUT_HAS_CONTENT_FORMAT */ shout_free(shouttemp); return; } if(icecast->name && shout_set_meta(shouttemp, SHOUT_META_NAME, icecast->name) != SHOUTERR_SUCCESS) { @@ -559,7 +563,7 @@ void process_outputs(channel_t *channel, int cur_scan_freq) { continue; pulse_write_stream(pdata, channel->mode, channel->waveout, channel->waveout_r, (size_t)WAVE_BATCH * sizeof(float)); -#endif +#endif /* WITH_PULSEAUDIO */ } } } @@ -589,7 +593,7 @@ void disable_channel_outputs(channel_t *channel) { } else if(output->type == O_PULSE) { pulse_data *pdata = (pulse_data *)(output->data); pulse_shutdown(pdata); -#endif +#endif /* WITH_PULSEAUDIO */ } } } @@ -874,7 +878,7 @@ void* output_thread(void *param) { #ifdef DEBUG timeval ts, te; gettimeofday(&ts, NULL); -#endif +#endif /* DEBUG */ while (!do_exit) { output_param->mp3_signal->wait(); for (int i = output_param->mixer_start; i < output_param->mixer_end; i++) { @@ -890,7 +894,7 @@ void* output_thread(void *param) { debug_bulk_print("mixeroutput: %lu.%lu %lu\n", te.tv_sec, (unsigned long) te.tv_usec, (te.tv_sec - ts.tv_sec) * 1000000UL + te.tv_usec - ts.tv_usec); ts.tv_sec = te.tv_sec; ts.tv_usec = te.tv_usec; -#endif +#endif /* DEBUG */ for (int i = output_param->device_start; i < output_param->device_end; i++) { device_t* dev = devices + i; if (dev->input->state == INPUT_RUNNING && dev->waveavail) { @@ -966,7 +970,7 @@ void* output_check_thread(void*) { pulse_setup(pdata, dev->channels[j].mode); } } -#endif +#endif /* WITH_PULSEAUDIO */ } } } @@ -989,7 +993,7 @@ void* output_check_thread(void*) { if (pdata->context == NULL){ pulse_setup(pdata, mixers[i].channel.mode); } -#endif +#endif /* WITH_PULSEAUDIO */ } } } diff --git a/src/pulse.cpp b/src/pulse.cpp index 800c163..69d7226 100644 --- a/src/pulse.cpp +++ b/src/pulse.cpp @@ -128,7 +128,7 @@ static void pulse_setup_streams(pulse_data *pdata) { .channels = 1 #else // for g++ 4.6 (eg. Raspbian Wheezy) PA_SAMPLE_FLOAT32LE, WAVE_RATE, 1 -#endif +#endif /* __cplusplus */ }; pa_channel_map_init_mono(&pdata->lmap); pdata->lmap.map[0] = (pdata->mode == MM_STEREO ? PA_CHANNEL_POSITION_LEFT : PA_CHANNEL_POSITION_MONO); diff --git a/src/rtl_airband.cpp b/src/rtl_airband.cpp index 213e240..9c06a52 100644 --- a/src/rtl_airband.cpp +++ b/src/rtl_airband.cpp @@ -26,16 +26,10 @@ // From this point we may safely assume that WITH_BCM_VC implies __arm__ -#if defined (__arm__) || defined (__aarch64__) - #ifdef WITH_BCM_VC #include "hello_fft/mailbox.h" #include "hello_fft/gpu_fft.h" -#endif - -#else /* x86 */ -#include -#endif /* x86 */ +#endif /* WITH_BCM_VC */ #include #include @@ -44,13 +38,7 @@ #include #include #include - -#ifndef __MINGW32__ #include -#else -#include -#endif - #include #include #include @@ -75,7 +63,7 @@ #ifdef WITH_PROFILING #include "gperftools/profiler.h" -#endif +#endif /* WITH_PROFILING */ using namespace std; using namespace libconfig; @@ -94,6 +82,7 @@ bool log_scan_activity = false; char *stats_filepath = NULL; size_t fft_size_log = DEFAULT_FFT_SIZE_LOG; size_t fft_size = 1 << fft_size_log; + #ifdef NFM float alpha = exp(-1.0f/(WAVE_RATE * 2e-4)); enum fm_demod_algo { @@ -101,27 +90,16 @@ enum fm_demod_algo { FM_QUADRI_DEMOD }; enum fm_demod_algo fm_demod = FM_FAST_ATAN2; -#endif +#endif /* NFM */ #ifdef DEBUG char *debug_path; -#endif +#endif /* DEBUG */ -#ifndef __MINGW32__ void sighandler(int sig) { log(LOG_NOTICE, "Got signal %d, exiting\n", sig); do_exit = 1; } -#else -BOOL WINAPI sighandler(int signum) { - if (CTRL_C_EVENT == signum) { - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - return TRUE; - } - return FALSE; -} -#endif void* controller_thread(void* params) { @@ -202,7 +180,7 @@ float fm_quadri_demod(float ar, float aj, float br, float bj) { return (float)((br*aj - ar*bj)/(ar*ar + aj*aj + 1.0f) * M_1_PI); } -#endif +#endif /* NFM */ class AFC { @@ -218,7 +196,8 @@ class AFC { return fft_results[index][0] * fft_results[index][0] + fft_results[index][1] * fft_results[index][1]; } -#endif +#endif /* WITH_BCM_VC */ + template size_t check(const FFT_RESULTS* fft_results, const size_t base, const float base_value, unsigned char afc) { @@ -271,7 +250,7 @@ class AFC if (dev->bins[index] != bin) { #ifdef AFC_LOGGING log(LOG_INFO, "AFC device=%d channel=%d: base=%zu prev=%zu now=%zu\n", dev->device, index, base, dev->bins[index], bin); -#endif +#endif /* AFC_LOGGING */ dev->bins[index] = bin; if ( bin > base ) channel->axcindicate = AFC_UP; @@ -296,7 +275,7 @@ void init_demod(demod_params_t *params, Signal *signal, int device_start, int de params->fftin = fftwf_alloc_complex(fft_size); params->fftout = fftwf_alloc_complex(fft_size); params->fft = fftwf_plan_dft_1d(fft_size, params->fftin, params->fftout, FFTW_FORWARD, FFTW_MEASURE); -#endif +#endif /* WITH_BCM_VC */ } void init_output(output_params_t *params, int device_start, int device_end, int mixer_start, int mixer_end) { @@ -345,7 +324,8 @@ void *demodulate(void *params) { #else fftwf_complex* fftin = demod_params->fftin; fftwf_complex* fftout = demod_params->fftout; -#endif +#endif /* WITH_BCM_VC */ + float ALIGNED32 levels_u8[256], levels_s8[256]; float *levels_ptr = NULL; @@ -363,7 +343,8 @@ void *demodulate(void *params) { float ALIGNED32 window[fft_size * 2]; #else float ALIGNED32 window[fft_size]; -#endif +#endif /* WITH_BCM_VC */ + const double a0 = 0.27105140069342f; const double a1 = 0.43329793923448f; const double a2 = 0.21812299954311f; const double a3 = 0.06592544638803f; const double a4 = 0.01081174209837f; @@ -380,13 +361,13 @@ void *demodulate(void *params) { window[i * 2] = window[i * 2 + 1] = (float)x; #else window[i] = (float)x; -#endif +#endif /* WITH_BCM_VC */ } #ifdef DEBUG struct timeval ts, te; gettimeofday(&ts, NULL); -#endif +#endif /* DEBUG */ size_t available; int device_num = demod_params->device_start; while (true) { @@ -395,7 +376,7 @@ void *demodulate(void *params) { #ifdef WITH_BCM_VC log(LOG_INFO, "Freeing GPU memory\n"); gpu_fft_release(fft); -#endif +#endif /* WITH_BCM_VC */ return NULL; } @@ -450,7 +431,7 @@ void *demodulate(void *params) { fftin[i][0] = scale * (float)buf2[0] * window[i]; fftin[i][1] = scale * (float)buf2[1] * window[i]; } -#endif +#endif /* WITH_BCM_VC */ } else if(dev->input->sfmt == SFMT_F32) { float const scale = 1.0f / dev->input->fullscale; #ifdef WITH_BCM_VC @@ -462,42 +443,37 @@ void *demodulate(void *params) { ptr[i].im = scale * buf2[1] * window[i*2]; } } -#else +#else // WITH_BCM_VC float *buf2 = (float *)(dev->input->buffer + dev->input->bufs); for(size_t i = 0; i < fft_size; i++, buf2 += 2) { fftin[i][0] = scale * buf2[0] * window[i]; fftin[i][1] = scale * buf2[1] * window[i]; } -#endif +#endif /* WITH_BCM_VC */ + } else { // S8 or U8 levels_ptr = (dev->input->sfmt == SFMT_U8 ? levels_u8 : levels_s8); + #ifdef WITH_BCM_VC sample_fft_arg sfa = {fft_size / 4, fft->in}; for (size_t i = 0; i < FFT_BATCH; i++) { samplefft(&sfa, dev->input->buffer + dev->input->bufs + i * bps, window, levels_ptr); sfa.dest+= fft->step; } -#elif defined (__arm__) || defined (__aarch64__) +#else unsigned char* buf2 = dev->input->buffer + dev->input->bufs; for (size_t i = 0; i < fft_size; i++, buf2 += 2) { fftin[i][0] = levels_ptr[buf2[0]] * window[i]; fftin[i][1] = levels_ptr[buf2[1]] * window[i]; } -#else /* x86 */ - unsigned char* buf2 = dev->input->buffer + dev->input->bufs; - for (size_t i = 0; i < fft_size; i += 2, buf2 += 4) { - __m128 a = _mm_set_ps(levels_ptr[buf2[3]], levels_ptr[buf2[2]], levels_ptr[buf2[1]], levels_ptr[buf2[0]]); - __m128 b = _mm_set_ps(window[i+1], window[i+1], window[i], window[i]); - a = _mm_mul_ps(a, b); - _mm_store_ps(&fftin[i][0], a); - } -#endif +#endif /* WITH_BCM_VC */ } + #ifdef WITH_BCM_VC gpu_fft_execute(fft); #else fftwf_execute(demod_params->fft); -#endif +#endif /* WITH_BCM_VC */ #ifdef WITH_BCM_VC for (int i = 0; i < dev->channel_count; i++) { @@ -527,7 +503,7 @@ void *demodulate(void *params) { dev->channels[j].iq_in[2*dev->waveend+1] = fftout[dev->bins[j]][1]; } } -#endif // WITH_BCM_VC +#endif /* WITH_BCM_VC */ dev->waveend += FFT_BATCH; @@ -622,7 +598,7 @@ void *demodulate(void *params) { // save off waveout before notch and ampfactor channel->prev_waveout = waveout; } -#endif // NFM +#endif /* NFM */ // process audio sample for CTCSS, will be no-op if not configured fparms->squelch.process_audio_sample(waveout); @@ -672,7 +648,7 @@ void *demodulate(void *params) { afc.finalize(dev, i, fft->out); #else afc.finalize(dev, i, demod_params->fftout); -#endif +#endif /* WITH_BCM_VC */ if (tui) { char symbol = fparms->squelch.signal_outside_filter() ? '~' : (char)channel->axcindicate; @@ -709,7 +685,7 @@ void *demodulate(void *params) { debug_bulk_print("waveavail %lu.%lu %lu\n", te.tv_sec, (unsigned long) te.tv_usec, (te.tv_sec - ts.tv_sec) * 1000000UL + te.tv_usec - ts.tv_usec); ts.tv_sec = te.tv_sec; ts.tv_usec = te.tv_usec; -#endif +#endif /* DEBUG */ demod_params->mp3_signal->send(); dev->row++; if (dev->row == 12) { @@ -729,10 +705,10 @@ void usage() { \t-F\t\t\tRun in foreground, do not display waterfalls (for running as a systemd service)\n"; #ifdef NFM cout<<"\t-Q\t\t\tUse quadri correlator for FM demodulation (default is atan2)\n"; -#endif +#endif /* NFM */ #ifdef DEBUG cout<<"\t-d \t\tLog debugging information to (default is "<\tUse non-default configuration file\n\t\t\t\t(default: "<> 25) & 0x1)) { - /* NOOP */ - } else { - printf("Unsupported CPU.\n"); - error(); - } -#endif /* !__arm__ */ +#endif /* DEBUG */ // If executing other than as root, GPU memory gets alloc'd and the // 'permission denied' message on /dev/mem kills rtl_airband without @@ -832,7 +800,7 @@ int main(int argc, char* argv[]) { cerr<<"FFT library requires that rtl_airband be executed as root\n"; exit(1); } -#endif +#endif /* WITH_BCM_VC */ // read config try { @@ -867,7 +835,8 @@ int main(int argc, char* argv[]) { #ifdef WITH_BCM_VC cerr<<"Using multiple_demod_threads not supported with BCM VideoCore for FFT\n"; exit(1); -#endif +#endif /* WITH_BCM_VC */ + multiple_demod_threads = true; } if(root.exists("multiple_output_threads") && (bool)root["multiple_output_threads"] == true) { @@ -880,7 +849,8 @@ int main(int argc, char* argv[]) { #ifdef NFM if(root.exists("tau")) alpha = ((int)root["tau"] == 0 ? 0.0f : exp(-1.0f/(WAVE_RATE * 1e-6 * (int)root["tau"]))); -#endif +#endif /* NFM */ + Setting &devs = config.lookup("devices"); device_count = devs.getLength(); if (device_count < 1) { @@ -888,7 +858,6 @@ int main(int argc, char* argv[]) { error(); } -#ifndef __MINGW32__ struct sigaction sigact, pipeact; memset(&sigact, 0, sizeof(sigact)); @@ -900,9 +869,6 @@ int main(int argc, char* argv[]) { sigaction(SIGINT, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); -#else - SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE ); -#endif devices = (device_t *)XCALLOC(device_count, sizeof(device_t)); shout_init(); @@ -940,7 +906,7 @@ int main(int argc, char* argv[]) { mixer_t *m = &mixers[z]; debug_print("mixer[%d]: name=%s, input_count=%d, output_count=%d\n", z, m->name, m->input_count, m->channel.output_count); } -#endif +#endif /* DEBUG */ } catch(const FileIOException &e) { cerr<<"Cannot read configuration file "<type == O_PULSE) { pulse_init(); pulse_setup((pulse_data *)(output->data), channel->mode); -#endif +#endif /* WITH_PULSEAUDIO */ } } } @@ -1054,7 +1018,7 @@ int main(int argc, char* argv[]) { } else if(output->type == O_PULSE) { pulse_init(); pulse_setup((pulse_data *)(output->data), channel->mode); -#endif +#endif /* WITH_PULSEAUDIO */ } } } @@ -1164,7 +1128,8 @@ int main(int argc, char* argv[]) { #ifdef WITH_PULSEAUDIO pulse_start(); -#endif +#endif /* WITH_PULSEAUDIO */ + sincosf_lut_init(); // Startup the demod threads @@ -1220,7 +1185,7 @@ int main(int argc, char* argv[]) { close_debug(); #ifdef WITH_PROFILING ProfilerStop(); -#endif +#endif /* WITH_PROFILING */ return 0; } diff --git a/src/rtl_airband.h b/src/rtl_airband.h index 4804310..3f0da97 100644 --- a/src/rtl_airband.h +++ b/src/rtl_airband.h @@ -32,15 +32,18 @@ #include // sockaddr_in #include "config.h" + #ifdef WITH_BCM_VC #include "hello_fft/gpu_fft.h" #else #include -#endif +#endif /* WITH_BCM_VC */ + #ifdef WITH_PULSEAUDIO #include #include -#endif +#endif /* WITH_PULSEAUDIO */ + #include "input-common.h" // input_t #include "squelch.h" #include "filters.h" @@ -50,19 +53,23 @@ #define SLEEP(x) usleep(x * 1000) #define THREAD pthread_t #define GOTOXY(x, y) printf("%c[%d;%df",0x1B,y,x) + #ifndef SYSCONFDIR #define SYSCONFDIR "/usr/local/etc" -#endif +#endif /* SYSCONFDIR */ + #define CFGFILE SYSCONFDIR "/rtl_airband.conf" #define PIDFILE "/run/rtl_airband.pid" #define MIN_BUF_SIZE 2560000 #define DEFAULT_SAMPLE_RATE 2560000 + #ifdef NFM #define WAVE_RATE 16000 #else #define WAVE_RATE 8000 -#endif +#endif /* NFM */ + #define WAVE_BATCH WAVE_RATE / 8 #define AGC_EXTRA 100 #define WAVE_LEN 2 * WAVE_BATCH + AGC_EXTRA @@ -77,7 +84,7 @@ #define LAMEBUF_SIZE 22000 //todo: calculate #define MIX_DIVISOR 2 -#if defined WITH_BCM_VC +#ifdef WITH_BCM_VC struct sample_fft_arg { size_t fft_size_by4; @@ -88,7 +95,7 @@ extern "C" void samplefft(sample_fft_arg *a, unsigned char* buffer, float* windo # define FFT_BATCH 250 #else # define FFT_BATCH 1 -#endif +#endif /* WITH_BCM_VC */ //#define AFC_LOGGING @@ -103,7 +110,7 @@ enum output_type { O_UDP_STREAM #ifdef WITH_PULSEAUDIO , O_PULSE -#endif +#endif /* WITH_PULSEAUDIO */ }; struct icecast_data { @@ -111,7 +118,7 @@ struct icecast_data { int port; #ifdef LIBSHOUT_HAS_TLS int tls_mode; -#endif +#endif /* LIBSHOUT_HAS_TLS */ const char *username; const char *password; const char *mountpoint; @@ -164,7 +171,7 @@ struct pulse_data { mix_modes mode; bool continuous; }; -#endif +#endif /* WITH_PULSEAUDIO */ struct mixer_data { struct mixer_t *mixer; @@ -187,7 +194,7 @@ enum modulations { MOD_AM #ifdef NFM , MOD_NFM -#endif +#endif /* NFM */ }; class Signal { @@ -233,7 +240,7 @@ struct channel_t { float pj; // previous sample - imaginary part float prev_waveout; // previous sample - waveout before notch / ampfactor float alpha; -#endif +#endif /* NFM */ uint32_t dm_dphi, dm_phi; // derotation frequency and current phase value enum mix_modes mode; // mono or stereo status axcindicate; @@ -258,7 +265,7 @@ struct device_t { input_t *input; #ifdef NFM float alpha; -#endif +#endif /* NFM */ int channel_count; size_t *base_bins, *bins; channel_t *channels; @@ -307,7 +314,7 @@ struct demod_params_t { fftwf_plan fft; fftwf_complex* fftin; fftwf_complex* fftout; -#endif +#endif /* WITH_BCM_VC */ }; struct output_params_t { @@ -387,7 +394,7 @@ int pulse_setup(pulse_data *pdata, mix_modes mixmode); void pulse_start(); void pulse_shutdown(pulse_data *pdata); void pulse_write_stream(pulse_data *pdata, mix_modes mode, const float *data_left, const float *data_right, size_t len); -#endif +#endif /* WITH_PULSEAUDIO */ #endif /* _RTL_AIRBAND_H */ diff --git a/src/rtl_airband_vfp.s b/src/rtl_airband_vfp.s deleted file mode 100644 index 8f16f4c..0000000 --- a/src/rtl_airband_vfp.s +++ /dev/null @@ -1,91 +0,0 @@ -# -# RTLSDR AM demodulator and streaming -# -# Copyright (c) 2014 Wong Man Hang -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -.text -.align 2 -.global samplefft -.type samplefft, %function -.fpu vfp - -samplefft: - -push {r4-r12, lr} -fstmdbs sp!, {s8-s31} - -fmrx r4, fpscr -bic r4, #0x00370000 -orr r4, #0x00070000 -fmxr fpscr, r4 - -#r0 is sample_fft_arg -#[r0, #0] is fft_size_by4 -#[r0, #4] is dest -ldr r4, [r0] -ldr r0, [r0, #4] - -ldrb r5, [r1] -ldrb r6, [r1, #1] -ldrb r7, [r1, #2] -ldrb r8, [r1, #3] -ldrb r9, [r1, #4] -ldrb r10, [r1, #5] -ldrb r11, [r1, #6] -ldrb r12, [r1, #7] - -.a: - -ldr r5, [r3, r5, LSL #2] -ldr r6, [r3, r6, LSL #2] -ldr r7, [r3, r7, LSL #2] -ldr r8, [r3, r8, LSL #2] -ldr r9, [r3, r9, LSL #2] -ldr r10, [r3, r10, LSL #2] -ldr r11, [r3, r11, LSL #2] -ldr r12, [r3, r12, LSL #2] -# load window to VFP -fldmias r2!,{s16-s23} -add r1, r1, #8 -# move level from ARM to VFP -fmsrr {s8, s9}, r5, r6 -fmsrr {s10, s11}, r7, r8 -fmsrr {s12, s13}, r9, r10 -fmsrr {s14, s15}, r11, r12 -pld [r1, #16] -fmuls s24, s8, s16 -pld [r2, #8] -ldrb r5, [r1] -ldrb r6, [r1, #1] -ldrb r7, [r1, #2] -ldrb r8, [r1, #3] -ldrb r9, [r1, #4] -ldrb r10, [r1, #5] -ldrb r11, [r1, #6] -ldrb r12, [r1, #7] -fstmias r0!,{s24-s31} -subs r4, r4, #1 -bne .a - -fmrx r4, fpscr -bic r4, #0x00370000 -fmxr fpscr, r4 - -fldmias sp!, {s8-s31} -pop {r4-r12, pc} - - diff --git a/src/squelch.cpp b/src/squelch.cpp index f1473fb..d81e521 100644 --- a/src/squelch.cpp +++ b/src/squelch.cpp @@ -20,8 +20,9 @@ #include "squelch.h" #ifdef DEBUG_SQUELCH +#include // errno #include // strerror() -#endif +#endif /* DEBUG_SQUELCH _*/ #include // pow() #include // assert() @@ -73,7 +74,7 @@ Squelch::Squelch(void) debug_file_ = NULL; raw_input_ = 0.0; filtered_input_ = 0.0; -#endif +#endif /* DEBUG_SQUELCH */ assert(open_delay_ > buffer_size_); @@ -203,7 +204,7 @@ void Squelch::process_raw_sample(const float &sample) { #ifdef DEBUG_SQUELCH raw_input_ = sample; -#endif +#endif /* DEBUG_SQUELCH */ sample_count_++; @@ -253,7 +254,7 @@ void Squelch::process_raw_sample(const float &sample) { void Squelch::process_filtered_sample(const float &sample) { #ifdef DEBUG_SQUELCH filtered_input_ = sample; -#endif +#endif /* DEBUG_SQUELCH */ if (!should_filter_sample()) { return; @@ -284,7 +285,7 @@ void Squelch::process_filtered_sample(const float &sample) { void Squelch::process_audio_sample(const float &sample) { #ifdef DEBUG_SQUELCH audio_input_ = sample; -#endif +#endif /* DEBUG_SQUELCH */ if (!ctcss_slow_.is_enabled()) { return; @@ -464,7 +465,7 @@ void Squelch::update_current_state(void) { #ifdef DEBUG_SQUELCH debug_state(); -#endif +#endif /* DEBUG_SQUELCH */ } bool Squelch::has_pre_filter_signal(void) { @@ -488,6 +489,8 @@ void Squelch::calculate_noise_floor(void) { noise_floor_ = noise_floor_ * decay_factor + std::min(pre_filter_.capped_, noise_floor_) * new_factor + 1e-6f; + debug_print("%zu: noise floor is now %f\n", sample_count_, noise_floor_); + // Need to update moving_avg_cap_ - depends on noise_floor_ calculate_moving_avg_cap(); @@ -556,8 +559,8 @@ bool Squelch::currently_flapping(void) const { ('post_filter_capped', np.single), ('current_state', np.intc), ('delay', np.intc), - ('low_signalcount', np.intc) - ('ctcss_fast_has_tone', np.intc) + ('low_signalcount', np.intc), + ('ctcss_fast_has_tone', np.intc), ('ctcss_slow_has_tone', np.intc) ]) @@ -638,4 +641,4 @@ void Squelch::debug_state(void) { debug_value((int)ctcss_slow_.has_tone()); } -#endif // DEBUG_SQUELCH +#endif /* DEBUG_SQUELCH */ diff --git a/src/squelch.h b/src/squelch.h index aa01906..3ba539e 100644 --- a/src/squelch.h +++ b/src/squelch.h @@ -24,7 +24,7 @@ #ifdef DEBUG_SQUELCH #include // needed for debug file output -#endif +#endif /* DEBUG_SQUELCH */ #include "ctcss.h" @@ -98,7 +98,7 @@ class Squelch { #ifdef DEBUG_SQUELCH ~Squelch(void); void set_debug_file(const char *filepath); -#endif +#endif /* DEBUG_SQUELCH */ private: enum State { @@ -175,7 +175,7 @@ class Squelch { void debug_value(const float &value); void debug_value(const int &value); void debug_state(void); -#endif +#endif /* DEBUG_SQUELCH */ }; -#endif +#endif /* _SQUELCH_H */ diff --git a/src/test_generate_signal.cpp b/src/test_generate_signal.cpp index cb0947c..0305fb4 100644 --- a/src/test_generate_signal.cpp +++ b/src/test_generate_signal.cpp @@ -220,7 +220,7 @@ TEST_F(GenerateSignalTest, get_sample_single_tone_only) { signal.add_tone(tone_freq, tone_ampl); Tone tone(sample_rate, tone_freq, tone_ampl); for (int i = 0 ; i < 60 * sample_rate ; ++i) { - ASSERT_EQ(signal.get_sample(), tone.get_sample()); + ASSERT_FLOAT_EQ(signal.get_sample(), tone.get_sample()); } } @@ -236,7 +236,7 @@ TEST_F(GenerateSignalTest, get_sample_two_tones) { Tone tone1(sample_rate, tone1_freq, tone1_ampl); Tone tone2(sample_rate, tone2_freq, tone2_ampl); for (int i = 0 ; i < 60 * sample_rate ; ++i) { - ASSERT_EQ(signal.get_sample(), tone1.get_sample() + tone2.get_sample()); + ASSERT_NEAR(signal.get_sample(), tone1.get_sample() + tone2.get_sample(), 0.000001); } }