1
2 /*
3 * Diverse Bristol midi routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 /*
23 * This will take a character filename and a float mapping, attempt to find the
24 * specified file with a few different names/locations and then parse the
25 * contents into the float array. The end result is a set of frequency tables
26 * that can be converted separately into the midi frequency map.
27 *
28 * Bounds checking is done to limit the float map to 128 entries.
29 *
30 * We need to look for the full path name, then look for the filename in
31 * our profiles directory, then look for the <filename>.scl in the same
32 * profiles directory.
33 *
34 * The midihandlers.c code will parse emulation mappings and uses midiFileMgt.c
35 * code here in the library.
36
37 ! meanquar.scl
38 !
39 1/4-comma meantone scale. Pietro Aaron's temperament (1523)
40 12
41 !
42 76.04900
43 193.15686
44 310.26471
45 5/4
46 503.42157
47 579.47057
48 696.57843
49 25/16
50 889.73529
51 1006.84314
52 1082.89214
53 2/1
54
55 */
56
57 #include <string.h>
58 #include <stdio.h>
59 #include <ctype.h>
60
61 #include "bristolmidi.h"
62
63 #define BUFSIZE 256
64
65 static float
getScalaFreq(char * line)66 getScalaFreq(char *line)
67 {
68 float freq;
69 char *denominator;
70
71 /* See if we have a fraction */
72 if ((denominator = index(line, '/')) != NULL)
73 {
74 freq = (atoi(line));
75 return(freq / atoi(++denominator));
76 }
77
78 /* See if we have a decimal and treat it then as cents */
79 if (index(line, '.') != NULL)
80 return(1.0 + atof(line) / 1200);
81
82 /* Assume we have a raw number */
83 return(atoi(line));
84 }
85
86 static char *
spanWhiteSpace(char * line)87 spanWhiteSpace(char *line)
88 {
89 int i = 0;
90
91 while (isspace(line[i]))
92 i++;
93
94 return(&line[i]);
95 }
96
97 static int
scalaParse(FILE * fd,float * freq)98 scalaParse(FILE *fd, float *freq)
99 {
100 char line[BUFSIZE];
101 char *scan;
102 int lineid = 0; /* To decide what to parse */
103 int freqindex = 0, count = 0;
104
105 while ((fgets(line, BUFSIZE, fd)) != 0)
106 {
107 if (line[0] == '!')
108 continue;
109
110 switch (lineid++)
111 {
112 case 0:
113 printf("Scale info: %s", line);
114 lineid = 1;
115 break;
116 case 1:
117 scan = spanWhiteSpace(line);
118 if ((count = atoi(scan)) < 0)
119 return(-1);
120 if (count > 128)
121 {
122 printf("Scala: cannot converge %i notes\n", count);
123 return(-2);
124 }
125 lineid = 2;
126 break;
127 default:
128 /* The rest should be frequencies */
129 scan = spanWhiteSpace(line);
130 if ((freq[freqindex] = getScalaFreq(scan)) <= 0)
131 continue;
132 freqindex++;
133 break;
134 }
135 }
136
137 return(freqindex);
138 }
139
140 int
bristolParseScala(char * file,float * freq)141 bristolParseScala(char *file, float *freq)
142 {
143 FILE *fd;
144 char *cache;
145 int ncount;
146
147 if ((cache = getBristolCache(file)) == NULL)
148 {
149 printf("Could not resolve cache\n");
150 return(-10);
151 }
152
153 if (file[0] == '/')
154 {
155 if ((fd = fopen(file, "r")) == (FILE *) NULL)
156 {
157 printf("Could not find scala file\n");
158 return(-1);
159 }
160 } else {
161 char filename[1024];
162
163 if (strlen(file) > 200)
164 {
165 printf("Will not open stupidly named file: %s\n", file);
166 return(-2);
167 }
168
169 /*
170 * First look for the complete filename:
171 */
172 sprintf(filename, "%s/memory/profiles/%s", cache, file);
173
174 if ((fd = fopen(filename, "r")) == (FILE *) NULL)
175 {
176 sprintf(filename, "%s/memory/profiles/%s.scl", cache, file);
177
178 if ((fd = fopen(filename, "r")) == (FILE *) NULL)
179 {
180 printf("Could not open named scala file %s\n", filename);
181 return(-3);
182 }
183 }
184 }
185
186 if ((ncount = scalaParse(fd, freq)) < 0)
187 {
188 printf("Could not parse named scala file %s\n", file);
189 fclose(fd);
190 return(-4);
191 }
192
193 fclose(fd);
194
195 printf("Converged %i notes from scala file %s\n", ncount, file);
196
197 return(ncount);
198 }
199
200