Recursive programming in MSP. Impossible?


    Dec 28 2005 | 11:17 am
    In the enclosed patch, a delayed audio signal is added to the input.
    Every attempt to implement such a structure fails. Tha audio network simply
    don't work. Cut the feedback wire and you hear the oscillator again. Why?
    max v2;
    --
    Jean-Yves Bernier

    • Dec 28 2005 | 11:28 am
      use send~ + receive~ or insert pause~ in the feedback loop...
    • Dec 28 2005 | 11:33 am
      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;-)
      t_
    • Dec 28 2005 | 1:02 pm
      hi Junior,
      You said pause~ ?
      I didn't knew that object.
      Philippe.
    • Dec 28 2005 | 1:11 pm
      hi,
      it's in the percolate bundle. you don't really need it, a
      send~/receive~pair does the same thing, namely introducing a small
      delay to prevent msp from blocking.
    • Dec 28 2005 | 1:19 pm
      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.
      --
      Jean-Yves Bernier
    • Dec 28 2005 | 1:19 pm
      At 14:11 +0100 28/12/2005, junior wrote:
      >it's in the percolate bundle. you don't really need it, a
      >send~/receive~pair does the same thing, namely introducing a small
      >delay to prevent msp from blocking.
      Yes, I've noticed that send~/receive~ works. But they add an extra delay
      wich depends on scheduling (I think) and the phase relationship is lost.
      --
      Jean-Yves Bernier
    • Dec 28 2005 | 1:32 pm
      hi Jean-Yves,
      add
      max v2;
      at the beginning
      and
      at the end of the text and you will be able to open the patch...
      Philippe.
    • Dec 28 2005 | 2:18 pm
    • Dec 28 2005 | 2:41 pm
      At 15:18 +0100 28/12/2005, Peter Castine wrote:
      >In terms of DSP, what you have *is* a loop. It's a feedback loop.
      >Period.
      Ok. This is what I suspected.
      >Googling, for instance, on
      > loop "no audio" site:synthesisters.com
      I found this one:
      >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.
      --
      Jean-Yves Bernier
    • Dec 28 2005 | 3:57 pm
      hi all
      stupid question: how much cpu utilization could change using a
      subpatcher and not an external for the same content?
      thank you all
      --
      e-mail: franzrosati@yahoo.it
    • Dec 29 2005 | 12:04 am
      When I have to do things that deal with samples themselves (and I
      need to pop vectors apart) I start thinking about java and or c
      externals.
      You could probably bang out a java extern that does exactly what you
      want way faster than hacking your way through msp.
      I use msp for all non-sample based stuff, i.e. milliseconds or stuff
      that is vector-size agnostic.
      _Mark
    • Dec 29 2005 | 8:33 am
      > 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.
      Ben
    • Dec 30 2005 | 4:34 pm
      At 0:33 -0800 29/12/2005, Ben Nevile wrote:
      >These techniques do not require feedback
      Biphase said "L" (Level) transmitter does not require feedback (it's a XOR
      between NRZ and clock). But receiver does, as other varieties of biphase
      (biphase "mark", differential biphase). See
      http://zone.ni.com/devzone/conceptd.nsf/2d17d611efb58b228625 67a9006ffe76/9ce4dbed595b119a86256e6f00704a7a/Content3/0.A90 6?OpenElement&FieldElemFormat=gif
      level during 1's of message depends on level at end of _previous_ bit. LTC
      is biphase-M, as is the code I'm dealing with, a Bassgen dissolve unit
      audio signal.
      >if you do not have clock for the decoding a PLL requires feedback.
      Yes ;(
      --
      Jean-Yves Bernier
    • Dec 30 2005 | 7:10 pm
      > 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.
      Ben
    • Dec 31 2005 | 1:40 pm
      Re: [max-msp] Recursive programming in MSP.
      Impossible
      At 11:10 -0800 30/12/2005, Ben Nevile wrote:
      >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.
      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". But
      there is an arithmetic form, in ascii art:
    • Dec 31 2005 | 8:14 pm
      > 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.)
      Ben
    • Jan 01 2006 | 6:06 pm
      At 12:14 -0800 31/12/2005, Ben Nevile wrote:
      >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.)
      Ben,
      I'm extremely interested in looking at your solution but your patch, as
      many other patches presented here, are Max 4.5.5 clipboards
      ("copy-as-text").
      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
      >version 1.5
      >installed you may want to download and install it (it will work free for
      >30 days.)
      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.
      Happy new year to all.
      --
      Jean-Yves Bernier
    • Jan 01 2006 | 6:15 pm
      Okay Jean-Yves, below is the patch saved-as-text. Enjoy!
      Ben
      max v2;
    • Jan 05 2006 | 12:24 am
      At 10:15 -0800 01/01/2006, Ben Nevile wrote:
      >Okay Jean-Yves, below is the patch saved-as-text. Enjoy!
      Thanks, Ben.
      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
      really usable.
      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.
      Enjoy.
      --
      Jean-Yves Bernier
    • Jan 05 2006 | 2:27 am
      > 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.)
      Ben
    • Jan 05 2006 | 4:01 pm
      At 18:27 -0800 04/01/2006, Ben Nevile wrote:
      [Changing the title]
      >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.
      It has not.
      >The first stage of this analysis would probably be a resampling of the data
      >down to its "natural" sampling rate.
      The natural sampling rate is the recovered bit stream clock. So, who/what
      procures the clock? There is a nice synchronizable phaser~ here
      (oscsync.txt)
      I'm trying to use it as a local oscillator.
      --
      Jean-Yves Bernier
    • Jan 05 2006 | 4:12 pm
      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.
      Here's my comb~ example patch:
    • Jan 05 2006 | 6:36 pm
      At 1:24 +0100 05/01/2006, Jean-Yves Bernier wrote:
      > it is unlikely that an external device will sync.
      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 :))
      --
      Jean-Yves Bernier
    • Jan 05 2006 | 6:46 pm
      > 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
      data. ie,
      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
      pulse.
      Ben
    • Jan 16 2006 | 12:08 pm
      Jean-Yves Bernier wrote:
      > I was underestimating the wonderful sync ability of the MIDI TimePiece:
      >
      > http://www2.pescadoo.net/Max-LTC-to-MTP.png
      >
      >
      > 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...
      Stefan
      --
      [][] [][][] [][] [][][] [][] [][][] [][] [][][]
      [][][][][][][][][][][][][][][][][][][][][][][][][][][][]
      Stefan Tiedje
      Klanggestalter
      Electronic Composition
      &
      Improvisation
      /~~~~~
      \ /|() ()|
      ))))) )| | |( \
      /// _/)/ )))))
      ___/ ///
      -------------------------x---
      --_____-----------|----------
      --(_|_ ----|-----|-----()---
      -- _|_)----|-----()----------
      ----------()------------x----
      14, Av. Pr. Franklin Roosevelt, 94320 Thiais, France
      Phone at CCMIX +33-1-49 77 51 72
    • Jan 17 2006 | 9:43 pm
      At 13:08 +0100 16/01/2006, Stefan Tiedje wrote:
      >It's not useless at all, not everybody does have a MIDI TimePiece...
      Hi Stefan.
      Although replacing a MTP/AV is not my goal, it may be a by-product of the
      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.
      Sounds familiar, huh...
      --
      Jean-Yves Bernier