12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- import struct
- # Constants for MIDI to Frequency conversion
- A4_MIDI = 69
- A4_FREQ = 440.0
- def midi_to_freq(note):
- return A4_FREQ * (2 ** ((note - A4_MIDI) / 12.0))
- def read_variable_length(data, index):
- value = 0
- while True:
- byte = data[index]
- index += 1
- value = (value << 7) | (byte & 0x7F)
- if not (byte & 0x80):
- break
- return value, index
- def parse_midi(filename):
- with open(filename, 'rb') as f:
- data = f.read()
-
- # Check MIDI header
- if data[:4] != b'MThd':
- raise ValueError("Invalid MIDI file")
-
- # Read header values
- header_size = struct.unpack('>I', data[4:8])[0]
- format_type, num_tracks, division = struct.unpack('>HHH', data[8:14])
- index = 14 + (header_size - 6)
- print("Header size:", header_size)
- print("Format type:", format_type)
- print("Number of tracks:", num_tracks)
- print("Division:", division)
-
- notes = []
- active_notes = {}
- last_time = 0
-
- while index < len(data):
- if data[index:index+4] == b'MTrk':
- index += 4
- track_length = struct.unpack('>I', data[index:index+4])[0]
- index += 4
- track_end = index + track_length
-
- while index < track_end:
- delta_time, index = read_variable_length(data, index)
- last_time += delta_time
- event = data[index]
- index += 1
-
- if event == 0xFF: # Meta event
- meta_type = data[index]
- index += 1
- length, index = read_variable_length(data, index)
- index += length # Skip meta event data
- elif event >= 0x80: # MIDI event
- status = event & 0xF0
- channel = event & 0x0F
-
- if status in (0x90, 0x80): # Note On/Off
- note = data[index]
- velocity = data[index + 1]
- index += 2
-
- if status == 0x90 and velocity > 0: # Note On
- active_notes[note] = last_time
- elif status == 0x80 or (status == 0x90 and velocity == 0): # Note Off
- if note in active_notes:
- start_time = active_notes.pop(note)
- duration = last_time - start_time
- pause_duration = 0 if not notes else start_time - (notes[-1][1] + notes[-1][2])
- notes.append((midi_to_freq(note), int(duration), int(pause_duration)))
- else:
- index += 1 # Skip unknown event
-
- return notes
- def generate_c_array(notes):
- c_code = "const struct Note notes[] = {\n"
- for freq, duration, pause in notes:
- c_code += f" {{{freq:.2f}, {duration}, {pause}}},\n"
- c_code += "};\n"
- return c_code
- # Example usage
- midi_file = "track_1.mid" # Replace with your MIDI file
- notes = parse_midi(midi_file)
- c_array = generate_c_array(notes)
- print(c_array)
|