![]() |
![]() ![]() ![]() ![]() ![]()
|
next newest topic | next oldest topic |
Author | Topic: Luddy - trigger question | |
cristian_vogel Member |
![]() ![]() ![]() You seem to be the person to ask Its simple but causing me a lot of headache I have a sequencer that is triggering a sample I want to hold the !KeyDown if the velocity is 0 , so we hear the whole sample, until the next positive velocity and !KeyDown event - a legato for sequencers, with the sustain dependent on whether the next step has a positive velocity or not. I just can't seem to find the best way of doing this reliably. [This message has been edited by cristian_vogel (edited 02 May 2009).] IP: Logged | |
Luddy Member |
![]() ![]() ![]() Hi Cristian,
oneshotgate := ((!KeyDown eq: 1) * (!KeyVelocity eq: 0)). normalgate := ((!KeyDown eq: 1) * (!KeyVelocity ne: 0)). (oneshotreset <+ (((trigger ramp: duration s + 1 ms) eq: 1) + normalgate)) If you call this block this way: OneShotTrigger value: <sample duration in seconds>. then it will generate one-shot triggers in response to zero-velocity keydown events. a non-zero velocity keydown event turns off the trigger. My guess is that this isn't quite good enough. you probably also want to generate a normal gate from the non-zero velocity keydowns. That hurts my head right now, haha. I gotta think some about it. What you want to do in that case is use (!Keydown eq: -1) * (!KeyVelocity ne: 0) to reset the one-shot trigger. This is necessary because you need the little 5ms voice-stealing period to create a gap in the whole output -- a moment when the whole gate is zero (or negative). -Luddy [This message has been edited by Luddy (edited 01 May 2009).] IP: Logged | |
pete Member |
![]() ![]() ![]() Sorry if this is a private conv I'm not sure if I understand what you want but if by velocity you meant !KeyVelocity, !KeyDown + (!KeyVelocity eq: 0) If velocity was just a hot param you could use !KeyDown + (!KeyDown sampleAndHold: ( !Velocity eq:0)) !Keydown has a single minus one pulse when triggered so this will retrigger on the next note after the long held note. If you don't want this to retrigger you can use (!KeyDown abs) + (!KeyDown sampleAndHold: ( !Velocity eq:0)) Sorry if I've not understood the requirement. [This message has been edited by pete (edited 02 May 2009).] IP: Logged | |
Luddy Member |
![]() ![]() ![]() Hi Pete, >> !KeyDown + (!KeyVelocity eq: 0) Hmm, doesn't this begin life as a 1 value? I.e., isn't the gate open when you first run the sound? -L IP: Logged | |
cristian_vogel Member |
![]() ![]() ![]() thanks for putting some thought into this I found that one sequencer then triggering a second single-step "trigger" sequencer was the only way to pass-thru the values of pitch and velocity , but masking the continuous !KeyDown messages sent by a sequencer. This allows to hold notes/samples/gates until a non-zero velocity step comes in. The most logical was to have the second sequencer dependent on a !KeyDown * (!KeyVelocity ne: 0) I tried this in the Step Field , and in the Gate (sequencer reset) field, but this was giving me erratic behaviour - now I understand form Luddy's post, that there is a -1 coming in first and this was probably triggering the logic twice and getting all muddied. It seems that the !KeyDown and the !KeyVelocity values don't seem to happen at the same time also. Plus, the step/ duration / rate / dutyCycle relation/brainache was probably introducing all sorts on weird behaviour - I WISH THE SEQUENCER WAS MORE STRAIGHTFORWARD ( no pun intended ) I even reached a point of building the whole sequencer in CapyTalk, building on Luddy's scripted version at the Tweaky. But the dutyCycle for the gate is useful, and I couldn't figure how to do this simply in a CapyTalk array sequencer.. Anyhow, I'll try your code tomorrow and let you know how I get on. IP: Logged | |
Luddy Member |
![]() ![]() ![]() Hi Cristian, Maybe Pete can correct or add to this, but I think the exact sequence of events on a note-on event are: !KeyDown goes to -1 for 5ms. !KeyDown goes to +1 so long as the note-off event has not yet arrived I hadn't thought about it before Pete's post, but it makes sense I guess that !KeyVelocity and !KeyPitch would keep their previous values even after a note-off event, for the same reason that they keep their values during a note-steal. -Luddy IP: Logged | |
pete Member |
![]() ![]() ![]() Hi Again >>>> !KeyDown + (!KeyVelocity eq: 0) >>Hmm, doesn't this begin life as a 1 value? I.e., isn't the gate open when you first run the sound? Yes of course you're right Luddy and to over come this you would need !KeyDown + (!KeyVelocity eq: 0) + (!KeyDown setReset: 0) -1 Hi Cristian, think I see what you are trying to achieve. You want a sequencer that will play notes of a sample player and to restart the sample on every note, unless you have programmed in zero velocity. In this case the pitch will move, the velocity will stay the same, but the sample will not go back the the beginning but will instead continue from where it is. You are not interested in the on duration of the note as you have set fade out time on the sample player to 1 day . Please tell me if I have this right? To achieve this you don't care when the !KeyDown returns to zero as long as it does not go to one at any time when a zero velocity note comes along. Luddy is correct that at trigger !KeyDown goes to minus one for a moment when trigger comes along. I thought it was for one tick (1 ms) instead of 5 ms but I'm not sure on this one. Any way If we use !KeyDown as it is and add one when the zero comes along the minus one will make a trigger when we don't want it. If we use !KeyDown abs the the trigger will happen (as Luddy says) before the zero velocity has come along and the trigger will get through. If we use !KeyDown clipTo01 instead, we remove the minus one and the leading edge trigger will now be 1 ms (or 5ms) latter. So you would need (!KeyDown clipTo01) - (!KeyVelocity eq:0) But there seems to be a feature in the sample player to make the steal work correctly. ((!KeyDown clipTo01) - (!KeyVelocity eq:0)) clipTo01 also it seems that the velocities don't work correctly with 11011101 instead I used {0.9} {0.9} {0.9} {0.0} {0.9} {0.9} {0.9} {0.0} which seemed to work. Don't know why? This should work but I think you will need to do a bit more work to make the velocity hold during the held note. but sampleAndHold: will do this hope it helps [This message has been edited by pete (edited 02 May 2009).] IP: Logged | |
pete Member |
![]() ![]() ![]()
IP: Logged | |
SSC Administrator |
![]() ![]() ![]() !KeyVelocity * (1 + !KeyDown) See 'non reattacking sequencer.kym' [This message has been edited by SSC (edited 02 May 2009).] IP: Logged | |
cristian_vogel Member |
![]() ![]() ![]() the secret life of triggers! thanks so much, armed with all this knowledge, I think can acheive the exact behaviour I am looking for IP: Logged | |
Luddy Member |
![]() ![]() ![]() >> !KeyVelocity * (1 + !KeyDown) But this produces a value of 0 when velocity is 0. As I understand it, Cristian wants a longer-than-usual (non-zero) gate in the case of velocity = 0. -Luddy [This message has been edited by Luddy (edited 03 May 2009).] IP: Logged | |
SSC Administrator |
![]() ![]() ![]() Hi Luddy! >> !KeyVelocity * (1 + !KeyDown) The idea of this expression was to trigger the sample when !KeyVelocity > 0 and to defeat the sequencer from retriggering it by !KeyDown when !KeyVelocity = 0. Using !KeyVelocity alone would be sufficient except in the case of two or more stages in a row being switched on. In order to retrigger, the gate value has to briefly go to zero first. (1 +!KeyDown) is 0 when !KeyDown goes to -1 during voice stealing, 1 when the key is up, and 2 when the key is down. The end result is a sequencer where stages with zero velocity do not retrigger the sample, but they also do not silence the sample; the sample continues to play until the next non-zero velocity stage. (This was based on Pete's summary of his own understanding of what Cristian was describing but maybe we misunderstood the original request?) IP: Logged | |
Luddy Member |
![]() ![]() ![]() >> Hi Luddy! Hi there! >> >> !KeyVelocity * (1 + !KeyDown) > The idea of this expression was to trigger the sample when !KeyVelocity > 0 and to defeat the sequencer from retriggering it by !KeyDown when !KeyVelocity = 0. The problem I see is that the expression must also *trigger* the sample to begin with, when !KeyDown occurs and !KeyVelocity = 0 for the first time. In other words, if the first thing that happens is that Cristian plays a !KeyDown with !KeyVelocity = 0, then a one-shot trigger should occur, and should play the whole sample out. Likewise, if two !KeyDowns occur in a row, each with velocity zero, and if they are far enough apart in time that the sample has been played all the way out, then I think the second one should retrigger the sample. Maybe we have different interpretations of the requirements. You are interpreting !KeyVelocity = 0 as a purely negative event, something to be ignored as it were. I interpret it as a positive request for a one-shot trigger, a special meaning being given to !KeyVelocity as it were. -L [This message has been edited by Luddy (edited 04 May 2009).] IP: Logged | |
cristian_vogel Member |
![]() ![]() ![]() quote: I just tried to run your example on my Paca and got 'ERROR: Improper store into indexable object' which is really strange I;m still getting erratic behaviour in my program even after all this discussion.. Its a multisample with my own samples, so I will have to try and build it into a generic thing so you can have a hack at the issue in context , and there's no confusion about what the goal is. IP: Logged | |
cristian_vogel Member |
![]() ![]() ![]()
quote: You will see from my attachment, how your example was not actually *holding* the gate, but just playing the release. I need a !KeyDown to *sustain* if the next velocity is zero or below a small velocity (like 0.1). I want to respect and play the sample with !KeyVelocity as a volume, not just an on off... This is for the heart of my NeverEngine sequencer which does interpolating/crossfading between two different banks of velocity values slowly over time. In the example I have attached, I put a sample loop, so you can hear that the gate is not being held, it was just not re-triggering. IP: Logged | |
pete Member |
![]() ![]() ![]() Hi Cristian I see what you want. The problem is that you can not have a duty cycle of 1 as this seems to kill the trigger altogether. Any thing less than 1 adds a gap between the notes before the trigger and it's this that makes the zero velocity masking too late. You could delay the gap to make it line up like this. ((((!KeyDown smooth: 6ms) asLogicValue)-0.5 ) smooth: 6ms)+(!KeyVelocity le:0.2). This is a two stage delay as you need that to get the trigger lined up. but a much better way is to use what you have with the simple trigger and with the decay set to 1 day and then use an external AR and VCA to make the envelope. By putting the release to 1 day you deactivate the built in envelope shaper and you can then add your own to the output of the sample player to make a much neater solution. hope this helps. IP: Logged | |
SSC Administrator |
![]() ![]() ![]()
![]() In this sequencer, when velocity = 0, the previous stage's gate stays down and the sample continues looping through the silent stage. Note that there is a FunctionGenerator in Gate field and extended duration is computed and transmitted using ExtraValues to allow for DutyCycle control. (Example also uploaded to tweaky for future reference). IP: Logged | |
cristian_vogel Member |
![]() ![]() ![]() this solution works great but seems to fail if there is shuffle/groove in the sequencer duration field IP: Logged |
All times are CT (US) | next newest topic | next oldest topic |
![]() ![]() |
This forum is provided solely for the support and edification of the customers of Symbolic Sound Corporation.