Blog

PART 14 – REALISM AND REALIGNMENT

Then nearly everything stopped working properly. I bet you thought the timing bug was going to be the worst of it right? Yeah me too. But no – sending notes to the right sounds was breaking in all sorts of ways, so a loop would play back properly, until I asked it to play a Formant sound, then it would play the loop AND a bunch of other loops too (er, wrong), then loops would not load/unload fully (purge to you KSP jockeys).. Sigh. Partial load/unload within a group (of Zones for you Kontakt gurus) is a BIG problem, because I cant ask Kontakt to do this I can ONLY ask for FULL load/unload of all zones in a  group, so it’s a bug in Kontakt…somewhere, unless its me – which really it might be.

The base level complexity here is doing Formant sounds, they need their own group, and these need keeping track of *everywhere*. I like them but they double the complexity. I couldn’t get them to behave. I thought for a while about how I could do this formant thing any other way.

There’s a formant filter in the FX system that works nicely, it doesn’t give you the same control over formant shapes however. But…. some of the “problems” with formants I was uncovering whilst using them in this product were, they were “unruly”, you could get a nice sounds but getting to targeted specific sounds was much harder, the controls were very sensitive, especially on drum sounds. Plus the range of formant sounds wasn’t that expansive for drum sounds (actually not much of a surprise when you think about it).

So losing the beloved formants, looked, in theory, to make Orbiter into LESS of a sound design tool, but in practice wasn’t as big a loss as it seemed. The user could get formant-ish sounds by putting a formant filter in one of the bus effect slots. Of course this meant that they would be applied all the time to every pad (nowhere near as nice as the current Formant effect solution).  Could I think of a way to get back this nice “switching formant effects in and out on each pad separately” control?

Well I now had a pad-effect area(previously occupied by the Formant effect), I could set it up to bypass/un-bypass an effect in the loops bus, in fact any effect in any slot in the bus (so 4 slots = 4 effects). Thus you could (for example) distort every 6th beat, phase every 4th beat, and formant filter beats 2,3,4, 9,and 22 etc. Etc. So I tried it, and yes the formant filter was a much more reliable effect, and as every playing loop had its own bus every loop could have a unique set of 4 FX to bypass/use. Sounded good.

Next I realised having this sort of control would “break” the on/off buttons on the bus effect tabs themselves.  In Bus 1 (for loop 1) you might put an Amp simulation in slot 1, and turn it on, then run the pattern only to find your Amp–sim is turned off, because every pad in the first loop has its FX control turned ON but each of these has its first FX toggled to OFF. So Orbiter thinks you want to turn OFF the first FX slot for every pad individually. Lots of UI interpretation problems then. This is what I came up with:

If you have the pad FX control turned off (the little “F” button), then Orbiter will look to the on/off setting in the effect slot itself.   If you have the pad FX control turned ON it will obey the settings you have in that pad itself, but only for that pad. It’s a little counter intuitive I feel. But I cant think of a better solution, and I really like the idea of per-pad effect control; it’s a little less Formant but a whole lot more of every other kind of effect(all 24 different choices of them).

All this work fixed the timing, the load/unload and the crashing issues – pretty much for good (fingers crossed though). So the ever onwards journey of the little “F-button” continues, from “Fade-In” to “Formant” to “FX”. Lets hope it can settle there now, not least because I cant think of anything else starting with “F”, well I can; but who needs a button for that?

I realise this is all a bit abstract, even with some screen shots, so here’s a quick video of the overall approach of Orbiter. I’ll try and do more detailed versions as I go.

YouTube player

 

PART 13A – USER ERROR

So more testing more head scratching, and more debugging code, and then Kontakt started to crash – badly, often and spectacularly (like dump logs of HEX stuff – for those of you doing dev with Kontakt). This is bad, very bad – perhaps it was a bug in Kontakt 5.5? However persistence, and adding a metric ton of debugging code, paid off as eventually I began to see Orbiter fail to count correctly. Yeah the stuff we all do 1,2,3,4,5,6…. Orbiter was doing stuff like this; 1,2,3,4,6,7,8…. Hey! Where did “5” go?

Now as it was counting 24 times every beat, missing an occasional number that I had incremented would show up as not a delay in timing but a speed up in timing(which is what I was seeing/hearing), and it meant it was something in my code, not in Kontakt (actually a relief). I spent a whole day chasing this down, and yes “User Error”. But (in the spirit of true honesty here), once I’d found the symptom I was having difficulty finding the problem, in the end I cast about a bit and changed a few initialisation values and checks and it started to work rock-solid again.

To be honest this sort of fix is horrible for your confidence as a coder, all your really good debugging and analysis code tells you its working properly, in fact I over-loaded Orbiter turning on all 4 loops, setting a sub-loop playback of 4 slices and then turning on ALL the repeats on ALL slices. A cacophony of noise(though sort of usable actually)  but the code was rock-solid on timing; well as rock solid as it ever could be(within 1-4ms). BUT…..

You really are not 100% sure how you fixed it, you sort of are, but it nags at you…..and I’m sure this will nag me : forever. And of course I hadn’t fixed it, well I had but I’d broken something else on the way, so I had to back track a few versions(days) to get to something that I could rely upon. So yeah broken, bug-fix, test, re-fix, more tests yada yada. I’m still doing it, what is really clear is at this point  I badly need a break – the fun has gone completely out of this.

Still all this testing, actually playing the instrument, gave me lots of insights into how it might get used as a playable “thing”.  I noticed I was spending an amount of time setting a whole lot of pad effect parameters to the same value. So what might be nice would be to have a user-friendly MACRO tab where I could have a number (6) of pots and that for each of these pots I could assign one or two different pad effect parameters, repeat count, envelope attack, Send 1 amount, whatever, and I could “play with” these as the loops were running: Done, and for example running a loop whilst moving a macro that changes all the envelope Attack and Decay settings gives yet another really really cool effect.

Screen shot attached where you can see the first macro pot is changing the envelope attack(“Env:A”) and the envelope decay(“Env:D”). The second macro is changing the likelihood of any reverse happening where a pad is set to do reverses, macro three is affecting the number of repeats for pads that are doing repeats, etc. etc.

part13A_macros

PART 13 – THE MOST IMPORTANT THING IN COMEDY – TIMING

So, as well as the being the most important thing in comedy, timing is also the most important thing in a loop playback engine that is using some sort of sequencing to get “cool” things done.  Well any kind of sequencing thing really, and Orbiter wasn’t playing nicely. It seemed to be speeding up – which was truly odd.

When you are writing real-time, re-entrant, parallel code in any product (and that’s what I’m doing here) you need to have a mental model of what is happening under the hood, and according to my model for Kontakt KSP any timing errors should all be about showing up late not early. I ran some tests. I ran some more tests. I went and had a lie down. It seemed that Orbiter was glitching somehow when the Repeat effect was used in a loop, but only when the repeat effect was applied in adjacent slices. Turn off repeats and apply any number of any other slice effects to any or all of the 4 playing loops and it seems rock solid.

So I’m a bit stuck. Right now I think I might have to refactor the play_a_note routine again, taking out all the sequential bits, make those happen, well, sequentially and then deal with the wait_states in the repeat section. I get the feeling it will get worse here before it gets better. Current thinking? There are a lot of listener call backs (24 per beat) so they might be making things “queue badly”, or the tasKfunc has some waits in it(otherwise what’s the point in using it) but maybe the unload/reload of state based values is also clogging the wheels somehow – can you see I’m really casting around for answers here?

I realise this is all getting very technical very fast, but if you get no other idea from this you should take away that I don’t know why its doing it and I’m trying a bunch of “stuff” to get it to stop. This “stuff” has in no way been identified as a solution to some defined problem – cause I don’t know what the root-problem is. What I suspect is happening is that tcm.wait(some period) cant interrupt and get back in to its correct slot as another taskfunc is still doing something, but this would make the “failing” wait show up late not early… mystified.

