Giter VIP home page Giter VIP logo

Comments (21)

crisptrutski avatar crisptrutski commented on May 18, 2024

In case you haven't encountered it - Tidal has an interesting way of expressing rhythm: https://github.com/tidalcycles/Tidal/blob/master/doc/tidal.md#sequences.

Not sure if the {} and [] notations for polyphony are useful when alda already has voices, but a shorthand for repetition and being able to nest these "time warps" is quite convenient.

Regarding the suggested * syntax, that seems clunky, and in the worst-case more verbose and less readable. Is there an issue with using the regular syntax, and then scaling all note durations based on the given duration of sequence / total of naive note durations in sequence?

from alda.

oz-codes avatar oz-codes commented on May 18, 2024

I think that this format is actually extremely intuitive and functional, and I can't wait to put it to personal use.

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

Hope that I didn't come across too forthright - more enthused than anything! This is exactly the kind of feature I'd enjoy using too, in the proposed form or with amendments 😄

To clear up what I'm saying about * as emphasis token, let me use some examples:

  1. {a2 b8 c d e16 f g}4 vs. {e************ b* c* d* e f g}4 (don't make me count)
  2. {{e f g}* }4 (if we support nesting, do crams need to support emphasis?)
  3. {a2 b*} (is this illegal? what does that mean about recursively calling existing patterns in a cram?)

Hence suggest that the usual notation applies, and actual lengths of notes are calculated by the obvious scaling, ie. {a4 e1}4 would have durations of 1/20th and 1/5th of a bar respectively, to give the duration of a quarter note, ie. the same meaning as {a16 e4}4 or {a12 e3}4

from alda.

daveyarwood avatar daveyarwood commented on May 18, 2024

@crisptrutski I totally agree! I really like what you're proposing -- it's much more elegant than my idea, and probably more intuitive. So basically, we would add up the note values inside the curly braces to get a total note value, and determine each note's lion-share of the total time (the note value to the right of the close curly brace) by dividing it by the total note value. Makes perfect sense to me.

I also like the idea of nesting -- it would make it easier to represent really complex rhythms.

from alda.

daveyarwood avatar daveyarwood commented on May 18, 2024

Somewhat off-topic, but this paper is a really interesting read involving algorithmic polyrhythms: http://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

Plan on fooling around with this sometime over the coming weekend 🎃

from alda.

daveyarwood avatar daveyarwood commented on May 18, 2024

🤘🎃🤘

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

OK, I'm cracking this open now!

First idea - use a macro to parse the notes inside the expression, but that fights against the "outside-in" resolution of macros. Next idea is to use binding to isolate changes to the main *dynamic-vars* in alda.lisp (and clear out the events), calculate the new events, scale their offsets and durations, and then reinject those events back into the root scope.

Simpler ideas welcome ^^,

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

Oh, also going to reset the environment's duration to a quarter note in the rebinding also. Let me know if you disagree with this, or if I'm missing any other attributes that need special treatment

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

RE: the grammer, I'm thinking we should only allow events inside the {} brackets - correct?

from alda.

daveyarwood avatar daveyarwood commented on May 18, 2024

RE: the grammer, I'm thinking we should only allow events inside the {} brackets - correct?

Seems legit. We probably don't want to allow voice groups (which are not technically events) or switching instruments inside the brackets. Basically it's like stretching the fabric of space-time around a portion of an instrument part's events 🌌

Oh, also going to reset the environment's duration to a quarter note in the rebinding also. Let me know if you disagree with this, or if I'm missing any other attributes that need special treatment

That sounds OK to me! We can always patch it in the future if it ends up confusing people.

OK, I'm cracking this open now!

First idea - use a macro to parse the notes inside the expression, but that fights against the "outside-in" resolution of macros. Next idea is to use binding to isolate changes to the main dynamic-vars in alda.lisp (and clear out the events), calculate the new events, scale their offsets and durations, and then reinject those events back into the root scope.

Simpler ideas welcome ^^,

I think the approach I would take is to add a new dynamic var like *time-scale-factor* or something, and use that in the calculation of durations. Then there could be a macro that binds *time-scale-factor* to a new value and evaluates the body within that context.

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

@daveyarwood OK, that approach might not work, because alter-var-root refers to.. the root. Don't think we can imperatively mutates dynamic bindings

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

Stretching time is appealing.. the issue is you still need to inspect the time taken before stretching. I guess you could eval with custom bindings, get the duration, then set the stretch-factor and eval again. That way you never nest the bindings and my current hurdle is solved.

Just seems inefficient, going to soldier on a little bit longer 🐻

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

Hmm.. push-thread-bindings seems to be end of the line unless I code to the Java implementation. That won't be fun to port to CLJS 😨

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

This is the part where I curse you for making alda.lisp global side effect based 😜

from alda.

daveyarwood avatar daveyarwood commented on May 18, 2024

Thanks to @crisptrutski's awesome work, we're very close to having C.R.A.M. (we should totally adopt this backronym in the official docs!) implemented. 🎩 🌟

Thinking ahead a bit to the "exact second/millisecond durations" part of this issue, we could implement that as a new alda.lisp function called exact-duration or duration-ms, which acts like a simplified version of duration that just returns a map that has a :duration-fn key, e.g. {:duration-fn (constantly 3000)}. I'm still in favor of adding first-class Alda syntax for this feature, as well, e.g. c60s (60 seconds), d+500ms (500 milliseconds)

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

OK, will see about adding that last part tonight. When it comes to "memory" of notes, that is based around beats at the moment, so it might be worth refactoring slightly so that the the duration state can be beat OR duration based, so that tempo changes interact as expected with both kinds of persistence.

Naming wise I'll go with duration-ms - exact-duration makes duration sound a bit too sloppy 😉

from alda.

daveyarwood avatar daveyarwood commented on May 18, 2024

When I have a chance, I might take a look at trying to simplify the way CRAM is implemented -- it's pretty snappy for me when running small snippets in the REPL, but evaluating multi-poly.alda takes a while, which makes me wonder if there are performance issues due to the whole "dry run, then rollback" thing.

from alda.

crisptrutski avatar crisptrutski commented on May 18, 2024

Definitely super slow - added that file as a benchmark intentionally, those nested crams are exponentially expensive. No argument that dry run sucks 😄

Got pretty close to getting it working without in first attempt, but will need either code-walking macros or refactoring of alda.lisp. Of those I prefer the second 😄

from alda.

daveyarwood avatar daveyarwood commented on May 18, 2024

(Reopening this until the "exact seconds/millisecond durations" feature is implemented)

from alda.

daveyarwood avatar daveyarwood commented on May 18, 2024

Working on second/millisecond durations now. I've decided to take a more flexible approach, creating an alternative to note-length instead of an alternative to duration.

e.g.:

# alda syntax
2000ms

# parses into
(duration (ms 2000))

The nice thing about this is that it creates the possibility of combining note-lengths (which represent a number of beats and are used in the context of the current tempo to calculate the length of the note in ms) with exact second/millisecond durations:

# alda syntax
4~2000ms

# parses into
(duration (note-length 4) (ms 2000))

The above duration == however long a quarter note is at the current tempo, plus 2000 ms.

from alda.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.