Skip to content

Making Music

Designing drum tones

This feature is currently in development. For now, a small handful of drums are available through the catalogue feature. Come back later for updates.


Designing instrument tones

In the physical world, it is very difficult to create a musical instrument. But thankfully, it is very easy for Modulo1 to construct virtual instruments that exist in the computer's memory. And there are two very different ways that you can instruct Modulo1 to design a virtual instrument.

The first method, makes use of an intelligent algorithm called the autoDesigner. It is simpler to use because it does not require you to specify the exact details of the instrument's design. You just enter some vague requirements and it will create something randomly that meets those requirements.

For example, if you want your instrument to do a significant amount of pitch bending (which is where the pitch changes over time during one note), your pitchBend requirement would be a high number between the range of 0.0 and 1.0, such as 0.9. And perhaps you might want a very low amount of distortion in your instrument, so your distortion requirement would be a low number between the range of 0.0 and 1.0, such as 0.12.

Here is an example:

1
2
3
4
tracks {
    var inst1 = autoDesigner({ name : "Phat Bass", type : "bass" });
    inst1.design({ pitchBend : 0.9, distortion: 0.12 });
};

The second method, makes use of an algorithm called the soundDesigner. Here is an example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
tracks {
    var bass = soundDesigner({ 
        name: "Dirty Bass 01", 
        type: "bass", 
        filter : "LP", 
        octave : 1 
    });

    bass.automate({ aspect: "filterCutoff", time: 0 ticks, value: 0.05 });
    bass.automate({ aspect: "filterCutoff", time: 80 ticks, value: 0.4 });
    bass.automate({ aspect: "filterCutoff", time: 100 ticks, value: 1.0 });

    var layer1 = bass.createLayer({ type : "square" });

    layer1.automate({ aspect: "distortion", time: 0 ticks, value: 0.7 });
    layer1.automate({ aspect: "interval", time: 0 ticks, value: 0.55 });
    layer1.automate({ aspect: "interval", time: 100 ticks, value: 0.5 });
    layer1.automate({ aspect: "amp", time: 0 ticks, value: 1.0 });
};

Info

For more information about designing instrument tones automatically, check out our page on the autoDesigner
For more information about designing instrument tones manually, check out our page on the soundDesigner


Composing drum riffs

It is possible to manually compose a drum riff through code like this:

1
2
3
composition (1 bar) {
    var myBeats = |X---X---X---X-xx|;
};

The variable myBeats will now hold a drumRiff. The duration of the riff is 16 beats. This code has an X on every beat that we want to play loudly, an x on every beat that we want to play quietly, and a - on every beat that we want to be silent.

Composing manually like this can be a useful tool, but it is the least advanced method for composing drum riffs. And the problem is that it can result in your code generating the exact same drum pattern every time that it is run. If that is your goal, then that's fine. However, the true power of Modulo1 is its ability to compose something automatically, based on the requirements that you provide.

For example, you might want there to be very short stretches of silence between drum hits. So, your silence_max requirement would be a small number between 0.0 and 1.0, such as 0.25. And perhaps you might want there to be a medium-lengthed section of consecutive drum hits. So, your hitsMax requirement would be a mid-ranged number between 0.0 and 1.0, such as 0.4.

Here is an example:

1
2
3
4
composition (1 bar) {
    var myBeats = drumRiff(16 beats);
    myBeats.compose({ silenceMax : 0.25, hitsMax : 0.4 });
};

It is possible to use a combination of manual, and the automatic methods:

1
2
3
4
5
6
7
composition (1 bar) {
    var myBeats = drumRiff(16 beats);
    myBeats.compose({ silenceMax : 0.25 });

    var newEnding = |X-xx|;
    myBeats.overwrite(newEnding, 12 beats, false);
};

In this example, we have manually created an additional drumRiff that has a duration of only 4 beats. Then, we overwrite use it to overwrite the last four beats of our original drumRiff. We provide the second parameter 12 to indicate that the overwriting will begin after the 12th beat within our 16 beat drumRiff.

Info

For more information about designing drum riffs, check out our page on drumRiffs


Preparing a drum riff for playback

Modulo1 will allow you to create as many drum riffs as you like, but they cannot make any sound unless you attach them to some drums. After you have created your drums, you need to let Modulo1 know that you intend to compose for those drums:

1
2
3
4
tracks {
    var kick = find drum in (catalogue) where (id == "xUYRHGDJBGR");
    use (kick) in (composition);
};

The use keyword tells Modulo1 that you intend to make something available in a different section of your code. In this instance, we are telling Modulo1 that we want to use the kick in the composition section of our code.

The next step, is to actually write the code for our composition section:

1
2
3
composition (1 bar) {
    kick.compose({ nearHitsSum : 0.4 });
};

You will notice that we did not have to create a drumRiff variable inside the composition code block. Instead, Modulo1 has allowed us to use the kick as if it were a drumRiff.


Composing instrument melodies

It is possible to manually compose notes for a melody like this:

1
2
3
4
5
6
7
8
composition (1 bar) {
    inst1 = melody(1 bar)[
        [3] for 2 beats,
        [-] for 1 beat,
        [4] for 4 beats,
        [3] for 2 beats
    ];
}

This will result in a melody that will: * Play pitch number 3 for a duration of 2 beats * Then pause for 1 beat * Play pitch number 4 for 4 beats * Then play pitch number 3 for 2 beats

Composing manually like this can be a useful tool, but unless you know how to exploit all of its complexities, it can result in your code generating the exact same melody every time it is run. If that is your goal, then that's fine. However, the true power of Modulo1 is its ability to compose something randomly, but still within the requirements that you provide. So that in essence, what you are doing is defining a genre, and asking Modulo to compose something within that genre. The intelligent composition algorithm helps you to achieve that whilst being easy to learn.

Here is an example:

1
2
3
composition (1 bar) {
    inst1.compose({ noteRange : 0.3, silence : 0.4 });
}

Info

For more information about designing melodies, check out our page on melodies


Putting it all together

The following code will generate a short loop of music:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
tracks {
    var kick = find drum in (catalogue) where (id == "xUYRHGDJBGR");
    var snare = find drum in (catalogue) where (id == "xJKSGHTWJDG");

    var inst1 = autoDesigner({ name : "Phat Bass", type : "bass" });
    inst1.design({ distortion : 0.4 });

    var inst2 = autoDesigner({ name : "Powerful", type : "lead" });
    inst1.design({ pitchBend : 0.2 });

    use (kick, snare, inst1, inst2) in (composition);
};

composition (1 bar) {
    kick.compose({ nearHitsSum : 0.4 });
    snare.overwrite(|---X---X---X---X|, 0 beats, false);

    inst1.compose({ silence : 0.4, noteRange : 0.2 });
    inst2.createNotes()[
        [3] for 2 beats,
        [-] for 1 beat,
        [4] for 4 beats,
        [3] for 2 beats
    ];
};