|
Post by uncledave on Feb 18, 2022 22:22:58 GMT
Thanks Dave, my programming experience is very Basic. I dabbled with a Sinclair ZX81 and later a Spectrum in the early 80s. I even managed a little Z80 assembly language. My only program, apart from some Basic, was to get my ZX81 to tell a tone generator add-on how to play the first movement of Beethoven’s Moonlight Sonata. After this I took up golf and spent all my spare time practising my swing 😂. In short, the StreamByter University didn’t seem too alien, but 40 years is quite a while so I may need a bit of practice and help. Very good. Actually, Basic and Z80 assembler are good training for SB programming. The business of a keyword on every line, and the implementation of indirect addressing (array indexing), are very Basic. And assembler experience means the step-by-step arithmetic is not unfamiliar. Also, having to manage your own memory map is assembler-like. For me, the biggest hazard in SB programming is leaving out an End. The whole script turns red, with no clue as to the location of the error. You just have to go through it line-by-line. Also, I sometimes choose an illegal Alias, for example tmp1 apparently means something, maybe double indexing on a timer variable, hard to say, but those are easy to recognize.
|
|
|
Post by mikefloutier on Feb 21, 2022 11:01:40 GMT
Many thanks Dave, I think I’m going to take a break from the SB scripts for a while, I’ve been learning so much and it needs time to settle. Also it’s become it of a rabbit trail and I’ve found myself distracted from the very things that led me to it in the first place; ironically!
I’ll be back!
|
|
|
Post by uncledave on Feb 21, 2022 11:44:16 GMT
Great! Keep in touch (Rikki don't...) 
|
|
|
Post by mikefloutier on Feb 21, 2022 11:59:42 GMT
Great! Keep in touch (Rikki don't...)  Thanks Dave, Donald and Co are definitely one of my favourite bands!
|
|
|
Post by mikefloutier on Mar 2, 2022 11:21:28 GMT
Great! Keep in touch (Rikki don't...)  Ok, as a solution to my dilemma of separating messages (ie. drum patterns from presets) without the option of different channels, I opted for this, which is fine for my live use: 1. Select Midi Guitar 2 and AudioKit Synth One (harmoniously paired) presets using BlueBoard in its proprietary mode (button A startup) with buttons A-D issuing PC 1-4. 2. To control the AR-909, I then planned to use one of the two external jack sockets on the BB to plug in a sustain pedal, programmed to issue CC #21. I was able to modify the script you kindly provided in order to scroll through my AR-909 drum machine’s patterns, without interfering with the MG2&S1 presets mentioned earlier. However, since I also want to use this “sustain” pedal to start and stop the AR-909, I made use of the Audiobus3’s midi-learn option to trigger the start/stop commands with Hold, rather than Press. I’m guessing I’ll have to make some use of the Timer special variable in order to get your script to ignore my Hold messages but I’ve no clue as to how to go about this. Can you please give me some pointers with this.
|
|
|
Post by uncledave on Mar 2, 2022 13:17:51 GMT
Hi Mike, Actually, the trick is to use a delayed internal SysEx message to detect whether the button was simply tapped or held. This is a bit strange until you get the hang of it. It would be easiest if you posted the script you need to modify, and I'll add the necessary code. Please put the script between [ code] and [ /code] HTML brackets (omitting the space, of course).
|
|
|
Post by uncledave on Mar 2, 2022 13:31:37 GMT
I've been thinking that you could do this all more gracefully by using a couple of scripts in Audiobus. The only problem I see is dealing with MG2. Could you please answer the following questions: [/em] of the BlueBoard configurations? [/ul] If any of those methods can be used to take MG out of the equation, I can describe a scheme using different MIDI channels and Audiobus MIDI routing that would let you control everything however you want using scripts in Audiobus.
|
|
|
Post by mikefloutier on Mar 2, 2022 13:47:36 GMT
Thanks Dave,
That would be great. The AB3 Start/Stop thingy is looking for a CC21, held for about one second.
I tried to tidy up stuff I thought would now be redundant but....wasn’t sure about the last little section regarding ignoring noteOffs.
#SelectPattern - single pedal
If load Set name selpat Alias $12 patternBase # first note number for patterns Alias 3 maxPattern # patterns numbered 0..3 Alias $21 noteUp # CC# # using the J array for saved values, I for temp values Alias J00 needInit Alias J01 currentPattern Ass J00 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Alias I10 temp0
# this sends both note on and note off (delayed) for the selection # apps tend to work better when notes are not left hanging Sub SelectPattern thePattern # get note number for the pattern Mat temp0 = patternBase + thePattern Snd 91 temp0 3F #using Ch 2 in AR-909 Snd 81 temp0 0 +D500 End
Sub UpdatePattern If currentPattern < maxPattern Mat currentPattern = currentPattern + 1 Else Ass currentPattern = 0 # back to Pattern 1 End SelectPattern currentPattern End
Ass needInit = 1 End # Initialization ———————————————————————————
If needInit == 1 Ass needInit = 0 UpdatePattern 0 End
# handle Note On # all notes are blocked, so only the pattern notes get through If MT == B0 # is it a CC If M1 == noteUp # is the CC 21 If M2 == $127 # is it button press UpdatePattern End End Block End
# ignore Note Off If MT == B0 Block End
|
|
|
Post by uncledave on Mar 2, 2022 14:10:10 GMT
Thanks. I'll have a look at this.
But I realize I was mistaken about the complexity. The following sample code can detect long vs short press. I used Note On/Off, but it could be whatever event you're using. The timer variables reset on every read. So, you read (and ignore it) on press. On release, the value is the number of ms since press, so it's easy to tell short press from long hold. Remember that you cannot read the timer twice, expecting the same result, because the second read will only give the time since the first read. As always, don't forget the $ when entering numbers. #TimerTest
If MT == 90 Ass I00 = T00 End
If MT == 80 If T00 < $500 # 500 ms, half a second Set LB0 SShort Else Set LB0 SLong End End
|
|
|
Post by mikefloutier on Mar 2, 2022 14:20:19 GMT
I've been thinking that you could do this all more gracefully by using a couple of scripts in Audiobus. The only problem I see is dealing with MG2. Could you please answer the following questions: [/em] of the BlueBoard configurations? [/ul] If any of those methods can be used to take MG out of the equation, I can describe a scheme using different MIDI channels and Audiobus MIDI routing that would let you control everything however you want using scripts in Audiobus.[/quote]Hi Dave, Sorry, I responded to your earlier message before seeing this one. 1. MG2 doesn’t respond to Midi inside AB3 unless BlueBoard is selected in the Midi Pedal box. So I guess the answer is No. 2. There is no ability, I can see, in MG2, so select channels, in or out. To be honest I don’t want to use MG2 or S1 inside AB3 as S1 crashes almost immediately and MG2 can’t save presets. I simply need to detect and ignore a CC21 pedal press that’s held for a short time, eg 250ms
|
|
|
Post by uncledave on Mar 2, 2022 14:27:33 GMT
Here's my update to your revised code. This is untested, but ought to work. This would replace both your If MT blocks. #CC 21 code
# This just presets the timer on press. Have to wait for release # to distinguish tap from hold. You can hard code the actual # channel in the If M0 test. Remember the channel in the # message is one less than the MIDI channel number.
If M0 == B0 $21 # detect CC21 on MIDI channel 1 Ass I00 = T00 # read timer If M2 == 0 # CC value is 127 on press, 0 on release If I00 < $500 UpdatePattern Else # long press. Do what you need. End End End Block
I used SB's interesting multiple word test capability to detect CC21 in a single step. I assume your CC does send 127 on press and 0 on release. The timer is read on both press and release, but all the actual action occurs on the release. The code for the long press is left as an exercise for the user  . Edit: I realize I left out the Block. Probably should put at the end, after all the Ends, so the only messages leaving here are those with explicit Sends. Just inserted Block.
|
|
|
Post by mikefloutier on Mar 2, 2022 15:03:32 GMT
Here's my update to your revised code. This is untested, but ought to work. This would replace both your If MT blocks. #CC 21 code
# This just presets the timer on press. Have to wait for release # to distinguish tap from hold. You can hard code the actual # channel in the If M0 test. Remember the channel in the # message is one less than the MIDI channel number.
If M0 == B0 $21 # detect CC21 on MIDI channel 1 Ass I00 = T00 # read timer If M2 == 0 # CC value is 127 on press, 0 on release If I00 < $500 UpdatePattern Else # long press. Do what you need. End End End Block
I used SB's interesting multiple word test capability to detect CC21 in a single step. I assume your CC does send 127 on press and 0 on release. The timer is read on both press and release, but all the actual action occurs on the release. The code for the long press is left as an exercise for the user  . Edit: I realize I left out the Block. Probably should put at the end, after all the Ends, so the only messages leaving here are those with explicit Sends. Just inserted Block. Thanks Dave, that makes sense, will give it a try after tea 🍰
|
|
|
Post by mikefloutier on Mar 2, 2022 19:52:07 GMT
Dave, sorry for the delay, had done a quick reply but it didn’t go for some reason.
What can I say, it works very well indeed, thank you! With a bit of trial and error I found that around 300ms worked for me, but great to be able to adjust it all so easily.
I have a couple of queries:
1. When I run it, each time I load it, it appears advance one pattern when I press and another pattern when I release (it’s possible both happen whilst holding but I can’t tell). I don’t have to hold for long for this to happen; not long enough to trigger the Start/Stop thing.
2. I was curious about the lines of code from, Ass needInit == 1, down to the 2nd End, ie.6 lines. J00 has already been assigned 00 in the If load section.
3. I’m also a little confused as to where Sub UpdatePattern Ends; did I make a mess of my editing?
|
|
|
Post by uncledave on Mar 2, 2022 21:35:25 GMT
Dave, sorry for the delay, had done a quick reply but it didn’t go for some reason. What can I say, it works very well indeed, thank you! With a bit of trial and error I found that around 300ms worked for me, but great to be able to adjust it all so easily. I have a couple of queries: 1. When I run it, each time I load it, it appears advance one pattern when I press and another pattern when I release (it’s possible both happen whilst holding but I can’t tell). I don’t have to hold for long for this to happen; not long enough to trigger the Start/Stop thing. UpdatePattern originally took a parameter for up/down, and the init logic was meant just to force sending the initial pattern number, to be sure the app was in sync with the script. You removed that logic so, each time you load it it increments by 1. You should remove the init logic. The initialization of J00 is just a default, to be sure everything is defined. Setting needInit to one at load time ensures that the initialization is done when the first message arrives. Remember, the main body code doesn't run until a message is received. That's why it seemed to take two steps the first time. You should remove that logic. UpdatePattern looks fine. There's an If/Else/End inside, then the Sub...End around it. The indentation's a bit off, but that's just a manual device to help readability. SB will be very upset if the block structure is incorrect, so you can be fairly confident it's right if Install Rules accepts it.
|
|
|
Post by mikefloutier on Mar 2, 2022 22:26:19 GMT
Many thanks Dave, I’m sure enlightenment will trickle in as I work through it.
I must admit to being ignorant of the business of what order the code runs in. I suppose:
1. The If Load stuff runs first, once only - does it matter where in the code it appears?
2. Subroutines never run unless they are called, and
3. The main body (which you mentioned runs every time a message is received) is everything else and is processed in the order written.
Thanks so much for all this, it’s very exciting to imagine all the potential it opens up for this super little piece of hardware.
|
|