These are the dark and ugly hours of product development, when the temptation to leave this all behind and go back to being a failed musician is most demanding.

Meanwhile as a small aside(well it’s timing related really..): I’d been playing the instrument a fair amount, and the one thing I was struggling with a bit (as a novice on this thing, as we all will be at the start) is getting the timing right for retriggering pattern steps, so for instance I might want to move the pattern to pad 9 every 4 beats, so as the pattern plays…: 1,2,3,4 <click on pad 9>, 9,10,11,12<click on pad 9>, 9,10,11,12, etc.  which means timing these clicks AFTER pad 12 has played but BEFORE pad 13, and sometimes I miss it. So I added the ability for Orbiter to accept quantised events. If you set Event Quantise(in the settings page) to (say) 4 then Orbiter will accept your “event”(say a pad click, or a resync etc.) anytime but will only act on it every 4 beats. So the interactive stuff above is easy now: 1,2<click on pad 9 say now>,3,4 , 9,10,11,<click on pad 9 somewhere here>,12,  9,10,11,12 etc.

Here’s a picture of a genius of timing, started out as a musician, no surprises there.

bobhope

PART 12 – RANDOMISATION IS YOUR FRIEND

Next, randomisation. A Loop Player, playing loops yeah? Good things about loops = performance, sound, recording all done for you, so instant usable sound source. Bad things = Next time thru the loop playback sounds exactly like this time thru the loop playback. 2+ times thru the loop = “it sounds like you are using a loop”, and historically there wasn’t so much you could do about this, until now…

Orbiter inherited a bunch of nice randomisation functionality from Slice. You can load up patterns, that reorder how parts of the loop (slices) get played. So of course you can start at slice 1 and move sequentially to slice 32 (SIMPLESTEP – is the name of the pattern in Orbiter) but of course there are dozens of different patterns in Orbiter, including some that randomise the bar sequence (RANDROW) or some part of every bar(RANDPART) etc. So already there are lots of randomisation things in Orbiter.

But I wanted to be able to randomise nearly EVERYTHING, especially the Voice and Sound controls. So first is the randomisation of ON/OFF states for every effect selector button in every pad. So for example, you can decide to have the reverse effect in pad 4 randomly applied or not, or the Tuning in pad 19, or Volume in pad 12, or the Sends in pads 4,6 and 22 etc. etc. Of course randomisation settings require to know how often they are likely to be applied – so I added controls in the Settings tab for on/off likelihood, and then as you will see took these out again.

Next was the effect values themselves. Clearly some effects, like Reverse or Random, only have an on/off state – they are either Reverse(d) or they are not, but every other effect has a set of values; for instance the Send controls can be randomly on or off, and each of the 4 send amounts should also be randomizable. So the user could set the Send effects on randomly 45% of the time and Send 1 thru 4 amounts to be randomised 60% of the time.  Again these controls get a “likelihood” dial in the settings page.  So now we have a huge amount of randomisation possibilities, such that no two loop iterations would ever sound exactly the same.

All this needed a nice way to get applied quickly by users so its time to rationalise the Alt/Shift/Ctrl click usage. So I did this – now Shift-Click on an effect button and all buttons of the same type are set to its value(ON or OFF). Ctrl-Click on a button and its randomisation is turned on/off. Same with the values widgets in each dialog, e.g. Shift-Click/drag on the Volume Control in the Volume Dialog, and all pads have their Volume set to the same amount. Ctrl-Click on the same control and all Volume amounts are set to randomise.

