~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to kmid/player/gusout.cc

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
 
 
3
    gusout.cc  - class GUSOut which implements support for Gravis
 
4
         Ultrasound cards through a /dev/sequencer device
 
5
    Copyright (C) 1998  Antonio Larrosa Jimenez
 
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 2 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, write to the Free Software
 
19
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
 
 
21
    Send comments and bug fixes to antlarr@arrakis.es
 
22
    or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
 
23
 
 
24
***************************************************************************/
 
25
#include "gusout.h"
 
26
#include <sys/stat.h>
 
27
#include <unistd.h>
 
28
#include <fcntl.h>
 
29
#include <stdio.h>
 
30
#include "sndcard.h"
 
31
#include <sys/ioctl.h>
 
32
#include <errno.h>
 
33
#include <string.h>
 
34
#include <sys/param.h>
 
35
#include <stdlib.h>
 
36
#include "../version.h"
 
37
#include "midispec.h"
 
38
#include "gusvoices.h"
 
39
 
 
40
SEQ_USE_EXTBUF();
 
41
 
 
42
struct pat_header
 
43
{
 
44
    char            magic[12];
 
45
    char            version[10];
 
46
    char            description[60];
 
47
    unsigned char   instruments;
 
48
    char            voices;
 
49
    char            channels;
 
50
    unsigned short  nr_waveforms;
 
51
    unsigned short  master_volume;
 
52
    unsigned long   data_size;
 
53
};
 
54
struct sample_header
 
55
{
 
56
    char            name[7];
 
57
    unsigned char   fractions;
 
58
    long            len;
 
59
    long            loop_start;
 
60
    long            loop_end;
 
61
    unsigned short  base_freq;
 
62
    long            low_note;
 
63
    long            high_note;
 
64
    long            base_note;
 
65
    short           detune;
 
66
    unsigned char   panning;
 
67
    
 
68
    unsigned char   envelope_rate[6];
 
69
    unsigned char   envelope_offset[6];
 
70
    
 
71
    unsigned char   tremolo_sweep;
 
72
    unsigned char   tremolo_rate;
 
73
    unsigned char   tremolo_depth;
 
74
    
 
75
    unsigned char   vibrato_sweep;
 
76
    unsigned char   vibrato_rate;
 
77
    unsigned char   vibrato_depth;
 
78
    
 
79
    char            modes;
 
80
    
 
81
    short           scale_frequency;
 
82
    unsigned short  scale_factor;
 
83
};
 
84
 
 
85
int get_dint(unsigned char *p)
 
86
{
 
87
    unsigned int v=0;
 
88
    
 
89
    for (int i=0;i<4;i++)
 
90
    {
 
91
        v |= (p[i] << (i*8));
 
92
    }
 
93
    return (int)v;
 
94
}
 
95
 
 
96
unsigned short get_word(unsigned char *p)
 
97
{
 
98
    unsigned short v=0;
 
99
    
 
100
    for (int i=0;i<2;i++)
 
101
        v |= (*p++ << (i*8));
 
102
    return (short)v;
 
103
}
 
104
 
 
105
GUSOut::GUSOut(int d,int total)
 
106
{
 
107
    seqfd = -1;
 
108
    devicetype=KMID_GUS;
 
109
    device= d;
 
110
#ifdef HANDLETIMEINDEVICES
 
111
    count=0.0;
 
112
    lastcount=0.0;
 
113
    rate=100;
 
114
#endif
 
115
    _ok=1;
 
116
    
 
117
    use8bit=0;
 
118
    nvoices=total;
 
119
    vm=new voiceManager(nvoices);
 
120
}
 
121
 
 
122
GUSOut::~GUSOut()
 
123
{
 
124
    delete map;
 
125
    closeDev();
 
126
    if (delete_GUS_patches_directory) 
 
127
    {
 
128
        delete GUS_patches_directory;
 
129
        delete_GUS_patches_directory = 0;
 
130
        GUS_patches_directory="/etc";
 
131
    }
 
132
}
 
133
 
 
134
void GUSOut::openDev (int sqfd)
 
