Oct 072013
 

I watched one of Carrie-Anne Philbin’s Geek Gurl Diaries videos yesterday about the newly released Sonic Pi application. Sonic Pi is a clever way of introducing programming concepts through making music. It looked like fun, so I had to have a play straight away.

I have a ‘musical past’, so this was rather irresistable. For some time I’ve been harbouring an urge to make a solenoid-powered glockenspiel play Rimsky-Korsakoff’s “Flight of the Bumblebee”, which is an amazing piece because it’s so fast.

Solenoids are costly, software isn’t

But that’s a really expensive project (solenoids + a decent glockenspiel) and I haven’t got there yet. Sonic Pi offered me the chance to do it without the costly hardware part. So I got hold of a score arranged for Piano, and started programming it in.

The first thing I did was set some variables for different rhythms, which meant the tempo could be varied by changing just the “speed” variable.

I forgot that, apart from the last three bars, and one quaver each in bars 83 & 95, the entire piece (treble part) is semi-quavers with ALMOST NO RESTS.

  1. # flight of the bumblebee RasPi.TV style (or lack thereof)  
  2. # https://raspi.tv/?p=5216  
  3.   
  4. # first some rythms  
  5. speed = 0.45  #set overall speed  
  6. breve = 8 * speed  
  7. semibreve = 4 * speed  
  8. minim = 2 * speed  
  9. crotchet = 1 * speed  
  10. quaver = 0.5 * speed  
  11. semi = 0.25 * speed  
  12. demi = 0.125 * speed  
  13. hemi = 0.0625 * speed  

One Pi I have can handle speed = 0.4 without mangling the sound. Another needs to be 0.45. Ideally it would be slightly faster. I’m not sure exactly what the limiting factor is, but it’s nice to be able to push the limits and see what you can get away with.

4-5 hours & 1268 lines

It’s a 5 page score and took about 4-5 hours to program in 1268 lines of code. It’s quite a good example too, because there are quite a lot of repeated segments, which gives you a chance to practice loops. This is the first time I’ve ever written anything in Ruby.

Three quarters of the way through, I also realised it would have been more elegant and efficient to make functions for some of the repetitive parts which start at different pitch. That might happen in a future revision.

Repeats are easy

I can remember the feeling, in the school orchestra, when you see those two little dots at the end of a passage. “Oh no, we’ve got to do it all again!” Well in Sonic Pi, you just add a 2.times do before your repeated passage and an end at the end and you’re good to go (you should indent too, for readability).

But for now, sit back and enjoy the Sonic Pi rendition of The Flight of the Bumblebee.

Listen to it here

 
 
 
00:00
 
00:00
 
 
 
 
 
 
 

Download Bumble-Sonic-Pi MP3 file

The penultimate note sounds flat, but it is coded correctly. :)

Sonic Pi code download

Download bee.txt Sonic Pi code

Or get it straight on your pi with…
wget https://raspi.tv/wp-content/uploads/2013/10/bee.txt