And I played with this for a while(a few days) until I realised instead of this Ctrl-Click nonsense all I needed to do to get individualised effect control was add another pot to every effect pop up, the “likelihood pot”, so now every pad effect has the ability to set its “likelihood”. So this Ctrl-Click stuff wasn’t needed for effect buttons at least, so I removed it, and thus I also had to go back and do some cleaning up in the Settings page but it was more in tune with the overall approach Orbiter uses and it added more flexibility always a good thing.  Now Orbiter offers users the ability to randomise patterns and on/off states for each pad effect and the actual pad effect settings themselves, so subtle to wild randomisation depending on your tastes, but not so much of the “classic loop repeating” sound.

Here’s what a typical dialog looks like in a pad, in this example the envelope dialog for (A)ttack, (H)old, (D)ecay and (?)Randomisation’

ScreenShot_EnvelopeLikelihoods

PART 11 – RISE OF THE MODS

As I mentioned, you could add a CC control to modulate the overall Loop-level Pan control any time you wanted. Possibly usable, but not very friendly of easy to configure.

I’d built a set of modulation controls in Formation, and even refined them since. How hard could it be to build a simple Pan Modulator and its Dialog? Turns out not really so hard at all. I built a set of controls and made them pop up in the space that would vacated by hiding first two rows of pads.

So now I had Pan back as something the user had better control over. I used the refined dialog to let the user select the number of steps in the modulation(4 to 32), the tempo, a retrigger on note start and a random amount to be added to each step(0 to 20), so in the end a useful modulation source.

The nicest results for modulation in Formation were using a modulator as a kind of volume gate (Trance Gate to those of you into those dance-y genres), and sitting right next to Pan in the Loop-level controls was, Volume. So it was a no brainer to add a modulator for Volume too. This might occasionally be useful for drum-loops, but I was pretty sure it would be great for pad, keys, basses, and guitar loops etc.

Further I could do this to the groove setting too, also up in the loop level controls.

Now I had a problem. What was the sensible tempo for these modulators? Well its nice to let the user set the tempo, but free-running volume modifiers can give you ugly artifacts, so I wanted the tempo sync-ed to the sound generating engine, basically the steps of a pattern. Sound generation was at a defined tempo for pattern playback, and fixing the volume and pan modulator values to sync up with each pattern step in turn was the best sounding approach for pattern play-back. But I wanted different time signatures not available in pattern mode(like 1/16 triplet feel) for pitched and stopped mode playback.

Under the hood this meant yet more changes to the way tempo was handled, painful changes but moving to a more generalised “Clock” possibly useful in other areas of the product one day. So that’s when the timing issues started to show up.  Remember I said something was coming back to bite me? If you listen closely you can hear me crying out with shock and dismay…

Meanwhile here’s the modulators screen design and a track of panning and gating sounds using a drum loop and two “cinematic sounds” from Orbiter.

https://soundcloud.com/channelrobot/volandpanmodulationtest

 

part11_Modulators

PART 10 – MA, IT’S THOSE CLICKS AGAIN….

So I’m driving to the day job again, just like every other morning, when I have an epiphany. Well no I didn’t but I did have a good idea that made me feel good. You remember our clicks solution? An envelope. It works but it cuts off some of the slice(in the attack portion), what would have been better would be to allow each slice to slide its start position forwards or backwards in the overall loop wav file.

I’d tried all sorts of Abelton Live/Recycle-like interfaces to define these positions, I’d even had a POSITION tab at one point (you may recall in the original Orbiter UI design) where you could hand-apply these sort of things. For some reason I’d never thought of the (now obvious) solution of just replacing one of the pad effect buttons with an offset effect button that would allow each pad to slide its start position forwards or backwards by a few hundred milliseconds. Took no time at all to implement.

But as usual someone(one of the pad effects) had to get sacrificed. This time it was the Pan control. I know, I know Pan is MUCH under-rated as an effect, but there already was a loop-level pan control which you could automate with some CC-control if you wanted. The trade was worth it. It seems to work absolutely perfectly – always a bad sign…. I must have forgotten something. And I had, more than one thing, and they were coming to bite me, but more on that later.

