32 #include <sys/ioctl.h>
35 #include <sys/param.h>
57 vm =
new VoiceManager (nvoices);
64 if (deleteFMPatchesDirectory)
66 free((
char *)FMPatchesDirectory);
67 deleteFMPatchesDirectory = 0;
68 FMPatchesDirectory=
"/etc";
74 #ifdef HAVE_OSS_SUPPORT
80 printfdebug(
"ERROR: Could not open /dev/sequencer\n");
99 #ifdef HAVE_OSS_SUPPORT
102 uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7};
103 sysex(gm_reset,
sizeof(gm_reset));
104 for (chn=0;chn<16;chn++)
116 if (opl==3) ioctl(seqfd, SNDCTL_FM_4OP_ENABLE, &device);
117 SEQ_VOLUME_MODE(device,VOL_METHOD_LINEAR);
119 for (
int i = 0; i < nvoices; i++)
121 SEQ_CONTROL(device, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
122 SEQ_STOP_NOTE(device, i, vm->note(i), 64);
127 void FMOut::loadFMPatches(
void)
129 #ifdef HAVE_OSS_SUPPORT
130 char patchesfile[strlen(FMPatchesDirectory)+7+1];
131 char drumsfile[strlen(FMPatchesDirectory)+9+1];
133 struct sbi_instrument instr;
136 for ( i=0; i<256; i++ )
138 int stereoeffect=rand()%3;
144 snprintf(patchesfile,
sizeof(patchesfile),
"%s/std.o3",FMPatchesDirectory);
149 snprintf(patchesfile,
sizeof(patchesfile),
"%s/std.sb",FMPatchesDirectory);
152 fh=fopen(patchesfile,
"rb");
153 if (fh==NULL)
return;
157 fread(tmp,size,1,fh);
159 instr.key = ((strncmp(tmp,
"4OP", 3) == 0))? OPL3_PATCH : FM_PATCH;
160 datasize = (strncmp(tmp,
"4OP", 3) == 0)? 22 : 11;
164 tmp[46] = (tmp[46] & 0xcf) | ((++stereoeffect)<<4);
165 stereoeffect=stereoeffect%3;
167 instr.operators[j] = tmp[j+36];
168 SEQ_WRPATCH(&instr,
sizeof(instr));
174 snprintf(drumsfile,
sizeof(drumsfile),
"%s/drums.o3",FMPatchesDirectory);
178 snprintf(drumsfile,
sizeof(drumsfile),
"%s/drums.sb",FMPatchesDirectory);
181 fh=fopen(drumsfile,
"rb");
182 if (fh==NULL)
return;
184 for (i=128;i<175;i++)
186 fread(tmp,size,1,fh);
188 instr.key = (strncmp(tmp,
"4OP", 3) == 0)? OPL3_PATCH : FM_PATCH;
189 datasize = (strncmp(tmp,
"4OP", 3) == 0)? 22 : 11;
193 tmp[46] = (tmp[46] & 0xcf) | ((++stereoeffect)<<4);
194 stereoeffect=stereoeffect%3;
196 instr.operators[j] = tmp[j+36];
197 SEQ_WRPATCH(&instr,
sizeof(instr));
202 printfdebug(
"Patches loaded\n");
209 if (patchloaded[p]==1)
return p;
211 printfdebug(
"Not loaded %d!\n",p);
214 while ((p<256)&&(patchloaded[p]==0)) p++;
226 if (chn==PERCUSSION_CHANNEL)
228 if (patchloaded[note+128]==0)
return;
230 if (patchloaded[chnpatch[chn]]==0)
return;
232 int v=vm->allocateVoice(chn,note);
234 if (chn==PERCUSSION_CHANNEL)
235 SEQ_SET_PATCH(device,v ,p=
patch(note+128))
237 SEQ_SET_PATCH(device,v ,p=map->
patch(chn,chnpatch[chn]));
238 SEQ_BENDER(device, v, chnbender[chn]);
240 SEQ_START_NOTE(device, v, note, vel);
243 SEQ_CHN_PRESSURE(device, v , chnpressure[chn]);
247 printfdebug(
"Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
255 while ((i=vm->search(chn,note))!=-1)
257 SEQ_STOP_NOTE(device, i, note, vel);
258 vm->deallocateVoice(i);
262 printfdebug(
"Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
270 while ((i=vm->search(chn,note))!=-1)
271 SEQ_KEY_PRESSURE(device, i, note,vel);
276 if (chn==PERCUSSION_CHANNEL)
return;
279 while ((i=vm->search(chn))!=-1)
280 SEQ_SET_PATCH(device,i,map->
patch(chn,
patch));
289 while ((i=vm->search(chn))!=-1)
290 SEQ_CHN_PRESSURE(device, i , vel);
292 chnpressure[chn]=vel;
297 chnbender[chn]=((int)msb<<7) | (lsb & 0x7F);
301 while ((i=vm->search(chn))!=-1)
302 SEQ_BENDER(device, i, chnbender[chn]);
308 if ((ctl==11)||(ctl==7))
310 v=(v*volumepercentage)/100;
315 while ((i=vm->search(chn))!=-1)
316 SEQ_CONTROL(device, i, ctl, v);
318 chncontroller[chn][ctl]=v;
328 if ((dir==NULL)||(dir[0]==0))
return;
329 if (deleteFMPatchesDirectory)
330 free((
char *)FMPatchesDirectory);
332 FMPatchesDirectory = strdup(dir);
334 deleteFMPatchesDirectory=1;
339 #ifdef HAVE_OSS_SUPPORT
340 int fd=open(
"/dev/mixer0",O_RDWR,0);
345 if (ioctl(fd,MIXER_WRITE(SOUND_MIXER_SYNTH),&a) == -1)
346 printfdebug(
"ERROR writing to mixer\n");
353 const char *FMOut::FMPatchesDirectory =
"/etc";
354 int FMOut::deleteFMPatchesDirectory = 0;
static void setFMPatchesDirectory(const char *dir)
Sets the directory where the FM patches are stored, that is, where the std.o3, std....
virtual void initDev(void)
See MidiOut::initDev()
int patch(int p)
Returns p if the patch p has been loaded, or another patch (already loaded) if p hasn't been loaded.
virtual void chnPatchChange(uchar chn, uchar patch)
See MidiOut::chnPatchChange()
virtual void keyPressure(uchar chn, uchar note, uchar vel)
See MidiOut::keyPressure()
virtual void openDev(int sqfd)
See MidiOut::openDev()
FMOut(int d=0, int total=12)
Constructor.
virtual void noteOff(uchar chn, uchar note, uchar vel)
See MidiOut::noteOff()
virtual void sysex(uchar *data, ulong size)
It's an empty function, as FM devices don't support System Exclusive messages.
virtual void noteOn(uchar chn, uchar note, uchar vel)
See MidiOut::noteOn()
virtual void setVolumePercentage(int i)
See MidiOut::setVolumePercentage()
virtual void closeDev(void)
See MidiOut::closeDev()
virtual void chnPitchBender(uchar chn, uchar lsb, uchar msb)
See MidiOut::chnPitchBender()
virtual void chnPressure(uchar chn, uchar vel)
See MidiOut::chnPressure()
virtual void chnController(uchar chn, uchar ctl, uchar v)
See MidiOut::chnController()
uchar patch(uchar chn, uchar pgm)
Returns the patch which pgm used on channel chn should be mapped to.
int ok(void)
Returns true if everything's ok and false if there has been any problem.