FluidSynthMidiDriver.cpp

Go to the documentation of this file.
00001 /* 
00002  * Copyright (C) 2001-2005 The ScummVM project
00003  * Copyright (C) 2005 The Pentagram Team
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018  */
00019 
00020 
00021 #include "pent_include.h"
00022 #include "FluidSynthMidiDriver.h"
00023 
00024 #ifdef USE_FLUIDSYNTH_MIDI
00025 
00026 //#include <cstring>
00027 
00028 const MidiDriver::MidiDriverDesc FluidSynthMidiDriver::desc = 
00029                 MidiDriver::MidiDriverDesc ("FluidSynth", createInstance);
00030 
00031 // MidiDriver method implementations
00032 
00033 FluidSynthMidiDriver::FluidSynthMidiDriver()
00034         : LowLevelMidiDriver(), _settings(0), _synth(0), _soundFont(-1) 
00035 {
00036 }
00037 
00038 void FluidSynthMidiDriver::setInt(const char *name, int val) {
00039         //char *name2 = strdup(name);
00040         char *name2 = const_cast<char*>(name);
00041 
00042         fluid_settings_setint(_settings, name2, val);
00043         //std::free(name2);
00044 }
00045 
00046 void FluidSynthMidiDriver::setNum(const char *name, double val) {
00047         //char *name2 = strdup(name);
00048         char *name2 = const_cast<char*>(name);
00049 
00050         fluid_settings_setnum(_settings, name2, val);
00051         //std::free(name2);
00052 }
00053 
00054 void FluidSynthMidiDriver::setStr(const char *name, const char *val) {
00055         //char *name2 = strdup(name);
00056         //char *val2 = strdup(val);
00057         char *name2 = const_cast<char*>(name);
00058         char *val2 = const_cast<char*>(val);
00059 
00060         fluid_settings_setstr(_settings, name2, val2);
00061         //std::free(name2);
00062         //std::free(val2);
00063 }
00064 
00065 int FluidSynthMidiDriver::open() {
00066 
00067         if (!stereo) {
00068                 perr << "FluidSynth only works with Stereo output" << std::endl;
00069                 return -1;
00070         }
00071 
00072         std::string soundfont = getConfigSetting("fluidsynth_soundfont", "");
00073 
00074         if (soundfont == "") {
00075                 perr << "FluidSynth requires a 'fluidsynth_soundfont' setting" << std::endl;
00076                 return -2;
00077         }
00078 
00079         _settings = new_fluid_settings();
00080 
00081         // The default gain setting is ridiculously low, but we can't set it
00082         // too high either or sound will be clipped. This may need tuning...
00083 
00084         setNum("synth.gain", 2.1);
00085         setNum("synth.sample-rate", sample_rate);
00086 
00087         _synth = new_fluid_synth(_settings);
00088 
00089         // In theory, this ought to reduce CPU load... but it doesn't make any
00090         // noticeable difference for me, so disable it for now.
00091 
00092         // fluid_synth_set_interp_method(_synth, -1, FLUID_INTERP_LINEAR);
00093         // fluid_synth_set_reverb_on(_synth, 0);
00094         // fluid_synth_set_chorus_on(_synth, 0);
00095 
00096         _soundFont = fluid_synth_sfload(_synth, soundfont.c_str(), 1);
00097         if (_soundFont == -1) {
00098                 perr << "Failed loading custom sound font '" << soundfont << "'" << std::endl;
00099                 return -3;
00100         }
00101 
00102         return 0;
00103 }
00104 
00105 void FluidSynthMidiDriver::close() {
00106 
00107         if (_soundFont != -1)
00108                 fluid_synth_sfunload(_synth, _soundFont, 1);
00109         _soundFont = -1;
00110 
00111         delete_fluid_synth(_synth);
00112         _synth = 0;
00113         delete_fluid_settings(_settings);
00114         _settings = 0;
00115 }
00116 
00117 void FluidSynthMidiDriver::send(uint32 b) {
00118         //uint8 param3 = (uint8) ((b >> 24) & 0xFF);
00119         uint32 param2 = (uint8) ((b >> 16) & 0xFF);
00120         uint32 param1 = (uint8) ((b >>  8) & 0xFF);
00121         uint8 cmd    = (uint8) (b & 0xF0);
00122         uint8 chan   = (uint8) (b & 0x0F);
00123 
00124         switch (cmd) {
00125         case 0x80:      // Note Off
00126                 fluid_synth_noteoff(_synth, chan, param1);
00127                 break;
00128         case 0x90:      // Note On
00129                 fluid_synth_noteon(_synth, chan, param1, param2);
00130                 break;
00131         case 0xA0:      // Aftertouch
00132                 break;
00133         case 0xB0:      // Control Change
00134                 fluid_synth_cc(_synth, chan, param1, param2);
00135                 break;
00136         case 0xC0:      // Program Change
00137                 fluid_synth_program_change(_synth, chan, param1);
00138                 break;
00139         case 0xD0:      // Channel Pressure
00140                 break;
00141         case 0xE0:      // Pitch Bend
00142                 fluid_synth_pitch_bend(_synth, chan, (param2 << 7) | param1);
00143                 break;
00144         case 0xF0:      // SysEx
00145                 // We should never get here! SysEx information has to be
00146                 // sent via high-level semantic methods.
00147                 perr << "FluidSynthMidiDriver: Receiving SysEx command on a send() call" << std::endl;
00148                 break;
00149         default:
00150                 perr << "FluidSynthMidiDriver: Unknown send() command 0x" << std::hex << cmd << std::dec << std::endl;
00151                 break;
00152         }
00153 }
00154 
00155 void FluidSynthMidiDriver::lowLevelProduceSamples(sint16 *samples, uint32 num_samples) {
00156         fluid_synth_write_s16(_synth, num_samples, samples, 0, 2, samples, 1, 2);
00157 }
00158 
00159 #endif

Generated on Fri Jul 27 22:27:14 2007 for pentagram by  doxygen 1.4.7