SynthMaker

bug in green data path [0.9.3y]

Archive · 2005 26 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

NothanUmber ·

Hi,

this one is really strange and in order to understand it i'd need a deeper understanding how the "green" data path is working...

First the "receipt":

* load this schematic * select the "PC Keyboard" at the MIDI in component * play some notes * you'll see that the debug int that is connected to the gate output of the note extractor changes it's value from 0 to 1 and the debug that is connected to the delay follows 200 ms later * now unselect the "PC Keyboard" and select any "real" midi in device (I tried any midi in device I have: Emagic MT4, Editol UM-1 and CME UF-8 USB) * now once you play you'll notice that the debug int that is connected to the note extractor changes it's value as expected but the debug int after the delay does nothing at all

From a user perspective this seems to be completely uncomprehensible as it shouldn't matter for the delay how it's input value is generated but perhaps there are some internal optimization tricks that don't expect some of the things I do in that schematic...

Greetings, NothanUmber

malc ·

A strange one indeed. I shall investigate further.

malc ·

I've been looking into this and it appears to be a problem with the timers. As I've mentioned before, these are just Windows timers which use the standard Windows message loop. I think MIDI also uses this loop and for some reason they are interfering. This is similar to the other issue you found (I think it was you) with the timer taking way longer to update than it should. In this case it was the redraws that were affecting things.

It looks like we need a better way to do the timers. I'm looking at this now.

Thanks.

malc ·

I have a solution to this now. I just need to refine and test it a bit more. Shouldn't be much longer.

malc ·

Hi NothanUmber,

I've spent a long time with this now but each solution brought new problems.

The timers are just Windows timers. These are fairly lightweight - not very accurate but very safe. They are fine for doing animations and the like but no good for accurate timing. They use the standard Windows message queues to send their triggers but these are very low priority.

The problem that you're seeing here is caused by the fact that MIDI messages arrive on a separate thread. The trigger is send to the timer and it does actually start. However, you never see any change because Windows timers belong to the thread that they are created in and this one will die as soon as the MIDI message has been processed.

Believe me, I've been through all sorts of alternatives to try and make the timers work with the MIDI threads but all of these lead to more instabilities. We don't want to make the software more unstable at this stage and the timers are not the most important issue on the agenda so we've had to leave them as they are.

If there's a specific effect you were trying to achieve then if you let us know what it is maybe we can find a way to do it for you.

Sorry I can't do more,

Malc.

lalo ·

malc wrote: Hi NothanUmber,

I've spent a long time with this now but each solution brought new problems.

The timers are just Windows timers. These are fairly lightweight - not very accurate but very safe. They are fine for doing animations and the like but no good for accurate timing. They use the standard Windows message queues to send their triggers but these are very low priority.

The problem that you're seeing here is caused by the fact that MIDI messages arrive on a separate thread. The trigger is send to the timer and it does actually start. However, you never see any change because Windows timers belong to the thread that they are created in and this one will die as soon as the MIDI message has been processed.

Believe me, I've been through all sorts of alternatives to try and make the timers work with the MIDI threads but all of these lead to more instabilities. We don't want to make the software more unstable at this stage and the timers are not the most important issue on the agenda so we've had to leave them as they are.

If there's a specific effect you were trying to achieve then if you let us know what it is maybe we can find a way to do it for you.

Sorry I can't do more,

Malc.

🙁

🙁

malc ·

If there's something specific you want to do lalo then please let us know.

The problem we've had is that all the solutions apply to the general case. More specific cases are much easier to deal with.

I wouldn't rule out making this all possible in the future but there are far more important issues that we need to deal with right now. If anyone thinks that timers triggered by MIDI events is top priority then do let us know.

Nu Audio Science ·

Dont you need timers to make sequencers or is this a different type of timer and not the windoze ones ?

lalo ·

Hi guys and malc !

at the moment i'd need it to do a kind of Midi Tap Tempo Plugins....

for this i'd need...

1. Exported VST with the ability to send tempo info to the host (this is in the VST Standhard)

2. Precise Timer to calculate the number of samples between 2 triggers (received from a midi CC button or a midi note)..in the case of midi note i'd need to filter out midi off messages

