Spectral stretching and more nifty FFT-stuff

Dec 12, 2006 at 6:37pm

Spectral stretching and more nifty FFT-stuff

So here I am, inside my phase-vocoding pfft~-subpatch. It filters, it gates, but.. it doesn’t transpose yet!

And I can’t just gizmo~ my way out of this because I want to be able to use a buffer~ (in conjunction with an index~ object) to tell my subpatch how much each bin should be transposed. And gizmo~ and fbinshift~ don’t take signals in it’s right inlet.

what to do…?

#29175
Dec 12, 2006 at 7:10pm

#90474
Dec 12, 2006 at 8:11pm

Thanks,

Yes, I think you understand my question very well. I just thought there was a way of changing the frequencies of all the bins by doing something with the phase or something like that. Of course, changing the bins is also a nice trick but I don’t understand what to do after my index~ object has changed the index-number. How can I tell an fftout~ to interpret bin 6 as being bin 4 for instance?

The patch I’m working on is very similar to the one used in the phase vocoder tutorial (http://www.cycling74.com/download/articles/tutorials/pvoc_patches.zip)
so any sollution that would work on that patch would also work on mine.

– Tb

#90475
Dec 12, 2006 at 8:16pm

Ah… wait, let me guess… I should use a two fft-sized buffers (real and imaginary) in which I poke~ all the bins..?

It sounds like there should be an easier way, and I’d be happy to hear of one, but this should work too, I think. I’m gonna try!

– Tb

#90476
Dec 12, 2006 at 8:48pm

#90477
Dec 12, 2006 at 10:56pm

I am also interested in this question. From my brief examination, it appears that you cannot directly do pitch scaling (i.e. multiply the frequency of each partial by a constant) within pfft~ as the only available resynthesis method is IFFT overlap/add, not oscillator bank. Though I have been titillated by the oscbank~ object (and in fact use it with one of my new LyonPotpourri externals for pitch scaling) and wonder if oscbank~ could be incorporated into a pfft~ subpatch for direct frequency manipulations.

Of course an alternative is to do time-scaling within pfft~ and then sample-rate convert outside of the pfft~ patch to get the desired pitch change. But you’re out of luck if you want to apply different multipliers to different partials. (See my magfreq_analysis~ in LyonPotpourri or pvwarp~ in FFTease for custom externals that do this.)

I would be delighted to be shown that pfft~ is in fact able to do direct frequency manipulations.

Eric

#90478
Dec 12, 2006 at 11:19pm

I am also interested in this area. I am working on something where I
want to separate bands of frequencies and shift each differently, the
kind of thing that was done in some of Trevor Wishart’s programs for
the Composers Desktop Project back in the 80s, but do it live. Plus
probably some other things of the kind….

Any ideas much appreciated

L

On 12 Dec 2006, at 22:56, Eric Lyon wrote:

>
> I am also interested in this question. From my brief examination,
> it appears that you cannot directly do pitch scaling (i.e. multiply
> the frequency of each partial by a constant) within pfft~ as the
> only available resynthesis method is IFFT overlap/add, not
> oscillator bank. Though I have been titillated by the oscbank~
> object (and in fact use it with one of my new LyonPotpourri
> externals for pitch scaling) and wonder if oscbank~ could be
> incorporated into a pfft~ subpatch for direct frequency manipulations.
>
> Of course an alternative is to do time-scaling within pfft~ and
> then sample-rate convert outside of the pfft~ patch to get the
> desired pitch change. But you’re out of luck if you want to apply
> different multipliers to different partials. (See my
> magfreq_analysis~ in LyonPotpourri or pvwarp~ in FFTease for custom
> externals that do this.)
>
> I would be delighted to be shown that pfft~ is in fact able to do
> direct frequency manipulations.
>
> Eric
>

Lawrence Casserley – lawrence@lcasserley.co.uk
Lawrence Electronic Operations – http://www.lcasserley.co.uk
Colourscape Music Festivals – http://www.colourscape.org.uk

#90479
Dec 12, 2006 at 11:30pm

> I am also interested in this area. I am working on something where I
> want to separate bands of frequencies and shift each differently, the
> kind of thing that was done in some of Trevor Wishart’s programs for
> the Composers Desktop Project back in the 80s, but do it live. Plus
> probably some other things of the kind….
>
> Any ideas much appreciated
>

Hi Lawrence,

Of course you could do precisely that with my magfreq_analysis~ hooked up to an oscbank~, but it may not be possible to do this exclusively using MaxMSP core objects. Someone please prove me wrong!

Eric

#90480
Dec 12, 2006 at 11:31pm

> I am also interested in this question. From my brief examination, it appears
> that you cannot directly do pitch scaling (i.e. multiply the frequency of each
> partial by a constant) within pfft~

Isn’t that what [gizmo~] does?

#90481
Dec 13, 2006 at 12:14am

Quote: jeanfrancois.charles wrote on Tue, 12 December 2006 23:31
—————————————————-
> > I am also interested in this question. From my brief examination, it appears
> > that you cannot directly do pitch scaling (i.e. multiply the frequency of each
> > partial by a constant) within pfft~
>
> Isn’t that what [gizmo~] does?
>
>

Yes, but gizmo~ cannot handle the more general case of independent bin frequency adjustments.

Eric

#90482
Dec 13, 2006 at 1:40am

#90483
Dec 13, 2006 at 4:23am

If I’m not mistaken, the change in phase of each bin in a phase vocoder is equal to the instantaneous frequency of that bin. I think the frame delta thingy in the pfft patch is what makes for a consistent unwrapping of the phase and hence each bin being within the specific frequency resolution around (fs/(size of fft))*index. If one were to create a structure which increased or decreased the rate of change of the phase of each bin individually one could probably independantly pitch shift whatever partial(indexed component of an fft) by whatever they wanted.

#90484
Dec 13, 2006 at 6:36am

#90485

p-s
Dec 13, 2006 at 9:03am

just on these last days I have been working in a patch
that
1. transforms phases into instantaneous frequencies
(I found a useful formula in the book DAFX ed. by U. Zolzer,
article by Arfib)
2. makes resynthesis with ioscbank~

so, to do so, I have to feed the third output of a FFT object
(index count), in the fourth input of ioscbank~ (index), right?

BUT

it seems that the speed of index count is not supported
by ioscbank~, and in fact it generates something like zipper noise…

Paolo

#90486
Dec 13, 2006 at 9:50am

Thanks Eric

I will have a look at your objects.

I had thought of sending the fft to two places, where one has all the
bins zeroed below my split frequency, and the other those above, then
use two gizmo~s. A bit cumbersome, though……

Best

L

On 12 Dec 2006, at 23:30, Eric Lyon wrote:

> Hi Lawrence,
>
> Of course you could do precisely that with my magfreq_analysis~
> hooked up to an oscbank~, but it may not be possible to do this
> exclusively using MaxMSP core objects. Someone please prove me wrong!
>
> Eric

Lawrence Casserley – lawrence@lcasserley.co.uk
Lawrence Electronic Operations – http://www.lcasserley.co.uk
Colourscape Music Festivals – http://www.colourscape.org.uk

#90487
Dec 13, 2006 at 3:24pm

Thanks a LOT for all your suggestions, I’m really learning about a lot of stuff very fast thanks to the help I get on this forum.

But the more you know, the more you know what you don’t know:

For instance, I can’t find any information on the order in which signals are sent. How can I make sure that I read a signal out of a buffer AFTER a new value has been written to this buffer?

So I have an fftin~ object sending out a signal which specifies the FFT-Bin index number. Suppose at a certain point this number is 10. Then I want to first write to a buffer at index number 10, and then read from it. Not the other way around.

Is there any way to control this? I can’t just use delay because I want the result to be sent to the fftout~ immediately. Not sending the data immediately this would alter the sound in ways that I didn’t intend to.

– Tb

#90488
Dec 14, 2006 at 3:01pm

Tarik wrote:
> Is there any way to control this? I can’t just use delay because I
> want the result to be sent to the fftout~ immediately. Not sending
> the data immediately this would alter the sound in ways that I didn’t
> intend to.

as far as I know, the same right to left rule that applies to scheduler
events, applies to audio rate events: its coming out first on the right
side. Unfortunately there is no such thing as audiorate trigger, but you
can encapsulate a simple input to output as trigger which should work
also with audio patch chords. I use that for having a trigger that does
not change the type you send in…

Save it as St.pat and call it with an argument to get a specified number
of outlets. If you call up the patch from disk to edit it, you need to
hold cmd-shift to prevent it from deleting too much…

#N comlet;
#P outlet 507 91 15 0;
#P objectname out[32];
#N comlet;
#P outlet 491 91 15 0;
#P objectname out[31];
#N comlet;
#P outlet 475 91 15 0;
#P objectname out[30];
#N comlet;
#P outlet 459 91 15 0;
#P objectname out[29];
#N comlet;
#P outlet 443 91 15 0;
#P objectname out[28];
#N comlet;
#P outlet 427 91 15 0;
#P objectname out[27];
#N comlet;
#P outlet 411 91 15 0;
#P objectname out[26];
#N comlet;
#P outlet 395 91 15 0;
#P objectname out[25];
#N comlet;
#P outlet 379 91 15 0;
#P objectname out[24];
#N comlet;
#P outlet 363 91 15 0;
#P objectname out[23];
#N comlet;
#P outlet 347 91 15 0;
#P objectname out[22];
#N comlet;
#P outlet 331 91 15 0;
#P objectname out[21];
#N comlet;
#P outlet 315 91 15 0;
#P objectname out[20];
#N comlet;
#P outlet 299 91 15 0;
#P objectname out[19];
#N comlet;
#P outlet 283 91 15 0;
#P objectname out[18];
#N comlet;
#P outlet 267 91 15 0;
#P objectname out[17];
#N comlet;
#P outlet 251 91 15 0;
#P objectname out[16];
#N comlet;
#P outlet 235 91 15 0;
#P objectname out[15];
#N comlet;
#P outlet 219 91 15 0;
#P objectname out[14];
#N comlet;
#P outlet 203 91 15 0;
#P objectname out[13];
#N comlet;
#P outlet 187 91 15 0;
#P objectname out[12];
#N comlet;
#P outlet 171 91 15 0;
#P objectname out[11];
#N comlet;
#P outlet 155 91 15 0;
#P objectname out[10];
#N comlet;
#P outlet 139 91 15 0;
#P objectname out[9];
#N comlet;
#P outlet 123 91 15 0;
#P objectname out[8];
#N comlet;
#P outlet 107 91 15 0;
#P objectname out[7];
#N comlet;
#P outlet 91 91 15 0;
#P objectname out[6];
#N comlet;
#P outlet 75 91 15 0;
#P objectname out[5];
#N comlet;
#P outlet 59 91 15 0;
#P objectname out[4];
#N comlet;
#P outlet 43 91 15 0;
#P objectname out[3];
#N comlet;
#P outlet 27 91 15 0;
#P objectname out[2];
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N thispatcher;
#Q end;
#P hidden newobj 11 151 73 196617 thispatcher;
#N vpatcher 10 59 245 264;
#P inlet 37 25 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 37 52 45 196617 roudone;
#P window linecount 1;
#P newex 37 115 140 196617 sprintf script delete out[%i];
#P window linecount 0;
#P newex 37 73 54 196617 int;
#P newex 37 94 50 196617 revzi 32;
#P outlet 37 137 15 0;
#P inlet 20 25 15 0;
#P connect 6 0 5 0;
#P connect 5 0 3 0;
#P connect 3 0 2 0;
#P connect 2 0 4 0;
#P connect 4 0 1 0;
#P fasten 0 0 3 1 25 45 86 45;
#P pop;
#P hidden newobj 11 130 73 196617 p scripting;
#P hidden newex 11 109 73 196617 patcherargs 2;
#P inlet 11 68 15 0;
#N comlet;
#P outlet 11 91 15 0;
#P objectname out[1];
#P connect 1 0 0 0;
#P fasten 1 0 5 0 16 87 32 87;
#P fasten 1 0 6 0 16 87 48 87;
#P fasten 1 0 7 0 16 87 64 87;
#P fasten 1 0 8 0 16 87 80 87;
#P fasten 1 0 9 0 16 87 96 87;
#P fasten 1 0 10 0 16 87 112 87;
#P fasten 1 0 11 0 16 87 128 87;
#P fasten 1 0 12 0 16 87 144 87;
#P fasten 1 0 13 0 16 87 160 87;
#P fasten 1 0 14 0 16 87 176 87;
#P fasten 1 0 15 0 16 87 192 87;
#P fasten 1 0 16 0 16 87 208 87;
#P fasten 1 0 17 0 16 87 224 87;
#P fasten 1 0 18 0 16 87 240 87;
#P fasten 1 0 19 0 16 87 256 87;
#P fasten 1 0 20 0 16 87 272 87;
#P fasten 1 0 21 0 16 87 288 87;
#P fasten 1 0 22 0 16 87 304 87;
#P fasten 1 0 23 0 16 87 320 87;
#P fasten 1 0 24 0 16 87 336 87;
#P fasten 1 0 25 0 16 87 352 87;
#P fasten 1 0 26 0 16 87 368 87;
#P fasten 1 0 27 0 16 87 384 87;
#P fasten 1 0 28 0 16 87 400 87;
#P fasten 1 0 29 0 16 87 416 87;
#P fasten 1 0 30 0 16 87 432 87;
#P fasten 1 0 31 0 16 87 448 87;
#P fasten 1 0 32 0 16 87 464 87;
#P fasten 1 0 33 0 16 87 480 87;
#P fasten 1 0 34 0 16 87 496 87;
#P fasten 1 0 35 0 16 87 512 87;
#P hidden connect 2 1 3 1;
#P hidden connect 3 0 4 0;
#P hidden connect 2 0 3 0;
#P window clipboard copycount 36;


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#90489
Dec 14, 2006 at 3:57pm

On Dec 14, 2006, at 10:01 AM, Stefan Tiedje wrote:
> as far as I know, the same right to left rule that applies to
> scheduler events, applies to audio rate events: its coming out
> first on the right side. Unfortunately there is no such thing as
> audiorate trigger,

Stefan:

My experience tells me this is a myth, although I would love to hear
someone from cycling weigh in on this. You’re not the only one I
have heard perpetuating it. In programming externals, the signal
vectors for all inputs are available each time you hit the perform
method. It is all passed at the same time. Any right to left
preference would have to be built into the C-code of an individual
object.

[pause]
OK, just read some more of the thread. Looks like you are talking
about in a patch and *not* inlets/outlets as I was. Here too, I
think the myth does not hold. The order is determined by the signal
flow from start to finish in an MSP chain. So the surefire method
for forcing object A to process after object B is to connect outlet
on A to inlet on B.

If they are not connected, figure out a way to do so! This is the
solution given the MSP paradigm. If you are writing into a buffer
*and* then immediately using that value, why not write into the
buffer *and* send the value on to the point in your patch where it is
needed? In other words, don’t rely on reading from the buffer in
this case.

–Nathan

—–
Nathan Wolek
nw@nathanwolek.com

http://www.nathanwolek.com

#90490
Dec 14, 2006 at 5:08pm

On 14 Dec 2006, at 16:57, Nathan Wolek wrote:

> On Dec 14, 2006, at 10:01 AM, Stefan Tiedje wrote:
>> as far as I know, the same right to left rule that applies to
>> scheduler events, applies to audio rate events: its coming out
>> first on the right side. Unfortunately there is no such thing as
>> audiorate trigger,
>
> Stefan:
>
> My experience tells me this is a myth, …

since the original question was about signal order in pffts, this
thread might be useful
http://www.cycling74.com/forums/index.php?
t=msg&goto=50842&rid=0&S=7f6fc62f27f045f33b120d749a0f53b0#msg_50842

the test patch i have posted in the above thread does state that
there is an issue with signal order – at least in pffts – and that it
seems to be the other way round, i.e. left before right.

and what about the following patch? position the poke~ object to the
left of index~ and compare to the original version.
although i’m not completely sure what’s going on behind the scenes,
it shows that in certain situations you do have to be careful about
relative position of your signal objects.
cheers,
volker.

#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 53 250 41 196617 *~ 0.1;
#P user ezdac~ 45 284 89 317 0;
#P user meter~ 77 212 204 239 50 0 168 0 103 103 103 255 153 0 255 0
0 217 217 0 153 186 0 12 3 3 3 3;
#P newex 53 183 27 196617 -~;
#P newex 210 58 39 196617 noise~;
#P message 87 45 29 196617 stop;
#P button 70 45 15 0;
#P newex 70 138 61 196617 index~ test;
#P newex 70 77 79 196617 count~ 0 100 1;
#P newex 152 255 86 196617 buffer~ test 100;
#P newex 135 138 57 196617 poke~ test;
#P window linecount 3;
#P comment 114 165 182 196617 compare poke sitting to the right of
index to poke being to the left of index…;
#P connect 11 0 10 0;
#P connect 11 0 10 1;
#P connect 8 0 11 0;
#P connect 8 0 9 0;
#P fasten 7 0 8 0 215 104 58 104;
#P connect 7 0 1 0;
#P connect 3 0 4 0;
#P connect 3 0 1 1;
#P connect 5 0 3 0;
#P connect 6 0 3 0;
#P connect 4 0 8 1;
#P window clipboard copycount 12;

#90491
Dec 15, 2006 at 3:36pm

#90492
Dec 15, 2006 at 4:44pm

>> and what about the following patch? position the poke~ object to the
>> left of index~ and compare to the original version.
> I don’t see any difference here. Is it normal?

do you mean no difference to the pfft example, or no difference
wether the position of poke~ is to the left or the right of index~?

#90493
Dec 15, 2006 at 6:34pm

#90494
Dec 15, 2006 at 6:48pm

#90495
Dec 16, 2006 at 4:12am

> My experience tells me this is a myth, although I would love to hear
> someone from cycling weigh in on this. You’re not the only one I
> have heard perpetuating it. In programming externals, the signal
> vectors for all inputs are available each time you hit the perform
> method. It is all passed at the same time.

exactly. you must think of “happens at the same time”
when you have 2 signals in a DSP.

so if you want to write one copy into a buffer and read
from the buffer, you need to implement at least one
sample delay. (not a vector – just one sample)

#90496
Dec 16, 2006 at 11:58am

Quote: Tyler Nitsch wrote on Tue, 12 December 2006 21:23
—————————————————-
> If I’m not mistaken, the change in phase of each bin in a phase vocoder is equal to the instantaneous frequency of that bin. I think the frame delta thingy in the pfft patch is what makes for a consistent unwrapping of the phase and hence each bin being within the specific frequency resolution around (fs/(size of fft))*index. If one were to create a structure which increased or decreased the rate of change of the phase of each bin individually one could probably independantly pitch shift whatever partial(indexed component of an fft) by whatever they wanted.
—————————————————-

This is basically correct. The way to frequency shift fft data without changing resynthesis methods is to phase correct by an amount appropriate to the shift – the phase corrections have to be phase accumulated also if you are operating directly on the cartesian values.

Frequency shifting or warping within a pfft~ is not something I’ve done without writing an external to do it, because it gets nasty in MSP code. It depends also what you want to do. The method used by gizmo~ (and that I have used for frequency warping) acts on peaks (sinusoidlal components) of an input, rather than individual bins (which represent parts of sinusoidal components). For this method MSP only is not an option – you have to do some form of programming of an external, or at least have a couple of extra objects, and writing efficient code would be very hard.

To simply shift individual bins by an integer number of bins is different issue, especially because the phase correction becomes trivial. It depends on overlap, but I think in all cases you might see in Max/MSP you only have to either leave the phase alone, or reverse the polarity of the complex part every other bin.

This is all covered in more detail (and properly) in this paper: http://www.ee.columbia.edu/~dpwe/papers/LaroD99-pvoc.pdf

So to answer Eric’s question it is possible (sort-of) depending on exactly what you want to do. Partial bin shifts are also possible but more complex than integer ones. Per-peak processing is currently not possible in pure Max/MSP code, but a simple peak finder object would make it possible, although inefficient. I hope this kind of thing will become easier in the future in pfft~, but we need more specialised objects for frame-based operations.

Regards,

Alex

#90497
Dec 16, 2006 at 12:11pm

Nathan Wolek wrote:
> My experience tells me this is a myth, although I would love to hear
> someone from cycling weigh in on this. You’re not the only one I have
> heard perpetuating it. In programming externals, the signal vectors
> for all inputs are available each time you hit the perform method. It
> is all passed at the same time. Any right to left preference would
> have to be built into the C-code of an individual object.

As I recall, I did pose the same question some time ago, and I got a
response from David or other c74 guru, maybe Jeremy, which claimed that.
But this was related to the patch cords. I guess that object outlets
could also follow that (common) rule, but I would never rely on it
(though it should be easy to test).

As long you do not create feedback, the signal vector chunks would not
create any problems with this, its the question weather to use the value
from the previous or the current vector and that would be determined by
the order…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#90498
Dec 16, 2006 at 12:14pm

> exactly. you must think of “happens at the same time”
> when you have 2 signals in a DSP.

This is incorrect. The signal vector of an MSP object has to be calcuated in some point in real-time, so there is an order for a DSP chain in which objects calculate their signal vectors – it is impossible for this to be done simultaneously.

Although for many purposes you can imagine that the signal cables in MSP are like analog audio cables and everything is simultaneous, this is in fact not the case, and in some specific instances it becomes an issue. The index~ / poke~ frame delay case is one of these.

The compilation of the DSP chain is done with max messages, and has therefore some relationship to the max right-left bottom-up system, although I seem to remember that tests in the past have produced unexpected (reversed) results so I won’t try to guess which side (right or left) is first. This is complicated by the fact that objects can make a request to be processed first in the DSP chain, so unlike with max objects, the order of execution cannot be expected for all cases to follow a strict rule.

Anyway, an official line on the index~ / poke~ thing would be useful, although i seem to remeber this being more-or-less sorted in the thread volker linked to, however I only get one message using the link – i seem to remember more discussion in this or another thread – maybe someone knows where it is…..

Alex

#90499
Dec 16, 2006 at 12:37pm

On Dec 16, 2006, at 7:11 AM, Stefan Tiedje wrote:
> As long you do not create feedback, the signal vector chunks would
> not create any problems with this, its the question weather to use
> the value from the previous or the current vector and that would be
> determined by the order…

Yes, getting inside the current vector means getting your hands dirty
and coding externals in C. This is what happened to me. Seems to
have motivated several others on this list as well.

——————-
Nathan Wolek, PhD — nwolek@stetson.edu
Assistant Professor of Music Technology
Stetson University – DeLand, FL

http://www.nathanwolek.com

#90500
Dec 16, 2006 at 12:54pm

On 16-Dec-2006, at 13:14, Alex Harker wrote:

>> exactly. you must think of “happens at the same time”
>> when you have 2 signals in a DSP.
>
> This is incorrect. The signal vector of an MSP object has to be
> calcuated in some point in real-time, so there is an order for a
> DSP chain in which objects calculate their signal vectors – it is
> impossible for this to be done simultaneously.

Actually, it’s _not_ incorrect.

Take an object like cartopol~ (or lp.c2p~). When the time to process
DSP comes around, both input vectors are full of data. It’s not like
cartopol~ gets a vector full of y-data, then waits a bit, gets a
vector full of x-data, pumps out a vector full of phase data,
triggering objects down the line of the phase outlet, and then
finally calculates a vector full of amplitude data and sends that out
the left outelt. (This is starting to sound like Jack Nicholson’s
‘dirty joke’ from Chinatown.)

What really happens is that when cartopol~ (or lp.c2p~) comes to
process DSP, it gets two vectors full of data. It fills up two output
vectors of data. Then MSP call the next item in the DSP chain. All
output data is there. Nobody has any idea whether phase or amp was
filled first, or whether the calculations were interwoven, or
anything else. And it doesn’t matter, because all objects down-chain
get all the data when their turn to process DSP comes up.

Obviously the processing is serialized inside each object, but the
processing is also completely encapsulated inside the object. So
other objects respond in a ‘input happens at the same time’ manner,
not in a right-to-left manner. This is significantly different from
the processing with plain-vanilla Max objects.

I can illustrate the above with working C code if you want.

————– http://www.bek.no/~pcastine/Litter/ ————-
Peter Castine +–> Litter Power & Litter Bundle for Jitter
Universal Binaries on the way
iCE: Sequencing, Recording &
Interface Building for |home | chez nous|
Max/MSP Extremely cool |bei uns | i nostri|
http://www.dspaudio.com/ http://www.castine.de

#90501
Dec 16, 2006 at 1:17pm

Quote: Peter Castine wrote on Sat, 16 December 2006 05:54

> Actually, it’s _not_ incorrect.

There is a confusion here between those talking about about DSP order of execution within an object (given a number of signal inputs/outputs to the object) and those talking about order of execution between DSP objects. Roman’s comments seemed unclear as to which situation he was refering to. For others reading the thread let’s make the distinction clear.

Neither of us appear to be wrong. Peter, your comments relate to order of execution within an object (which is up to the programmer in question) – my comments relate to order of execution between objects(as in the poke~ index~ cases cited).

Order of execution within an object shouldn’t be an issue for end users. Order of execution between objects is an issue for max programmers in some cases.

No need for the examples – thanks

Regards

Alex

#90502
Dec 16, 2006 at 4:41pm

Hi there,

I find this thread very interesting…

At this point I have two questions:

1 – Talking about order of execution within an MSP
object, and given an MSP object with multiple outlets,
how is it up to the programmer to decide the output
order? What I mean is that whether in your perform
method you entirely process a vector before the other,
that doesn’t change the actual final output order,
which – in my understanding – is something hard-wired
inside MSP, which 3rd party programmers have no access
to.

Code examples:

n = blksize;
while (n–) {
*out0++ = 0.f;
*out1++ = 1.f;
*out2++ = 2.f;
*out3++ = 3.f;
}

or

n = blksize;
while (n–) {
*out3++ = 3.f;
*out2++ = 2.f;
*out1++ = 1.f;
*out0++ = 0.f;
}

or even

n = blksize;
while (n–) {
*out0++ = 0.f;
}
n = blksize;
while (n–) {
*out1++ = 0.f;
}
n = blksize;
while (n–) {
*out2++ = 0.f;
}
n = blksize;
while (n–) {
*out3++ = 0.f;
}

In my understanding the above loops have no bearing to
the output order of the object. Can someone confirm
this or not?

2 – Talking about order of execution between objects
leads to the same result. Is there anything that a
programmer could do or not do to make this behaviour
more consistent? As far as I know it is still
something internal to the inner-workings of MSP,
however maybe I am overlooking something…

BTW, all of the above does NOT apply for plain Max
object, where the programmer is actually 100%
responsible for output order.

Please someone comment on this.

Thank you.

- Luigi

— Alex Harker wrote:

>
> Quote: Peter Castine wrote on Sat, 16 December 2006
> 05:54
>
> > Actually, it’s _not_ incorrect.
>
> There is a confusion here between those talking
> about about DSP order of execution within an object
> (given a number of signal inputs/outputs to the
> object) and those talking about order of execution
> between DSP objects. Roman’s comments seemed unclear
> as to which situation he was refering to. For others
> reading the thread let’s make the distinction clear.
>
> Neither of us appear to be wrong. Peter, your
> comments relate to order of execution within an
> object (which is up to the programmer in question) -
> my comments relate to order of execution between
> objects(as in the poke~ index~ cases cited).
>
> Order of execution within an object shouldn’t be an
> issue for end users. Order of execution between
> objects is an issue for max programmers in some
> cases.
>
> No need for the examples – thanks
>
> Regards
>
> Alex
>

————————————————————
THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
————————————————————

Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around

http://mail.yahoo.com

#90503
Dec 16, 2006 at 6:21pm

On 16-Dec-2006, at 17:41, Luigi Castelli wrote:

> In my understanding the above loops have no bearing to
> the output order of the object. Can someone confirm
> this or not?

This is exactly the point I was trying to make.

————– http://www.bek.no/~pcastine/Litter/ ————-
Peter Castine +–> Litter Power & Litter Bundle for Jitter
Universal Binaries on the way
iCE: Sequencing, Recording &
Interface Building for |home | chez nous|
Max/MSP Extremely cool |bei uns | i nostri|
http://www.dspaudio.com/ http://www.castine.de

#90504
Dec 16, 2006 at 6:59pm

Its very nice to see this whole discussion going on ’cause I was feeling like an idiot, not knowing how the order in signals in MSP actually works. Unfortunately I still can’t say anything sensible about this subject.

But I’d like to jump in again and post a little example of an extremely simple binshifting patch (yeah, way back in this thread we also discussed binshifting), which shows some strange behaviour.

When I shift the fft-signal one bin up (by simply using delay), the sound gets distorted. If I shift it up two bins, the sound is transposed nicely. If I shift it up three bins, it gets distorted again and with four it sound perfect again… and so on.

My question is: why??

To test it, save the following as “binshift.pat” (this is the pfft~ subpatch)

—————————————————–

#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N in 2;
#P newobj 171 60 23 9109513 in 2;
#P number 171 91 35 9 0 0 0 139 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 151 125 59 9109513 delay~ 2048;
#P newex 90 125 59 9109513 delay~ 2048;
#P newex 90 183 45 9109513 fftout~ 1;
#P newex 90 60 40 9109513 fftin~ 1;
#P comment 196 62 125 9109513 amount of bins to shift up;
#P connect 1 0 3 0;
#P connect 3 0 2 0;
#P connect 4 0 2 1;
#P connect 5 0 3 1;
#P connect 1 1 4 0;
#P connect 6 0 5 0;
#P connect 5 0 4 1;
#P window clipboard copycount 7;

—————————————————–

And save the following as… well, as whatever you like:

—————————————————–

#P window setfont “Sans Serif” 9.;
#P number 218 90 35 9 0 0 1 139 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P message 134 90 28 9109513 open;
#P toggle 117 90 15 0;
#P user ezdac~ 133 190 177 223 0;
#N sfplay~ 1 120960 0 ;
#P newobj 134 123 40 9109513 sfplay~;
#P newex 134 155 94 9109513 pfft~ binshift 2048 2;
#P comment 181 71 100 9109513 set binshifting-amount;
#P connect 1 0 3 0;
#P connect 4 0 2 0;
#P connect 5 0 2 0;
#P connect 2 0 1 0;
#P connect 1 0 3 1;
#P connect 6 0 1 1;
#P window clipboard copycount 7;

———————————————————

- Tb

#90505
Dec 16, 2006 at 6:59pm

#90506
Dec 16, 2006 at 7:10pm

> So to answer Eric’s question it is possible (sort-of) depending on exactly what you want to do.
> Partial bin shifts are also possible but more complex than integer ones.
> Per-peak processing is currently not possible in pure Max/MSP code,
> but a simple peak finder object would make it possible, although inefficient.
> I hope this kind of thing will become easier in the future in pfft~,
> but we need more specialised objects for frame-based operations.
>

This sounds great in theory, but I’ve never actually seen it done without some C intervention a la gizmo~. Could you show us a pfft~ patch that pitch-scales its input (i.e. multiplies each frequency in the spectrum by a user manipulable constant) using only MaxMSP core objects?

Eric

#90507
Dec 16, 2006 at 7:10pm

> So to answer Eric’s question it is possible (sort-of) depending on exactly what you want to do.
> Partial bin shifts are also possible but more complex than integer ones.
> Per-peak processing is currently not possible in pure Max/MSP code,
> but a simple peak finder object would make it possible, although inefficient.
> I hope this kind of thing will become easier in the future in pfft~,
> but we need more specialised objects for frame-based operations.
>

This sounds great in theory, but I’ve never actually seen it done without some C intervention a la gizmo~. Could you show us a pfft~ patch that pitch-scales its input (i.e. multiplies each frequency in the spectrum by a user manipulable constant) using only MaxMSP core objects?

Eric

#90508
Dec 16, 2006 at 7:14pm

Sorry about the double post above. And of course not using gizmo~ in the patch – that would be cheating!

#90509
Dec 16, 2006 at 7:19pm

On Dec 16, 2006, at 1:21 PM, Peter Castine wrote:
> This is exactly the point I was trying to make.

And you are both right, MSP delivers them at the same time. But the
effect of Luigi’s last example could be the *appearance* of out0
being ignorant of out1, out2, & out3, and so on.

It would only be an issue in feedback situations, which is a lot of
situations in computer music. But I don’t need to tell either of you
that. Just recording it here for posterity. :)

——————-
Nathan Wolek, PhD — nwolek@stetson.edu
Assistant Professor of Music Technology
Stetson University – DeLand, FL

http://www.nathanwolek.com

#90510
Dec 16, 2006 at 7:25pm

On Dec 16, 2006, at 11:41 AM, Luigi Castelli wrote:
> Talking about order of execution between objects
> leads to the same result. Is there anything that a
> programmer could do or not do to make this behaviour
> more consistent?

Luigi;
The only thing I know is to force the user to connect outlet to inlet
a la [tapin~] & [tapout~]. Of course they use a non-MSP connection,
a technique that I believe is undocumented. What info are they
passing? Don’t recall this in the SDK. Anyone else know how this is
done or where to find the info?

This thread is becoming ever more “dev”.
–Nathan

——————-
Nathan Wolek, PhD — nwolek@stetson.edu
Assistant Professor of Music Technology
Stetson University – DeLand, FL

http://www.nathanwolek.com

#90511
Dec 16, 2006 at 11:15pm

Quote: Luigi Castelli wrote on Sat, 16 December 2006 09:41

> 1 – Talking about order of execution within an MSP
> object, and given an MSP object with multiple outlets,
> how is it up to the programmer to decide the output
> order?

It’s not. I didn’t mean to imply this. Output order and order of execution are not the same thing. Inside an object the order that code is executed (for instance what order the outputs are calulated in) is up to the programmer of the object, as appropriate to the situation. This has effectively no relevance to the end-user (max/msp programmer) as long as it performs the dsp correctly. In fact this is exactly what your code examples demonstrate. Sorry for any confusion.

