Back to Top

Home/Tutorials

Random Music Generator


What's up, peeps? It's your friend Neil, and I've brought the code for another piece of educational software. This time we are going to build a random music generator, which can create and play great soundtracks at the push of a button. The project uses 12 audio samples; simply Google "free audio loops" if you don't have any laying around. And if you see a "Big Fish Audio" result close to the top, get the loops from those guys, who are known to produce top notch content. Don't worry, you won't need to buy anything from them; their free samples will be good enough for this project.


random music generator

var current_length = 0;

var loop_handle = 0;


BMAP* pointer_tga = "pointer.tga";

BMAP* generate1_tga = "generate1.tga";

BMAP* generate2_tga = "generate2.tga";


SOUND* loop01_wav = "loop01.wav";

SOUND* loop02_wav = "loop02.wav";

SOUND* loop03_wav = "loop03.wav";

SOUND* loop04_wav = "loop04.wav";

SOUND* loop05_wav = "loop05.wav";

SOUND* loop06_wav = "loop06.wav";

SOUND* loop07_wav = "loop07.wav";

SOUND* loop08_wav = "loop08.wav";

SOUND* loop09_wav = "loop09.wav";

SOUND* loop10_wav = "loop10.wav";

SOUND* loop11_wav = "loop11.wav";

SOUND* loop12_wav = "loop12.wav";


FONT* arial_font = "Arial#20";


function generate_song();


The code begins with a few variables, bitmaps, and sounds declarations. You can add more than 12 loops, because this will make the generated soundtracks much more interesting. Don't forget to modify function generate_song() as well, of course.


We are also defining a font, which will be used to display the "Seconds left" string on the screen, as well as a function prototype, which corresponds to the function that will do all the heavy lifting.


PANEL* main_pan =

{

bmap = "main.png";

layer = 10;

pos_x = 0;

pos_y = 0;

button (70, 80, generate1_tga, generate1_tga, generate2_tga, generate_song, NULL, NULL);

digits(70, 130, "Seconds left: %.1f", arial_font, 1, current_length);

flags = SHOW;

}


void main()

{

random_seed(0);

video_border(bmap_create("main.png"), 0, 0, 270, 180);

}


function mouse_startup()

{  

mouse_mode = 2;

mouse_map = pointer_tga;

while (1)

{  

  vec_set(mouse_pos, mouse_cursor);

  wait(1);

}

}


The code continues with a panel definition; it's the bitmap that will be used to display the "Generate" button, as well as to show the "Seconds left" time.


Function main() initializes the random number generator and creates a frame around the main.png bitmap, giving our tool a nice aspect, while function mouse_startup() allows us to move the mouse around. I've already discussed how this code works in a previous article, so I won't do it again.


function generate_song()

{

if (current_length > 0) {return;}

current_length = 60;


If the song is currently playing, a new "Generate" button press won't create a new song, because the first line of code inside function generate_song() prevents it from doing that. Then, we set the length of our soundtrack to 60 seconds; you can use any other value here.


var temp;

while (1)

{

  temp = 1 + integer(random(12));

  switch(temp)

  {

   case 1:

    loop_handle = snd_play (loop01_wav, 100, 0);

    break;

   case 2:

    loop_handle = snd_play (loop02_wav, 100, 0);

    break;

   case 3:

    loop_handle = snd_play (loop03_wav, 100, 0);

    break;


We define a variable named temp, and then we assign it a random integer that can range from 1 to 12. The "switch" instruction chooses various paths depending on the value of temp. If the generated integer has a value of one, the code will play the loop01_wav sound, and then will break out of the cycle. The same thing happens when temp is set to 2... 12, so we won't discuss that.


   case 4:

    loop_handle = snd_play (loop04_wav, 100, 0);

    break;

   case 5:

    loop_handle = snd_play (loop05_wav, 100, 0);

    break;

   case 6:

    loop_handle = snd_play (loop06_wav, 100, 0);

    break;

   case 7:

    loop_handle = snd_play (loop07_wav, 100, 0);

    break;

   case 8:

    loop_handle = snd_play (loop08_wav, 100, 0);

    break;

   case 9:

    loop_handle = snd_play (loop09_wav, 100, 0);

    break;

   case 10:

    loop_handle = snd_play (loop10_wav, 100, 0);

    break;

   case 11:

    loop_handle = snd_play (loop11_wav, 100, 0);

    break;

   case 12:

    loop_handle = snd_play (loop12_wav, 100, 0);

    break;

  }


The next "while" loop ensures that the timer works properly, by subtracting a value of 1 from the current_length variable each second. If the generated sountrack is over (current_length < 0), the application will display a value of zero, because a negative "Seconds left" value wouldn't look good on the screen.


  while (snd_playing (loop_handle))

  {

   current_length -= time_step / 16;

   if (current_length < 0)

   {

    current_length = 0;

    return;

   }

   wait (1);

  }

}

wait (1);

}


See? That wasn't a complicated code snippet! Many programmers use similar techniques to build advanced samplers, so you are in good company ;)