^^ crow strategies: Just Friends

works perfectly for me with crow + m4l. what version of ableton are you on?

1 Like
  1. haven’t updated to 11.1 yet but will do so this week

hmm, have been reports of crashes with m4l devices and ableton 11 but not heared of troubles with the crow pack…

I’m trying to query the JF voices to see which one is free.
According to the Just Type help page, I should be able to do something like the following to see if, when the strum() function is called by the clock, the channel (in this case 1) is free or not. Whatever I do, it keeps repeating that it’s true in the rate of the clock. Maybe I’m not getting something- how does this work?

function strum()
  while true do
  
    clock.sync(1/2)
    
    -- check if voice 1 is free
    channel = 1
    if crow.ii.jf.get('trigger', channel) == True then
      print("true!")
    else
      print("false!")
    end

    note = math.random(#notes[1])
    crow.ii.jf.pitch(math.random(6),(notes[noteSet][note]/12-1)+tune)
    crow.ii.jf.trigger(math.random(6),1)
    
  end
end

crow.ii.jf.event = function( e, value )
  if e.name == 'trigger' then
    -- handle trigger response
      -- e.arg: first argument, ie channel
      -- e.device: index of device
      print(e.arg)
  end
end

The problem (or at least one of) is that crow.ii.jf.get(...) doesn’t return anything! It triggers an asynchronous event that is received in the crow.ii.jf.event() handler (which you have correctly configured). Where you are printing print(e.arg) in that handler, try adding the value so you can see what it’s actually reporting: print(e.arg, value).

Secondly, I think that in lua truthy is true, not True though I could be wrong and it has an upper-case alias (regardless, changing that won’t fix this case).

I think that when you get the 'trigger', it will return 1 or 0 (rather than true and false) though I’d confirm that by looking at the print in the event handler.

Curious why you’re trying to inspect the voice allocator (though it’s cool that you can! i didn’t conceive of that as a use-case when getting trigger states). I always assumed people would use the in-built play_note allocator, or make their own custom allocator and use play_voice instead.

1 Like

Thank you, it seems your assumptions are right, on true being lowercase and trigger not returning true/false…
though value always returns 1 for me, even if I make sure it is playing or not by commenting out the triggering of the voice. Any idea why? This is my code:

function strum()
  while true do
    clock.sync(1/8)
    
    -- check if voice 1 is free
    channel = 1
    crow.ii.jf.get('trigger', channel)

    note = math.random(#notes[1])
    crow.ii.jf.pitch(math.random(6),(notes[noteSet][note]/12-1)+tune)
    --crow.ii.jf.trigger(math.random(6),1)
    
  end
end

crow.ii.jf.event = function( e, value )
  if e.name == 'trigger' then
    -- handle trigger response
      -- e.arg: first argument, ie channel
      -- e.device: index of device
      print(e.arg, value)
  end
end

As for why I’m trying to inspect the voice allocator- after making my Tidbit script I had this (still vague) idea of doing a slow version. Vague idea incoming:
It would have slow moving notes that would never suddenly change pitch while they are playing (so no triggering notes that are playing, hence the need for this). It would however have gradual/glissandi-like pitch changes during its AR envelope (is this possible at all?). It would be called HIKE and would look like six mountains on Norns display, and some animation would indicate the pitch and the AR envelope form. Of course this would be influenced by twiddling TIME. Anyway the idea is not complete yet, but I have a hunch this could be interesting.

EDIT: simpler said- this would allow you to play notes only when there is one voice free- making the TIME knob also responsible for the rate new notes are let in- and making sure there are not sudden pitch changes while envelopes are going.

1 Like

sounds really interesting!

i think the issue is the way get 'trigger' is implemented might mean it’s always 1 when in synthesis mode. the reason being, trigger returns whether the channel is in motion – i don’t think this variable tracks whether the volume has hit zero, so when the oscillator goes silent it is still oscillating (just being muted), like in an analogue oscillator.

for your idea of the frequency of notes being played being relatively to the TIME knob, you could just poll the value of time with crow.ii.jf.get 'time' (receiving the value in the jf.event handler), and control a norns clock which triggers the notes. i’d use jf.play_voice and build a simple round-robin allocator – it’s just a wrapping counter from 1 to 6.

regarding the gliss idea, there is no in-built support for this (JF is already at the limit of processing power in synthesis mode). the way i’d suggest to try it is with something like the fnl function i made for a maps stream (ep3.lua · GitHub) – it lets you continuously sweep values over i2c with a given framerate. you’ll probably need to experiment with the speed, and interleaving the oscillators to find something stable though (as the technique can easily saturate the i2c bus).

4 Likes

Thank you so much! This is great and it’s wonderful to hear a bit about how things are implemented! A lot to unpack and to experiment with here… I’ll try some stuff out :slight_smile: Thanks!

I’ve been using a crow script running Just Friends as a synthesizer. After I change to a different script in Crow, something unrelated to JF, JF continues to run in the same mode. I’m not sure how to get it back to it’s normal operation. Is there an ii.jf___ command to quit?

ii.jf.mode(0) should switch it. 1 is synth mode, 0 is standard

2 Likes

is it only some JF’s that behave this way when working with crow or do you always have to send JF this command to get it back to normal?

in my own experience, jf will reset to non-synth mode after power cycling. if you’re not rebooting, it will continue running in synth mode until you tell it not to.

if it’s an option/useful, i sometimes add some code to switch modes when one of the inputs receives a gate

2 Likes

Not crow-related, but other modules will also affect the mode of JF. In particular I find that Ansible will put JF into synth mode on startup, if it was set to send output to JF before it was powered down. That can be a knotty problem if you don’t have a grid with you when you turn the case on the next time.

2 Likes

Unexpected mode changes for JF over i2c are a bit problematic in my experience and have often lead to me frantically trying a bunch of different things on crow, Ansible, teletype to try and get JF back to normal. I’m not sure what the answer is, but I wonder if at least every device that can switch JF to mode 1 never does so unless explicitly told to by the user. So, for Ansible, it should start up in mode 0 even if it shut down in mode 1, and for teletype it shouldn’t switch to mode 1 even if a JF.NOTE command is sent (iirc this will quietly switch JF to mode 1).

I also kind of wish there was a way on JF itself to reset back to mode 0 by wiggling the switch a bunch of times or something. Although I guess that wouldn’t prevent it being switched back again by Ansible.

this is not happening for me. i routinely use jf.note commands in my scripts, and as long you don’t put the mode switch (jf.mode 1) in your init script, jf will not respond to note commands and will function as normal.

Interesting… I wonder if it might be Ansible for me that’s doing this. Will do more testing!

9 posts were merged into an existing topic: ^^ crow: max for live + max: updated 210630

Hi everyone,

I’m not sure about it and I didn’t found an answer so I wanted to ask. Is it possible to use ii.jf.retune with the Synthesis mode ? So, it could be possible to tune each voice with ratios instead of volts ? Thank you !

retune won’t get you what you want, but you can use the regular ii.jf.play_note (or play_voice), and generate the pitch argument with the justvolts function. It’d look something like:

ii.jf.play_note( justvolts(3/2), 3)

you could wrap this in a helper function if you want it feel different, eg:

jf_play_ratio( 3, 2 )
4 Likes

Oh I see, fantastic ! Thanks a lot. I was too focused on the Just Type reference on github and missed the globals on the crow script reference.