gogins / cloud-5

Complete browser-based computer music studio for algorithmic composition and live coding

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"Cancycle" for Csound, CsoundAC, and Strudel at Brooklyn College on 10/20/2023.

gogins opened this issue · comments

  • 200 word bio.
  • Program notes.
  • The piece itself - interactive visual music using cloud-5.

Bio

I was born in 1950 in Salt Lake City, and grew up with trips to mountains, deserts, and unlocked university labs. My father was an inventor, my mother an artist. I have pursued poetry, photography, music performance, and composition. I have lived in Salt Lake City, Los Angeles, Seattle, and New York. I have a B.A. in comparative religion from the University of Washington, 1984, where I also studied computer music with John Rahn. Computer music became my major interest. It also enabled me to make a living as a programmer. In the late 1980s, I benefited greatly from Brad Garton's openness to non-student participation in the woof user group and concerts at the Columbia-Princeton Electronic Music Center. Currently, I contribute code to Csound, am the author of an algorithmic composition system for Csound, host the International Csound Csound Users Group meetings online, and am on the steering committee for the New York City Electroacoustic Music Festival. I write articles and papers on computer music, and I create computer music. I have a special interest in mathematical methods of algorithmic composition. I am married to Heidi Rogers. We live in the Catskills and in Manhattan.

Program Notes

This is a piece of interactive visual music implemented using my all-HTML5 system for making and performing computer music, cloud-5.

cloud-5 runs exclusively in standard Web browsers from a local or remote Web server. The system includes WebAssembly builds of Csound and my algorithmic composition library CsoundAC, the live coding system Strudel with some patches and additions by me, and whatever other JavaScript or WebAssembly components are needed.

I composed this piece using an orchestra of fairly complex Csound instruments together with a Strudel patch that uses CsoundAC for generating chord progressions and modulations. I set up the Strudel patch to make it easy to shape the piece by live coding during performance. The basic idea is that there are three rather repetitive sections, and the performer is expected to introduce variations in these sections by moving the sliders (especially the circle map parameters and the run and offset parameters), and by removing and adding code during play.

The piece also includes a music visualizer written in OpenGL Shader Language.

Things I would like to do in this piece:

  • Better instruments. Still need more zingy, staccato sounds.
  • Better sliders for those instruments, more obvious changes of sound and texture.
  • Swap out Strudel chords for CsoundAC Scales, Chords, and modulations. The selected modulation can be patternified.
  • Got to get negative values out of slider. Done.
  • Get continuous Strudel "signals" to control sliders/Csound control channels. Doesn't always make sense.
  • Better visualization. Done for now.
  • It will have a control or setting for playing a fixed period of time, then fading out, as well as a display of time elapsed. This needs to be configurable on/off. Now working, but it would be better to exit performance after fadeout. I can get the actual Csound thread to stop, but the Csound WASM API doesn't know that. Leaving this for now.
  • All sounds will be from Csound.
  • Put in changes of dynamics.
  • Put in random pans.
  • Sequencing Patterns on tracks; patterns repeat [0, n] times as with arrange, but arrange only does [1, n] which is useless for my purposes. I sort of got this working with csac.arrangeTrack, but it's not a proper pattern, and the timing does not always behave intuitively. But it is possible to mute Patterns in the track. See https://strudel.tidalcycles.org/learn/code for how to do this with comments using the keyboard shortcut [Cmd-/].
  • Circle map generator? Done.
  • Not run, but some recognizable motif or quotation? Easy to try.... Not doing at this time, maybe in the next piece.
  • Imperative to level gains across instruments.
  • Warning level diagnostics for all chord and scale changes.
  • Try Euclidean rhythms. Works.
  • Try CsoundAC Chord and transformations in place of Scale. No time for this now, maybe for Luck Dragon gig.
  • Must rehearse just with MacBook, no big screen.

The new slider in Strudel is very cool. To get it to work with csoundn, n rather than note must be used.

What I most want is to use a slider with discrete steps as a switch to control what Patterns are playing.

The slider can perhaps be used to switch between, mix, or cut up other Patterns. This could be used to make a piece that is set up to make certain possibilities easier for live coding. Patterns that could be controlled in this way include:

  • degradeBy and relatives.
  • sometimesBy and relatives; 0 or 1 would switch the function applied off and on.
  • someCyclesBy and relatives; 0 or 1 would switch the function applied off and on.
  • when and relatives.
  • See if there's some way to adapt arrange. No, won't take slider for the count of repetitions.

Sigh... none of these work as required out of the box.

Of course it's possible to just comment out and in chains of Patterns.

This works:

chooseWith(slider(0.6365, .5, 1), ["bd", "hh", "sd"]).s().fast(4)

No, it doesn't work if the list consists of patterns.

I will look through this resource: Online Encyclopedia of Integer Sequences. I thought these sequences had interesting graphs. Many even provide a way to save the sequence as a MIDI file, which will play just fine in Pianoteq.

Unfortunately these sample a sequence to obtain an array; what I need is to simply recurrently generate the sequence.

So conceptually there are two dimensions, tracks or time lines, and the vertical dimension. I need to assemble tracks from sub-patterns with from 0 to some N of repetitions each. Then I need to have one note, or one rest, on either sub-patterns or on the track as a whole, to create differential canon. A transposition of the whole track also should be applied.

Multiple tracks are then simply stacked to create the vertical dimension.

This doesn't currently work because stack aligns the ends as well as the beginnings of its Patterns, and so can't do differential canons.

arrange works up to a point, but not when the repetitions of a Pattern are set to 0, and not with use of slider for the number of repetitions.

I may have to define a switch or repeat Pattern. Actually this would be cat with a condition:

