< Back to IRCAM Forum

'Screamer' functions as visual boxes

Hi everyone!

I’m new to the forums so I thought I’d share the results of my efforts to make functions from the constraints library ‘Screamer’ available as visual boxes.

The library:
https://github.com/omggelato/paradigm/releases/download/v.1.0.0/myextension.zip

I also added a modulo operator, absolute value, and a few other basic functions. Note that these OpenMusic boxes are defined within the :OM package.

I’m currently using this library in the course of designing a workspace that generates a second voice for a given theme in 1st, 2nd, 3rd, 4th-species counterpoint. As I continue to add documentation and improve the various patches and functions the workspace could become a useful instructional technology.

The library + workspace:
https://github.com/omggelato/paradigm/releases/download/v.1.0.1/Paradigm__v.1.0.1.zip

One major limitation with implementing Screamer using visual boxes is its reliance on a code-walker that rewrites functions in order to facilitate backtracking. Invoked from within the visual environment, Screamer sees calls to the various OM visual box methods instead of the names of the functions native to Screamer and then raises an error. The functions that invoke Screamer’s solver, ONE-VALUE, ALL-VALUES, etc, are invoked in this library with FIND-ANY and FIND-ALL.

Let me know if you are also working with Screamer too, or if you notice any problems in the library.

Wow, this sounds great. Will definitely have a look. Thanks!

Hi Shantus,
Thanks for sharing your work. I’ll take a look.
I’m also working in a library using Screamer inside OM, with the kind help of Karim Haddad. It’s called OM-Screamer, but it’s on it’s early stages of development.

The library is divided in three parts:

  • The restoration of OM-Backtrack (from OM 4);
  • Screamer-solver (a generic constraint solver);
  • Screamer-score (a constraint solver for generating music scores).
    Feel free to share your comments, if you find this library useful. It still needs a full documentation of the screamer-solver and screamer-score functions, but there are some examples in the tutorials patches.
    Best,
    Paulo

I’m sure that you both have gone further down this road than I. Here some things I’ve noted along the way:

For the constraints-variables boxes instead of the function name ending with ‘-v’ I’ve found that adding a question mark makes it easier to visually distinguish. +v, /v, etc is presented as ?+,?/, etc.

Working with the forwards constraints variables I’ve had some success generating them applying rules and sending them to a solver (I’ve designated it FIND-ALL, but such naming might be too similar to a certain commercial Knowledge-Based System). Evaluating boxes in patches results in calls to functions and methods related to the OM visual boxes system. This confuses Screamer (as you have likely found out) and makes it impossible to use ‘either’ and other functions termed ‘non-deterministic’ within Screamer. With its reliance on a code-walker, certain optimizations it tries to perform don’t immediately seem possible from the visual environment. If you connect screamer:=v to screamer:assert! in a patch, it will work, but Screamer will not call the optimized assert-=v function because as you know the text of the code being processed includes omng box-calls. The same is true for the other optimized functions. I see that your extension uses quoting in calls involving ‘nondeterministic’ functions and forward constraints variables.

My library also tries to cache constraints variables. For instance, if you have a list of variables like: (55 [x1] [x2] [x1] [x4]), and apply some operator to them (such as modulo 2):

