CocoMIDI Pro File Format

****************************************************************************************************************

Coco MIDI Pro

(from a message posted on either CIS or Delphi by Frank Delargy)

Several people on this SIG and others have shown interest in the internal format of the TRACK and SONG (ALL) files saved by COCOMIDI_II. There are several reasons for wanting to know the format. As you know COCOMIDI-II will create a LYRA file from any COCOMIDI recording. COCOMIDI-II records each track in a polyphonic fashion; ie. more than one note per track. LYRA, however uses a completely different approach and its format limits each track to one note. When COCOMIDI converts its recordings to LYRA FORMAT it uses only one note per track in the conversion. LYRA tracks can be converted into COCOMIDI format, but COCOMIDI format is not readily converted into LYRA format.

I have played around with several algorithms to retain all of the notes (max 8) but I have been unhappy with the results and thus have never implemented them. I put this file up here to let those of you who enjoy a challenge have a fair bash at it. If you are successful in creating a nice-looking, orderly LYRA file from a series of polyphonic COCOMIDI tracks I would like to eventually include it in COCOMIDI, but that will be your call. I would like a copy though!

This text file will try to explain the format and how it is used by COCOMIDI. Lester has published the LYRA format and I believe it is posted somewhere on this SIG.

TRACKS:

COCOMIDI records one track at a time. Basically every MIDI byte that is sent out by the synthesizer is recorded as is. Interspersed with the MIDI data are other data that keep track of the timing. Most MIDI events consist of a status byte and two data bytes. For example a key pressed may produce the series of bytes in hexadecimal $90, $3C, $48. Subsequent note on & off events may not repeat the status byte. The synthesiser may send out $3D,$48,$30,$00 etc.

COCOMIDI records each event with a minimum of three bytes. The first byte is the tick timing byte, which may take on any value from 0 to 191. The normal MIDI timing clock is 24 clocks/quarter note. To enable greater accuracy COCOMIDI uses 48 clocks per quarter note and 4 times 48 is 192. A value of 96 would therefore correspond to a half note interval. Obviously this one byte counter will not allow for more than 4 quarter notes duration. When the tick timer byte reaches 192 it increments a second timing byte. In 4/4 time this byte would be equivalent to the number of measures recorded. For this reason I will refer to this as the measure timing byte. The tick timing byte is set back to 0 and both bytes continue to increment appropriately until the next MIDIevent is sensed. At that time if the measure timer is the same as before, only the tick timer will be recorded. If the measure timer has changed from the last MIDI event recorded, A special byte $FF will be recorded. Immediately following this byte are the current measure & tick timing bytes. The MIDI event will then be recorded in the usual manner ie Tick byte, data byte 1, data byte 2.

If the measure byte reaches 256, it is reset to 0 and a special byte $FE will be recorded, followed by the measure byte and tick byte. Then $FF is recorded with the low measure byte and the tick byte. Finally the three bytes defining the event (tick, data byte 1, data byte 2) are recorded.

MJIDI data is broken up systematically to fit into the three byte COCOMIDI format.

Control bytes ($90+) are stored as;

tick byte, control byte, dummy byte eg. $23,$90,$8F

Data bytes from one data byte control codes (Program change & channel pressure) are stored as;

tick byte, data byte, dummy byte eg. $24,$40,$8F

Data bytes from two data byte control codes (Note Off, Note On, Polyphonic key pressure, Control Change and Pitch Wheel Change) are stored as;

tick byte, data byte #1, data byte #2 eg. $25,$4C,$40

See the COCOMIDI user manual for a discussion of the 'Start Loop'

and 'End Loop' control bytes.

Following is a SOURCERER ZAP printout of a COCOMIDI II track showing several of the points mentioned above. The COCOMIDI II EDITOR listing of the track follows the hex dump output.

Following the Track information is the source code the data area that is saved with all of the tracks in the 'ALL' save mode.

PROGRAM:FORMAT PAGE No. 01 THE SOURCERER

address data......................................... ASCII ........

