Thank you Giuseppe!  I will give this a try this evening, really appreciate it!

Best,
Dan 
--
Dan Nigrin / Defective Records / https://defectiverecords.com  
Fauxmo: a Fizmo editor / Cyclic, M185 & Klee Sequencers / MC-4, MC-202 and DSX 
Hacks

On 5/17/21, 5:36 AM, "Giuseppe Silvi" <gramma...@me.com> wrote:

    Hi Dan,
    I don’t know the process behaviour, but here I attached the upgrade to the 
STDFAUST functions.

    best,
    giuseppe

    /* The Kansas City Standard (KCS) uses frequency shift keying to encode 
binary
       digits at 300 bps as an audio signal. This Faust module provides a KCS
       signal analyzer for the Casio FA-3 tape interface used with the early 
Casio
       Basic pocket computers from the 1980s, such as the Casio PB-100 and the
       FX-730P. You can find more info about the hardware of these PDA 
precursors
       at http://www.pisi.com.pl/piotr433. */

    /* This got quite a bit more involved than I first made it out to be. Maybe
       that's also the reason why I couldn't find any ready-made solution on the
       net that would work with the noisy output signal produced by my Casio
       PB-100 calculator. Thanks are due to Jos Horsmeier for pointing out that
       autocorrelation might do the trick, which it actually did. :) */

    // MODIFIED BY DAN NIGRIN December 2007
    import("stdfaust.lib"); 
    //import("math.lib");
    //import("music.lib");

    /* Here are a few threshold constants you might have to tinker with. The
       default values seem to work ok with the FA-3 interface, but YMMV. */

    K0 = 0.1; // absolute threshold of noise gate
    K1 = 0.3; // rectifier threshold (relative to max amplitude)

    // DAN NIGRIN CHANGE
    // K2       = 0.8; // rising edges of autocorrelation signal
    // take out the constant, and make a variable
    K2 = hslider("K2", 0.8, 0.5, 1.0, 0.01);

    // DAN NIGRIN CHANGE
    // K3       = 0.3; // falling edges of autocorrelation signal
    // take out the constant, and make a variable
    K3 = hslider("K3", 0.3, 0.1, 0.6, 0.01);

    /* Maximum size of various delay lines; this must always be a power of 2 and
       larger than the window size n (see below). */

    N = 1024;

    /* Frequency of the 1-bit base tone (which is also the frequency of the
       lead-in tone). For standard KCS this is 2400 Hz, but the frequencies of 
the
       Casio FA-3 tape interface are slightly shifted because it uses a 32768Hz
       xtal as a reference, resulting in 32768Hz/14=2340Hz as logic 1. In any
       case, 8 cycles of this wave represent a 1 bit, while a 0 bit consists of 
4
       cycles of half the frequency. The length of one symbol thus corresponds 
to
       SR*8/freq samples which is also used as the window size for the
       autocorrelation analysis. */

    freq = hslider("freq", 2340, 1000, 5000, 1);
    k = ma.SR/freq : ceil : int;    // period length (samples)
    n = ma.SR*4/freq : ceil : int;  // symbol length (samples) - MODIFIED BY 