135
{
 
136
    _ok=1;
 
137
    seqfd = sqfd;
 
138
    //vm->cleanLists();
 
139
    if (seqfd==-1)
 
140
    {
 
141
        printf("ERROR: Could not open /dev/sequencer\n");
 
142
        return;
 
143
    }
 
144
    
 
145
#ifdef HANDLETIMEINDEVICES
 
146
    ioctl(seqfd,SNDCTL_SEQ_NRSYNTHS,&ndevs);
 
147
    ioctl(seqfd,SNDCTL_SEQ_NRMIDIS,&nmidiports);
 
148
    
 
149
    rate=0;
 
150
    int r=ioctl(seqfd,SNDCTL_SEQ_CTRLRATE,&rate);
 
151
    if ((r==-1)||(rate<=0)) rate=HZ;
 
152
    convertrate=1000/rate;
 
153
    
 
154
    count=0.0;
 
155
    lastcount=0.0;
 
156
    
 
157
#endif
 
158
    //seqbuf_clean();
 
159
    //ioctl(seqfd,SNDCTL_SEQ_RESET);
 
160
    //ioctl(seqfd,SNDCTL_SEQ_PANIC);
 
161
    
 
162
    if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &device)==-1) 
 
163
    {
 
164
        printf("Error reseting gus samples. Please report\n");
 
165
    };
 
166
    use8bit=0;
 
167
    totalmemory = device;
 
168
    ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &totalmemory);
 
169
    freememory = device;
 
170
    ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &freememory);
 
171
    
 
172
#ifdef GUSOUTDEBUG
 
173
    printf("GUS Device %d opened (%d voices)\n",device,nvoices);
 
174
#ifdef HANDLETIMEINDEVICES
 
175
    printf("Number of synth devices : %d\n",ndevs);
 
176
    printf("Number of midi ports : %d\n",nmidiports);
 
177
    printf("Rate : %d\n",rate);
 
178
#endif
 
179
#endif
 
180
    
 
181
 
 
182
}
 
183
 
 
184
void GUSOut::closeDev (void)
 
185
{
 
186
    if (!ok()) return;
 
187
#ifdef HANDLETIMEINDEVICES
 
188
    SEQ_STOP_TIMER();
 
189
    SEQ_DUMPBUF();
 
190
#endif
 
191
    vm->cleanLists();
 
192
    //if (seqfd>=0)
 
193
    //    close(seqfd);
 
194
    seqfd=-1;
 
195
}
 
196
 
 
197
void GUSOut::initDev (void)
 
198
{
 
199
    int chn;
 
200
    if (!ok()) return;
 
201
#ifdef HANDLETIMEINDEVICES
 
202
    count=0.0;
 
203
    lastcount=0.0;
 
204
#endif
 
205
    uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7};
 
206
    sysex(gm_reset, sizeof(gm_reset));
 
207
    for (chn=0;chn<16;chn++)
 
208
    {
 
209
        chnmute[chn]=0;
 
210
        chnPatchChange(chn,0);
 
211
//        chnPressure(chn,127);
 
212
        chnPitchBender(chn, 0x00, 0x40);
 
213
        chnController(chn, CTL_MAIN_VOLUME,127);
 
214
        chnController(chn, CTL_EXT_EFF_DEPTH, 0);
 
215
        chnController(chn, CTL_CHORUS_DEPTH, 0);
 
216
        chnController(chn, 0x4a, 127);
 
217
    }
 
218
    
 
219
    
 
220
    for (int i = 0; i < nvoices; i++)
 
221
    {
 
222
        SEQ_CONTROL(device, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
 
223
        SEQ_STOP_NOTE(device, i, vm->Note(i), 64);
 
224
    }
 
225
    
 
226
}
 
227
 
 
228
 
 
229
int GUSOut::patch(int p)
 
230
{
 
231
    if (patchloaded[p]==1) return p;
 
232
    printf("Not loaded %d!\n",p);
 
233
    p=0;
 
234
    while ((p<256)&&(patchloaded[p]==0)) p++;
 
235
    return p;
 
236
}
 
237
 
 
238
void GUSOut::noteOn  (uchar chn, uchar note, uchar vel)
 
