Try this patch. I think it has to do with vector processing. You'll have to
avoid msp is processing the output of an audio vector with the same vector,
creating a endless processing loop. It's something like the "stack overflow"
for msp. Maybe someone can give a proper technical explanation;-)
At 12:33 +0100 28/12/2005, Thijs Koerselman wrote:
> Try this patch.
For some unknown reason, I can't open this text file in Max (4.1).
> You'll have to avoid msp is processing the output of an audio vector
> with the same vector, creating a endless processing loop.
It is not an endless loop, it is recursive programming. I'm computing
biphase codes from NRZ and clock. The coder and decoder have
forward/backward terms (similar to a recursive filter). I guess MSP can't
compile an audio network with loops.
>1) in order to get the 1 sample delay needed for your filter in MSP,
>you need to set the signal vectorsize to 1, then use a send~ and
>receive~ pair to copy and delay the output signal y[n-1] back to the
>top of the dsp-chain.
So, a pair of send~/receive~ delays for exactly 'vectorsize' samples. This
is a workaround for my problem. Thanks.
> I'm computing
> biphase codes from NRZ and clock. The coder and decoder have
> forward/backward terms (similar to a recursive filter).
For the encoder going from NRZ/clock to biphase, how about using
cycle~ in combination with a custom buffer~ and a *~ object that flips
its argument between -1 and 1 depending on that input? And if you
have clock for the decoder, how about a multiplication of the input
with a similar custom cycle~ running in sync, followed by a
thresholder and a factor of 2 downsampled poly~ to extract the proper
samples? These techniques do not require feedback, although if you do
not have clock for the decoding a PLL requires feedback.
> level during 1's of message depends on level at end of _previous_ bit.
There is a transition in the middle of a 1, but no transition in the
middle of a 0, so with a locked clock I don't understand why the
decoding would require feedback. A phase-locked loop requires
feedback, but if you're willing to lock "slowly" the feedback does not
have to be single-sample.
> Because MSP is not C, and you can't express such a thing as "flip at the
> middle of bit cell if message is one".
I present the below patch as proof that you can express such a thing
in MSP. It contains both a biphase-M encoder and decoder programmed
completely in MSP. Some important ingredients are selector~, +=~,
count~, delay~, and a loose send~ and receive~ feedback loop to keep
the accumulator from overflowing. The graphing of the results is done
using Jitter, so if you don't have version 1.5 installed you may want
to download and install it (it will work free for 30 days.)
>I present the below patch as proof that you can express such a thing
>in MSP. It contains both a biphase-M encoder and decoder programmed
>completely in MSP. Some important ingredients are selector~, +=~,
>count~, delay~, and a loose send~ and receive~ feedback loop to keep
>the accumulator from overflowing. The graphing of the results is done
>using Jitter, so if you don't have version 1.5 installed you may want
>to download and install it (it will work free for 30 days.)
I'm extremely interested in looking at your solution but your patch, as
many other patches presented here, are Max 4.5.5 clipboards
At 12:02 +0200 07/10/2005, Jeremy Bernstein wrote:
>This new format is the result of the copy-as-text feature in Max
>4.5.5 - patches pasted like this can only be opened in Max 4.5.5 or
>later (without a lot of work).
I'm using Max 4.1 since I'm bound to OS/9 for a while. Installing 4.5.5
requires me to go on an OS/X machine (with no audio and no MIDI), asking
for a new authorization or being disabled again in 30 days.
In the meantime, could you please "save as text"?
>The graphing of the results is done using Jitter, so if you don't have
>installed you may want to download and install it (it will work free for
I graph with poke~ing to a buffer linked to a waveform display. Think it
can do it. I also can dac~ to a real multi-trace scope.
>Okay Jean-Yves, below is the patch saved-as-text. Enjoy!
I'm still de-engineering your patch. Tricky! The accumulator is a
five-state logic, is it?
Your bit clock is half the audio sample rate. I use a different technique
in order to match various bit rates. Due to tapin~/tapout~ use, I'm limited
to the set of periods equal to VectorSize/SampleFreq. For example, 64/44.1
= 1.45mS, 32/44.1 = 0.72mS, and it is unlikely that an external device will
sync. It's even less likely to sync on an external signal, assuming that
the PLL problem had been solved, wich is a project left for a next rainy
week-end, if any. So, I end with yet another proof of concept, but nothing
Let me, in turn, present some patches. In order to keep this mail short,
rendez-vous at .
Figure 1 is the arithmetic (boolean), rather than algorithmic description
of the coder and decoder. Two kinds of biphase code are represented :
"level" and differential. They are derived from the definition:
1 -> a'(i) = -a'(i-1), a''(i) = -a'(i)
0 -> a'(i) = +a'(i-1), a''(i) = -a'(i)
where a', a'' are the two consecutive voltage values in a bit cell.
biphase-M is slightly different, i've not finished the decoder.
Some background : I have to deal with a variety of audio-visual tape codes
(Simda, Bassgen, Dataton...). The idea is to recover old programs ans
transcode them in a standard protocole, as MIDI or Kodak P-bus. Some are
FM, some are baseband.
It was really simple for FM codes and was first implemented using N.I.
Reaktor. I thank Mac/MSP was more suitable. Since SMPTE LTC is biphase-M,
is well documented and available in the studio, the program should pass
the LTC test (some a/v codes are very close to LTC).
The test patch would work for 3 codes, generate and recover a known cyclic
bit pattern (and known matching line codes). I use a buffer~ between Max
and MSP. bits2buf loads the pattern in the buffer. buf2NRZ~ reads this
buffer (index~). CLK~ is a simple train~.
It works "sometimes". When the DSP starts, you get randomly one of three
conditions for the recovered NRZ:
- line code (wrong)
- inverted NRZ (wrong)
- original NRZ (good)
This, I think, is due to the way tapin~/tapout~ are initialized or
flushed. Display is with scope~ and is readable with only a small set of
parameters. preset~ #1 works well with a 128 samples vector size. It's
better to reload the patch if you change the vector size.
> Your bit clock is half the audio sample rate. I use a different technique
> in order to match various bit rates. Due to tapin~/tapout~ use, I'm limited
> to the set of periods equal to VectorSize/SampleFreq...
Hm. I don't think I understand why your project has to be done in a
real-time mode. It seems to me an easier method would be to record~
all of the data and then analyze off-line. The first stage of this
analysis would probably be a resampling of the data down to its
"natural" sampling rate. You could then use your MSP network to
decode the data (in real time, if you liked.)
On Dec 28, 2005, at 10:41 AM, Peter Castine wrote:
> Look at Jean-Yves' patch:
thanks for posting that image, Peter. A lot easier to understand that
reading the patch as text!! ;)
You can often find the right object to make what you want, even if it's
not obvious. Jean-Yves' example patch is a type of comb filter, so
instead of writing it as a patch using delay~ (which, as has been
pointed out, is impossible unless you use the send~/receive~ trick to
break the loop) it might be easier to just use the comb~ object. Check
out the little diagram in the comb~ object's help file and you'll see
that it's just an N-sample delay with optional feedforward and feedback
delay. (I say optional because you can set either coefficient to zero
to turn it off, and by default the coefficients are set to zero.)
Remember that biquad~, comb~, teeth~ and allpass~ are not just filter
objects but also delay lines with some bells and whistles. They can
therefore be used to make these sorts of delay-with-feedback networks.
Now, you can't embed an allpass filter (or any other dsp) *within* the
feedback loop of a comb~ -- something which some reverb algorithms use
-- but in a lot of those cases you're dealing with larger delay times
and can implement the thing as a patch using tapin~/tapout~ instead.
> The natural sampling rate is the recovered bit stream clock. So, who/what
> procures the clock?
hm. Since there's no clock synchronization time or anything I guess
the best way would be to use an algorithm that optimizes an estimate
of the clock period and phase offset with repetetive passes over the
1. identify the zero-crossings in the signal
2. make an intelligent guess at the phase offset and period
3. calculate the difference between the estimated and identified zero-crossings
4. if differences are larger than some threshold, revise estimate and
go back to 3.
You can do all of this with buffer~ objects and uzi and counter
objects and what not. This algorithm assumes that the tape wow and
flutter will be minimal - ie, the input signal is reasonably steady.
If not you have a more complicated problem.
Once you've got a reasonable offset and frequency you can do a pass
with an FIR lowpass filter of the appropriate length to reduce the
bit-rate of the signal to the natural rate of one sample per clock
Jean-Yves Bernier wrote:
> I was underestimating the wonderful sync ability of the MIDI TimePiece:
> So, it is now a bit more than a proof of concept. Max/MSP generating LTC.
> Perftectly useless, but I like it :))
It's not useless at all, not everybody does have a MIDI TimePiece...
I'm currently working on phase-locking to an external signal.
To close this thread on recursive programming, I've learned to use
tapin~/tapout~ as well as teeth~ as recursive operators. But I came to a
better solution, non recursive, non vector size-dependant. So, solving the
problem was thinking different.