3. a way to keep an array of subsequent elapsed time values and do a kind of average...

oviously this is not a 'common' priority...so i got (sadly) to do it with ...SE 🙁

hope in the future when other priorities will be solved..this will go again under your and jorge's hands 🙂

lowe guys

lalo

NothanUmber ·

Hi malc,

could you perhaps make me a proprietary "green" delay that takes e.g. an int value, waits for the given time in milliseconds and then outputs it again on the other side. (Or is it possible to build something like that with SM components without using a timer component? I had an "ugly pseudo delay" that just did a very expensive calculation as a workaround which worked but was a little bit unreliably (sometimes the s&h captured the new value sometimes the old one - perhaps I should have made the calculation even more expensive...). The other question is: Do I really need that delay. In order to answer that question one would have to have a closer look inside the "Tune String" component of the WindStringController (here the latest version - haven't changed much in the last time). The "problem" why I introduced the delay is the following: The sample and hold after the delay has to capture the value of the float select that matches the current note event. The problem is that the sample and hold is triggered at the same time as the "AND" component that is prechained to the float select. So the sample and hold always captures the old value as the result for the new one isn't available at that point of time. So the optimal solution would be some kind of synchronization mechanism, a trigger output for each component that sends a signal once the component has computed it's output (perhaps activateable via drop down menu so it doesn't irritate people that don't need it). Just looking whether the output changes is not sufficient as there could be the case that the new output equals the old one. Then some kind of gate that is opened by the note gate and let's pass exactly one changed signal would let pass the next arbitrary changed value - not only one that is computed as a result of a new note on event of the current string.

Greetings, NothanUmber

NothanUmber ·

Just found the "sleep" component which should be sufficient for my plans (will be able to test it with my midi equipment not until next week though). But probably you'll have the same problem with "sleep" as with "timer" as both will make use of the windows timer. (Was introducing a separate windows timer instance per timer component that is independent of the one you use for midi introduce the instabilities you were speaking of? Have you tried to introduce a global "SM time", that is synchronized with the current unix time stamp in ms (updated by a windows timer that belongs to the singleton SM time object which is created when SM starts and "lives" until the program terminates. That way one could also easily get the current time e.g. for randomization stuff as a side effect 😉 ). This singleton "SM time" could then be delegated and used in all cases where a resolution of one ms is sufficient. So you won't have many timers that interfere with each other and the advantage to be able to have a common synced clock for all green (edit: and midi) components (good for synchronization purposes) - much like it is the case with the sample rate for the white ones. Presumably the SM world isn't as straightforward as I think, but from my limited point of view that would make sense 🙂

Greetings, NothanUmber

P.S.: An idea for the synchronization: A component with a corresponding pair of inputs and outputs (automatically created as it's the case e.g. for the multiplexer but on both sides) that only let's pass all incoming data in one step (and delay the others until the last arrived) would be nice. Then one wouldn't need explicit triggers as suggested above, everything would be done transparent for the user.

malc ·

@ NAS first,

You do need a timing mechanism for squencers but the windows timers are not accurate enough. The timers we have are really meant for animation or applications that don't need precise timing. Sequencers would need something different.

@ lalo,

For similar reasons to those stated above you wouldn't get an accurate enough result from using windows timers. You'd need something that syncs with the host noting the sample position as you tap.

Can you do this with SE then? I'd be interested to know how you'd do it.

@ NothanUmber,

Sleep doesn't use a timer, it just halts the executing process. It's better than a timer for accuracy but it can be out by around a millisecond. It's not so good for long delays.

The problem with timers isn't the number of them, it's the way they work. Windows timers insert messages into the windows message queue to say that the required time has elapsed. However, these messages are handled with very low priority so if there are other messages to be processed they will get handled first. This can introduce big delays.

The problem with timers and MIDI is to do with multithreading. If you start a timer in one thread it will send it's messages to that thread only. When the thread dies so does the timer. So if you trigger a timer from a MIDI event the timer will be created in the MIDI thread and not in the main application thread.

I tried creating timers that ran in their own threads but this introduces many possibilities for syncronisation bugs that we don't have time to deal with at the moment.

I had a look at your schematic but I couldn't really understand the problem. Would you be able to explain the issue again to me.

lalo ·

malc wrote: @ lalo,

For similar reasons to those stated above you wouldn't get an accurate enough result from using windows timers. You'd need something that syncs with the host noting the sample position as you tap.

Can you do this with SE then? I'd be interested to know how you'd do it.

Yes i can do it in SE using a custom module programmed by Chris Kerry using ASM (is very efficient and use almost 0 cpu)...

what i'd need is not to sync to the host....but sync the host to the Tap Tempo plugin....wich is doable in Bidule (the host i use for livesets)...and its a feature supported by VST SDK

thanx

lalo

NothanUmber ·

malc wrote: The problem with timers and MIDI is to do with multithreading. If you start a timer in one thread it will send it's messages to that thread only. When the thread dies so does the timer. So if you trigger a timer from a MIDI event the timer will be created in the MIDI thread and not in the main application thread.

Hm, and if you would extend the criteria when to terminate a (midi) thread to not only watching for the presence of midi events but also currently running timers inside that thead? Then the thread wouldn't be suspended and the timer should continue to work that way?!?

malc wrote: I had a look at your schematic but I couldn't really understand the problem. Would you be able to explain the issue again to me.

Thanks for having a look at it! Tried to make you a simple schematic to point out the problem and - ran into another bug that immediately crashes SM 🙁 In order to reproduce the crash just connect the "value A" to the trigger input of the "sample and hold A" or the delay output of the "Green Int Delay" to the trigger input of the "sample and hold B". The initial purpose of this schematic was to show you that the "sample and hold A" only captures the sum of the last value of "value A" + 1 instead of the current one + 1 because the calculation of the new value wasn't finished before the sampling takes place. The second variant "B" with the delay in the middle tries to change that behaviour by adding a delay in between (as said above perhaps a "sleep" would be better here.) (Couldn't test the code because of the crashing bug so I don't know whether it demonstrates the intended behaviour or not but perhaps it nontheless gives you a better impression on what I think the problem could be in my WindStringController)

Greetings, NothanUmber

malc ·

Thanks NothanUmber.

Does the schematic crash or does it just hang? For me it just hangs waiting for the huge number of calculations to complete.

The green data works in a single process. Calculations occur according to triggers and the order of calculations is determined by the order of the links. The only way that one event can occur before another is if the link order dictates so.

I made a similar schematic to the one you sent me and everything behaves as I'd expect. Would you mind modifying this one in order to demonstrate the problem.

[old link]

Thanks,

Malc.

NothanUmber ·

Hi,

malc wrote: Does the schematic crash or does it just hang? For me it just hangs waiting for the huge number of calculations to complete.

You're right, it only hangs. But are you sure that it takes that long to calculate a few hundred pows and logs? (In my former WIndStringController the "ugly delay" (which used the same "math" delayed my computer only for a fraction of a second)

malc wrote: The green data works in a single process. Calculations occur according to triggers and the order of calculations is determined by the order of the links. The only way that one event can occur before another is if the link order dictates so.

I made a similar schematic to the one you sent me and everything behaves as I'd expect. Would you mind modifying this one in order to demonstrate the problem.

Yes, that's what I wanted to build. As it seems, the problem is more difficult (and probably ugly to debug, sorry in advance...😉 ) it seems to have to do with the fact, that the input values that are fed into the sample and hold come from outside the module. Here a schematic based on your one with four variants. The one with a delay and external string components (the upper one) behaves completely inconsistently on my computer (just change the value on the lower left from "1" to "2" (or any other even and uneven numbers= and forth an back and you'll see that the value is not updated every time in the upper case. In the case of the WindStringController things are even more complicated as we have some kind of feedback path between the inputs the output of the sample and hold (but I don't know whether that matters in that case). Here introducing a delay helped a little while in the case of this example it obviously does the opposite (the strange thing is that the lower one with a delay but internal textstrings works as expected...)

Greetings, NothanUmber

P.S.: Just realized that you can even throw out the unnamed modules with the sleeps inside that I copied from your schematic in order to simplify things , the bug is also reproducable without them.

infuzion ·

NothanUmber wrote: ...the problem is more difficult (and probably ugly to debug, sorry in advance...😉 ) it seems to have to do with the fact, that the input values that are fed into the sample and hold come from outside the module.

Ok, I thought I was going loopy when I tried to do some outside processing on a drag/click edit I was working on, & the internal & external results weren't matching. Things mostly cleared up when I changed the Redraw trigger to one of the external inputs rather than the DragY.

NothanUmber ·

Hi again,

my "analysis" from yesterday did not hit the right spot, I was fooled by "the real bug" that seems to be either in the sample and hold or in green data path (then we'd be on topic again, yeah 🙂 ) (or somewhere completely different, whoknows...) Here another schematic that does exactly what one expects it to do: It outputs "even" for even values and "uneven" for uneven ones. In order to produce the bug do the following:

* disconnect the wires between the "value" and the "sample and hold" as well as between the "value" and the "test even" component. * Change the "value" to any uneven number * First reconnect the wire between "value" and the trigger input of the sample and hold (the order between this and the next point is important) * Then also rewire the "value" back to the "test even" component

Now the "logics" seem to be reversed: You'll get the "even" message for uneven values and vice versa until you disconnect and reconnect the wire between the "value" and the "sample and hold" component again.

Greetings, NothanUmber

malc ·

Hi NothanUmber,

I tried your other schematic (the one you posted yesterday). I swapped the two links at the inputs to the 'external event-strings and delay' module and it worked fine. This is because the link order needs to be such that the trigger input is hit after the int input.

I'll have a look at this new one and get back to you.

NothanUmber ·

Another sidenote: The logics are not reversed, you simply get the "eveness infos" for the last value instead of the current one. Could it be the case that SM generates different internal programs depending on the order of the rewireing? (in the one case a program that first triggers the sample and hold and then calculates a new value (wrong) and in the other case one that calculates the value before triggering the sample and hold (right))?)

Greetings, NothanUmber

NothanUmber ·

malc wrote: I tried your other schematic (the one you posted yesterday). I swapped the two links at the inputs to the 'external event-strings and delay' module and it worked fine.

That's like fighting fire. Sometimes introducing a new bug helps to eliminate the old one 😉 (Just have a look inside the component, I think the wires should have been right. "Fixing" the old schematic is simple: Just deconnect and reconnect the wire between the value in the lower left and the trigger of the upper test component once and it works correctly from now on. Or a better idea: Don't waste your time on the old schematic, the new one should be much easier to trace down the bug 🙂 )

Greetings, NothanUmber

malc ·

Ok I had a look at the new one. The behaviour you're describing is exactly what I'd expect. The logic is reversed because the link order needs to be the other way round.

If you connect to the sample and hold first then when the value changes the sample and hold will get the first trigger and this will send a chain of events back up to the String Select. The string select will then return the last value that was used as the boolean input will not have changed since it was last asked for a value. This will result in the even/uneven state for the previous value being returned to the sample and hold.

The link to the test even component will then get the trigger and the String Select will have it's state switched. But this doesn't send a trigger to the right it only changes the value that is returned when it is next asked fro it's value.

So to get the effect you want you need the links to be connected the other way round. Link order can be very important in some schematics.

NothanUmber ·

malc wrote: Ok I had a look at the new one. The behaviour you're describing is exactly what I'd expect. The logic is reversed because the link order needs to be the other way round.

Thanks for having a look! Is there a way to determine which "link order" is active in a certain schematic (other then trying it out)? If not please offer something like that or newcomers will go nuts and even for experienced people it's awful to debug if you can have several schematics that look absolutely the same but do entirely different things.

I'll post some proposal into the ideas section.

Greetings, NothanUmber

malc ·

There is indeed a way to determine the link order. Have a look at the follwoing link for details on this:

[old link]

NothanUmber ·

Oh, perhaps sometimes I should read the manual... 😮 Cool!

Greetings, NothanUmber

NothanUmber ·

Just saw that the link order was indeed wrong on several places in my WindStringController. Now there is a good chance that everything could be working as expected when I try it next time at the weekend 🙂 Thanks again for all the support!

Greetings, NothanUmber

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.