HTML

notes.py

Nov 18th, 2016
206
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.73 KB | None | 0 0
  1. # Copyright 2012 Justas Sadzevicius
  2. # Licensed under the MIT license: http://www.opensource.org/licenses/MIT
  3. # Notes library for Finch buzzer
  4.  
  5. #("Middle C" is C4 )
  6.  
  7. frequencies = {
  8.     'C0': 16.35,
  9.     'C#0': 17.32,
  10.     'Db0': 17.32,
  11.     'D0': 18.35,
  12.     'D#0': 19.45,
  13.     'Eb0': 19.45,
  14.     'E0': 20.6,
  15.     'F0': 21.83,
  16.     'F#0': 23.12,
  17.     'Gb0': 23.12,
  18.     'G0': 24.5,
  19.     'G#0': 25.96,
  20.     'Ab0': 25.96,
  21.     'A0': 27.5,
  22.     'A#0': 29.14,
  23.     'Bb0': 29.14,
  24.     'B0': 30.87,
  25.     'C1': 32.7,
  26.     'C#1': 34.65,
  27.     'Db1': 34.65,
  28.     'D1': 36.71,
  29.     'D#1': 38.89,
  30.     'Eb1': 38.89,
  31.     'E1': 41.2,
  32.     'F1': 43.65,
  33.     'F#1': 46.25,
  34.     'Gb1': 46.25,
  35.     'G1': 49.0,
  36.     'G#1': 51.91,
  37.     'Ab1': 51.91,
  38.     'A1': 55.0,
  39.     'A#1': 58.27,
  40.     'Bb1': 58.27,
  41.     'B1': 61.74,
  42.     'C2': 65.41,
  43.     'C#2': 69.3,
  44.     'Db2': 69.3,
  45.     'D2': 73.42,
  46.     'D#2': 77.78,
  47.     'Eb2': 77.78,
  48.     'E2': 82.41,
  49.     'F2': 87.31,
  50.     'F#2': 92.5,
  51.     'Gb2': 92.5,
  52.     'G2': 98.0,
  53.     'G#2': 103.83,
  54.     'Ab2': 103.83,
  55.     'A2': 110.0,
  56.     'A#2': 116.54,
  57.     'Bb2': 116.54,
  58.     'B2': 123.47,
  59.     'C3': 130.81,
  60.     'C#3': 138.59,
  61.     'Db3': 138.59,
  62.     'D3': 146.83,
  63.     'D#3': 155.56,
  64.     'Eb3': 155.56,
  65.     'E3': 164.81,
  66.     'F3': 174.61,
  67.     'F#3': 185.0,
  68.     'Gb3': 185.0,
  69.     'G3': 196.0,
  70.     'G#3': 207.65,
  71.     'Ab3': 207.65,
  72.     'A3': 220.0,
  73.     'A#3': 233.08,
  74.     'Bb3': 233.08,
  75.     'B3': 246.94,
  76.     'C4': 261.63,
  77.     'C#4': 277.18,
  78.     'Db4': 277.18,
  79.     'D4': 293.66,
  80.     'D#4': 311.13,
  81.     'Eb4': 311.13,
  82.     'E4': 329.63,
  83.     'F4': 349.23,
  84.     'F#4': 369.99,
  85.     'Gb4': 369.99,
  86.     'G4': 392.0,
  87.     'G#4': 415.3,
  88.     'Ab4': 415.3,
  89.     'A4': 440.0,
  90.     'A#4': 466.16,
  91.     'Bb4': 466.16,
  92.     'B4': 493.88,
  93.     'C5': 523.25,
  94.     'C#5': 554.37,
  95.     'Db5': 554.37,
  96.     'D5': 587.33,
  97.     'D#5': 622.25,
  98.     'Eb5': 622.25,
  99.     'E5': 659.26,
  100.     'F5': 698.46,
  101.     'F#5': 739.99,
  102.     'Gb5': 739.99,
  103.     'G5': 783.99,
  104.     'G#5': 830.61,
  105.     'Ab5': 830.61,
  106.     'A5': 880.0,
  107.     'A#5': 932.33,
  108.     'Bb5': 932.33,
  109.     'B5': 987.77,
  110.     'C6': 1046.5,
  111.     'C#6': 1108.73,
  112.     'Db6': 1108.73,
  113.     'D6': 1174.66,
  114.     'D#6': 1244.51,
  115.     'Eb6': 1244.51,
  116.     'E6': 1318.51,
  117.     'F6': 1396.91,
  118.     'F#6': 1479.98,
  119.     'Gb6': 1479.98,
  120.     'G6': 1567.98,
  121.     'G#6': 1661.22,
  122.     'Ab6': 1661.22,
  123.     'A6': 1760.0,
  124.     'A#6': 1864.66,
  125.     'Bb6': 1864.66,
  126.     'B6': 1975.53,
  127.     'C7': 2093.0,
  128.     'C#7': 2217.46,
  129.     'Db7': 2217.46,
  130.     'D7': 2349.32,
  131.     'D#7': 2489.02,
  132.     'Eb7': 2489.02,
  133.     'E7': 2637.02,
  134.     'F7': 2793.83,
  135.     'F#7': 2959.96,
  136.     'Gb7': 2959.96,
  137.     'G7': 3135.96,
  138.     'G#7': 3322.44,
  139.     'Ab7': 3322.44,
  140.     'A7': 3520.0,
  141.     'A#7': 3729.31,
  142.     'Bb7': 3729.31,
  143.     'B7': 3951.07,
  144.     'C8': 4186.01,
  145.     'C#8': 4434.92,
  146.     'Db8': 4434.92,
  147.     'D8': 4698.64,
  148.     'D#8': 4978.03,
  149.     'Eb8': 4978.03,
  150. }
  151.  
  152.  
  153. class Command(object):
  154.     octave = 4
  155.     note = ''
  156.     duration = 0
  157.     sym = ''
  158.  
  159.     def reset(self):
  160.         self.note = ''
  161.         self.duration = 0
  162.         self.sym = ''
  163.  
  164.     def emit(self):
  165.         if not self.note or not self.duration:
  166.             return None
  167.         if self.note == '-':
  168.             return (0, self.duration)
  169.         ref = self.note.upper()+self.sym+str(self.octave)
  170.         frequency = frequencies.get(ref)
  171.         if not frequency:
  172.             return None
  173.         return (frequency, self.duration)
  174.  
  175.  
  176. def parse(sheet, speed=0.25):
  177.     """Parse a sheet of notes to a sequence of (duration, frequency) commands.
  178.  
  179.    speed is a duration of a "tick" in seconds.
  180.    Each *symbol* in the sheet takes up one tick.
  181.  
  182.    Valid notes are C, D, E, F, G, A, B and - (which means silence).
  183.    Sheet can also contain semitones:  C#, Eb, etc.
  184.    You can change active octave with numbers 0-8.
  185.  
  186.    Here are some examples:
  187.  
  188.    To play Do for four ticks and then Re for eight ticks, pass:
  189.    'C   D       '
  190.  
  191.    To play Do for two ticks, then silence for two ticks, then Do again:
  192.    'C - C '
  193.  
  194.    To play Do Re Mi, but octave higher:
  195.    'C5D E '
  196.  
  197.    parse('C3E G E ', speed=0.25)
  198.    will play C major chord over 2 seconds
  199.  
  200.    parse('C3  Eb  G   Eb   ', speed=0.125)
  201.    will play C minor chord over 2 seconds also
  202.    """
  203.     sheet = list(sheet)
  204.     commands = []
  205.  
  206.     next = Command()
  207.     while sheet:
  208.         #pop off a token
  209.         token = sheet.pop(0)
  210.  
  211.         #if next note is reached, append the current note onto the commands
  212.         if (token in 'CDEFGAB-' and next.note):
  213.             entry = next.emit()
  214.             if entry:
  215.                 commands.append(entry)
  216.                 next.reset()
  217.             #set the next note equal to the token
  218.             next.note = token
  219.            
  220.         #special case for the first note
  221.         if (token in 'CDEFGAB-' and not next.note):
  222.             next.note = token
  223.  
  224.         #handle octaves
  225.         elif token.isdigit():
  226.             next.octave = int(token)
  227.             next.duration -= speed
  228.         #handle flats and sharps
  229.         elif ((token == '#' or token == 'b') and next.note):
  230.             next.sym = token
  231.             next.duration -= speed
  232.         #rhythm
  233.         next.duration += speed
  234.     #append the last note into the commands
  235.     entry = next.emit()
  236.     if entry:
  237.         commands.append(entry)
  238.         next.reset()
  239.  
  240.     return commands
  241.  
  242. def sing(finch, sheet, speed=0.05):
  243.     """Sing a melody.
  244.  
  245.    sheet - a string of notes.  For the format see parse method in notes.py
  246.    speed - speed of a single tick in seconds.
  247.  
  248.    Example: sing('C D E F G A B C5', speed=0.1)
  249.    """
  250.     music = parse(sheet, speed=speed)
  251.     for freq, duration in music:
  252.         if duration:
  253.             finch.buzzer_with_delay(duration, int(freq))
Advertisement
Comments
  • User was banned
Add Comment
Please, Sign In to add comment