What the best practices for saving Gibberwocky scripts within Max patches?
And is there an automated way to reload them?

If not do people just save them as text files outside of the patch (or maybe inside via a comment or something?) and manually reload them?

Also, I’m brand new to the language and I’ve got my first patch hooked up and communicating. I’m trying to make values smoothly transition using .seq instead of jump though. The line documentation is hurting my head a bit. I tried to modify the example but it’s still jumping the ratio message and not interpolating it. Any ideas?

l = line( 4, 2.9, 3.1 )
message( 'ratio' ).seq(l, 2  )

l.start.seq( [2,3.8,4], 2 )
l.period.seq( [1/2,1],1 )

Thank you.

If you’re using https://gibberwocky.cc/burble as the editor, you can use Ctrl+Shift+S to save your current file and then Ctrl+Shift+L to load this. This is only for a single script, so I use it to save functions / values that I might want to use across multiple gibberwocky sessions… “setting the stage” if you will. Otherwise, yes, unfortunately I just save by copying/pasting into a text editor. There might be some improvements to that coming this summer.

In regards to the line example you posted, it should sample the line every two measures, changing the start/period at various other times. Is the problem that this isn’t the behavior you see, or is that it’s not the behavior you were expecting?

Thanks for trying gibberwocky out!

1 Like

Thanks @charlieroberts.

Essentially I’d like the simplest way possible to do something like this:
message( 'ratio' ).seq( [2.9,3.1], 2 )
But have the values slowly move from 2.9 to 3.1 (for instance) over the course of 2 measures instead of jumping every 2 measures.

And got it re: the editor. Do you save them in an external editor? Or do you save them in Max somehow And speaking of, is it possible to use a code editor instead of https://gibberwocky.cc/burble ?

Cheers!
Ben

It would be nice if there was some concept of control rate in the Max version of gibberwocky, but I don’t think it currently exists. So, you can either use line to make a gen~ expression in [gibberwocky] and sample it in Max (see the “modulating with gen~ tutorial”), or you can just sequence using your line object at a much faster rate. For example, this should sent an interpolated ‘ratio’ message every 1/128th note, the line has a period of two measures:

l = line( 2, 2.9, 3.1 )
message( 'ratio' ).seq( l, 1/128  )

