Mod-noise-removal

The mod-noise-removal service seems to take up a lot of CPU even with a blank (new) pedalboard, apart from the obvious fact that it’s something to get rid of noise can anyone explain what it’s actually doing? I’ve downloaded all the moddevices repos @github but a grep across that codebase doesn’t find the code for this, can someone point me in the right direction?

1 Like

I don’t know if the source code is available at this time. My understanding from other threads is that they discovered that RAM operations were occurring at regular intervals, and that was causing or contributing to the problem. The purpose of the tool is to “keep the RAM busy” or introduce jitter that will disrupt the operation intervals and prevent harmonic frequencies from being generated by the memory hardware.

1 Like

wow, that sounds interesting, bet it was hard to find that issue. So that would probably explain why the task might “work harder” on a blank pedalboard when there’s not much going on?

1 Like

That is a splendid hack indeed ! Thanks for this, @falkTX.

2 Likes

There is no special reason to keep the code closed, it is pretty minimal anyway.
We just thought anyone could do something very similar very quickly, and a repo just for such thing seem wasteful.

For the curious ones, here is the full code:

#define _GNU_SOURCE
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <systemd/sd-daemon.h>
#define MEM_ALLOC_SIZE 4096

static volatile bool g_running = true;

static void* alloc_free_run(void* arg) {
    void* mem;

    while (g_running) {
        mem = malloc(MEM_ALLOC_SIZE);
        if (!mem) break;
        pthread_yield();
        free(mem);
        pthread_yield();
    }

    return NULL;

    // unused
    (void)arg;
}

static void create_thread(pthread_t* thread, int cpu)
{
    pthread_attr_t attributes;
    pthread_attr_init(&attributes);
    pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE);
    pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM);

    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(cpu, &cpuset);
    pthread_attr_setaffinity_np(&attributes, sizeof(cpuset), &cpuset);

    pthread_create(thread, &attributes, alloc_free_run, NULL);

    pthread_attr_destroy(&attributes);
}

static void signal_handler(int sig)
{
    g_running = false;
    return;

    // unused
    (void)sig;
}

int main()
{
    pthread_t t1, t2;
    create_thread(&t1, 0);
    create_thread(&t2, 1);
#ifdef __aarch64__
    pthread_t t3, t4;
    create_thread(&t3, 2);
    create_thread(&t4, 3);
#endif

    struct sigaction sig;
    memset(&sig, 0, sizeof(sig));

    sig.sa_handler = signal_handler;
    sig.sa_flags   = SA_RESTART;
    sigemptyset(&sig.sa_mask);
    sigaction(SIGTERM, &sig, NULL);
    sigaction(SIGINT, &sig, NULL);

    sd_notify(0, "READY=1");

    while (g_running) usleep(200*1000);

    sd_notify(0, "STOPPING=1");

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
#ifdef __aarch64__
    pthread_join(t3, NULL);
    pthread_join(t4, NULL);
#endif

    return 0;
}

Also might be worth mentioning. Both Duo and Duo X run a realtime kernel; priorities are set in a way so that this “noise-removal” is run with no RT priority (SCHED_OTHER) and with +15 “niceness”.
So it makes it a non-RT process that runs lower in priority than anything else in the system.

During our tests, it did not affect the visible performance of the unit, though it does make it look strange looking at something like top telling you 100% cpu is busy all the time.

2 Likes

Thanks for the detailed reply and the code dump!

2 Likes