1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #include "general.h"
7 #include "fileoutput.h"
8
9 /*
10
11 Ringtone Tools - Copyright 2001-2005 Michael Kohn (mike@mikekohn.net)
12 This falls under the Kohnian license. Please read
13 it at http://ringtonetools.mikekohn.net/
14
15 This program is NOT opensourced. You may not use any part
16 of this program for your own software.
17
18 */
19
get_next(FILE * in)20 int get_next(FILE *in)
21 {
22 int ch;
23
24 while(1)
25 {
26 ch=getc(in);
27
28 if (ch==' ' || ch=='\t')
29 { continue; }
30 else
31 if (ch=='\n' || ch=='\r')
32 {
33 ch=getc(in);
34 if (ch!='\r' && ch!='\n') ungetc(ch,in);
35 return '\n';
36 }
37 else
38 if (ch==EOF)
39 { return EOF; }
40 else
41 { return tolower(ch); }
42 }
43
44 return 0;
45 }
46
get_field(FILE * in,char * field_name,char * field_value)47 int get_field(FILE *in, char *field_name, char *field_value)
48 {
49 int ch,ptr,p;
50 char *buffer;
51 int marker;
52
53 buffer=field_name;
54 marker=ftell(in);
55
56 field_name[0]=0;
57 field_value[0]=0;
58
59 ptr=0; p=0;
60 while(1)
61 {
62 ch=getc(in);
63
64 if (ptr==0 && p==0)
65 {
66 if (ch=='\r' || ch=='\n') continue;
67 if (ch==EOF) return -1;
68 }
69
70 if (ch==':' && p==0)
71 {
72 buffer[ptr]=0;
73 if (strcasecmp(buffer,"melody")==0) return 2;
74
75 buffer=field_value;
76 ptr=0;
77 p++;
78 continue;
79 }
80
81 if (ch=='\n' || ch=='\r' || ch==EOF || ptr==1023)
82 {
83 if (p==0)
84 {
85 fseek(in,marker,SEEK_SET);
86 return 1;
87 }
88
89 buffer[ptr]=0;
90 return 0;
91 }
92
93 buffer[ptr++]=ch;
94 }
95
96 return 0;
97 }
98
parse_num(FILE * in)99 int parse_num(FILE *in)
100 {
101 int ch,i;
102
103 i=0;
104
105 while(1)
106 {
107 ch=getc(in);
108 if (ch>='0' && ch<='9')
109 {
110 i=(i*10)+(ch-'0');
111 }
112 else
113 { ungetc(ch,in); return i; }
114 }
115 }
116
parse_melody(FILE * in,FILE * out,struct note_t * note,int out_type)117 void parse_melody(FILE *in, FILE *out, struct note_t *note, int out_type)
118 {
119 int ch,t;
120 int tone_modifier;
121 int repeat,repeat_count=0;
122 unsigned char default_octave;
123 char token[255];
124
125 default_octave=4;
126 tone_modifier=0;
127 repeat=ftell(in);
128
129 header_route(out,note,1,out_type);
130
131 while(1)
132 {
133 ch=get_next(in);
134 if (ch==EOF || ch=='\n') break;
135
136 if (ch=='*')
137 {
138 ch=get_next(in);
139 if (ch==EOF || ch=='\n') break;
140
141 default_octave=ch-'0';
142 if (default_octave>8) default_octave=4;
143 continue;
144 }
145
146 if (ch=='{')
147 {
148 repeat=ftell(in);
149
150 continue;
151 }
152
153 if (ch=='}')
154 {
155 ch=get_next(in);
156 if (ch==EOF || ch=='\n') break;
157 if (ch=='@')
158 {
159 gettoken(in,token,2);
160 t=atoi(token);
161 #ifdef DEBUG
162 printf("%d\n",t);
163 #endif
164 if (repeat_count<t)
165 { fseek(in,repeat,SEEK_SET); }
166
167 repeat_count++;
168
169 continue;
170 }
171
172 break;
173 }
174
175 if (ch=='v')
176 {
177 ch=get_next(in);
178 if (ch==EOF || ch=='\n') break;
179
180 if (ch=='-') { note->volume--; }
181 else
182 if (ch=='+') { note->volume++; }
183 else
184 if (ch>='0' && ch<='9') note->volume=parse_num(in);
185
186 if (note->volume<0) note->volume=0;
187 else
188 if (note->volume>15) note->volume=15;
189
190 volume_route(out,note,1,out_type);
191
192 continue;
193 }
194
195 if (ch=='#')
196 {
197 tone_modifier=1;
198 continue;
199 }
200
201 if (ch=='&')
202 {
203 tone_modifier=-1;
204 continue;
205 }
206
207 if (ch=='a') note->tone=10;
208 else
209 if (ch=='h' || ch=='b') note->tone=12;
210 else
211 if (ch=='c') note->tone=1;
212 else
213 if (ch=='d') note->tone=3;
214 else
215 if (ch=='e') note->tone=5;
216 else
217 if (ch=='f') note->tone=6;
218 else
219 if (ch=='g') note->tone=8;
220 else
221 if (ch=='p' || ch=='r') note->tone=0;
222
223 note->tone=note->tone+tone_modifier;
224 if (note->tone<1 && ch!='r' && ch!='p')
225 {
226 note->tone=12;
227 note->scale--;
228 }
229 else
230 if (note->tone>12)
231 {
232 note->tone=1;
233 note->scale++;
234 }
235
236 ch=get_next(in);
237 /* if (ch==EOF || ch=='\n') break; */
238
239 note->length=2;
240 if (ch>='0' && ch<='5')
241 {
242 note->length=ch-'0';
243 ch=get_next(in);
244 }
245
246 if (ch=='.') note->modifier=1;
247 else
248 if (ch==':') note->modifier=2;
249 else
250 if (ch==';') note->modifier=3;
251 else
252 {
253 ungetc(ch,in);
254 note->modifier=0;
255 }
256
257 note->scale=default_octave-3;
258 if (note->scale<0) note->scale=0;
259
260 note_route(out,note,1,out_type);
261
262 if (ch==EOF || ch=='\n') break;
263
264 tone_modifier=0;
265 }
266
267 footer_route(out,note,1,out_type);
268 }
269
parse_imelody(FILE * in,FILE * out,int out_type,struct note_t * note)270 int parse_imelody(FILE *in, FILE *out, int out_type, struct note_t *note)
271 {
272 char field_name[1024],field_value[1024];
273 int i;
274
275 note->bpm=120;
276
277 while(1)
278 {
279 i=get_field(in,field_name,field_value);
280
281 if (i==1 || i==2)
282 {
283 parse_melody(in,out,note,out_type);
284 break;
285 }
286 else
287 if (i==-1)
288 { break; }
289
290 if (strcasecmp(field_name,"name")==0)
291 {
292 strncpy(note->songname,field_value,SONGNAME_LEN);
293 note->songname[SONGNAME_LEN-1]=0;
294 }
295 else
296 if (strcasecmp(field_name,"beat")==0)
297 {
298 note->bpm=atoi(field_value);
299 if (note->bpm==0) note->bpm=120;
300 }
301 else
302 if (strcasecmp(field_name,"volume")==0)
303 {
304 note->volume=atoi(field_value);
305 if (note->volume<=0 || note->volume>15) note->volume=7;
306 }
307 else
308 if (strcasecmp(field_name,"style")==0 && strlen(field_value)==2)
309 {
310 note->style=field_value[1]-'0';
311 if (note->style<0 || note->style>2) note->style=0;
312 }
313 }
314
315 return (0);
316 }
317
318
319
320