I don’t have a way to save sketches in Max currently, I just use an external editor. An Atom plugin was made a while back, but I think the project would need to be updated to work correctly (https://github.com/wichniowski/atom-gibberwocky). Hope to make some progress on better editor support this summer.

1 Like

Thanks again @charlieroberts. I’ll check out that ~gen tutorial.

So essentially I wasn’t sampling the line enough? I’d still have to do this full code to step through values in the line, correct?

l = line( 4, 2, 3.5 )
message( 'ratio' ).seq( l, 1/128  )
l.start.seq( [2,3.8,4], 2 )
l.period.seq( [2,3,4],2 )

I realized that because this is all within Max I can very easily achieve what I’m looking for by slewing in Max after receiving the stepped values from Gibberwocky. I’d ideally like to understand the language better but it works for now this way as well. Thanks.

Yeah, just applying some type of slewing / lowpass on the stepped signal should work well!

Here’s what should be happening the way you have the code now:

// create a line/ramp/phasor/sawtooth traveling from 2 to 3.5 over four measures
l = line( 4, 2, 3.5 )
// sample the line object each 1/128 note and send the result out the left [gibberwocky] outlet
// output with the prefix 'ratio'
message( 'ratio' ).seq( l, 1/128  )
// every two measures, change the minimum/start value of the line
// note: I have no idea what happens when the start value is greater than the end value in line() !
l.start.seq( [2,3.8,4], 2 )
// every two measures, change the period of the line
l.period.seq( [2,3,4],2 )

Hope that’s helpful!

2 Likes

Super helpful thank you!

2 Likes

Hey @charlieroberts. I’m back with a few more questions, lol.
I’ve been exploring the integration with some Max patches and loving the results I’m getting with it.

My first question is about gaining control back via the Max gui objects after I’ve stopped the Gibberwocky control. I assumed that .clear() would work but it doesn’t seem to be. Am I using it wrong? I tried .stop() before the clear messages but that didn’t seem to make a difference. I also tried separating the commands with a carriage return in between.

l = line( 4, 2.9, 3.1 )
message( 'ratio' ).seq( l, 2  ).clear()
l.start.seq( [2.015,3.8,4], 2 ).clear()
l.period.seq( [1/2,1], 1 ).clear()
params[ 'Slew' ].seq( [20, 30, 80], 1.99 ).clear()

I’ve also noticed one persistent bug with the graph displays for visual feedback. It consistently removes the comma after the closed bracket here:

l.start.seq( [2.015,3.8,4], 2 ).clear()
and turns it into:
l.start.seq( [2.015,3.8,4] 2 ).clear()
I then get errors on upon that when I do the next evaluation.

As always, thank you!

EDIT: Sometimes the bug seems to remove the bracket FYI

Yeah, that graph display bug is really annoying. I’ll try to see if I can fix it this week.

In regards to stopping the sequences, there’s a bit towards the end of the “basic sequencing” tutorial that talks about how sequencers are assigned different ID numbers. Unfortunately, the tutorial doesn’t get into how you use these ID numbers, which is the info that you actually need.

In your case you’re only applying one sequence to each property, so all of them use the default ID of 0. This means you can target them as follows:

l.start[ 0 ].stop()
l.period[ 0 ].stop()
message( 'ratio' )[ 0 ].stop()
params[ 'Slew' ][ 0 ].stop()

If you create multiple sequencers targeting properties you then need to specify individual sequence IDs, as a third parameter to any call to .seq(), you can then use that ID to select that particular sequence for manipulation.

You can see a little bit more of this syntax for targeting sequences in the “patterns and pattern transformations” tutorial as well.

1 Like

Ah. Brilliant thank you!

EDIT: Sorry @charlieroberts , a follow up question.
That syntax doesn’t seem to be working with sequenced params. ie:

params[ 'Slew' ].seq( [820, 1030, 1400], 2, 0 )

params[ 'Slew' ][ 0 ].stop() 

I noticed in the documentation that params don’t have any methods mentioned. Does this explain why that doesn’t work but adding a .stop() does? ie:

params[ 'Slew' ].seq( [820, 1030, 1400], 2, 0 ).stop()

Thanks again!

Hmmmm… I can’t recreate this bug. Using the gibberwocky.maxhelp patch, I can run this line from the introductory tutorial:

params['White_Queen'].seq( [10,32,64,92,127], 1 )

and then stop it with:

params['White_Queen'][0].stop()

… as well as restart it with a call to .start().

One other idea you could try… every call to .seq() returns the generated sequencer object. You could store that in a variable and then use that reference to stop/start. For example:

seq = params['White_Queen'].seq( [10,32,64,92,127], 1 )
// wait some amount of time and then...
seq.stop()
1 Like

I’m curious on how to implement the accumulator if you get a sec.

I’d like the second value in both of the seq arrays to accumulate by an integer of 1 each time the seq loops. So the 1.75 and 4.8 values below:

message( 'ratio' ).seq( [1.5, 1.75], [8, 4.8] )

Should I store those values as variables and run accum on them?
I’m sure it’s not right as it doesn’t work, but something like this?

one = 1.75
one.accum(1, 1.75, 5.75)
two = 4.8
two.accum(1, 4.8, 10.8)
message( 'ratio' ).seq( [1.5, one], [2, two] )

Thank you for all your help.
B

Hmmm… so that’s getting outside of the built-in gibberwocky functions; we’ll need to write some (very short) custom JavaScript functions to make this happen. In our arrays, our second items will be functions that will return the value of variables. Then we’ll create a standalone sequencer that updates those values over time.

If you haven’t done much JS before ()=>{ //some code } is shorthand to create a function that executes a chunk of code, ()=>someValue is even shorter and creates a function that returns a value.

value1 = 1.75
value2 = 4.8
message( 'ratio' ).seq( [1.5, ()=>value1 ], [8, ()=>value2 ] )

Seq( ()=> { value1++; value2++ }, [ 8, ()=> value2 ] ).start()

Seq is creates a standalone sequencer object… these objects are created behind the scene whenever you sequence anything. In this case we explicitly create one and tell it to call a function that increments our values.

Please feel free to ask questions about this code chunk!

1 Like

Better way… we just define a function that increments its value and then returns it.

customaccum = (val, incr=1) => {
  return ()=> val += incr
}

message( 'ratio' ).seq( [1.5, customaccum(1.75) ], [8, customaccum(4.8)] )

In this example, the values increment by one by default, but you can also pass an optional second argument to customaccum to change the increment amount.

1 Like

Wow. This is really beautiful @charlieroberts.
Thank you so much!!!

1 Like

Back with two more:

  • I’m a bit confused on how to get fade to work. I tried this:
    params[ 'VelScaleALL' ]( fade( 3, 0.63, 0.8 ) )
    but I get a console message that says: socket live is not ready for messaging which makes me fear that it’s maybe a Live only command? I also tried .fade which is clearly incorrect as well. I’m guessing that I’m just implementing it wrong but is there something similar when using Max if so?

  • Is there a command to stop all of the sequencers globally?
    Like a way to script All sequencers stopped?

Thanks as ever!

1 Like

In regards to fade, a couple of problems. fade() uses gen~ expressions, which means in gibberwocky.max it can only be used with the dedicated gen~ outputs of the [gibberwocky] object. But as you noted, it seems that gibberwocky is currently hardcoded to try and send messages to Live when the fade end. I can fix that (I think) but getting it to work with params might be very difficult.

If you want to stop sequencers but leave gen~ expressions running you can use:

Seq._seqs.forEach( s => s.stop() )

Seq._seqs basically stores all running sequences. But I’ll add a simpler global stop() and start() functions next time I push to the main website. Thanks for the suggestion!

Thanks @charlieroberts.

I’ve got .line working over here with a corresponding .stop message after the fade so all good.
And thanks on being open to the global stop idea!

Ben

Recently started diving into Gibberwocky and totally loving it, I’ve been using Max/MSP and Live on a daily basis for years now and it feels so refreshing to have access to things such as LOM and gen~ via code, the syntax is also way more appealing to me than the Haskell-y form of Tidal.

On the other hand, I was wondering if there’s any way to customize the editor (things such as cursor behaviour - I believe it’s by default set on emacs mode - and theme or keymaps). I did try to get into the Atom package but am having some difficulties to get it running on Mac OS Mojave 10.14.6 (I know this is not the right thread to talk about this) and I find the local editor to be so cool anyway. I was just wondering if there’s any way to make the typing enviroment a bit more personal (that’s the only reason why I’d be looking into the Atom version).

@charlieroberts congrats for creating such a cool platform and integration, not detouring too much from my daily tools makes my live-coding(-ish) practices way more useful and intriguing :slight_smile:

2 Likes

Thank you @Ste_v ! glad you’re enjoying it.

I totally understand the desire to use your own editor / personalize the editing experience, and I wish the Atom plugin worked, but I don’t think the project-owner has done anything with it in quite some time.

But you can add your own key commands like so:

Gibber.Environment.keymap['Alt-N'] = ()=> tracks[0].note(0)

If you’re looking for something like vim mode, I could add that in; it’s in gibber so the port is fairly easy. If you want to try the theme system in gibber (a tiny wrapper around @neauoire’s awesome theme work) and see if it works for you I could potentially add it to gibberwocky as well (although it’d be a bit more work): Gibber

Can you describe the cursor behavior you’d like control over?

3 Likes