/************************************************************************** midimapper.cpp - The midi mapper object This file is part of LibKMid 0.9.5 Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Send comments and bug fixes to Antonio Larrosa ***************************************************************************/ #include "midimapper.h" #include #include #include #ifdef HAVE_CONFIG_H #include #endif MidiMapper::MidiMapper(const char *name) { _ok=1; keymaps=NULL; _filename=NULL; mapPitchBender=0; mapExpressionToVolumeEvents=0; if ((name==NULL)||(name[0]==0)) { deallocateMaps(); int i; for (i=0;i<16;i++) { channelmap[i]=i; channelPatchForced[i]=-1; } for (i=0;i<128;i++) patchmap[i]=i; } else loadFile(name); } MidiMapper::~MidiMapper() { if (_filename) free(_filename); deallocateMaps(); } void MidiMapper::deallocateMaps(void) { int i; for (i=0;i<16;i++) channelKeymap[i]=NULL; for (i=0;i<128;i++) patchKeymap[i]=NULL; Keymap *km; while (keymaps!=NULL) { km=keymaps->next; delete keymaps; keymaps=km; } } void MidiMapper::getValue(char *s,char *v) { char *c=s; while ((*c!=0)&&(*c!='=')) c++; if (*c==0) v[0]=0; else { c++; while (*c!=0) { *v=*c; c++;v++; } *v=0; } } void MidiMapper::removeSpaces(char *s) { char *a=s; while ((*a!=0)&&(*a==' ')) a++; if (*a==0) {*s=0;return;}; while (*a!=0) { while ((*a!=0)&&(*a!=' ')&&(*a!=10)&&(*a!=13)) { *s=*a; s++; a++; } while ((*a!=0)&&((*a==' ')||(*a==10)||(*a==13))) a++; *s=' ';s++; if (*a==0) {*s=0;return;}; } *s=0; } int MidiMapper::countWords(char *s) { int c=0; while (*s!=0) { if (*s==' ') c++; s++; } return c; } void MidiMapper::getWord(char *t,char *s,int w) { int i=0; *t=0; while ((*s!=0)&&(iname, name, KM_NAME_SIZE); km->name[KM_NAME_SIZE - 1] = 0; int i; if (use_same_note==1) { for (i=0;i<128;i++) km->key[i]=note; } else { for (i=0;i<128;i++) km->key[i]=i; } addKeymap(km); return km; } void MidiMapper::addKeymap(Keymap *newkm) { Keymap *km=keymaps; if (keymaps==NULL) { keymaps=newkm; newkm->next=NULL; return; } while (km->next!=NULL) km=km->next; km->next=newkm; newkm->next=NULL; return; } MidiMapper::Keymap *MidiMapper::keymap(char *n) { Keymap *km=keymaps; while ((km!=NULL)&&(strcmp(km->name,n)!=0)) km=km->next; return km; } void MidiMapper::readOptions(FILE *fh) { #ifdef MIDIMAPPERDEBUG printf("Loading Options ... \n"); #endif char s[101]; char v[101]; char t[101]; int fin=0; mapPitchBender=0; while (!fin) { s[0]=0; while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); if (strncmp(s,"PitchBenderRatio",16)==0) { getValue(s,v); removeSpaces(v); getWord(t,v,0); mapPitchBender=1; pitchBenderRatio=atoi(t); } else if (strncmp(s,"MapExpressionToVolumeEvents",27)==0) mapExpressionToVolumeEvents=1; else if (strncmp(s,"END",3)==0) { fin=1; } else { printf("ERROR: Invalid option in OPTIONS section of map file : (%s)\n",s); _ok=0; return; } } } void MidiMapper::readPatchmap(FILE *fh) { char s[101]; char v[101]; char t[101]; char name[256]; /* Longer than t and 'AllKeysTo' */ int i=0; int j,w; #ifdef MIDIMAPPERDEBUG printf("Loading Patch map ... \n"); #endif while (i<128) { s[0]=0; while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); getValue(s,v); removeSpaces(v); w=countWords(v); j=0; patchKeymap[i]=NULL; patchmap[i]=i; while (j=w) { printf("ERROR: Invalid option in PATCHMAP section of map file\n"); _ok=0; return; } getWord(t,v,j); sprintf(name,"AllKeysTo%s",t); patchKeymap[i]=createKeymap(name,1,atoi(t)); } else { patchmap[i]=atoi(t); } j++; } i++; } s[0]=0; while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); if (strncmp(s,"END",3)!=0) { printf("ERROR: End of section not found in map file\n"); _ok=0; return; } } void MidiMapper::readKeymap(FILE *fh,char *first_line) { char s[101]; char v[101]; #ifdef MIDIMAPPERDEBUG printf("Loading Key map ... %s",first_line); #endif removeSpaces(first_line); getWord(v,first_line,2); Keymap *km=new Keymap; strncpy(km->name, v, KM_NAME_SIZE); km->name[KM_NAME_SIZE - 1] = 0; int i=0; while (i<128) { s[0]=0; while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); getValue(s,v); removeSpaces(v); km->key[i]=atoi(v); i++; } s[0]=0; while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); if (strncmp(s,"END",3)!=0) { printf("ERROR: End of section not found in map file\n"); _ok=0; return; } addKeymap(km); } void MidiMapper::readChannelmap(FILE *fh) { char s[101]; char v[101]; char t[101]; int i=0; int w,j; #ifdef MIDIMAPPERDEBUG printf("Loading Channel map ... \n"); #endif while (i<16) { s[0]=0; while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); getValue(s,v); removeSpaces(v); w=countWords(v); j=0; channelKeymap[i]=NULL; channelPatchForced[i]=-1; channelmap[i]=i; while (j=w) { printf("ERROR: Invalid option in CHANNELMAP section of map file\n"); _ok=0; return; } getWord(t,v,j); channelKeymap[i]=keymap(t); } else if (strcmp(t,"ForcePatch")==0) { j++; if (j>=w) { printf("ERROR: Invalid option in CHANNELMAP section of map file\n"); _ok=0; return; } getWord(t,v,j); channelPatchForced[i]=atoi(t); } else { channelmap[i]=atoi(t); } j++; } i++; } s[0]=0; while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); if (strncmp(s,"END",3)!=0) { printf("END of section not found in map file\n"); _ok=0; return; } } const char *MidiMapper::filename(void) { return (_filename)? _filename : ""; } uchar MidiMapper::key(uchar chn,uchar pgm, uchar note) { uchar notemapped=note; if (patchKeymap[pgm]!=NULL) notemapped=patchKeymap[pgm]->key[note]; if (channelKeymap[chn]!=NULL) notemapped=channelKeymap[chn]->key[note]; return notemapped; } uchar MidiMapper::patch(uchar chn,uchar pgm) { return (channelPatchForced[chn] == -1) ? patchmap[pgm] : (uchar)channelPatchForced[chn] ; } void MidiMapper::pitchBender(uchar ,uchar &lsb,uchar &msb) { if (mapPitchBender) { short pbs=((short)msb<<7) | (lsb & 0x7F); pbs=pbs-0x2000; short pbs2=(((long)pbs*pitchBenderRatio)/4096); #ifdef MIDIMAPPERDEBUG printf("Pitch Bender (%d): %d -> %d \n",chn,pbs,pbs2); #endif pbs2=pbs2+0x2000; lsb=pbs2 & 0x7F; msb=(pbs2 >> 7)&0x7F; } } void MidiMapper::controller(uchar ,uchar &ctl, uchar &) { if ((mapExpressionToVolumeEvents)&&(ctl==11)) ctl=7; }