Playing the drum machine

Now that we have a mechanism to load drum samples and a mechanism to define beat patterns in place, let us add the ability to play these beat patterns. In many ways, this is the core of our program.

Let us first understand the functionality that we want to achieve here. Once the user has loaded one or more drum sample and has defined a beat pattern using the toggle buttons, we need to scan each column of the pattern to see if it finds a green button. If it finds one, our code should play the corresponding drum sample before moving ahead. Moreover, green buttons on the same column should play almost together, while there should be some time gap between each successive column, which would define the tempo of the music.

Prepare for Lift Off

We will use the pymedia module to play the sound files. The pymedia module can play a wide variety of sound formats such as .wav, .ogg, .mp3, .avi, .divx, .dvd, and .cdda on multiple operating systems.

Without getting into the details of how pymedia plays the sound files, the official documentation tells us that we can play audio files using the following code sample:

import time, wave, pymedia.audio.sound as sound 
f= wave.open( 'YOUR FILE NAME', 'rb' )
sampleRate= f.getframerate()
channels= f.getnchannels() 
format= sound.AFMT_S16_LE
snd= sound.Output( sampleRate, channels, format )
s= f.readframes( 300000 )
snd.play( s )

If you run this piece of code as an independent script and supply the file location of a supported audio file in place of 'YOUR FILE NAME', this should play the media file on your computer.

Using this code sample, we will implement the play functionality for our drum machine.

Engage Thrusters

  1. Let us first import all of the necessary modules into our namespace (refer to the code in 3.05.py):
    import time
    import wave
    import pymedia.audio.sound as sound
  2. Next, we will define the play_sound method as follows:
    def play_sound(self, sound_filename):
      try:
        self.s = wave.open(sound_filename, 'rb')
        sample_rate = self.s.getframerate()
        channels = self.s.getnchannels()
        frmt = sound.AFMT_S16_LE
              self.snd= sound.Output(sample_rate, channels, frmt)
              s = self.s.readframes(300000)
        self.snd.play(s)
      except:
        pass

    This method simply takes the API provided by pymedia and wraps it into a method that takes a filename and plays it.

  3. Let us now define the play method that actually plays the beat samples:
    def play(self):
      for i in range(len(self.button[0])):
        for item in self.button:
          try:
            if item[i].cget('bg') == 'green':
            if not self.widget_drum_file_name [self.button.index(item)]:continue
            sound_filename = self.widget_drum_file_name [self.button.index(item)]
             self.play_sound(sound_filename)
          except: continue
          time.sleep(3/4.0)

    The description of the code is listed as follows:

    • We loop through all of the buttons scanning each column before moving to the next column. For every button, we use widget.cget() to check to see if its color is green.
    • If the color is green, we check if there is a corresponding drum sample loaded. If not, we ignore the green button and move to the next item in the loop using continue.
    • If the color is green and there is a corresponding drum sample loaded, we use the previously-defined pymedia wrapper method for playing audio to play that sample.
    • Before moving to the next column the code is made to sleep for a small interval. If the code is not made to sleep for a small duration, the program would play all the samples at a very rapid succession.
    • We have chosen to make the code sleep for a time period of one-eighth of a second. You can change this sleep time to vary the tempo.

Objective Complete – Mini Debriefing

In this iteration, we added the capability to play the loaded drum samples.

Our drum machine is now operational. You can load drum samples, define beat patterns, and when you click on the Play button, the drum machine plays that beat pattern!

Note

In this example, we decided whether or not to play a drum sample based on the color of the button. This has been used here for demonstration purposes. However, it is not a good practice to mix logic with appearance. A better idea would be to implement a data structure for buttons that would keep track of button state as "clicked" or "not-clicked", and then play the audio based on this button's state. Implementation of this dual button states is left as an exercise for you to explore.

Classified Intel

In our previous code, we used widget.cget() to fetch the current value of the button's bg option to check if it is green. You can use w.cget(key) to return the current value of a widget option. Also, note that cget() always returns the value as a string even if you give a nonstring value when configuring the widget option.

Similar to widget.cget()method, Tkinter offers a wide variety of methods for all its widgets. For a list of basic widget methods, refer to the The basic widget methods section in Appendix B, Quick Reference Sheets.

If you want to know all of the options configured for a particular widget, you may use the widget.config() method instead, as follows: (See the code in 3.06.py)

from Tkinter import *
root = Tk()
widget = Button(root, text="#", bg='green')
widget.pack()
print widget.config()
print widget.config('bg')
root.mainloop()

This code will print a dictionary showing all the key-value pairs for widget options and their values listed as tuples. For example, in the preceding code the line print widget.config('bg') prints a tuple:

('background', 'background', 'Background', <border object at 022A1AC8>, 'green')
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.189.228