home *** CD-ROM | disk | FTP | other *** search
- /*
- CONVERT.C
-
- 27-jun-88, Marc Savary, Ad Lib Inc.
-
- Module to convert *.ROL file to AdLib Midi file, *.MUS & *.SND
-
- The beginning of the .MUS file contains 70 bytes
- of start-up information (see convert.h file):
- 1: major version # of file
- 1: minor version # of file
- 4: melody identification
- 30: melody name
- 1: ticks per beat
- 1: beats per measure
- 4: length of melody, in ticks
- 4: length of melody's data part
- 4: total number of commands in melody, including NOTE-ON, NOTE-OFF,
- PROGRAM-CHANGE, AFTER-TOUCH, PITCH-BEND, OVERFLOW, SYSTEM-XOR
- & STOP
- 8: filler area, set to zero
- 1: sound mode: 0 == melodic, 1 == percussive
- 1: pitch bend range, from 1 to 12
- 2: basic tempo
- 8: filler area, set to zero
-
- Following the header is the musical data.
- The data part of the .MUS file contains midi 1.0 commands with timing
- bytes of 1/tickBeat. tickBeat is the number of divisions per beat.
- The relation between tickBeat, tempo (beat per minute) & frequency of
- the timing counter is:
- frequency = (tempo / 60) * tickBeat.
-
- Timing bytes vary from 0 to 0xFE and precede every command. A timing
- byte of 0xF8 means timing overflow with a value of 240. An overflow
- byte is always followed by another overflow byte or timing byte.
-
- Program changes refer to timbre definitions in the .SND bank file by their
- relative order. While converting files, if a timbre ( ref. by it's name)
- is not found in the bank file, its definition is appended to the end.
-
- A tempo change is specified within a SYSTEM EXCLUSIVE MESSAGE:
- 0xF0 0x7F 00 <integer> <frac> 0xF7, where 'integer' is the integer
- part of the tempo multiplier and 'frac' the fractionnal part, in 1/128.
-
- Each voice is associated with one midi channel. In melodic mode,
- channels 0 to 8 are melodic; in percussive mode, channels 0 to 5
- are melodic and channels 6 to 11 are percussive.
-
- The last MIDI command of the file is STOP ( 0xFC).
-
- If compiling with Lattice, 'LATTICE' must be defined for MEMORY.C
- and BANK.C.
-
- With Microsoft, use the following ('MICROSOFT' must be defined for
- this file and BANK.C):
- cl -DMICROSOFT -AS -J -Zi /Zp1 -Ox -Gs play.c bank.c adlib.c
-
- */
-
- #include "mem.h"
- #include "convert.h"
- #include "adlib.h"
- #include "bank.h"
- #include "strmidi.h"
-
- #include "fcntl.h"
- #include "stdio.h"
-
- #ifdef MICROSOFT
- #include <sys\types.h>
- #include <sys\stat.h>
- #define open(x,y) open(x,y,S_IWRITE)
- #define setmem(x,y,z) memset(x,z,y)
- #define min(x,y) ((x < y) ? x:y)
- #define max(x,y) ((x > y) ? x:y)
- #endif
-
- #define NR_MELO_VOICES 9 /* in melodic mode */
- #define NR_PERC_VOICES 11 /* in percussive mode */
-
- #define BLOCK_SIZE 512 /* must be power of two !!! */
- #define instrumFileExtension ".INS"
- #define musicFileExtension ".ROL"
-
- #define MAJOR_VERSION 1
- #define MINOR_VERSION 0
-
- /* type of events, decreasing in order of priority: */
- #define NOTE_OFF_TP 0
- #define PRESET_TP 1
- #define PITCH_TP 2
- #define VOLUME_TP 3
- #define TEMPO_TP 4
- #define NOTE_ON_TP 5
- #define NR_TYPES 6
-
-
-
- typedef int Time;
-
- typedef
- struct {
- unsigned nrBytes;
- unsigned size;
- Handle liste;
- } ListDesc;
-
- typedef
- struct {
- Time time;
- float tempo;
- } TempoEvent;
-
- typedef
- struct {
- int note;
- int duree;
- } NoteEvent;
-
-
- typedef
- struct {
- Time time;
- char instrumName[ 9];
- char filler;
- int timbreIndex;
- } InstrumEvent;
-
- typedef
- struct {
- Time time;
- float volume;
- } VolumeEvent;
-
-
- typedef
- struct {
- Time time;
- float pitch;
- } PitchEvent;
-
- typedef
- struct {
- char instrumName[ 9];
- int params[ 26];
- } TimbreDef;
-
- typedef
- struct {
- long rollTime;
- long rollPos;
- char voice;
- char used;
- char type;
- } Cedule;
-
- #define NoteAtPos( vc, pos) ((NoteEvent *) *noteList[ vc].liste + pos)
- #define PitchAtPos( vc, pos) ((PitchEvent *) *pitchList[ vc].liste + pos)
- #define VolumeAtPos( vc, pos) ((VolumeEvent *) *volumeList[ vc].liste + pos)
- #define InstrumAtPos( vc, pos) ((InstrumEvent *) *instrumList[ vc].liste + pos)
- #define TempoAtPos( pos) ((TempoEvent *) *tempoList.liste + pos)
-
- #define PitchSize( vc) ( pitchList[ vc].size)
- #define InstrumSize( vc) ( instrumList[ vc].size)
- #define VolumeSize( vc) ( volumeList[ vc].size)
- #define TempoSize() ( tempoList.size)
- #define NoteSize( vc) ( noteList[ vc].size)
-
- ListDesc instrumList[ NR_VOICES];
- ListDesc noteList[ NR_VOICES];
- ListDesc pitchList[ NR_VOICES];
- ListDesc volumeList[ NR_VOICES];
- ListDesc tempoList;
- ListDesc timbreList;
- int srcTickBeat,
- destTickBeat;
- int beatMeasure;
- char notPercusMode;
- float basicTempo;
- int pitchBRange;
- Time duree_piece; /* length of piece */
-
- Cedule cedList[ NR_TYPES][ NR_VOICES];
- long offTime[ NR_VOICES];
- long mpuTime;
- char statusArray[ NR_TYPES] = { NOTE_ON_BYTE, PROG_CHANGE_BYTE,
- PITCH_BEND_BYTE, AFTER_TOUCH_BYTE,
- 00, NOTE_ON_BYTE };
- char status;
- long byteCount;
- long commCount;
- char voiceVolume[ NR_VOICES];
- int outFile;
- BankPtr timbBank;
-
- extern long ConvertTime();
-
-
-
-
- main( argc, argv)
- int argc;
- char * argv[];
- {
- char buff[ 150];
-
- if( argc < 4) {
- fprintf( stderr, "\nUSE: convert <infile.rol> <bankfile.tim> <outfile.mus>");
- exit( 1);
- }
-
- InitMemory( 32);
- ColdInit();
-
- timbBank = OpenBank( argv[ 2], 1);
- if( NULL == timbBank) {
- fprintf( stderr, "\nCannot open timbre bank file '%s'.", argv[ 2]);
- exit( 1);
- }
-
- outFile = open( argv[ 3], O_WRONLY + O_RAW + O_TRUNC + O_CREAT);
- if( -1 == outFile) {
- fprintf( stderr, "\nUnable to open write file '%s'.", argv[ 3]);
- exit( 1);
- }
-
- if( !ConvertFile( argv[ 1])) {
- fprintf( stderr, "\nUnable to open read file '%s'.", argv[ 1]);
- exit( 1);
- }
- close( outFile);
- CloseBank( timbBank);
- } /* main() */
-
-
-
-
- ColdInit()
- {
- int i;
-
- for( i = 0; i < NR_VOICES; i++) {
- instrumList[ i].size = 0;
- instrumList[ i].liste = NewHandle( (Size) 4);
- instrumList[ i].nrBytes = 4;
-
- noteList[ i].size = 0;
- noteList[ i].liste = NewHandle( (Size) 4);
- noteList[ i].nrBytes = 4;
-
- pitchList[ i].size = 0;
- pitchList[ i].liste = NewHandle( (Size) 4);
- pitchList[ i].nrBytes = 4;
-
- volumeList[ i].size = 0;
- volumeList[ i].liste = NewHandle( (Size) 4);
- volumeList[ i].nrBytes = 4;
- }
- tempoList.size = 0;
- tempoList.liste = NewHandle( (Size) 4);
- tempoList.nrBytes = 4;
-
- timbreList.size = 0;
- timbreList.liste = NewHandle( (Size) 4);
- timbreList.nrBytes = 4;
-
- /* Set the number of ticks per beat of the resulting conversion
- ( must be a multiple of the ticks/beat of the .ROL file)
- This value is used for the conversion of the timing base. */
- destTickBeat = DEFAULT_TICK_BEAT;
- } /* ColdInit() */
-
-
-
- /*
- For doing conversion, we first load the piece, and simulate
- the playing for ordering the events, using priority values when
- the events occur at the same time.
- */
- int ConvertFile( fileName)
- char * fileName;
- {
-
- int voix, nb_voices;
- Time longueur;
- Cedule * ced;
- struct MusHeader mHd;
- extern Cedule * NextCedule();
-
- if( ! MyLoadMelo( fileName))
- return 0;
- LoadTimbres();
-
- setmem( &mHd, sizeof( struct MusHeader), 0);
- write( outFile, &mHd, sizeof( struct MusHeader));
-
- StartCedule();
-
- while( ced = NextCedule()) {
- switch( ced->type) {
- case PRESET_TP: DoPreset( ced); break;
- case PITCH_TP: DoPitch( ced); break;
- case VOLUME_TP: DoVolume( ced); break;
- case TEMPO_TP: DoTempo( ced); break;
- case NOTE_ON_TP: DoNoteOn( ced); break;
- case NOTE_OFF_TP: DoNoteOff( ced); break;
- default: printf( "\nBad event type: %d", ced->type);
- }
- }
- DoEndMelo();
-
- mHd.majorVersion = MAJOR_VERSION;
- mHd.minorVersion = MINOR_VERSION;
- mHd.tickBeat = destTickBeat;
- mHd.beatMeasure = beatMeasure;
- mHd.totalTick = ConvertTime( duree_piece);
- mHd.dataSize = byteCount;
- mHd.nrCommand = commCount;
- mHd.soundMode = !notPercusMode;
- mHd.pitchBRange = pitchBRange;
- mHd.basicTempo = basicTempo;
-
- /* write header to output file: */
- lseek( outFile, 0L, 0);
- write( outFile, &mHd, sizeof( struct MusHeader));
- } /* ConvertFile() */
-
-
-
- /*
- Start the simulation of playing a melody.
- */
- StartCedule()
- {
- int i, j, k;
- Cedule * ced;
-
- ced = &cedList[ 0][ 0];
- for( i = 0; i < NR_TYPES; i++)
- for( k = 0; k < NR_VOICES; k++, ced++) {
- ced->rollTime = 0;
- ced->rollPos = 0;
- ced->used = 0;
- ced->voice = k;
- ced->type = i;
- }
- for( k = 0; k < NR_VOICES; k++) {
- CedulePreset( k, 0);
- CedulePitch( k, 0);
- CeduleVolume( k, 0);
- offTime[ k] = 0;
- CeduleNoteOn( k, 0);
- }
- CeduleTempo( 0);
- mpuTime = 0;
- status = 0;
- byteCount = 0;
- commCount = 0;
- } /* StartCedule() */
-
-
- /*
- Find and return the next event with the lowest time value.
- Return NULL if no more.
- */
- Cedule * NextCedule()
- {
- Cedule * ced, * next;
- long lowTime;
- int type, vc;
-
- ced = &cedList[ 0][ 0];
- next = NULL;
- lowTime = 0x7fffffff;
- for( type = 0; type < NR_TYPES; type++)
- for( vc = 0; vc < NR_VOICES; vc++, ced++) {
- if( ! ced->used)
- continue;
- if( ced->rollTime < lowTime) {
- lowTime = ced->rollTime;
- next = ced;
- }
- }
- return next;
- } /* NextCedule() */
-
-
- /*
- Insert in the schedule list the note starting at position
- 'pos' of the .ROL note list of voice 'voice'
- */
- CeduleNoteOn( voice, pos)
- {
- unsigned size;
- Cedule * ced;
- ListDesc * lD;
- NoteEvent * nE;
-
- ced = &cedList[ NOTE_ON_TP][ voice];
- lD = ¬eList[ voice];
- size = lD->size;
- ced->used = 0;
- nE = (NoteEvent *) *lD->liste + pos;
- while( nE->note == 0 && pos < size) {
- /* silences are notes of pitch == 0, and must be skiped */
- offTime[ voice] += nE->duree;
- nE++;
- pos++;
- }
- if( pos < size) {
- ced->rollPos = pos;
- ced->rollTime = offTime[ voice];
- ced->used = 1;
- offTime[ voice] += nE->duree;
- }
- } /* CeduleNoteOn() */
-
-
- CeduleNoteOff( voice, pos)
- {
- Cedule * ced;
-
- ced = &cedList[ NOTE_OFF_TP][ voice];
- ced->rollTime = offTime[ voice];
- ced->rollPos = pos;
- ced->used = 1;
- } /* CeduleNoteOff() */
-
-
-
- CedulePreset( voice, pos)
- {
- Cedule * ced;
- InstrumEvent * iE;
-
- if( NoteSize( voice) == 0)
- return;
- ced = &cedList[ PRESET_TP][ voice];
- if( pos >= InstrumSize( voice))
- ced->used = 0;
- else {
- iE = InstrumAtPos( voice, pos);
- ced->rollTime = iE->time;
- ced->rollPos = pos;
- ced->used = 1;
- }
- } /* CedulePreset() */
-
-
- CedulePitch( voice, pos)
- {
- Cedule * ced;
- PitchEvent * pE;
-
- if( NoteSize( voice) == 0)
- return;
- ced = &cedList[ PITCH_TP][ voice];
- if( pos >= PitchSize( voice))
- ced->used = 0;
- else {
- pE = PitchAtPos( voice, pos);
- ced->rollPos = pos;
- ced->rollTime = pE->time;
- ced->used = 1;
- }
- } /* CedulePitch() */
-
-
- CeduleVolume( voice, pos)
- {
- Cedule * ced;
- VolumeEvent * vE;
-
- if( NoteSize( voice) == 0)
- return;
- ced = &cedList[ VOLUME_TP][ voice];
- if( pos >= VolumeSize( voice))
- ced->used = 0;
- else {
- vE = VolumeAtPos( voice, pos);
- ced->rollPos = pos;
- ced->rollTime = vE->time;
- ced->used = 1;
- }
- } /* CeduleVolume() */
-
-
- CeduleTempo( pos)
- {
- Cedule * ced;
- TempoEvent * tE;
-
- ced = &cedList[ TEMPO_TP][ 0];
- if( pos >= TempoSize())
- ced->used = 0;
- else {
- tE = TempoAtPos( pos);
- ced->rollPos = pos;
- ced->rollTime = tE->time;
- ced->used = 1;
- }
- } /* CeduleTempo() */
-
-
-
-
- /*
- In the normal sequencing order, a note-on must be done
- on the voice & note specified by 'ced'.
-
- Note-on command: <timing> <9n> <pitch> <volume>
- where 'n' is the voice number.
- */
- DoNoteOn( ced)
- Cedule * ced;
- {
- NoteEvent * nE;
- unsigned vol;
-
- DoTiming( ced);
- DoStatus( ced);
- nE = NoteAtPos( ced->voice, ced->rollPos);
- DoData( nE->note);
- vol = max( 1, voiceVolume[ ced->voice]);
- DoData( vol);
-
- /* schedule the note-off of this note: */
- CeduleNoteOff( ced->voice, ced->rollPos);
-
- /* schedule the next note-on for this voice: */
- CeduleNoteOn( ced->voice, ced->rollPos +1);
- } /* DoNoteOn() */
-
-
- /*
- Note-off command: <timing> <9n> <pitch> <00>
- where 'n' is the voice number.
- */
- DoNoteOff( ced)
- Cedule * ced;
- {
- NoteEvent * nE;
-
- DoTiming( ced);
- DoStatus( ced);
- nE = NoteAtPos( ced->voice, ced->rollPos);
- DoData( nE->note);
- DoData( 0);
- ced->used = 0;
- } /* DoNoteOff() */
-
-
- /*
- Pitch command: <timing> <En> <pitch-low> <pitch-high>
- where 'n' is the voice number.
- */
- DoPitch( ced)
- Cedule * ced;
- {
- PitchEvent * pE;
- unsigned uPitch;
-
- DoTiming( ced);
- DoStatus( ced);
- pE = PitchAtPos( ced->voice, ced->rollPos);
- uPitch = pE->pitch * MID_PITCH;
- uPitch = min( MAX_PITCH, uPitch);
- DoData( uPitch);
- DoData( uPitch >> 7);
- CedulePitch( ced->voice, ced->rollPos +1);
- } /* DoPitch() */
-
-
- /*
- After touch command: <timing> <An> <volume>
- where 'n' is the voice number.
- */
- DoVolume( ced)
- Cedule * ced;
- {
- VolumeEvent * vE;
- NoteEvent * nE;
- Cedule * nCed;
- unsigned volume;
-
- vE = VolumeAtPos( ced->voice, ced->rollPos);
- volume = vE->volume * MAX_VOLUME;
- nCed = &cedList[ NOTE_ON_TP][ ced->voice];
- if( nCed->used && nCed->rollTime == ced->rollTime) {
- /* velocity (volume) is occuring in the same time than a note-on
- on this voice; it will be sent with the note-on itself. ... */
- ;
- }
- else {
- DoTiming( ced);
- DoStatus( ced);
- DoData( volume);
- }
- voiceVolume[ ced->voice] = volume;
- CeduleVolume( ced->voice, ced->rollPos +1);
- } /* DoVolume() */
-
-
- /*
- Preset change command: <timing> <Cn> <preset>
- where 'n' is the voice number.
- */
- DoPreset( ced)
- Cedule * ced;
- {
- InstrumEvent * iE;
-
- DoTiming( ced);
- DoStatus( ced);
- iE = InstrumAtPos( ced->voice, ced->rollPos);
- DoData( iE->timbreIndex);
- CedulePreset( ced->voice, ced->rollPos +1);
- } /* DoPreset() */
-
-
- /*
- Tempo: <timing> <F0> <7F> <00> <integer> <frac> <F7>
- (non standard)
- */
- DoTempo( ced)
- Cedule * ced;
- {
- TempoEvent * tE;
- unsigned ent, frac;
-
- tE = TempoAtPos( ced->rollPos);
- ent = min( (unsigned)tE->tempo, 127);
- frac = (tE->tempo - ent) * 128;
- DoTiming( ced);
- PutByte( SYSTEM_XOR_BYTE);
- status = 0; /* status must be re-sent next time */
- PutByte( ADLIB_CTRL_BYTE);
- PutByte( TEMPO_CTRL_BYTE);
- DoData( ent);
- DoData( frac);
- PutByte( EOX_BYTE);
- CeduleTempo( ced->rollPos +1);
- } /* DoTempo() */
-
-
- /*
- End melody: <timing> <FC>
- */
- DoEndMelo()
- {
- commCount++;
- PutByte( 0);
- PutByte( STOP_BYTE);
- } /* DoEndMelo() */
-
-
-
- /*
- Add the timing bytes. If the delay ( in "n/destTickBeat" Beats)
- is greater than or equal to OVERFLOW, insert enough overflow bytes
- before the timing byte.
- */
- DoTiming( ced)
- Cedule * ced;
- {
- long time;
-
- commCount++;
- time = ConvertTime( ced->rollTime);
- while( time - OVERFLOW >= mpuTime) {
- commCount++;
- PutByte( OVERFLOW_BYTE);
- mpuTime += OVERFLOW;
- }
- PutByte( time - mpuTime);
- mpuTime = time;
- } /* DoTiming() */
-
-
- /*
- Convert the time 'rollTime' from the base 'srcTickBeat' (.ROL) to
- the base 'destTickBeat' ( .MUS)
- */
- long ConvertTime( rollTime)
- Time rollTime;
- {
- long time;
-
- time = (long)rollTime * destTickBeat;
- time /= srcTickBeat;
- return time;
- } /* ConverTime() */
-
-
- /*
- Generate a status byte for the NOTE-ON, NOTE-OFF, PRESET-CHANGE, PITCH-BEND
- or AFTER-TOUCH (volume) midi command.
- */
- DoStatus( ced)
- Cedule * ced;
- {
- char newStatus;
-
- newStatus = statusArray[ ced->type] + ced->voice;
- if( newStatus != status) {
- status = newStatus;
- PutByte( status);
- }
- } /* DoStatus() */
-
-
- /*
- Send data byte (high bit set to 0) to output file.
- */
- DoData( data)
- char data;
- {
- PutByte( data & 0x7f);
- } /* DoData() */
-
-
- /*
- Send byte to output file, increment byte counter.
- */
- PutByte( data)
- char data;
- {
- write( outFile, &data, 1);
- byteCount++;
- } /* PutByte() */
-
-
-
-
-
- /*
- -------------------------------------------------------------
- The following routines are used to load a .ROL file in memory.
- Allocate memory using the routines in the MEMORY.C file.
- -------------------------------------------------------------
- */
-
-
- SizeList( liste, nrElems, sizeElem)
- ListDesc * liste;
- unsigned nrElems;
- unsigned sizeElem;
- {
- unsigned newSize;
-
- newSize = nrElems * sizeElem;
- if( newSize > liste->nrBytes) {
- newSize = ( newSize + BLOCK_SIZE) & ( ~ (BLOCK_SIZE -1));
- SetHandleSize( liste->liste, (Size)newSize);
- if( MemError())
- SysErr( MemError(), 0);
- liste->nrBytes = newSize;
- }
- liste->size = nrElems;
- } /* SizeListe() */
-
-
- SysErr( err, type)
- {
- fprintf( stderr, "\nMemory allocation error, code= %d", err);
- exit( 1);
- }
-
-
-
- SizeTempo( size)
- {
- SizeList( &tempoList, size, sizeof( TempoEvent));
- } /* SizeTempo() */
-
- SizePitch( voice, size)
- {
- SizeList( &pitchList[ voice], size, sizeof( PitchEvent));
- } /* SizePitch() */
-
- SizeInstrum( voice, size)
- {
- SizeList( &instrumList[ voice], size, sizeof( InstrumEvent));
- } /* SizeInstrum() */
-
- SizeVolume( voice, size)
- {
- SizeList( &volumeList[ voice], size, sizeof( VolumeEvent));
- } /* SizeVolume() */
-
- SizeNote( voice, size)
- {
- SizeList( ¬eList[ voice], size, sizeof( NoteEvent));
- } /* SizeNote() */
-
- SizeTimbre( size)
- {
- SizeList( &timbreList, size, sizeof( TimbreDef));
- } /* SizeTimbre() */
-
-
-
- TempoEvent * TempoPtr( pos)
- {
- return ( TempoEvent *) *tempoList.liste + pos;
- } /* TempoPtr() */
-
- VolumeEvent * VolumePtr( voice, pos)
- {
- return ( VolumeEvent *) *volumeList[ voice].liste + pos;
- } /* VolumePtr() */
-
- PitchEvent * PitchPtr( voice, pos)
- {
- return ( PitchEvent *) *pitchList[ voice].liste + pos;
- } /* PitchPtr() */
-
- InstrumEvent * InstrumPtr( voice, pos)
- {
- return ( InstrumEvent *) *instrumList[ voice].liste + pos;
- } /* InstrumPtr() */
-
- NoteEvent * NotePtr( voice, pos)
- {
- return ( NoteEvent *) *noteList[ voice].liste + pos;
- } /* NotePtr() */
-
- TimbreDef * TimbrePtr( pos)
- {
- return ( TimbreDef *) *timbreList.liste + pos;
- } /* TimbrePtr() */
-
-
-
-
- int MyLoadMelo( fileName)
- char * fileName;
- {
- int fileId, i;
- char buffer[ 255];
-
- pitchBRange = 1;
-
- strcpy( buffer, fileName);
- /* strcat( buffer, musicFileExtension); */
- fileId = open( buffer, O_RDONLY + O_RAW);
- if( fileId == -1)
- return 0;
-
- duree_piece = 0;
-
- if( 4 != read( fileId, buffer, 4)) /* skip file version, major & minor */
- return 0;
- if( 40 != read( fileId, buffer, 40)) /* skip filler field */
- return 0;
- if( 2 != read( fileId, &srcTickBeat, 2))
- return 0;
- if( 2 != read( fileId, &beatMeasure, 2))
- return 0;
- if( 5 != read( fileId, buffer, 5)) /* skip Y scale, X scale & filer */
- return 0;
- if( 1 != read( fileId, ¬PercusMode, 1))
- return 0;
- if( (90 + 38 + 15) != read( fileId, buffer, 90 + 38 + 15))
- return 0; /* skip 3 filler field */
- if( 4 != read( fileId, &basicTempo, 4))
- return 0;
- if( ! LoadTempo( fileId))
- return 0;
-
- for( i = 0; i < NR_VOICES; i++) {
- if( 15 != read( fileId, buffer, 15)) /* skip filler */
- return 0;
- if( ! LoadNotes( fileId, i))
- return 0;
- if( 15 != read( fileId, buffer, 15))
- return 0;
- if( ! LoadInstrumEvt( fileId, i))
- return 0;
- if( 15 != read( fileId, buffer, 15))
- return 0;
- if( ! LoadVolume( fileId, i))
- return 0;
- if( 15 != read( fileId, buffer, 15))
- return 0;
- if( ! LoadPitch( fileId, i))
- return 0;
- }
- LisMidiData( fileId);
- close( fileId);
- return 1;
- } /* MyLoadMelo() */
-
-
-
- int LoadPitch( fileId, voice)
- {
- int size, i, ok;
- PitchEvent * pEvent;
-
- if( 2 != read( fileId, &size, 2))
- return 0;
- SizePitch( voice, size);
- pEvent = PitchPtr( voice, 0);
- ok = 1;
- for( i = 0; i < size && ok; i++, pEvent++)
- ok = ( 6 == read( fileId, pEvent, 6));
- return ok;
- } /* LoadPitch() */
-
-
- int LoadVolume( fileId, voice)
- {
- int size, i, ok;
- VolumeEvent * vEvent;
-
- if( 2 != read( fileId, &size, 2))
- return 0;
- SizeVolume( voice, size);
- vEvent = VolumePtr( voice, 0);
- ok = 1;
- for( i = 0; i < size && ok; i++, vEvent++) {
- ok = ( 6 == read( fileId, vEvent, 6));
- }
- return ok;
- } /* LoadVolume() */
-
-
-
-
- int LoadInstrumEvt( fileId, voice)
- {
- int size, ok, i;
- InstrumEvent * iEvent;
-
- if( 2 != read( fileId, &size, 2))
- return 0;
- ok = 1;
- SizeInstrum( voice, size);
- iEvent = InstrumPtr( voice, 0);
- for( i = 0; i < size && ok; i++, iEvent++)
- ok = ( 14 == read( fileId, iEvent, 14));
- return ok;
- } /* LoadInstrumEvt() */
-
-
-
-
- int LoadNotes( fileId, voice)
- {
- NoteEvent * nEvent;
- Time time, lastTime;
- int count, ok;
-
- time = 0;
- if( 2 != read( fileId, &lastTime, 2))
- return 0;
- ok = 1;
- count = 0;
- SizeNote( voice, count);
- while( time < lastTime && ok ) {
- SizeNote( voice, count + 1);
- nEvent = NotePtr( voice, count);
- count++;
- ok = ( 4 == read( fileId, nEvent, 4));
- time += nEvent->duree;
- }
- duree_piece = max( duree_piece, lastTime);
- return ok;
- } /* LoadNotes() */
-
-
-
-
-
-
- int LoadTempo( fileId)
- {
- int size, i, ok;
- TempoEvent * tEvent;
-
- if( 2 != read( fileId, &size, 2))
- return 0;
-
- SizeTempo( size);
- tEvent = TempoPtr( 0);
- ok = 1;
- for( i = 0; i < size && ok; i++, tEvent++) {
- ok = ( 6 == read( fileId, tEvent, 6));
- }
- return ok;
- } /* LoadTempo() */
-
-
-
- /*
- If the .ROL file was written by the "Visual Composer/MIDI Supplement",
- the pitch bend range is read from the file.
- */
- LisMidiData( fileId)
- {
- struct midi_vars midiParam;
- int i;
-
- midiParam.midiVersion_ = 0;
- read( fileId, &midiParam, sizeof( struct midi_vars));
- if( midiParam.midiVersion_) {
- /* le fichier contient le data MIDI ... */
- pitchBRange = midiParam.pitchRange_;
- }
- } /* LisMidiData() */
-
-
- /*
- For each timbre reference in the .ROL file, search the index
- of the bank file (.SND) for the timbre. If it exists, get the relative
- position of the definition, if not, search in the current directory for
- the timbre, and add it to the end of the bank file. The relative position
- is the value saved with the command PROGRAM-CHANGE in the .MUS file.
-
- If the timbre is not found, a warning message is printed on the screen,
- and the timbre reference value is set to 0 ( first timbre of bank).
- */
- LoadTimbres()
- {
- int voice, j, k, ok, nrDefs, fileId, timbPos;
- int timbreDef[ TIMBRE_DEF_LEN];
- InstrumEvent * iEvent;
- char fileN[ 80];
- char buff[ 10];
-
- for( voice = 0; voice < NR_VOICES; voice++) {
- iEvent = InstrumPtr( voice, 0);
- for( j = instrumList[ voice].size; j; j--, iEvent++) {
- iEvent->timbreIndex = 0; /* the first, by default */
-
- if( GetTimbre( iEvent->instrumName, &timbPos, timbreDef, timbBank))
- iEvent->timbreIndex = timbPos;
- else {
- setmem( timbreDef, TIMBRE_DEF_SIZE, 0);
- strcpy( fileN, iEvent->instrumName);
- strcat( fileN, instrumFileExtension);
- fileId = open( fileN, O_RDONLY + O_RAW);
- if( fileId != -1) {
- read( fileId, buff, 2); /* skip instrum header */
- read( fileId, timbreDef, TIMBRE_DEF_SIZE);
- close( fileId);
- AddTimbre( iEvent->instrumName, &timbPos, timbreDef, timbBank);
- iEvent->timbreIndex = timbPos;
- }
- else {
- fprintf( stderr, "\nInstrument not found: %s", fileN);
- }
- }
- }
- }
- } /* LoadTimbres() */
-
-
-
-
-
-
-
-