DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/mt32/Synth.h
00001 /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
00002  * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
00003  *
00004  *  This program is free software: you can redistribute it and/or modify
00005  *  it under the terms of the GNU Lesser General Public License as published by
00006  *  the Free Software Foundation, either version 2.1 of the License, or
00007  *  (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 Lesser General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Lesser General Public License
00015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #ifndef MT32EMU_SYNTH_H
00019 #define MT32EMU_SYNTH_H
00020 
00021 #include <cstdarg>
00022 
00023 namespace MT32Emu {
00024 
00025 class File;
00026 class TableInitialiser;
00027 class Partial;
00028 class PartialManager;
00029 class Part;
00030 class ROMImage;
00031 
00037 enum DACInputMode {
00038         // Produces samples at double the volume, without tricks.
00039         // * Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)
00040         // * Higher quality than the real devices
00041         DACInputMode_NICE,
00042 
00043         // Produces samples that exactly match the bits output from the emulated LA32.
00044         // * Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)
00045         // * Much less likely to overdrive than any other mode.
00046         // * Half the volume of any of the other modes, meaning its volume relative to the reverb
00047         //   output when mixed together directly will sound wrong.
00048         // * Perfect for developers while debugging :)
00049         DACInputMode_PURE,
00050 
00051         // Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).
00052         // Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):
00053         // 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX
00054         DACInputMode_GENERATION1,
00055 
00056         // Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG).
00057         // Bit order at DAC (where each number represents the original LA32 output bit number):
00058         // 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14
00059         DACInputMode_GENERATION2
00060 };
00061 
00062 typedef void (*FloatToBit16sFunc)(Bit16s *target, const float *source, Bit32u len, float outputGain);
00063 
00064 const Bit8u SYSEX_MANUFACTURER_ROLAND = 0x41;
00065 
00066 const Bit8u SYSEX_MDL_MT32 = 0x16;
00067 const Bit8u SYSEX_MDL_D50 = 0x14;
00068 
00069 const Bit8u SYSEX_CMD_RQ1 = 0x11; // Request data #1
00070 const Bit8u SYSEX_CMD_DT1 = 0x12; // Data set 1
00071 const Bit8u SYSEX_CMD_WSD = 0x40; // Want to send data
00072 const Bit8u SYSEX_CMD_RQD = 0x41; // Request data
00073 const Bit8u SYSEX_CMD_DAT = 0x42; // Data set
00074 const Bit8u SYSEX_CMD_ACK = 0x43; // Acknowledge
00075 const Bit8u SYSEX_CMD_EOD = 0x45; // End of data
00076 const Bit8u SYSEX_CMD_ERR = 0x4E; // Communications error
00077 const Bit8u SYSEX_CMD_RJC = 0x4F; // Rejection
00078 
00079 const int MAX_SYSEX_SIZE = 512;
00080 
00081 const unsigned int CONTROL_ROM_SIZE = 64 * 1024;
00082 
00083 struct ControlROMPCMStruct {
00084         Bit8u pos;
00085         Bit8u len;
00086         Bit8u pitchLSB;
00087         Bit8u pitchMSB;
00088 };
00089 
00090 struct ControlROMMap {
00091         Bit16u idPos;
00092         Bit16u idLen;
00093         const char *idBytes;
00094         Bit16u pcmTable; // 4 * pcmCount bytes
00095         Bit16u pcmCount;
00096         Bit16u timbreAMap; // 128 bytes
00097         Bit16u timbreAOffset;
00098         bool timbreACompressed;
00099         Bit16u timbreBMap; // 128 bytes
00100         Bit16u timbreBOffset;
00101         bool timbreBCompressed;
00102         Bit16u timbreRMap; // 2 * timbreRCount bytes
00103         Bit16u timbreRCount;
00104         Bit16u rhythmSettings; // 4 * rhythmSettingsCount bytes
00105         Bit16u rhythmSettingsCount;
00106         Bit16u reserveSettings; // 9 bytes
00107         Bit16u panSettings; // 8 bytes
00108         Bit16u programSettings; // 8 bytes
00109         Bit16u rhythmMaxTable; // 4 bytes
00110         Bit16u patchMaxTable; // 16 bytes
00111         Bit16u systemMaxTable; // 23 bytes
00112         Bit16u timbreMaxTable; // 72 bytes
00113 };
00114 
00115 enum MemoryRegionType {
00116         MR_PatchTemp, MR_RhythmTemp, MR_TimbreTemp, MR_Patches, MR_Timbres, MR_System, MR_Display, MR_Reset
00117 };
00118 
00119 enum ReverbMode {
00120         REVERB_MODE_ROOM,
00121         REVERB_MODE_HALL,
00122         REVERB_MODE_PLATE,
00123         REVERB_MODE_TAP_DELAY
00124 };
00125 
00126 class MemoryRegion {
00127 private:
00128         Synth *synth;
00129         Bit8u *realMemory;
00130         Bit8u *maxTable;
00131 public:
00132         MemoryRegionType type;
00133         Bit32u startAddr, entrySize, entries;
00134 
00135         MemoryRegion(Synth *useSynth, Bit8u *useRealMemory, Bit8u *useMaxTable, MemoryRegionType useType, Bit32u useStartAddr, Bit32u useEntrySize, Bit32u useEntries) {
00136                 synth = useSynth;
00137                 realMemory = useRealMemory;
00138                 maxTable = useMaxTable;
00139                 type = useType;
00140                 startAddr = useStartAddr;
00141                 entrySize = useEntrySize;
00142                 entries = useEntries;
00143         }
00144         int lastTouched(Bit32u addr, Bit32u len) const {
00145                 return (int)(((unsigned long)offset(addr) + len - 1u) / entrySize);
00146         }
00147         int firstTouchedOffset(Bit32u addr) const {
00148                 return (int)((unsigned int)offset(addr) % entrySize);
00149         }
00150         int firstTouched(Bit32u addr) const {
00151                 return (int)((unsigned int)offset(addr) / entrySize);
00152         }
00153         Bit32u regionEnd() const {
00154                 return startAddr + entrySize * entries;
00155         }
00156         bool contains(Bit32u addr) const {
00157                 return addr >= startAddr && addr < regionEnd();
00158         }
00159         int offset(Bit32u addr) const {
00160                 return (int)(addr - startAddr);
00161         }
00162         Bit32u getClampedLen(Bit32u addr, Bit32u len) const {
00163                 if (addr + len > regionEnd())
00164                         return regionEnd() - addr;
00165                 return len;
00166         }
00167         Bit32u next(Bit32u addr, Bit32u len) const {
00168                 if (addr + len > regionEnd()) {
00169                         return regionEnd() - addr;
00170                 }
00171                 return 0;
00172         }
00173         Bit8u getMaxValue(int off) const {
00174                 if (maxTable == NULL)
00175                         return 0xFF;
00176                 return maxTable[(unsigned int)off % entrySize];
00177         }
00178         Bit8u *getRealMemory() const {
00179                 return realMemory;
00180         }
00181         bool isReadable() const {
00182                 return getRealMemory() != NULL;
00183         }
00184         void read(unsigned int entry, unsigned int off, Bit8u *dst, unsigned int len) const;
00185         void write(unsigned int entry, unsigned int off, const Bit8u *src, unsigned int len, bool init = false) const;
00186 };
00187 
00188 class PatchTempMemoryRegion : public MemoryRegion {
00189 public:
00190         PatchTempMemoryRegion(Synth *useSynth, Bit8u *useRealMemory, Bit8u *useMaxTable) : MemoryRegion(useSynth, useRealMemory, useMaxTable, MR_PatchTemp, MT32EMU_MEMADDR(0x030000), sizeof(MemParams::PatchTemp), 9) {}
00191 };
00192 class RhythmTempMemoryRegion : public MemoryRegion {
00193 public:
00194         RhythmTempMemoryRegion(Synth *useSynth, Bit8u *useRealMemory, Bit8u *useMaxTable) : MemoryRegion(useSynth, useRealMemory, useMaxTable, MR_RhythmTemp, MT32EMU_MEMADDR(0x030110), sizeof(MemParams::RhythmTemp), 85) {}
00195 };
00196 class TimbreTempMemoryRegion : public MemoryRegion {
00197 public:
00198         TimbreTempMemoryRegion(Synth *useSynth, Bit8u *useRealMemory, Bit8u *useMaxTable) : MemoryRegion(useSynth, useRealMemory, useMaxTable, MR_TimbreTemp, MT32EMU_MEMADDR(0x040000), sizeof(TimbreParam), 8) {}
00199 };
00200 class PatchesMemoryRegion : public MemoryRegion {
00201 public:
00202         PatchesMemoryRegion(Synth *useSynth, Bit8u *useRealMemory, Bit8u *useMaxTable) : MemoryRegion(useSynth, useRealMemory, useMaxTable, MR_Patches, MT32EMU_MEMADDR(0x050000), sizeof(PatchParam), 128) {}
00203 };
00204 class TimbresMemoryRegion : public MemoryRegion {
00205 public:
00206         TimbresMemoryRegion(Synth *useSynth, Bit8u *useRealMemory, Bit8u *useMaxTable) : MemoryRegion(useSynth, useRealMemory, useMaxTable, MR_Timbres, MT32EMU_MEMADDR(0x080000), sizeof(MemParams::PaddedTimbre), 64 + 64 + 64 + 64) {}
00207 };
00208 class SystemMemoryRegion : public MemoryRegion {
00209 public:
00210         SystemMemoryRegion(Synth *useSynth, Bit8u *useRealMemory, Bit8u *useMaxTable) : MemoryRegion(useSynth, useRealMemory, useMaxTable, MR_System, MT32EMU_MEMADDR(0x100000), sizeof(MemParams::System), 1) {}
00211 };
00212 class DisplayMemoryRegion : public MemoryRegion {
00213 public:
00214         DisplayMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Display, MT32EMU_MEMADDR(0x200000), MAX_SYSEX_SIZE - 1, 1) {}
00215 };
00216 class ResetMemoryRegion : public MemoryRegion {
00217 public:
00218         ResetMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Reset, MT32EMU_MEMADDR(0x7F0000), 0x3FFF, 1) {}
00219 };
00220 
00221 class ReverbModel {
00222 public:
00223         virtual ~ReverbModel() {}
00224         // After construction or a close(), open() will be called at least once before any other call (with the exception of close()).
00225         virtual void open() = 0;
00226         // May be called multiple times without an open() in between.
00227         virtual void close() = 0;
00228         virtual void setParameters(Bit8u time, Bit8u level) = 0;
00229         virtual void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples) = 0;
00230         virtual bool isActive() const = 0;
00231         
00232         virtual void saveState( std::ostream &stream ) { (void)stream; }
00233         virtual void loadState( std::istream &stream ) { (void)stream; }
00234 };
00235 
00236 class ReportHandler {
00237 friend class Synth;
00238 
00239 public:
00240         virtual ~ReportHandler() {}
00241 
00242 protected:
00243 
00244         // Callback for debug messages, in vprintf() format
00245         virtual void printDebug(const char *fmt, va_list list);
00246 
00247         // Callbacks for reporting various errors and information
00248         virtual void onErrorControlROM() {}
00249         virtual void onErrorPCMROM() {}
00250         virtual void showLCDMessage(const char *message);
00251         virtual void onDeviceReset() {}
00252         virtual void onDeviceReconfig() {}
00253         virtual void onNewReverbMode(Bit8u /* mode */) {}
00254         virtual void onNewReverbTime(Bit8u /* time */) {}
00255         virtual void onNewReverbLevel(Bit8u /* level */) {}
00256         virtual void onPartStateChanged(int /* partNum */, bool /* isActive */) {}
00257         virtual void onPolyStateChanged(int /* partNum */) {}
00258         virtual void onPartialStateChanged(int /* partialNum */, int /* oldPartialPhase */, int /* newPartialPhase */) {}
00259         virtual void onProgramChanged(int /* partNum */, char * /* patchName */) {}
00260 };
00261 
00262 class Synth {
00263 friend class Part;
00264 friend class RhythmPart;
00265 friend class Poly;
00266 friend class Partial;
00267 friend class Tables;
00268 friend class MemoryRegion;
00269 friend class TVA;
00270 friend class TVF;
00271 friend class TVP;
00272 private:
00273         PatchTempMemoryRegion *patchTempMemoryRegion;
00274         RhythmTempMemoryRegion *rhythmTempMemoryRegion;
00275         TimbreTempMemoryRegion *timbreTempMemoryRegion;
00276         PatchesMemoryRegion *patchesMemoryRegion;
00277         TimbresMemoryRegion *timbresMemoryRegion;
00278         SystemMemoryRegion *systemMemoryRegion;
00279         DisplayMemoryRegion *displayMemoryRegion;
00280         ResetMemoryRegion *resetMemoryRegion;
00281 
00282         Bit8u *paddedTimbreMaxTable;
00283 
00284         bool isEnabled;
00285 
00286         PCMWaveEntry *pcmWaves; // Array
00287 
00288         const ControlROMMap *controlROMMap;
00289         Bit8u controlROMData[CONTROL_ROM_SIZE];
00290         Bit16s *pcmROMData;
00291         size_t pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM
00292 
00293         Bit8s chantable[32];
00294 
00295         Bit32u renderedSampleCount;
00296 
00297 
00298         MemParams mt32ram, mt32default;
00299 
00300         ReverbModel *reverbModels[4];
00301         ReverbModel *reverbModel;
00302         bool reverbEnabled;
00303         bool reverbOverridden;
00304 
00305         FloatToBit16sFunc la32FloatToBit16sFunc;
00306         FloatToBit16sFunc reverbFloatToBit16sFunc;
00307         float outputGain;
00308         float reverbOutputGain;
00309 
00310         bool isOpen;
00311 
00312         bool isDefaultReportHandler;
00313         ReportHandler *reportHandler;
00314 
00315         PartialManager *partialManager;
00316         Part *parts[9];
00317 
00318         // FIXME: We can reorganise things so that we don't need all these separate tmpBuf, tmp and prerender buffers.
00319         // This should be rationalised when things have stabilised a bit (if prerender buffers don't die in the mean time).
00320 
00321         float tmpBufPartialLeft[MAX_SAMPLES_PER_RUN];
00322         float tmpBufPartialRight[MAX_SAMPLES_PER_RUN];
00323         float tmpBufMixLeft[MAX_SAMPLES_PER_RUN];
00324         float tmpBufMixRight[MAX_SAMPLES_PER_RUN];
00325         float tmpBufReverbOutLeft[MAX_SAMPLES_PER_RUN];
00326         float tmpBufReverbOutRight[MAX_SAMPLES_PER_RUN];
00327 
00328         Bit16s tmpNonReverbLeft[MAX_SAMPLES_PER_RUN];
00329         Bit16s tmpNonReverbRight[MAX_SAMPLES_PER_RUN];
00330         Bit16s tmpReverbDryLeft[MAX_SAMPLES_PER_RUN];
00331         Bit16s tmpReverbDryRight[MAX_SAMPLES_PER_RUN];
00332         Bit16s tmpReverbWetLeft[MAX_SAMPLES_PER_RUN];
00333         Bit16s tmpReverbWetRight[MAX_SAMPLES_PER_RUN];
00334 
00335         // These ring buffers are only used to simulate delays present on the real device.
00336         // In particular, when a partial needs to be aborted to free it up for use by a new Poly,
00337         // the controller will busy-loop waiting for the sound to finish.
00338         Bit16s prerenderNonReverbLeft[MAX_PRERENDER_SAMPLES];
00339         Bit16s prerenderNonReverbRight[MAX_PRERENDER_SAMPLES];
00340         Bit16s prerenderReverbDryLeft[MAX_PRERENDER_SAMPLES];
00341         Bit16s prerenderReverbDryRight[MAX_PRERENDER_SAMPLES];
00342         Bit16s prerenderReverbWetLeft[MAX_PRERENDER_SAMPLES];
00343         Bit16s prerenderReverbWetRight[MAX_PRERENDER_SAMPLES];
00344         int prerenderReadIx;
00345         int prerenderWriteIx;
00346 
00347         unsigned int partialLimit;
00348 
00349         bool prerender();
00350         void copyPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u pos, Bit32u len);
00351         void checkPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u &pos, Bit32u &len);
00352         void doRenderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len);
00353 
00354         void playAddressedSysex(unsigned char channel, const Bit8u *sysex, Bit32u len);
00355         void readSysex(unsigned char channel, const Bit8u *sysex, Bit32u len) const;
00356         void initMemoryRegions();
00357         void deleteMemoryRegions();
00358         MemoryRegion *findMemoryRegion(Bit32u addr);
00359         void writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, const Bit8u *data);
00360         void readMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, Bit8u *data);
00361 
00362         bool loadControlROM(const ROMImage &controlROMImage);
00363         bool loadPCMROM(const ROMImage &pcmROMImage);
00364 
00365         bool initPCMList(Bit16u mapAddress, Bit16u count);
00366         bool initTimbres(Bit16u mapAddress, Bit16u offset, int timbreCount, int startTimbre, bool compressed);
00367         bool initCompressedTimbre(int drumNum, const Bit8u *mem, unsigned int memLen);
00368 
00369         void refreshSystemMasterTune();
00370         void refreshSystemReverbParameters();
00371         void refreshSystemReserveSettings();
00372         void refreshSystemChanAssign(unsigned int firstPart, unsigned int lastPart);
00373         void refreshSystemMasterVol();
00374         void refreshSystem();
00375         void reset();
00376 
00377         void printPartialUsage(unsigned long sampleOffset = 0);
00378 
00379         void partStateChanged(int partNum, bool isPartActive);
00380         void polyStateChanged(int partNum);
00381         void partialStateChanged(const Partial * const partial, int oldPartialPhase, int newPartialPhase);
00382         void newTimbreSet(int partNum, char patchName[]);
00383         void printDebug(const char *fmt, ...);
00384 
00385 public:
00386         static Bit8u calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum);
00387 
00388         // Optionally sets callbacks for reporting various errors, information and debug messages
00389         Synth(ReportHandler *useReportHandler = NULL);
00390         ~Synth();
00391 
00392         // Used to initialise the MT-32. Must be called before any other function.
00393         // Returns true if initialization was sucessful, otherwise returns false.
00394         // controlROMImage and pcmROMImage represent Control and PCM ROM images for use by synth.
00395         bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage);
00396 
00397         // Closes the MT-32 and deallocates any memory used by the synthesizer
00398         void close(void);
00399 
00400         // Sends a 4-byte MIDI message to the MT-32 for immediate playback
00401         void playMsg(Bit32u msg);
00402         void playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity);
00403 
00404         // Sends a string of Sysex commands to the MT-32 for immediate interpretation
00405         // The length is in bytes
00406         void playSysex(const Bit8u *sysex, Bit32u len);
00407         void playSysexWithoutFraming(const Bit8u *sysex, Bit32u len);
00408         void playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len);
00409         void writeSysex(unsigned char channel, const Bit8u *sysex, Bit32u len);
00410 
00411         void setReverbEnabled(bool reverbEnabled);
00412         bool isReverbEnabled() const;
00413         void setReverbOverridden(bool reverbOverridden);
00414         bool isReverbOverridden() const;
00415         void setDACInputMode(DACInputMode mode);
00416 
00417         // Sets output gain factor. Applied to all output samples and unrelated with the synth's Master volume.
00418         void setOutputGain(float);
00419 
00420         // Sets output gain factor for the reverb wet output. setOutputGain() doesn't change reverb output gain.
00421         void setReverbOutputGain(float);
00422 
00423         // Renders samples to the specified output stream.
00424         // The length is in frames, not bytes (in 16-bit stereo,
00425         // one frame is 4 bytes).
00426         void render(Bit16s *stream, Bit32u len);
00427 
00428         // Renders samples to the specified output streams (any or all of which may be NULL).
00429         void renderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len);
00430 
00431         // Returns true when there is at least one active partial, otherwise false.
00432         bool hasActivePartials() const;
00433 
00434         // Returns true if hasActivePartials() returns true, or reverb is (somewhat unreliably) detected as being active.
00435         bool isActive() const;
00436 
00437         const Partial *getPartial(unsigned int partialNum) const;
00438 
00439         void setPartialLimit( unsigned int partialLimit );
00440         unsigned int getPartialLimit() const;
00441         
00442         void readMemory(Bit32u addr, Bit32u len, Bit8u *data);
00443 
00444         // partNum should be 0..7 for Part 1..8, or 8 for Rhythm
00445         const Part *getPart(unsigned int partNum) const;
00446 
00447         // svn-daum
00448         void *dumpRam();
00449         void loadRam( void *buf );
00450 
00451         void findPart( const Part *src, Bit8u *index_out );
00452         void findPartial( const Partial *src, Bit8u *index_out );
00453         void findPartialParam( const TimbreParam::PartialParam *src, Bit16u *index_out1, Bit16u *index_out2 );
00454         void findPatchCache( const PatchCache *src, Bit16u *index_out1, Bit16u *index_out2 );
00455         void findPatchTemp( const MemParams::PatchTemp *src, Bit8u *index_out );
00456         void findPCMWaveEntry( const PCMWaveEntry *src, Bit16u *index_out );
00457         void findPoly( const Poly *src, Bit16u *index_out1, Bit16u *index_out2 );
00458         void findRhythmTemp( const MemParams::RhythmTemp *src, Bit8u *index_out );
00459         void findTimbreParam( const TimbreParam *src, Bit8u *index_out );
00460 
00461         Part *indexPart( Bit8u index );
00462         Partial *indexPartial( Bit8u index );
00463         TimbreParam::PartialParam *indexPartialParam( Bit16u index1, Bit16u index2 );
00464         PatchCache *indexPatchCache( Bit16u index1, Bit16u index2 );
00465         MemParams::PatchTemp *indexPatchTemp( Bit8u index );
00466         PCMWaveEntry *indexPCMWaveEntry( Bit16u index );
00467         Poly *indexPoly( Bit16u index1, Bit16u index2 );
00468         MemParams::RhythmTemp *indexRhythmTemp( Bit8u index );
00469         TimbreParam *indexTimbreParam( Bit8u index );
00470 };
00471 
00472 
00473 // debugger only
00474 //#define WIN32_DEBUG
00475 //#define WIN32_DUMP
00476 }
00477 
00478 #endif