>What I mean is that whether in your perform
> method you entirely process a vector before the other,
> that doesn’t change the actual final output order
> In my understanding the above loops have no bearing to
> the output order of the object. Can someone confirm
> this or not?

Yes, it doesn’t matter, one can essentially assume that they are simultaneous, but it may matter to the programmer in cases where outputs/inputs have dependencies on one another.

> 2 – Talking about order of execution between objects
> leads to the same result. Is there anything that a
> programmer could do or not do to make this behaviour
> more consistent? As far as I know it is still
> something internal to the inner-workings of MSP,
> however maybe I am overlooking something…

I’m not sure about whether one can control the consistency of this. My point is merely that it may matter in a feedback-related situation (as others have mentioned). In pfft~ this problem occurs if you try to use buffer~ objects for storing data that relates to a frame – like phase-accumulating in cartesian geometry using a buffer~ to store vals from one frame to the next. In this case you would want to read out of the buffer before writing in order to get the values from the previous frame. If you write first then you’ll be reading values that you’ve just written in, and it won’t work (although as the recent c74 tutorial on phase vocoders shows a [send~] and [receive~] combination is a more reliable method in this instance, because it doesn’t depend on object positioning on the screen). As with fft operations the main limitation of msp is the difficulty of operating across a frame, or between frames (the paradigm of treating each sample as the same on which most msp objects work is not so appropriate in this context because the position of the sample within the vectro has meaning) using buffer~s in this way may be useful, and hence it is important to understand whether you will incur the delay or not if you use this method.

As I reflect on this though I am not sure that there is any need for this given that send~ and receive~ is more reliable, and for non-delayed examples anything that could require a buffer~ (eg. re-ordering within a frame) can be done with vectral~. I’d be happy to be corrected on any of this though.

Regards

Alex

#90512
Dec 16, 2006 at 11:16pm

Quote: Luigi Castelli wrote on Sat, 16 December 2006 09:41

> 1 – Talking about order of execution within an MSP
> object, and given an MSP object with multiple outlets,
> how is it up to the programmer to decide the output
> order?

It’s not. I didn’t mean to imply this. Output order and order of execution are not the same thing. Inside an object the order that code is executed (for instance what order the outputs are calulated in) is up to the programmer of the object, as appropriate to the situation. This has effectively no relevance to the end-user (max/msp programmer) as long as it performs the dsp correctly. In fact this is exactly what your code examples demonstrate. Sorry for any confusion.

>What I mean is that whether in your perform
> method you entirely process a vector before the other,
> that doesn’t change the actual final output order
> In my understanding the above loops have no bearing to
> the output order of the object. Can someone confirm
> this or not?

Yes, it doesn’t matter, one can essentially assume that they are simultaneous, but it may matter to the programmer in cases where outputs/inputs have dependencies on one another.

> 2 – Talking about order of execution between objects
> leads to the same result. Is there anything that a
> programmer could do or not do to make this behaviour
> more consistent? As far as I know it is still
> something internal to the inner-workings of MSP,
> however maybe I am overlooking something…

I’m not sure about whether one can control the consistency of this. My point is merely that it may matter in a feedback-related situation (as others have mentioned). In pfft~ this problem occurs if you try to use buffer~ objects for storing data that relates to a frame – like phase-accumulating in cartesian geometry using a buffer~ to store vals from one frame to the next. In this case you would want to read out of the buffer before writing in order to get the values from the previous frame. If you write first then you’ll be reading values that you’ve just written in, and it won’t work (although as the recent c74 tutorial on phase vocoders shows a [send~] and [receive~] combination is a more reliable method in this instance, because it doesn’t depend on object positioning on the screen). As with fft operations the main limitation of msp is the difficulty of operating across a frame, or between frames (the paradigm of treating each sample as the same on which most msp objects work is not so appropriate in this context because the position of the sample within the vectro has meaning) using buffer~s in this way may be useful, and hence it is important to understand whether you will incur the delay or not if you use this method.

As I reflect on this though I am not sure that there is any need for this given that send~ and receive~ is more reliable, and for non-delayed examples anything that could require a buffer~ (eg. re-ordering within a frame) can be done with vectral~. I’d be happy to be corrected on any of this though.

Regards

Alex

#90513
Dec 17, 2006 at 12:34am

Quote: Eric Lyon wrote on Sat, 16 December 2006 12:10

> This sounds great in theory, but I’ve never actually seen it done without some C intervention a la gizmo~. Could you show us a pfft~ patch that pitch-scales its input (i.e. multiplies each frequency in the spectrum by a user manipulable constant) using only MaxMSP core objects?
>
> Eric

Ummmm. No – sorry, some people here are talking about by-bin operations (which CAN be done), some people about operations on sinusoidal peaks (which will excite several bins, which need to be treated as a whole and kept in correct phase alignment for “correct” resynsthesis). The latter CAN’T (as I understand it) be done.

What you’re asking for can’t be done with vanilla MSP (afaik) because to transponse properly, you need to be able to detect sinusoidal peaks and then shift them, rather than operate on each bin separately. This isn’t possible in MSP code. The other problem is that for fractional transpositions between 0 and 1 (or -1 and 1 if you allow negative frequencies), or warping where the peaks maybe be overlapped at the output, you need to be able to do a += operation on the output buffer – which I don’t know how to do in MSP code (i don’t think it can be done), as peaks will be pasted on top of one another in these cases.

What CAN be done currently in MSP code is transforms which take no account of sinusoidal peaks, and instead operate on individual bins, but I haven’t done any work with this method, because you are messing up your data quite a lot by doing this, and you can’t do a traditional and accurate transposition, although maybe it might sound great for a bizzare frequency warping effect. I could code something up, but it might take a while. However, I’m pretty confident that this is technically possible, even if hard to achieve.

My approach used to be to do everything for this kind of thing in C (I have an external for frequency warping in stereo for instance that works much like gizmo~), but I have come to realise more and more that MSP is not that far off being able to do these kinds of things. We just need tools to do things like :

–find peaks and give a reasonably accurate amplitude / freq estimate (ideally I’d like to be able to do some calculations only once-per-peak for effeciency reasons, but this would require a variable vector size patcher~/poly~ style object, which is currently not possible, or an object using expr type arguments – which would actually be feasible)

– += ops on a buffer (zeroing the buffer at the start of each frame)

– find max/min vals in a frame

– sum across a frame

etc.

These kind of objects would make more fft-based operations available to the object-programming max user. Maybe at some point I’ll make some of them. Hopefully, though we can get objects at some point in the main MSP distro for this stuff.

I might code up the peak finder with expr based per-peak calculation – that would get us pretty close to the frequency-based stuff, and maybe do a frame-sized buffer with a += input (I don’t have time to get to know how to use buffer~ from an external right now). Then I could make a patch that would do what you want. It would of course be using C (and hence cheating), but the point is that the task would be broken up into stages that individually might be modified or recombined within Max to change the process or design a new one, whereas something like gizmo~ does the whole thing within an external without allowing the user to intervene.

