# src/fluid_midi.c

    00001 /* FluidSynth - A Software Synthesizer
    00002  *
    00003  * Copyright (C) 2003  Peter Hanappe and others.
    00004  *
    00005  * This library is free software; you can redistribute it and/or
    00006  * modify it under the terms of the GNU Library General Public License
    00007  * as published by the Free Software Foundation; either version 2 of
    00008  * the License, or (at your option) any later version.
    00009  *
    00010  * This library is distributed in the hope that it will be useful, but
    00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013  * Library General Public License for more details.
    00014  *
    00015  * You should have received a copy of the GNU Library General Public
    00016  * License along with this library; if not, write to the Free
    00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    00018  * 02111-1307, USA
    00019  */
    00020
    00021 #include "fluid_midi.h"
    00022 #include "fluid_sys.h"
    00023 #include "fluid_synth.h"
    00024 #include "fluid_settings.h"
    00025
    00026 /* all outgoing user messages are stored in a global text buffer */
    00027 #define MIDI_MESSAGE_LENGTH 1024
    00028 char midi_message_buffer[MIDI_MESSAGE_LENGTH];
    00029
    00030
    00031 /* Taken from Nagano Daisuke's USB-MIDI driver */
    00032
    00033 static int remains_f0f6[] = {
    00034         0,
    00035         2,
    00036         3,
    00037         2,
    00038         2,
    00039         2,
    00040         1
    00041 };
    00042
    00043 static int remains_80e0[] = {
    00044         3,
    00045         3,
    00046         3,
    00047         3,
    00048         2,
    00049         2,
    00050         3
    00051 };
    00052
    00053
    00054 /***************************************************************
    00055  *
    00056  *                      MIDIFILE
    00057  */
    00058
    00065 fluid_midi_file* new_fluid_midi_file(char* filename)
    00066 {
    00067         fluid_midi_file* mf;
    00068
    00069         mf = FLUID_NEW(fluid_midi_file);
    00070         if (mf == NULL) {
    00071                 FLUID_LOG(FLUID_ERR, "Out of memory");
    00072                 return NULL;
    00073         }
    00074         FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file));
    00075
    00076         mf->c = -1;
    00077         mf->running_status = -1;
    00078         mf->fp = FLUID_FOPEN(filename, "rb");
    00079
    00080         if (mf->fp == NULL) {
    00081                 FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
    00082                 FLUID_FREE(mf);
    00083                 return NULL;
    00084         }
    00085
    00086         if (fluid_midi_file_read_mthd(mf) != FLUID_OK) {
    00087                 FLUID_FREE(mf);
    00088                 return NULL;
    00089         }
    00090         return mf;
    00091 }
    00092
    00098 void delete_fluid_midi_file(fluid_midi_file* mf)
    00099 {
    00100         if (mf == NULL) {
    00101                 return;
    00102         }
    00103         if (mf->fp != NULL) {
    00104                 FLUID_FCLOSE(mf->fp);
    00105         }
    00106         FLUID_FREE(mf);
    00107         return;
    00108 }
    00109
    00110 /*
    00111  * Get the next byte in a MIDI file.
    00112  */
    00113 int fluid_midi_file_getc(fluid_midi_file* mf)
    00114 {
    00115         unsigned char c;
    00116         int n;
    00117         if (mf->c >= 0) {
    00118                 c = mf->c;
    00119                 mf->c = -1;
    00120         } else {
    00121                 n = FLUID_FREAD(&c, 1, 1, mf->fp);
    00122                 mf->trackpos++;
    00123         }
    00124         return (int) c;
    00125 }
    00126
    00127 /*
    00128  * fluid_midi_file_push
    00129  */
    00130 int fluid_midi_file_push(fluid_midi_file* mf, int c)
    00131 {
    00132         mf->c = c;
    00133         return FLUID_OK;
    00134 }
    00135
    00136 /*
    00137  * fluid_midi_file_read
    00138  */
    00139 int fluid_midi_file_read(fluid_midi_file* mf, void* buf, int len)
    00140 {
    00141         int num = FLUID_FREAD(buf, 1, len, mf->fp);
    00142         mf->trackpos += num;
    00143 #if DEBUG
    00144         if (num != len) {
    00145                 FLUID_LOG(FLUID_DBG, "Coulnd't read the requested number of bytes");
    00146         }
    00147 #endif
    00148         return (num != len)? FLUID_FAILED : FLUID_OK;
    00149 }
    00150
    00151 /*
    00152  * fluid_midi_file_skip
    00153  */
    00154 int fluid_midi_file_skip(fluid_midi_file* mf, int skip)
    00155 {
    00156         int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR);
    00157         if (err) {
    00158                 FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
    00159                 return FLUID_FAILED;
    00160         }
    00161         return FLUID_OK;
    00162 }
    00163
    00164 /*
    00165  * fluid_midi_file_read_mthd
    00166  */
    00167 int fluid_midi_file_read_mthd(fluid_midi_file* mf)
    00168 {
    00169         char mthd[15];
    00170         if (fluid_midi_file_read(mf, mthd, 14) != FLUID_OK) {
    00171                 return FLUID_FAILED;
    00172         }
    00173         if ((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6) || (mthd[9] > 2)) {
    00174                 FLUID_LOG(FLUID_ERR, "Doesn't look like a MIDI file: invalid MThd header");
    00175                 return FLUID_FAILED;
    00176         }
    00177         mf->type = mthd[9];
    00178         mf->ntracks = (unsigned) mthd[11];
    00179         mf->ntracks += (unsigned int) (mthd[10]) << 16;
    00180         if((mthd[12]) < 0){
    00181                 mf->uses_smpte = 1;
    00182                 mf->smpte_fps = -mthd[12];
    00183                 mf->smpte_res = (unsigned) mthd[13];
    00184                 FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet");
    00185                 return FLUID_FAILED;
    00186         } else {
    00187                 mf->uses_smpte = 0;
    00188                 mf->division = (mthd[12] << 8) | (mthd[13] & 0xff);
    00189                 FLUID_LOG(FLUID_DBG, "Division=%d", mf->division);
    00190         }
    00191         return FLUID_OK;
    00192 }
    00193
    00194 /*
    00195  * fluid_midi_file_load_tracks
    00196  */
    00197 int fluid_midi_file_load_tracks(fluid_midi_file* mf, fluid_player_t* player)
    00198 {
    00199         int i;
    00200         for (i = 0; i < mf->ntracks; i++) {
    00201                 if (fluid_midi_file_read_track(mf, player, i) != FLUID_OK) {
    00202                         return FLUID_FAILED;
    00203                 }
    00204         }
    00205         return FLUID_OK;
    00206 }
    00207
    00208 /*
    00209  * fluid_isasciistring
    00210  */
    00211 int fluid_isasciistring(char* s)
    00212 {
    00213         int i;
    00214         int len = (int) FLUID_STRLEN(s);
    00215         for (i = 0; i < len; i++) {
    00216                 if (!fluid_isascii(s[i])) {
    00217                         return 0;
    00218                 }
    00219         }
    00220         return 1;
    00221 }
    00222
    00223 /*
    00224  * fluid_getlength
    00225  */
    00226 long fluid_getlength(unsigned char *s)
    00227 {
    00228         long i = 0;
    00229         i = s[3] | (s[2]<<8) | (s[1]<<16) | (s[0]<<24);
    00230         return i;
    00231 }
    00232
    00233 /*
    00234  * fluid_midi_file_read_tracklen
    00235  */
    00236 int fluid_midi_file_read_tracklen(fluid_midi_file* mf)
    00237 {
    00238         unsigned char length[5];
    00239         if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) {
    00240                 return FLUID_FAILED;
    00241         }
    00242         mf->tracklen = fluid_getlength(length);
    00243         mf->trackpos = 0;
    00244         mf->eot = 0;
    00245         return FLUID_OK;
    00246 }
    00247
    00248 /*
    00249  * fluid_midi_file_eot
    00250  */
    00251 int fluid_midi_file_eot(fluid_midi_file* mf)
    00252 {
    00253 #if DEBUG
    00254         if (mf->trackpos > mf->tracklen) {
    00255                 printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen);
    00256         }
    00257 #endif
    00258         return mf->eot || (mf->trackpos >= mf->tracklen);
    00259 }
    00260
    00261 /*
    00262  * fluid_midi_file_read_track
    00263  */
    00264 int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int num)
    00265 {
    00266         fluid_track_t* track;
    00267         unsigned char id[5], length[5];
    00268         int found_track = 0;
    00269         int skip;
    00270
    00271         if (fluid_midi_file_read(mf, id, 4) != FLUID_OK) {
    00272                 return FLUID_FAILED;
    00273         }
    00274         id[4]='\0';
    00275
    00276         while (!found_track){
    00277
    00278                 if (fluid_isasciistring((char*) id) == 0) {
    00279                         FLUID_LOG(FLUID_ERR, "An non-ascii track header found, currupt file");
    00280                         return FLUID_FAILED;
    00281
    00282                 } else if (strcmp((char*) id, "MTrk") == 0) {
    00283
    00284                         found_track = 1;
    00285
    00286                         if (fluid_midi_file_read_tracklen(mf) != FLUID_OK) {
    00287                                 return FLUID_FAILED;
    00288                         }
    00289
    00290                         track = new_fluid_track(num);
    00291                         if (track == NULL) {
    00292                                 FLUID_LOG(FLUID_ERR, "Out of memory");
    00293                                 return FLUID_FAILED;
    00294                         }
    00295
    00296                         while (!fluid_midi_file_eot(mf)) {
    00297                                 if (fluid_midi_file_read_event(mf, track) != FLUID_OK) {
    00298                                         return FLUID_FAILED;
    00299                                 }
    00300                         }
    00301
    00302                         fluid_player_add_track(player, track);
    00303
    00304                 } else {
    00305                         found_track = 0;
    00306                         if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) {
    00307                                 return FLUID_FAILED;
    00308                         }
    00309                         skip = fluid_getlength(length);
    00310 /*        fseek(mf->fp, skip, SEEK_CUR); */
    00311                         if (fluid_midi_file_skip(mf, skip) != FLUID_OK) {
    00312                                 return FLUID_FAILED;
    00313                         }
    00314                 }
    00315         }
    00316         if (feof(mf->fp)) {
    00317                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00318                 return FLUID_FAILED;
    00319         }
    00320         return FLUID_OK;
    00321 }
    00322
    00323 /*
    00324  * fluid_midi_file_read_varlen
    00325  */
    00326 int fluid_midi_file_read_varlen(fluid_midi_file* mf)
    00327 {
    00328         int i;
    00329         int c;
    00330         mf->varlen = 0;
    00331         for (i = 0;;i++) {
    00332                 if (i == 4) {
    00333                         FLUID_LOG(FLUID_ERR, "Invalid variable length number");
    00334                         return FLUID_FAILED;
    00335                 }
    00336                 c = fluid_midi_file_getc(mf);
    00337                 if (c < 0) {
    00338                         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00339                         return FLUID_FAILED;
    00340                 }
    00341                 if (c & 0x80){
    00342                         mf->varlen |= (int) (c & 0x7F);
    00343                         mf->varlen <<= 7;
    00344                 } else {
    00345                         mf->varlen += c;
    00346                         break;
    00347                 }
    00348         }
    00349         return FLUID_OK;
    00350 }
    00351
    00352 /*
    00353  * fluid_midi_file_read_event
    00354  */
    00355 int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
    00356 {
    00357         int dtime;
    00358         int status;
    00359         int type;
    00360         int tempo;
    00361         unsigned char* metadata = NULL;
    00362         unsigned char* dyn_buf = NULL;
    00363         unsigned char static_buf[256];
    00364         int nominator, denominator, clocks, notes, sf, mi;
    00365         fluid_midi_event_t* evt;
    00366         int channel = 0;
    00367         int param1 = 0;
    00368         int param2 = 0;
    00369
    00370         /* read the delta-time of the event */
    00371         if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
    00372                 return FLUID_FAILED;
    00373         }
    00374         dtime = mf->varlen;
    00375
    00376         /* read the status byte */
    00377         status = fluid_midi_file_getc(mf);
    00378         if (status < 0) {
    00379                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00380                 return FLUID_FAILED;
    00381         }
    00382
    00383         /* not a valid status byte: use the running status instead */
    00384         if ((status & 0x80) == 0) {
    00385                 if ((mf->running_status & 0x80) == 0) {
    00386                         FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status");
    00387                         return FLUID_FAILED;
    00388                 }
    00389                 fluid_midi_file_push(mf, status);
    00390                 status = mf->running_status;
    00391         }
    00392
    00393         /* check what message we have */
    00394         if (status & 0x80) {
    00395                 mf->running_status = status;
    00396
    00397                 if ((status == MIDI_SYSEX) || (status == MIDI_EOX)) {     /* system exclusif */
    00398                         /*
    00399                          * Sysex messages are not handled yet
    00400                          */
    00401                         /* read the length of the message */
    00402                         if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
    00403                                 return FLUID_FAILED;
    00404                         }
    00405
    00406                         if (mf->varlen) {
    00407
    00408                                 if (mf->varlen < 255) {
    00409                                         metadata = &static_buf[0];
    00410                                 } else {
    00411                                         FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen);
    00412                                         dyn_buf = FLUID_MALLOC(mf->varlen + 1);
    00413                                         if (dyn_buf == NULL) {
    00414                                                 FLUID_LOG(FLUID_PANIC, "Out of memory");
    00415                                                 return FLUID_FAILED;
    00416                                         }
    00417                                         metadata = dyn_buf;
    00418                                 }
    00419
    00420                                 /* read the data of the message */
    00421                                 if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) {
    00422                                         if (dyn_buf) {
    00423                                                 FLUID_FREE(dyn_buf);
    00424                                         }
    00425                                         return FLUID_FAILED;
    00426                                 }
    00427
    00428                                 if (dyn_buf) {
    00429                                         FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
    00430                                         FLUID_FREE(dyn_buf);
    00431                                 }
    00432                         }
    00433
    00434                         return FLUID_OK;
    00435
    00436                 } else if (status == MIDI_META_EVENT) {             /* meta events */
    00437
    00438                         int result = FLUID_OK;
    00439
    00440                         /* get the type of the meta message */
    00441                         type = fluid_midi_file_getc(mf);
    00442                         if (type < 0) {
    00443                                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00444                                 return FLUID_FAILED;
    00445                         }
    00446
    00447                         /* get the length of the data part */
    00448                         if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
    00449                                 return FLUID_FAILED;
    00450                         }
    00451
    00452                         if (mf->varlen < 255) {
    00453                                 metadata = &static_buf[0];
    00454                         } else {
    00455                                 FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen);
    00456                                 dyn_buf = FLUID_MALLOC(mf->varlen + 1);
    00457                                 if (dyn_buf == NULL) {
    00458                                         FLUID_LOG(FLUID_PANIC, "Out of memory");
    00459                                         return FLUID_FAILED;
    00460                                 }
    00461                                 metadata = dyn_buf;
    00462                         }
    00463
    00464                         /* read the data */
    00465                         if (mf->varlen)
    00466                         {
    00467                                 if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) {
    00468                                         if (dyn_buf) {
    00469                                                 FLUID_FREE(dyn_buf);
    00470                                         }
    00471                                         return FLUID_FAILED;
    00472                                 }
    00473                         }
    00474
    00475                         /* handle meta data */
    00476                         switch (type) {
    00477
    00478                         case MIDI_COPYRIGHT:
    00479                                 metadata[mf->varlen] = 0;
    00480                                 break;
    00481
    00482                         case MIDI_TRACK_NAME:
    00483                                 metadata[mf->varlen] = 0;
    00484                                 fluid_track_set_name(track, (char*) metadata);
    00485                                 break;
    00486
    00487                         case MIDI_INST_NAME:
    00488                                 metadata[mf->varlen] = 0;
    00489                                 break;
    00490
    00491                         case MIDI_LYRIC:
    00492                                 break;
    00493
    00494                         case MIDI_MARKER:
    00495                                 break;
    00496
    00497                         case MIDI_CUE_POINT:
    00498                                 break; /* don't care much for text events */
    00499
    00500                         case MIDI_EOT:
    00501                                 if (mf->varlen != 0) {
    00502                                         FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event");
    00503                                         result = FLUID_FAILED;
    00504                                         break;
    00505                                 }
    00506                                 mf->eot = 1;
    00507                                 break;
    00508
    00509                         case MIDI_SET_TEMPO:
    00510                                 if (mf->varlen != 3) {
    00511                                         FLUID_LOG(FLUID_ERR, "Invalid length for SetTempo meta event");
    00512                                         result = FLUID_FAILED;
    00513                                         break;
    00514                                 }
    00515                                 tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
    00516                                 evt = new_fluid_midi_event();
    00517                                 if (evt == NULL) {
    00518                                         FLUID_LOG(FLUID_ERR, "Out of memory");
    00519                                         result = FLUID_FAILED;
    00520                                         break;
    00521                                 }
    00522                                 evt->dtime = dtime;
    00523                                 evt->type = MIDI_SET_TEMPO;
    00524                                 evt->channel = 0;
    00525                                 evt->param1 = tempo;
    00526                                 evt->param2 = 0;
    00527                                 fluid_track_add_event(track, evt);
    00528                                 break;
    00529
    00530                         case MIDI_SMPTE_OFFSET:
    00531                                 if (mf->varlen != 5) {
    00532                                         FLUID_LOG(FLUID_ERR, "Invalid length for SMPTE Offset meta event");
    00533                                         result = FLUID_FAILED;
    00534                                         break;
    00535                                 }
    00536                                 break; /* we don't use smtp */
    00537
    00538                         case MIDI_TIME_SIGNATURE:
    00539                                 if (mf->varlen != 4) {
    00540                                         FLUID_LOG(FLUID_ERR, "Invalid length for TimeSignature meta event");
    00541                                         result = FLUID_FAILED;
    00542                                         break;
    00543                                 }
    00544                                 nominator = metadata[0];
    00545                                 denominator = pow(2.0, (double) metadata[1]);
    00546                                 clocks = metadata[2];
    00547                                 notes = metadata[3];
    00548
    00549                                 FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d",
    00550                                           nominator, denominator, clocks, notes);
    00551
    00552                                 break;
    00553
    00554                         case MIDI_KEY_SIGNATURE:
    00555                                 if (mf->varlen != 2) {
    00556                                         FLUID_LOG(FLUID_ERR, "Invalid length for KeySignature meta event");
    00557                                         result = FLUID_FAILED;
    00558                                         break;
    00559                                 }
    00560                                 sf = metadata[0];
    00561                                 mi = metadata[1];
    00562                                 break;
    00563
    00564                         case MIDI_SEQUENCER_EVENT:
    00565                                 break;
    00566
    00567                         default:
    00568                                 break;
    00569                         }
    00570
    00571                         if (dyn_buf) {
    00572                                 FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
    00573                                 FLUID_FREE(dyn_buf);
    00574                         }
    00575
    00576                         return result;
    00577
    00578                 } else {                /* channel messages */
    00579
    00580                         type = status & 0xf0;
    00581                         channel = status & 0x0f;
    00582
    00583                         /* all channel message have at least 1 byte of associated data */
    00584                         if ((param1 = fluid_midi_file_getc(mf)) < 0) {
    00585                                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00586                                 return FLUID_FAILED;
    00587                         }
    00588
    00589                         switch (type) {
    00590
    00591                         case NOTE_ON:
    00592                                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
    00593                                         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00594                                         return FLUID_FAILED;
    00595                                 }
    00596                                 break;
    00597
    00598                         case NOTE_OFF:
    00599                                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
    00600                                         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00601                                         return FLUID_FAILED;
    00602                                 }
    00603                                 break;
    00604
    00605                         case KEY_PRESSURE:
    00606                                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
    00607                                         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00608                                         return FLUID_FAILED;
    00609                                 }
    00610                                 break;
    00611
    00612                         case CONTROL_CHANGE:
    00613                                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
    00614                                         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00615                                         return FLUID_FAILED;
    00616                                 }
    00617                                 break;
    00618
    00619                         case PROGRAM_CHANGE:
    00620                                 break;
    00621
    00622                         case CHANNEL_PRESSURE:
    00623                                 break;
    00624
    00625                         case PITCH_BEND:
    00626                                 if ((param2 = fluid_midi_file_getc(mf)) < 0) {
    00627                                         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
    00628                                         return FLUID_FAILED;
    00629                                 }
    00630
    00631                                 param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
    00632                                 param2 = 0;
    00633                                 break;
    00634
    00635                         default:
    00636                                 /* Can't possibly happen !? */
    00637                                 FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
    00638                                 return FLUID_FAILED;
    00639                         }
    00640                         evt = new_fluid_midi_event();
    00641                         if (evt == NULL) {
    00642                                 FLUID_LOG(FLUID_ERR, "Out of memory");
    00643                                 return FLUID_FAILED;
    00644                         }
    00645                         evt->dtime = dtime;
    00646                         evt->type = type;
    00647                         evt->channel = channel;
    00648                         evt->param1 = param1;
    00649                         evt->param2 = param2;
    00650                         fluid_track_add_event(track, evt);
    00651                 }
    00652         }
    00653         return FLUID_OK;
    00654 }
    00655
    00656 /*
    00657  * fluid_midi_file_get_division
    00658  */
    00659 int fluid_midi_file_get_division(fluid_midi_file* midifile)
    00660 {
    00661         return midifile->division;
    00662 }
    00663
    00664 /******************************************************
    00665  *
    00666  *     fluid_track_t
    00667  */
    00668
    00673 fluid_midi_event_t* new_fluid_midi_event()
    00674 {
    00675         fluid_midi_event_t* evt;
    00676         evt = FLUID_NEW(fluid_midi_event_t);
    00677         if (evt == NULL) {
    00678                 FLUID_LOG(FLUID_ERR, "Out of memory");
    00679                 return NULL;
    00680         }
    00681         evt->dtime = 0;
    00682         evt->type = 0;
    00683         evt->channel = 0;
    00684         evt->param1 = 0;
    00685         evt->param2 = 0;
    00686         evt->next = NULL;
    00687         return evt;
    00688 }
    00689
    00695 int delete_fluid_midi_event(fluid_midi_event_t* evt)
    00696 {
    00697         fluid_midi_event_t *temp;
    00698
    00699         while (evt)
    00700         {
    00701                 temp = evt->next;
    00702                 FLUID_FREE(evt);
    00703                 evt = temp;
    00704         }
    00705         return FLUID_OK;
    00706 }
    00707
    00714 int fluid_midi_event_get_type(fluid_midi_event_t* evt)
    00715 {
    00716         return evt->type;
    00717 }
    00718
    00726 int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
    00727 {
    00728         evt->type = type;
    00729         return FLUID_OK;
    00730 }
    00731
    00737 int fluid_midi_event_get_channel(fluid_midi_event_t* evt)
    00738 {
    00739         return evt->channel;
    00740 }
    00741
    00748 int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
    00749 {
    00750         evt->channel = chan;
    00751         return FLUID_OK;
    00752 }
    00753
    00759 int fluid_midi_event_get_key(fluid_midi_event_t* evt)
    00760 {
    00761         return evt->param1;
    00762 }
    00763
    00770 int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
    00771 {
    00772         evt->param1 = v;
    00773         return FLUID_OK;
    00774 }
    00775
    00781 int fluid_midi_event_get_velocity(fluid_midi_event_t* evt)
    00782 {
    00783         return evt->param2;
    00784 }
    00785
    00792 int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
    00793 {
    00794         evt->param2 = v;
    00795         return FLUID_OK;
    00796 }
    00797
    00803 int fluid_midi_event_get_control(fluid_midi_event_t* evt)
    00804 {
    00805         return evt->param1;
    00806 }
    00807
    00814 int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
    00815 {
    00816         evt->param1 = v;
    00817         return FLUID_OK;
    00818 }
    00819
    00825 int fluid_midi_event_get_value(fluid_midi_event_t* evt)
    00826 {
    00827         return evt->param2;
    00828 }
    00829
    00836 int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
    00837 {
    00838         evt->param2 = v;
    00839         return FLUID_OK;
    00840 }
    00841
    00847 int fluid_midi_event_get_program(fluid_midi_event_t* evt)
    00848 {
    00849         return evt->param1;
    00850 }
    00851
    00858 int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val)
    00859 {
    00860         evt->param1 = val;
    00861         return FLUID_OK;
    00862 }
    00863
    00869 int fluid_midi_event_get_pitch(fluid_midi_event_t* evt)
    00870 {
    00871         return evt->param1;
    00872 }
    00873
    00880 int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val)
    00881 {
    00882         evt->param1 = val;
    00883         return FLUID_OK;
    00884 }
    00885
    00886 /*
    00887  * fluid_midi_event_get_param1
    00888  */
    00889 /* int fluid_midi_event_get_param1(fluid_midi_event_t* evt) */
    00890 /* { */
    00891 /*   return evt->param1; */
    00892 /* } */
    00893
    00894 /*
    00895  * fluid_midi_event_set_param1
    00896  */
    00897 /* int fluid_midi_event_set_param1(fluid_midi_event_t* evt, int v) */
    00898 /* { */
    00899 /*   evt->param1 = v; */
    00900 /*   return FLUID_OK; */
    00901 /* } */
    00902
    00903 /*
    00904  * fluid_midi_event_get_param2
    00905  */
    00906 /* int fluid_midi_event_get_param2(fluid_midi_event_t* evt) */
    00907 /* { */
    00908 /*   return evt->param2; */
    00909 /* } */
    00910
    00911 /*
    00912  * fluid_midi_event_set_param2
    00913  */
    00914 /* int fluid_midi_event_set_param2(fluid_midi_event_t* evt, int v) */
    00915 /* { */
    00916 /*   evt->param2 = v; */
    00917 /*   return FLUID_OK; */
    00918 /* } */
    00919
    00920 /******************************************************
    00921  *
    00922  *     fluid_track_t
    00923  */
    00924
    00925 /*
    00926  * new_fluid_track
    00927  */
    00928 fluid_track_t* new_fluid_track(int num)
    00929 {
    00930         fluid_track_t* track;
    00931         track = FLUID_NEW(fluid_track_t);
    00932         if (track == NULL) {
    00933                 return NULL;
    00934         }
    00935         track->name = NULL;
    00936         track->num = num;
    00937         track->first = NULL;
    00938         track->cur = NULL;
    00939         track->last = NULL;
    00940         track->ticks = 0;
    00941         return track;
    00942 }
    00943
    00944 /*
    00945  * delete_fluid_track
    00946  */
    00947 int delete_fluid_track(fluid_track_t* track)
    00948 {
    00949         if (track->name != NULL) {
    00950                 FLUID_FREE(track->name);
    00951         }
    00952         if (track->first != NULL) {
    00953                 delete_fluid_midi_event(track->first);
    00954         }
    00955         FLUID_FREE(track);
    00956         return FLUID_OK;
    00957 }
    00958
    00959 /*
    00960  * fluid_track_set_name
    00961  */
    00962 int fluid_track_set_name(fluid_track_t* track, char* name)
    00963 {
    00964         int len;
    00965         if (track->name != NULL) {
    00966                 FLUID_FREE(track->name);
    00967         }
    00968         if (name == NULL) {
    00969                 track->name = NULL;
    00970                 return FLUID_OK;
    00971         }
    00972         len = FLUID_STRLEN(name);
    00973         track->name = FLUID_MALLOC(len + 1);
    00974         if (track->name == NULL) {
    00975                 FLUID_LOG(FLUID_ERR, "Out of memory");
    00976                 return FLUID_FAILED;
    00977         }
    00978         FLUID_STRCPY(track->name, name);
    00979         return FLUID_OK;
    00980 }
    00981
    00982 /*
    00983  * fluid_track_get_name
    00984  */
    00985 char* fluid_track_get_name(fluid_track_t* track)
    00986 {
    00987         return track->name;
    00988 }
    00989
    00990 /*
    00991  * fluid_track_get_duration
    00992  */
    00993 int fluid_track_get_duration(fluid_track_t* track)
    00994 {
    00995         int time = 0;
    00996         fluid_midi_event_t* evt = track->first;
    00997         while (evt != NULL) {
    00998                 time += evt->dtime;
    00999                 evt = evt->next;
    01000         }
    01001         return time;
    01002 }
    01003
    01004 /*
    01005  * fluid_track_count_events
    01006  */
    01007 int fluid_track_count_events(fluid_track_t* track, int* on, int* off)
    01008 {
    01009         fluid_midi_event_t* evt = track->first;
    01010         while (evt != NULL) {
    01011                 if (evt->type == NOTE_ON) {
    01012                         (*on)++;
    01013                 } else if (evt->type == NOTE_OFF) {
    01014                         (*off)++;
    01015                 }
    01016                 evt = evt->next;
    01017         }
    01018         return FLUID_OK;
    01019 }
    01020
    01021 /*
    01022  * fluid_track_add_event
    01023  */
    01024 int fluid_track_add_event(fluid_track_t* track, fluid_midi_event_t* evt)
    01025 {
    01026         evt->next = NULL;
    01027         if (track->first == NULL) {
    01028                 track->first = evt;
    01029                 track->cur = evt;
    01030                 track->last = evt;
    01031         } else {
    01032                 track->last->next = evt;
    01033                 track->last = evt;
    01034         }
    01035         return FLUID_OK;
    01036 }
    01037
    01038 /*
    01039  * fluid_track_first_event
    01040  */
    01041 fluid_midi_event_t* fluid_track_first_event(fluid_track_t* track)
    01042 {
    01043         track->cur = track->first;
    01044         return track->cur;
    01045 }
    01046
    01047 /*
    01048  * fluid_track_next_event
    01049  */
    01050 fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track)
    01051 {
    01052         if (track->cur != NULL) {
    01053                 track->cur = track->cur->next;
    01054         }
    01055         return track->cur;
    01056 }
    01057
    01058 /*
    01059  * fluid_track_reset
    01060  */
    01061 int
    01062 fluid_track_reset(fluid_track_t* track)
    01063 {
    01064         track->ticks = 0;
    01065         track->cur = track->first;
    01066         return FLUID_OK;
    01067 }
    01068
    01069 /*
    01070  * fluid_track_send_events
    01071  */
    01072 int
    01073 fluid_track_send_events(fluid_track_t* track,
    01074                         fluid_synth_t* synth,
    01075                         fluid_player_t* player,
    01076                         unsigned int ticks)
    01077 {
    01078         int status = FLUID_OK;
    01079         fluid_midi_event_t* event;
    01080
    01081         while (1) {
    01082
    01083                 event = track->cur;
    01084                 if (event == NULL) {
    01085                         return status;
    01086                 }
    01087
    01088 /*              printf("track=%02d\tticks=%05u\ttrack=%05u\tdtime=%05u\tnext=%05u\n", */
    01089 /*                     track->num, */
    01090 /*                     ticks, */
    01091 /*                     track->ticks, */
    01092 /*                     event->dtime, */
    01093 /*                     track->ticks + event->dtime); */
    01094
    01095                 if (track->ticks + event->dtime > ticks) {
    01096                         return status;
    01097                 }
    01098
    01099
    01100                 track->ticks += event->dtime;
    01101                 status = fluid_midi_send_event(synth, player, event);
    01102                 fluid_track_next_event(track);
    01103
    01104         }
    01105         return status;
    01106 }
    01107
    01108 /******************************************************
    01109  *
    01110  *     fluid_player
    01111  */
    01112
    01118 fluid_player_t* new_fluid_player(fluid_synth_t* synth)
    01119 {
    01120         int i;
    01121         fluid_player_t* player;
    01122         player = FLUID_NEW(fluid_player_t);
    01123         if (player == NULL) {
    01124                 FLUID_LOG(FLUID_ERR, "Out of memory");
    01125                 return NULL;
    01126         }
    01127         player->status = FLUID_PLAYER_READY;
    01128         player->loop = 0;
    01129         player->ntracks = 0;
    01130         for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) {
    01131                 player->track[i] = NULL;
    01132         }
    01133         player->synth = synth;
    01134         player->timer = NULL;
    01135         player->playlist = NULL;
    01136         player->current_file = NULL;
    01137         player->division = 0;
    01138         player->send_program_change = 1;
    01139         player->miditempo = 480000;
    01140         player->deltatime = 4.0;
    01141         return player;
    01142 }
    01143
    01149 int delete_fluid_player(fluid_player_t* player)
    01150 {
    01151         if (player == NULL) {
    01152                 return FLUID_OK;
    01153         }
    01154         fluid_player_stop(player);
    01155         fluid_player_reset(player);
    01156         FLUID_FREE(player);
    01157         return FLUID_OK;
    01158 }
    01159
    01160 int fluid_player_reset(fluid_player_t* player)
    01161 {
    01162         int i;
    01163
    01164         for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) {
    01165                 if (player->track[i] != NULL) {
    01166                         delete_fluid_track(player->track[i]);
    01167                         player->track[i] = NULL;
    01168                 }
    01169         }
    01170         player->current_file = NULL;
    01171         player->status = FLUID_PLAYER_READY;
    01172         player->loop = 0;
    01173         player->ntracks = 0;
    01174         player->division = 0;
    01175         player->send_program_change = 1;
    01176         player->miditempo = 480000;
    01177         player->deltatime = 4.0;
    01178         return 0;
    01179 }
    01180
    01181 /*
    01182  * fluid_player_add_track
    01183  */
    01184 int fluid_player_add_track(fluid_player_t* player, fluid_track_t* track)
    01185 {
    01186         if (player->ntracks < MAX_NUMBER_OF_TRACKS) {
    01187                 player->track[player->ntracks++] = track;
    01188                 return FLUID_OK;
    01189         } else {
    01190                 return FLUID_FAILED;
    01191         }
    01192 }
    01193
    01194 /*
    01195  * fluid_player_count_tracks
    01196  */
    01197 int fluid_player_count_tracks(fluid_player_t* player)
    01198 {
    01199         return player->ntracks;
    01200 }
    01201
    01202 /*
    01203  * fluid_player_get_track
    01204  */
    01205 fluid_track_t* fluid_player_get_track(fluid_player_t* player, int i)
    01206 {
    01207         if ((i >= 0) && (i < MAX_NUMBER_OF_TRACKS)) {
    01208                 return player->track[i];
    01209         } else {
    01210                 return NULL;
    01211         }
    01212 }
    01213
    01214 int fluid_player_add(fluid_player_t* player, char* midifile)
    01215 {
    01216         char *s = FLUID_STRDUP(midifile);
    01217         player->playlist = fluid_list_append(player->playlist, s);
    01218         return 0;
    01219 }
    01220
    01221 /*
    01222  * fluid_player_load
    01223  */
    01224 int fluid_player_load(fluid_player_t* player, char *filename)
    01225 {
    01226         fluid_midi_file* midifile;
    01227
    01228         midifile = new_fluid_midi_file(filename);
    01229         if (midifile == NULL) {
    01230                 return FLUID_FAILED;
    01231         }
    01232         player->division = fluid_midi_file_get_division(midifile);
    01233
    01234         /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */
    01235
    01236         if (fluid_midi_file_load_tracks(midifile, player) != FLUID_OK){
    01237                 return FLUID_FAILED;
    01238         }
    01239         delete_fluid_midi_file(midifile);
    01240         return FLUID_OK;
    01241 }
    01242
    01243 /*
    01244  * fluid_player_callback
    01245  */
    01246 int fluid_player_callback(void* data, unsigned int msec)
    01247 {
    01248         int i;
    01249         int status = FLUID_PLAYER_DONE;
    01250         fluid_player_t* player;
    01251         fluid_synth_t* synth;
    01252         player = (fluid_player_t*) data;
    01253         synth = player->synth;
    01254
    01255         /* Load the next file if necessary */
    01256         while (player->current_file == NULL) {
    01257
    01258                 if (player->playlist == NULL) {
    01259                         return 0;
    01260                 }
    01261
    01262                 fluid_player_reset(player);
    01263
    01264                 player->current_file = fluid_list_get(player->playlist);
    01265                 player->playlist = fluid_list_next(player->playlist);
    01266
    01267                 FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__, player->current_file);
    01268
    01269                 if (fluid_player_load(player, player->current_file) == FLUID_OK) {
    01270
    01271                         player->begin_msec = msec;
    01272                         player->start_msec = msec;
    01273                         player->start_ticks = 0;
    01274                         player->cur_ticks = 0;
    01275
    01276                         for (i = 0; i < player->ntracks; i++) {
    01277                                 if (player->track[i] != NULL) {
    01278                                         fluid_track_reset(player->track[i]);
    01279                                 }
    01280                         }
    01281
    01282                 } else {
    01283                         player->current_file = NULL;
    01284                 }
    01285         }
    01286
    01287         player->cur_msec = msec;
    01288         player->cur_ticks = (player->start_ticks +
    01289                              (int) ((double) (player->cur_msec - player->start_msec) / player->deltatime));
    01290
    01291         for (i = 0; i < player->ntracks; i++) {
    01292                 if (!fluid_track_eot(player->track[i])) {
    01293                         status = FLUID_PLAYER_PLAYING;
    01294                         if (fluid_track_send_events(player->track[i], synth, player, player->cur_ticks) != FLUID_OK) {
    01295                                 /* */
    01296                         }
    01297                 }
    01298         }
    01299
    01300         player->status = status;
    01301
    01302         if (player->status == FLUID_PLAYER_DONE) {
    01303                 FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec",
    01304                           __FILE__, __LINE__, (msec - player->begin_msec) / 1000.0);
    01305                 player->current_file = NULL;
    01306         }
    01307
    01308         return 1;
    01309 }
    01310
    01316 int fluid_player_play(fluid_player_t* player)
    01317 {
    01318         if (player->status == FLUID_PLAYER_PLAYING) {
    01319                 return FLUID_OK;
    01320         }
    01321
    01322         if (player->playlist == NULL) {
    01323                 return FLUID_OK;
    01324         }
    01325
    01326         player->status = FLUID_PLAYER_PLAYING;
    01327
    01328         player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback,
    01329                                         (void*) player, 1, 0);
    01330         if (player->timer == NULL) {
    01331                 return FLUID_FAILED;
    01332         }
    01333         return FLUID_OK;
    01334 }
    01335
    01341 int fluid_player_stop(fluid_player_t* player)
    01342 {
    01343         if (player->timer != NULL) {
    01344                 delete_fluid_timer(player->timer);
    01345         }
    01346         player->status = FLUID_PLAYER_DONE;
    01347         player->timer = NULL;
    01348         return FLUID_OK;
    01349 }
    01350
    01351 /* FIXME - Looping seems to not actually be implemented? */
    01352
    01359 int fluid_player_set_loop(fluid_player_t* player, int loop)
    01360 {
    01361         player->loop = loop;
    01362         return FLUID_OK;
    01363 }
    01364
    01372 int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
    01373 {
    01374         player->miditempo = tempo;
    01375         player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
    01376         player->start_msec = player->cur_msec;
    01377         player->start_ticks = player->cur_ticks;
    01378
    01379         FLUID_LOG(FLUID_DBG,"tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
    01380                   tempo, player->deltatime, player->cur_msec, player->cur_ticks);
    01381
    01382         return FLUID_OK;
    01383 }
    01384
    01391 int fluid_player_set_bpm(fluid_player_t* player, int bpm)
    01392 {
    01393         return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm));
    01394 }
    01395
    01402 int fluid_player_join(fluid_player_t* player)
    01403 {
    01404         return player->timer? fluid_timer_join(player->timer) : FLUID_OK;
    01405 }
    01406
    01407 /************************************************************************
    01408  *       MIDI PARSER
    01409  *
    01410  */
    01411
    01412 /*
    01413  * new_fluid_midi_parser
    01414  */
    01415 fluid_midi_parser_t* new_fluid_midi_parser()
    01416 {
    01417         fluid_midi_parser_t* parser;
    01418         parser = FLUID_NEW(fluid_midi_parser_t);
    01419         if (parser == NULL) {
    01420                 FLUID_LOG(FLUID_ERR, "Out of memory");
    01421                 return NULL;
    01422         }
    01423         parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */
    01424         return parser;
    01425 }
    01426
    01427 /*
    01428  * delete_fluid_midi_parser
    01429  */
    01430 int delete_fluid_midi_parser(fluid_midi_parser_t* parser)
    01431 {
    01432         FLUID_FREE(parser);
    01433         return FLUID_OK;
    01434 }
    01435
    01436 /*
    01437  * fluid_midi_parser_parse
    01438  *
    01439  * Purpose:
    01440  * The MIDI byte stream is fed into the parser, one byte at a time.
    01441  * As soon as the parser has recognized an event, it will return it.
    01442  * Otherwise it returns NULL.
    01443  */
    01444 fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigned char c)
    01445 {
    01446         /*********************************************************************/
    01447         /* 'Process' system real-time messages                               */
    01448         /*********************************************************************/
    01449         /* There are not too many real-time messages that are of interest here.
    01450          * They can occur anywhere, even in the middle of a noteon message!
    01451          * Real-time range: 0xF8 .. 0xFF
    01452          * Note: Real-time does not affect (running) status.
    01453          */
    01454         if (c >= 0xF8){
    01455                 if (c == MIDI_SYSTEM_RESET){
    01456                         parser->event.type = c;
    01457                         parser->status = 0; /* clear the status */
    01458                         return &parser->event;
    01459                 };
    01460                 return NULL;
    01461         };
    01462
    01463         /*********************************************************************/
    01464         /* 'Process' system common messages (again, just skip them)          */
    01465         /*********************************************************************/
    01466         /* There are no system common messages that are of interest here.
    01467          * System common range: 0xF0 .. 0xF7
    01468          */
    01469
    01470         if (c > 0xF0){
    01471                 /* MIDI specs say: To ignore a non-real-time message, just discard all data up to
    01472                  * the next status byte.
    01473                  * And our parser will ignore data that is received without a valid status.
    01474                  * Note: system common cancels running status. */
    01475                 parser->status = 0;
    01476                 return NULL;
    01477         };
    01478
    01479         /*********************************************************************/
    01480         /* Process voice category messages:                                  */
    01481         /*********************************************************************/
    01482         /* Now that we have handled realtime and system common messages, only
    01483          * voice messages are left.
    01484          * Only a status byte has bit # 7 set.
    01485          * So no matter the status of the parser (in case we have lost sync),
    01486          * as soon as a byte >= 0x80 comes in, we are dealing with a status byte
    01487          * and start a new event.
    01488          */
    01489
    01490         if (c & 0x80){
    01491                 parser->channel = c & 0x0F;
    01492                 parser->status = c & 0xF0;
    01493                 /* The event consumes x bytes of data... (subtract 1 for the status byte) */
    01494                 parser->nr_bytes_total=fluid_midi_event_length(parser->status)-1;
    01495                 /* of which we have read 0 at this time. */
    01496                 parser->nr_bytes = 0;
    01497                 return NULL;
    01498         };
    01499
    01500         /*********************************************************************/
    01501         /* Process data                                                      */
    01502         /*********************************************************************/
    01503         /* If we made it this far, then the received char belongs to the data
    01504          * of the last event. */
    01505         if (parser->status == 0){
    01506                 /* We are not interested in the event currently received.
    01507                  * Discard the data. */
    01508                 return NULL;
    01509         };
    01510
    01511         /* Store the first couple of bytes */
    01512         if (parser->nr_bytes < FLUID_MIDI_PARSER_MAX_PAR){
    01513                 parser->p[parser->nr_bytes]=c;
    01514         };
    01515         parser->nr_bytes++;
    01516
    01517         /* Do we still need more data to get this event complete? */
    01518         if (parser->nr_bytes < parser->nr_bytes_total){
    01519                 return NULL;
    01520         };
    01521
    01522         /*********************************************************************/
    01523         /* Send the event                                                    */
    01524         /*********************************************************************/
    01525         /* The event is ready-to-go.
    01526          * About 'running status':
    01527          * The MIDI protocol has a built-in compression mechanism. If several similar events are sent
    01528          * in-a-row, for example note-ons, then the event type is only sent once. For this case,
    01529          * the last event type (status) is remembered.
    01530          * We simply keep the status as it is, just reset
    01531          * the parameter counter. If another status byte comes in, it will overwrite the status. */
    01532         parser->event.type = parser->status;
    01533         parser->event.channel = parser->channel;
    01534         parser->nr_bytes = 0; /* Related to running status! */
    01535         switch (parser->status){
    01536         case NOTE_OFF:
    01537         case NOTE_ON:
    01538         case KEY_PRESSURE:
    01539         case CONTROL_CHANGE:
    01540         case PROGRAM_CHANGE:
    01541         case CHANNEL_PRESSURE:
    01542                 parser->event.param1 = parser->p[0]; /* For example key number */
    01543                 parser->event.param2 = parser->p[1]; /* For example velocity */
    01544                 break;
    01545         case PITCH_BEND:
    01546                 /* Pitch-bend is transmitted with 14-bit precision. */
    01547                 parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */
    01548                 break;
    01549         default:
    01550                 /* Unlikely */
    01551                 return NULL;
    01552         };
    01553         return &parser->event;
    01554 };
    01555
    01556 /* Purpose:
    01557  * Returns the length of the MIDI message starting with c.
    01558  * Taken from Nagano Daisuke's USB-MIDI driver */
    01559 int fluid_midi_event_length(unsigned char event){
    01560         if ( event < 0xf0 ) {
    01561                 return remains_80e0[((event-0x80)>>4)&0x0f];
    01562         } else if ( event < 0xf7 ) {
    01563                 return remains_f0f6[event-0xf0];
    01564         } else {
    01565                 return 1;
    01566         }
    01567 }
    01568
    01569 /************************************************************************
    01570  *       fluid_midi_send_event
    01571  *
    01572  * This is a utility function that doesn't really belong to any class
    01573  * or structure. It is called by fluid_midi_track and fluid_midi_device.
    01574  */
    01575 int fluid_midi_send_event(fluid_synth_t* synth, fluid_player_t* player, fluid_midi_event_t* event)
    01576 {
    01577         switch (event->type) {
    01578         case NOTE_ON:
    01579                 if (fluid_synth_noteon(synth, event->channel, event->param1, event->param2) != FLUID_OK) {
    01580                         return FLUID_FAILED;
    01581                 }
    01582                 break;
    01583         case NOTE_OFF:
    01584                 if (fluid_synth_noteoff(synth, event->channel, event->param1) != FLUID_OK) {
    01585                         return FLUID_FAILED;
    01586                 }
    01587                 break;
    01588         case CONTROL_CHANGE:
    01589                 if (fluid_synth_cc(synth, event->channel, event->param1, event->param2) != FLUID_OK) {
    01590                         return FLUID_FAILED;
    01591                 }
    01592                 break;
    01593         case MIDI_SET_TEMPO:
    01594                 if (player != NULL) {
    01595                         if (fluid_player_set_midi_tempo(player, event->param1) != FLUID_OK) {
    01596                                 return FLUID_FAILED;
    01597                         }
    01598                 }
    01599                 break;
    01600         case PROGRAM_CHANGE:
    01601                 if (fluid_synth_program_change(synth, event->channel, event->param1) != FLUID_OK) {
    01602                         return FLUID_FAILED;
    01603                 }
    01604                 break;
    01605         case PITCH_BEND:
    01606                 if (fluid_synth_pitch_bend(synth, event->channel, event->param1) != FLUID_OK) {
    01607                         return FLUID_FAILED;
    01608                 }
    01609                 break;
    01610         default:
    01611                 break;
    01612         }
    01613         return FLUID_OK;
    01614 }