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