Maybe not the answer you were looking for, but I’d be interested to hear your thoughts….

Alex

#90514
Dec 17, 2006 at 12:44am

> Maybe not the answer you were looking for, but I’d be interested
> to hear your thoughts….

Not the answer I was hoping for, but pretty much the answer I was expecting. Things could be much simplified if pfft~ were generalized to provide magnitude/frequency representation (see my LyonPotpourri external magfreq_analysis~) and oscillator bank resynthesis. F. R. Moore in Elements of Computer Music discusses this dual resynthesis option as a convenient way to effect arbitrary frequency transformations. The only drawback is that under many conditions, oscillator resynthesis is considerably more CPU-expensive than IFFT.

In any case, the consensus here seems to be that while pfft~ has covered some distance, it has not quite crossed the finish line.

Eric

#90515
Dec 17, 2006 at 1:15am

Ok, I am clear now. Thanks Alex.

Intuitevely I would agree that the send~/receive~
combination should take care of any ordering problem,
since it automatically introduces a 1 vector delay.
However I haven’t practically tried it, so I don’t
really know…

The other solution that Nathan suggested appeals to me
greatly as well. Using the same technique as
tapin~/tapout~ might open new possibilities not only
because it solves the FFT buffer reading/writing
problem, but also because allows to write externals
that are able to use the memory buffer that tapin~
provides. As as matter of fact a while ago I started
writing a granular object called graintap~, with the
intent of doing exactly this: reading from tapin~ and
granulating the tapin~ buffer in real time.
The only problem is that I later realized that the
technique to access tapin~ is not documented and an
attempt to ask the C74 folks to share some
tapin~/tapout~ code miserably failed.
I would greatly appreciate if anybody who knew how to
access the tapin~ memory buffer could share the
technique…. or – even better – if the tapout~ code
was included in the next SDK release….

Ciao.

- Luigi

— Alex Harker wrote:

>
> Quote: Luigi Castelli wrote on Sat, 16 December 2006
> 09:41
>
> > 1 – Talking about order of execution within an MSP
> > object, and given an MSP object with multiple
> outlets,
> > how is it up to the programmer to decide the
> output
> > order?
>
> It’s not. I didn’t mean to imply this. Output order
> and order of execution are not the same thing.
> Inside an object the order that code is executed
> (for instance what order the outputs are calulated
> in) is up to the programmer of the object, as
> appropriate to the situation. This has effectively
> no relevance to the end-user (max/msp programmer) as
> long as it performs the dsp correctly. In fact this
> is exactly what your code examples demonstrate.
> Sorry for any confusion.
>
> >What I mean is that whether in your perform
> > method you entirely process a vector before the
> other,
> > that doesn’t change the actual final output order
> > In my understanding the above loops have no
> bearing to
> > the output order of the object. Can someone
> confirm
> > this or not?
>
> Yes, it doesn’t matter, one can essentially assume
> that they are simultaneous, but it may matter to the
> programmer in cases where outputs/inputs have
> dependencies on one another.
>
> > 2 – Talking about order of execution between
> objects
> > leads to the same result. Is there anything that a
> > programmer could do or not do to make this
> behaviour
> > more consistent? As far as I know it is still
> > something internal to the inner-workings of MSP,
> > however maybe I am overlooking something…
>
> I’m not sure about whether one can control the
> consistency of this. My point is merely that it may
> matter in a feedback-related situation (as others
> have mentioned). In pfft~ this problem occurs if you
> try to use buffer~ objects for storing data that
> relates to a frame – like phase-accumulating in
> cartesian geometry using a buffer~ to store vals
> from one frame to the next. In this case you would
> want to read out of the buffer before writing in
> order to get the values from the previous frame. If
> you write first then you’ll be reading values that
> you’ve just written in, and it won’t work (although
> as the recent c74 tutorial on phase vocoders shows a
> [send~] and [receive~] combination is a more
> reliable method in this instance, because it doesn’t
> depend on object positioning on the screen). As with
> fft operations the main limitation of msp is the
> difficulty of operating across a frame, or between
> frames (the paradigm of treating each sample as the
> same on which most msp objects!
> work is not so appropriate in this context because
> the position of the sample within the vectro has
> meaning) using buffer~s in this way may be useful,
> and hence it is important to understand whether you
> will incur the delay or not if you use this method.
>
> As I reflect on this though I am not sure that there
> is any need for this given that send~ and receive~
> is more reliable, and for non-delayed examples
> anything that could require a buffer~ (eg.
> re-ordering within a frame) can be done with
> vectral~. I’d be happy to be corrected on any of
> this though.
>
> Regards
>
> Alex
>

————————————————————
THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
————————————————————

Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around

http://mail.yahoo.com

#90516
Dec 17, 2006 at 1:42am

> The other solution that Nathan suggested appeals to me
> greatly as well. Using the same technique as
> tapin~/tapout~ might open new possibilities not only
> because it solves the FFT buffer reading/writing
> problem, but also because allows to write externals
> that are able to use the memory buffer that tapin~
> provides. As as matter of fact a while ago I started
> writing a granular object called graintap~, with the
> intent of doing exactly this: reading from tapin~ and
> granulating the tapin~ buffer in real time.
> The only problem is that I later realized that the
> technique to access tapin~ is not documented and an
> attempt to ask the C74 folks to share some
> tapin~/tapout~ code miserably failed.
> I would greatly appreciate if anybody who knew how to
> access the tapin~ memory buffer could share the
> technique…. or – even better – if the tapout~ code
> was included in the next SDK release….
>

Hi Luigi,

I’m curious as to what benefit you might get by accessing a tapin~ buffer, rather than just accessing a normal MaxMSP buffer allocated with buffer~. I agree that it would be interesting to see the code to tapin~ and tapout~. Perhaps they bear some vestigial resemblance to Pd’s tabwrite~/tabread~ (or not)?

Eric

#90517
Dec 17, 2006 at 2:45am

Hi,

This is one of the most interesting thread I read from several years.
Thanks for sharing a such upper-erudition!

And while reading, came to me this question about a new plug I’m
writing:
Inside a [pfft~], is there a significant difference between [gizmo~]
versus [fbinshift~] for pitch-shifting a frequency domain?
Qualitative difference in the resultant transposed signal?
Difference in fastness and stability?

All insights welcome!

(I’m running the current 4.6.2 on a quad G5)

Kind regards,
Philippe Gruchet

#90518
Dec 17, 2006 at 4:09am

> Hi Luigi,
>
> I’m curious as to what benefit you might get by accessing a tapin~ buffer, rather than just accessing a normal MaxMSP buffer allocated with buffer~. I agree that it would be interesting to see the code to tapin~ and tapout~. Perhaps they bear some vestigial resemblance to Pd’s tabwrite~/tabread~ (or not)?
>
> Eric

yeah, the idea to bypass the runtime signal enviroment
is tempting, but what would it help? (in the given case)

in the case of tepin/tapout both of these objects have
at least on one side a connection to the “same sample at
the same time” world.

#90519
Dec 17, 2006 at 1:38pm

On Dec 16, 2006, at 8:15 PM, Luigi Castelli wrote:
> I would greatly appreciate if anybody who knew how to
> access the tapin~ memory buffer could share the
> technique…. or – even better – if the tapout~ code
> was included in the next SDK release….

I’ll second that request. The reason I made the suggestion in the
first place was due to consideration I have given to a similar-styled
functionality for a future external project. Example code would be
very helpful.

——————-
Nathan Wolek, PhD — nwolek@stetson.edu
Assistant Professor of Music Technology
Stetson University – DeLand, FL

http://www.nathanwolek.com

#90520
Dec 17, 2006 at 2:53pm

#90521
Dec 17, 2006 at 3:12pm

>
>
> yeah, the idea to bypass the runtime signal enviroment
> is tempting, but what would it help? (in the given case)
>

I’m not sure I understand this. How does tapin~/tapout~ bypass the runtime environment in a way that buffer~/groove~ does not?

> in the case of tepin/tapout both of these objects have
> at least on one side a connection to the “same sample at
> the same time” world.
>
>

Actually I think this is not the case, since there is an enforced feedback delay, the size of a signal vector. Or are you saying something else here?

Eric

#90522
Dec 17, 2006 at 3:18pm

> I’ll second that request. The reason I made the suggestion in the
> first place was due to consideration I have given to a similar-styled
> functionality for a future external project. Example code would be
> very helpful.
>

Hi Nathan,

If you don’t mind my asking, what would you hope to gain from access to tapin~ memory that you could not get from accessing buffer~ memory?

Eric

#90523
Dec 17, 2006 at 6:58pm

On Dec 17, 2006, at 3:18 PM, Eric Lyon wrote:
> If you don’t mind my asking, what would you hope to gain from
> access to tapin~ memory that you could not get from accessing
> buffer~ memory?

Eric:
Well, I have gotten a little frustrated with all the connections that
are necessary for multiple voices in my granular toolkit. You
currently have to connect the signals for parameters to every
[grain.*~] object. So I want to address this in a 2.0 upgrade that I
am currently in the *early* stages of thinking about.

One thing that I have considered would involve a central [grainhub~]
object to which you would connect your algorithms for durations,
sampling increment, etc. Then like the tap twins, you would connect
a single Max cord to any voices that should use its incoming data.

[buffer~] would not quite work for the way I envision it. Although
the named variable passing may be an improvement over hard wired
patching.

The other alternative is to make the [grain.*~] objects polyphonic.
But then you lose the ability to route different grains to different
places.

Anyway, I would love to hear yours (or anybody’s) thoughts on this
scheme. I hope I have explained it well enough.

–Nathan

—–
Nathan Wolek
nw@nathanwolek.com

http://www.nathanwolek.com

#90524
Dec 17, 2006 at 8:13pm

Well, first of all I think that – as a Max/MSP user -
anything you can do with tapin~/tapout~ can be done as
well with buffer~ and some combination of objects
specific to your case such as record~, wave~, groove,
etc… and even send~ and receive~ if you need
feedback.

However I often look at what is the easiest, quickest
and most efficient way to do perform some task. When I
say easier I also mean that allows me to think the
least.

- When I set up a buffer object, I have to think about
the buffer~ name, the size of the buffer, the number
of channels, then I have to instantiate a record~
object, think if I want to loop or not, etc… With
tapin~ I tell it the size of the memory buffer and
connect the output of my sound source to its inlet.
Done. Feedback is a few steps away too, no need of
send~ or receive~ objects. So it’s definetely easier
and probably more efficient too.

- Also there would be a graphical element that could
potentially make a patcher easier to read. When you
see many objects connected to a tapin~ you can easily
guess that they work together. With buffer~ you have
no patchcord connection between objects sharing the
same buffer~, only a name reference.

- At a code level, I am not crazy about the
interleaved nature of the buffer~ interface, which, by
the way, doesn’t really allow for any optimization to
be performed by the reading object, especially if you
want to use cubic interpolation.

- Finally I think it’s always good to have more than
one way of doing something. So expanding your
programming options by learning some more
inner-workings of my all-time favorite program is
always fun ;-)

Having said all of this, I don’t mean in anyway that
buffer~ is not useful or is an object that should be
avoided. It’s a great external without which much of
the MSP functionality would not be possible. I am just
underlining some of the potential reasons why someone
like me would want to know more about the
tapin~/tapout~ scheme.

My 2 cents.

Ciao.

- Luigi

— Eric Lyon wrote:

>
> > I’ll second that request. The reason I made the
> suggestion in the
> > first place was due to consideration I have given
> to a similar-styled
> > functionality for a future external project.
> Example code would be
> > very helpful.
> >
>
> Hi Nathan,
>
> If you don’t mind my asking, what would you hope to
> gain from access to tapin~ memory that you could not
> get from accessing buffer~ memory?
>
> Eric
>
>

————————————————————
THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
————————————————————

Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around

http://mail.yahoo.com

#90525
Dec 17, 2006 at 8:46pm

On Dec 17, 2006, at 3:13 PM, Luigi Castelli wrote:
> – Also there would be a graphical element that could
> potentially make a patcher easier to read.

This would be a big benefit in my hypothetical use of the tap twins
model.

—–
Nathan Wolek
nw@nathanwolek.com

http://www.nathanwolek.com

#90526
Dec 17, 2006 at 9:26pm

On 17 Dec 2006, at 03:45, Philippe GRUCHET wrote:

> Inside a [pfft~], is there a significant difference between
> [gizmo~] versus [fbinshift~] for pitch-shifting a frequency domain?
> Qualitative difference in the resultant transposed signal?

hi philippe
not sure i’m following you here, but pitch-shifting (gizmo~) is not
the same as frequency-shifting (fbinshift~)
so you can’t really compare the two quality-wise etc.
volker

#90527
Dec 17, 2006 at 10:42pm

Peter Castine wrote:
> On 16-Dec-2006, at 17:41, Luigi Castelli wrote:
>
>> In my understanding the above loops have no bearing to
>> the output order of the object. Can someone confirm
>> this or not?
>
>
> This is exactly the point I was trying to make.

But the original question was for the patching side. And the
index~/poke~ examples shows, that the order does matter and has to
matter, and its obviously (luckily) a question of position at the time
the DSP chain is constructed (audio switched on) and not for example
order of creation. But it seems reveresed to the Max order. Could
someone point Joshua or David to the thread please, those who know the
innerds of MSP could shed some light on it, the rest is doomed to
speculation…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#90528
Dec 18, 2006 at 12:16am

>
> [buffer~] would not quite work for the way I envision it. Although
> the named variable passing may be an improvement over hard wired
> patching.
>
> The other alternative is to make the [grain.*~] objects polyphonic.
> But then you lose the ability to route different grains to different
> places.
>

