1 | /* A very simple program, that converts an AGI-song into a MIDI-song. */
|
---|
2 | /* Feel free to use it for anything. */
|
---|
3 |
|
---|
4 | /* To compile (using DJGPP for MS/DOS) type: */
|
---|
5 | /* gcc -lm -O3 snd2midi.c -o snd2midi */
|
---|
6 | /* if you've got problems on unix, type: */
|
---|
7 | /* gcc -lm -O3 -DUNIX snd2midi.c -o snd2midi */
|
---|
8 |
|
---|
9 | /* The default instrument is "piano" for all the channels, what gives */
|
---|
10 | /* good results on most games. But I found, that some songs are interesting */
|
---|
11 | /* with other instruments. If you want to experiment, modify the "instr" */
|
---|
12 | /* array. */
|
---|
13 |
|
---|
14 | /* Timing is not perfect, yet. It plays correct, when I use the */
|
---|
15 | /* Gravis-Midiplayer, but the songs are too fast when I use playmidi on */
|
---|
16 | /* Linux. */
|
---|
17 |
|
---|
18 | /* (A Wavetable-card is handy, here :-) */
|
---|
19 |
|
---|
20 | /* ---------------------------------------------------------------------- */
|
---|
21 | /* Original program developed by Jens. Christian Restemeier */
|
---|
22 |
|
---|
23 | /* Modifications for a speed choice: 4 September 1997, Lance Ewing. */
|
---|
24 | /* If SLOW is defined, then the speed will be more suitable for the */
|
---|
25 | /* majority of MIDI players. The initial speed used doesn't seem to be */
|
---|
26 | /* standard. */
|
---|
27 |
|
---|
28 | #include <stdio.h>
|
---|
29 | #include <stdlib.h>
|
---|
30 | #include <math.h>
|
---|
31 |
|
---|
32 | /* #define SLOW */
|
---|
33 |
|
---|
34 | #ifndef SLOW
|
---|
35 | #define SPEED_FACTOR 4
|
---|
36 | #else
|
---|
37 | #define SPEED_FACTOR 6
|
---|
38 | #endif
|
---|
39 |
|
---|
40 | unsigned char *snddata;
|
---|
41 |
|
---|
42 | /* channel / intrument setup: */
|
---|
43 |
|
---|
44 | /* most songs are good with this: */
|
---|
45 | unsigned char instr[] = {0, 0, 0};
|
---|
46 |
|
---|
47 | /* cool for sq2:
|
---|
48 | unsigned char instr[] = {50, 51, 19};
|
---|
49 | */
|
---|
50 |
|
---|
51 | void write_byte(FILE *f, long data)
|
---|
52 | {
|
---|
53 | fwrite(&data,1,1,f);
|
---|
54 | }
|
---|
55 |
|
---|
56 | void write_word(FILE *f, long data)
|
---|
57 | {
|
---|
58 | write_byte(f,(data>>8)&255);
|
---|
59 | write_byte(f,data&255);
|
---|
60 | }
|
---|
61 |
|
---|
62 | void write_long(FILE *f, long data)
|
---|
63 | {
|
---|
64 | write_byte(f,(data>>24)&255);
|
---|
65 | write_byte(f,(data>>16)&255);
|
---|
66 | write_byte(f,(data>>8)&255);
|
---|
67 | write_byte(f,data&255);
|
---|
68 | }
|
---|
69 |
|
---|
70 | void write_delta(FILE *f,long delta)
|
---|
71 | {
|
---|
72 | long i;
|
---|
73 | i=delta>>21; if (i>0) write_byte(f,(i&127)|128);
|
---|
74 | i=delta>>14; if (i>0) write_byte(f,(i&127)|128);
|
---|
75 | i=delta>>7; if (i>0) write_byte(f,(i&127)|128);
|
---|
76 | write_byte(f,delta&127);
|
---|
77 | }
|
---|
78 |
|
---|
79 | void write_midi(FILE *f)
|
---|
80 | {
|
---|
81 | long lp,ep;
|
---|
82 | int n;
|
---|
83 | double ll;
|
---|
84 |
|
---|
85 | ll=log10(pow(2.0,1.0/12.0));
|
---|
86 |
|
---|
87 | /* Header */
|
---|
88 | fwrite("MThd",4,1,f);
|
---|
89 | write_long(f,6);
|
---|
90 | write_word(f,1); /* mode */
|
---|
91 | write_word(f,3); /* number of tracks */
|
---|
92 | write_word(f,192); /* ticks / quarter */
|
---|
93 |
|
---|
94 | for (n=0;n<3;n++) {
|
---|
95 | unsigned short start, end, pos;
|
---|
96 |
|
---|
97 | fwrite("MTrk",4,1,f);
|
---|
98 | lp=ftell(f);
|
---|
99 | write_long(f,0); /* chunklength */
|
---|
100 | write_delta(f,0); /* set instrument */
|
---|
101 | write_byte(f,0xc0+n);
|
---|
102 | write_byte(f,instr[n]);
|
---|
103 | start=snddata[n*2+0] | (snddata[n*2+1]<<8);
|
---|
104 | end=((snddata[n*2+2] | (snddata[n*2+3]<<8)))-5;
|
---|
105 |
|
---|
106 | for (pos=start; pos<end; pos+=5) {
|
---|
107 | unsigned short freq, dur;
|
---|
108 | dur=(snddata[pos+0] | (snddata[pos+1]<<8))*SPEED_FACTOR;
|
---|
109 | freq=((snddata[pos+2] & 0x3F) << 4) + (snddata[pos+3] & 0x0F);
|
---|
110 | if (snddata[pos+2]>0) {
|
---|
111 | double fr;
|
---|
112 | int note;
|
---|
113 | /* I don't know, what frequency equals midi note 0 ... */
|
---|
114 | /* This moves the song 4 octaves down: */
|
---|
115 | fr=(log10(111860.0 / (double)freq) / ll) - 48;
|
---|
116 | note=floor(fr+0.5);
|
---|
117 | if (note<0) note=0;
|
---|
118 | if (note>127) note=127;
|
---|
119 | /* note on */
|
---|
120 | write_delta(f,0);
|
---|
121 | write_byte(f,144+n);
|
---|
122 | write_byte(f,note);
|
---|
123 | write_byte(f,100);
|
---|
124 | /* note off */
|
---|
125 | write_delta(f,dur);
|
---|
126 | write_byte(f,128+n);
|
---|
127 | write_byte(f,note);
|
---|
128 | write_byte(f,0);
|
---|
129 | } else {
|
---|
130 | /* note on */
|
---|
131 | write_delta(f,0);
|
---|
132 | write_byte(f,144+n);
|
---|
133 | write_byte(f,0);
|
---|
134 | write_byte(f,0);
|
---|
135 | /* note off */
|
---|
136 | write_delta(f,dur);
|
---|
137 | write_byte(f,128+n);
|
---|
138 | write_byte(f,0);
|
---|
139 | write_byte(f,0);
|
---|
140 | }
|
---|
141 | }
|
---|
142 | write_delta(f,0);
|
---|
143 | write_byte(f,0xff);
|
---|
144 | write_byte(f,0x2f);
|
---|
145 | write_byte(f,0x0);
|
---|
146 | ep=ftell(f);
|
---|
147 | fseek(f,lp,SEEK_SET);
|
---|
148 | write_long(f,(ep-lp)-4);
|
---|
149 | fseek(f,ep,SEEK_SET);
|
---|
150 | }
|
---|
151 | }
|
---|
152 |
|
---|
153 | /* MS/DOS requires "b"-mode, but I heard, that some unix-systems don't */
|
---|
154 | /* like it. */
|
---|
155 | #ifndef UNIX
|
---|
156 | #define O_RB "rb"
|
---|
157 | #define O_WB "wb"
|
---|
158 | #else
|
---|
159 | #define O_RB "r"
|
---|
160 | #define O_WB "w"
|
---|
161 | #endif
|
---|
162 |
|
---|
163 | void main(int argc, char *argv[])
|
---|
164 | {
|
---|
165 | FILE *fsnd, *fmid;
|
---|
166 | long size;
|
---|
167 |
|
---|
168 | if (argc<3) {
|
---|
169 | printf("snd2midi <sndfile> <midifile>\n");
|
---|
170 | } else {
|
---|
171 | if ((fsnd=fopen(argv[1],"rb"))!=NULL) {
|
---|
172 | fseek(fsnd,0,SEEK_END);
|
---|
173 | size=ftell(fsnd);
|
---|
174 | fseek(fsnd,0,SEEK_SET);
|
---|
175 | snddata=malloc(size);
|
---|
176 | fread(snddata,1,size,fsnd);
|
---|
177 | fclose(fsnd);
|
---|
178 |
|
---|
179 | if ((fmid=fopen(argv[2],"wb"))!=NULL) {
|
---|
180 | write_midi(fmid);
|
---|
181 | fclose(fmid);
|
---|
182 | printf("ok !\n");
|
---|
183 | } else printf("Error opening output !\n");
|
---|
184 | free(snddata);
|
---|
185 | } else printf("Error opening input !\n");
|
---|
186 | }
|
---|
187 | }
|
---|
188 |
|
---|
189 |
|
---|