Accelerating Polyrhythm — User Guide
Generates stereo polyrhythmic event grids whose shared cycle duration changes from an initial speed to a specified final speed, with optional frequency, amplitude, rhythm, pan, or seeded random evolution.
Overview
Accelerating Polyrhythm synthesizes two rhythmic layers — and, in one preset, a true third layer — inside a common sequence of cycles. Each layer subdivides every cycle into its own number of equally spaced beats. For example, a 3:2 setting places three P1 events and two P2 events inside each shared cycle.
The cycle duration can accelerate, remain steady, or decelerate across the piece. The script then renders each event as a short synthesized tone, positions the layers in stereo with constant-power panning, and peak-normalizes the completed stereo result to 0.9.
Quick start
- Run
Accelerating_Polyrhythm.praat; no input Sound is required. - Choose a preset, or choose Custom to use the values in the form.
- For Custom, set the initial cycle duration, number of cycles, beat counts, frequencies, and final speed ratio.
- Choose exponential or linear acceleration and, if desired, a morph type.
- Set the maximum event-tone duration, attack, decay, waveform, and random seed.
- Enable Draw_visualization to inspect the generated event lattice, IOIs, and active transformation.
- Run the script. The output is a stereo Sound named from the rendered ratio, such as
AccelPoly_3v2.
Timing & acceleration
Acceleration_factor is the total end-speed / start-speed ratio. It is not multiplied again on every cycle.
For cycle c, progress is:
p = (c - 1) / (Total_cycles - 1)
with p = 0 when only one cycle is requested. The speed factor is:
Exponential: speed = Acceleration_factor ^ p Linear: speed = 1 + (Acceleration_factor - 1) * p cycle_duration = Base_duration_s / speed
Thus the first cycle always has speed factor 1.0, while the final cycle reaches Acceleration_factor.
Target total duration
If Target_total_duration_s is greater than zero, it overrides the entered initial cycle duration. The script solves the initial duration so that the sum of all cycle durations follows the selected acceleration law and equals the target:
Base_duration_s = Target_total_duration_s / sum(1 / speed[c])
A target value of 0 leaves Base_duration_s in control.
Beat placement
Within each cycle, each layer is evenly subdivided:
P1 IOI = cycle_duration / P1_beats P2 IOI = cycle_duration / P2_beats P3 IOI = cycle_duration / P3_beats (triple-layer preset only)
The next cycle starts immediately after the current cycle duration, so the acceleration law changes the actual event spacing from cycle to cycle.
Presets
Presets replace the central pattern, cycle, acceleration, morph, and waveform settings shown below. Target_total_duration_s, Random_seed, Play_result, and Draw_visualization remain independently user-controlled. Most presets also leave the form's attack, decay, and maximum tone duration unchanged unless explicitly listed.
| Preset | Pattern / frequencies | Cycles & timing | Morph / waveform |
|---|---|---|---|
| Custom | Uses form values | Uses form values | Uses form values |
| 3:2 Hemiola (gentle) | 3:2; 440 / 554.37 Hz | T0 1.107 s; 6 cycles; 1.5× exponential | None; Sine |
| 4:3 Cross-rhythm | 4:3; 330 / 440 Hz | T0 0.687 s; 8 cycles; 2× exponential | None; Sine |
| 5:4 Quintuplet feel | 5:4; 392 / 523.25 Hz | T0 0.858 s; 8 cycles; 2× exponential | Frequency morph; Sine |
| 7:4 Progressive rock | 7:4; 220 / 440 Hz | T0 1.340 s; 6 cycles; 1.8× exponential | None; band-limited Square |
| 5:3 Bell-like cross-rhythm | 5:3; 800 / 1200 Hz | T0 0.379 s; 10 cycles; 2.5× exponential | Pan morph; Pluck; max tone 60 ms; attack 2 ms; decay 50 ms |
| 8:5 Golden-ratio approximation | 8:5; 261.63 / 392 Hz | T0 1.207 s; 8 cycles; 1.618× exponential | Frequency morph; Sine |
| 3:2:4 Triple layer | 3:2:4; 262 / 392 / 523.25 Hz | T0 0.460 s; 12 cycles; 2× exponential | Random evolution; Sine; three real layers |
| Nancarrow Study 21 inspired | 17:18; 220 / 233.08 Hz | T0 3.577 s; 6 cycles; 1.06× exponential | None; Pluck; max tone 80 ms |
| Reich-inspired phase drift | 12:12; 330 / 440 Hz | T0 2.740 s; 12 cycles; 1.02× linear | None; Sine; P2 phase offset moves 0 → 1 beat |
| Ligeti Etude feel | 5:7; 440 / 554.37 Hz | T0 0.527 s; 10 cycles; 2.2× exponential | Rhythm morph; Sine; attack 3 ms; decay 40 ms |
Morph types
| Mode | Actual transformation from first to final cycle |
|---|---|
| None | Beat counts, frequencies, amplitudes, and pan remain at their base values; only the acceleration law changes timing. |
| Frequency morph | P1 frequency rises from 100% to 150% of its base value. P2 falls from 100% to 75%. If P3 exists, it falls to 90%. The paths may converge, cross, or remain separated depending on the starting frequencies. |
| Amplitude morph | P1 moves from 100% to 50% of its base amplitude; P2 moves from 50% to 100%. This is a partial balance exchange, not a fade to silence. |
| Rhythm morph | P1 gains up to four beats across the piece: base_beats + round(4 * progress). P2 and optional P3 keep their beat counts. |
| Pan morph | P1 and P2 linearly exchange their starting pan positions. With the standard hidden positions, P1 moves from -0.5 to +0.5 and P2 from +0.5 to -0.5. |
| Random evolution | Once per cycle: each active layer frequency is randomized to 80–120% of base, amplitude to 60–100%, and pan receives ±0.3 before clamping to -1…+1. Beat counts are unchanged. |
Random seed
Random_seed = 0 initializes unpredictably. A positive seed makes the Random evolution event states reproducible. When Random evolution is not selected, synthesis is deterministic regardless of the seed field.
Tone & stereo synthesis
Each rhythmic event is rendered at the fixed internal sample rate of 44.1 kHz. Its duration is limited by both Max_tone_duration_ms and the current rhythmic density:
tone_duration = min(Max_tone_duration,
0.8 * smallest_IOI_in_current_cycle)
This prevents a tone from occupying more than 80% of the tightest layer spacing. If acceleration or a requested target duration would reduce an event below six samples, the script stops rather than rendering sub-sample-like clicks.
Envelope
Each event has a linear attack and a linear final decay. For very short events the requested times are automatically shortened: attack is at most one third of the tone duration and decay at most one half.
Waveforms
| Waveform | Implementation |
|---|---|
| Sine | Single sinusoid at the event frequency. |
| Triangle (band-limited) | Finite odd-harmonic approximation through the 9th partial, with alternating signs and 1/n² amplitudes. Partials above the Nyquist guard are omitted. |
| Square (band-limited) | Finite odd-harmonic approximation through the 9th partial with 1/n amplitudes; out-of-range partials are omitted. |
| Pluck (decaying harmonics) | Fundamental plus a decaying second harmonic (0.5·e-10t) and third harmonic (0.25·e-20t), subject to the Nyquist guard. It is a compact synthetic pluck-like spectrum, not a physical string model. |
Fundamental frequencies must remain below 0.48 × 44100 = 21168 Hz. The same guard is checked again after frequency morphing or randomization.
Stereo placement
The output is always stereo. P1 starts at pan -0.5 and P2 at +0.5; the triple-layer preset places P1 at -0.65, P2 at +0.65, and P3 at center. The panning law is constant power:
angle = (pan + 1) / 2 * pi/2 left = cos(angle) right = sin(angle)
The Pan morph swaps P1 and P2 spatial positions over the piece. Random evolution adds cycle-level pan variation.
Parameters
| Parameter | Default | Meaning |
|---|---|---|
| Preset | Custom | Selects one of the predefined configurations or leaves the form values active. |
| Base_duration_s | 2.0 s | Duration of cycle 1 when Target total duration is 0. |
| Target_total_duration_s | 0 | If greater than 0, recalculates the initial cycle duration to meet this total duration under the chosen acceleration law. |
| Total_cycles | 8 | Number of shared rhythmic cycles; capped at 1000. |
| Pattern1_beats / Pattern2_beats | 3 / 4 | Number of evenly spaced events per cycle for each layer; each is capped at 1000. |
| Pattern1_frequency_Hz / Pattern2_frequency_Hz | 300 / 500 Hz | Base tone fundamentals before any morph. |
| Acceleration_factor | 2.0 | Final speed relative to cycle 1. >1 accelerates; 1 is steady; 0–1 decelerates. |
| Exponential_acceleration | Yes | Selects a^p rather than linear interpolation from 1 to a. |
| Morph_type | None | Optional cycle-level transformation in frequency, amplitude, rhythm, pan, or random parameters. |
| Max_tone_duration_ms | 100 ms | Upper limit for each event tone; current rhythmic spacing may shorten it further. |
| Attack_ms | 5 ms | Requested linear attack. Negative values are clamped to 0. |
| Decay_ms | 30 ms | Requested linear ending decay. Negative values are clamped to 0. |
| Waveform | Sine | Sine, finite band-limited triangle/square, or pluck-like decaying-harmonic tone. |
| Random_seed | 0 | 0 = unpredictable Random evolution; positive = reproducible. Negative values are clamped to 0. |
| Play_result | Yes | Plays the generated Sound after rendering. |
| Draw_visualization | Yes | Draws the actual generated event/timing/morph data. |
Output behavior
- Input: none; this is a generator.
- Sample rate: fixed internally at 44,100 Hz.
- Channels: always stereo.
- Time domain: starts at 0 s; duration is the sum of the generated cycle durations.
- Object name:
AccelPoly_P1vP2, orAccelPoly_P1vP2vP3for the triple-layer preset. - Final level: the complete stereo Sound is deliberately peak-normalized to 0.9. This is upward or downward normalization, not attenuation-only safety limiting.
- Randomness: only Random evolution changes event parameters stochastically; a positive seed reproduces those cycle states.
Visualization
The v0.4 figure is driven by the same arrays used to render the audio, rather than by an independent illustrative approximation.
- Panel A — Actual Event Lattice: event onset times for P1/P2/(P3); stem height reflects actual event amplitude. Vertical guides mark actual cycle boundaries.
- Panel B — Actual Inter-Onset Interval by Cycle: piecewise IOI values in milliseconds for each active layer. Rhythm morph changes P1's plotted IOI as its beat count changes.
- Panel C — Active mechanism: adapts to the current process: speed factor, frequency, amplitude, beat count, pan, random frequency realization, or Reich-preset P2 phase offset.
- Summary bar: states the acceleration law, P1 start/end IOI, total duration, event count, and random-state description.
Turning the visualization off skips only drawing; it does not alter the precomputed event states or audio rendering.
Technical notes
Preset-specific processes
The Reich-inspired phase drift preset uses two equal 12-pulse grids. P2 receives a cycle-level offset that progresses from 0 to one complete P2 beat over the piece. Because one full beat is equivalent to the original periodic grid, the final cycle returns to an aligned onset set. This is a discrete, cycle-stepped phase process rather than continuous sample-by-sample phasing.
The 3:2:4 Triple layer preset genuinely renders P3 in addition to P1 and P2; its third layer has four beats per cycle, 523.25 Hz, amplitude 0.32, and center pan.
Event count and safety guards
The script precomputes all cycle states and event onsets before audio synthesis. It guards cycle count, beat counts, fundamental frequency, target timing, and minimum event duration. Panning is clamped to -1…+1 after morphing/randomization.
Further Reading
- Reich, S. (1968). “Music as a Gradual Process.” Reprinted in Writings on Music 1965–2000, Oxford University Press. Direct context for perceptible gradual musical processes and Reich's phase-shifting practice.
- IRCAM. “Conlon Nancarrow — Parcours de l'œuvre.” Discusses Nancarrow's acceleration canons, including Study No. 21 (Canon X) and Study No. 27. Direct context for the Nancarrow-inspired acceleration preset.
- Roads, C. (2023). The Computer Music Tutorial, 2nd ed. MIT Press. General technical reference for digital synthesis, signal generation, algorithmic composition, and computer-music timing.