• ddw_music

    @impression What if you store your chords in the format:

    note0 vel0 dur0 note1 vel1 dur1 ...

    That is, don't bother with clumping all the note numbers together at all -- interleave them from the start.

    Then your iterator can "get $1 3" and increment by 3 each time.

    Maybe an example later when I have a bit more time.

    hjh

    posted in technical issues read more
  • ddw_music

    @impression said:

    I can’t really use [clone] for my synth setup.

    I'm curious, why is that? There's probably a solution. If it's the first time you're using [clone], I can see how it might be tricky to figure out, but "haven't figured it out" may not be the same as "can't use it."

    I’d basically need to generate my own note on and note off messages manually.

    That's probably the [makenote] object.

    hjh

    posted in technical issues read more
  • ddw_music

    For computer-to-computer communication, Open Sound Control over a LAN may be easier than MIDI (as a transport device).

    hjh

    posted in technical issues read more
  • ddw_music

    BTW though: I hadn't looked closely at the sources earlier, so I was conjecturing. Looked just now. If we take, say, "unpack" as an example of an object that typically has multiple outlets, and see how it responds to a list:

    in m.connective.c:

    static void unpack_list(t_unpack *x, t_symbol *s, int argc, t_atom *argv)
    {
        t_atom *ap;
        t_unpackout *u;
        int i;
        if (argc > x->x_n) argc = (int)x->x_n;
        for (i = argc, u = x->x_vec + i, ap = argv + i; u--, ap--, i--;)
        {
            t_atomtype type = u->u_type;
            if (type != ap->a_type)
                pd_error(x, "unpack: type mismatch");
            else if (type == A_FLOAT)
                outlet_float(u->u_outlet, ap->a_w.w_float);
            else if (type == A_SYMBOL)
                outlet_symbol(u->u_outlet, ap->a_w.w_symbol);
            else outlet_pointer(u->u_outlet, ap->a_w.w_gpointer);
        }
    }
    

    ... where each output value calls either outlet_float() or outlet_symbol() or outlet_pointer(). It'll move to the next outlet when the outlet_ function returns.

    m_obj.c:

    void outlet_float(t_outlet *x, t_float f)
    {
        t_outconnect *oc;
        if(!stackcount_add())
            outlet_stackerror(x);
        else
            for (oc = x->o_connections; oc; oc = oc->oc_next)
                pd_float(oc->oc_to, f);
        stackcount_release();
    }
    

    OK, check for stack overflow and then call pd_float() for each connection from that outlet. (_bang, _symbol, _pointer are similar.)

    m_pd.c:

    void pd_float(t_pd *x, t_float f)
    {
        if (x == &pd_objectmaker)
            ((t_floatmethodr)(*(*x)->c_floatmethod))(x, f);
        else
            (*(*x)->c_floatmethod)(x, f);
    }
    

    Get a reference to the next object's floatmethod function, e.g. and call it: a method handler --> an iterator over connections --> a connection handler --> another object's method handler, at which point the cycle recurs.

    So the way that it backtracks seems to be simply that e.g. outlet_float() returns and the method handler resumes where it left off: normal tree-traversal recursion using C's call stack (without data return, as these are all void).

    Gotos do appear in the Pd source but it looks like the vast majority of these are used for early-exit or for input validation before performing some operation -- goto error, goto fail, goto doit, etc. I don't see them in the message-passing functions. (What I also don't see in the message-passing functions is an explicit stack of objects/connections -- stackcount_add() is just a global counter, no real push/pop -- so if I guessed that pd keeps its own stack of objects visited, that was a wrong conjecture.)

    hjh

    posted in technical issues read more
  • ddw_music

    @impression said:

    Lets say I want 32 polyphony, that would be an insane effort.

    IMO this all comes down to data structure design. A bad design will require insane effort. A good design will scale up to any amount of polyphony you need.

    What's the input? From your MIDI keyboard?

    What do you need to do with the notes afterward? Just spit the MIDI events back out, or quantize them, etc etc?

    [text sequence] is a nice way to store note sequences. Each entry starts with the time delta before this note, followed by the note data, which may be anything you want (e.g., note number, sustain time, velocity, suitable for [makenote] when playing back).

    It would really help if you could explain the goal, to help design a way to un-insane the insane effort.

    hjh

    posted in technical issues read more
  • ddw_music

    @oid Agreed, yes, let's move on.

    hjh

    posted in technical issues read more
  • ddw_music

    @oid Thanks. I think this confirms that you and I are talking at orthogonal purposes. What I've been trying to say is that one can use a linked list to implement a stack and use that stack to organize gotos into procedure-call behavior, or one could use a dedicated Stack data type and implement the same behavior using only structured control flow, and the behavior in both cases is that of a procedure call. Pointing out that the one is just a linked list and gotos doesn't make it not procedure-call behavior.

    I.e. we're focusing on different levels of abstraction. Or, in answer to your earlier question, "are they really procedure calls or is that just conceptual?" -- I'm mainly interested in the conceptual aspect, yes, and you're mainly interested in the concrete implementation. So any confusion/frustration stems from talking past each other.

    hjh

    posted in technical issues read more
  • ddw_music

    @jameslo said:

    Hmm, that's interesting, have you considered Java's use of gotos? :)

    Nice one :grin: well, there's a time and place for everything. There are gotos in SuperCollider's C++ codebase, iirc mainly in the long switch blocks in the bytecode interpreter. I guess... it's like second inversion triads. In conventional harmony, there are a few legit ways to use them, but otherwise, don't; same for gotos.

    hjh

    posted in technical issues read more
  • ddw_music

    @oid Perhaps I owe an apology for an excessively critical post -- I can see that I was a bit too heated.

    Perhaps part of the problem in this thread is trying to find terminology without agreeing on terminology -- I'm using some terms in a way that you disagree with, or might be misunderstanding to some extent, and vice versa.

    I think some of the things that have been said in this thread are misleading in some ways. Message-passing along patch cables isn't a goto -- it just isn't. Gotos have been discouraged for a long time because they're messy. Overuse produces spaghetti code, and goto-heavy code is hard to debug because gotos are history-less -- there's no backtrace to see how you got into a bad place. Pd message passing keeps all the history until you reach the end of the chain. Stack traces are a characteristic of procedure/function calls -- not a characteristic of gotos.

    I do see that Pd doesn't use a stack for returning data to a caller. But there have been some statements that seem to go beyond that, for instance, "without a return stack we can't actually return" -- that's true, we can't return data but execution can and does return back to an object that was previously touched.

    Again, probably a lot of this is about terminology -- for example, when I used the term "procedure call," that isn't the normal way that Pd users talk about message passing, so there's a bit of "well that doesn't make sense"... but I think the behavior of Pd control objects lines up very closely with the behavior of procedure calls, and I think some of the resistance to this idea has been overstated to some extent or another. (Likewise, to suggest that you totally rejected the idea of a stack is a considerable overstatement -- which I certainly have to retract.)

    So I am sorry about getting a bit punchy there -- at the same time, I'm a bit bewildered why so many things I've tried to say in this thread seem to have gotten a "well, no, that's not it" where I guess I hoped for a "hmm, that's interesting, have you considered?"

    hjh

    posted in technical issues read more
  • ddw_music

    @impression The first step is to work out the data structure. If it's my project, I'd go with one of these approaches:

    • Save MIDI note on and note off directly, without much analysis. Playback logic would then be very similar to MIDI polyphonic playback.
    • Or, use note-off to calculate the sustain duration of the preceding note that matches the note-off pitch. It's harder to calculate that, but then you get a list of notes with parameters "note number, velocity, sustain duration" -- may be more useful for algorithmically manipulating the notes.

    What are your thoughts about how to play back the sequence?

    hjh

    posted in technical issues read more

Internal error.

Oops! Looks like something went wrong!