catWhen(when, pattern)

If when is true, returns this.cat(pattern); if when is false, returns this.

  • SeidelHarmOsc, sounds great.
  • FMWaterBell, of course.
  • Sweeper, of course.
  • Harpsichord, probably.
  • Droner, if slow.
  • Shiner, maybe.
  • Blower, maybe.
  • Xing, probably.
  • PluckedString, not this time.
  • Kung2, no.
  • Kung4, no.

This is the most impressive patch I've seen for Strudel: https://strudel.tidalcycles.org/?YtkX3prz4D7h. It dynamically composes an arrange from a whole set of patches.

I searched Strudel's Discord channel for "arrange" and found a lot of people feeling confused, so I'm not the only one.

I'm beginning to get the same feeling about Strudel that I used to have about Jeskola Buzz -- that it is a really cool way of arranging musical thought. But I find I can edit Strudel pieces much much faster than I ever could Buzz pieces.

Investigate:

Major outstanding objectives:

  • Switchable Patterns.
  • pianoroll working the same with all outputs.

I can't seem to use stack with run. Not true; the problem is, one can't use stack to do differential canons.

What's the difference between off and offset?

/**
 * Superimposes the function result on top of the original pattern, delayed by the given time.
 * @name off
 * @memberof Pattern
 * @param {Pattern | number} time offset time
 * @param {function} func function to apply
 * @returns Pattern
 * @example
 * "c3 eb3 g3".off(1/8, x=>x.add(7)).note()
 */

In Cancycle-5, each note in a chord triggers acST and acSM, not just acSCV. What I need is for there to be only one trigger of acST and acSM at any given time, but acSCV will act as it now does.

Does Strudel's chord do this and, if so, how? In tonal/voicings.mjs, chord is a control, not a Pattern; voicing is a pattern that applies the chord to the note.

There are two ways I can think of to implement the desired behavior:

  • Imitate chord but with all of my Patterns for CsoundAC.
  • The Hap times appear to be identical for the extra transformations. I can simply not apply another of the same Pattern at the same time. In other words, an early return for another application of the same Pattern at the same time.

But this would kind of mix the metaphors and muddy the waters. Problem solved by tracking changes of input to Statefi;Patterns, see below.

Indeed, the CsoundAC objects can be attached to the Hap value as controls.

Hap.value.chord
Hap.value.scale

The problem remains however, as the operations on these objects are still going to be triggered by multiple Patterns.

But see scaleTranspose and related Patterns. The scale is a member of the Hap context.

Problem solved by using changes of inputs to StatefulPatterns, see below.

The solution is simple. Change the state when and only when the value of the Pattern input changes. The trigger may not even be necessary.

The only hackish element of this is the need to have a toggle for Patterns such as acCK that do not essentially involve an input value. In place of the trigger, we use a toggle.

This now seems to be working in the context of a real piece.

Musical objectives for this piece involve "long-scale composition:"

  • Two levels of rhythm, e.g. fast patterns on top of slower patterns.
  • Contrasting sections.
  • Differential canons.

This kind of works for arranging, as it implements silencing sections in the arrangement, but the timing is only correct if each section is the same duration, and slider cannot be used to set the number of repetitions of a segment:

export function arrangeTrack(...sections) {
    sections = sections.filter(function(element) {
        return element[0] >= 1;
    });
    const total = sections.reduce((sum, [cycles]) => sum + cycles, 0);
    sections = sections.map(([cycles, section]) => [cycles, section.fast(cycles)]);
    return timeCat(...sections).slow(total);
};

Differential canons are possible in Strudel only with polymeter but that accepts lists whereas I want it to accept Patterns. And polymeter depends upon the _sequenceCount function.

I don't see how to a version of polymeter that works with Patterns and not lists.

Wrong, differential canons are possible with stack, but the number of cycles in each layer must differ:

stack(
  "<a5 b5 c6>".note().piano().gain(.5),
    "<a2 b2>".note().s("gm_blown_bottle"),
  "<db3 e3 gb3 ab3>".note().s("harp")).fast(6).pianoroll()

Better music visualizers:

Try to get shorter, more percussive sounds using "Emulations and Models" but with sample tables omitted or swapped for generated tables. Two more instruments should do it. Try:

  • vibes opcode/vibes.csd example.
  • barmodel opcode/barmodel.csd example (no sample file required). I have an .inc file for this; it doesn't sound good. However, I think it can be tweaked to sound quite good, so I will try it.
  • marimba opcode/marimba.csd example.

Instruments needing controls in addition to levels:

  • Sweeper:
gk_Sweeper_britel init .05 in [0, 10]
gk_Sweeper_britels init .25 in [0, 10]
gk_Sweeper_briteh init 4 in [0, 10]
gk_Sweeper_britehs init .5 in [0, 10]
  • Blower:
gk_Blower_grainDensity init 90 in [20, 1000]
gk_Blower_grainDuration init 0.2 in [.01, 2]
gk_Blower_grainAmplitudeRange init 100 in [0, 1000]
gk_Blower_grainFrequencyRange init 10 in [0, 300]
  • Droner? First 5 partials (on Controls overlay). No time.
  • Bower:
gk_Bower_pressure init 0.325 in [0, 4] 

To make this piece better in the limited time remaining, sections:

  1. Circle map, andante, chiming sounds, mezzo-forte.
  2. Circle map, largo, evolving pads, forte.
  3. run and offset, with jux, plucked string sounds, allegro, forte.
  4. Circle map, andante, mixture of chimes and pads, piano.

Parameters will be preselected, I will vary them during performance.

This is finished enough. I will try to practice and tweak some more before the concert tonight.