LowLevelMidiDriver.h

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003-2005  The Pentagram Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifndef LOWLEVELMIDIDRIVER_H_INCLUDED
00020 #define LOWLEVELMIDIDRIVER_H_INCLUDED
00021 
00022 #include "MidiDriver.h"
00023 #include "XMidiSequenceHandler.h"
00024 
00025 class XMidiEventList;
00026 class XMidiSequence;
00027 
00028 #include <queue>
00029 #include <SDL.h>
00030 #include <SDL_thread.h>
00031 
00034 #define LLMD_NUM_SEQ    4
00035 
00043 class   LowLevelMidiDriver : public MidiDriver, private XMidiSequenceHandler
00044 {
00045 public:
00046         LowLevelMidiDriver();
00047         virtual ~LowLevelMidiDriver();
00048 
00049         // MidiDriver Implementation
00050         virtual int                     initMidiDriver(uint32 sample_rate, bool stereo);
00051         virtual void            destroyMidiDriver();
00052         virtual int                     maxSequences();
00053         virtual void            setGlobalVolume(int vol);
00054 
00055         virtual void            startSequence(int seq_num, XMidiEventList *list, bool repeat, int vol, int branch = -1);
00056         virtual void            finishSequence(int seq_num);
00057         virtual void            pauseSequence(int seq_num);
00058         virtual void            unpauseSequence(int seq_num);
00059         virtual void            setSequenceVolume(int seq_num, int vol);
00060         virtual void            setSequenceSpeed(int seq_num, int speed);
00061         virtual bool            isSequencePlaying(int seq_num);
00062         virtual uint32          getSequenceCallbackData(int seq_num);
00063 
00064         virtual void            produceSamples(sint16 *samples, uint32 bytes);
00065 
00066         virtual void            loadTimbreLibrary(IDataSource*, TimbreLibraryType type);
00067 
00068 protected:
00069 
00070         // Will be wanted by software drivers
00071         uint32                  sample_rate;
00072         bool                    stereo;
00073 
00076         virtual int                     open()=0;
00077 
00079         virtual void            close()=0;
00080 
00082         virtual void            send(uint32 message)=0;
00083 
00085         //
00086         // Note that this is slightly different to the API used in ScummVM. 
00087         // The 0xF0 status isn't assumed, and the final 0xF7 also isn't assumed, and is the
00088         // final byte of the msg buffer. length includes the final byte. The reason for the
00089         // differences is because the midi specifications can have SysEx messages that does 
00090         // start with 0xF0 and don't end with 0xF7. Chances are though they will never be
00091         // encountered.
00092         virtual void            send_sysex(uint8 status, const uint8 *msg, uint16 length) { };
00093 
00095         virtual void            increaseThreadPriority() { };
00096 
00098         virtual void            lowLevelProduceSamples(sint16 *samples, uint32 num_samples) { };
00099 
00101         virtual void            yield() { SDL_Delay(1); }
00102 
00103 private:
00104 
00105         struct ComMessage {
00106 
00107                 ComMessage(int T) : type(T) { }
00108 
00109                 ComMessage(const ComMessage &other)
00110                 {
00111                         type = other.type;
00112                         sequence = other.sequence;
00113                         std::memcpy (&data, &other.data, sizeof(data));
00114                 }
00115 
00116                 ComMessage & operator = (const ComMessage &other)
00117                 {
00118                         type = other.type;
00119                         sequence = other.sequence;
00120                         std::memcpy (&data, &other.data, sizeof(data));
00121                         return  *this;
00122                 }
00123 
00124                 int                             type;
00125                 int                             sequence;
00126                 union
00127                 {
00128                         struct {
00129                                 XMidiEventList  *list;
00130                                 bool                    repeat;
00131                                 int                             volume;
00132                                 int                             branch;
00133                         } play;
00134 
00135                         struct {
00136                                 bool                    paused;
00137                         } pause;
00138 
00139                         struct {
00140                                 int                             level;
00141                         } volume;
00142 
00143                         struct {
00144                                 int                             percentage;
00145                         } speed;
00146 
00147                         struct {
00148                                 int                             code;
00149                         } init_failed;
00150 
00151                 } data;
00152         };
00153 
00154         bool                                    uploading_timbres;      // Set in 'uploading' timbres mode
00155 
00156         // Communications
00157         std::queue<ComMessage>  messages;
00158         SDL_mutex                               *mutex;
00159         SDL_mutex                               *cbmutex;
00160         SDL_cond                *cond;
00161         sint32                                  peekComMessageType();
00162         void                                    sendComMessage(ComMessage& message);
00163         void                                    waitTillNoComMessages();
00164         void                                    lockComMessage();
00165         void                                    unlockComMessage();
00166 
00167         // State
00168         bool                                    playing[LLMD_NUM_SEQ];                  // Only set by thread
00169         sint32                                  callback_data[LLMD_NUM_SEQ];    // Only set by thread
00170 
00171         // Shared Data
00172         int                                             global_volume;
00173         uint32                                  xmidi_clock;                                    // Xmidi clock, returned by getTickCount
00174         int                                             chan_locks[16];                                 // Which seq a chan has been locked by
00175         int                                             chan_map[LLMD_NUM_SEQ][16];             // Maps from locked logical chan to phyiscal
00176         XMidiSequence                   *sequences[LLMD_NUM_SEQ];
00177         int                                             next_sysex;                                             // Time we can next send sysex at (is SDL_GetTick() value)
00178 
00179         // Software Synth only Data
00180         uint32                                  total_seconds;                                  // xmidi_clock = total_seconds*6000 
00181         uint32                                  samples_this_second;                    //              + samples_this_second*6000/sample_rate;
00182         uint32                                  samples_per_iteration;
00183 
00184         // Thread Based Only Data
00185         SDL_Thread                              *thread;
00186 
00187         // Timbre Banks
00188         struct MT32Timbre {
00189                 uint32          time_uploaded;
00190                 int                     index;
00191                 bool            protect;
00192                 uint8           timbre[246];
00193         };
00194         struct MT32Patch {
00195                 sint8           timbre_bank;                    // 0-3  (group A, group B, Memory, Rhythm)
00196                 sint8           timbre_num;                             // 0-63
00197                 uint8           key_shift;                              // 0-48
00198                 uint8           fine_tune;                              // 0-100 (-50 - +50)
00199                 uint8           bender_range;                   // 0-24
00200                 uint8           assign_mode;                    // 0-3 (POLY1, POLY2, POLY3, POLY4)
00201                 uint8           reverb_switch;                  // 0-1 (off,on)
00202                 uint8           dummy;
00203         };
00204         static const MT32Patch  mt32_patch_template;
00205         struct MT32Rhythm {
00206                 uint8           timbre;                                 // 0-94 (M1-M64,R1-30,OFF)
00207                 uint8           output_level;                   // 0-100
00208                 uint8           panpot;                                 // 0-14 (L-R)
00209                 uint8           reverb_switch;                  // 0-1 (off,on)
00210         };
00211 
00212 
00213         MT32Patch                               **mt32_patch_banks[128];                        // 128 banks, of 128 Patches
00214         MT32Timbre                              **mt32_timbre_banks[128];                       // 128 banks, of 128 Timbres
00215         MT32Rhythm                              *mt32_rhythm_bank[128];                         // 1 bank of rhythm
00216         int                                             mt32_timbre_used[64][2];
00217         int                                             mt32_bank_sel[LLMD_NUM_SEQ][16];
00218         int                                             mt32_patch_bank_sel[128];
00219 
00220         void                                    loadXMidiTimbreLibrary(IDataSource *ds);
00221         void                                    extractTimbreLibrary(XMidiEventList *eventlist);
00222     void                                        uploadTimbre(int bank, int timbre);
00223         void                                    setPatchBank(int bank, int patch);
00224         void                                    loadRhythmTemp(int temp);
00225         void                                    sendMT32SystemMessage(uint32 address_base, uint16 address_offset, uint32 len, const void *data);
00226 
00227         // Shared Methods
00228 
00231         bool                                    playSequences();
00232 
00233         // Thread Methods
00234         int                                             initThreadedSynth();
00235         void                                    destroyThreadedSynth();
00236         static int                              threadMain_Static(void *data);
00237         int                                             threadMain();
00238 
00239         // Software methods
00240         int                                             initSoftwareSynth();
00241         void                                    destroySoftwareSynth();
00242 
00243         // XMidiSequenceHandler implementation
00244         virtual void                    sequenceSendEvent(uint16 sequence_id, uint32 message);
00245         virtual void                    sequenceSendSysEx(uint16 sequence_id, uint8 status, const uint8 *msg, uint16 length);
00246         virtual uint32                  getTickCount(uint16 sequence_id);
00247         virtual void                    handleCallbackTrigger(uint16 sequence_id, uint8 data);
00248 
00249         int                                             protectChannel(uint16 sequence_id, int chan, bool protect);
00250         int                                             lockChannel(uint16 sequence_id, int chan, bool lock);
00251 
00252         int                                             unlockAndUnprotectChannel(uint16 sequence_id);
00253 
00255         void                                    muteAllChannels();
00256 };
00257 
00258 #endif //LOWLEVELMIDIDRIVER_H_INCLUDED

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