Meanwhile, whilst I’m here: You should never under-estimate playing with a thing as a way to make it clear what needs doing next. I’d got quite pleased with myself (pride before a fall) with the 4 loop playback, and I spent a fair while just playing the product. What became clear was it really would be much more of an instrument if I added key-switches to mute/unmute each loop, so I added those too, and rearranged the loops section a little. Now I could really “play” Orbiter, like a proper deck or instrument. Deck? Did I say deck? Suddenly I’m some sort of urban street DJ person….. not as if that’s a bad thing but one look at me in the flesh will tell you how unhip I really am. Still it’s a sign Orbiter is usable and useful as an instrument, in the same way a set of decks is/are/can be.

NewMutes

PART 9 – A SOLUTION

When I got back I’d changed my mind(sorta). It was getting out of hand, it was ugly, and sprawling, some of these ideas would have to get controlled, or go, or I could abandon the whole thing.

If I got rid of the position tab and the phrase player tab I thought I might be able to get the useful controls for each of the 4 loops onto the “main” page, if not – goodbye(for now) to Orbiter. So I had a go through a UI design in Skinman (see attached). It seemed to work and I got the FX back where (I thought) they belonged. We lost the 12 slots for loops, but as we were now playing back 4 loops at a time it was a compromise I could live with.

Still this meant that the internal code in the FX section would have to be overhauled. I’d originally built the FX system to be vastly re-usable(groups, busses, inserts, sends whatever) but it had become hugely difficult to implement, and nearly impossible (for me) to debug. So I’d cut it down to handle what I’d needed at the time (in Formation) which was one bus, and the sends, now I’d need each loop(4 of them) to have their own bus so the FX system would now have to display and manage 4 different busses and the send FX. So that’s what I did next.

Nicely using busses (my favourite way of architecting multiple playback of sounds to be frank) allowed independent control over volume and pan for each loop, so I put these up in the loops area, and I added the groove and humanise controls into that section too. It all looked more cohesive – a little crowded maybe but sensible(at least to my eye).  A quick trip to “play_a_note” to change it into a task func (for all you KSP jockeys)  and it started to playback 4 loops, this might work!

I realised it really really did work when I accidentally configured two (similar sounding) loops to playback at the same time and activated a set of Formant settings in only one of them – and I could mute unmute this loop, as well as spice up the first loop as much or little as I liked using that or the volume control for this second loop. Next I turned on a random(ish) set of mute controls on the original loop, and then set only those pads to play in the second loop – again interesting stuff. I’d really seen Orbiter strength as playing back separate stems (like Kicks, snares, tops, fx etc.) not multiple full loops – but as I currently didn’t have many stem versions of loops I’d had to work with 4 full loops – and even these worked well! Yeah this could work…

Here’s a screen shot and some audio featuring me “messing about” with 4 simple loops

part10_orbiterasolution

https://soundcloud.com/channelrobot/4loopmixv01

 

PART 8 – ORBITER, A FALSE START

OK, so a few weeks had passed by now and it was nearing the end of the year. I had a lot of new and useful stuff in there. So a launch date for Black-Friday/Cyber Monday had disappeared in the rear-view mirror and so had any Christmas landing. Plus I had to go to New Zealand for some family issues.

So the choices were either A. knuckle down to long nights of effort – with no guarantee of getting to a good release date in 2016, B. Relax, do (nearly) nothing and wait for a Q1 2017 release. Or C. Stay on the development track, build as good and fully featured product as I could (I already had a name for this “ultimate looper” : Orbiter) adding new features thru Q1 2017 and then release later in (maybe Q2) 2017.

Guess which I decided on?  Yeah: C —- Sometimes I despair at myself…

