1 // 2 // /home/ms/source/sidplay/libsidplay/include/RCS/emucfg.h,v 3 // 4 // This is an interface to the Emulator Engine and does not access any 5 // audio hardware or driver. 6 // 7 // THIS CLASS INTERFACE CAN ONLY BE USED TO INSTANTIATE A -SINGLE OBJECT-. 8 // DUE TO EFFICIENCY CONCERNS, THE EMULATOR ENGINE CONSISTS OF -GLOBAL- 9 // OBJECTS. Currently, the only aim of this class is to allow a safe 10 // initialization of those objects. 11 // 12 13 #ifndef SIDPLAY1_EMUCFG_H 14 #define SIDPLAY1_EMUCFG_H 15 16 17 #include "compconf.h" 18 #include "mytypes.h" 19 #include "sidtune.h" 20 21 22 // An instance of this structure is used to transport emulator settings 23 // to and from the interface class. 24 struct emuConfig 25 { 26 uword frequency; // [frequency] = Hz, min=4000, max=48000 27 int bitsPerSample; // see below, ``Sample precision'' 28 int sampleFormat; // see below, ``Sample encoding'' 29 int channels; // see below, ``Number of physical audio channels'' 30 int sidChips; // --- unsupported --- 31 int volumeControl; // see below, ``Volume control modes'' 32 33 bool mos8580; // true, false (just the waveforms) 34 bool measuredVolume; // true, false 35 36 bool emulateFilter; // true, false 37 float filterFs; // 1.0 <= Fs 38 float filterFm; // Fm != 0 39 float filterFt; // 40 41 int memoryMode; // MPU_BANK_SWITCHING, MPU_TRANSPARENT_ROM, 42 // MPU_PLAYSID_ENVIRONMENT 43 44 int clockSpeed; // SIDTUNE_CLOCK_PAL, SIDTUNE_CLOCK_NTSC 45 46 bool forceSongSpeed; // true, false 47 48 // 49 // Working, but experimental. 50 // 51 int digiPlayerScans; // 0=off, number of C64 music player calls used to 52 // scan it for PlaySID Extended SID Register usage. 53 54 int autoPanning; // see below, ``Auto-panning'' 55 }; 56 57 58 // Memory mode settings: 59 // 60 // MPU_BANK_SWITCHING: Does emulate every bank-switching that one can 61 // consider as useful for music players. 62 // 63 // MPU_TRANSPARENT_ROM: An emulator environment with partial bank-switching. 64 // Required to run sidtunes which: 65 // 66 // - use the RAM under the I/O address space 67 // - use RAM at $E000-$FFFA + jump to Kernal functions 68 // 69 // MPU_PLAYSID_ENVIRONMENT: A PlaySID-like emulator environment. 70 // Required to run sidtunes which: 71 // 72 // - are specific to PlaySID 73 // - do not contain bank-switching code 74 // 75 // Sidtunes that would not run on a real C64 because their players were 76 // prepared to assume the certain emulator environment provided by PlaySID. 77 78 enum 79 { 80 // Memory mode settings. 81 // 82 MPU_BANK_SWITCHING = 0x20, 83 MPU_TRANSPARENT_ROM, 84 MPU_PLAYSID_ENVIRONMENT, 85 86 // Volume control modes. Use ``SIDEMU_NONE'' for no control. 87 // 88 SIDEMU_VOLCONTROL = 0x40, 89 SIDEMU_FULLPANNING, 90 SIDEMU_HWMIXING, 91 SIDEMU_STEREOSURROUND, 92 93 // Auto-panning modes. Use ``SIDEMU_NONE'' for none. 94 // 95 SIDEMU_CENTEREDAUTOPANNING = 0x50, 96 97 // This can either be used as a dummy, or where one does not 98 // want to make an alternative setting. 99 SIDEMU_NONE = 0x1000 100 }; 101 102 103 // Sample format and configuration constants. The values are intended to 104 // be distinct from each other. Some of the constants have a most obvious 105 // value, so they can be used in calculations. 106 107 // Sample encoding (format). 108 const int SIDEMU_UNSIGNED_PCM = 0x80; 109 const int SIDEMU_SIGNED_PCM = 0x7F; 110 111 // Number of physical audio channels. 112 // ``Stereo'' means interleaved channel data. 113 const int SIDEMU_MONO = 1; 114 const int SIDEMU_STEREO = 2; 115 116 // Sample precision (bits per sample). The endianess of the stored samples 117 // is machine dependent. 118 const int SIDEMU_8BIT = 8; 119 const int SIDEMU_16BIT = 16; 120 121 122 // Auto-panning modes. Only valid for mixing modes ``SIDEMU_FULLPANNING'' 123 // or ``SIDEMU_STEREOSURROUND''. 124 // 125 // The volume levels left/right build the panning boundaries. The panning 126 // range is the difference between left and right level. After enabling 127 // this you can override the default levels with your own ones using the 128 // setVoiceVolume() function. A default is provided to ensure sane 129 // initial settings. 130 // NOTE: You can mute a voice by setting left=right=0 or total=0. 131 // 132 // Auto-panning starts each new note on the opposite pan-position and 133 // then moves between the left and right volume level. 134 // 135 // Centered auto-panning starts in the middle, moves outwards and then 136 // toggles between the two pan-positions like normal auto-panning. 137 138 139 // Default filter parameters. 140 const float SIDEMU_DEFAULTFILTERFS = 400.0; 141 const float SIDEMU_DEFAULTFILTERFM = 60.0; 142 const float SIDEMU_DEFAULTFILTERFT = 0.05; 143 144 145 // Volume control modes 146 // 147 // int volumeControl; 148 // bool setVoiceVolume(int voice, ubyte leftLevel, ubyte rightLevel, uword total); 149 // uword getVoiceVolume(int voice); 150 // 151 // Relative voice volume is ``total'' from 0 (mute) to 256 (max). If you use it, 152 // you don't have to modulate each L/R level yourself. 153 // 154 // A noticable difference between FULLPANNING and VOLCONTROL is FULLPANNING's 155 // capability to mix four (all) logical voices to a single physical audio 156 // channel, whereas VOLCONTROL is only able to mix two (half of all) logical 157 // voices to a physical channel. 158 // Therefore VOLCONTROL results in slightly better sample quality, because 159 // it mixes at higher amplitude. Especially when using a sample precision of 160 // 8-bit and stereo. In mono mode both modes operate equally. 161 // 162 // NOTE: Changing the volume control mode resets the current volume 163 // level settings for all voices to a default: 164 // 165 // MONO | left | right STEREO | left | right 166 // ----------------------- ----------------------- 167 // voice 1 | 255 | 0 voice 1 | 255 | 0 168 // voice 2 | 255 | 0 voice 2 | 0 | 255 169 // voice 3 | 255 | 0 voice 3 | 255 | 0 170 // voice 4 | 255 | 0 voice 4 | 0 | 255 171 // 172 // SURROUND | left | right 173 // ------------------------ 174 // voice 1 | 255 | 255 175 // voice 2 | 255 | 255 176 // voice 3 | 255 | 255 177 // voice 4 | 255 | 255 178 // 179 // 180 // Because of the asymmetric ``three-voice'' nature of most sidtunes, it is 181 // strongly advised to *not* use plain stereo without pan-positioning the 182 // voices. 183 // 184 // int digiPlayerScans; 185 // 186 // If the integer above is set to ``x'', the sidtune will be scanned x player 187 // calls for PlaySID digis on the fourth channel. If no digis are used, the 188 // sidtune is hopefully ``three-voice-only'' and can be amplified a little bit. 189 // 190 // 191 // SIDEMU_NONE 192 // 193 // No volume control at all. Volume level of each voice is not adjustable. 194 // Voices cannot be turned off. No panning possible. Most likely maximum 195 // software mixing speed. 196 // 197 // 198 // SIDEMU_VOLCONTROL 199 // 200 // In SIDEMU_STEREO mode two voices should build a pair, satisfying the 201 // equation (leftlevel_A + leftlevel_B) <= 255. Generally, the equations: 202 // sum leftLevel(i) <= 512 and sum rightLevel(i) <= 512 203 // must be satisfied, i = [1,2,3,4]. 204 // 205 // In SIDEMU_MONO mode only the left level is used to specify a voice's 206 // volume. If you specify a right level, it will be set to zero. 207 // 208 // 209 // SIDEMU_FULLPANNING 210 // 211 // Volume level of each voice is adjustable between 255 (max) and 0 (off). 212 // Each voice can be freely positioned between left and right, or both. 213 // 214 // 215 // SIDEMU_STEREOSURROUND 216 // 217 // Volume level of each voice is adjustable between 255 (max) and 0 (off). 218 // Each voice can be freely positioned between left and right. 219 // Effect is best for left=255 plus right=255. 220 // 221 // 222 // SIDEMU_HWMIXING 223 // 224 // Used for external mixing only. The sample buffer is split into four (4) 225 // equivalent chunks, each representing a single voice. The client has to 226 // take care of the sample buffer length to be dividable by four. 227 228 229 class sidTune; 230 231 232 class emuEngine 233 { 234 public: // --------------------------------------------------------- public 235 236 // The constructor creates and initializes the object with defaults. 237 // Upon successful creation, use emuEngine::getConfig(...) to 238 // retrieve the default settings. 239 emuEngine(); 240 virtual ~emuEngine(); // destructor 241 242 const char* getVersionString(); 243 244 // Set and retrieve the SID emulator settings. Invalid values will not 245 // be accepted. 246 // Returns: false, if invalid values. 247 // true, else. 248 bool setConfig( struct emuConfig& ); 249 void getConfig( struct emuConfig& ); 250 251 // Use this function together with a valid sidTune-object to fill 252 // a buffer with calculated sample data. 253 friend void sidEmuFillBuffer(emuEngine&, sidTune&, 254 void* buffer, udword bufLen ); 255 256 // See ``sidtune.h'' for info on these. 257 friend bool sidEmuInitializeSong(emuEngine &, sidTune &, uword songNum); 258 friend bool sidEmuInitializeSongOld(emuEngine &, sidTune &, uword songNum); 259 260 // Reset the filter parameters to default settings. 261 void setDefaultFilterStrength(); 262 263 // This will even work during playback, but only in volume control modes 264 // SIDEMU_VOLCONTROL, SIDEMU_FULLPANNING or SIDEMU_STEREOSURROUND. For the 265 // modes SIDEMU_NONE or SIDEMU_HWMIXING this function has no effect. 266 // 267 // voice=[1,2,3,4], leftLevel=[0,..,255], rightLevel=[0,...,255] 268 // total: 0=mute, ~128=middle, 256=max 269 bool setVoiceVolume(int voice, ubyte leftLevel, ubyte rightLevel, uword total); 270 271 // Returns: high-byte = left level, low-byte = right level. 272 uword getVoiceVolume(int voice); 273 274 // Only useful to determine the state of a newly created object and 275 // the current state after returning from a member function. 276 operator bool() { return isReady; } getStatus()277 bool getStatus() { return isReady; } 278 279 // Public to the user, but need not be used explicitly. 280 bool reset(); 281 bool resetSampleEmu(); 282 void amplifyThreeVoiceTunes(bool isThreeVoiceTune); 283 284 // Used for a run-time endianess check on Unix. Verifies the compiled 285 // code and returns ``false'' if incorrectly set up. 286 bool verifyEndianess(); 287 288 #if defined(SIDEMU_TIME_COUNT) 289 int getSecondsThisSong(); 290 int getSecondsTotal(); 291 resetSecondsThisSong()292 void resetSecondsThisSong() { secondsThisSong = 0; } 293 #endif 294 295 296 protected: // --------------------------------------------------- protected 297 298 // Set a random (!) random seed value. 299 virtual void setRandomSeed(); // default uses ``time.h'' 300 301 302 private: // ------------------------------------------------------- private 303 304 bool isReady; 305 emuConfig config; 306 307 #if defined(SIDEMU_TIME_COUNT) 308 // Used for time and listening mileage. 309 udword bytesCountTotal, bytesCountSong; 310 int secondsTotal, secondsThisSong; 311 #endif 312 313 // 6510-interpreter. 314 // 315 bool MPUstatus; 316 int memoryMode, clockSpeed; 317 ubyte randomSeed; 318 319 void MPUreset(); 320 ubyte * MPUreturnRAMbase(); 321 322 // 323 bool isThreeVoiceAmplified; // keep track of current mixer state 324 bool isThreeVoiceTune; // this toggled from outside 325 326 bool freeMem(); 327 bool allocMem(); 328 void configureSID(); 329 void initMixerEngine(); 330 void initMixerFunction(); 331 void setDefaultVoiceVolumes(); 332 void filterTableInit(); 333 334 emuEngine(const emuEngine&); 335 emuEngine& operator=(emuEngine&); 336 }; 337 338 339 #endif /* SIDPLAY1_EMUCFG_H */ 340