Generate cantus firums

Introduction

CF1 music generator generates a melody (cantus firmus) by searching for a combination of notes which has minimum rule violations penalty. Each note in this melody will have the same note length. There will be no pauses inside a melody. Example of generation result:

Cantus firmus ("fixed song") is a pre-existing melody forming the basis of a polyphonic composition. It is also used to write counterpoint exercises by superimposing additional voices above or below it.

The rules that are used for cantus firmus generation can be enabled or disabled by user. For generating and correction of cantus firmus mainly Cantus and Melody rule groups are used. By default the rules are tuned to generating a vocal cantus firmus starting and ending with a tonic note.

Generation parameters

Key generator input parameters:

  • Number of notes to generate. Also can be changed in config with parameter c_len.

Due to the nature of algorithm and large number of rules used, generating long cantus firmus can take long. Time needed to generate cantus increases with the length of cantus, but it is not a static value, because number of operations to generate cantus of same length differs due to randomization. This means that longer canti can sometimes take less time to generate and sometimes more. If time needed to generate cantus exceeds some limit (1 to 10 minutes, depending on server settings), task will be aborted and melody with some mistakes will be returned. You can see mistakes in PDF files. In our tests, cantus with 250 notes without mistakes could always be generated during 2 minutes.

  • Mode
    • Natural major
    • Melodic minor
  • Enable or disable rules

In expert mode user can also change other parameters in text configuration:

  • Generate cantus firmus for soprano (cantus_high=1) or bass (cantus_high=0) voice. By default cantus firmus for bass is generated. Changing this parameter results in minor changes of some rules (first notes, cadential progression in the middle of cantus firmus) - which are also noted in comments to these rules.
  • GUI allows to choose only C major or C minor key for simplicity. In config user can choose any key (e.g. key=Bbm), but in this case you also need to change first and last notes correspondingly so that they are root notes of the selected key (e.g. first_note=Bb4 and last_note=Bb4). Algorithm supports only natural major and melodic minor modes.
  • Choose octave of generated cantus firmus by changing octave of first and last notes (e.g. first_note=Bb3 and last_note=Bb3)
  • Generate multiple cantus firmi at once by increasing t_cnt (e.g. t_cnt=100) to total number of notes. For example, t_cnt of 100 will generate 3 cantus firmi, 30 notes each.

Generating multiple cantus firmus will take more time.

Other parameters in config should be changed only if you know what you are doing.

Generation results

Generated melody is output in several formats:

  • PDF file with sheet music (icon will appear at the top of page after generation)
  • MIDI file (icon will appear at the top of page after generation)
  • MIDI file, adapted for playback with virtual instruments. You usually do not need this file. It can be accessed by clicking "Browse all files" on Files tab.

When browsing all files, you can notice that there is one file with .MID extension and one or more files with .MIDI extension. Pay attention that file with .MID extension is the main MIDI file, while .MIDI files are all adapted for playback. Usually you will need file with .MID extension to import generated music in other software.

  • MP3 file with generated music being played back with virtual instruments. If you need more control over virtual instruments selection and tuning, you can upload generated music to Artinfuser Studio

Also, multiple log files are produced as a result of generation process, which can help to understand what happened during generation. They can be viewed on the Info tab.

There are some other technical files (waveform image, waveform csv, adaptation noteinfo), that can be accessed by clicking "Browse all files" on Files tab. They are not important and will not be detailed here.

Troubleshooting

Problem Solution
Generation takes long Try decreasing length of cantus or revert rules to their default settings. If you changed t_cnt in config, reset it to 1.
Generation fails with error First try to restart the processing. If this does not help, try to unroll your latest changes, which could result in the error. In Expert mode on the Config tab you will find history of all your changes under the Save button. Pay attention that due to complex generation algorithms, some combinations of rules severities can result in unexpected behaviour. Try to set rules severities back to their default values or create new generation task. If you applied any changes previously, you will find default values in "Rule changes" box under the rules tree on the Settings tab. Also, keep in mind that trying to generate too long cantus can result in error due to timeout. Try decreasing length of cantus.

If you cannot find solution to your problem, please create support request (menu Support)

Playback

See playback section.

How algorithms work

Generating cantus firmus currently supports two methods: Strict Appending Scan (SAS) and Sliding Windows Approximation (SWA). Default algorithm is SWA, but in some situations you may want to switch to SAS.

Compare algorithms:

  • SAS scans all possible variants of note combinations, skips all melodies containing at least one mistake, and returns only melodies, which strictly comply to all of the rules. SWA starts with random melody and gradually fixes all mistakes that are found in it.
  • If there is not enough time for long music generation, SAS will return nothing. SWA will return partially optimized result, containing some mistakes. Several mistakes not always make music worse, but rather can result in a new experiment. Mistakes, that were not corrected, can be seen in PDF file.
  • SAS can return result very fast, but sometimes can take very long time (e.g. 10 times longer) - thus, processing time is less predictable. SWA usually requires approximately same time (or up to 2 times longer).

