Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sequins.lua - musical structure utilities #359

Closed
trentgill opened this issue Aug 3, 2020 · 2 comments
Closed

Sequins.lua - musical structure utilities #359

trentgill opened this issue Aug 3, 2020 · 2 comments
Labels
enhancement New feature or request

Comments

@trentgill
Copy link
Collaborator

From the Maps stream, I came up with some fun functions that allow for a more streamlined approach to building basic arpeggiators and such. They would likely be great additions to the crow (and norns) standard libraries.

Below is the example in question, particularly useful for generating arpeggios and basic sequences, but it could be expanded into slightly more of a library such that the 'scales' could be updated on the fly (at present they are captured & owned by the arp). Naming could be improved as there are likely implications beyond simple arpeggiators.

--- the userspace function call style
myskal = {3,6,9,15,18,21,-6}
myarp2 = run_arp( function(v) ii.wsyn.play_note(v,3) end -- what to do at each note of the arp
		, make_sequence( myskal, 'next' ) -- a generator to return the next arp note
		, 4/3 -- a timing in 'clock' module style
		)

-- takes an action, a generator, and a timing
function run_arp( fn, seq, sync )
  return clock.run(
    function()
      while true do
        clock.sync( sync )
        fn( seq() )
      end
    end)
end

-- generator that takes a table & a behaviour, returning a function that will give the next step
-- arg1: scale table eg{0,2,4,7,9}
-- arg2: behaviour enum:{'next','prev',rand','drunk'} -- n as next#
-- retv: function that generates the next note
function make_sequence( skal, behaviour )
  skix = 1
  return
    function() -- was 'new_note'
      if behaviour == 'next' then
        skix = skix + 1
      elseif behaviour == 'prev' then
        skix = skix - 1
      elseif behaviour == 'rand' then
        skix = math.random(#skal)
      elseif behaviour == 'drunk' then
        skix = skix + math.random(-1,1)
      end
      -- clamp to skal size
      while skix < 1 do skix = skix + #skal end
      while skix > #skal do skix = skix - #skal end
      -- scale 12TET notes to v8
      return skal[skix] /12
    end
end

Also, there is the possibility of using the clock library for (re)implementing ASL style constructs where the output is a control-rate destination. Particularly useful for ii destinations where we can't & don't need audio rate ASL generation. Instead, generating each 'frame' in lua is fine. Would be nice to provide versions of the the asllib.lua functions which are applied to a generic function at a given framerate. Could be useful for dynamic sample-rate reduction (read sample&hold) of the functions.

-- userspace call
mylfo = fn_lfo(
    function(v)
      ii.wsyn.fm_index(v)
      output[1].volts = v
    end)

function fn_lfo( fn, duration, min, max, fps )
  -- set defaults
  duration, min, max, fps = duration or 1
                          , min or 0
                          , max or 5
                          , fps or 30
  local phase = 0
  local range = max - min
  return clock.run(
    function()
      while true do
        phase = phase + 1/(duration*fps)
        while phase >= 1 do phase = phase -1 end -- wrap
        -- TODO add 'shapes' here. currently just triangle. ramp/sawtooth is even easier
        local o = phase * 2      -- triangle
        o = (o > 1) and 1-o or o -- triangle
        o = o * range + min -- maps to [min,max]
        fn( o )
        clock.sleep(1/fps)
      end
    end)
end
@trentgill trentgill added the enhancement New feature or request label Aug 3, 2020
@ryanlaws
Copy link

This reminds me a fair amount of SuperCollider's (stream-based, event-generating) pattern library, which you may already be familiar with. For example, this is a rough translation of myarp from the first code block (NB velocity of 3 is very loud in SC-land!):
Pbind(\note, Pseq([3,6,9,15,18,21,-6], inf), \amp, 3, \dur, 4/3).play;
I have been thinking about translating some of these pattern constructs into lua within crow/norns, so it is encouraging to see a simple implementation above. These could be building blocks for a basic composition/synthesis environment (which may or may not jibe with current design goals).

@trentgill trentgill changed the title Add musical structure utilities Sequins.lua - musical structure utilities Apr 20, 2021
This was referenced Apr 21, 2021
@trentgill
Copy link
Collaborator Author

fixed in #387

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants