Jump to content

Featured Replies

Posted

Hi everyone,

I'm sharing this post in the Managing Complexity section because I believe this is an appropriate place to discuss constraint-based compositional systems such as the Cluster Engine.

> ⚠️ Note: This post is not intended for beginners in Opusmodus. It assumes familiarity with advanced concepts such as pitch/rhythm domains, OMN, and generative constraint programming using external libraries like TOT by Torsten Anders.

The example below shows how to generate a polyphonic duo using a set of constraints and automatic mapping of rhythm, pitch, and dynamics. It also showcases how the Cluster rules in TOT can serve as a solid starting point for creative exploration.

Hope this inspires further discussion or variations!


Introduction

This post presents a study for two violins generated with the Cluster Engine by Örjan Sandred, now integrated into Opusmodus through the TOT library by Torsten Anders. This constraint-based generation engine was originally developed in PWGL, and later ported to SBCL by Örjan Sandred, Julien Vincenot, and Torsten Anders and finally ported to LispWorks and Opusmodus by Torsten Anders.

In this Opusmodus version, the Cluster Engine offers a powerful system for rule-based musical generation, where voices are controlled through a set of structural and stylistic constraints.

This example demonstrates how we can generate contrapuntal textures with internal coherence, avoiding direct repetitions, controlling harmonic intervals, and dynamically shaping rhythm and pitch domains.

> 💡 Note: The constraint rules used in this example are based on the excellent TOT presets Cluster Rules provided in the library by Torsten Anders.

Objective

To automatically generate a musical section for two violins:
- Using constrained pitch and rhythm domains.
- Ensuring polyphonic independence between voices.
- Mapping dynamic shapes to rhythmic density (with "traditional" Opusmodus procedure...)
- Optionally adding rests for sparseness.

Setup

Load the TOT system:


(asdf:load-system :tot)


Set the number of musical cells:

(setf ncells 24)
(setf *rnd-rest* nil)
(setf *rnd-rest-percent* 0.25)



Domains

Rhythmic domains (encoded in OMN):

