Blog

PART 17 – MEANWHILE IN A GALAXY FAR FAR AWAY…..

Take a look at one of the screen designs, look down at the bottom, yep those are the ever present unchanging effect system controls. They’re pretty sophisticated. All 4 loops have 4 slots each into which the user can place any of around 20 effects, there’s also 4 send effects too – that the pad Send effect controls the routing to. The user can select any one of 6 different effects to load into each Send slot. In the end the FX System is a completely separate thing that just sits at the bottom of any other product page adding lots of really nice effect addition and control.

I built this system for an unreleased product called Cadence, but then reused it for Formation, and it’s been in every product since. It’s massive, and good, and not everything I wanted it to be (but I admit I was being hugely ambitious). As I’ve mentioned here before it started out as an all-singing-all-dancing solution to ANY product design, handling group based effects, bus effects, insert effects and send effects. If you could load an effect somewhere in Kontakt this would do it too. It has nearly killed me more than once.

I cut it down to work for Formation(one bus and the sends) and this worked fine for Slice too. But adding 4 parallel loops in Orbiter required me to add in 4 busses alongside the Sends. So I’ve done that. But the problem has always been about saving the effect settings – which I got a handle on at the end of Slice 4.2 (never released, and now replaced by my decision to go with Snapshots anyway), and modulation – or more specifically the lack of any modulation of effect parameters.

So given I’d been in Modulation adding mode, before being so rudely interrupted(<- look a real-time coding pun!) by all that timing rework,  I thought about adding modulators to the FX system too. But timing, timing, timing – this modulation system wasn’t going to make that less of a problem. There would need to be about 10 to 20 modulators, they would each need to be capable of working on up to 240 effect parameters – in real time. Possibly a big ask. But I’d re-built the internal product “Clock” so I could reuse that, and see if it broke things badly or not. Can you tell I’m still worrying abut timing issues here?

Stepping back for a minute (and only for a minute) sanity seemed to prevail(for a change). I realise, importantly, that I’m burned out. Time to stop adding stuff in, so reluctantly effect system modulation will also have to wait for another product to do it and get retro-fitted here. Users always have the CC learn facility available anyway, and this is not a synth, modulating filters etc. isnt a must-have feature, it’s a loop player. Or to keep this Star Wars analogy alive “These are not the feature changes you are looking for…”

part13A_macros

PART 16 -TO ARP OR NOT TO ARP

So it may be obvious that I’ve been re-using lots of code I built in other products (like Formation, Cadence and Slice itself) as well as more general modules like the effect and modulation systems. There are lots of other things laying around here at CR headquarters (well on the cloud-drives anyway). Which led me down the following garden-path….

So when Orbiter ISNT playing a pattern then pressing a key gets you a specific slice of the loop, or (in pitched mode) a re-pitched version of a named-slice. So in “Stopped Mode” you *can* just play the loop through by pressing each slice-associated key in turn – sure loading up a pattern then pressing play on the pattern tab is way easier, but you could do-it-yourself if you wanted.  Plus you could press those keys in all sorts of different orders to get your own hand-rolled pattern. So one way to think of Orbiter is as a kind of ROMpler with sounds under each pad/key and a sophisticated pattern player bolted on.

So thinking about that – two ideas came to mind – it seemed pretty simple to assume that if I wrote a little (say 8 track) sequencer on the front of Orbiter to play specific pads that might be a nice addition. Unsurprisingly I have one of those lying around. I could just wire it up and see if it worked. This thought came early in the journey home from work, but before I’d got home this other thought occurred to me:

“You know what? That was the original idea for Formation – build a little sequencer on the front, but in the end this turned into the MUCH nicer Sequencing Arpeggiator that got shipped, why not just use that instead?”

Now if you haven’t seen the “sequencing arpeggiator” in Formation, well you should. It’s really unique, and really powerful.  It “listens” for up to 8 key presses, and for each key that is pressed (in order) instead of playing the associated note, like any other arpeggiator, it has a  little independent 16 step one-note sequencer it associates with that note and it plays thru that sequence repeatedly. Yeah, it’s hard to visualise based on a textural description but it sounds great and its clearly obvious when you see it in action. You can do loads of very very cool things with it from standard arpeggiator patterns to rising and falling polyrhythmic shapes, chords AND runs at the same time or after one another etc.

It needed a few things taking out of it to make it work with Orbiter, but removing stuff is (sometimes) easier than adding so I did a quick UI sketch (based on the existing arpeggiator). It looks do-able. But the nagging voice in my head is now saying “you are making this all too complicated…” And perhaps that is true, but its also really cool stuff. Conflicted now. As it stand’s I think I’ll schedule this in Version 1.1.

