|
I have used a few methods, but the most straight forward was to:
Use MIDIeditor to move the notes in to separate channels, this let me pick the 3 most important notes at any time and easily preview them. I did try to automate them, but it wasn't very reliable. You might also want to tidy up the timing here.
Then use MIDIanal to convert the MIDI to a .CSV, I have attached MIDIanal.png with the settings that I used.
I wrote a c++ program attached as make_music.zip to parse the .CSV and convert to register settings for notes, duration's for notes and the time to the next note on that channel.
The text file produced for carnival is attached as carnival_music.zip and contains 3 sections:
.snd_channels .snd_channel_0 \\ %rrrrllll len +8* reg EQUB &5D, &64, &5C, &3C, ..., 0 .snd_channel_1 \\ %rrrrllll len +8* reg EQUB &E8, &92, &93, &92, ..., 0 .snd_channel_2 \\ %rrrrllll len +8* reg EQUB &C2, &B2, &B2, &DA, ..., 0
These are the indices into the tables below; (num & 7) indexes snd_len and snd_gap while (num >> 3) indexes snd_reg_lo and snd_reg_hi. 0 means go back to the beginning (I was going to extend this but didn't need to).
snd_len_mul and snd_len_div were used to convert note timings to 50Hz, but in the latest version, the multiplication is done in real time to allow the music to change speed.
.snd_len \\ 10 lengths - hand hacked to 8 EQUB 0 * snd_len_mul / snd_len_div EQUB 1 * snd_len_mul / snd_len_div EQUB 1 * snd_len_mul / snd_len_div ... EQUB 8 * snd_len_mul / snd_len_div .snd_gap \\ 10 gaps - hand hacked to 8 EQUB (0+2) * snd_len_mul / snd_len_div EQUB (1+0) * snd_len_mul / snd_len_div EQUB (1+1) * snd_len_mul / snd_len_div ... EQUB (8+0) * snd_len_mul / snd_len_div
Note is silenced after snd_len updates and a new one started after snd_gap updates.
.snd_reg_lo \\ 30 notes %1cc0rrrr channel, reg & %00001111 EQUB %10000000 + (0 * %00100000) + (286 MOD 16) EQUB %10000000 + (0 * %00100000) + (321 MOD 16) EQUB %10000000 + (1 * %00100000) + (321 MOD 16) ... EQUB %10000000 + (1 * %00100000) + 0 .snd_reg_hi \\ 30 notes %00rrrrrr reg >> 4 EQUB 286 DIV 16 EQUB 321 DIV 16 EQUB 321 DIV 16 ... EQUB 1922 DIV 16 EQUB 0
These are the two bytes to write to the slow data bus, _lo first to latch the channel for _hi. I could have saved a few bytes by or-ing in the channel, but this lets me "hack" in silence by substituting a volume register setting for pitch.
In the actual music I needed 10 len/gap combinations and hand hacked the note to make a 12 length out of two 6 lengths with no gaps.
I am planning on making a sound tutorial at some point, but the basics are:
Set the system via data direction register to all write to put data on the slow data bus:
lda #&FF : sta SysViaDDRA \\ when sound selected, write val as per SN76489 data byte format
Then put the data on the bus and hold the sound select (or whatever it is called) on for 10us before turning it off per register setting:
.snd_write_A \\ A is written to sound slow data bus : Z=0 A=8 X=X Y=Y { SEI sta SysViaRegA \\ UG/AUG sample says SysViaRegH but OS uses no handshake \\ handshake regA lda #0+0 : sta SysViaRegB \\ enable sound for 8us (addr 0, bit 0) PHA : PLA : PHA : PLA \\ 3+4+3+4 + 2(lda #) = 16 clocks = 8us lda #0+8 : sta SysViaRegB \\ disable sound (addr 0, bit 1) CLI RTS }
Here, I use SEI/CLI - they aren't really necessary as I have all the interrupts covered and none actually touch the SysVia, but to be safe, you should probably include the lda #&FF : sta SysViaDDRA inside the SEI/CLI and do it each time.
The code in make_music.zip is probably quite hard to read, as I wrote it late at night, in a hurry and was quite fed-up with sound at the time!
It reads the notes, tracks start and end, tries to find a unit of time that fits all the note and gap lengths and then scales them accordingly - this works better if your source is precise, or if you tweak it in a MIDI editor. You could just fix float scale = beats[i]; to a number that works for you.
Richard
| Attachments: |
File comment: EQUB file ready for BEEBasm with carnival music in it
carnival_music.zip [793 Bytes]
Not downloaded yet
|
File comment: C++ source code for parsing the .CSV and creating the BBC ready EQUB file
make_music.zip [2.13 KiB]
Downloaded 1 time
|
File comment: Settings that I use

MIDIanal.png [ 30.1 KiB | Viewed 29 times ]
|
|