I'm bumping a thread I started last year, as I've still not been able to find 
the solution.  

I've been using some old (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 the external is not behaving correctly.  Giuseppe Silvi helped me to 
update the calls to the previous libraries that were used (math.lib and 
music.lib) to the current stdfaust.lib in the code listed below, but the 
behavior is still not correct.  I have two videos that illustrate the 
difference in behavior between old and new versions, which hopefully gives 
clues to where the problem lies - you'll see differences in the 4th and 5th 
audio outputs:

Working 32 bit-version:
https://defectiverecords.com/temp/kcs202debug-Max7-32bit.mp4 
<https://defectiverecords.com/temp/kcs202debug-Max7-32bit.mp4> 

Non-working 64 bit version:
https://defectiverecords.com/temp/kcs202debug-Max8-64bit.mp4 
<https://defectiverecords.com/temp/kcs202debug-Max8-64bit.mp4> 

The code is very well documented as you can see below, but sadly my Faust 
skills are not up to debugging this (not to mention that I don't really 
understand how it works in the first place!).  I'm happy to post the original 
code if at all helpful.  My best guess is that a function in one of the 
original libraries is not equivalent to that used in the new stdfaust.lib?

Thank you for any tips in advance!
Dan
--
Dan Nigrin / Defective Records / https://defectiverecords.com 
<https://defectiverecords.com/>
Fauxmo: a Fizmo editor / Cyclic, M185 & Klee Sequencers / MC-4, MC-202 and DSX 
Hacks


/* 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 <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);
};
-- 
Dan Nigrin -  Defective Records - https://defectiverecords.com 
Fauxmo: a Fizmo editor / Cyclic, M185 & Klee Sequencers / DSX, MC-4 & MC-202 
Hack

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

Reply via email to