Dial 0.2.0

Dial

Marks notches in time.

Dial is a polyrhythmic, polyphasic clock source/metronome and ramp/phasor generator.

I occasionally jam with local friends in a very small group. I usually bring some MIDI gear with a solid clock, and I wanted a similarly solid CV clock source to see if I could get away from MIDI. Naturally I also wanted to do something a little weird with it.

Caveat usor: I have not yet tested enough to have confidence in the actual solidity of this clock, but it sounds pretty good to me :slight_smile:

Requirements

Crow 2.0.0

Controls

  • In 1: BPM voltage input
  • Out 1-4: Arbitrary ASL actions (default pulse(0.001)), or phasors

Reconcilers

Dial uses what it calls reconcilers to figure out when a full cycle has elapsed, what its boundaries are, and what to do when they are crossed.

native(asl_action)

This reconciler takes an ASL action as its argument. On setup it will attach this action to the output, and will trigger the output when the cycle boundary is crossed.
native(pulse(0.01))

raw(start_voltage, end_voltage)

This is the raw output of the phasor, albeit scaled to the specified start and end voltages. These default to 0v and 5v, respectively.
raw(0, 5)

Configuration

Global variables

By changing the settings at the top (well, right below that first big block of comments), you can get up to 4 clock sources with completely different divisions (or multiplications) of the BPM clock.

  • bpm_min / bpm_max - Minimum/maximum BPM.
  • voltage_minimum / voltage_maximum - Minimum/maximum input voltage.

configure()

Modify the contents of this function to change divisor behavior. There are 3 available syntaxes for this.

Divisor only

This is uses the specified divisor with a phase of 0 and native(pulse(0.001)) for the reconciler.

{ 1, 2, 3, 4 }

Numeric table with divisor, phase and reconciler optional

This can provides the same capabilities as in v0.0.1(including the behavior of using pulse(0.001) as the action), but is now specified in one 2D table instead of two 1D tables. A reconciler can be specified as the 3rd item in an inner table.

-- divisor, phase
{ 
  { 1, 0 }, 
  { 2, 0 }, 
  { 3, 0 }, 
  { 4, 0, native(pulse(0.1)) }  -- reconciler specified
}

Call d() with two numbers

This is functionally identical to the previous.

-- divisor, phase
{ 
  d(1, 0), 
  d(2, 0), 
  d(3, 0), 
  d(4, 0, native(pulse(0.1)))
}

Some suggested values are provided in comments in the neighborhood of the default values.

Fun Facts

  • When a reconciler is not specified, ASL’s pulse(0.001) will be used - this is a pulse as brief as allowed in ASL (0.001 seconds, a.k.a. 1ms). Feel free to change this, of course.
  • This will make an attempt to reign the BPM to values that make sense for my use cases in lieu of a display. That is to say, quantized to the nearest integer BPM value, no decimal point. I plan to round it to the nearest multiple of 4 in a subsequent version.

TODO

  • Add input configurability
  • Do something with input 2. Suggestions welcome. Ideas include:
    • Start/stop toggle or some other transport-type feature
    • Phase reset - would require “backup” of initial phases.

Wishlist

  • Configurability via norns

Download

Evergreen - https://github.com/ryanlaws/crowscripts/blob/main/dial.lua
Latest - https://github.com/ryanlaws/crowscripts/releases/tag/dial-0.2.0

19 Likes

this is a really cool idea. simple to grok but really powerful. amazing.

3 Likes

Thank you very much. I’m really just scratching an itch! Your lua chops are well beyond mine, so I appreciate any suggestions you have.

the code looks great. it’s super clean and efficient.

2 Likes

+1000

i also really enjoy the commented out div/phase tables :slight_smile:
looking forward to a dronecaster-esque library of pulse patterning!

1 Like

Dial 0.1.0 has been released. This is a decent refactor which changes configuration syntax/options (apologies if I ruined anyone’s 4-channel pulse masterpiece - I promise porting is easy!) including arbitrary ASL actions and a phasor (ramp/saw) shape, cleans up a little bit of mess, and lays the groundwork for some features I’d like to add soon.


Also there’s tags and releases now. Well, the one tag/release.

EDIT: Documentation updated!

1 Like

Dial 0.2.0 has been released. This adds new reconcilers built on the refactor done in the 0.1.0 release:

  • duty() is a 2-step sequence between 2 arbitrary voltages with arbitrary phase split point
  • split() is a 2-step switch between 2 child reconcilers with arbitrary phase split point (NOTE - this almost definitely does not work with native()!)

Also, the new bpm_quantization configuration allows for quantizing BPM to steps of 1, 2, 4, or 10.

Documentation pending. Please see examples for now.

3 Likes