Closed gogins closed 1 year ago
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.
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:
slider
. Done.sliders
/Csound control channels. Doesn't always make sense.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-/].run
, but some recognizable motif or quotation? Easy to try.... Not doing at this time, maybe in the next piece.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.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
.
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:
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 justacSCV
. 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:
chord
but with all of my Patterns for CsoundAC.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:"
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:
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]
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]
gk_Bower_pressure init 0.325 in [0, 4]
To make this piece better in the limited time remaining, sections:
run
and offset
, with jux
, plucked string sounds, allegro, forte.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.