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 }

Generated on Sat Nov 17 13:40:23 2007 for libfluidsynth by  doxygen 1.5.3