# # Render a tune represented using ABC notation. # from SimpleGraphics import * from math import log2 from time import sleep # Evaluate a value that might be a whole number or a fraction. Such values # show up as note lengths and as a description of the unit note length. # # Parameters: # s: A string the contains either a whole number or a fraction such as "1/4" # or "2" # # Returns: The floating point value of either the whole number or the # fraction. # def evaluateFraction(s): if "/" in s: # It's a fraction... # Separate the numerator from the denominator and convert each to a float. parts = s.split("/") numerator = float(parts[0]) denominator = float(parts[1]) # Evaluate the fraction and return the result. return numerator / denominator else: # It's not a fraction, so just return the value as a float. return float(s) # # Draw a staff with a treble clef, and 10 pixels between adjancent lines. # The staff will fill the width of the window, leaving 50 pixels on the # left and right edges of it. TrebleCelf_71.gif must be stored in the # same folder as the .py file. # # Parameters: # y: The vertical position of the top line of the staff. # # Returns: (None) # def drawStaff(y): for i in range(5): line(50, y + i * 10, getWidth() - 50, y + i * 10) treble_clef_image = loadImage("TrebleClef_71.gif") drawImage(treble_clef_image, 60, y - 16) # # Draw a music note with a hollow or filled head, stem, flag and dot as needed # for its duration. # # Parameters: # x, y: The location of the center of the head of the note. # duration: The duration of the note as a floating-point number. Supported # durations are 0.125, 0.25, 0.375, 0.5, 0.75, and 1.0. # inspace: True if the note resides in the space between two staff lines, # False if the note is on a line. # upstem: True if the note should be drawn with its stem extending up # from the head of the note, False if the stem should extend # downward. # color: The color of the note as a named color. # def drawNote(x, y, duration, inspace=True, upstem=True, color="black"): assert(x >= 0 and x <= getWidth()) assert(y >= 0 and y <= getHeight()) assert(duration in [1/8, 1/4, 3/8, 1/2, 3/4, 1]) assert(inspace == True or inspace == False) assert(upstem == True or upstem == False) # Set the outline color. setOutline(color) # Set the fill color so that the note is either open or filled, depending on # what is needed for its duration. if duration <= 3 / 8: setFill(color) else: setFill(None) # Draw the head of the note. ellipse(x-7, y-5, 14, 11) # These additional ellipses increase the weight of the line around the head # of open notes. ellipse(x-6, y-5, 12, 11) ellipse(x-7, y-4, 14, 9) # Draw the stem of the note (if needed, and in the correct direction). if duration < 1: # The note needs a stem... if upstem == False: # It's a down stem... line(x-7, y, x-7, y+35) # Does the note get a flag? if duration <= 1 / 8: #curve(x-7, y+35, x-7, y+25, x-15, y+15, x-11, y+5) curve(x-7, y+35, x-7, y+25, x+3, y+16, x-1, y+7) else: # It's an up stem... line(x+6, y, x+6, y-35) # Does the note get a flag? if duration <= 1 / 8: curve(x+7, y-35, x+7, y-25, x+15, y-15, x+11, y-5) # Does the note need a dot? if duration == 3/8 or duration == 3/4: setFill(color) # Does the dot get drawn vertically centered on the note because it is in # a space, or slightly above center to avoid being on a line? if inspace == True: ellipse(x + 11, y - 2, 4, 4) else: ellipse(x + 11, y - 5, 4, 4)