Oh the second idea? Well “Orbiter is as a kind of ROMpler” means you could use other sounds than loop slices, so it wouldn’t be so hard to turn Orbiter(or its engine) into a drum machine, and a pretty unique and powerful one at that. Another day perhaps.

ObiterArpDesign

Building Audio Products

So I wrote a white paper about the Kontakt developer/library market back in 2015. It seems to have been quoted and pointed at quite a bit recently, and occasionally I send it along to people asking about how much I charge for development and will I build them their all-singing-all-dancing mega instrument. If you are thinking about getting into developing a kontakt instrument library, either as coder, designer or as an owner of samples, you should give it a read. It might prove insightful and offer you a way in (or not).

Not much has changed in the interim, apart from the arrival of GUI builders which ease the coding-pain of building a UI, but as that’s about 20% of your coding effort it’s probably not a golden key solution for anyone and will probably add to the number of instruments in a crowded market.

The other thing that happens a fair bit is people arrive with development requests and a very poor understanding of what the costs are going to be. So I’wrote a new paper on the costs of coding.

The original white paper is here: KontaktMarket2015

The Cost Of Coding paper is here: The Cost of Code

These papers may be controversial, and you are free to disagree in any way you like. Take them for what you will, they are my experience.

 

 

PART 15 – SAVE, LOAD, LOAD, SAVE

Adding in all this new stuff meant going back to the Save/Load system to include it all. Now clearly users LOVE presets, and I can see why., I do too – but building out preset systems? Yeah not so lovely.  But here goes…

So there are a number of questions to ask:

  1. What should be included in the preset and what shouldn’t?
  2. Why aren’t we all using that nice snapshot feature that NI gave us?

Well answer 1. is “as much as is useful” and answer 2 is, well, complicated… let’s look at Orbiter and see how we get along.

OK so what is “as much as is useful”? Well in Orbiter’s case this is probably all 4 loops and all their settings, as well as all the bus and send effect settings too. Plus given you will be playing Orbiter at some point we will need all 12 patterns and all the sub loop data as well as all the “transient/permanent” settings for the key switches. Looking at that list there isnt really anything else in Orbiter…. So essentially “as much as is useful” here means – everything that a snapshot would save. So on to the second question, why not use the snapshot system?

There are pluses and minuses with the snapshot system. Here’s the plusses:

  • You can drag and drop snapshots onto Kontakt and it will load the instrument for you(if its not loaded already)
  • Once its set up properly its convenient to use, better in all likelihood than some preset system which asks you to go find your custom coded presets in the file system
  • NI built it so it will probably upgrade/remain reasonably reliable across versions of Kontakt
  • See the point above, so developers don’t have to build their own system – and there are limitations to such a system – you save EVERYTHING in a big array, but the array size is limited, it’s pretty massive at 32K elements, but by now I had A LOT of arrays for configurations across all 4 loops I might be getting near this limit.

The minuses:

  • Snapshots have to live in a specific spot on the users machine (and its different for Mac and Windows users)
  • That spot is NOT a sub-folder of the instrument(WHHHYYYYY NI? WHY OH WHY?) So for a product you ship the user will need to do a separate manual step to copy the snapshots into the correct directory/folder on their hard drive.

So what to do? I’ve had a “hand-built” preset system in (nearly) every product I’ve shipped. But that is partly because I’ve been shipping products since before Kontakt had Snapshots. So (re)building another is in theory only an effort challenge not a design challenge. But for Orbiter this effort just quadrupled. I think I’m biting the bullet here, and starting to use the Snapshot system from here on. So out goes Load and Save, and in comes a bunch of additional install instructions – perhaps I should build that installer I kept thinking about, and that would automate the install including setting up Snapshots…..

Meanwhile yet more playing sold me on the idea that it would be nice to be able to switch dynamically between sets of effects, you could set a loop up with a ton of repeats, or envelopes or FX toggling etc. and that was great but when I was playing the loop back, I could dynamically mute/unmute the loop, and change the overall pattern but I couldn’t switch “effect layouts” (for the want of a better phrase) for each loop – If I added an A/B switch for Voice settings and another for Sound settings I could in effect have yet another way to play loops, – playing the loop in up to 4 different variations:

  1. A & A
  2. A & B
  3. B & A
  4. B & B

Toggling these with a  key-switch seemed a good idea too. So I added it. There’s a lot of key-switches by now.  So I spent a fair while sorting and remapping these. Added key-switches for the modulators too.

Here’s those A/B toggles.

ScreenShotAB_Buttons

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.

 

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