Couldn’t you have user-defined multiple outlets on a polyphonic grain generator and then route to as many different places as desired? Alternatively one could use multiple copies of the grain generator, driven by similar or identical data sets.

>
> Anyway, I would love to hear yours (or anybody’s) thoughts on this
> scheme. I hope I have explained it well enough.
>

Have you tried doing granular synthesis using poly~ driven by JavaScript? It seems like it should be possible, but then again, I don’t know what the overhead would be and if poly~ would be happy with 1000s of active voices.

Eric

#90529
Dec 18, 2006 at 12:35am

>
> However I often look at what is the easiest, quickest
> and most efficient way to do perform some task. When I
> say easier I also mean that allows me to think the
> least.
>

I totally agree with that design philosophy.

> – When I set up a buffer object, I have to think about
> the buffer~ name, the size of the buffer, the number
> of channels, then I have to instantiate a record~
> object, think if I want to loop or not, etc… With
> tapin~ I tell it the size of the memory buffer and
> connect the output of my sound source to its inlet.
> Done.

While I see your point, I think you overplay the attention overhead of using buffer~. Yes, you can specify all the above options but if you just want a monophonic buffer of duration 1 second, you just say “buffer~ mybufname 1000″ and you’re done. Note also that assuming you’re going to write your own external to interact with buffer~ then you don’t have to worry about the intricacies of record~/groove~ either, just the idiosyncracies of your own object :-) And you still have record~ and groove~ if you decide you want to use them after all.

> Feedback is a few steps away too, no need of
> send~ or receive~ objects. So it’s definetely easier
> and probably more efficient too.
>

Now that’s an interesting question – is tapin~/tapout~ more efficient than buffer~/whatever~? That might require a response from a c74 agent for a definitive answer.

> – Also there would be a graphical element that could
> potentially make a patcher easier to read. When you
> see many objects connected to a tapin~ you can easily
> guess that they work together. With buffer~ you have
> no patchcord connection between objects sharing the
> same buffer~, only a name reference.
>

By the same token, things could get confusing if you wanted to connect your tapin~ to other objects in subpatches. I find the name reference about equally helpful to the tapin~/tapout~ cable, visually, but that might be an artifact of writing too much C code.

> – At a code level, I am not crazy about the
> interleaved nature of the buffer~ interface, which, by
> the way, doesn’t really allow for any optimization to
> be performed by the reading object, especially if you
> want to use cubic interpolation.
>

You could enforce mono buffers on your users. Again we’d have to hear from c74 if there is an efficiency difference between using a mono buffer and internal tapin~ memory.

> – Finally I think it’s always good to have more than
> one way of doing something. So expanding your
> programming options by learning some more
> inner-workings of my all-time favorite program is
> always fun ;-)
>

No argument against that!

Eric

#90530
Dec 18, 2006 at 2:00am

#90531
Dec 18, 2006 at 2:20am

Hi Volker,

>> is there a significant difference between [gizmo~] versus
>> [fbinshift~] for pitch-shifting a frequency domain?
>> Qualitative difference in the resultant transposed signal?
> not sure I’m following you here, but pitch-shifting (gizmo~) is not
> the same as frequency-shifting (fbinshift~)

About processing a FFT, you’re right, of course ;-)
Well, my approach here is more musical than technical.

> so you can’t really compare the two quality-wise etc.

My question is about what you’re thinking of these two objects for
just a real-time (no audible latency) ‘transposition’ purpose.
(In frequency or pitch, or both.)
Comparing some subjective results (“the two quality-wise”) and
technical (speed and stability) from several users could be useful.

In my case, the best pitch-shifter (a plug-in) I was able to test
didn’t process an incoming polyphonic&homophonic audio steam in real-
time. (I started first with the internal Apple’s AUPitch in several
AU hosts.)
In the other way, the fastest plug-in I tried out was almost usable
in real-time but *very* noisy. No future for this one!
So, I decided to work with gizmo and fbinshift.

I’m still listening for your… any point of view ;-)

Cheers,
Philippe

#90532
Dec 18, 2006 at 2:58am

#90533
Dec 18, 2006 at 8:50am

Eric Lyon wrote:
> Could you show us a pfft~ patch that pitch-scales its input (i.e.
> multiplies each frequency in the spectrum by a user manipulable
> constant) using only MaxMSP core objects?

Do account mxj~ as MaxMSP core?

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#90534
Dec 18, 2006 at 9:02am

Nathan Wolek wrote:
> The other alternative is to make the [grain.*~] objects polyphonic.
> But then you lose the ability to route different grains to different
> places.

Why? I do that all the time, the multichannel distribution is just part
of the voice…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#90535
Dec 18, 2006 at 11:44am

> > Could you show us a pfft~ patch that pitch-scales its input (i.e.
> > multiplies each frequency in the spectrum by a user manipulable
> > constant) using only MaxMSP core objects?
>
> Do account mxj~ as MaxMSP core?
>

Definitely.

Eric

#90536
Dec 18, 2006 at 12:43pm

Hi,

One of us has slightly changed the name of this topic and inside the same thread, instead of creating a new topic.
I’m the faulty guy, thinking that my question had its place here.

I apologize for the disturbance to the forum readers.
Philippe

#90537
Dec 18, 2006 at 9:01pm

#90538
Dec 18, 2006 at 10:56pm

>> MSP46ReferenceManual, page 169, “freqshift In left inlet”.
>
> hm, am still using 4.5.6 – so no freqshifting with gizmo~ for me,
> i guess…

I’ve just switched to 4.6.2 last week and I’ve still 4.5.7 installed.
You’re right, the ‘freqshift’ message to left inlet of gizmo~ doesn’t exist in 4.5.7.
I can tell you that the two versions of Max works well on a same machine, alternatively if needed, or even together!

Bye,
Philippe

#90539
Dec 18, 2006 at 11:07pm

Quote: Eric Lyon wrote on Mon, 18 December 2006 04:44
—————————————————-
> > > Could you show us a pfft~ patch that pitch-scales its input (i.e.
> > > multiplies each frequency in the spectrum by a user manipulable
> > > constant) using only MaxMSP core objects?
> >
> > Do account mxj~ as MaxMSP core?
> >
>
> Definitely.
>
> Eric
>
—————————————————-

Oh if only this email had come earlier everything might have all gone very differently……..

Anyway, after reconsidering the problem, I became more and more convinced that there must be a way to implement a gizmo~ equivalent (a least the basic transposition bit) in core-MSP objects – I considered mxj~ not to be an option simply because I already knew it was possible using mxj~ because you can can do all the loop and maths stuff in Java if you can do it in C.

At this point my question to Eric is: what’s your interest in a MSP-only implementation – is it just portability, or is it accessiblity to more users? Obviously mxj~ provides the first of these, although the second is more problematic, as although the API is simpler DSP code in text is still going to be too much for many users?

Back to the problem. To cut a long story short, I then spent a long train journey which would have otherwise been quite dull (or at least dull in a different way) coding an MSP only solution with no mxj~. It’s presented below (sorry – no comments or explanation included). However, it’s pretty hopelessly inefficient (takes 20% CPU on my MBP and only runs with an i/o vs of > 512 compared to gizmo~s 3-4%, so it’s of almost no practical value – expect to demonstrate that it can be done, and a for the use of a few interesting MSP techniques to ‘cheat’ things that are not easy to do in MSP code).

Of most relevance to this discussion is a trick using poly~ to force the desired order of execution within a DSP chain. By encapsulating various poke~ and index~ objects within individual poly~s I figured out that it would be possible to chain them together with dummy in~s and out~s in the desired order, and because each one has it’s own internal dsp chain this forces the order to be that in which they are connected (as with normal individual msp) objects. So, this is a viable solution for anyone who wishes to force a certain order of execution to make a patch work. After doing this the position of the poly~ objects on the screen becomes irrelevant to the correct functioning of the patch (I wasn’t actually able to get correct results using positioning).

So, the patch is below. I’ll make a second post with a revised version using an mxj~ class to do the least effecient bit in this version, including the source for the java class.

Sorry about the many separate patches – it was the only way…..

I fear I have sunk to new levels of geekdom…..

>>>>> Save as whatever you like and load as a pfft with any fft size you like (2048 or 4096 recommened) and with an overlap of 4 – audio goes in the left – the transposition multiple in the right< <<<<<<<

