1. Towards the Next Milestone
The next goal is to create a program to play MIDI files using Z80 assembler. By specifying it on the command line, it is planned to make it possible to play MIDI files directly with the RC2014 computer alone.
Since a file system is required, the platform will be migrated from SCM to CP/M. Also, accurate timing generation for music playback requires timer interrupts. It would be good to have a Z80CTC card or a Z180 with a built-in CTC. Alternatively, J.B. Langston's designed TMS9918A Video Card for RC2014 can generate interrupts with vertical sync signals (1/50sec), which might be better.
To handle MIDI files, it is necessary to write a MIDI parser in Z80 assembler, which seems to be more complex than previous programs. Therefore, first, we will consider the MIDI file parser and the program for real-time management of playback time.
2. Structure of MIDI Files
Since the parsing of MIDI files is written in Python, it will be completed by replacing it with Z80 assembler. It seems easy to create if you ask ChatGPT. Also, so far, only NOTE messages have been handled, but it is necessary to modify it to handle other types of messages as well.
The existing Python MIDI file parser supports only single-track files and has limitations. Some MIDI files contain multiple tracks to handle multiple instruments simultaneously. Reading multiple tracks is just a matter of executing a single track multiple times, so it doesn't seem too difficult.
However, MIDI files with multiple tracks contain time information for each track, so to play them synchronously, it is necessary to devise a way to read them in real-time. Specifically, it is necessary to manage the playback time for each track and calculate the time to trigger the next event. This part seems to be a fairly complex algorithm. Also, since it is music playback, processing delays are fatal. It is necessary to adopt the fastest possible algorithm.
3. Looking at MIDI Files
Anyway, it seems necessary to check the structure of the MIDI files available. Therefore, I asked ChatGPT to create a program to dump MIDI files in Python.
Use it as follows:
$ python midi_parser.py Greensleeves.mid
- Format type: 0
- Number of tracks: 1
- Time division: 384
- Parsing track 1...
- Track length: 2256 bytes
- Delta time: 0, Total time: 0 ticks
- Meta event: Type 0x58, Length: 4, Data: b'\x04\x02\x18\x08'
- Delta time: 0, Total time: 0 ticks
- Meta event: Type 0x51, Length: 3, Data: b'\x1a(m'
- Delta time: 0, Total time: 0 ticks
- Meta event: Type 0x3, Length: 21, Data: b'Elec. Piano (Classic)'
- Delta time: 0, Total time: 0 ticks
- Program Change - Channel: 0, Program Number: 0
- Delta time: 0, Total time: 0 ticks
- Note ON - Channel: 0, Note: 38, Velocity: 50
- Delta time: 96, Total time: 96 ticks
- Note OFF - Channel: 0, Note: 38, Velocity: 0
- Delta time: 0, Total time: 96 ticks
- Note ON - Channel: 0, Note: 45, Velocity: 50
- Delta time: 96, Total time: 192 ticks
- Note OFF - Channel: 0, Note: 45, Velocity: 0
- Delta time: 0, Total time: 192 ticks
- Note ON - Channel: 0, Note: 50, Velocity: 50
- Delta time: 96, Total time: 288 ticks
- Note OFF - Channel: 0, Note: 50, Velocity: 0
- Delta time: 0, Total time: 288 ticks
- Note ON - Channel: 0, Note: 53, Velocity: 50
- Delta time: 96, Total time: 384 ticks
- Note OFF - Channel: 0, Note: 53, Velocity: 0
- Delta time: 0, Total time: 384 ticks
- Note ON - Channel: 0, Note: 50, Velocity: 50
- Delta time: 96, Total time: 480 ticks
- Note OFF - Channel: 0, Note: 50, Velocity: 0
- Delta time: 0, Total time: 480 ticks
- Note ON - Channel: 0, Note: 45, Velocity: 50
- Delta time: 96, Total time: 576 ticks
- Note OFF - Channel: 0, Note: 45, Velocity: 0
- Delta time: 0, Total time: 576 ticks
Each MIDI message is assigned a delta time. This indicates the timing to generate the MIDI message. It is called an EVENT, and it indicates the elapsed time from the previous message to generate the EVENT. It is necessary to accumulate the delta time from the beginning of the track and determine the timing to generate the EVENT (i.e., send the MIDI message). Each track is independently assigned a delta time. The MIDI player needs to keep track of playing point in every tracks.
(To Be Continued)
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.