Jump to content

I added a few features to the Humanize function...


borfo
 Share

Recommended Posts

edit: attached project.hex-es for the LPC and STM32f4 cores in case anyone wants to try this out - let me know if you notice any bugs.  The STM hex is untested - I haven't built my stm core yet.

 

How to use the Robotizer:

 

MENU+FX -> Robo - enters the robotizer page

 

Robot on/off - enables and disables all robotizers for this track.

 

Prob - the overall probability that any robotizers are applied.  This overall probability setting is combined with individual probability settings for each robotizer, so you can make one robotizer happen more often than others (eg: change notes often, but never skip them, and only rarely change the velocity).  Hold SELECT and use encoders to set individual robotizer probabilities (indicated by vertical bars beside each robotizer).  Individual probability is multiplied by overall probability, then compared with a random number.  If the random number is lower, then the robotizer will be applied.  A different random number is called for each individual robotizer.

 

Skip - skip some steps (play them at zero velocity)

 

Octave - changes octaves.  the selected number is the range - if "2" is selected, the note will jump up or down 0, 1, or 2 octaves.

 

Note - changes notes.  Cumulative with octave changes.

 

VelCC - velocity changes.  This robotizer is weighted using some bad math in order to avoid out-of-range numbers, and produce more musical results.  As a result of the way it's implemented, it's got a distinct character when the numbers are low (you'll get more loud accents if you keep the number low when you're starting with a velocity that's already relatively loud.), and a different character when the number is higher.

 

Len - changes the gate length.

 

Sustain - adds sustain to some notes.

 

NoFX - temporarily disables Echo and LFO.

 

+Echo - Adds echo to some notes.  Uses the settings on the Echo FX page, ignoring the FX enabled/disabled state on the Echo page.  In other words:  adjust the +Echo setting on the FX robotizer page to occasionally apply echo to notes, using the echo settings currently selected on the FX echo page.

 

+Duplicate - Adds FX Duplicate to some notes.  Uses the settings on the FX Duplicate page.

 

 

Prob, Skip, and NoFX do not have ranges, only probabilities.  The vertical bar and the number for these robotizers controls the same variable.

 

ROBOTIZER MASK:

 

- hold SELECT on the robotize page and use GP buttons to edit robotizer mask (indicated by GP LEDs).  Only selected steps will have robotizers applied to them.  Mask is 16 steps long, so it repeats from measure to measure.

 

 

 

 

DjjYHRg.jpg

 

###############################

 

As a first MIDIbox programming project, I'd like to screw around with the humanize function a bit...  I'm thinking I'll duplicate it, call it humanize2 or something, and add a few enhancements.  To start with I think I'll make note, velocity and length each have individual intensity settings rather than just on/off, then maybe add a few other features, like probability of playing each note, delays and repeats, etc.  Then, I was thinking I might add a "humanize mask" - use the GP buttons to select steps in a measure, and the humanizing would only apply to the selected steps (so you could set it up to only humanize certain steps in each measure).

 

From a look at the code, at least the first couple of items on that list look like relatively easy projects for a C noob.

 

I'm wondering where I should store the data for this though - looking at the code, it seems that seq_cc_trk (defined in seq_cc.h and .c) is used to store the track data that's accessible via CC - eg: the current humanize values are stored there...  I don't want to interfere with the already defined CCs, and there aren't too many free slots apparently.  Since this is just a screwaround project I don't need my variables to be accessible by CC.  Is there another struct where track variables not accessible by CC are stored that I should use?

STM-project.hex

LPC-project.hex

Edited by borfo
Link to comment
Share on other sites

No, there is no other struct, because from my experience sooner or later a user will ask for (external) CC control and then we will be in big trouble if the CC format (128 parameters maximum) hasn't been considered ;-)

 

RAM limitations (especially LPC17) are also a reason why I haven't started with alternative structures yet.

 

However, I consider to start with an alternative struct for MIDIbox V4 Plus, which will only run on a STM32F4 (less RAM limitations, more freedom for extensions).

It could be made accessible via special NRPN channels and loopback ports (for those who want to automate changes).

 

But I'm still not ready to start with this step.

 

However, for your first experiments, just use quick&dirty methods, code could be merged later based on the "official" approach.

 

Best Regards, Thorsten.

Link to comment
Share on other sites

Thanks - I guess I'll just store the data in seq_cc_trk then, and I'll work on the original humanize function rather than duplicating it - doesn't really matter if I use up space in seq_cc_trk since this is just an experiment anyway.

Edited by borfo
Link to comment
Share on other sites

Cool - that was easy...  Still a work in progress, but added an "octave" humanizer (note now switches among notes close to the original note, and octave jumps octaves) and gave each of the humanize options their own intensity rather than just an on/off setting.  I've still got some work to do on how the humanization is applied, and I think I'll also add an overall "probability" setting (the chance that each of the humanizers is applied to each step) and a "skip notes" setting (the chance that a given note won't be played), but I got a basic implementation working anyway... 

 

Is there any documentation on the gp_leds settings anywhere?  This stuff (lights the LEDs to indicate the selected parameter):

 

    case ITEM_GXTY: *gp_leds = 0x0001; break;
    case ITEM_HUMANIZE_OCTAVE: *gp_leds = 0x000e; break;
    case ITEM_HUMANIZE_NOTE: *gp_leds = 0x0010; break;
    case ITEM_HUMANIZE_VELOCITY: *gp_leds = 0x0020; break;
    case ITEM_HUMANIZE_LENGTH: *gp_leds = 0x00c0; break;
 

 

Also, I could probably get away with using 4 bit (or even 2 bit for the octave setting) numbers rather than 8 bit numbers for some of these settings to save some space in seq_cc_trk.  Shorter number ranges would make the humanizers easier to use (no need to turn the encoder so many times), and I could store two settings in one CC byte that way...  Is there an example of storing more than one 2 or 4 bit numbers in the seq_cc_trk bytes anywhere in the codebase?

 

Could I arbitrarily define seq_trk_cc numbers above 0x7f without breaking anything?  I realize these numbers wouldn't be accessible by CC, but if I'm just looking for a place to store variables for purposes of experimenting with the humanize function, would arbitrarily defining higher seq_trk_cc numbers work?

 

Great codebase, by the way TK - it's really easy to work with, even not knowing much at all about C or hardware programming.  The toolchain setup is super easy too - I've had real problems with some other open hardware projects just trying to get to the point where I could compile anything, and the MIOS toolchain setup is super easy...

 

[files deleted...  current project.hex files are in first post]

Edited by borfo
Link to comment
Share on other sites

Fine! :smile:

 

*gp_leds is just a binary coded pattern which will be copied into the 16 DOUT SRs of the GP LEDs.

 The rightmost LED (GP #1) is bit #0, hence at the right side.

 

E.g. 0x0001 -> GP #1 will be set

0x0002 -> GP #2 will be set

0x0003 -> GP #1 and #2 will be set

 

 

Also, I could probably get away with using 4 bit (or even 2 bit for the octave setting) numbers rather than 8 bit numbers for some of these settings to save some space in seq_cc_trk.  Shorter number ranges would make the humanizers easier to use (no need to turn the encoder so many times), and I could store two settings in one CC byte that way...  Is there an example of storing more than one 2 or 4 bit numbers in the seq_cc_trk bytes anywhere in the codebase?

 

The transpose values are a good example:

  u8       transpose_semi:4;  // semitons transpose
  u8       transpose_oct:4;   // octave transpose

 

Could I arbitrarily define seq_trk_cc numbers above 0x7f without breaking anything?  I realize these numbers wouldn't be accessible by CC, but if I'm just looking for a place to store variables for purposes of experimenting with the humanize function, would arbitrarily defining higher seq_trk_cc numbers work?

 

CC numbers above 127 won't be stored in the pattern bank on SD Card.

There is currently no simple way to overcome this limitation.

 

My plan is to write a conversion function which migrates the banks for V4 Plus, but as mentioned above, it's not the right time to start with this.

So, just continue with the quick&dirty way

 

 

Great codebase, by the way TK - it's really easy to work with, even not knowing much at all about C or hardware programming.  The toolchain setup is super easy too - I've had real problems with some other open hardware projects just trying to get to the point where I could compile anything, and the MIOS toolchain setup is super easy...

 

Thanks!

When I look into seq_ui_humanize today, I would change two or three minor details to make it easier customizable (already did this for some other pages).

There is also an error in my code: #define NUM_OF_ITEMS should be 5, not 7, otherwise the cursor inc/dec function isn't working correctly.

 

I will change this before the next release

(but I won't take over your changes yet - too early... ;-)

 

Best Regards, Thorsten.

Link to comment
Share on other sites

Thanks for the answers...

 

CC numbers above 127 won't be stored in the pattern bank on SD Card.

There is currently no simple way to overcome this limitation.

 

So, if I used numbers above 127, they wouldn't save, but apart from that they would work ok without breaking anything?

Link to comment
Share on other sites

Ok...  I implemented a "skip note" humanizer, and added individual probabilities for each of the humanizers, as well as an overall probability that any humanizers will be applied.  The vertical bars beside the humanizer parameters represent the relative probability that that humanizer will be applied (so, for example, you can set it up so notes are changed more often than octaves, etc.)  Hold select and turn the encoders to set the individual probabilities.

 

The numbers under each humanizer are ranges - eg: if Octave is set to 2, the note will jump up or down 0 1, or 2 octaves.  If note is set to 3, the note will jump up or down 0, 1, 2 or 3 notes, in addition to the octave shift.

 

When each humanizer is called, the overall probability is multiplied by that humanizer's individual probability, and that number is compared to a random number.  If the random number is lower, then the humanizer is applied.

 

I weighted the velocity randomization a bit in a totally convoluted "I don't know math" kind of way...  Bad math aside, it produces pretty good-sounding results.

 

This thing is fun to code for...

 

[files deleted...  current project.hex files are in first post]

Edited by borfo
Link to comment
Share on other sites

Wow...  This is pretty fun in combination with FX_echo and the DIR menu page stuff.  WIth a couple of tracks going, this gets very generative sounding...  neat.

 

 

TK - is there a flag I could temporarily set so I could add a "NOFX" humanizer?  ...so that no further FX except force-to-scale (ie: no echo, lfo, etc...) would be applied to the current step before it's played?  ...or temporarily change the number of echo repeats?  ...or temporarily enable sustain?

Edited by borfo
Link to comment
Share on other sites

haha...  Wow, is this thing ever fun to code for.

 

I implemented the humanize mask - on the humanize page hold SELECT and press the GP buttons to edit the 16 step humanize mask.  If the current step % (modulo) 16 is active in the step mask, then humanize will be applied.  If not active in the humanize mask, the current step will not be humanized.

 

I also added an on/off switch for the humanize function.

 

This codebase is great - most of this stuff "just worked" on my first try, and I'm more or less guessing at how to call global variables, and how to deal with steps...

 

[files deleted...  current project.hex files are in first post]

Edited by borfo
Link to comment
Share on other sites

In making this, I broke (commented out) the bit of code in seq_humanize.c that checks for the random trigger layer:

 

  // check if random value trigger set
  if( SEQ_TRG_RandomValueGet(track, step, 0) ) {//RK - I broke this.
//    mode = 0x01; // Note Only
//    intensity = 4*24; // +/- 1 octave
  } else {
 

 

...and a bunch of my humanize variables are declared out of the OK CC range (above 127) in seq_trk_cc

 

//RK - probability vars - out of normal CC range
#define SEQ_CC_HUMANIZE_SKIP_PROBABILITY    0x80
#define SEQ_CC_HUMANIZE_OCT_PROBABILITY        0x81
#define SEQ_CC_HUMANIZE_NOTE_PROBABILITY    0x82
#define SEQ_CC_HUMANIZE_VEL_PROBABILITY        0x83
#define SEQ_CC_HUMANIZE_LEN_PROBABILITY        0x84
#define SEQ_CC_HUMANIZE_ACTIVE        0x85
#define SEQ_CC_HUMANIZE_MASK1        0x86
#define SEQ_CC_HUMANIZE_MASK2        0x87

 

 

There were a few small changes to some other files required to make this compile (commenting out saving the old humanize variables, for example)...  But the main stuff to get this to work is in the files I've attached above.

 

I just listened to three one-bar tracks play more or less by themselves for like an hour...  This thing produces pretty musical results...  Lots of little subtle (and not so subtle) variations...

 

...edited the first post to add the .hex files, a brief description of the added features, and a picture of the UI.

Edited by borfo
Link to comment
Share on other sites

I just listened to three one-bar tracks play more or less by themselves for like an hour...  This thing produces pretty musical results...  Lots of little subtle (and not so subtle) variations...

 

This motivated me to integrate your current code into the firmware in the way that it doesn't affect the legacy humanize function, and everybody will be able to try it out (with the known store/restore limitations).

 

It's in seq_ui_fx_humanize2.c and seq_humanize2.c now

All new CCs got the "humanize2" prefix and are above 127

 

Please take over the changes to simplify sharing :smile:

 

It seems that the UI doesn't give access to all parameters yet, right?

Note that I simplified the parameter modification handling (and I did the same improvements in seq_ui_humanize.c): the button handler calls the encoder handling with incrementer=0, so that the same code can be used for both control elements.

 

 

Btw.: is this still a "humanizer"?

Or a randomizer, or robotizer, or noodleizer? ;-)

 

Best Regards, Thorsten.

Link to comment
Share on other sites

Cool.  Thanks!

 

It seems that the UI doesn't give access to all parameters yet, right?

 

Did you grab my code from my last post with attachments?  Everything should be working...  Does the version you were working from have the "humanize mask" thing (hold select to edit, mask is indicated by GP LEDs, and edited with SELECT+GP buttons, steps not in the mask don't get humanized)?  If you're working from that version, all the UI elements should work.

 

Btw.: is this still a "humanizer"?

Or a randomizer, or robotizer, or noodleizer? ;-)

 

I vote for "Robotizer."

Edited by borfo
Link to comment
Share on other sites

Ok, taken over.

 

The UI handling is not really intuitive, the second parameter layer activated with the SELECT button is some kind of hidden function, there is no display change if SELECT is pressed - so without knowing this, somebody could think that the Fx is not working.

 

I also did a minor optimisation in seq_humanize2.ct: check for the humnote/humoct/humvel/humlen first before fetching a random number, this saves some cycles if the function is not activated.

 

Best Regards, Thorsten.

Link to comment
Share on other sites

@Borfo: could you please integrate the changes into the new "*humanize2*" files by yourself and give me the changed code?

 

I just want to ensure that I don't miss anything again, and that we are working with the same sources.

 

Best Regards, Thorsten.

Link to comment
Share on other sites

OK.  I added a NoFX function, which disables effects applied after the Robotizer temporarily, for the current step.  Right now it only disables LFO and Echo - I figured people might want to use the limiter after the Robotizer.

 

I'm working on three more robotizers: Sustain (sustains the current note until the next note is played), Add Echo to the step (even if echo is disabled), and Add Duplicate.  But they're a little more complicated than the others, and I don't want to fuck anything up, so they're not fully implemented in this version - the parts that are done are commented out of the UI.

 

Here are the files.  There are changes in all the files attached.  I changed the name from Humanizer2 to Robotizer throughout, including filenames, so there are a few more changes to make outside of the attached files.  Specifically:

 

seq_live.c
29: change filename to robotize.h

Change HUMANIZE2 function call to ROBOTIZE


Replace the following references to HUMANIZE2 with ROBOTIZE

seq_ui.h:328:extern s32 SEQ_UI_FX_HUMANIZE2_Init(u32 mode);
seq_ui_fx.c:34:  SEQ_UI_PAGE_FX_HUMANIZE2, // GP3
seq_ui_pages.h:68:  SEQ_UI_PAGE_FX_HUMANIZE2 = 38,

And replace this:
seq_ui_pages.c:85:  { "FX_HUMANIZER2","Hum2 ", "Track Fx: Hum.2   ", 57, (void *)&SEQ_UI_FX_HUMANIZE2_Init },

With this:
  { "FX_ROBOTIZE",  "Robo ", "Track Fx: Robotize", 57, (void *)&SEQ_UI_FX_ROBOTIZE_Init },


And replace this:
seq_ui_fx.c:133:  SEQ_LCD_PrintString("Echo Hum. Hum2 Limit LFO Dupl.");

With this:
  SEQ_LCD_PrintString("Echo Hum. Robo Limit LFO Dupl.");

 

ALSO - the main FX Menu page seems to be broken in my local copy, either because of something in rev. 2117, or because of one of the lines above...  Loop and Scale are offset on the LCD from the GP button that controls them...  Loop is over GP 10, Scale is over GP 11, but GP9 and GP10 control them.
 

 

 

How to use the thing:

 

MENU+FX -> Robo - enters the robotizer page

 

Robot on/off - enables and disables all robotizers for this track.

 

Prob - the overall probability that any robotizers are applied.  This overall probability setting is combined with individual probability settings for each robotizer, so you can make one robotizer happen more often than others (eg: change notes often, but never skip them, and only rarely change the velocity).  Hold SELECT and use encoders to set individual robotizer probabilities (indicated by vertical bars beside each robotizer).  Individual probability is multiplied by overall probability, then compared with a random number.  If the random number is lower, then the robotizer will be applied.  A different random number is called for each individual robotizer.

 

Skip - skip steps (play them at zero velocity)

 

Octave - changes octaves.  the selected number is the range - if "2" is selected, the note will jump up or down 0, 1, or 2 octaves.

 

Note - changes notes.  Cumulative with octave changes.

 

VelCC - velocity changes.  This robotizer is weighted using some bad math in order to avoid out-of-range numbers, and produce more musical results.  As a result of the way it's implemented, it's got a distinct character when the numbers are low (you'll get more loud accents if you keep the number low when you're starting with a velocity that's already relatively loud.), and a different character when the number is higher.

 

Len - changes the gate length.

 

NoFX - temporarily disables Echo and LFO.

 

 

Prob, Skip, and NoFX do not have ranges, only probabilities.  The vertical bar and the number for these robotizers controls the same variable.

 

ROBOTIZER MASK:

 

- hold SELECT on the robotize page and use GP buttons to edit robotizer mask (indicated by GP LEDs).  Only selected steps will have robotizers applied to them.  Mask is 16 steps long, so it repeats from measure to measure.

seq_cc.c

seq_cc.h

seq_core.c

seq_robotize.c

seq_robotize.h

seq_ui_fx_robotize.c

LPC-project.hex

Edited by borfo
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...