Writing Music Using PHP

Original author: Timothy Boronczyk
  • Transfer
I am not a specialist in probability theory, artificial intelligence, or machine learning, and the lessons of elementary music have long been forgotten. But if you take me 10 minutes, you will find that even a small supply of knowledge can give impressive results when applied creatively. I want to share with you how to teach PHP how to make music.

For example, this:

generated melody

You see a melody generated in PHP. Yes, of course, this melody is not one of the most memorable, but it is not ugly. And surprisingly, the code generating this sequence of notes is quite short.

So what is going on? In short, the musical data is analyzed by the script in order to “learn” to understand which intervals make up pleasant melodies. Then the script creates a new composition, choosing the heights based on their knowledge. Technically speaking, the script computes a probability map of melodic intervals and applies the Markov process to generate a new sequence.

Standing on the shoulders of giants


Composing music does not come from nothing. Bach was impressed by Buxtehude and Vivaldi. Chopin was influenced by Liszt and Wagner. Mozart and Haydn taught Beethoven. The same melody phrase can be found in different parts of the work. Orpheus and Eurydice Gluck and the motive of the anthem Non Dignus contain common musical phrases.

common musical phrases in Orpheus and Eurydice Gluck and the motive of the anthem Non Dignus

If you ask PHP to write blindly, the results are not very good. As evidence, I will cite a melody composed by comparing random values ​​of successful function calls rand()with notes.

random tune

If you do not know the technique of dodecafony , then for inspiration and understanding it is better to start from classical compositions.

To do this, I first rewrote the melody of several parts of musical works using a scientific pitch designation system . I did not bother with the duration of the notes. Instead, I focused on the very pitch of the sound. “Before” the first octave from the usual notes was entered as C4 (where C is the name of the note, 4 is the octave), the note is half a tone above 'C # 4', another half a tone above D4, and so on, as a result, the melody (here showing the first 8 measures Tantum Ergo ) was written like this:

first 8 measures from Tantum Ergo, Bottazzo

A4 C5 G4 A4 G4 A#4 D5 A4 B4 A4 C5 D5 C5 G4 B4 B4 C5

Now I have a sequence of notes that is easy to parse and which I could also easily use for analysis. For example, which note most likely follows A4? which ultimately gives:

A4 C5G4A4 G4A#4 D5A4 B4A4 C5D5 C5 G4 B4 B4 C5



C5 G4 B4 C5

We see that in 50% of cases the note is C5, in 25% of cases it is C4, and in 25% of cases it is B4.

This process makes of warm and lively music something only a computer understands with its cold and insensitive mathematical essence.

Calling Doctor Markov


We are familiar with deterministic systems - systems where the same input always returns the same result. Addition is a deterministic function in which 2 and 4 at the input will always give 6. Stochastic systems, on the contrary, behave with a certain level of randomness. The same input can lead to completely different results, for example with a function array_rand(). There is an element of chance in the composition of music. If this is not so, any composer, having met the note F4, will continue it equally, creating another hit for the insatiable dynasty of pop singers. But chance nevertheless brings its own corrections, despite the fact that, at a subconscious level, the composer understands what combinations are pleasing to the hearing.

A vivid example of a stochastic system that also relates to a script composing music is the Markov process (named after the mathematician Andrei Markov who not only studied it, but also grew a wonderful beard). Here's how Nick Didkovsky explains :

Markov analysis examines the sequence of events and analyzes the trends of a single event following it. Using this analysis, you can create a new sequence of random and at the same time related events that look similar to the original. The Markov process is useful in analyzing related random events, i.e. events that are related to past events.

A traditional example used to illustrate the concept is a weather forecast graph. Suppose the day after a sunny day has a 90% chance of being sunny, and the one following a rainy day has a 50% chance of being rainy. The graph will look like this:

Count Markov Sunny / rainy

Depending on the mechanism used to find the probability, going through the graph of 5 iterations, we might find that the first day is sunny, the next is rainy, after it is sunny again, then still sunny and sunny again, or go in sunny, sunny, sunny, rainy, rainy with repeated passage.