So I built a UI design for Orbiter.  I’d been a heavy user of Stylus RMX once in my producer days, so I knew what the competition was. I wanted to do all the useful things from Stylus, plus a bunch more.  Slice already did things Stylus can’t, like playback different patterns(reordering loop elements) and play formant-based noises etc. So I was off to a reasonable start. But I also knew I’d need simultaneous play-back of multiple loops. My experience with Stylus also told me that I nearly never used more than 4 loops at once (it just gets too crowded in there) – so 4 loops at the same time was a compromise, but a reasonable one, if in the end I could get to 8 loops (Stylus’ limit) simultaneously then great.

I also wanted pitched (done!) and maybe a phrase player too, as well as even finer grained control over slice start and playback position. A screen shot is attached. I added a POSITION tab where the user could hand-manage the start and end point of any slice(so I was fiddling with those clicks and bump noises again), a PHRASE tab where the user could record a little phrase, or sequence, of their own making, and play that back. Plus 4 META-TABS where you could select the loop you wanted to edit/work with.

All these things meant moving the FX off to their own tab (no longer enough real-estate on the main page), but I’d done multichannel mixers before so a 4 channel one in another Script slot in Kontakt, with FX display and editing should be a cinch. It was, but it was also anemic (there wasn’t much beyond a Gain slider, pan, and mute above the existing FX panel moved from the original).  Anyway, off to NZ (60 hours flying in a 120 hour timeframe) and plenty of time to think about it.  But even before I left I wasn’t looking forwards to either the flights or the new UI implementation – it just didn’t feel right.

part8_orbiterdeadend

PART 7 – PITCHING

This “play_a_note” thing was starting to show other benefits too. I realised it wouldn’t be hard to add a completely other way of playing a note(pad/slice/sound).

{Aside: Really its getting out of hand, what should I be calling this “bit of a loop” Slice? Pad? Sound? Beat? OK for this episode I will settle on “Pad” – Aside over.}

I could re-pitch a selected pad across the whole keyboard. Instead of assigning 32 different pads to 32 keyboard keys I would assign a single pad across all the keyboard and retune the sound it made to match the pressed key.  This might not be such a great deal for drum sounds (Slice’s bread and butter loops) but for already pitched loops, like bass loops or evolving sounds etc. You would get a whole new mode of playing parts of the loop.

In the end 2 octaves either side of the original pad sound was about the limit of usefulness so I implemented it. Deciding how to show this in the interface was a bit problematic, until again I gave up on my original approach to the interface and adapted to circumstance. I added a whole new tab so you could be in pattern mode or pitched mode. To get to pitched mode you simply press the PITCHED tab, select a pad; that identifies the sound(loop start point) you want to play with, define a middle note, which when pressed plays the original pad sound, and then you start playing the two octaves above or below your defined middle note. Simple really. Sure its not Abelton Live or anything, sounds speed up and slow down as you move across the keyboard, but even this “old-school” pitched sound is pretty interesting.  Chords made up of re-pitched snare sounds anyone?

Below are some loops played using this pitched mode.

Whilst I’m here it might be worth talking about the “other” mode available in Slice. It’s got no name, but you could call it “not pattern and not pitched” mode, but I tend to mentally refer to it as “Stopped Mode”. If you have the PATTERN tab selected, but you are NOT playing a pattern (so STOPPED right?), then when you click on a pad(with your mouse) Slice works out which part of the loop you want, it moves to the start position of that “slice” and plays it  – nothing special there, that’s what pattern playback does but it does it for a whole sequence of pads.

But if you press the *keyboard key* associated with a pad(instead of clicking on a pad with your mouse) then Slice works out which part of the loop you want, it moves to the start position of that “slice” and starts playing the loop from there, and here’s the important bit: and continues to play through the loop until you lift off the key. So if you press and hold the key associated with the first pad then Slice starts at the beginning of the loop and keeps playing through the loop until you lift off the key, so you can easily play through the whole loop if you want, or pick another pad and you can start your “continuous playback” from any of the 32 pad positions.

https://soundcloud.com/channelrobot/testrendercinematicpitched

https://soundcloud.com/channelrobot/testrenderbasspitched

https://soundcloud.com/channelrobot/testrenderdrumlooppitched