Some combinations of rules can work faster with SAS algorithm, while generally SWA algorithm is recommended and selected by default. You can select algorithm by editing method parameter in config (method=sas or method=swa)

SWA algorithm is built on top of SAS algorithm, so we will discuss SAS first.

Algorithm: Strict Appending Scan

Algorithm is written in C++ language for optimal performance.

SAS method works by scanning all possible variants of notes from left to right and checking if each combination of variants satisfies the rules. Key characteristic of algorithm is that all combinations, which start with notes, that do not comply with the rules, are automatically skipped:

  1. Choose the first possible variant of the first note. At this point we have only one generated note.
  2. Check if this first note does not violate rules, which can be evaluated without other notes generated.
  3. If the first note does not pass all rule checks, try another possible variant of the first note (go to 1). If this is the last possible variant, fail generation (no possible solution found).
  4. If the first note passes rule checks, start scanning the second note (go to 5)
  5. Choose the first possible variant of the second note. At this point we have two generated notes.
  6. Check if the first two generated notes do not violate rules, which can be evaluated without other notes generated.
  7. If the first two generated notes do not pass all rule checks, try another possible variant of the second note (go to 5). If this is the last possible variant of the second note, reset it to first variant and return to first note, trying its next possible variant (go to 1).
  8. If the first two generated notes pass all rule checks, start scanning the third note (go to 9)
  9. Choose the first possible variant of the third note...

It is important that checking rules is limited while not all notes are generated:

  • Some rules require full cantus to be generated. They are checked only at the last step.
    Examples: repeated melodic climax, resolution of penultimate note.
  • Some rules can be checked only after several more next notes to the right are generated.
    Examples: too many notes in one measure, suspension resolution.

As more and more rules are checked while cantus grows, generating later notes requires more variants to be tested. Returning to previous notes is the process that requires much processing time (e.g. returning from step 7 to step 1). Some rules require to return to previous notes. If previous note does not have variants, which satisfy the rules, the return can be deeper to several notes to the left. This can significantly slow down generation, which is an important characteristic of this algorithm.

To achieve different results on each algorithm run, algorithm scans variants in a random order. Order of possible notes for each measure is randomized before scanning possible combinations of notes.

Algorithm: Sliding Windows Approximation

Algorithm is written in C++ language for optimal performance.

SWA method works by trying to replace each note of a melody with all possible variants of other notes while choosing variants that result in minimum sum of violated rules' penalties. Before running SWA, a random melody is generated, which is then step by step morphed into a better melody.

In this video you can see how melody is morphed by SWA CP1 counterpoint generation algorithm from random to a sane melody. Colored notes (having one or more violations of counterpoint rules) are being gradually replaced with gray notes:


SWA algorithm actually consists of multiple SAS algorithm runs:

  1. Run SAS for each window of one note length.
    1. Try to replace first note with every possible pitch. Calculate total rules violations penalty for each pitch. Choose variant with lowest penalty (or stay with initial melody if all variants have greater penalty than initial variant).
    2. Try to replace second note with every possible pitch. Calculate total rules violations penalty for each pitch. Choose variant with lowest penalty (or stay with initial melody if all variants have greater penalty than initial variant).
    3. Repeat previous steps for each note in a melody.
  2. Run SAS for each window of two notes length.
    1. Try to replace first note with every possible pitch. Calculate total rules violations penalty for each pitch - for rules which can be evaluated without notes to the right. If penalty is greater than penalty for initial portion of melody to this note, skip this variant. If penalty is less or equal, go to next step (5).
    2. Try to replace second note with every possible pitch. Calculate total rules violations penalty for each pitch. Choose variant with lowest penalty (or stay with initial melody if all variants have greater penalty than initial variant).
    3. After checking all possible variants for second note, return to first note and find next variant for first note (go to 2.1), then try all variants of second note (go to 2.2)
    4. After checking all possible combinations of two notes, repeat previous steps 1.1 - 1.3 for each two adjacent notes in melody.
  3. Run SAS for each window of three notes length...

It is important that checking rules is limited while not all notes are generated inside a window (e.g. when generating first note in window of two notes):

  • Some rules require full cantus to be generated. They are checked only at the last step.
    Examples: repeated melodic climax, resolution of penultimate note.
  • Some rules can be checked only after several more next notes to the right are generated.
    Examples: too many notes in one measure, suspension resolution.

The run of SAS with window size of one note is very fast, but increasing size of window leads to exponential growth of processing time required. SAS in SWA skips all combinations starting with notes, which already have greater penalty, but still processing windows longer than 10 notes is slow.

To achieve different results on each algorithm run, algorithm scans variants in a random order. Order of possible pitches of each note is randomized before scanning.