239
{
 
240
    if (vel==0)
 
241
    {
 
242
        noteOff(chn,note,vel);
 
243
    }
 
244
    else
 
245
    {
 
246
        if (chn==PERCUSSION_CHANNEL)
 
247
        {
 
248
            if (patchloaded[note+128]==0) return;
 
249
            else
 
250
                if (patchloaded[chnpatch[chn]]==0) return;
 
251
        };
 
252
        int v=vm->allocateVoice(chn,note);
 
253
        int p;
 
254
        if (chn==PERCUSSION_CHANNEL)
 
255
            SEQ_SET_PATCH(device,v ,p=patch(note+128))
 
256
        else
 
257
            SEQ_SET_PATCH(device,v ,p=map->patch(chn,chnpatch[chn])); 
 
258
        SEQ_BENDER(device, v, chnbender[chn]);
 
259
        
 
260
        SEQ_START_NOTE(device, v, note, vel);
 
261
        //        SEQ_CONTROL(device, v, CTL_MAIN_VOLUME, chncontroller[chn][CTL_MAIN_VOLUME]);
 
262
        SEQ_CHN_PRESSURE(device, v , chnpressure[chn]);
 
263
    }
 
264
    
 
265
#ifdef GUSOUTDEBUG
 
266
    printf("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
 
267
#endif
 
268
}
 
269
 
 
270
void GUSOut::noteOff (uchar chn, uchar note, uchar vel)
 
271
{
 
272
    int i;
 
273
    vm->initSearch();
 
274
    while ((i=vm->Search(chn,note))!=-1)
 
275
    {
 
276
        SEQ_STOP_NOTE(device, i, note, vel);
 
277
        vm->deallocateVoice(i);
 
278
    }
 
279
    
 
280
#ifdef GUSOUTDEBUG
 
281
    printf("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
 
282
#endif
 
283
}
 
284
 
 
285
void GUSOut::keyPressure (uchar chn, uchar note, uchar vel)
 
286
{
 
287
    int i;
 
288
    vm->initSearch();
 
289
    while ((i=vm->Search(chn,note))!=-1)
 
290
        SEQ_KEY_PRESSURE(device, i, note,vel);
 
291
}
 
292
 
 
293
void GUSOut::chnPatchChange (uchar chn, uchar patch)
 
294
{
 
295
    if (chn==PERCUSSION_CHANNEL) return;
 
296
    int i;
 
297
    vm->initSearch();
 
298
    while ((i=vm->Search(chn))!=-1)
 
299
        SEQ_SET_PATCH(device,i,map->patch(chn,patch)); 
 
300
    chnpatch[chn]=patch;
 
301
    
 
302
}
 
303
 
 
304
void GUSOut::chnPressure (uchar chn, uchar vel)
 
305
{
 
306
/*    int i;
 
307
    vm->initSearch();
 
308
    while ((i=vm->Search(chn))!=-1)
 
309
        SEQ_CHN_PRESSURE(device, i , vel);
 
310
    chnpressure[chn]=vel;
 
311
*/
 
312
}
 
313
 
 
314
void GUSOut::chnPitchBender(uchar chn,uchar lsb, uchar msb)
 
315
{
 
316
    chnbender[chn]=((int)msb<<7) | (lsb & 0x7F);
 
317
    
 
318
    int i;
 
319
    vm->initSearch();
 
320
    while ((i=vm->Search(chn))!=-1)
 
321
        SEQ_BENDER(device, i, chnbender[chn]);
 
322
}
 
323
 
 
324
void GUSOut::chnController (uchar chn, uchar ctl, uchar v) 
 
325
{
 
326
    if ((ctl==11)||(ctl==7))
 
327
    {
 
328
        v=(v*volumepercentage)/100;
 
329
        if (v>127) v=127;
 
330
    };
 
331
    
 
332
    int i;
 
333
    vm->initSearch();
 
334
    while ((i=vm->Search(chn))!=-1)
 
335
        SEQ_CONTROL(device, i, ctl, v);
 
336
    
 
337
    chncontroller[chn][ctl]=v;
 
338
}
 
339
 
 
340
void GUSOut::sysex(uchar *, ulong )
 
341
{
 
342
    
 
343
}
 
344
 
 
345
void GUSOut::setGUSPatchesDirectory(const char *dir)
 
346
{
 
347
    if ((dir==NULL)||(dir[0]==0)) return;
 
348
    if (delete_GUS_patches_directory) delete GUS_patches_directory;
 
349
    char *GUS_patches_directory2=new char[strlen(dir)+1];
 
350
    strcpy(GUS_patches_directory2,dir);
 
351
    GUS_patches_directory = GUS_patches_directory2;
 
352
    delete_GUS_patches_directory=1;
 
353
}
 
354
 
 
355
char *GUSOut::patchName(int pgm)
 
356
{
 
357
    return GUS_voice_names[pgm];
 
358
}
 
359
 
 
360
 
 
361
int GUSOut::loadPatch(int pgm)
 
362
{
 
363
    struct pat_header header;
 
364
    struct sample_header sample;
 
365
    if (patchloaded[pgm]==1)
 
366
    {
 
367
        printf("Trying to reload a patch. This should never happen, please report.\n");
 
368
        return 0;
 
369
    }
 
370
    if ((patchName(pgm)==NULL)||((patchName(pgm))[0]==0))
 
371
    {
 
372
        printf("Couldn't guess patch name for patch number %d\n",pgm);
 
373
        return -1;
 
374
    }
 
375
    char *s=new char[strlen(GUS_patches_directory)+strlen(patchName(pgm))+10];
 
376
    if (s==NULL) return -1;
 
377
    sprintf(s,"%s/%s.pat",GUS_patches_directory,patchName(pgm));
 
378
    printf("Loading patch : %s\n",s);
 
379
    struct patch_info *patch=NULL;
 
380
    struct stat info;
 
381
    if (stat(s, &info)==-1)
 
382
    {
 
383
        printf("File %s doesn't exist\n",s);
 
384
        return -1;
 
385
    }
 
386
    
 
387
    FILE *fh=fopen(s,"rb");
 
388
    if (fh==NULL)
 
389
    {
 
390
        printf("Couldn't open patch %s\n",s);
 
391
        return -1;
 
392
    }
 
393
    
 
394
    unsigned char tmp[256];
 
395
    if (fread(tmp,1,0xef,fh)!=0xef)
 
396
    {
 
397
        fclose(fh);
 
398
        printf("Short file ! \n");
 
399
        return -1;
 
400
    }
 
401
    memcpy ((char *) &header, tmp, sizeof (header)); 
 
402
    
 
403
    if (strncmp(header.magic,"GF1PATCH110",12)!=0)
 
404
    {
 
405
        printf("File %s is corrupted or it isn't a patch file\n",s);
 
406
        return -1;
 
407
    }
 
408
    if (strncmp(header.version,"ID#000002",10)!=0)
 
409
    {
 
410
        printf("File %s's version is not supported\n",s);
 
411
        return -1;
 
412
    }
 
413
    unsigned short nWaves= *(unsigned short *)&tmp[85];
 
414
#ifdef GUSOUTDEBUG
 
415
    unsigned short masterVolume= *(unsigned short *)&tmp[87];
 
416
    printf("nWaves: %d\n",nWaves);
 
417
    printf("masterVolume : %d\n",masterVolume);
 
418
#endif
 
419
    
 
420
    unsigned short i;
 
421
    int offset=0xef;
 
422
    for (i=0;i<nWaves;i++)
 
423
    {
 
424
        fseek(fh,offset,SEEK_SET);
 
425
        
 
426
        if (fread(tmp,1,sizeof(sample),fh) != sizeof(sample))
 
427
        {
 
428
            fclose(fh);
 
429
            printf("Short file\n");
 
430
            return -1;
 
431
        }
 
432
        memcpy ((char *) &sample, tmp, sizeof (sample));
 
433
        sample.fractions = (char)tmp[7];
 
434
        sample.len = get_dint(&tmp[8]);
 
435
        sample.loop_start = get_dint(&tmp[12]);
 
436
        sample.loop_end = get_dint(&tmp[16]);
 
437
        sample.base_freq = get_word(&tmp[20]);
 
438
        sample.low_note = get_dint(&tmp[22]);
 
439
        sample.high_note = get_dint(&tmp[26]);
 
440
        sample.base_note = get_dint(&tmp[30]);
 
441
        sample.detune = (short)get_word(&tmp[34]);
 
442
        sample.panning = (unsigned char) tmp[36];  
 
443
        
 
444
        memcpy (sample.envelope_rate, &tmp[37], 6);
 
445
        memcpy (sample.envelope_offset, &tmp[43], 6);
 
446
        
 
447
        sample.tremolo_sweep = (unsigned char) tmp[49];
 
448
        sample.tremolo_rate = (unsigned char) tmp[50];
 
449
        sample.tremolo_depth = (unsigned char) tmp[51];
 
450
        
 
451
        sample.vibrato_sweep = (unsigned char) tmp[52];
 
452
        sample.vibrato_rate = (unsigned char) tmp[53];
 
453
        sample.vibrato_depth = (unsigned char) tmp[54];
 
454
        sample.modes = (unsigned char) tmp[55];
 
455
        sample.scale_frequency = (short)get_word(&tmp[56]);
 
456
        sample.scale_factor = get_word(&tmp[58]);
 
457
        
 
458
        offset = offset + 96;
 
459
        
 
460
        patch = (struct patch_info *) malloc(sizeof (*patch) + sample.len);
 
461
        if (patch == NULL)
 
462
        {
 
463
            printf("Not enough memory\n");
 
464
            return -1;
 
465
        }
 
466
        patch->key = GUS_PATCH;
 
467
        patch->device_no = device;
 
468
        patch->instr_no = pgm;
 
469
        patch->mode = sample.modes | WAVE_TREMOLO | WAVE_VIBRATO | WAVE_SCALE;
 
470
        patch->len = sample.len;
 
471
        patch->loop_start = sample.loop_start;
 
472
        patch->loop_end = sample.loop_end;
 
473
        patch->base_note = sample.base_note;
 
474
        patch->high_note = sample.high_note;
 
475
        patch->low_note = sample.low_note;
 
476
        patch->base_freq = sample.base_freq;
 
477
        patch->detuning = sample.detune;
 
478
        patch->panning = (sample.panning - 7) * 16;
 
479
        
 
480
        memcpy (patch->env_rate, sample.envelope_rate, 6);
 
481
        memcpy (patch->env_offset, sample.envelope_offset, 6);
 
482
        
 
483
        patch->tremolo_sweep = sample.tremolo_sweep;
 
484
        patch->tremolo_rate = sample.tremolo_rate;
 
485
        patch->tremolo_depth = sample.tremolo_depth;
 
486
        
 
487
        patch->vibrato_sweep = sample.vibrato_sweep;
 
488
        patch->vibrato_rate = sample.vibrato_rate;
 
489
        patch->vibrato_depth = sample.vibrato_depth;
 
490
        
 
491
        patch->scale_frequency = sample.scale_frequency;
 
492
        patch->scale_factor = sample.scale_factor;
 
493
        
 
494
        patch->volume = header.master_volume; 
 
495
        
 
496
        if (fseek (fh, offset, 0) == -1)
 
497
        {
 
498
            fclose(fh);
 
499
            return -1;
 
500
        }
 
501
        
 
502
        if ((long)fread (patch->data, 1,sample.len,fh) != sample.len)
 
503
        {
 
504
            printf ("Short file\n");
 
505
            return -1;
 
506
        }
 
507
        
 
508
        SEQ_WRPATCH (patch, sizeof (*patch) + sample.len);
 
509
        
 
510
        offset = offset + sample.len;
 
511
        
 
512
    }
 
513
    patchloaded[pgm]=1;
 
514
    
 
515
    fclose(fh);
 
516
    free(patch); // Shouldn't this 'free' be within the 'for' loop ?
 
517
    delete s;
 
518
    freememory = device;
 
519
    ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &freememory);
 
520
    return 0;
 
521
}
 
522
 
 
523
 
 
524
void GUSOut::setPatchesToUse(int *patchesused)
 
525
{
 
526
    int k;
 
527
    for (k=0;k<256;k++) patchloaded[k]=0;
 
528
    
 
529
    int patchesordered[256]; //This holds the pgm used ordered by a method which
 
530
    // put first the patches more oftenly used, and then the least
 
531
    // In example, if a song only uses a piano and a splash cymbal,
 
532
    // This is set to : 0,188,-1,-1,-1,-1 ...
 
533
    getPatchesLoadingOrder(patchesused,patchesordered);
 
534
    
 
535
    // If above line doesn't work, perhaps you could try this ? :
 
536
    // for (int j=0;j<256;j++) patchesordered[j]=patchesused[j];
 
537
    printf("Patches used : \n");
 
538
    for (k=0;k<256;k++)
 
539
    {
 
540
        if (patchesused[k]!=-1) printf("%d,",patchesused[k]);
 
541
    }
 
542
    printf("\n Patches used, sorted :\n");
 
543
    for (k=0;k<256;k++)
 
544
    {
 
545
        if (patchesordered[k]!=-1) printf("%d,",patchesordered[k]);
 
546
    }
 
547
    
 
548
    int i=0;
 
549
    while (patchesordered[i]!=-1)
 
550
    {
 
551
        printf("Load Patch : %d\n",patchesordered[i]);
 
552
        loadPatch(patchesordered[i]);
 
553
        i++;
 
554
    }
 
555
}
 
556
 
 
557
int compare_decreasing(const void *a,const void *b)
 
558
{
 
559
    struct instr_gm
 
560
    {
 
561
        int used;
 
562
        int pgm; 
 
563
    };
 
564
    instr_gm *ai=(instr_gm *)a;
 
565
    instr_gm *bi=(instr_gm *)b;
 
566
    return ai->used<bi->used;
 
567
}
 
568
 
 
569
void GUSOut::getPatchesLoadingOrder(int *patchesused,int *patchesordered)
 
570
{
 
571
    struct instr_gm
 
572
    {
 
573
        int used;
 
574
        int pgm; 
 
575
    };
 
576
    
 
577
    instr_gm tempmelody[128];
 
578
    instr_gm tempdrums[128];
 
579
    int i,j;
 
580
    for (i=0,j=128;i<128;i++,j++) 
 
581
    {
 
582
        tempmelody[i].used=patchesused[i];
 
583
        tempmelody[i].pgm=i;
 
584
        tempdrums[i].used=patchesused[j];
 
585
        tempdrums[i].pgm=j;
 
586
    }
 
587
    /* SORT */ // Decreasing order (first most used patch, then less used patch)
 
588
    qsort(&tempmelody[0],128,sizeof(instr_gm),compare_decreasing);
 
589
    qsort(&tempdrums[0],128,sizeof(instr_gm),compare_decreasing);
 
590
    
 
591
    /* Once they are sorted, the result is put on patchesordered in the following
 
592
     way : If tempmelody is : M0 M1 M2 M3 ... M127 and tempdrums is :
 
593
     D0 D1 D2 D3 ... D127, the result is :
 
594
     M0 D0 M1 M2 D1 M3 M4 D2 M5 M6 D3  ...
 
595
     P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 ...
 
596
     */
 
597
    
 
598
#ifdef GUSOUTDEBUG
 
599
    for (int k=0;k<128;k++)
 
600
    {
 
601
        printf("%d - %d\n",tempmelody[k].used,tempmelody[k].pgm);
 
602
    }
 
603
    for (int k=0;k<128;k++)
 
604
    {
 
605
        printf("%d : %d\n",tempdrums[k].used,tempdrums[k].pgm);
 
606
    }
 
607
#endif
 
608
    
 
609
    i=0;
 
610
    int totalmelody=0;
 
611
    while ((i<128)&&(tempmelody[i].used!=0))
 
612
    {
 
613
        totalmelody++;
 
614
        i++;
 
615
    }
 
616
    i=0;
 
617
    int totaldrums=0;
 
618
    while ((i<128)&&(tempdrums[i].used!=0))
 
619
    {
 
620
        totaldrums++;
 
621
        i++;
 
622
    }
 
623
    printf("Totalmelody : %d,totaldrums : %d\n",totalmelody,totaldrums);
 
624
    int tgt=0;
 
625
    
 
626
    int tm=totalmelody;
 
627
    int td=totaldrums;
 
628
    int cm,cd;
 
629
    cm=cd=0;
 
630
    if ((tm!=0)&&(td!=0))
 
631
    {
 
632
        patchesordered[0]=tempmelody[0].pgm;
 
633
        patchesordered[1]=tempdrums[0].pgm;
 
634
        tm--;td--;
 
635
        cm++;cd++;
 
636
        tgt+=2;
 
637
        while ((tm>0)&&(td>0))
 
638
        {
 
639
            if (((tgt-1)%3)==0) 
 
640
            {
 
641
                patchesordered[tgt]=tempdrums[cd].pgm;
 
642
                cd++;
 
643
                td--;
 
644
            }
 
645
            else
 
646
            {
 
647
                patchesordered[tgt]=tempmelody[cm].pgm;
 
648
                cm++;
 
649
                tm--;
 
650
            }
 
651
            tgt++;      
 
652
        }
 
653
    }
 
654
    while (tm>0)
 
655
    {
 
656
        patchesordered[tgt]=tempmelody[cm].pgm;
 
657
        tgt++;
 
658
        cm++;
 
659
        tm--;
 
660
    }
 
661
    while (td>0)
 
662
    {
 
663
        patchesordered[tgt]=tempdrums[cd].pgm;
 
664
        tgt++;
 
665
        cd++;
 
666
        td--;
 
667
    }
 
668
    
 
669
    // Now we put as not used (-1) the rest of the array
 
670
    while (tgt<256)
 
671
    {
 
672
        patchesordered[tgt]=-1;
 
673
        tgt++;
 
674
    }
 
675
}
 
676
 
 
677
//char *GUSOut::GUS_patches_directory="/mnt/dosc/gravis/patches";
 
678
const char *GUSOut::GUS_patches_directory="/dos/ultrasnd/midi";
 
679
 
 
680
int GUSOut::delete_GUS_patches_directory = 0;
 
681
/* No, this doesn't delete any file :-) it's just for internal use */