max v2;
#N vpatcher 625 79 1374 836;
#P origin -101 -15;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 374 299 68 196617 +~;
#P newex 432 276 39 196617 +~;
#P newex 374 276 39 196617 +~;
#P newex 85 471 108 196617 poly~ FIndFirstPeak 1;
#P newex 575 589 123 196617 buffer~ AmpBuffer 2000;
#P newex 513 124 88 196617 poly~ StoreAmps;
#P newex 335 249 27 196617 – 2;
#P newex 257 249 27 196617 – 1;
#P newex 243 209 53 196617 fftinfo~;
#P newex 134 334 37 196617 ==~ 0;
#N in 2;
#P newobj 212 530 25 196617 in 2;
#N vpatcher 10 59 538 536;
#P window setfont “Sans Serif” 9.;
#P window linecount 0;
#P newex 312 387 31 196617 cos~;
#P newex 231 389 31 196617 cos~;
#P newex 31 325 27 196617 *~;
#P newex 302 291 34 196617 !=~ 0;
#P newex 312 354 45 196617 -~ 0.25;
#P newex 31 391 140 196617 poke~ PhaseCorrect;
#P newex 157 183 135 196617 buffer~ PhaseCorrect 2000;
#P newex 31 137 104 196617 index~ PhaseCorrect;
#P newex 31 292 63 196617 pong~ 1 0 1;
#P inlet 412 70 15 0;
#P newex 302 236 31 196617 !/ 1.;
#P window linecount 1;
#P newex 302 214 27 196617 /;
#P newex 302 181 53 196617 fftinfo~;
#P newex 302 263 27 196617 *~;
#P outlet 312 424 15 0;
#P outlet 231 423 15 0;
#P inlet 316 34 15 0;
#P outlet 366 293 15 0;
#P outlet 461 256 15 0;
#P window linecount 0;
#P newex 366 266 27 196617 -~;
#P newex 366 171 27 196617 -~;
#P newex 383 198 40 196617 trunc~;
#P newex 340 139 27 196617 *~;
#P inlet 383 102 15 0;
#P window linecount 1;
#P newex 461 229 27 196617 +~;
#P fasten 1 0 17 0 388 127 36 127;
#P fasten 11 0 16 0 307 286 36 286;
#P connect 17 0 16 0;
#P connect 16 0 22 0;
#P connect 22 0 19 0;
#P fasten 21 0 22 1 307 317 53 317;
#P fasten 8 0 19 1 321 166 101 166;
#P lcolor 16;
#P fasten 22 0 23 0 36 350 236 350;
#P connect 23 0 9 0;
#P connect 12 0 13 0;
#P connect 13 0 14 0;
#P connect 14 0 11 0;
#P connect 11 0 21 0;
#P fasten 22 0 20 0 36 350 317 350;
#P connect 20 0 24 0;
#P connect 24 0 10 0;
#P fasten 12 2 13 1 335 206 324 206;
#P fasten 4 0 11 1 371 259 324 259;
#P fasten 1 0 2 0 388 127 345 127;
#P fasten 15 0 2 1 417 89 362 89;
#P lcolor 16;
#P fasten 2 0 4 0 345 163 371 163;
#P connect 4 0 5 0;
#P connect 5 0 7 0;
#P connect 1 0 4 1;
#P fasten 4 0 3 0 371 193 388 193;
#P connect 3 0 5 1;
#P fasten 3 0 0 0 388 219 466 219;
#P connect 0 0 6 0;
#P fasten 8 0 0 1 321 62 483 62;
#P lcolor 16;
#P pop;
#P newobj 58 553 164 196617 p CalcShift;
#P newex 11 717 260 196617 fftout~ 1;
#P newex 11 653 27 196617 -~;
#P newex 28 625 27 196617 *~;
#P newex 111 653 27 196617 -~;
#P newex 143 624 27 196617 *~;
#N vpatcher 381 217 633 445;
#P window setfont “Sans Serif” 9.;
#P newex 137 143 27 196617 +~;
#P newex 47 143 27 196617 -~;
#P newex 176 113 27 196617 *~;
#P newex 137 113 27 196617 *~;
#P newex 95 113 27 196617 *~;
#P newex 47 114 27 196617 *~;
#N comlet D:;
#P inlet 112 83 15 0;
#N comlet C:;
#P inlet 64 88 15 0;
#N comlet A:;
#P inlet 47 26 15 0;
#N comlet Complex Result:;
#P outlet 137 167 15 0;
#N comlet Real Result:;
#P outlet 47 167 15 0;
#N comlet B:;
#P inlet 59 55 15 0;
#P connect 3 0 6 0;
#P lcolor 7;
#P connect 6 0 10 0;
#P connect 10 0 1 0;
#P connect 4 0 6 1;
#P lcolor 13;
#P fasten 7 0 10 1 100 136 69 136;
#P fasten 0 0 7 0 64 79 100 79;
#P connect 5 0 7 1;
#P fasten 3 0 8 0 52 46 142 46;
#P lcolor 7;
#P connect 8 0 11 0;
#P connect 11 0 2 0;
#P fasten 5 0 8 1 117 105 159 105;
#P fasten 9 0 11 1 181 136 159 136;
#P fasten 0 0 9 0 64 79 181 79;
#P fasten 4 0 9 1 69 109 198 109;
#P lcolor 13;
#P pop;
#P newobj 11 594 115 196617 p Complex_Multiply;
#P newex 575 609 126 196617 buffer~ PeakCorBuf 2000;
#N vpatcher 10 59 687 296;
#P window setfont “Sans Serif” 9.;
#P newex 409 101 90 196617 poke~ AccumBuf2;
#P newex 309 72 38 196617 sig~ 0;
#P newex 309 102 97 196617 poke~ AccumBuf;
#P newex 512 121 125 196617 buffer~ AccumBuf2 2000;
#N comlet Output:;
#P outlet 109 187 15 0;
#N comlet Imag Val 2:;
#P inlet 247 77 15 0;
#N comlet Imag Val 1:;
#P inlet 210 77 15 0;
#N comlet Lower Bin Index:;
#P inlet 284 77 15 0;
#N comlet Real Val 2:;
#P inlet 173 77 15 0;
#N comlet Real Val 1:;
#P inlet 136 77 15 0;
#N comlet FFT Bin Index:;
#P inlet 352 37 15 0;
#N comlet Output:;
#P outlet 19 187 15 0;
#P newex 136 102 159 196617 poly~ AccumBuf.poly 1 up 2 vs 2;
#P newex 512 101 119 196617 buffer~ AccumBuf 2000;
#P newex 19 127 27 196617 +~;
#P newex 109 166 94 196617 index~ AccumBuf2;
#P newex 19 166 88 196617 index~ AccumBuf;
#P fasten 6 0 2 0 357 61 24 61;
#P connect 2 0 0 0;
#P connect 0 0 5 0;
#P fasten 4 0 2 1 141 123 41 123;
#P fasten 2 0 1 0 24 155 114 155;
#P connect 1 0 12 0;
#P connect 7 0 4 0;
#P connect 8 0 4 1;
#P connect 10 0 4 2;
#P connect 11 0 4 3;
#P connect 9 0 4 4;
#P connect 15 0 14 0;
#P connect 6 0 14 1;
#P fasten 15 0 16 0 314 95 414 95;
#P fasten 6 0 16 1 357 68 454 68;
#P pop;
#P newobj 11 691 260 196617 p SumOut;
#N vpatcher 20 74 302 475;
#P origin 0 -25;
#P window setfont “Sans Serif” 9.;
#P window linecount 0;
#P newex 22 195 32 196617 *~ 2;
#P newex 144 122 58 196617 delay~ 2 2;
#P newex 205 122 30 196617 >~ 1;
#P newex 22 170 34 196617 !=~ 0;
#P newex 118 194 58 196617 delay~ 1 1;
#P inlet 13 7 15 0;
#P outlet 68 352 15 0;
#P newex 68 330 114 196617 poly~ StorePeakCors 1;
#P newex 68 300 27 196617 /~;
#P newex 188 270 64 196617 -~;
#P newex 85 270 32 196617 *~ 2;
#P newex 85 248 27 196617 -~;
#P newex 118 221 32 196617 *~ 2;
#P newex 85 191 27 196617 +~;
#P inlet 85 43 15 0;
#P window linecount 1;
#P newex 85 67 29 196617 log~;
#P newex 188 149 27 196617 *~;
#P fasten 11 0 13 0 18 149 27 149;
#P lcolor 7;
#P connect 13 0 16 0;
#P fasten 7 0 8 0 193 295 73 295;
#P fasten 8 0 9 0 73 317;
#P connect 9 0 10 0;
#P connect 2 0 1 0;
#P connect 1 0 3 0;
#P lcolor 16;
#P connect 3 0 5 0;
#P connect 5 0 6 0;
#P connect 6 0 8 1;
#P lcolor 16;
#P fasten 0 0 3 1 193 186 107 186;
#P fasten 4 0 5 1 123 242 107 242;
#P fasten 1 0 12 0 90 150 123 150;
#P lcolor 16;
#P connect 12 0 4 0;
#P fasten 16 0 4 1 27 216 145 216;
#P lcolor 12;
#P fasten 1 0 15 0 90 93 149 93;
#P lcolor 16;
#P fasten 11 0 9 1 18 323 177 323;
#P lcolor 7;
#P fasten 15 0 0 0 149 144 193 144;
#P connect 0 0 7 0;
#P fasten 11 0 14 0 18 33 210 33;
#P lcolor 7;
#P connect 14 0 0 1;
#P fasten 1 0 7 1 90 93 247 93;
#P lcolor 16;
#P pop;
#P newobj 389 179 109 196617 p PeakCorrection;
#P newex 76 500 94 196617 poly~ ReadPeaks 1;
#P newex 353 440 115 196617 poly~ FindPeakStarts 1;
#P newex 607 407 103 196617 poly~ ZeroPeakBuf 1;
#P newex 212 275 55 196617 ==~ 1023;
#P newex 575 628 110 196617 buffer~ PeakBuf 2000;
#P newex 353 412 31 196617 sah~;
#P newex 321 343 63 196617 selector~;
#P newex 293 275 52 196617 !=~ 1022;
#P newex 374 321 37 196617 ==~ 4;
#P newex 461 252 27 196617 >~;
#P newex 432 252 27 196617 >~;
#P newex 403 253 27 196617 >~;
#P newex 374 253 27 196617 >~;
#P newex 374 25 96 196617 fftin~ 1;
#N vpatcher 10 59 205 247;
#P outlet 49 109 15 0;
#P inlet 78 43 15 0;
#P inlet 49 43 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 49 86 39 196617 +~;
#P window linecount 1;
#P newex 78 64 27 196617 *~;
#P window linecount 0;
#P newex 49 64 27 196617 *~;
#P connect 3 0 0 0;
#P connect 0 0 2 0;
#P connect 2 0 5 0;
#P connect 3 0 0 1;
#P connect 4 0 1 0;
#P connect 1 0 2 1;
#P connect 4 0 1 1;
#P pop;
#P newobj 374 64 79 196617 p AmpsSquared;
#P newex 513 146 84 196617 poly~ ReadAmps;
#P newex 148 363 53 196617 selector~;
#P fasten 3 0 20 0 379 52 16 52;
#P connect 20 0 24 0;
#P connect 24 0 18 0;
#P connect 18 0 25 0;
#P fasten 20 0 23 0 16 620 33 620;
#P fasten 23 0 24 1 33 649 33 649;
#P fasten 26 2 23 1 165 616 50 616;
#P lcolor 16;
#P fasten 3 1 20 1 422 57 51 57;
#P lcolor 10;
#P fasten 3 2 26 0 465 88 63 88;
#P lcolor 16;
#P fasten 23 0 18 1 33 648 66 648;
#P fasten 3 2 16 0 465 88 81 88;
#P lcolor 16;
#P fasten 26 0 20 2 63 584 86 584;
#P fasten 3 2 34 0 465 88 90 88;
#P lcolor 16;
#P fasten 20 1 22 0 121 620 116 620;
#P fasten 22 0 18 2 116 677 116 677;
#P fasten 26 1 20 3 114 578 121 578;
#P fasten 21 0 22 1 148 648 133 648;
#P fasten 13 0 28 0 217 319 139 319;
#P fasten 28 0 34 1 139 420 139 420;
#P fasten 16 0 26 1 81 535 140 535;
#P fasten 20 1 21 0 121 620 148 620;
#P fasten 28 0 0 0 139 358 153 358;
#P fasten 34 0 16 1 90 495 165 495;
#P connect 26 2 21 1;
#P lcolor 16;
#P fasten 21 0 18 3 148 648 166 648;
#P fasten 15 0 34 2 358 464 188 464;
#P fasten 3 2 0 1 465 88 196 88;
#P lcolor 16;
#P fasten 26 3 18 4 216 575 216 575;
#P fasten 3 2 13 0 465 88 217 88;
#P lcolor 16;
#P connect 27 0 26 2;
#P connect 29 1 30 0;
#P connect 30 0 13 1;
#P fasten 3 2 18 5 465 88 720 88 720 679 266 679;
#P lcolor 16;
#P connect 18 1 25 1;
#P fasten 3 2 9 0 465 88 298 88;
#P lcolor 16;
#P fasten 9 0 10 0 298 330 326 330;
#P lcolor 7;
#P fasten 29 1 31 0 262 234 340 234;
#P connect 31 0 9 1;
#P fasten 0 0 11 0 153 397 358 397;
#P connect 11 0 15 0;
#P connect 3 0 2 0;
#P fasten 2 0 4 0 379 192 379 192;
#P lcolor 7;
#P connect 4 0 35 0;
#P connect 35 0 37 0;
#P connect 37 0 8 0;
#P connect 8 0 10 1;
#P fasten 10 0 11 1 326 366 379 366;
#P fasten 13 0 11 1 217 366 379 366;
#P lcolor 14;
#P fasten 3 2 17 0 465 88 394 88;
#P lcolor 16;
#P fasten 1 0 4 1 518 228 396 228;
#P fasten 2 0 5 0 379 203 408 203;
#P lcolor 7;
#P fasten 5 0 35 1 408 273 408 273;
#P fasten 1 1 5 1 542 236 425 236;
#P fasten 2 0 6 0 379 203 437 203;
#P lcolor 7;
#P connect 6 0 36 0;
#P fasten 36 0 37 1 437 298 437 298;
#P fasten 3 1 2 1 422 57 448 57;
#P lcolor 10;
#P fasten 1 2 6 1 566 240 454 240;
#P fasten 14 0 15 1 612 432 463 432;
#P fasten 2 0 7 0 379 203 466 203;
#P lcolor 7;
#P fasten 7 0 36 1 466 273 466 273;
#P fasten 1 3 7 1 590 245 483 245;
#P fasten 1 0 17 1 518 171 493 171;
#P fasten 2 0 32 0 379 102 518 102;
#P lcolor 7;
#P connect 32 0 1 0;
#P fasten 3 2 32 1 465 88 596 88;
#P lcolor 16;
#P fasten 3 2 14 0 465 88 612 88;
#P lcolor 16;
#P fasten 17 0 14 1 394 198 705 198;
#P lcolor 10;
#P pop;

>>>>>>>> Save as AccumBuf.poly in the same folder < <<<<<<<<<
////////////////////////////////////////////////////////////

max v2;
#N vpatcher 10 59 534 374;
#P origin 3 0;
#P window setfont “Sans Serif” 9.;
#P newex 319 158 148 196617 selector~ 2;
#N in~ 3;
#P newobj 388 114 33 196617 in~ 3;
#P newex 319 218 27 196617 +~;
#P newex 319 257 90 196617 poke~ AccumBuf2;
#N in~ 4;
#P newobj 457 114 33 196617 in~ 4;
#P newex 336 193 94 196617 index~ AccumBuf2;
#P newex 257 158 30 196617 -~ 1;
#P newex 48 158 148 196617 selector~ 2;
#P newex 48 32 67 196617 count~ 1 3 1;
#N in~ 5;
#P newobj 257 83 33 196617 in~ 5;
#N out~ 1;
#P newobj 7 257 39 196617 out~ 1;
#N in~ 1;
#P newobj 117 114 33 196617 in~ 1;
#P newex 48 218 27 196617 +~;
#P newex 48 257 84 196617 poke~ AccumBuf;
#N in~ 2;
#P newobj 186 114 33 196617 in~ 2;
#P newex 65 193 88 196617 index~ AccumBuf;
#P connect 7 0 8 0;
#P connect 8 0 3 0;
#P connect 3 0 2 0;
#P fasten 9 0 0 0 262 179 70 179;
#P lcolor 16;
#P connect 0 0 3 1;
#P fasten 9 0 2 1 262 240 90 240;
#P lcolor 16;
#P connect 4 0 8 1;
#P connect 1 0 8 2;
#P fasten 6 0 9 0 262 110 262 110;
#P fasten 7 0 9 0 53 109 262 109;
#P fasten 7 0 15 0 53 58 324 58;
#P connect 15 0 13 0;
#P connect 13 0 12 0;
#P fasten 9 0 10 0 262 179 341 179;
#P lcolor 16;
#P connect 10 0 13 1;
#P fasten 9 0 12 1 262 240 364 240;
#P lcolor 16;
#P connect 14 0 15 1;
#P connect 11 0 15 2;
#P pop;

>>>>>>>> Save as FindFirstPeak in the same folder < <<<<<<<<<
////////////////////////////////////////////////////////////

max v2;
#N vpatcher 20 74 234 332;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N out~ 1;
#P newobj 46 192 39 196617 out~ 1;
#N in~ 3;
#P newobj 131 30 33 196617 in~ 3;
#P newex 79 114 38 196617 sig~ 0;
#P newex 46 144 76 196617 poke~ PeakBuf;
#P newex 46 59 27 196617 *~;
#P newex 46 89 38 196617 sah~;
#N in~ 1;
#P newobj 46 30 33 196617 in~ 1;
#N in~ 2;
#P newobj 91 31 33 196617 in~ 2;
#P connect 1 0 3 0;
#P connect 3 0 2 0;
#P connect 2 0 4 0;
#P fasten 0 0 3 1 96 53 68 53;
#P fasten 3 0 2 1 51 80 79 80;
#P connect 5 0 4 1;
#P pop;

>>>>>>>> Save as FindPeakStarts in the same folder < <<<<<<<<<
////////////////////////////////////////////////////////////

max v2;
#N vpatcher 20 74 281 394;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N in~ 2;
#P newobj 189 46 33 196617 in~ 2;
#N out~ 1;
#P newobj 50 272 39 196617 out~ 1;
#P newex 112 198 30 196617 -~ 1;
#P newex 129 151 31 196617 +~ 1;
#P newex 49 226 85 196617 poke~ PeakBuf;
#P newex 112 174 27 196617 *~;
#P newex 129 129 27 196617 -~;
#P newex 63 78 38 196617 delta~;
#P newex 80 134 30 196617 >~ 0;
#P newex 63 102 41 196617 *~ 0.5;
#N in~ 1;
#P newobj 63 47 33 196617 in~ 1;
#P fasten 0 0 6 0 68 69 54 69;
#P connect 0 0 3 0;
#P connect 3 0 1 0;
#P fasten 1 0 2 0 68 123 85 123;
#P lcolor 16;
#P fasten 8 0 6 1 117 218 91 218;
#P lcolor 16;
#P fasten 2 0 5 0 85 167 117 167;
#P connect 5 0 8 0;
#P fasten 0 0 4 0 68 69 134 69;
#P connect 4 0 7 0;
#P connect 7 0 5 1;
#P fasten 1 0 4 1 68 123 151 123;
#P lcolor 16;
#P pop;