(setf r-domain1 (omn-encode '((s s s s)(e e)(3q = =)(q)(h.)(h))))
(setf r-domain2 (omn-encode r-domain1))


Pitch domains (custom 7-note scale):

(setf harmo (make-scale 'a4 7 :alt '(2 1)))
(setf p-domain1 (mclist (pitch-to-midi harmo)))
(setf p-domain2 (mclist (pitch-to-midi (pitch-transpose (rndn 1 -12 -7) harmo))))


Cluster Engine Generation

Using the Cluster Engine with TOT rules:


(setf cluster-out
(cr::cluster-engine
ncells
(ce:rules->cluster
(cr:no-direct-repetition :voices '(0 1))
(cr:no-repetition :voices '(0 1) :window 3)
(cr:set-intervals :voices '(0 1) :intervals '(1 2 3 4 6 7))
(cr:resolve-skips :voices '(0 1) :skip-size 5)
(cr:set-harmonic-intervals :voices '(0 1) :intervals '(3 4 5 7))
(cr:min/max-interval :voices '(0 1) :max-interval 4 :min-interval 1)
(cr:durations-control-intervals :voices '(0 1) :rel-factor 16 :acc-factor 16)
(cr:no-parallels :voices '(0 1))
(cr:no-voice-crossing :voices '(0 1)))
'((3 4))
(append
(list r-domain1 p-domain1)
(list r-domain2 p-domain2))))


Processing the Output

Extract rhythm and pitch for both voices:


(setf line1.len (first cluster-out))
(setf line1.pitch (second cluster-out))
(setf line2.len (third cluster-out))
(setf line2.pitch (fourth cluster-out))
(setf ts (car (fifth cluster-out)))


Convert to OMN notation:


(setf line1 (omn-to-time-signature (make-omn :pitch (midi-to-pitch line1.pitch) :length line1.len) ts))
(setf line2 (omn-to-time-signature (make-omn :pitch (midi-to-pitch line2.pitch) :length line2.len) ts))


Dynamic Shaping via Density Analysis


(setf dyn1 (mclist (vector-to-velocity 'pp 'ff (density-analysis line1 :type :length))))
(setf dyn2 (mclist (vector-to-velocity 'pp 'ff (density-analysis line2 :type :length))))

(setf omn1.d (velocity-to-dynamic (omn-replace :velocity dyn1 line1)))
(setf omn2.d (velocity-to-dynamic (omn-replace :velocity dyn2 line2)))


Optional Random Rests


(if *rnd-rest*
(progn
(setf omn1.d (rnd-rest *rnd-rest-percent* omn1.d))
(setf omn2.d (rnd-rest *rnd-rest-percent* omn2.d))))


Final Score


(def-score EtudeClusterEngine
(:title "Study Duo using Cluster Engine"
:composer "Stéphane Boussuge"
:copyright "Copyright © s.boussuge 2025"
:key-signature 'chromatic
:time-signature '((1 1 1) 4)
:tempo 91
:layout (bracket-group
(violin1-layout 'violin1)
(violin2-layout 'violin2)))

(violin1 :omn omn1.d :channel 1 :sound 'gm :program 'violin :volume 100 :pan 54 :controllers (91 '(48)))
(violin2 :omn omn2.d :channel 2 :sound 'gm :program 'violin :volume 100 :pan 74 :controllers (91 '(60))))


Conclusion

This short algorithmic composition study demonstrates how the Cluster Engine, combined with a rich preset rule system (TOT), can help generate structured and coherent polyphonic music for multiple voices.

By blending constraint programming, statistical dynamics, and stochastic variation (rests), we can explore highly controlled yet musical outcomes — ideal for modern compositional practice.

Acknowledgments

Many thanks to Örjan Sandred, Torsten Anders, and Julien Vincenot for their inspiring work in constraint-based composition and particularly to Torsten for the development of the TOT system for Opusmodus.


Would love to hear feedback or see variations based on other rule combinations!

Stéphane

Score229-DuoVn_ClusterEng.opmo

The "TOT" library is already included by default in Opusmodus ?

I receive a message like this:

<<automatic abort>>

OM 4 >

Error: Component :tot not found

1 (continue) Retry ASDF operation.

2 Retry ASDF operation after resetting the configuration.

3 Retry ASDF operation.

4 Retry ASDF operation after resetting the configuration.

5 (abort) Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.

Type :bug-form "<subject>" for a bug report template or :? for other options.

OM 5 : 1 >

Thanks, Stephane. Looks good.

  • Author

14 hours ago, Stephane Boussuge said:

external libraries like TOT by Torsten Anders.

Hi Julio,

no, as I said into the post, the TOT library is not included in OM.

Here's the link to Torsten's Github:

GitHub
No image preview

tanders - Overview

I am a composer, researching and developing software for computer-aided composition. - tanders

A very interesting post! Thank you for it.

What might be very interesting is an audio recording as an additional means to evaluate this approach. It is a large undertaking to install this extension to Opusmodus. Hearing the result might be an incentive to users to take the plunge.

A general question:

Has anyone successfully installed this software on a Windows system?

IF so, could you please post some information about this here for general reference?

I cannot figure out where to place the tot-master folder and/or tot.asd file so that asdf can parse it. So far I have tried a lot of approaches, but the documentation is not inclusive of how this might work on the Windows platform, at least as far as I can see so far.

With thanks,

Robert

On 5/29/2025 at 3:19 PM, JulioHerrlein said:

The "TOT" library is already included by default in Opusmodus ?

I receive a message like this:

<<automatic abort>>

OM 4 >

Error: Component :tot not found

1 (continue) Retry ASDF operation.

2 Retry ASDF operation after resetting the configuration.

3 Retry ASDF operation.

4 Retry ASDF operation after resetting the configuration.

5 (abort) Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.

Type :bug-form "<subject>" for a bug report template or :? for other options.

OM 5 : 1 >

Thanks, Stephane. Looks good.

This is precisely my issue as well on Windows with Opusmodus 3. Is there any news of how to get this to work?

On Windows 10 this is what I did to port the software to run the example:

I created a directory in C: Users called common-lisp. And placed the various source directories from Torsten's GitHub, including dependent library cl-utilities. I also installed MiniZinc for completeness.

asdf parses this directory by default on a Windows OS.

Create an account or sign in to comment


Copyright © 2014-2025 Opusmodus™ Ltd. All rights reserved.
Product features, specifications, system requirements and availability are subject to change without notice.
Opusmodus, the Opusmodus logo, and other Opusmodus trademarks are either registered trademarks or trademarks of Opusmodus Ltd.
All other trademarks contained herein are the property of their respective owners.

Powered by Invision Community

Important Information

Terms of Use Privacy Policy