1
0

import_midi.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import struct
  2. # Constants for MIDI to Frequency conversion
  3. A4_MIDI = 69
  4. A4_FREQ = 440.0
  5. def midi_to_freq(note):
  6. return A4_FREQ * (2 ** ((note - A4_MIDI) / 12.0))
  7. def read_variable_length(data, index):
  8. value = 0
  9. while True:
  10. byte = data[index]
  11. index += 1
  12. value = (value << 7) | (byte & 0x7F)
  13. if not (byte & 0x80):
  14. break
  15. return value, index
  16. def parse_midi(filename):
  17. with open(filename, 'rb') as f:
  18. data = f.read()
  19. # Check MIDI header
  20. if data[:4] != b'MThd':
  21. raise ValueError("Invalid MIDI file")
  22. # Read header values
  23. header_size = struct.unpack('>I', data[4:8])[0]
  24. format_type, num_tracks, division = struct.unpack('>HHH', data[8:14])
  25. index = 14 + (header_size - 6)
  26. print("Header size:", header_size)
  27. print("Format type:", format_type)
  28. print("Number of tracks:", num_tracks)
  29. print("Division:", division)
  30. notes = []
  31. active_notes = {}
  32. last_time = 0
  33. while index < len(data):
  34. if data[index:index+4] == b'MTrk':
  35. index += 4
  36. track_length = struct.unpack('>I', data[index:index+4])[0]
  37. index += 4
  38. track_end = index + track_length
  39. while index < track_end:
  40. delta_time, index = read_variable_length(data, index)
  41. last_time += delta_time
  42. event = data[index]
  43. index += 1
  44. if event == 0xFF: # Meta event
  45. meta_type = data[index]
  46. index += 1
  47. length, index = read_variable_length(data, index)
  48. index += length # Skip meta event data
  49. elif event >= 0x80: # MIDI event
  50. status = event & 0xF0
  51. channel = event & 0x0F
  52. if status in (0x90, 0x80): # Note On/Off
  53. note = data[index]
  54. velocity = data[index + 1]
  55. index += 2
  56. if status == 0x90 and velocity > 0: # Note On
  57. active_notes[note] = last_time
  58. elif status == 0x80 or (status == 0x90 and velocity == 0): # Note Off
  59. if note in active_notes:
  60. start_time = active_notes.pop(note)
  61. duration = last_time - start_time
  62. pause_duration = 0 if not notes else start_time - (notes[-1][1] + notes[-1][2])
  63. notes.append((midi_to_freq(note), int(duration), int(pause_duration)))
  64. else:
  65. index += 1 # Skip unknown event
  66. return notes
  67. def generate_c_array(notes):
  68. c_code = "const struct Note notes[] = {\n"
  69. for freq, duration, pause in notes:
  70. c_code += f" {{{freq:.2f}, {duration}, {pause}}},\n"
  71. c_code += "};\n"
  72. return c_code
  73. # Example usage
  74. midi_file = "track_1.mid" # Replace with your MIDI file
  75. notes = parse_midi(midi_file)
  76. c_array = generate_c_array(notes)
  77. print(c_array)