>>>>>>>> Save as ReadAmps in the same folder < <<<<<<<<<
////////////////////////////////////////////////////////////

max v2;
#N vpatcher 46 391 463 609;
#P origin 59 0;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 63 45 50 196617 capture~;
#P newex 300 120 92 196617 index~ AmpBuffer;
#P newex 206 120 92 196617 index~ AmpBuffer;
#P newex 111 120 92 196617 index~ AmpBuffer;
#P newex 300 79 30 196617 -~ 2;
#P newex 206 79 31 196617 +~ 2;
#P newex 111 79 30 196617 -~ 1;
#P newex 12 79 31 196617 +~ 1;
#N out~ 4;
#P newobj 300 145 39 196617 out~ 4;
#N out~ 3;
#P newobj 206 145 39 196617 out~ 3;
#N out~ 2;
#P newobj 111 145 39 196617 out~ 2;
#N out~ 1;
#P newobj 12 145 39 196617 out~ 1;
#P newex 12 120 92 196617 index~ AmpBuffer;
#N in~ 1;
#P newobj 12 36 33 196617 in~ 1;
#P fasten 0 0 6 0 17 66 17 66;
#P connect 6 0 1 0;
#P connect 1 0 2 0;
#P connect 0 0 13 0;
#P fasten 0 0 7 0 17 66 116 66;
#P connect 7 0 10 0;
#P connect 10 0 3 0;
#P fasten 0 0 8 0 17 66 211 66;
#P connect 8 0 11 0;
#P connect 11 0 4 0;
#P fasten 0 0 9 0 17 66 305 66;
#P connect 9 0 12 0;
#P connect 12 0 5 0;
#P pop;

>>>>>>>> Save as ReadPeaks in the same folder < <<<<<<<<<
////////////////////////////////////////////////////////////

max v2;
#N vpatcher 10 59 246 295;
#P window setfont “Sans Serif” 9.;
#P newex 18 150 27 196617 +~;
#P newex 18 121 95 196617 index~ PeakCorBuf;
#N out~ 1;
#P newobj 18 175 39 196617 out~ 1;
#N in~ 2;
#P newobj 152 37 33 196617 in~ 2;
#N in~ 1;
#P newobj 116 37 33 196617 in~ 1;
#P newex 116 62 79 196617 index~ PeakBuf;
#P newex 116 95 31 196617 sah~;
#P fasten 0 0 5 0 121 116 23 116;
#P connect 5 0 6 0;
#P connect 6 0 4 0;
#P fasten 0 0 6 1 121 145 40 145;
#P connect 2 0 1 0;
#P connect 1 0 0 0;
#P fasten 1 0 0 1 121 91 142 91;
#P pop;

>>>>>>>> Save as StoreAmps in the same folder < <<<<<<<<<
////////////////////////////////////////////////////////////

max v2;
#N vpatcher 10 59 212 199;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N in~ 2;
#P newobj 75 28 33 196617 in~ 2;
#N out~ 1;
#P newobj 130 90 39 196617 out~ 1;
#P newex 36 91 88 196617 poke~ AmpBuffer;
#N in~ 1;
#P newobj 36 50 33 196617 in~ 1;
#P connect 0 0 1 0;
#P connect 3 0 1 1;
#P fasten 3 0 2 0 80 67 135 67;
#P pop;

>>>>>>>> Save as StorePeakCors in the same folder < <<<<<<<<<
////////////////////////////////////////////////////////////

max v2;
#N vpatcher 302 382 518 611;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N out~ 1;
#P newobj 49 130 39 196617 out~ 1;
#N in~ 2;
#P newobj 90 50 33 196617 in~ 2;
#N in~ 1;
#P newobj 50 50 33 196617 in~ 1;
#P newex 50 81 91 196617 poke~ PeakCorBuf;
#P connect 1 0 0 0;
#P connect 2 0 0 1;
#P pop;

>>>>>>>> Save as ZeroPeakBuf in the same folder < <<<<<<<<<
////////////////////////////////////////////////////////////

max v2;
#N vpatcher 20 74 223 255;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N in~ 2;
#P newobj 121 77 33 196617 in~ 2;
#N out~ 1;
#P newobj 121 97 39 196617 out~ 1;
#P newex 36 49 38 196617 sig~ 0;
#P newex 36 98 81 196617 poke~ PeakBuf;
#N in~ 1;
#P newobj 71 71 33 196617 in~ 1;
#P connect 2 0 1 0;
#P lcolor 16;
#P connect 0 0 1 1;
#P pop;

/////////////////////////////////////////////////////////////

Alright – that’s the lot.

#90540
Dec 18, 2006 at 11:16pm

As promised here is the revised pfft patch along with the mxj code for the mxj~ class (called SumOut), as mentioned in the previous post.

You still need all the other files in the same directory, you just use this patch as the pfft patch (same deal – any fft size prob 2048 / 4096 are best, and an overlap of 4 (or more but you’ll be lucky if you get it to run and you may need to adjust i/o vector sizes to get it running smoothly without CPU spiking). You’ll also need to compile the mxj~ class on your machine.

I think the most efficient way of doing this with MSP objects only might be to do it all in mxj~, although this is just a hunch, and I’m not going to try it. There are definitely parts of the MSP code that could be done more efficiently in Java, because redundant calculations could be avoided.

Alex

>>>>>>>>>>>>>>> The revised pfft patch < <<<<<<<<<<<<<<<<<<<

max v2;
#N vpatcher 625 79 1366 803;
#P origin -101 -15;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 116 635 71 196617 mxj~ SumOut;
#P newex 11 636 71 196617 mxj~ SumOut;
#P newex 374 299 68 196617 +~;
#P newex 432 276 39 196617 +~;
#P newex 374 276 39 196617 +~;
#P newex 85 471 108 196617 poly~ FIndFirstPeak 1;
#P newex 575 589 123 196617 buffer~ AmpBuffer 2000;
#P newex 513 124 88 196617 poly~ StoreAmps;
#P newex 335 249 27 196617 – 2;
#P newex 257 249 27 196617 – 1;
#P newex 243 209 53 196617 fftinfo~;
#P newex 134 334 37 196617 ==~ 0;
#N in 2;
#P newobj 212 530 25 196617 in 2;
#N vpatcher 10 59 538 536;
#P window setfont “Sans Serif” 9.;
#P window linecount 0;
#P newex 312 387 31 196617 cos~;
#P newex 231 389 31 196617 cos~;
#P newex 31 325 27 196617 *~;
#P newex 302 291 34 196617 !=~ 0;
#P newex 312 354 45 196617 -~ 0.25;
#P newex 31 391 140 196617 poke~ PhaseCorrect;
#P newex 157 183 135 196617 buffer~ PhaseCorrect 2000;
#P newex 31 137 104 196617 index~ PhaseCorrect;
#P newex 31 292 63 196617 pong~ 1 0 1;
#P inlet 412 70 15 0;
#P newex 302 236 31 196617 !/ 1.;
#P window linecount 1;
#P newex 302 214 27 196617 /;
#P newex 302 181 53 196617 fftinfo~;
#P newex 302 263 27 196617 *~;
#P outlet 312 424 15 0;
#P outlet 231 423 15 0;
#P inlet 316 34 15 0;
#P outlet 461 256 15 0;
#P window linecount 0;
#P newex 366 171 27 196617 -~;
#P newex 340 139 27 196617 *~;
#P inlet 383 102 15 0;
#P window linecount 1;
#P newex 461 229 27 196617 +~;
#P fasten 1 0 14 0 388 127 36 127;
#P fasten 8 0 13 0 307 286 36 286;
#P connect 14 0 13 0;
#P connect 13 0 19 0;
#P connect 19 0 16 0;
#P fasten 18 0 19 1 307 317 53 317;
#P fasten 5 0 16 1 321 166 101 166;
#P lcolor 16;
#P fasten 19 0 20 0 36 350 236 350;
#P connect 20 0 6 0;
#P connect 9 0 10 0;
#P connect 10 0 11 0;
#P connect 11 0 8 0;
#P connect 8 0 18 0;
#P fasten 19 0 17 0 36 350 317 350;
#P connect 17 0 21 0;
#P connect 21 0 7 0;
#P fasten 9 2 10 1 335 206 324 206;
#P fasten 3 0 8 1 371 259 324 259;
#P fasten 1 0 2 0 388 127 345 127;
#P fasten 12 0 2 1 417 89 362 89;
#P lcolor 16;
#P fasten 2 0 3 0 345 163 371 163;
#P connect 1 0 3 1;
#P fasten 3 0 0 0 371 208 466 208;
#P connect 0 0 4 0;
#P fasten 5 0 0 1 321 62 483 62;
#P lcolor 16;
#P pop;
#P newobj 58 553 164 196617 p CalcShift;
#P newex 11 664 115 196617 fftout~ 1;
#N vpatcher 381 217 633 445;
#P window setfont “Sans Serif” 9.;
#P newex 137 143 27 196617 +~;
#P newex 47 143 27 196617 -~;
#P newex 176 113 27 196617 *~;
#P newex 137 113 27 196617 *~;
#P newex 95 113 27 196617 *~;
#P newex 47 114 27 196617 *~;
#N comlet D:;
#P inlet 112 83 15 0;
#N comlet C:;
#P inlet 64 88 15 0;
#N comlet A:;
#P inlet 47 26 15 0;
#N comlet Complex Result:;
#P outlet 137 167 15 0;
#N comlet Real Result:;
#P outlet 47 167 15 0;
#N comlet B:;
#P inlet 59 55 15 0;
#P connect 3 0 6 0;
#P lcolor 7;
#P connect 6 0 10 0;
#P connect 10 0 1 0;
#P connect 4 0 6 1;
#P lcolor 13;
#P fasten 7 0 10 1 100 136 69 136;
#P fasten 0 0 7 0 64 79 100 79;
#P connect 5 0 7 1;
#P fasten 3 0 8 0 52 46 142 46;
#P lcolor 7;
#P connect 8 0 11 0;
#P connect 11 0 2 0;
#P fasten 5 0 8 1 117 105 159 105;
#P fasten 9 0 11 1 181 136 159 136;
#P fasten 0 0 9 0 64 79 181 79;
#P fasten 4 0 9 1 69 109 198 109;
#P lcolor 13;
#P pop;
#P newobj 11 594 115 196617 p Complex_Multiply;
#P newex 575 609 126 196617 buffer~ PeakCorBuf 2000;
#N vpatcher 20 74 302 475;
#P origin 0 -25;
#P window setfont “Sans Serif” 9.;
#P newex 22 195 32 196617 *~ 2;
#P newex 144 122 58 196617 delay~ 2 2;
#P newex 205 122 30 196617 >~ 1;
#P newex 22 170 34 196617 !=~ 0;
#P newex 118 194 58 196617 delay~ 1 1;
#P inlet 13 7 15 0;
#P outlet 68 352 15 0;
#P newex 68 330 114 196617 poly~ StorePeakCors 1;
#P newex 68 300 27 196617 /~;
#P newex 188 270 64 196617 -~;
#P newex 85 270 32 196617 *~ 2;
#P newex 85 248 27 196617 -~;
#P newex 118 221 32 196617 *~ 2;
#P newex 85 191 27 196617 +~;
#P inlet 85 43 15 0;
#P window linecount 1;
#P newex 85 67 29 196617 log~;
#P newex 188 149 27 196617 *~;
#P fasten 11 0 13 0 18 149 27 149;
#P lcolor 7;
#P connect 13 0 16 0;
#P fasten 7 0 8 0 193 295 73 295;
#P fasten 8 0 9 0 73 317;
#P connect 9 0 10 0;
#P connect 2 0 1 0;
#P connect 1 0 3 0;
#P lcolor 16;
#P connect 3 0 5 0;
#P connect 5 0 6 0;
#P connect 6 0 8 1;
#P lcolor 16;
#P fasten 0 0 3 1 193 186 107 186;
#P fasten 4 0 5 1 123 242 107 242;
#P fasten 1 0 12 0 90 150 123 150;
#P lcolor 16;
#P connect 12 0 4 0;
#P fasten 16 0 4 1 27 216 145 216;
#P lcolor 12;
#P fasten 1 0 15 0 90 93 149 93;
#P lcolor 16;
#P fasten 11 0 9 1 18 323 177 323;
#P lcolor 7;
#P fasten 15 0 0 0 149 144 193 144;
#P connect 0 0 7 0;
#P fasten 11 0 14 0 18 33 210 33;
#P lcolor 7;
#P connect 14 0 0 1;
#P fasten 1 0 7 1 90 93 247 93;
#P lcolor 16;
#P pop;
#P newobj 389 179 109 196617 p PeakCorrection;
#P newex 76 500 94 196617 poly~ ReadPeaks 1;
#P newex 353 440 115 196617 poly~ FindPeakStarts 1;
#P newex 607 407 103 196617 poly~ ZeroPeakBuf 1;
#P newex 212 275 55 196617 ==~ 1023;
#P newex 575 628 110 196617 buffer~ PeakBuf 2000;
#P newex 353 412 31 196617 sah~;
#P newex 321 343 27 196617 *~;
#P newex 293 275 52 196617 !=~ 1022;
#P newex 374 321 37 196617 ==~ 4;
#P newex 461 252 27 196617 >~;
#P newex 432 252 27 196617 >~;
#P newex 403 253 27 196617 >~;
#P newex 374 253 27 196617 >~;
#P newex 374 25 96 196617 fftin~ 1;
#N vpatcher 10 59 205 247;
#P outlet 49 109 15 0;
#P inlet 78 43 15 0;
#P inlet 49 43 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 49 86 39 196617 +~;
#P window linecount 1;
#P newex 78 64 27 196617 *~;
#P window linecount 0;
#P newex 49 64 27 196617 *~;
#P connect 3 0 0 0;
#P connect 0 0 2 0;
#P connect 2 0 5 0;
#P connect 3 0 0 1;
#P connect 4 0 1 0;
#P connect 1 0 2 1;
#P connect 4 0 1 1;
#P pop;
#P newobj 374 64 79 196617 p AmpsSquared;
#P newex 513 146 84 196617 poly~ ReadAmps;
#P newex 155 363 27 196617 *~;
#P fasten 3 0 19 0 379 52 16 52;
#P connect 19 0 33 0;
#P connect 33 0 20 0;
#P fasten 3 1 19 1 422 57 51 57;
#P lcolor 10;
#P fasten 3 2 21 0 465 88 63 88;
#P lcolor 16;
#P fasten 21 2 33 1 217 619 77 619;
#P lcolor 16;
#P fasten 3 2 16 0 465 88 81 88;
#P lcolor 16;
#P fasten 21 0 19 2 63 584 86 584;
#P fasten 3 2 29 0 465 88 90 88;
#P lcolor 16;
#P fasten 21 1 19 3 140 578 121 578;
#P connect 19 1 34 0;
#P connect 34 0 20 1;
#P fasten 13 0 23 0 217 319 139 319;
#P fasten 23 0 29 1 139 420 139 420;
#P fasten 16 0 21 1 81 535 140 535;
#P fasten 23 0 0 0 139 358 160 358;
#P fasten 29 0 16 1 90 495 165 495;
#P fasten 3 2 0 1 465 88 177 88;
#P lcolor 16;
#P fasten 21 2 34 1 217 619 182 619;
#P lcolor 16;
#P fasten 15 0 29 2 358 464 188 464;
#P fasten 3 2 13 0 465 88 217 88;
#P lcolor 16;
#P connect 22 0 21 2;
#P connect 24 1 25 0;
#P connect 25 0 13 1;
#P fasten 3 2 9 0 465 88 298 88;
#P lcolor 16;
#P fasten 9 0 10 0 298 330 326 330;
#P lcolor 7;
#P fasten 24 1 26 0 262 234 340 234;
#P connect 26 0 9 1;
#P fasten 8 0 10 1 379 340 343 340;
#P fasten 0 0 11 0 160 397 358 397;
#P connect 11 0 15 0;
#P connect 3 0 2 0;
#P fasten 2 0 4 0 379 192 379 192;
#P lcolor 7;
#P connect 4 0 30 0;
#P connect 30 0 32 0;
#P connect 32 0 8 0;
#P fasten 13 0 11 1 217 366 379 366;
#P lcolor 14;
#P fasten 10 0 11 1 326 366 379 366;
#P fasten 3 2 17 0 465 88 394 88;
#P lcolor 16;
#P fasten 1 0 4 1 518 228 396 228;
#P fasten 2 0 5 0 379 203 408 203;
#P lcolor 7;
#P fasten 5 0 30 1 408 273 408 273;
#P fasten 1 1 5 1 542 236 425 236;
#P fasten 2 0 6 0 379 203 437 203;
#P lcolor 7;
#P connect 6 0 31 0;
#P fasten 31 0 32 1 437 298 437 298;
#P fasten 3 1 2 1 422 57 448 57;
#P lcolor 10;
#P fasten 1 2 6 1 566 240 454 240;
#P fasten 14 0 15 1 612 432 463 432;
#P fasten 2 0 7 0 379 203 466 203;
#P lcolor 7;
#P fasten 7 0 31 1 466 273 466 273;
#P fasten 1 3 7 1 590 245 483 245;
#P fasten 1 0 17 1 518 171 493 171;
#P fasten 2 0 27 0 379 102 518 102;
#P lcolor 7;
#P connect 27 0 1 0;
#P fasten 3 2 27 1 465 88 596 88;
#P lcolor 16;
#P fasten 3 2 14 0 465 88 612 88;
#P lcolor 16;
#P fasten 17 0 14 1 394 198 705 198;
#P lcolor 10;
#P pop;

>>>>>>>>>>>>>>>>> The java class code. You’ll need to compile it as SumOut (no tilda btw) < <<<<<<<<<<<<<<<<

import com.cycling74.max.*;
import com.cycling74.msp.*;

public class SumOut extends MSPPerformer
{

public SumOut()
{
declareInlets(new int[]{SIGNAL,SIGNAL});
declareOutlets(new int[]{SIGNAL});

setInletAssist(new String[]{
“Value (sig)”, “Index (sig)”});
setOutletAssist(new String[]{
“Output (sig)”});
}

public void dspsetup(MSPSignal[] ins, MSPSignal[] outs)
{
}

public void perform(MSPSignal[] ins, MSPSignal[] outs)
{
int i;
float[] in = ins[0].vec;
float[] in2 = ins[1].vec;
float[] out = outs[0].vec;
int lower;
float bit;
float interp;

for(i = 0; i < in.length;i++)
{
out[i] = 0;

}

for(i = 0; i < in.length;i++)
{
lower = (int) in2[i];
bit = in2[i] – lower;
interp = in[i] * bit;
if (lower >= 0 && lower < in.length) out[lower] += in[i] - interp;
lower++;
if (lower >= 0 && lower < in.length) out[lower + 1] += interp;

}
}
}

#90541
Dec 19, 2006 at 12:17am

> At this point my question to Eric is: what’s your interest in a
> MSP-only implementation – is it just portability, or is it
> accessiblity to more users? Obviously mxj~ provides the first
> of these, although the second is more problematic, as although
> the API is simpler DSP code in text is still going to be too
> much for many users

Two parts to this. Even though I develop and share my externals, I admit that third party externals make me nervous. For example I noticed some third party externals distributed with expiration dates. And others you never know how soon they will be recompiled whenever MaxMSP needs a new format. I think I mitigated that in my own externals by open-sourcing them, but nevertheless, I still think it’s better when the functionality is inside of MaxMSP. For one thing c74 generally provides a level of documentation of their objects that you’d have to pay me to do for mine :-)

