Guest User

Midi Analyser

a guest
Sep 22nd, 2016
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.95 KB | None | 0 0
  1. # Open MIDI file
  2. print("NOTE: The midi file must be in the same directory as this .exe file!", "\n")
  3.  
  4. fil = input("Enter the name of the midi file you want analysed: ")
  5.  
  6. if fil[-4] + fil[-3] + fil[-2] + fil[-1] != ".mid":
  7.     fil += ".mid"
  8.  
  9. mFile = open(fil, 'rb')
  10.  
  11. print("\n" + "Analysing", fil, "\n")
  12.  
  13. # Checks if file is MIDI
  14. hChunk = mFile.read(4)
  15. if hChunk != b'MThd':
  16.     raise ValueError('Not a MIDI file')
  17.  
  18. contents = mFile.read()
  19.  
  20. # Close MIDI file again
  21. mFile.close()
  22.  
  23. # Number of bytes in the MIDI file
  24. midi_len = len(contents)
  25.  
  26. # Puts all bytes into this list
  27. midi_bytes = []
  28.  
  29. for i in range(0, midi_len):
  30.     byte = "x{:02X}".format(contents[i])
  31.     midi_bytes.append(byte)
  32. # To compare integers with given values you can just do : contents[i]==0x4d
  33.  
  34. # ---------------HEADER CHUNK--------------- #
  35. # Find Format, number of tracks, 'delta time' of MIDI
  36. for i in range(0, 10): # Header chunck is 14 bytes long (first 4 was removed)
  37.     if i == 5: # Checks format
  38.         if midi_bytes[i] == "x00":
  39.             print("Format: Single track", "\n")
  40.         elif midi_bytes[i] == "x01":
  41.             print("Format: Multiple track", "\n")
  42.         elif midi_bytes[i] == "x02":
  43.             print("Format: Multiple song (i.e. a series of single track songs)", "\n")
  44.  
  45.     if i == 7: # Finds number of tracks in MIDI
  46.         num_track = int(midi_bytes[i][1:3], 16)
  47.         print("Number of tracks:", num_track, "\n")
  48.  
  49.     if i == 8: #Finds delta timing
  50.         n = midi_bytes[i][1:3] + midi_bytes[i + 1][1:3]
  51.         num_delta = int(n, 16)
  52.         print("Number of ticks per quater note:", num_delta, "\n")
  53. # ------------------END--------------------- #
  54.  
  55. # Remove head chunk - no longer needed
  56. for i in range(0, 10):
  57.     del midi_bytes[0]
  58.  
  59. # --------------TRACK CHUNK----------------- #
  60. # INFO
  61. # All the differant keys
  62. keys = {
  63.     '0 C': 0,
  64.     '1 C#': 0,
  65.     '2 D': 0,
  66.     '3 D#': 0,
  67.     '4 E': 0,
  68.     '5 F': 0,
  69.     '6 F#': 0,
  70.     '7 G': 0,
  71.     '8 G#': 0,
  72.     '9 A': 0,
  73.     'A A#': 0,
  74.     'B B': 0
  75. }
  76.  
  77. for i in range(0, len(midi_bytes) - 3): # iterates through the midi (without head chunk)
  78.     # Looks for start of track chunk (MTrk)
  79.     if midi_bytes[i][1:3] + \
  80.        midi_bytes[i + 1][1:3] + \
  81.        midi_bytes[i + 2][1:3] + \
  82.        midi_bytes[i + 3][1:3] == "4D54726B":
  83.         # Found a track chunk
  84.  
  85.         # How long is the chunk?
  86.         len_of_chunk = int(midi_bytes[i + 4][1:3] +
  87.                            midi_bytes[i + 5][1:3] +
  88.                            midi_bytes[i + 6][1:3] +
  89.                            midi_bytes[i + 7][1:3], 16)
  90.  
  91.         # print("debug - chunk found") #DEBUG
  92.  
  93.         # iterates through that chunk (from 8 bytes after chunk start to length of chunk + 8 (from the 8 after))
  94.         for j in range(9, len_of_chunk + 8):
  95.             # Looks for keys
  96.  
  97.             bit = int(midi_bytes[j][1:3], 16)
  98.  
  99.             if midi_bytes[j - 1][1] == "8" and bit <= 127:
  100.  
  101.                 # print(bit) # For debugging
  102.  
  103.                 if bit % 12 == 0:
  104.                     # C found
  105.                     keys["0 C"] += 1
  106.                 elif bit % 12 == 1:
  107.                     # C# found
  108.                     keys["1 C#"] += 1
  109.                 elif bit % 12 == 2:
  110.                     # D found
  111.                     keys["2 D"] += 1
  112.                 elif bit % 12 == 3:
  113.                     # D# found
  114.                     keys["3 D#"] += 1
  115.                 elif bit % 12 == 4:
  116.                     # E found
  117.                     keys["4 E"] += 1
  118.                 elif bit % 12 == 5:
  119.                     # F found
  120.                     keys["5 F"] += 1
  121.                 elif bit % 12 == 6:
  122.                     # F# found
  123.                     keys["6 F#"] += 1
  124.                 elif bit % 12 == 7:
  125.                     # G found
  126.                     keys["7 G"] += 1
  127.                 elif bit % 12 == 8:
  128.                     # G# found
  129.                     keys["8 G#"] += 1
  130.                 elif bit % 12 == 9:
  131.                     # A found
  132.                     keys["9 A"] += 1
  133.                 elif bit % 12 == 10:
  134.                     # A# found
  135.                     keys["A A#"] += 1
  136.                 elif bit % 12 == 11:
  137.                     # B found
  138.                     keys["B B"] += 1
  139.  
  140. keys_in_total = 0
  141.  
  142. # Find the total amount of keys by adding them together
  143. for k, v in keys.items():
  144.     keys_in_total += v
  145.  
  146. # Print it in a pretty fashion
  147. for k, v in sorted(keys.items()):
  148.     percent = round((v / keys_in_total) * 50)  # To make it print in percent
  149.     leftover = 50 - percent
  150.     if len(k) == 4:  # This if statement just makes the output prettier
  151.         print(k[2::], "|", "#" * percent + "." * leftover, "|", v)
  152.     else: # Maybe change # to █ ?
  153.         print(k[2::], "", "|", "#" * percent + "." * leftover, "|", v)
  154. print("\n" + "Notes in total:", keys_in_total)
  155. # DOESNT WORK ON CRY ME A RIVER !?
  156.  
  157. # print(midi_bytes)
  158.  
  159. # Stops it from closing instantly
  160. input("\n" + "Press 'Enter' to exit")
Advertisement
Add Comment
Please, Sign In to add comment