00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "midimapper.h"
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <stdlib.h>
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033
00034 MidiMapper::MidiMapper(const char *name)
00035 {
00036 _ok=1;
00037 keymaps=NULL;
00038 _filename=NULL;
00039 mapPitchBender=0;
00040 mapExpressionToVolumeEvents=0;
00041 if ((name==NULL)||(name[0]==0))
00042 {
00043 deallocateMaps();
00044 int i;
00045 for (i=0;i<16;i++)
00046 {
00047 channelmap[i]=i;
00048 channelPatchForced[i]=-1;
00049 }
00050 for (i=0;i<128;i++) patchmap[i]=i;
00051 }
00052 else
00053 loadFile(name);
00054 }
00055
00056 MidiMapper::~MidiMapper()
00057 {
00058 if (_filename) free(_filename);
00059 deallocateMaps();
00060 }
00061
00062 void MidiMapper::deallocateMaps(void)
00063 {
00064 int i;
00065 for (i=0;i<16;i++) channelKeymap[i]=NULL;
00066 for (i=0;i<128;i++) patchKeymap[i]=NULL;
00067 Keymap *km;
00068 while (keymaps!=NULL)
00069 {
00070 km=keymaps->next;
00071 delete keymaps;
00072 keymaps=km;
00073 }
00074 }
00075
00076 void MidiMapper::getValue(char *s,char *v)
00077 {
00078 char *c=s;
00079 while ((*c!=0)&&(*c!='=')) c++;
00080 if (*c==0) v[0]=0;
00081 else
00082 {
00083 c++;
00084 while (*c!=0)
00085 {
00086 *v=*c;
00087 c++;v++;
00088 }
00089 *v=0;
00090 }
00091 }
00092
00093 void MidiMapper::removeSpaces(char *s)
00094 {
00095 char *a=s;
00096 while ((*a!=0)&&(*a==' ')) a++;
00097 if (*a==0) {*s=0;return;};
00098 while (*a!=0)
00099 {
00100 while ((*a!=0)&&(*a!=' ')&&(*a!=10)&&(*a!=13))
00101 {
00102 *s=*a;
00103 s++;
00104 a++;
00105 }
00106 while ((*a!=0)&&((*a==' ')||(*a==10)||(*a==13))) a++;
00107 *s=' ';s++;
00108 if (*a==0) {*s=0;return;};
00109 }
00110 *s=0;
00111
00112 }
00113
00114 int MidiMapper::countWords(char *s)
00115 {
00116 int c=0;
00117 while (*s!=0)
00118 {
00119 if (*s==' ') c++;
00120 s++;
00121 }
00122 return c;
00123 }
00124
00125 void MidiMapper::getWord(char *t,char *s,int w)
00126 {
00127 int i=0;
00128 *t=0;
00129 while ((*s!=0)&&(i<w))
00130 {
00131 if (*s==' ') i++;
00132 s++;
00133 }
00134 while ((*s!=0)&&(*s!=' ')&&(*s!=10)&&(*s!=13))
00135 {
00136 *t=*s;
00137 t++;s++;
00138 }
00139 *t=0;
00140 }
00141
00142
00143 void MidiMapper::loadFile(const char *name)
00144 {
00145 _ok=1;
00146 FILE *fh = fopen(name,"rt");
00147 if ( fh == NULL ) { _ok = -1; return; };
00148 char s[101];
00149 s[0] = 0;
00150 if ( _filename != NULL ) free(_filename);
00151 _filename = strdup(name);
00152 #ifdef MIDIMAPPERDEBUG
00153 printf("Loading mapper ...\n");
00154 #endif
00155 while (!feof(fh))
00156 {
00157 s[0]=0;
00158 while ((!feof(fh))&&((s[0]==0)||(s[0]=='#'))) fgets(s,100,fh);
00159 if (strncmp(s,"DEFINE",6)==0)
00160 {
00161 if (strncmp(&s[7],"PATCHMAP",8)==0) readPatchmap(fh);
00162 else
00163 if (strncmp(&s[7],"KEYMAP",6)==0) readKeymap(fh,s);
00164 else
00165 if (strncmp(&s[7],"CHANNELMAP",10)==0) readChannelmap(fh);
00166 else
00167 {
00168 printf("ERROR: Unknown DEFINE line in map file\n");
00169 _ok=0;
00170 }
00171 if (_ok==0)
00172 {
00173 printf("The midi map file will be ignored\n");
00174 fclose(fh);
00175 return;
00176 }
00177 }
00178 else if (strncmp(s,"OPTIONS",7)==0) readOptions(fh);
00179 }
00180 fclose(fh);
00181 }
00182
00183 MidiMapper::Keymap *MidiMapper::createKeymap(char *name,uchar use_same_note,uchar note)
00184 {
00185 Keymap *km=new Keymap;
00186 strncpy(km->name, name, KM_NAME_SIZE);
00187 km->name[KM_NAME_SIZE - 1] = 0;
00188
00189 int i;
00190 if (use_same_note==1)
00191 {
00192 for (i=0;i<128;i++)
00193 km->key[i]=note;
00194 }
00195 else
00196 {
00197 for (i=0;i<128;i++)
00198 km->key[i]=i;
00199 }
00200 addKeymap(km);
00201 return km;
00202 }
00203
00204 void MidiMapper::addKeymap(Keymap *newkm)
00205 {
00206 Keymap *km=keymaps;
00207 if (keymaps==NULL)
00208 {
00209 keymaps=newkm;
00210 newkm->next=NULL;
00211 return;
00212 }
00213 while (km->next!=NULL) km=km->next;
00214 km->next=newkm;
00215 newkm->next=NULL;
00216 return;
00217 }
00218
00219 MidiMapper::Keymap *MidiMapper::keymap(char *n)
00220 {
00221 Keymap *km=keymaps;
00222 while ((km!=NULL)&&(strcmp(km->name,n)!=0)) km=km->next;
00223 return km;
00224 }
00225
00226 void MidiMapper::readOptions(FILE *fh)
00227 {
00228 #ifdef MIDIMAPPERDEBUG
00229 printf("Loading Options ... \n");
00230 #endif
00231 char s[101];
00232 char v[101];
00233 char t[101];
00234 int fin=0;
00235 mapPitchBender=0;
00236 while (!fin)
00237 {
00238 s[0]=0;
00239 while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh);
00240 if (strncmp(s,"PitchBenderRatio",16)==0)
00241 {
00242 getValue(s,v);
00243 removeSpaces(v);
00244 getWord(t,v,0);
00245 mapPitchBender=1;
00246 pitchBenderRatio=atoi(t);
00247 }
00248 else if (strncmp(s,"MapExpressionToVolumeEvents",27)==0) mapExpressionToVolumeEvents=1;
00249 else if (strncmp(s,"END",3)==0)
00250 {
00251 fin=1;
00252 }
00253 else
00254 {
00255 printf("ERROR: Invalid option in OPTIONS section of map file : (%s)\n",s);
00256 _ok=0;
00257 return;
00258 }
00259 }
00260 }
00261
00262 void MidiMapper::readPatchmap(FILE *fh)
00263 {
00264 char s[101];
00265 char v[101];
00266 char t[101];
00267 char name[256];
00268 int i=0;
00269 int j,w;
00270 #ifdef MIDIMAPPERDEBUG
00271 printf("Loading Patch map ... \n");
00272 #endif
00273 while (i<128)
00274 {
00275 s[0]=0;
00276 while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh);
00277 getValue(s,v);
00278 removeSpaces(v);
00279 w=countWords(v);
00280 j=0;
00281 patchKeymap[i]=NULL;
00282 patchmap[i]=i;
00283 while (j<w)
00284 {
00285 getWord(t,v,j);
00286 if (strcmp(t,"AllKeysTo")==0)
00287 {
00288 j++;
00289 if (j>=w)
00290 {
00291 printf("ERROR: Invalid option in PATCHMAP section of map file\n");
00292 _ok=0;
00293 return;
00294 }
00295 getWord(t,v,j);
00296 sprintf(name,"AllKeysTo%s",t);
00297 patchKeymap[i]=createKeymap(name,1,atoi(t));
00298 }
00299 else
00300 {
00301 patchmap[i]=atoi(t);
00302 }
00303 j++;
00304 }
00305 i++;
00306 }
00307 s[0]=0;
00308 while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh);
00309 if (strncmp(s,"END",3)!=0)
00310 {
00311 printf("ERROR: End of section not found in map file\n");
00312 _ok=0;
00313 return;
00314 }
00315 }
00316
00317 void MidiMapper::readKeymap(FILE *fh,char *first_line)
00318 {
00319 char s[101];
00320 char v[101];
00321 #ifdef MIDIMAPPERDEBUG
00322 printf("Loading Key map ... %s",first_line);
00323 #endif
00324 removeSpaces(first_line);
00325 getWord(v,first_line,2);
00326 Keymap *km=new Keymap;
00327 strncpy(km->name, v, KM_NAME_SIZE);
00328 km->name[KM_NAME_SIZE - 1] = 0;
00329
00330 int i=0;
00331 while (i<128)
00332 {
00333 s[0]=0;
00334 while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh);
00335 getValue(s,v);
00336 removeSpaces(v);
00337 km->key[i]=atoi(v);
00338 i++;
00339 }
00340 s[0]=0;
00341 while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh);
00342 if (strncmp(s,"END",3)!=0)
00343 {
00344 printf("ERROR: End of section not found in map file\n");
00345 _ok=0;
00346 return;
00347 }
00348 addKeymap(km);
00349 }
00350
00351 void MidiMapper::readChannelmap(FILE *fh)
00352 {
00353 char s[101];
00354 char v[101];
00355 char t[101];
00356 int i=0;
00357 int w,j;
00358 #ifdef MIDIMAPPERDEBUG
00359 printf("Loading Channel map ... \n");
00360 #endif
00361 while (i<16)
00362 {
00363 s[0]=0;
00364 while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh);
00365 getValue(s,v);
00366 removeSpaces(v);
00367 w=countWords(v);
00368 j=0;
00369 channelKeymap[i]=NULL;
00370 channelPatchForced[i]=-1;
00371 channelmap[i]=i;
00372 while (j<w)
00373 {
00374 getWord(t,v,j);
00375 if (strcmp(t,"Keymap")==0)
00376 {
00377 j++;
00378 if (j>=w)
00379 {
00380 printf("ERROR: Invalid option in CHANNELMAP section of map file\n");
00381 _ok=0;
00382 return;
00383 }
00384 getWord(t,v,j);
00385 channelKeymap[i]=keymap(t);
00386 }
00387 else if (strcmp(t,"ForcePatch")==0)
00388 {
00389 j++;
00390 if (j>=w)
00391 {
00392 printf("ERROR: Invalid option in CHANNELMAP section of map file\n");
00393 _ok=0;
00394 return;
00395 }
00396 getWord(t,v,j);
00397 channelPatchForced[i]=atoi(t);
00398 }
00399 else
00400 {
00401 channelmap[i]=atoi(t);
00402 }
00403 j++;
00404 }
00405 i++;
00406 }
00407 s[0]=0;
00408 while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh);
00409 if (strncmp(s,"END",3)!=0)
00410 {
00411 printf("END of section not found in map file\n");
00412 _ok=0;
00413 return;
00414 }
00415
00416 }
00417
00418 const char *MidiMapper::filename(void)
00419 {
00420 return (_filename)? _filename : "";
00421 }
00422
00423 uchar MidiMapper::key(uchar chn,uchar pgm, uchar note)
00424 {
00425 uchar notemapped=note;
00426 if (patchKeymap[pgm]!=NULL) notemapped=patchKeymap[pgm]->key[note];
00427 if (channelKeymap[chn]!=NULL) notemapped=channelKeymap[chn]->key[note];
00428 return notemapped;
00429 }
00430
00431 uchar MidiMapper::patch(uchar chn,uchar pgm)
00432 {
00433 return (channelPatchForced[chn] == -1) ?
00434 patchmap[pgm] : (uchar)channelPatchForced[chn] ;
00435 }
00436
00437 void MidiMapper::pitchBender(uchar ,uchar &lsb,uchar &msb)
00438 {
00439 if (mapPitchBender)
00440 {
00441 short pbs=((short)msb<<7) | (lsb & 0x7F);
00442 pbs=pbs-0x2000;
00443 short pbs2=(((long)pbs*pitchBenderRatio)/4096);
00444 #ifdef MIDIMAPPERDEBUG
00445 printf("Pitch Bender (%d): %d -> %d \n",chn,pbs,pbs2);
00446 #endif
00447 pbs2=pbs2+0x2000;
00448 lsb=pbs2 & 0x7F;
00449 msb=(pbs2 >> 7)&0x7F;
00450 }
00451 }
00452
00453 void MidiMapper::controller(uchar ,uchar &ctl, uchar &)
00454 {
00455 if ((mapExpressionToVolumeEvents)&&(ctl==11)) ctl=7;
00456 }