Second part is that if there is a commonly accepted MaxMSP way to solve a problem, it’s more likely to propagate than special solutions via third party externals. The important exception is when third party externals solve a problem that c74 has left open, such that it becomes the de facto community solution.

>
> Back to the problem. To cut a long story short, I then spent a
> long train journey which would have otherwise been quite dull
> (or at least dull in a different way) coding an MSP only
> solution with no mxj~.

This looks very cool – a virtuoso effort. Unfortunately I could not quite get sound out of it. It appears that there are a few missing connections, for example see “FindPeakStarts” as it generates from the code you posted.

In any case the complexity of your (truly impressive) MaxMSP style solution convinces me that at least so far, the best solution is still a custom external like gizmo~ or my pvoc~. Sort of like how the American colonialists when they gave up on trying to figure out the British tax code decided it was simpler to just overthrow the government :)

Cheers,
Eric

#90542
Dec 19, 2006 at 2:35am

On Dec 18, 2006, at 12:16 AM, Eric Lyon wrote:
> Have you tried doing granular synthesis using poly~ driven by
> JavaScript?

But then I couldn’t get sample accurate triggering. And you know all
about that right? ;)

—–
Nathan Wolek
nw@nathanwolek.com

http://www.nathanwolek.com

#90543
Dec 19, 2006 at 5:31am

#90544
Dec 19, 2006 at 8:44am

Quote: Eric Lyon wrote on Mon, 18 December 2006 17:17

> Two parts to this. Even though I develop and share my externals, I admit that third party externals make me nervous.

> Second part is that if there is a commonly accepted MaxMSP way to solve a problem, it’s more likely to propagate than special solutions via third party externals.

These are fair points…

Unfortunately I could not quite get sound out of it. It appears that there are a few missing connections, for example see “FindPeakStarts” as it generates from the code you posted.

This code all regenerates fine for me (the in~ / out~ objects with no connections are there for the order of execution hack – they do actually do something, but don’t need to be connected)

The only problem I had was that the main pfft patch misconnected a couple of outlets from a poly when it wasn’t present, so it may be worth a quick try of making the directory with the downloaded poly in current and pasting the pfft patch again from text into an empty window. Save it as Transpose.pfft and use the wrapper patcher below, which should default to passing audio through unchanged – change the numberbox to change transposition.

Alex

max v2;
#N vpatcher 44 122 390 355;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 249 57 60 196617 loadmess 1;
#P newex 19 41 42 196617 gizmo~;
#P flonum 249 81 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 155 40 81 196617 loadmess loop 1;
#P message 121 41 30 196617 open;
#P newex 121 133 35 196617 *~ 1.;
#P user ezdac~ 121 165 165 198 0;
#P toggle 94 43 15 0;
#N sfplay~ 1 120960 0 ;
#P newobj 121 71 44 196617 sfplay~;
#P newex 121 108 138 196617 pfft~ Transpose.pfft 4096 8;
#P fasten 6 0 1 0 160 64 126 64;
#P fasten 2 0 1 0 99 64 126 64;
#P connect 5 0 1 0;
#P connect 1 0 0 0;
#P connect 0 0 4 0;
#P connect 4 0 3 0;
#P fasten 4 0 3 1 126 157 160 157;
#P connect 9 0 7 0;
#P connect 7 0 0 1;
#P pop;

> In any case the complexity of your (truly impressive) MaxMSP style solution convinces me that at least so far, the best solution is still a custom external like gizmo~ or my pvoc~. Sort of like how the American colonialists when they gave up on trying to figure out the British tax code decided it was simpler to just overthrow the government :)
>
> Cheers,
> Eric
>
—————————————————-

#90545
Dec 19, 2006 at 6:17pm

> > Have you tried doing granular synthesis using poly~ driven by
> > JavaScript?
>
> But then I couldn’t get sample accurate triggering. And you know all
> about that right? ;)
>
>

Owww! Hoist by my own petard. But perhaps one day JavaScript will implement signal inlets and outlets. Never hurts to start planning ahead :=)

Eric

#90546
Dec 19, 2006 at 7:26pm

> The only problem I had was that the main pfft patch
> misconnected a couple of outlets from a poly when it wasn’t
> present, so it may be worth a quick try of making the directory
> with the downloaded poly in current and pasting the pfft patch
> again from text into an empty window. Save it as Transpose.pfft
> and use the wrapper patcher below, which should default to
> passing audio through unchanged – change the numberbox to
> change transposition.
>
>

Thanks for the followup. What you say makes sense, but now with the patch looking good, still no joy. Maybe my ancient TiBook is cursed. It seems every time I pick it up another piece falls off. Anyone else have better luck?

Eric

#90547
Dec 20, 2006 at 4:44am

#90548
Dec 20, 2006 at 9:02am

#90549
Dec 20, 2006 at 9:55am

all (zip and unzipped) versions work fine on winXP …

_y.

#90550
Dec 20, 2006 at 10:04am

> I include three pft patches with a testing wrapper patch
> (Transpose TEST) which will need to be altered to load each one
> (defaults to Transpose2.pfft):
>
> Transpose2.pfft – is the original MSP only version
> Transpose3.pfft – the revised version sent to the list
> Transpose4.pfft – IS A NEW PRACTICAL VERSION
>

3 & 4 work fine. 2 did not work for me. Very impressive! BTW the unconnected gizmo~ in the parent patch appears to be superfluous. Is it there for a reason?

Thanks,
Eric

#90551
Dec 21, 2006 at 5:29am

#90552
Dec 21, 2006 at 10:30pm

Quote: Eric Lyon wrote on Wed, 20 December 2006 03:04

> 3 & 4 work fine. 2 did not work for me. Very impressive!

Cheers. My question to you G4 powerbook guys is – are you using 4.5.x ? My suspicion is that if so, the order of execution index~/poke~ situation has changed between 4.5 and 4.6, and that the one ordering I did not force with poly~ (zeroing the output buffer BEFORE summing the output bins) is executing in the opposite order on 4.5 and hence the output is silence. This is just a hunch, as as previously mentioned the patch worked fine for a friend on a G4 powerbook with max 4.6. If this is the case it essentially (for me) points to the fact that dsp order of execution must be considered unpredictable, unless a clear order dependency is present (output of one object to the input of another).

If not, then sorry no clue…. It’s not like it’s useful as a patch anyway though – more a technical exercise.

>BTW the unconnected gizmo~ in the parent patch appears to be superfluous. Is it there for a reason?

Quick access to the help patch so I could do an auditory comparison when I was debugging the code. I wanted also to compare artefacts, as many c74 objects use double rather than float values internally and so I thought gizmo~ might do a slightly better job (sound-wise – gizmo~ has some other cool features that I didn’t implement). However, I can’t say I could hear much difference in the end myself. I left it so others could judge for themselves..

Alex

#90553
Dec 21, 2006 at 11:10pm

> My question to you G4 powerbook guys is – are you using
> 4.5.x ?

Nope, latest and greatest 4.6.x.

> If this is the case it essentially (for me) points to the fact
> that dsp order of execution must be considered unpredictable,
> unless a clear order dependency is present (output of one
> object to the input of another).
>

Yes, that’s how I understand the situation. Again, *very* nice work.

Eric

#90554

You must be logged in to reply to this topic.