(mapcar #'(lambda (x) (?% x 2))

… the second time the ?% operator encounters the variable [x1] it will return the variable it generated the first time. That way, additional constraints applied elsewhere will be applied to the same variable.

The

I’m not sure if this is necessary from a Screamer-architecture point-of-view, and I haven’t run into any situation where it seemed necessary to do this.

I modified TEMPLATE to facilitate working with sequences of variables. If a symbol is prefixed with ? and ends with a ‘+’, a sequence number is incremented. A symbol ending with a ‘#’ maintains the previous sequence number. I find this useful for working with variables corresponding to sequences (like MIDI-note values). So for instance to generate a fourth-species counterpoint for a given theme I can enter:

((nil ?x+) (?x# ?x+) (?x# ?x+) ?x+)
 (62       69        64        62))

which is translated by my om::?template function into:

((nil ?x0) (?x0 ?x1) (?x1 ?x2) ?x3)
 (62       69        64        62))

and then a mixture of variables and symbols when passed to SCREAMER:TEMPLATE (((nil [?x0]) ([?x0] [?x1]) ([?x1] [?x2]) [?x3]) (62 69 64 62))

There are two notes in voice 2 for every note of the C.F. The same variable carries over in voice 2, creating suspensions. A that point, a simple rule can be defined that a dissonant vertical interval be escaped by step.

The functions defined in general.lisp under the heading ‘variables registry’ I don’t think are necessary. Every call to a boolean constraint operator caches the resulting variable if it is not already present in the registry. The combination of the function invoked and its arguments are used as the key in the map. Functions like max, min, and, or, =, /=, etc use set-equality to compare arguments. member-of functions use set-equality to compare the second argument. +, *, avg, etc compare the arguments as unordered lists. The rest of the functions use list-equality. I now leave this feature turned off (t2l::disable-variable-cache-map). If I got rid of it, the library would be substantially smaller.

https://github.com/omggelato/paradigm/releases/download/v.1.1.1/OM.Workspace.and.Library.zip

My interest in finding out more about existing constraints libraries like OM-Screamer or continuing to try to develop this in connection to a visual workspace is their potential as instructional technology. Being able to read through and evaluate several hundred generated counterpoints for a given theme, or to interact with program objects and symbols to design one’s own rule-set for polyphony, can help to level the playing field in music theory classrooms. As for creative applications, I am not sure I can make any promises.

Anyway, OM-Screamer looks very promising, especially the visual score-object. I wasn’t aware of the features in OM 4 being brought into this package. Thanks for sharing!

Hi Shantus,
about Screamer libraries I’ve found the OM-Backtrack (that’s included in OM-Screamer, ported from OM 4), a repository in Github ( https://github.com/music-custom/music-custom/tree/master/lib ) and an old library from PWGL called smc ( https://github.com/JulienVincenot/PWGL-community-library/tree/main/User-library/smc-0.2.7 ), but the latter is very dependant on the PWGL environment. In the OM-Backtrack library there is a mechanism to compile the om patch using screamer::defun instead of cl::defun, and the screamer macros all-values, one-value and print-values is used to generate a non-deterministic patch. You can take a look at the files non-deter-patch.lisp, screamboxes.lisp, screamfuns.lisp and screaminterface.lisp. Maybe these can be helpful.
About the screamer-score, it is possible to create counterpoint too and I’ve made some experiment on this matter. For example, this is a patch that creates an 1st species counterpoint (it’s not perfect yet and I’ve made only for testing purposes):


The screamer-score inputs are:

  • a poly object (in this case we have an open voice - all the notes are the middle C [6000] and only the rhythms will be used by the solver - and the cantus firmus);

  • a screamer-score-domain object (or a list of domains). In this case we have only one domain for the upper voice.

  • the constraints (a lambda patch connected to the constraint-one-voice, constraint-harmony, constraint-profile or constraint-measure) - here are two examples, one for a single voice and another for harmonic intervals:
    constraint-one-voice
    constraint-harmony
    The first constraint calculates the absolute melodic intervals between the notes 1 and 2, 2 and 3, 3 and 4, etc… (That why there are two inputs and the constraint is applied recursively when the mode “n-inputs” is selected). This intervals should be a member of the list in midicents (0 100 200 300 400 500 700 800 900 1200).
    The second constraint is for the harmonic intervals between the two voices and them should be a member of the list (300 400 700 800 900 1200 1500 1600) - only consonantes up to a tenth.
    The result is a poly object and up to now it is working just fine. The advantage of this approach is that the screamer-score creates an screamer variable for each note (a-member-ofv or a-random-member-ofv) and organizes the list of variables for melodic or harmonic constraints (the rests are represented as a null value [nil], like in the Cluster-Engine library).
    I don’t know if this is what are you looking for, but maybe it can help too.
    P.S.: about your library, I did not have time to look at the code yet, but I will try to do it soon.

Best,
Paulo

1 Like

Hi Paulo,

I am going in now to try and see what I can glean from your approach in non-deter-patch. I don’t have the familiarity with the OM-Box classes yet to try to attempt such a feat, but I’ve made a lot of progress using the forward-constraint variables and passing them all to a solver.

Like I pointed out earlier, the species-counterpoint examples I put in the workspace I attached relies on a special nested-list structure to express 1-to-N note-to-note structures. These can be arbitrarily complicated, but in order to define the structure of the list in connection with the forward-chaining rules, backtracking is required. So for instance, with two voices, in 2nd species ((_ _ ) (( ) ( ) ( ))) or 1st species (( _ ) ( _ _)), or some mixture of various templates could then be filled with variables, and then passed through the set of rules. If all of the constraints fail, it could backtrack and define a new list structure where the elements are nested differently.

This sort of list structure allows for most if not all of the patches corresponding to rules to have only one inlet.


An ideal visual control for list-structures that model the 1-to-N relation between voices would be some sort of tree-structure. So for each note in one voice, there might be two corresponding notes in another voice. Very complex nested structures, even. This way, note-to-note polyphony can be represented in a manner that may be conducive to analysis.

There’s a lot of functionality Screamer makes available, even compared to products like KnowledgeWorks.

PS: The first link ‘music-custom’ is an earlier iteration of this workspace I am putting together. I changed my Github login. The name ‘Paradigm’ occurred to me because I thought of strict-polyphony as just one of many possible paradigms. There could perhaps be a new folder corresponding to paradigms like modal-jazz or tonnetz.

PS: I will also check out SMC – it seems as though people have been wrestling with systems of this sort for quite some time.