5D00 54 45 53 54 20 20 20 20 20 20 20 20 00 90 80 FF TEST

5D10 02 87 87 4C 40 FF 03 09 09 4C 00 56 4A 40 81 4A L@ L VJ@ J

5D20 00 9C 48 40 BF 48 00 FF 07 25 25 3C 40 47 3E 40 H@ H %%<@G>@

5D30 54 40 40 61 3C 00 67 3E 00 7C 41 40 83 40 00 90 T@@a< g> |A@ @

5D40 41 00 FF 82 67 67 46 40 78 46 00 FF FC 5D 5D 30 A ggF@xF ]]0

5D50 40 BC 30 00 FF FD 0C 0C 2F 40 52 2F 00 72 2D 40 @ 0 /@R/ r-@

5D60 9E 2F 40 A9 2D 00 FF FE 1B 1B 30 40 21 2F 00 5D /@ - 0@!/ ]

5D70 32 40 64 30 00 98 32 00 FE 00 98 FF 00 98 98 E0 2@d0 2

5D80 00 98 40 42 9A 40 44 9C 00 46 9F 00 49 A1 40 4C @B @D F I @L

5D90 A3 40 50 A5 00 54 A7 40 57 AA 00 5B AC 40 5E AE @P T @W [ @^

5DA0 40 61 B0 40 65 B2 00 69 B4 40 6C B7 00 70 B9 00 @a @e i @l p

5DB0 74 BB 00 78 BD 40 7B BF 40 7F FF 01 78 78 00 7E t x @{ @ xx ~

5DC0 7C 00 7B 80 00 78 87 00 74 8E 00 70 92 40 6B 96 | { x t p @k

5DD0 40 67 9B 00 63 9F 40 5E A4 00 5A A8 00 56 AC 40 @g c @^ Z V @

5DE0 52 B1 00 4D B3 00 4A B5 00 47 BA 40 40 BC 00 40 R M J G @@ @

5DF0 FF 02 1D 1D 90 00 1D 30 40 45 E0 00 45 00 43 47 0@E E CG

5E00 40 45 4A 00 48 4C 00 4C 4E 00 50 50 00 53 52 00 @EJ HL LN PP SR

5E10 56 54 40 59 57 40 5C 59 40 5F 5B 00 62 5D 40 65 VT@YW@\Y@_[ b]@e

5E20 5F 40 68 61 40 6B 64 00 6F 66 40 71 68 00 74 6A _@ha@kd of@qh tj

5E30 40 76 6C 00 79 6E 40 7B 71 00 7E 73 40 7F 9F 00 @vl yn@{q ~s@

5E40 79 A2 00 70 A4 40 66 A6 40 5A A8 00 4A AA 00 41 y p @f @Z J A

5E50 AC 00 40 B6 90 00 B6 30 00 FF 06 5E 5E C0 00 5E @ 0 ^^ ^

5E60 04 80 FF 0A 75 75 90 00 75 48 40 96 47 40 A5 48 uu uH@ G@ H

5E70 00 FF 0B 06 06 47 00 FF 0E 35 35 B0 00 35 01 00 G 55 5

5E80 FF 0F 8E 8E 90 00 8E 39 40 AC 39 00 FF 10 1B 1B 9@ 9

5E90 37 40 37 37 00 43 39 40 5F 39 00 FF 11 16 16 B0 7@77 C9@_9

5EA0 00 16 41 7F FF 12 22 22 90 00 22 34 40 4C 35 40 A "" "4@L5@

5EB0 50 34 00 7A 34 40 83 35 00 96 34 00 00

COCOMIDI-II EDITOR List output for TRACK #1 with some extra comments.

TEST FROM: 23820 TO: 24252

MEMORY TIME BYTE 1 BYTE 2 (COMMENTS) added comments

====== ==== ====== ====== ========== **************

23820 0:0:0 90 NOTE ON CH:1 Track usually starts

23823 TIMING BYTES: 2:2:39 0:0:0 time. First note

23826 2:2:39 76 64 E 4 ON at 2:2:39 so needs

23829 TIMING BYTES: 3:0:9 timing byte.

23832 3:0:9 76 0 E 4 OFF Note off at 3:0:9 so

23835 3:1:38 74 64 D 4 ON need another timing

23838 3:2:33 74 0 D 4 OFF byte.

23841 3:3:12 72 64 C 4 ON

23844 3:3:47 72 0 C 4 OFF

23847 TIMING BYTES: 7:0:37 Waited a while so need

23850 7:0:37 60 64 C 3 ON timing byte to signify

23853 7:1:23 62 64 D 3 ON change in measure

23856 7:1:36 64 64 E 3 ON

23859 7:2:1 60 0 C 3 OFF

23862 7:2:7 62 0 D 3 OFF

23865 7:2:28 65 64 F 3 ON

23868 7:2:35 64 0 E 3 OFF

23871 7:3:0 65 0 F 3 OFF

23874 TIMING BYTES: 130:2:7 Quite a bit later.

23877 130:2:7 70 64 A# 3 ON Notice no intervening

23880 130:2:24 70 0 A# 3 OFF timing bytes needed.

23883 TIMING BYTES: 252:1:45 Later still.

23886 252:1:45 48 64 C 2 ON

23889 252:3:44 48 0 C 2 OFF

23892 TIMING BYTES: 253:0:12

23895 253:0:12 47 64 B 1 ON

23898 253:1:34 47 0 B 1 OFF

23901 253:2:18 45 64 A 1 ON

23904 253:3:14 47 64 B 1 ON

23907 253:3:25 45 0 A 1 OFF

23910 TIMING BYTES: 254:0:27

23913 254:0:27 48 64 C 2 ON

23916 254:0:33 47 0 B 1 OFF

23919 254:1:45 50 64 D 2 ON

23922 254:2:4 48 0 C 2 OFF

23925 254:3:8 50 0 D 2 OFF

23928 TIMING BYTES: 256:0:0 Measure overflow. So $FE

23931 TIMING BYTES: 256:3:8 inserted. Notice editor

23934 256:3:8 E0 PITCH WHEEL CH:1 does not list 256:3:8

23937 256:3:8 64 66 until regular timing

23940 256:3:10 64 68 byte. (See ZAP output)

23943 256:3:12 0 70

23946 256:3:15 0 73

23949 256:3:17 64 76

23952 256:3:19 64 80

23955 256:3:21 0 84

23958 256:3:23 64 87

23961 256:3:26 0 91

23964 256:3:28 64 94

23967 256:3:30 64 97

23970 256:3:32 64 101

23973 256:3:34 0 105

23976 256:3:36 64 108

23979 256:3:39 0 112

23982 256:3:41 0 116

23985 256:3:43 0 120

23988 256:3:45 64 123

23991 256:3:47 64 127

23994 TIMING BYTES: 257:2:24

23997 257:2:24 0 126

24000 257:2:28 0 123

24003 257:2:32 0 120

24006 257:2:39 0 116

24009 257:2:46 0 112

24012 257:3:2 64 107

24015 257:3:6 64 103

24018 257:3:11 0 99

24021 257:3:15 64 94

24024 257:3:20 0 90

24027 257:3:24 0 86

24030 257:3:28 64 82

24033 257:3:33 0 77

24036 257:3:35 0 74

24039 257:3:37 0 71

24042 257:3:42 64 64

24045 257:3:44 0 64

24048 TIMING BYTES: 258:0:29

24051 258:0:29 90 NOTE ON CH:1 A control code

24054 258:0:29 48 64 C 2 ON

24057 258:1:21 E0 PITCH WHEEL CH:1 A control code

24060 258:1:21 0 67 followed by data bytes

24063 258:1:23 64 69

24066 258:1:26 0 72

24069 258:1:28 0 76

24072 258:1:30 0 80

24075 258:1:32 0 83

24078 258:1:34 0 86

24081 258:1:36 64 89

24084 258:1:39 64 92

24087 258:1:41 64 95

24090 258:1:43 0 98

24093 258:1:45 64 101

24096 258:1:47 64 104

24099 258:2:1 64 107

24102 258:2:4 0 111

24105 258:2:6 64 113

24108 258:2:8 0 116

24111 258:2:10 64 118

24114 258:2:12 0 121

24117 258:2:14 64 123

24120 258:2:17 0 126

24123 258:2:19 64 127

24126 258:3:15 0 121

24129 258:3:18 0 112

24132 258:3:20 64 102

24135 258:3:22 64 90

24138 258:3:24 0 74

24141 258:3:26 0 65

24144 258:3:28 0 64

24147 258:3:38 90 NOTE ON CH:1

24150 258:3:38 48 0 C 2 OFF

24153 TIMING BYTES: 262:1:46

24156 262:1:46 C0 PROG CHANGE CH:1 A one data-byte control

24159 262:1:46 4 code

24162 TIMING BYTES: 266:2:21

24165 266:2:21 90 NOTE ON CH:1

24168 266:2:21 72 64 C 4 ON

24171 266:3:6 71 64 B 3 ON

24174 266:3:21 72 0 C 4 OFF

24177 TIMING BYTES: 267:0:6

24180 267:0:6 71 0 B 3 OFF

24183 TIMING BYTES: 270:1:5

24186 270:1:5 B0 CONT CHANGE CH:1

24189 270:1:5 1 0

24192 TIMING BYTES: 271:2:46

24195 271:2:46 90 NOTE ON CH:1

24198 271:2:46 57 64 A 2 ON

24201 271:3:28 57 0 A 2 OFF

24204 TIMING BYTES: 272:0:27

24207 272:0:27 55 64 G 2 ON

24210 272:1:7 55 0 G 2 OFF

24213 272:1:19 57 64 A 2 ON

24216 272:1:47 57 0 A 2 OFF

24219 TIMING BYTES: 273:0:22

24222 273:0:22 B0 CONT CHANGE CH:1

24225 273:0:22 65 127

24228 TIMING BYTES: 274:0:34

24231 274:0:34 90 NOTE ON CH:1

24234 274:0:34 52 64 E 2 ON

24237 274:1:28 53 64 F 2 ON

24240 274:1:32 52 0 E 2 OFF

24243 274:2:26 52 64 E 2 ON

24246 274:2:35 53 0 F 2 OFF

24249 274:3:6 52 0 E 2 OFF

24252 ******* END OF TRACK *********

Following is the source code for the part of memory that is saved when

the ALL option is used. Basically it is a memory dump of the tracks

with the following information as a header. Each version will load in

the file at the appropriate address and modify the absolute addresses

after the load.

* This memory saved as part of ALL song save

ALLSAV FCB $41+$80,$4C+$80,$4C+$80 "ALL"

FCC /25/ version #

WHSTRT FDB START1 pointer to start of recording

* If this differs from current version then

* update all addresses after loading.

TIMEX FDB 96 Counter for beats

MET FCB 1 Set to 1 if Metronome ON

BEATS FCB 48 Ticks per clock MIDI

SLAVE FCB 0 Which timing? Set to values below.

* 0 = OFF (NORMAL)

* 1 = MASTER (COCO puts out timing bytes)

* $FF(-1)= SLAVE (Clock updated by external device eg. drum machine)

* $FE(-2)= STEP INPUT (Wait for keyboard presses)

CPQ FCB 2 Clocks per beat: 2=24/beat

* CPB for Master clock output =1 for 48/beat

* 4=12/Beat 8=6/Beat 24=2/Beat 48=1/Beat

NUMBEA FCB 4 number of beats per measure

*

***********************************

* Addresses of start & end of tracks

* May be modified by later versions at time of loading

* should be used to calculate offset.

* 16 bytes per track for no data.

TRAK1S FDB START1 start of track1

FDB START1+1*16-1 end of track1

FDB START1+1*16 start track2

FDB START1+2*16-1 end of track 2

FDB START1+2*16 etc...

FDB START1+3*16-1

FDB START1+3*16

FDB START1+4*16-1

FDB START1+4*16

FDB START1+5*16-1

FDB START1+5*16

FDB START1+6*16-1

FDB START1+6*16

FDB START1+7*16-1

FDB START1+7*16

FDB START1+8*16-1

FDB START1+8*16

FDB START1+9*16-1

FDB START1+9*16

FDB START1+10*16-1

FDB START1+10*16

FDB START1+11*16-1

FDB START1+11*16

FDB START1+12*16-1

FDB START1+12*16

FDB START1+13*16-1

FDB START1+13*16

FDB START1+14*16-1

FDB START1+14*16

FDB START1+15*16-1

FDB START1+15*16

FDB START1+16*16-1 end of track16

* track 17 is never used for recording.

* Only here for programming efficiency

FDB START1+16*16 start of track 17

ENDT17 FDB START1+17*16-1 end of track 17

* extra room for moving buffer addresses

FDB START1+17*16

FDB START1+18*16-1

***********************************

* Status of tracks

* 0=Off, 1=Play, $FF=Record(temporary)

STATUS FCB 0,0,0,0,0,0,0,0

FCB 0,0,0,0,0,0,0,0

*Channel assignment

CHAN.1 FCB 0,0,0,0,0,0,0,0 Send to channel

FCB 0,0,0,0,0,0,0,0 for appropriate track #

TRNSPO FCB 0,0,0,0,0,0,0,0 transpose values

FCB 0,0,0,0,0,0,0,0 for each track

* high byte of track addresses for COCO3

* not used in version 2.7 or lower but here for future

TRKHIB FCB 0,0,0,0,0,0,0,0

FCB 0,0,0,0,0,0,0,0

* Various Control Filter Flags follow

* 0=don't filter not 0= filter

FLTR.R FCB 0 filter out real-time commands

* change filter status

* separate filters for Ax, Bx, Cx, Dx,Ex & Fx

A.FLTR FCB 0 key pressure

B.FLTR FCB 0 control change

C.FLTR FCB 0 program change

D.FLTR FCB 0 channel pressure

E.FLTR FCB 0 pitch wheel

* always ignore system message

F.FLTR FCB 1 system message (always on)

TICKS FCB 192 # of ticks per measure

* (Changed by Tempo setting)

PNCHIN FCB 0,0,0 punch in measure

PCHOUT FCB 0,0,0 punch out measure

STPNCH FCB 0,0,0 start play measure

ENPNCH FCB 0,0,0 end play measure

SAVSTR FDB 0 start measure hex

SAVEND FDB 9999 end measure hex

SAVPIN FDB 0 punch in hex

SAVPOU FDB 0 punch out hex

RLMEAS FDB 0 count measures

RLBEAT FCB 0 count beats

* extra room for future versions

FDB 0,0,0,0,0,0,0,0

FDB 0,0,0,0,0,0,0,0

* end of data area

*

*

* This area is for the song mode parameters

*

ORG ALLSAV+$100

** PLAN MODE information **

* format for each line=

* track #, starting measure, ending measure, # of times

* can chain 252/6 (32) tracks together

CHAIN

FCB -1,0,0,0,0,0 1

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0 10

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0 16

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0 20

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0 30

FCB -1,0,0,0,0,0

FCB -1,0,0,0,0,0 32

*

********************************************************************

* Track memory starts $200 (512) above ALLSAV (V2.5=$5500+$200)

********************************************************************

ORG ALLSAV+$200

START1 EQU * start of recordings

* initial comments & data for each track

*

FCC /EMPTY / comment

FCB $0,$90,$80,0 meas 0:0:0: note on channel 1

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

FCC /EMPTY /

FCB $0,$90,$80,0

***

Moves out from here.

Well good luck and let me know how you make out.

Frank Delargy

DEL Software