DAN NIGRIN FROM SR*8

    /* Input gain in dB. Use this to make up for a weak input signal. Changes to
       this value will also trigger a recalibration of the signal envelop (see
       below). */

    gain = ba.db2linear(hslider("gain", 0, -96, 96, 0.1));

    /* 1 pole LP used to estimate the current signal strength. This unit is used
       to trigger processing as soon as the signal rises above a certain 
absolute
       threshold. */

    env = abs : *(1-g) : + ~ *(g)
    with {
        t = 0.1;            // attack/release time in seconds
        g = exp(-1/(ma.SR*t));  // corresponding gain factor
    };

    /* Determine the maximum amplitude used to compute the threshold for
       rectifying the signal. This gets recalibrated automagically when t=1 
(which
       happens in the main program as soon as the signal rises above a certain
       threshold or the input gain is modified). */

    maxenv(t) = *(1-t) : max ~ *(1-t);

    /* Rectify a signal using a given threshold, and turn the rectified signal
       into a train of "trigger" pulses. */

    rect(m,x) = x>=m;
    trigger(x) = x>x';

    /* Integrate a signal over a window with given length d. */

    integrate(d,x) = x-de.delay(N,d,x) : + ~ _;

    /* Sample-and-hold. Repeats last nonzero value of the input signal. */

    samplehold(x) = rwtable(2, 0, x==0, x, 0);

    /* Clock signal. Repeats last nonzero value of the input signal every d
       samples. */

    clock(d,x) = rwtable(N, 0, x==0, x, (int : %(int(d)) : *(x==0)) ~ +(1));

    /* Signal cleanup. This removes "nearby" double pulses (less than d samples
       away from each other) in the output signal. Only the second pulse of each
       such pair is kept. NOTE: Since a Faust program processes signals 
"on-line",
       i.e., it cannot look into the future, this unit delays the input signal 
by
       d samples. */

    cleanup(d,x) = (1-v)*de.delay(N, d, x)
    with {
        u = integrate(d, abs(x))>1;
        v = trigger(1-u);
    };

    /* The main program. The input is the mono signal x0 to be analyzed. The 
main
       output is the y1 signal. A single-sample +1 pulse means a binary 1, a -1
       pulse a binary 0. In between the symbol pulses the y1 signal is 0. */

    /* For illustrative and debugging purposes we also output the preamplified
       input signal, the gate signal (useful to sense when a transmission starts
       and stops), the rectified input signal and the rectified autocorrelation
       signal. Essentially, the latter is the rectified autocorrelation of the
       rectified input signal which is then sampled at the symbol rate to
       construct the output signal. Some complications arise, though, because 
the
       detected 0 and 1 bit pulses are not fully in sync and the symbol length
       rounded to samples is not fully accurate either. This is taken care of 
by a
       final "cleanup" phase in which any resulting spurious double pulses are
       removed from the output signal. */

    process(x0) = attach(x1, e : hbargraph("maximum", 0, 1)), g1, r1, s1, y1
    with {
        /* Apply input gain. */

        x = x0*gain;

        /* Noise gate. */

        g = env(x)>K0;

        /* Rectified input signal, with pulses of length k for each period of
           the input signal. This is done by detecting the rising edges during
           the first half of the signal period. */

        e = maxenv((g>g')|(gain!=gain'), x);
        r = integrate(k, trigger(rect(K1*e,x)*g)) : min(1);

        /* Autocorrelation of the rectified input signal. Note that the
           rectified signal looks more like 1-1-1-1-... for 1-bits, whereas
           0-bits look more like 1-0-1-0-..., where each 0 or 1 represents one
           base frequency period of k samples here. Hence the 1-bit signal's
           autocorrelation for a delta of k samples will be close to 1,
           whereas the 0-bit signal produces an autocorrelation close to 0. */

        a = integrate(n, r*de.delay(N, k, r))/n;

        /* Lead bits corresponding to rising and falling edges of the
           autocorrelation signal (1 = 1 bit, -1 = 0 bit). */

        b = g*(trigger(a>=K2)-trigger(a<=K3));

        /* Clock signal (pulses at symbol rate, triggered by lead bits). */

        c = g*(clock(n, b>0)-clock(n, b<0));

        /* Sample-and-hold of the lead bits, yielding the rectified
           autocorrelation signal. */

        s = g*samplehold(b);

        /* The preliminary output signal, which is obtained from the rectified
           autocorrelation signal by sampling at the pulses given by the clock
           signal. In effect, this repeats the lead bits at the symbol rate. */

        y = (c>0)*(s>0)-(c<0)*(s<0);

        /* Finally clean up the output signal to remove any spurious double
           pulses which are less than n2 = half the period away from each
           other. Note that this delays the signal by n2 samples, so we apply
           a corresponding delay to the other output signals as well. */

        n2 = int(n/2);
        y1 = cleanup(n2, y);
        x1 = de.delay(N, n2, x);
        g1 = de.delay(N, n2, g);
        r1 = de.delay(N, n2, r);
        s1 = de.delay(N, n2, s);
    };



    > On 16 May 2021, at 04:21, Dan Nigrin <d...@defectiverecords.com> wrote:
    > 
    > Hello list,
    > 
    > New to the list.  I've been using some old (circa 2007) Faust code, 
originally developed by Albert Graef, and modified slightly by me, in one of my 
Max creations.  I compiled the Faust code into a Max external.
    > 
    > I've recently been trying to update my Max application to 64 bit, so I 
recompiled the Faust code (using the online IDE) to create a 64 bit Max 
external.  That worked fine (with one minor tweak that Stephane Letz helped me 
with), but now the external is not behaving correctly.
    > 
    > I am NOT a Faust expert (or even basic user really), so I'm looking at 
this with newbie eyes.  When I look online at "current" Faust, it seems that 
most of the libraries have now been included in "stdfaust.lib", and so as I 
look at my old code, I'm wondering if I need to update the calls to functions 
from those older libraries (music.lib and math.lib) to the current ones?  I 
assume math.lib maps to the current maths.lib, but what about music.lib?
    > 
    > Thanks for any assistance in advance, I greatly appreciate it!
    > 
    > -Dan




_______________________________________________
Faudiostream-users mailing list
Faudiostream-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/faudiostream-users

Reply via email to