I hope it’s now clear what I’m getting at - we have the opportunity to limit the random process of “choosing the next note,” using the weighted probabilities determined by analyzing the melodies for a better sound.

A4 sheet music

This simple process allows us to create tolerable melodies, spending much less time than it would take for a monkey accidentally knocking on the keys of an organ to play the complete works of Messian.

Robots composers (singularity is near)


Well, I hope, in general terms, you understand the key principles that I used to create music. Even if not, you at least suffered my humor and deserved to see some code.

pitchProb = [];
    }
    public function train($noteData) {
       $numNotes = count($noteData);
       for ($i = 0; $i < $numNotes - 1; $i++) {
           $current = $noteData[$i];
           $next = $noteData[$i + 1];
           $this->pitchProb[$current][] = $next;
       }
   }
   public function compose($note, $numNotes) {
       $melody = [$note];
       while (--$numNotes) {
           $i = array_rand($this->pitchProb[$note], 1);
           $note = $this->pitchProb[$note][$i];
           $melody[] = $note;
       }
       return $melody;
   }
}


train($noteData);
$melody = $c->compose($_GET['note'], $_GET['count']);
echo 'Treble Clef';
foreach ($melody as $note) {
    echo '' .
        $note . '';
}


The learning process is described in a method train()that takes an input array of notes for training (the encoded melody is separated by spaces). The code is simple, fast and clumsy; Notes are stored in a two-dimensional array with a probability indirectly implied by the number of elements.

In the filled state, the array will look something like this:

array(9) {
  ["A4"]=> array(13) {
    [0]=> string(2) "C5"
    [1]=> string(2) "G4"
    [2]=> string(3) "A#4"
    [3]=> string(2) "C5"
    [4]=> string(2) "B4"
    [5]=> string(3) "A#4"
    [6]=> string(2) "G4"
    [7]=> string(2) "A4"
    [8]=> string(2) "D5"
    [9]=> string(2) "G4"
    [10]=> string(2) "C5"
    [11]=> string(2) "C5"
    [12]=> string(2) "G4"
  }
  ["C5"]=> array(11) {
...


Looking at the data, we see that a randomly selected note following A4 has an approximately 31% chance of becoming C5 since 4 out of 13 list items contain this value. (Yes, I know that it is better to operate on probabilities than to keep a list of all possible notes in the composition in my memory, but I did it on purpose to better illustrate the idea.)

The method compose()encapsulates the logic of generating a melodic sequence. Having received at the input the desired duration of the sequence of notes following the initial one, the method randomly selects the value of the notes from the array until it receives as many as needed.

Naturally, we are people and want to see the result in our usual musical notation. So I created a set of images to help the script. Each image reflects a note in a corresponding place among other notes. file names correspond to note names. Walking through the melody and rendering IMG elements is fine with me.

Faster, higher, stronger!


It is impressive how simple the ideas used to write a script that can behave were almost like a real composer. Of course, there is no limit to perfection, much more can be added and corrected. You can consider this your first experience in mastering musical intelligence. David Cope, a computer music composer since 1981, said :

Simply splitting a piece of music into smaller pieces and randomly combining them in a new order will almost certainly make nonsense. Effective rebuilding requires extensive musical analysis and very careful rebuilding to remain effective even at the most basic level.

Besides the obvious changes, such as changes in matrix height to maintain probabilities, what improvements would you make? Maybe replace this naive approach with a completely different mechanism for analyzing music? Analyze input from MIDI files? What is needed to reveal harmony? What about chords? Duration of notes? The “handwriting” of composers? Can your script learn based on the analysis of its own good melodies and use them to supplement its knowledge base? How could you redistribute the samples to create new work?

I would be interested to read your comments on the results of experiments in the field of artificial intelligence of controlled composing of music.



From a translator : I really wanted to listen to the melodies that result. savostin suggested to output in MIDI using a library in PHP , I liked the idea. And the melodies themselves, as it seemed to me, are easiest to take from the Internet in RTTTL format . He hurriedly sketched an example from the article, but sharpened for working with RTTTL and connected the output to MIDI. Now everyone can appreciate the work done by the author of the article.

Demo

Also popular now: