30 #include "gusvoices.h"
35 #include <sys/ioctl.h>
38 #include <sys/param.h>
46 #ifdef HAVE_OSS_SUPPORT
52 unsigned char instruments;
55 unsigned short nr_waveforms;
56 unsigned short master_volume;
57 unsigned long data_size;
62 unsigned char fractions;
66 unsigned short base_freq;
71 unsigned char panning;
73 unsigned char envelope_rate[6];
74 unsigned char envelope_offset[6];
76 unsigned char tremolo_sweep;
77 unsigned char tremolo_rate;
78 unsigned char tremolo_depth;
80 unsigned char vibrato_sweep;
81 unsigned char vibrato_rate;
82 unsigned char vibrato_depth;
86 short scale_frequency;
87 unsigned short scale_factor;
90 int get_dint(
unsigned char *p)
101 unsigned short get_word(
unsigned char *p)
105 for (
int i=0;i<2;i++)
106 v |= (*p++ << (i*8));
121 vm=
new VoiceManager(nvoices);
129 if (delete_GUS_patches_directory)
131 free((
char *)GUS_patches_directory);
132 delete_GUS_patches_directory = 0;
133 GUS_patches_directory=
"/etc";
144 printfdebug(
"ERROR: Could not open /dev/sequencer\n");
148 #ifdef HAVE_OSS_SUPPORT
154 if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &device)==-1)
156 printfdebug(
"Error reseting gus samples. Please report\n");
159 totalmemory = device;
160 ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &totalmemory);
162 ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &freememory);
180 #ifdef HAVE_OSS_SUPPORT
183 uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7};
184 sysex(gm_reset,
sizeof(gm_reset));
185 for (chn=0;chn<16;chn++)
198 for (
int i = 0; i < nvoices; i++)
200 SEQ_CONTROL(device, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
201 SEQ_STOP_NOTE(device, i, vm->note(i), 64);
210 if (patchloaded[p]==1)
return p;
211 printfdebug(
"Not loaded %d!\n",p);
213 while ((p<256)&&(patchloaded[p]==0)) p++;
225 if (chn==PERCUSSION_CHANNEL)
227 if (patchloaded[note+128]==0)
return;
229 if (patchloaded[chnpatch[chn]]==0)
return;
231 int v=vm->allocateVoice(chn,note);
233 if (chn==PERCUSSION_CHANNEL)
234 SEQ_SET_PATCH(device,v ,p=
patch(note+128))
236 SEQ_SET_PATCH(device,v ,p=map->
patch(chn,chnpatch[chn]));
237 SEQ_BENDER(device, v, chnbender[chn]);
239 SEQ_START_NOTE(device, v, note, vel);
241 SEQ_CHN_PRESSURE(device, v , chnpressure[chn]);
244 printfdebug(
"Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
251 while ((i=vm->search(chn,note))!=-1)
253 SEQ_STOP_NOTE(device, i, note, vel);
254 vm->deallocateVoice(i);
258 printf(
"Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
266 while ((i=vm->search(chn,note))!=-1)
267 SEQ_KEY_PRESSURE(device, i, note,vel);
272 if (chn==PERCUSSION_CHANNEL)
return;
275 while ((i=vm->search(chn))!=-1)
276 SEQ_SET_PATCH(device,i,map->
patch(chn,
patch));
293 chnbender[chn]=((int)msb<<7) | (lsb & 0x7F);
297 while ((i=vm->search(chn))!=-1)
298 SEQ_BENDER(device, i, chnbender[chn]);
303 if ((ctl==11)||(ctl==7))
305 v=(v*volumepercentage)/100;
311 while ((i=vm->search(chn))!=-1)
312 SEQ_CONTROL(device, i, ctl, v);
314 chncontroller[chn][ctl]=v;
324 if ((dir==NULL)||(dir[0]==0))
return;
325 if (delete_GUS_patches_directory)
326 free((
char *)GUS_patches_directory);
328 GUS_patches_directory = strdup(dir);
329 delete_GUS_patches_directory=1;
332 const char *GUSOut::patchName(
int pgm)
334 return GUS_voice_names[pgm];
340 #ifdef HAVE_OSS_SUPPORT
341 struct pat_header header;
342 struct sample_header sample;
343 if (patchloaded[pgm]==1)
346 printf(
"Trying to reload a patch. This should never happen, please report.\n");
350 if ((patchName(pgm)==NULL)||((patchName(pgm))[0]==0))
353 printf(
"Couldn't guess patch name for patch number %d\n",pgm);
357 char *s=
new char[strlen(GUS_patches_directory)+strlen(patchName(pgm))+10];
358 if (s==NULL)
return -1;
359 sprintf(s,
"%s/%s.pat",GUS_patches_directory,patchName(pgm));
361 printf(
"Loading patch : %s\n",s);
363 struct patch_info *
patch=NULL;
365 if (stat(s, &info)==-1)
368 printf(
"File %s doesn't exist\n",s);
373 FILE *fh=fopen(s,
"rb");
377 printf(
"Couldn't open patch %s\n",s);
382 unsigned char tmp[256];
383 if (fread(tmp,1,0xef,fh)!=0xef)
387 printf(
"Short file ! \n");
391 memcpy ((
char *) &header, tmp,
sizeof (header));
393 if (strncmp(header.magic,
"GF1PATCH110",12)!=0)
396 printf(
"File %s is corrupted or it isn't a patch file\n",s);
400 if (strncmp(header.version,
"ID#000002",10)!=0)
403 printf(
"File %s's version is not supported\n",s);
407 unsigned short nWaves= *(
unsigned short *)&tmp[85];
409 unsigned short masterVolume= *(
unsigned short *)&tmp[87];
410 printf(
"nWaves: %d\n",nWaves);
411 printf(
"masterVolume : %d\n",masterVolume);
416 for (i=0;i<nWaves;i++)
418 fseek(fh,offset,SEEK_SET);
420 if (fread(tmp,1,
sizeof(sample),fh) !=
sizeof(sample))
424 printf(
"Short file\n");
428 memcpy ((
char *) &sample, tmp,
sizeof (sample));
429 sample.fractions = (char)tmp[7];
430 sample.len = get_dint(&tmp[8]);
431 sample.loop_start = get_dint(&tmp[12]);
432 sample.loop_end = get_dint(&tmp[16]);
433 sample.base_freq = get_word(&tmp[20]);
434 sample.low_note = get_dint(&tmp[22]);
435 sample.high_note = get_dint(&tmp[26]);
436 sample.base_note = get_dint(&tmp[30]);
437 sample.detune = (short)get_word(&tmp[34]);
438 sample.panning = (
unsigned char) tmp[36];
440 memcpy (sample.envelope_rate, &tmp[37], 6);
441 memcpy (sample.envelope_offset, &tmp[43], 6);
443 sample.tremolo_sweep = (
unsigned char) tmp[49];
444 sample.tremolo_rate = (
unsigned char) tmp[50];
445 sample.tremolo_depth = (
unsigned char) tmp[51];
447 sample.vibrato_sweep = (
unsigned char) tmp[52];
448 sample.vibrato_rate = (
unsigned char) tmp[53];
449 sample.vibrato_depth = (
unsigned char) tmp[54];
450 sample.modes = (
unsigned char) tmp[55];
451 sample.scale_frequency = (short)get_word(&tmp[56]);
452 sample.scale_factor = get_word(&tmp[58]);
454 offset = offset + 96;
456 patch = (
struct patch_info *) malloc(
sizeof (*
patch) + sample.len);
460 printf(
"Not enough memory\n");
464 patch->key = GUS_PATCH;
465 patch->device_no = device;
466 patch->instr_no = pgm;
467 patch->mode = sample.modes | WAVE_TREMOLO | WAVE_VIBRATO | WAVE_SCALE;
468 patch->len = sample.len;
469 patch->loop_start = sample.loop_start;
470 patch->loop_end = sample.loop_end;
471 patch->base_note = sample.base_note;
472 patch->high_note = sample.high_note;
473 patch->low_note = sample.low_note;
474 patch->base_freq = sample.base_freq;
475 patch->detuning = sample.detune;
476 patch->panning = (sample.panning - 7) * 16;
478 memcpy (
patch->env_rate, sample.envelope_rate, 6);
479 memcpy (
patch->env_offset, sample.envelope_offset, 6);
481 patch->tremolo_sweep = sample.tremolo_sweep;
482 patch->tremolo_rate = sample.tremolo_rate;
483 patch->tremolo_depth = sample.tremolo_depth;
485 patch->vibrato_sweep = sample.vibrato_sweep;
486 patch->vibrato_rate = sample.vibrato_rate;
487 patch->vibrato_depth = sample.vibrato_depth;
489 patch->scale_frequency = sample.scale_frequency;
490 patch->scale_factor = sample.scale_factor;
492 patch->volume = header.master_volume;
494 if (fseek (fh, offset, 0) == -1)
500 if ((
long)fread (
patch->data, 1,sample.len,fh) != sample.len)
503 printf (
"Short file\n");
508 SEQ_WRPATCH (
patch,
sizeof (*
patch) + sample.len);
510 offset = offset + sample.len;
519 ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &freememory);
527 #ifdef HAVE_OSS_SUPPORT
529 for (k=0;k<256;k++) patchloaded[k]=0;
531 int patchesordered[256];
535 patchesLoadingOrder(patchesused,patchesordered);
540 printf(
"Patches used : \n");
543 if (patchesused[k]!=-1) printf(
"%d,",patchesused[k]);
545 printf(
"\n Patches used, sorted :\n");
548 if (patchesordered[k]!=-1) printf(
"%d,",patchesordered[k]);
553 while (patchesordered[i]!=-1)
556 printf(
"Load Patch : %d\n",patchesordered[i]);
564 int compare_decreasing(
const void *a,
const void *b)
571 instr_gm *ai=(instr_gm *)a;
572 instr_gm *bi=(instr_gm *)b;
573 return ai->used<bi->used;
577 void GUSOut::patchesLoadingOrder(
int *patchesused,
int *patchesordered)
585 instr_gm tempmelody[128];
586 instr_gm tempdrums[128];
588 for (i=0,j=128;i<128;i++,j++)
590 tempmelody[i].used=patchesused[i];
592 tempdrums[i].used=patchesused[j];
596 qsort(&tempmelody[0],128,
sizeof(instr_gm),compare_decreasing);
597 qsort(&tempdrums[0],128,
sizeof(instr_gm),compare_decreasing);
607 for (
int k=0;k<128;k++)
609 printf(
"%d - %d\n",tempmelody[k].used,tempmelody[k].pgm);
611 for (
int k=0;k<128;k++)
613 printf(
"%d : %d\n",tempdrums[k].used,tempdrums[k].pgm);
619 while ((i<128)&&(tempmelody[i].used!=0))
626 while ((i<128)&&(tempdrums[i].used!=0))
632 printf(
"Totalmelody : %d,totaldrums : %d\n",totalmelody,totaldrums);
640 if ((tm!=0)&&(td!=0))
642 patchesordered[0]=tempmelody[0].pgm;
643 patchesordered[1]=tempdrums[0].pgm;
647 while ((tm>0)&&(td>0))
651 patchesordered[tgt]=tempdrums[cd].pgm;
657 patchesordered[tgt]=tempmelody[cm].pgm;
666 patchesordered[tgt]=tempmelody[cm].pgm;
673 patchesordered[tgt]=tempdrums[cd].pgm;
682 patchesordered[tgt]=-1;
688 const char *GUSOut::GUS_patches_directory=
"/usr/share/ultrasnd";
690 int GUSOut::delete_GUS_patches_directory = 0;
virtual void openDev(int sqfd)
See MidiOut::openDev()
virtual void noteOff(uchar chn, uchar note, uchar vel)
See MidiOut::noteOff()
static void setGUSPatchesDirectory(const char *dir)
Sets the directory where the GUS patches are stored, that is, where the acpiano.pat,...
virtual void noteOn(uchar chn, uchar note, uchar vel)
See MidiOut::noteOn()
virtual void chnController(uchar chn, uchar ctl, uchar v)
See MidiOut::chnController()
virtual void keyPressure(uchar chn, uchar note, uchar vel)
See MidiOut::keyPressure()
int patch(int p)
Returns p if the patch with number p has been correctly loaded.
int loadPatch(int pgm)
Loads a single patch on the synthesizer memory.
virtual void chnPressure(uchar chn, uchar vel)
See MidiOut::chnPressure()
virtual void initDev(void)
See MidiOut::initDev()
void setPatchesToUse(int *patchesused)
See DeviceManager::setPatchesToUse() .
virtual void closeDev(void)
See MidiOut::closeDev()
virtual void chnPatchChange(uchar chn, uchar patch)
See MidiOut::chnPatchChange()
GUSOut(int d=0, int total=12)
Constructor.
virtual void chnPitchBender(uchar chn, uchar lsb, uchar msb)
See MidiOut::chnPitchBender()
virtual void sysex(uchar *data, ulong size)
It's an empty function, as GUS synths don't support System Exclusive messages.
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.
TQString name(StdAccel id)
TQString description(StdAccel id)