No video from me today as my video PC has died. :( But here’s the GeekGurlDiaries video I mentioned that shows you how to do all this.

  8 Responses to “Sonic Pi – flight of the Bumblebee”

  1. Thank you once again Alex for this new and nice add-on to my list of applications for
    the RasPi.
    I’ve got it bumble_ing after reading 3x your instructions.

    Olaf

  2. Nice :-) That’s quite an impressive amount of typing there Alex!

    • Quite a lot of it was cutting and pasting blocks of 8 as I did a bar at a time.

      Hardest part was keeping track, which is why, nearer the end, I started adding bar numbers in comments.

      With hindsight, it could be done much more efficiently with functions for each of the main repeating themes, feeding the function the note number to start the sequence at. Although I don’t know how to do functions in Ruby yet, I can’t imagine it’s massively different/harder than Python.

      That’s for V2 :)

  3. This is great. I had thought of doing the bee before but was put off by the length. well done on your stamina! After an initial play through I made a couple of changes. The speed factor (0.45) is about as low as it will go without the output breaking up with clicks etc. However, if you change the synth to saw_beep by inserting the line
    with_synth “saw_beep
    after the variable declarations but before the first play command, then this synth is more amenable to playing faster. I was then able to reduce the speed factor to as low as 0.25 with acceptable output, and this gets nearer to the 1 minute duration for the piece, taking 1 min 23 seconds.

    If you are interested I have written quite a few sonic=pi pieces from beatles to bach which are available on https://gist.github.com/rbnpi

    • Excellent. I hadn’t played about with different synth sounds.

      I’m off abroad in a bit. When I get back, I’ll have a look at your Sonic Pi work Robin.

      If I did it again, I’d definitely try to use a function for the repeating themes, just passing it the value of the starting note.

  4. […] Sonic Pi flight of bumblebee video from RasPi.TV: Using Sonic Pi to play flight of the bumblebee on a Raspberry Pi also using an HDMIPi portable Hi-Def screen. This is using the V1 HDMIPi prototype which has HDMI audio broken out to 3.5mm stereo jack. It’s a bit crackly, but that’s Sonic Pi, not the hardware. […]

  5. […] Rimsky Korsakoff’s Flight of the Bumble Bee for Sonic Pi 2. I know that there is at least one version out there already for Sonic Pi 1, written by Alex Eames of Raspi-TV, which  used a single synth, and numerical […]

  6. That is a lot of work! Here is the same song but with less code. You can use the play_pattern_timed which works really well for playing a list of notes. I kept the same groupings you had.

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    # Flight of the Bumblebee
     
    # Set BPM
    use_bpm 140
     
    # Define note lengths
    breve = 8
    semibreve = 4
    minim = 2
    crotchet = 1
    quaver = 0.5
    semi = 0.25
    demi = 0.125
    hemi = 0.0625
     
    # Set Synthesizer
    use_synth :pretty_bell
     
    play_pattern_timed [93, 92, 91, 90, 91, 90, 89, 88], semi
    play_pattern_timed [89, 88, 87, 86, 85, 84, 83, 82], semi
    play_pattern_timed [81, 80, 79, 78, 79, 78, 77, 76], semi
    play_pattern_timed [77, 76, 75, 74, 73, 72, 71, 70], semi
     
    2.times do
      play_pattern_timed [69, 68, 67, 66, 67, 66, 65, 64], semi
    end
     
    # bar 7
     
    2.times do
      2.times do
        play_pattern_timed [69, 68, 67, 66, 65, 70, 69, 68], semi
        play_pattern_timed [69, 68, 67, 66, 65, 66, 67, 68], semi
      end
     
      play_pattern_timed [69, 68, 67, 66, 67, 66, 65, 64], semi
      play_pattern_timed [65, 66, 67, 68, 69, 70, 69, 68], semi
      play_pattern_timed [69, 68, 67, 66, 67, 66, 65, 64], semi
      play_pattern_timed [65, 66, 67, 68, 69, 71, 72, 73], semi
     
      2.times do
        play_pattern_timed [74, 73, 72, 71, 70, 75, 74, 73], semi
        play_pattern_timed [74, 73, 72, 71, 70, 71, 72, 73], semi
      end
     
      2.times do
        play_pattern_timed [74, 73, 72, 71, 72, 71, 70, 69], semi
        play_pattern_timed [70, 71, 72, 73, 74, 75, 74, 73], semi
      end
     
      play_pattern_timed [74, 62, 62, 62, 62, 62, 62, 62], semi
      play_pattern_timed [63, 62, 63, 75, 63, 62, 63, 75], semi
     
      8.times do
        play 74
        sleep semi
      end
     
      play_pattern_timed [75, 74, 75, 87, 75, 74, 75, 87], semi
      play_pattern_timed [86, 75, 74, 73, 74, 75, 74, 73], semi
      play_pattern_timed [74, 75, 74, 73, 74, 75, 74, 73], semi
     
      2.times do
        play_pattern_timed [74, 75, 76, 77, 78, 77, 76, 75], semi
      end
     
      # bar 31
      play_pattern_timed [74, 67, 67, 67, 67, 67, 67, 67], semi
      play_pattern_timed [68, 67, 68, 80, 68, 67, 68, 80], semi
     
      play_pattern_timed [67, 79, 79, 79, 79, 79, 79, 79], semi
      play_pattern_timed [80, 79, 80, 92, 80, 79, 80, 92], semi
     
      play_pattern_timed [91, 80, 79, 78, 79, 80, 79, 78], semi
     
      # bar 36
      play_pattern_timed [79, 80, 79, 78, 79, 80, 79, 78], semi
     
      2.times do
        play_pattern_timed [79, 80, 81, 82, 83, 82, 81, 80], semi
      end
     
      play_pattern_timed [79, 78, 77, 76, 75, 80, 79, 78], semi
     
      # bar 40
      play_pattern_timed [79, 78, 77, 76, 75, 76, 77, 78], semi
      play_pattern_timed [79, 78, 77, 76, 77, 76, 75, 74], semi
     
      # bar 42
      play_pattern_timed [75, 76, 77, 78, 77, 78, 79, 80], semi
      play_pattern_timed [81, 80, 79, 78, 79, 78, 77, 76], semi
     
      # bar 44
      play_pattern_timed [77, 76, 75, 74, 73, 72, 71, 70], semi
     
      8.times do
        play_pattern_timed [69, 70, 69, 68], semi
      end
     
      #bar 49
      play_pattern_timed [69, 68, 67, 66, 67, 66, 65, 64], semi
     
      # bar 50
      play_pattern_timed [65, 64, 63, 62, 61, 60, 59, 58], semi
     
      8.times do
        play_pattern_timed [57, 58, 57, 56], semi
      end
     
      play_pattern_timed [57, 58, 59, 60, 61, 62, 63, 64], semi
      play_pattern_timed [65, 66, 67, 68, 69, 70, 71, 72], semi
      play_pattern_timed [73, 74, 75, 76, 77, 78, 79, 80], semi
     
      2.times do
        play_pattern_timed [81, 82, 81, 80], semi
      end
    end # main repeat loop
     
    # bar 63
    2.times do
      play_pattern_timed [81, 80, 79, 78, 77, 82, 81, 80], semi
      play_pattern_timed [81, 80, 79, 78, 77, 78, 79, 80], semi
    end
     
    # bar 65, page 4
    play_pattern_timed [81, 80, 79, 78, 79, 78, 77, 76], semi
    play_pattern_timed [77, 78, 79, 80, 81, 83, 84, 85], semi
     
    #bar 67
    2.times do
      play_pattern_timed [86, 85, 84, 83, 82, 87, 86, 85], semi
      play_pattern_timed [86, 85, 84, 83, 82, 83, 84, 85], semi
    end
     
    # bar 71
    play_pattern_timed [86, 85, 84, 83, 84, 83, 82, 81], semi
    play_pattern_timed [82, 83, 84, 85, 86, 87, 86, 85], semi
    play_pattern_timed [86, 85, 84, 83, 82, 83, 84, 85], semi
     
    # bar 74
    play_pattern_timed [74, 76, 77, 79, 81, 83, 81, 80], semi
     
    # bar 75
    2.times do
      play_pattern_timed [81, 80, 79, 78, 77, 82, 81, 80], semi
      play_pattern_timed [81, 80, 79, 78, 77, 78, 79, 80], semi
    end
     
    #bar 79
    play 81
    sleep quaver
    play_pattern_timed [73, 74, 75, 76, 77, 78], semi
    play_pattern_timed [79, 78, 77, 76, 77, 76, 75, 74], semi
     
    # bar 81
    play_pattern_timed [73, 74, 75, 76, 77, 78, 79, 80], semi
    play_pattern_timed [81, 82, 81, 80, 81, 82, 81, 80], semi
     
    # bar 83
    play 93
    sleep quaver
    play_pattern_timed [73, 74, 75, 76, 77, 78], semi
    play_pattern_timed [79, 78, 77, 76, 77, 76, 75, 74], semi
     
    # bar 85
    play_pattern_timed [73, 74, 75, 76, 77, 78, 79, 80], semi
    play_pattern_timed [81, 82, 81, 80, 81, 83, 84, 85], semi
    play_pattern_timed [86, 85, 84, 83, 84, 83, 82, 81], semi
    play_pattern_timed [82, 81, 80, 79, 78, 77, 76, 75], semi
     
    #bar 89
    play_pattern_timed [74, 73, 72, 71, 72, 71, 70, 69], semi
    play_pattern_timed [70, 69, 68, 67, 66, 65, 64, 63], semi
     
    #bar 91
    play_pattern_timed [62, 63, 62, 61, 63, 62, 63, 75], semi
    play_pattern_timed [62, 63, 62, 64, 62, 65, 62, 67], semi
     
    # 93
    play_pattern_timed [81, 82, 81, 80, 81, 93, 81, 95], semi
    play_pattern_timed [93, 83, 81, 95, 81, 96, 81, 97], semi
     
    # 95
    play 98
    sleep quaver
     
    # quaver rest
    sleep quaver
     
    play_pattern_timed [69, 70, 71, 72], semi
    play_pattern_timed [73, 74, 75, 76, 77, 78, 79, 80], semi
     
    #97
    play_pattern_timed [81, 82, 83, 84, 85, 86, 87, 88], semi
    play_pattern_timed [89, 90, 91, 92, 93, 95, 96, 97], semi
     
    #99
    play 98
    sleep minim
     
    #100
    play 110
    sleep minim
     
    play 86
    sleep crotchet

Leave a Reply to Olaf Cancel reply