Mercurial > hg > dmlib
annotate jssplr.c @ 136:8ac24d753304
Cleanups.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 05 Oct 2012 04:11:24 +0300 |
parents | ff0fe1d1ab3d |
children | 69e3041032e9 |
rev | line source |
---|---|
0 | 1 /* |
2 * miniJSS - Module playing routines | |
3 * Programmed and designed by Matti 'ccr' Hamalainen | |
4 * (C) Copyright 2006-2009 Tecnic Software productions (TNSP) | |
5 */ | |
6 #include "jssplr.h" | |
7 #include <string.h> | |
8 #include <stdlib.h> | |
9 | |
10 // FIXME!! FIX ME! | |
11 #include <math.h> | |
12 | |
13 /* Miscellaneous tables | |
14 */ | |
15 #define jmpNSineTable (256) | |
16 static int *jmpSineTable = NULL; | |
17 | |
18 | |
19 static const Sint16 jmpXMAmigaPeriodTab[13 * 8] = { | |
20 907, 900, 894, 887, 881, 875, 868, 862, 856, 850, 844, 838, | |
21 832, 826, 820, 814, 808, 802, 796, 791, 785, 779, 774, 768, | |
22 762, 757, 752, 746, 741, 736, 730, 725, 720, 715, 709, 704, | |
23 699, 694, 689, 684, 678, 675, 670, 665, 660, 655, 651, 646, | |
24 640, 636, 632, 628, 623, 619, 614, 610, 604, 601, 597, 592, | |
25 588, 584, 580, 575, 570, 567, 563, 559, 555, 551, 547, 543, | |
26 538, 535, 532, 528, 524, 520, 516, 513, 508, 505, 502, 498, | |
27 494, 491, 487, 484, 480, 477, 474, 470, 467, 463, 460, 457, | |
28 | |
29 453, 450, 447, 443, 440, 437, 434, 431 | |
30 }; | |
31 | |
32 | |
33 #define jmpNMODEffectTable (36) | |
34 static const char jmpMODEffectTable[jmpNMODEffectTable] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
35 | |
36 | |
37 /* Helper functions | |
38 */ | |
136 | 39 static int jmpNoteToAmigaPeriod(int note, int finetune) |
0 | 40 { |
41 int tmp = (note + finetune + 8); | |
42 if (tmp < 0) tmp = 0; else | |
43 if (tmp > 103) tmp = 103; | |
44 return jmpXMAmigaPeriodTab[tmp]; | |
45 } | |
46 | |
47 | |
48 static int jmpGetPeriodFromNote(JSSPlayer *mp, int note, int finetune) | |
49 { | |
50 int res; | |
51 | |
52 if (JMPGETMODFLAGS(mp, jmdfAmigaPeriods)) | |
53 { | |
54 int mfinetune = finetune / 16, | |
55 mnote = (note % 12) * 8, | |
56 moctave = note / 12, | |
57 period1, period2; | |
58 | |
59 period1 = jmpNoteToAmigaPeriod(mnote, mfinetune); | |
60 | |
61 if (finetune < 0) | |
62 { | |
63 mfinetune--; | |
64 finetune = -finetune; | |
65 } else | |
66 mfinetune++; | |
67 | |
68 period2 = jmpNoteToAmigaPeriod(mnote, mfinetune); | |
69 | |
70 mfinetune = finetune & 15; | |
71 period1 *= (16 - mfinetune); | |
72 period2 *= mfinetune; | |
73 | |
74 res = ((period1 + period2) * 2) >> moctave; | |
75 | |
76 //fprintf(stderr, "jmpGetAmigaPeriod(%d, %d) = %d\n", note, finetune, res); | |
77 } | |
78 else | |
79 { | |
80 //fprintf(stderr, "jmpGetLinearPeriod(%d, %d) = %d\n", note, finetune, res); | |
81 //res = ((120 - note) << 6) - (finetune / 2); | |
82 res = 7680 - (note * 64) - (finetune / 2); | |
83 if (res < 1) res = 1; | |
84 } | |
85 | |
86 return res; | |
87 } | |
88 | |
89 | |
90 static void jmpCSetPitch(JSSPlayer *mp, int channel, int value) | |
91 { | |
92 assert(mp != NULL); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
93 assert(mp->device != NULL); |
0 | 94 |
95 if (value > 0) | |
96 { | |
97 if (JMPGETMODFLAGS(mp, jmdfAmigaPeriods)) | |
98 { | |
99 // Frequency = 8363*1712 / Period | |
100 //fprintf(stderr, "jmpCSetPitch::AMIGA(%d, %d)\n", channel, value); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
101 jvmSetFreq(mp->device, channel, 14317456.0f / (double) value); |
0 | 102 } |
103 else | |
104 { | |
105 // Frequency = Frequency = 8363*2^((6*12*16*4 - Period) / (12*16*4)) | |
106 //fprintf(stderr, "jmpCSetPitch::Linear(%d, %d)\n", channel, value); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
107 jvmSetFreq(mp->device, channel, |
0 | 108 8363.0f * pow(2.0f, (4608.0f - (double) value) / 768.0f)); |
109 } | |
110 } | |
111 } | |
112 | |
113 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
114 static void jmpCSetVolume(JSSPlayer * mp, JSSPlayerChannel *chn, int channel, int volume) |
0 | 115 { |
116 assert(mp != NULL); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
117 assert(mp->device != NULL); |
0 | 118 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
119 if (volume < mpMinVol) volume = mpMinVol; else |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
120 if (volume > mpMaxVol) volume = mpMaxVol; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
121 |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
122 //fprintf(stderr, "chn %d: vol=%d, fad=%d, env=%d\n", channel, volume, chn->iCFadeOutVol, chn->iCVolEnv); |
135
ff0fe1d1ab3d
Implement using of volume ramps in the player code. This MAY or MAY NOT be
Matti Hamalainen <ccr@tnsp.org>
parents:
61
diff
changeset
|
123 /* |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
124 jvmSetVolume(mp->device, channel, |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
125 (chn->iCFadeOutVol * chn->iCVolEnv * volume) / (16 * 65536)); |
135
ff0fe1d1ab3d
Implement using of volume ramps in the player code. This MAY or MAY NOT be
Matti Hamalainen <ccr@tnsp.org>
parents:
61
diff
changeset
|
126 */ |
ff0fe1d1ab3d
Implement using of volume ramps in the player code. This MAY or MAY NOT be
Matti Hamalainen <ccr@tnsp.org>
parents:
61
diff
changeset
|
127 jvmSetVolumeRamp(mp->device, channel, jvmGetVolume(mp->device, channel), |
ff0fe1d1ab3d
Implement using of volume ramps in the player code. This MAY or MAY NOT be
Matti Hamalainen <ccr@tnsp.org>
parents:
61
diff
changeset
|
128 (chn->iCFadeOutVol * chn->iCVolEnv * volume) / (16 * 65536)); |
0 | 129 } |
130 | |
131 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
132 static void jmpCSetPanning(JSSPlayer * mp, JSSPlayerChannel *chn, int channel, int panning) |
0 | 133 { |
134 assert(mp != NULL); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
135 assert(mp->device != NULL); |
0 | 136 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
137 jvmSetPan(mp->device, channel, |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
138 panning + (((chn->iCPanEnv - 32) * (128 - abs(panning - 128))) / 32)); |
0 | 139 } |
140 | |
141 | |
142 static void jmpCSetPosition(JSSPlayer * mp, int channel, int value) | |
143 { | |
144 assert(mp != NULL); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
145 assert(mp->device != NULL); |
0 | 146 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
147 jvmSetPos(mp->device, channel, value); |
0 | 148 } |
149 | |
150 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
151 static int jmpFindEnvPoint(JSSEnvelope * env, const int pos) |
0 | 152 { |
153 int i; | |
154 | |
155 for (i = 0; i < env->npoints - 1; i++) | |
156 { | |
157 if (env->points[i].frame <= pos && | |
158 env->points[i + 1].frame >= pos) | |
159 return i; | |
160 } | |
161 | |
162 return -1; | |
163 } | |
164 | |
165 | |
166 static void jmpExecEnvelope(JSSEnvelope * env, BOOL keyOff, int * frames, BOOL * doExec, int * result) | |
167 { | |
168 int currPoint, delta; | |
169 JSSEnvelopePoint *ipf1, *ipf2; | |
170 | |
171 // OK, find the current point based on frame | |
172 currPoint = jmpFindEnvPoint(env, *frames); | |
173 | |
174 // Check if the envelope has ended | |
175 if (currPoint < 0 && (env->flags & jenvfLooped) == 0) | |
176 { | |
177 *doExec = FALSE; | |
178 return; | |
179 } | |
180 | |
181 // Do the envelope looping here, if needed | |
182 if ((env->flags & jenvfLooped) && *frames >= env->points[env->loopE].frame) | |
183 { | |
184 currPoint = env->loopS; | |
185 *frames = env->points[currPoint].frame; | |
186 } | |
187 | |
188 // If the current point is OK, then process the envelope | |
189 if (currPoint >= 0) | |
190 { | |
191 // Linearly interpolate the value for given frame | |
192 ipf1 = &env->points[currPoint]; | |
193 ipf2 = &env->points[currPoint + 1]; | |
194 | |
195 delta = (ipf2->frame - ipf1->frame); | |
196 if (delta > 0) | |
197 *result = ipf1->value + ((ipf2->value - ipf1->value) * (*frames - ipf1->frame)) / delta; | |
198 else | |
199 *result = ipf1->value; | |
200 } | |
201 | |
202 // The frame counter IS processed even if the envelope is not! | |
203 if ((env->flags & jenvfSustain) && currPoint == env->sustain && | |
204 env->points[currPoint].frame == env->points[env->sustain].frame) { | |
205 if (keyOff) (*frames)++; | |
206 } else | |
207 (*frames)++; | |
208 } | |
209 | |
210 | |
61
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
211 static void jmpProcessExtInstrument(JSSPlayerChannel *chn, int channel) |
0 | 212 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
213 JSSExtInstrument *inst = chn->iCExtInstrument; |
61
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
214 (void) channel; |
0 | 215 |
216 // Get the instrument for envelope data | |
217 if (!inst) return; | |
218 | |
219 // Process the autovibrato | |
220 /* | |
221 FIXME fix me FIX me!!! todo. | |
222 */ | |
223 | |
224 // Process the volume envelope | |
225 if (inst->volumeEnv.flags & jenvfUsed) | |
226 { | |
227 // Process the instrument volume fadeout | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
228 if (chn->iCKeyOff && chn->iCFadeOutVol > 0 && inst->fadeOut > 0) |
0 | 229 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
230 int tmp = chn->iCFadeOutVol - inst->fadeOut; |
0 | 231 if (tmp < 0) tmp = 0; |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
232 chn->iCFadeOutVol = tmp; |
0 | 233 |
234 JMPSETNDFLAGS(cdfNewVolume); | |
235 } | |
236 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
237 if (chn->iCVolEnv_Exec) |
0 | 238 { |
239 // Execute the volume envelope | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
240 jmpExecEnvelope(&(inst->volumeEnv), |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
241 chn->iCKeyOff, |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
242 &(chn->iCVolEnv_Frames), &(chn->iCVolEnv_Exec), |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
243 &(chn->iCVolEnv)); |
0 | 244 |
245 JMPSETNDFLAGS(cdfNewVolume); | |
246 } | |
247 } | |
248 else | |
249 { | |
250 // If the envelope is not used, set max volume | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
251 if (chn->iCVolEnv != mpMaxVol) |
0 | 252 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
253 chn->iCVolEnv = mpMaxVol; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
254 chn->iCFadeOutVol = mpMaxFadeoutVol; |
0 | 255 JMPSETNDFLAGS(cdfNewVolume); |
256 } | |
257 } | |
258 | |
259 // Process the panning envelope | |
260 if (inst->panningEnv.flags & jenvfUsed) | |
261 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
262 if (chn->iCPanEnv_Exec) |
0 | 263 { |
264 // Execute the panning envelope | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
265 jmpExecEnvelope(&(inst->panningEnv), chn->iCKeyOff, |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
266 &(chn->iCPanEnv_Frames), &(chn->iCPanEnv_Exec), |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
267 &(chn->iCPanEnv)); |
0 | 268 |
269 JMPSETNDFLAGS(cdfNewPanPos); | |
270 } | |
271 } | |
272 else | |
273 { | |
274 // If the envelope is not used, set center panning | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
275 if (chn->iCPanEnv != mpPanCenter) |
0 | 276 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
277 chn->iCPanEnv = mpPanCenter; |
0 | 278 JMPSETNDFLAGS(cdfNewPanPos); |
279 } | |
280 } | |
281 } | |
282 | |
283 | |
284 /* | |
285 * The player | |
286 */ | |
287 JSSPlayer *jmpInit(JSSMixer *pDevice) | |
288 { | |
289 JSSPlayer *mp; | |
290 | |
291 // Initialize global tables | |
292 if (jmpSineTable == NULL) | |
293 { | |
294 int i; | |
295 if ((jmpSineTable = dmMalloc(jmpNSineTable * sizeof(int))) == NULL) | |
296 JSSERROR(DMERR_MALLOC, NULL, "Could not allocate memory for sinus table.\n"); | |
297 | |
298 for (i = 0; i < 256; i++) | |
299 { | |
300 float f = ((float) i * M_PI * 2.0f) / 256.0f; | |
301 jmpSineTable[i] = (int) (sin(f) * 2048.0f); | |
302 } | |
303 } | |
304 | |
305 // Allocate a player structure | |
306 mp = dmMalloc0(sizeof(JSSPlayer)); | |
307 if (!mp) | |
308 JSSERROR(DMERR_MALLOC, NULL, "Could not allocate memory for player structure.\n"); | |
309 | |
310 // Set variables | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
311 mp->device = pDevice; |
0 | 312 #ifdef JSS_SUP_THREADS |
313 mp->mutex = dmCreateMutex(); | |
314 #endif | |
315 | |
316 return mp; | |
317 } | |
318 | |
319 | |
320 int jmpClose(JSSPlayer * mp) | |
321 { | |
322 if (mp == NULL) | |
323 return DMERR_NULLPTR; | |
324 | |
325 // Stop player | |
326 jmpStop(mp); | |
327 | |
328 // Deallocate resources | |
329 #ifdef JSS_SUP_THREADS | |
330 dmDestroyMutex(mp->mutex); | |
331 #endif | |
332 | |
333 // Clear structure | |
334 memset(mp, 0, sizeof(JSSPlayer)); | |
335 dmFree(mp); | |
336 | |
337 return DMERR_OK; | |
338 } | |
339 | |
340 | |
341 /* Reset the envelopes for given channel. | |
342 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
343 static void jmpResetEnvelopes(JSSPlayerChannel *chn) |
0 | 344 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
345 chn->iCPanEnv_Frames = chn->iCVolEnv_Frames = 0; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
346 chn->iCPanEnv_Exec = chn->iCVolEnv_Exec = TRUE; |
0 | 347 } |
348 | |
349 | |
350 /* Clear module player structure | |
351 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
352 void jmpClearChannel(JSSPlayerChannel *chn) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
353 { |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
354 memset(chn, 0, sizeof(JSSPlayerChannel)); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
355 |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
356 chn->iCNote = jsetNotSet; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
357 chn->iCInstrumentN = jsetNotSet; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
358 chn->iCExtInstrumentN = jsetNotSet; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
359 chn->iCPanning = mpPanCenter; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
360 chn->iCPanEnv = mpPanCenter; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
361 } |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
362 |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
363 |
0 | 364 void jmpClearPlayer(JSSPlayer * mp) |
365 { | |
366 int i; | |
367 assert(mp != NULL); | |
368 JSS_LOCK(mp); | |
369 | |
370 // Initialize general variables | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
371 mp->patternDelay = 0; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
372 mp->newRowSet = FALSE; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
373 mp->newOrderSet = FALSE; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
374 mp->tick = jsetNotSet; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
375 mp->row = 0; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
376 mp->lastPatLoopRow = 0; |
0 | 377 |
378 // Initialize channel data | |
379 for (i = 0; i < jsetNChannels; i++) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
380 jmpClearChannel(&mp->channels[i]); |
0 | 381 |
382 JSS_UNLOCK(mp); | |
383 } | |
384 | |
385 | |
386 /* Set module | |
387 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
388 void jmpSetModule(JSSPlayer * mp, JSSModule * module) |
0 | 389 { |
390 assert(mp != NULL); | |
391 JSS_LOCK(mp); | |
392 | |
393 jmpStop(mp); | |
394 jmpClearPlayer(mp); | |
395 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
396 mp->module = module; |
0 | 397 |
398 JSS_UNLOCK(mp); | |
399 } | |
400 | |
401 | |
402 /* Stop playing | |
403 */ | |
404 void jmpStop(JSSPlayer * mp) | |
405 { | |
406 assert(mp != NULL); | |
407 JSS_LOCK(mp); | |
408 | |
409 if (mp->isPlaying) | |
410 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
411 jvmRemoveCallback(mp->device); |
0 | 412 mp->isPlaying = FALSE; |
413 } | |
414 | |
415 JSS_UNLOCK(mp); | |
416 } | |
417 | |
418 | |
419 /* Resume playing | |
420 */ | |
421 void jmpResume(JSSPlayer * mp) | |
422 { | |
423 assert(mp != NULL); | |
424 JSS_LOCK(mp); | |
425 | |
426 if (!mp->isPlaying) | |
427 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
428 int result = jvmSetCallback(mp->device, jmpExec, (void *) mp); |
0 | 429 if (result != DMERR_OK) |
430 JSSERROR(result,, "Could not initialize callback for player.\n"); | |
431 | |
432 mp->isPlaying = TRUE; | |
433 } | |
434 | |
435 JSS_UNLOCK(mp); | |
436 } | |
437 | |
438 | |
439 /* Sets new order using given value as reference. | |
440 * Jumps over skip-points and invalid values, loops | |
441 * to first order if enabled. | |
442 */ | |
443 static void jmpSetNewOrder(JSSPlayer * mp, int order) | |
444 { | |
445 BOOL orderOK; | |
446 int pattern; | |
447 | |
448 pattern = jsetOrderEnd; | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
449 mp->order = jsetNotSet; |
0 | 450 orderOK = FALSE; |
451 | |
452 while (!orderOK) | |
453 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
454 if (order < 0 || order >= mp->module->norders) |
0 | 455 { |
456 jmpStop(mp); | |
457 orderOK = TRUE; | |
458 } | |
459 else | |
460 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
461 pattern = mp->module->orderList[order]; |
0 | 462 if (pattern == jsetOrderSkip) |
463 { | |
464 order++; | |
465 } | |
466 else | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
467 if (pattern >= mp->module->npatterns || pattern == jsetOrderEnd) |
0 | 468 { |
469 jmpStop(mp); | |
470 orderOK = TRUE; | |
471 } | |
472 else | |
473 { | |
474 // All OK | |
475 orderOK = TRUE; | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
476 mp->pattern = mp->module->patterns[pattern]; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
477 mp->npattern = pattern; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
478 mp->order = order; |
0 | 479 } |
480 } | |
481 } | |
482 } | |
483 | |
484 | |
485 /* Set new tempo-value of the player. | |
486 */ | |
136 | 487 static void jmpSetTempo(JSSPlayer * mp, int tempo) |
0 | 488 { |
489 assert(mp != NULL); | |
490 JSS_LOCK(mp); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
491 assert(mp->device != NULL); |
0 | 492 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
493 mp->tempo = tempo; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
494 jvmSetCallbackFreq(mp->device, (tempo * 2) / 5); |
0 | 495 JSS_UNLOCK(mp); |
496 } | |
497 | |
498 | |
136 | 499 static void jmpClearChannels(JSSPlayer * mp) |
0 | 500 { |
501 int i; | |
502 assert(mp != NULL); | |
503 JSS_LOCK(mp); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
504 assert(mp->device != NULL); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
505 assert(mp->module != NULL); |
0 | 506 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
507 for (i = 0; i < mp->module->nchannels; i++) |
0 | 508 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
509 jvmStop(mp->device, i); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
510 jvmClear(mp->device, i); |
0 | 511 } |
512 | |
513 JSS_UNLOCK(mp); | |
514 } | |
515 | |
516 | |
517 /* Starts playing module from a given ORDER. | |
518 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
519 int jmpPlayOrder(JSSPlayer * mp, int order) |
0 | 520 { |
521 int result; | |
522 assert(mp != NULL); | |
523 | |
524 JSS_LOCK(mp); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
525 assert(mp->module != NULL); |
0 | 526 |
527 // Stop if already playing | |
528 jmpStop(mp); | |
529 jmpClearChannels(mp); | |
530 | |
531 // Check starting order | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
532 if (order < 0 || order >= mp->module->norders) |
0 | 533 { |
534 JSS_UNLOCK(mp); | |
535 JSSERROR(DMERR_INVALID_ARGS, DMERR_INVALID_ARGS, "Invalid playing startorder given.\n"); | |
536 } | |
537 | |
538 // Initialize playing | |
539 jmpClearPlayer(mp); | |
540 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
541 jmpSetNewOrder(mp, order); |
0 | 542 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
543 if (mp->order == jsetNotSet) |
0 | 544 { |
545 JSS_UNLOCK(mp); | |
546 JSSERROR(DMERR_NOT_SUPPORTED, DMERR_NOT_SUPPORTED, | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
547 "Could not start playing from given order #%i\n", order); |
0 | 548 } |
549 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
550 mp->speed = mp->module->defSpeed; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
551 jmpSetTempo(mp, mp->module->defTempo); |
0 | 552 |
553 // Set callback | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
554 result = jvmSetCallback(mp->device, jmpExec, (void *) mp); |
0 | 555 if (result != DMERR_OK) |
556 { | |
557 JSS_UNLOCK(mp); | |
558 JSSERROR(result, result, "Could not initialize callback for player.\n"); | |
559 } | |
560 | |
561 mp->isPlaying = TRUE; | |
562 | |
563 JSS_UNLOCK(mp); | |
564 return 0; | |
565 } | |
566 | |
567 | |
568 /* Play given pattern | |
569 */ | |
570 int jmpPlayPattern(JSSPlayer * mp, int pattern) | |
571 { | |
572 int result; | |
573 assert(mp != NULL); | |
574 JSS_LOCK(mp); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
575 assert(mp->module != NULL); |
0 | 576 |
577 // Stop if already playing | |
578 jmpStop(mp); | |
579 jmpClearChannels(mp); | |
580 | |
581 // Initialize playing | |
582 jmpClearPlayer(mp); | |
583 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
584 mp->npattern = pattern; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
585 mp->speed = mp->module->defSpeed; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
586 jmpSetTempo(mp, mp->module->defTempo); |
0 | 587 |
588 // Set callback | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
589 result = jvmSetCallback(mp->device, jmpExec, (void *) mp); |
0 | 590 if (result != DMERR_OK) |
591 { | |
592 JSS_UNLOCK(mp); | |
593 JSSERROR(result, result, "Could not initialize callback for player.\n"); | |
594 } | |
595 | |
596 mp->isPlaying = TRUE; | |
597 | |
598 JSS_UNLOCK(mp); | |
599 return 0; | |
600 } | |
601 | |
602 | |
603 /* Set volume for given module channel. | |
604 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
605 static void jmpSetVolume(JSSPlayerChannel * chn, int channel, int volume) |
0 | 606 { |
61
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
607 (void) channel; |
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
608 |
0 | 609 // Check values |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
610 if (volume < mpMinVol) volume = mpMinVol; else |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
611 if (volume > mpMaxVol) volume = mpMaxVol; |
0 | 612 |
613 // Set the volume | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
614 chn->iCVolume = volume; |
0 | 615 JMPSETNDFLAGS(cdfNewVolume); |
616 } | |
617 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
618 #define jmpChangeVolume(Q, Z, X) jmpSetVolume(Q, Z, chn->iCVolume + (X)) |
0 | 619 |
620 | |
621 /* Change the pitch of given channel by ADelta. | |
622 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
623 static void jmpChangePitch(JSSPlayerChannel *chn, int channel, int delta) |
0 | 624 { |
625 int value; | |
61
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
626 (void) channel; |
0 | 627 |
628 // Calculate new pitch and check it | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
629 value = chn->iCPitch + delta; |
0 | 630 if (value < 0) |
631 value = 0; | |
632 | |
633 // Set the new pitch | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
634 chn->iCPitch = value; |
0 | 635 JMPSETNDFLAGS(cdfNewPitch); |
636 } | |
637 | |
638 | |
639 /* Do a note portamento (pitch slide) effect for given module channel. | |
640 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
641 static void jmpDoPortamento(JSSPlayerChannel * chn, int channel) |
0 | 642 { |
61
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
643 (void) channel; |
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
644 |
0 | 645 // Check for zero parameter |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
646 if (chn->iLastPortaToNoteParam == 0) |
0 | 647 { |
648 JMPSETNDFLAGS(cdfNewPitch); | |
649 return; | |
650 } | |
651 | |
652 /* Slide the pitch of channel to the destination value | |
653 * with speed of iLastPortaToNoteParam[] * 4 and stop when it equals. | |
654 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
655 if (chn->iCPitch != chn->iLastPortaToNotePitch) |
0 | 656 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
657 if (chn->iCPitch < chn->iLastPortaToNotePitch) |
0 | 658 { |
659 // Increase pitch UP | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
660 jmpChangePitch(chn, channel, chn->iLastPortaToNoteParam * 4); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
661 if (chn->iCPitch > chn->iLastPortaToNotePitch) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
662 chn->iCPitch = chn->iLastPortaToNotePitch; |
0 | 663 } |
664 else | |
665 { | |
666 // Decrease pitch DOWN | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
667 jmpChangePitch(chn, channel, -(chn->iLastPortaToNoteParam * 4)); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
668 if (chn->iCPitch < chn->iLastPortaToNotePitch) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
669 chn->iCPitch = chn->iLastPortaToNotePitch; |
0 | 670 } |
671 } | |
672 } | |
673 | |
674 | |
675 /* Do a tremolo effect for given module channel. | |
676 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
677 static void jmpDoTremolo(JSSPlayer * mp, JSSPlayerChannel *chn, int channel) |
0 | 678 { |
679 int delta, pos, depth; | |
680 | |
681 // Check settings | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
682 if (chn->iTremoloDepth == 0 || chn->iTremoloSpeed == 0) |
0 | 683 return; |
684 | |
685 // Get position of tremolo waveform | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
686 pos = chn->iTremoloPos & 255; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
687 depth = chn->iTremoloDepth; |
0 | 688 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
689 switch (chn->iTremoloWC & 3) |
0 | 690 { |
691 case 0: // Sine-wave | |
692 delta = (jmpSineTable[pos] * depth) / 2048; | |
693 break; | |
694 | |
695 case 1: // Ramp down | |
696 delta = ((pos - 128) * depth) / 128; | |
697 break; | |
698 | |
699 case 2: // Square | |
700 delta = (((pos & 128) - 64) * depth) / 64; | |
701 break; | |
702 | |
703 default: | |
704 return; | |
705 } | |
706 | |
707 // Set the new volume | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
708 jmpCSetVolume(mp, chn, channel, chn->iCVolume + delta); |
0 | 709 |
710 // Advance tremolo waveform position | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
711 chn->iTremoloPos += chn->iTremoloSpeed; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
712 if (chn->iTremoloPos > 255) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
713 chn->iTremoloPos = 0; |
0 | 714 } |
715 | |
716 | |
717 /* Do a vibrato effect for given module channel. | |
718 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
719 static void jmpDoVibrato(JSSPlayer * mp, JSSPlayerChannel *chn, int channel) |
0 | 720 { |
721 int delta, pos, depth; | |
722 | |
723 // Check settings | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
724 if (chn->iVibratoDepth == 0 || chn->iVibratoSpeed == 0) |
0 | 725 return; |
726 | |
727 // Get position of vibrato waveform | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
728 pos = chn->iVibratoPos & 255; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
729 depth = chn->iVibratoDepth; |
0 | 730 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
731 switch (chn->iVibratoWC & 3) |
0 | 732 { |
733 case 0: // Sine-wave | |
734 delta = (jmpSineTable[pos] * depth) / 2048; | |
735 break; | |
736 | |
737 case 1: // Ramp down | |
738 delta = ((pos - 128) * depth) / 16; | |
739 break; | |
740 | |
741 case 2: // Square | |
742 delta = (((pos & 128) - 64) * depth) / 8; | |
743 break; | |
744 | |
745 default: | |
746 return; | |
747 } | |
748 | |
749 // Set the new frequency | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
750 jmpCSetPitch(mp, channel, chn->iCPitch + delta); |
0 | 751 |
752 // Advance vibrato waveform position | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
753 chn->iVibratoPos += chn->iVibratoSpeed; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
754 if (chn->iVibratoPos > 255) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
755 chn->iVibratoPos = 0; |
0 | 756 } |
757 | |
758 | |
759 /* Do a volume slide effect for given module channel. | |
760 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
761 static void jmpDoVolumeSlide(JSSPlayerChannel * chn, int channel, int param) |
0 | 762 { |
763 int paramX, paramY; | |
764 | |
765 JMPMAKEPARAM(param, paramX, paramY) | |
766 | |
767 if (paramY == 0) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
768 jmpChangeVolume(chn, channel, paramX); |
0 | 769 if (paramX == 0) |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
770 jmpChangeVolume(chn, channel, -paramY); |
0 | 771 } |
772 | |
773 | |
774 /* Execute a pattern loop effect/command for given module channel. | |
775 * | |
776 * This routine works for most of the supported formats, as they | |
777 * use the 'standard' implementation ascending from MOD. However, | |
778 * here is included also a slightly kludgy implementation of the | |
779 * FT2 patloop bug. | |
780 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
781 static void jmpDoPatternLoop(JSSPlayer * mp, JSSPlayerChannel *chn, int channel, int paramY) |
0 | 782 { |
61
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
783 (void) channel; |
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
784 |
0 | 785 // Check what we need to do |
786 if (paramY > 0) | |
787 { | |
788 // SBx/E6x loops 'x' times | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
789 if (chn->iPatLoopCount == 1) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
790 chn->iPatLoopCount = 0; |
0 | 791 else |
792 { | |
793 // Check if we need to set the count | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
794 if (chn->iPatLoopCount == 0) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
795 chn->iPatLoopCount = (paramY + 1); |
0 | 796 |
797 // Loop to specified row | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
798 chn->iPatLoopCount--; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
799 mp->newRow = chn->iPatLoopRow; |
0 | 800 mp->newRowSet = TRUE; |
801 } | |
802 } | |
803 else | |
804 { | |
805 // SB0/E60 sets the loop start point | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
806 chn->iPatLoopRow = mp->row; |
0 | 807 |
808 // This is here because of the infamous FT2 patloop bug | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
809 mp->lastPatLoopRow = mp->row; |
0 | 810 } |
811 } | |
812 | |
813 | |
814 /* Do arpeggio effect | |
815 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
816 static void jmpDoArpeggio(JSSPlayer * mp, JSSPlayerChannel *chn, int channel, int paramY, int paramX) |
0 | 817 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
818 JSSInstrument *tempInst = chn->iCInstrument; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
819 |
0 | 820 if (tempInst) |
821 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
822 int tmp = chn->iCNote; |
0 | 823 if (tmp == jsetNotSet || tmp == jsetNoteOff) return; |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
824 switch (mp->tick & 3) |
0 | 825 { |
826 case 1: | |
827 tmp += paramX; | |
828 break; | |
829 case 2: | |
830 tmp += paramY; | |
831 break; | |
832 } | |
833 jmpCSetPitch(mp, channel, jmpGetPeriodFromNote(mp, tmp + tempInst->ERelNote, tempInst->EFineTune)); | |
834 } | |
835 } | |
836 | |
837 | |
838 /* | |
839 * Process pattern effects | |
840 */ | |
841 static void jmpProcessRowEffect(JSSPlayer * mp, int channel, JSSNote * currNote) | |
842 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
843 JSSPlayerChannel *chn = &(mp->channels[channel]); |
0 | 844 int param, paramX, paramY; |
845 char effect; | |
846 | |
847 param = currNote->param; | |
848 JMPMAKEPARAM(param, paramX, paramY); | |
849 JMPGETEFFECT(effect, currNote->effect); | |
850 | |
851 switch (effect) | |
852 { | |
853 case '0': // 0xy = Arpeggio | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
854 jmpDoArpeggio(mp, chn, channel, paramX, paramY); |
0 | 855 break; |
856 | |
857 case 'W': // Used widely in demo-music as MIDAS Sound System sync-command | |
858 case 'Q': // SoundTracker/OpenCP: Qxx = Set LP filter resonance | |
859 case 'Z': // SoundTracker/OpenCP: Zxx = Set LP filter cutoff freq | |
860 break; | |
861 | |
862 case '1': | |
863 case '2': // 1xy = Portamento Up, 2xy = Portamento Down : IMPL.VERIFIED | |
864 if (param) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
865 chn->iLastPortaParam = param; |
0 | 866 break; |
867 | |
868 case '3': // 3xy = Porta To Note | |
869 if (param) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
870 chn->iLastPortaToNoteParam = param; |
0 | 871 |
872 if (currNote->note != jsetNotSet && currNote->note != jsetNoteOff) { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
873 chn->iLastPortaToNotePitch = chn->iCPitch; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
874 chn->iCPitch = chn->iCOldPitch; |
0 | 875 JMPUNSETNDFLAGS(cdfNewPitch | cdfNewInstr | cdfNewPanPos); |
876 } | |
877 break; | |
878 | |
879 case '4': // 4xy = Vibrato : IMPL.VERIFIED | |
880 if (paramX) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
881 chn->iVibratoSpeed = paramX; |
0 | 882 |
883 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
884 chn->iVibratoDepth = paramY; |
0 | 885 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
886 if ((chn->iVibratoWC & 4) == 0) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
887 chn->iVibratoPos = 0; |
0 | 888 break; |
889 | |
890 case '5': // 5xy = Portamento + Volume Slide | |
891 case '6': // 6xy = Vibrato + Volume slide | |
892 if (param) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
893 chn->iLastVolSlideParam = param; |
0 | 894 break; |
895 | |
896 case '7': // 7xy = Tremolo | |
897 if (paramX) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
898 chn->iTremoloSpeed = paramX; |
0 | 899 |
900 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
901 chn->iTremoloDepth = paramY; |
0 | 902 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
903 if ((chn->iTremoloWC & 4) == 0) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
904 chn->iTremoloPos = 0; |
0 | 905 break; |
906 | |
907 case '8': // 8xx = Set Panning | |
908 JMPDEBUG("Set Panning used, UNIMPLEMENTED"); | |
909 break; | |
910 | |
911 case '9': // 9xx = Set Sample Offset : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
912 if (chn->iCNewDataFlags & cdfNewPitch) |
30 | 913 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
914 chn->iCPosition = param * 0x100; |
0 | 915 JMPSETNDFLAGS(cdfNewPos); |
916 } | |
917 break; | |
918 | |
919 case 'A': // Axy = Volume Slide : IMPL.VERIFIED | |
920 if (param) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
921 chn->iLastVolSlideParam = param; |
0 | 922 break; |
923 | |
924 case 'B': // Bxx = Pattern Jump : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
925 mp->newOrder = param; |
0 | 926 mp->newOrderSet = TRUE; |
927 mp->jumpFlag = TRUE; | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
928 mp->lastPatLoopRow = 0; |
0 | 929 break; |
930 | |
931 case 'C': // Cxx = Set Volume : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
932 jmpSetVolume(chn, channel, param); |
0 | 933 break; |
934 | |
935 case 'D': // Dxx = Pattern Break : IMPL.VERIFIED | |
936 // Compute the new row | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
937 mp->newRow = (paramX * 10) + paramY; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
938 if (mp->newRow >= mp->pattern->nrows) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
939 mp->newRow = 0; |
0 | 940 |
941 mp->newRowSet = TRUE; | |
942 | |
943 // Now we do some tricky tests | |
944 if (!mp->breakFlag && !mp->jumpFlag) { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
945 mp->newOrder = mp->order + 1; |
0 | 946 mp->newOrderSet = TRUE; |
947 } | |
948 | |
949 mp->breakFlag = TRUE; | |
950 break; | |
951 | |
952 case 'E': // Exy = Special Effects | |
953 switch (paramX) { | |
954 case 0x00: // E0x - Set filter (NOT SUPPORTED) | |
955 JMPDEBUG("Set Filter used, UNSUPPORTED"); | |
956 break; | |
957 | |
958 case 0x01: // E1x - Fine Portamento Up | |
959 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
960 chn->iCLastFinePortamentoUpParam = paramY; |
0 | 961 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
962 jmpChangePitch(chn, channel, -(chn->iCLastFinePortamentoUpParam * 4)); |
0 | 963 break; |
964 | |
965 case 0x02: // E2x - Fine Portamento Down | |
966 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
967 chn->iCLastFinePortamentoDownParam = paramY; |
0 | 968 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
969 jmpChangePitch(chn, channel, (chn->iCLastFinePortamentoDownParam * 4)); |
0 | 970 break; |
971 | |
972 case 0x03: // E3x - Glissando Control (NOT SUPPORTED) | |
973 break; | |
974 | |
975 case 0x04: // E4x - Set Vibrato waveform | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
976 chn->iVibratoWC = paramY; |
0 | 977 break; |
978 | |
979 case 0x05: // E5x - Set Finetune | |
980 JMPDEBUG("Set Finetune used, UNIMPLEMENTED"); | |
981 break; | |
982 | |
983 case 0x06: // E6x - Set Pattern Loop | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
984 jmpDoPatternLoop(mp, chn, channel, paramY); |
0 | 985 break; |
986 | |
987 case 0x07: // E7x - Set Tremolo waveform | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
988 chn->iTremoloWC = paramY; |
0 | 989 break; |
990 | |
991 case 0x08: // E8x - Set Pan Position | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
992 chn->iCPanning = (paramY * 16); |
0 | 993 JMPSETNDFLAGS(cdfNewPanPos); |
994 break; | |
995 | |
996 case 0x09: // E9x - Retrig note | |
997 JMPDEBUG("Retrig Note used, UNIMPLEMENTED"); | |
998 break; | |
999 | |
1000 case 0x0a: // EAx - Fine Volumeslide Up | |
1001 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1002 chn->iCLastFineVolumeslideUpParam = paramY; |
0 | 1003 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1004 jmpChangeVolume(chn, channel, chn->iCLastFineVolumeslideUpParam); |
0 | 1005 break; |
1006 | |
1007 case 0x0b: // EBx - Fine Volumeslide Down | |
1008 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1009 chn->iCLastFineVolumeslideDownParam = paramY; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1010 jmpChangeVolume(chn, channel, -(chn->iCLastFineVolumeslideDownParam)); |
0 | 1011 break; |
1012 | |
1013 case 0x0c: // ECx - Set Note Cut (NOT PROCESSED IN TICK0) | |
1014 break; | |
1015 | |
1016 case 0x0d: // EDx - Set Note Delay : IMPL.VERIFIED | |
1017 if (paramY > 0) | |
1018 { | |
1019 // Save the ND-flags, then clear | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1020 chn->iSaveNDFlags = chn->iCNewDataFlags; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1021 chn->iCNewDataFlags = 0; |
0 | 1022 // TODO .. does this only affect NOTE or also instrument? |
1023 } | |
1024 break; | |
1025 | |
1026 case 0x0e: // EEx - Set Pattern Delay : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1027 mp->patternDelay = paramY; |
0 | 1028 break; |
1029 | |
1030 case 0x0f: // EFx - Invert Loop (NOT SUPPORTED) | |
1031 JMPDEBUG("Invert Loop used, UNSUPPORTED"); | |
1032 break; | |
1033 | |
1034 default: | |
1035 JMPDEBUG("Unsupported special command used"); | |
1036 } | |
1037 break; | |
1038 | |
1039 case 'F': // Fxy = Set Speed / Tempo : IMPL.VERIFIED | |
1040 if (param > 0) | |
1041 { | |
1042 if (param < 0x20) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1043 mp->speed = param; |
0 | 1044 else |
1045 jmpSetTempo(mp, param); | |
1046 } | |
1047 break; | |
1048 | |
1049 case 'G': // Gxx = Global Volume | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1050 mp->globalVol = param; |
0 | 1051 JMPSETNDFLAGS(cdfNewGlobalVol); |
1052 break; | |
1053 | |
1054 | |
1055 case 'H': // Hxx = Global Volume Slide | |
1056 JMPDEBUG("Global Volume Slide used, UNIMPLEMENTED"); | |
1057 break; | |
1058 | |
1059 case 'K': // Kxx = Key-off (Same as key-off note) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1060 chn->iCKeyOff = TRUE; |
0 | 1061 break; |
1062 | |
1063 case 'L': // Lxx = Set Envelope Position | |
1064 JMPDEBUG("Set Envelope Position used, NOT verified with FT2"); | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1065 chn->iCPanEnv_Frames = param; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1066 chn->iCVolEnv_Frames = param; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1067 chn->iCPanEnv_Exec = TRUE; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1068 chn->iCVolEnv_Exec = TRUE; |
0 | 1069 break; |
1070 | |
1071 case 'R': // Rxy = Multi Retrig note | |
1072 JMPDEBUG("Multi Retrig Note used, UNIMPLEMENTED"); | |
1073 break; | |
1074 | |
1075 case 'T': // Txy = Tremor | |
1076 if (param) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1077 chn->iLastTremorParam = param; |
0 | 1078 break; |
1079 | |
1080 case 'X': // Xxy = Extra Fine Portamento | |
1081 switch (paramX) | |
1082 { | |
1083 case 0x01: // X1y - Extra Fine Portamento Up | |
1084 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1085 chn->iCLastExtraFinePortamentoUpParam = paramY; |
0 | 1086 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1087 jmpChangePitch(chn, channel, - chn->iCLastExtraFinePortamentoUpParam); |
0 | 1088 break; |
1089 | |
1090 case 0x02: // X2y - Extra Fine Portamento Down | |
1091 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1092 chn->iCLastExtraFinePortamentoDownParam = paramY; |
0 | 1093 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1094 jmpChangePitch(chn, channel, chn->iCLastExtraFinePortamentoUpParam); |
0 | 1095 break; |
1096 | |
1097 default: | |
1098 JMPDEBUG("Unsupported value in Extra Fine Portamento command!"); | |
1099 break; | |
1100 } | |
1101 break; | |
1102 | |
1103 default: | |
1104 JMPDEBUG("Unsupported effect"); | |
1105 break; | |
1106 } | |
1107 } | |
1108 | |
1109 | |
1110 static void jmpProcessNewRow(JSSPlayer * mp, int channel) | |
1111 { | |
1112 JSSNote *currNote; | |
1113 JSSExtInstrument *extInst = NULL; | |
1114 JSSInstrument *inst = NULL; | |
1115 BOOL newNote = FALSE; | |
1116 int tmp, paramX, paramY; | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1117 JSSPlayerChannel *chn = &(mp->channels[channel]); |
0 | 1118 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1119 JMPGETNOTE(currNote, mp->row, channel); |
0 | 1120 |
1121 // Check for a new note/keyoff here | |
1122 if (currNote->note == jsetNoteOff) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1123 chn->iCKeyOff = TRUE; |
0 | 1124 else |
1125 if (currNote->note >= 0 && currNote->note <= 96) | |
1126 { | |
1127 // New note was set | |
1128 newNote = TRUE; | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1129 chn->iCNote = currNote->note; |
0 | 1130 } |
1131 | |
1132 // Check for new instrument | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1133 if (currNote->instrument != jsetNotSet) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1134 { |
0 | 1135 /* Envelopes and ext.instrument fadeout are initialized always if |
1136 * new instrument is set, even if the instrument does not exist. | |
1137 */ | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1138 jmpResetEnvelopes(chn); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1139 chn->iCKeyOff = FALSE; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1140 chn->iCFadeOutVol = mpMaxFadeoutVol; |
0 | 1141 |
1142 // We save the instrument number here for later use | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1143 if (currNote->instrument >= 0 && currNote->instrument < mp->module->nextInstruments) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1144 chn->iCExtInstrumentN = currNote->instrument; |
0 | 1145 } |
1146 | |
1147 /* ONLY if newNote was SET NOW and ExtInstrument HAS BEEN set, we can | |
1148 * set new pitches, and other things... | |
1149 */ | |
1150 if (newNote) | |
1151 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1152 if (chn->iCExtInstrumentN != jsetNotSet) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1153 extInst = mp->module->extInstruments[chn->iCExtInstrumentN]; |
0 | 1154 else |
1155 extInst = NULL; | |
1156 | |
1157 if (extInst) | |
1158 { | |
1159 // Set instrument | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1160 int note = chn->iCNote; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1161 chn->iCExtInstrument = extInst; |
0 | 1162 |
1163 // We set new Instrument ONLY if NEW NOTE has been set | |
1164 if (note != jsetNotSet) | |
1165 { | |
1166 // Get instrument number | |
1167 tmp = extInst->sNumForNotes[note]; | |
1168 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1169 if (tmp >= 0 && tmp < mp->module->ninstruments) { |
0 | 1170 // Set the new instrument |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1171 inst = mp->module->instruments[tmp]; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1172 chn->iCInstrumentN = tmp; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1173 chn->iCInstrument = inst; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1174 chn->iCVolume = inst->volume; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1175 chn->iCPanning = inst->EPanning; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1176 chn->iCPosition = 0; |
0 | 1177 |
1178 // Set NDFlags | |
1179 JMPSETNDFLAGS(cdfNewInstr | cdfNewPos | cdfNewPanPos | cdfNewVolume); | |
1180 } | |
1181 } | |
1182 } | |
1183 } | |
1184 | |
1185 if (inst) | |
1186 { | |
1187 // Save old pitch for later use | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1188 chn->iCOldPitch = chn->iCPitch; |
0 | 1189 |
1190 // Compute new pitch | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1191 tmp = (chn->iCNote + inst->ERelNote); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1192 //fprintf(stderr, "HEH: %d + %d = %d\n", chn->iCNote, inst->ERelNote, tmp); |
0 | 1193 if (tmp < 0) |
1194 tmp = 0; | |
1195 else if (tmp > 119) | |
1196 tmp = 119; | |
1197 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1198 chn->iCPitch = jmpGetPeriodFromNote(mp, tmp, inst->EFineTune); |
0 | 1199 JMPSETNDFLAGS(cdfNewPitch); |
1200 } | |
1201 | |
1202 // Process the volume column | |
1203 JMPMAKEPARAM(currNote->volume, paramX, paramY); | |
1204 | |
1205 switch (paramX) | |
1206 { | |
1207 case 0x00: | |
1208 case 0x01: | |
1209 case 0x02: | |
1210 case 0x03: | |
1211 case 0x04: | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1212 jmpSetVolume(chn, channel, currNote->volume); |
0 | 1213 break; |
1214 | |
1215 case 0x07: // Dx = Fine Volumeslide Down : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1216 jmpChangeVolume(chn, channel, -paramY); |
0 | 1217 break; |
1218 | |
1219 case 0x08: // Ux = Fine Volumeslide Up : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1220 jmpChangeVolume(chn, channel, paramY); |
0 | 1221 break; |
1222 | |
1223 case 0x09: // Sx = Set vibrato speed : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1224 chn->iVibratoSpeed = paramY; |
0 | 1225 break; |
1226 | |
1227 case 0x0a: // Vx = Vibrato : IMPL.VERIFIED | |
1228 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1229 chn->iVibratoDepth = paramY; |
0 | 1230 break; |
1231 | |
1232 case 0x0e: // Mx = Porta To Note : IMPL.VERIFIED | |
1233 if (paramY) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1234 chn->iLastPortaToNoteParam = paramY; |
0 | 1235 |
1236 if (currNote->note != jsetNotSet && currNote->note != jsetNoteOff) { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1237 chn->iLastPortaToNotePitch = chn->iCPitch; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1238 chn->iCPitch = chn->iCOldPitch; |
0 | 1239 JMPUNSETNDFLAGS(cdfNewPitch | cdfNewInstr | cdfNewPanPos); |
1240 } | |
1241 break; | |
1242 } | |
1243 | |
1244 // ...And finally process the Normal effects | |
1245 if (currNote->effect != jsetNotSet) | |
1246 jmpProcessRowEffect(mp, channel, currNote); | |
1247 } | |
1248 | |
1249 | |
1250 static void jmpProcessEffects(JSSPlayer * mp, int channel) | |
1251 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1252 JSSPlayerChannel *chn = &(mp->channels[channel]); |
0 | 1253 JSSNote *currNote; |
1254 int param, paramX, paramY, tmp; | |
1255 char effect; | |
1256 | |
1257 // Process the volume column effects | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1258 JMPGETNOTE(currNote, mp->row, channel); |
0 | 1259 JMPMAKEPARAM(currNote->volume, paramX, paramY); |
1260 | |
1261 switch (paramX) | |
1262 { | |
1263 case 0x05: // -x = Volumeslide Down : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1264 jmpChangeVolume(chn, channel, -paramY); |
0 | 1265 break; |
1266 | |
1267 case 0x06: // +x = Volumeslide Down : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1268 jmpChangeVolume(chn, channel, paramY); |
0 | 1269 break; |
1270 | |
1271 case 0x0a: // Vx = Vibrato : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1272 jmpDoVibrato(mp, chn, channel); |
0 | 1273 break; |
1274 | |
1275 case 0x0e: // Mx = Porta To Note : IMPL.VERIFIED | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1276 jmpDoPortamento(chn, channel); |
0 | 1277 break; |
1278 } | |
1279 | |
1280 // ...And finally process the Normal effects | |
1281 if (currNote->effect == jsetNotSet) | |
1282 return; | |
1283 | |
1284 param = currNote->param; | |
1285 JMPMAKEPARAM(param, paramX, paramY); | |
1286 JMPGETEFFECT(effect, currNote->effect); | |
1287 | |
1288 switch (effect) | |
1289 { | |
1290 case '0': // 0xy = Arpeggio | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1291 jmpDoArpeggio(mp, chn, channel, paramX, paramY); |
0 | 1292 break; |
1293 | |
1294 case '1': // 1xy = Portamento Up | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1295 if (chn->iLastPortaParam > 0) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1296 jmpChangePitch(chn, channel, -(chn->iLastPortaParam * 4)); |
0 | 1297 break; |
1298 | |
1299 case '2': // 2xy = Portamento Down | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1300 if (chn->iLastPortaParam > 0) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1301 jmpChangePitch(chn, channel, (chn->iLastPortaParam * 4)); |
0 | 1302 break; |
1303 | |
1304 case '3': // 3xy = Porta To Note | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1305 jmpDoPortamento(chn, channel); |
0 | 1306 break; |
1307 | |
1308 case '4': // 4xy = Vibrato | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1309 jmpDoVibrato(mp, chn, channel); |
0 | 1310 break; |
1311 | |
1312 case '5': // 5xy = Portamento + Volume Slide | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1313 jmpDoPortamento(chn, channel); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1314 jmpDoVolumeSlide(chn, channel, chn->iLastVolSlideParam); |
0 | 1315 break; |
1316 | |
1317 case '6': // 6xy = Vibrato + Volume Slide | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1318 jmpDoVibrato(mp, chn, channel); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1319 jmpDoVolumeSlide(chn, channel, chn->iLastVolSlideParam); |
0 | 1320 break; |
1321 | |
1322 case '7': // 7xy = Tremolo | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1323 jmpDoTremolo(mp, chn, channel); |
0 | 1324 break; |
1325 | |
1326 case 'A': // Axy = Volume slide | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1327 jmpDoVolumeSlide(chn, channel, chn->iLastVolSlideParam); |
0 | 1328 break; |
1329 | |
1330 case 'E': // Exy = Special Effects | |
1331 switch (paramX) | |
1332 { | |
1333 case 0x0c: // ECx - Set Note Cut | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1334 if (mp->tick == paramY) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1335 jmpSetVolume(chn, channel, jsetMinVol); |
0 | 1336 break; |
1337 | |
1338 case 0x0d: // EDx - Set Note Delay | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1339 if (mp->tick == paramY) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1340 chn->iCNewDataFlags = chn->iSaveNDFlags; |
0 | 1341 break; |
1342 } | |
1343 break; | |
1344 | |
1345 case 'T': // Txy = Tremor | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1346 JMPMAKEPARAM(chn->iLastTremorParam, paramX, paramY) |
0 | 1347 paramX++; |
1348 paramY++; | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1349 tmp = (chn->iTremorCount % (paramX + paramY)); |
0 | 1350 if (tmp < paramX) |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1351 jmpCSetVolume(mp, chn, channel, chn->iCVolume); |
0 | 1352 else |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1353 jmpCSetVolume(mp, chn, channel, jsetMinVol); |
0 | 1354 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1355 chn->iTremorCount = (tmp + 1); |
0 | 1356 break; |
1357 } | |
1358 } | |
1359 | |
1360 | |
1361 /* This is the main processing callback-loop of a module player. | |
1362 * It processes the ticks, calling the needed jmpProcessNewRow() | |
1363 * and jmpProcessEffects() methods for processing the module playing. | |
1364 */ | |
1365 void jmpExec(void *pDEV, void *pMP) | |
1366 { | |
1367 JSSPlayer *mp; | |
1368 JSSMixer *dev; | |
1369 int channel, flags; | |
1370 | |
1371 // Check some things via assert() | |
1372 assert(pMP != NULL); | |
1373 mp = (JSSPlayer *) pMP; | |
1374 JSS_LOCK(mp); | |
1375 | |
1376 dev = (JSSMixer *) pDEV; | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1377 assert(mp->device == dev); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1378 assert(mp->module != NULL); |
0 | 1379 |
1380 // Check if we are playing | |
1381 if (!mp->isPlaying) | |
1382 goto out; | |
1383 | |
1384 // Clear channel new data flags | |
1385 mp->jumpFlag = FALSE; | |
1386 mp->breakFlag = FALSE; | |
1387 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1388 for (channel = 0; channel < jsetNChannels; channel++) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1389 mp->channels[channel].iCNewDataFlags = 0; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1390 |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1391 //fprintf(stderr, "1: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row); |
0 | 1392 |
1393 // Check for init-tick | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1394 if (mp->tick < 0) |
0 | 1395 { |
1396 // Initialize pattern | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1397 if (mp->order != jsetNotSet) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1398 jmpSetNewOrder(mp, mp->order); |
0 | 1399 |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1400 mp->newRow = 0; |
0 | 1401 mp->newRowSet = TRUE; |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1402 mp->tick = mp->speed; |
0 | 1403 } |
1404 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1405 //fprintf(stderr, "2: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row); |
0 | 1406 |
1407 // Check if we are playing | |
1408 if (!mp->isPlaying) | |
1409 goto out; | |
1410 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1411 assert(mp->pattern); |
0 | 1412 |
1413 // Update the tick | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1414 mp->tick++; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1415 if (mp->tick >= mp->speed) |
0 | 1416 { |
1417 // Re-init tick counter | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1418 mp->tick = 0; |
0 | 1419 |
1420 // Check pattern delay | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1421 if (mp->patternDelay > 0) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1422 mp->patternDelay--; |
0 | 1423 else |
1424 { | |
1425 // New pattern row | |
1426 if (mp->newRowSet) | |
1427 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1428 mp->row = mp->newRow; |
0 | 1429 mp->newRowSet = FALSE; |
1430 } else | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1431 mp->row++; |
0 | 1432 |
1433 // Check for end of pattern | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1434 if (mp->row >= mp->pattern->nrows) |
0 | 1435 { |
1436 // Go to next order | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1437 if (mp->order != jsetNotSet) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1438 jmpSetNewOrder(mp, mp->order + 1); |
0 | 1439 else |
1440 mp->isPlaying = FALSE; | |
1441 | |
1442 // Check for FT2 quirks | |
1443 if (JMPGETMODFLAGS(mp, jmdfFT2Replay)) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1444 mp->row = mp->lastPatLoopRow; |
0 | 1445 else |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1446 mp->row = 0; |
0 | 1447 } |
1448 | |
1449 if (!mp->isPlaying) | |
1450 goto out; | |
1451 | |
1452 // Check current order | |
1453 if (mp->newOrderSet) | |
1454 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1455 jmpSetNewOrder(mp, mp->newOrder); |
0 | 1456 mp->newOrderSet = FALSE; |
1457 } | |
1458 | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1459 //fprintf(stderr, "3: tick=%d, order=%d, iPattern=%d, row=%d\n", mp->tick, mp->order, mp->npattern, mp->row); |
0 | 1460 |
1461 if (!mp->isPlaying) | |
1462 goto out; | |
1463 | |
1464 // TICK #0: Process new row | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1465 for (channel = 0; channel < mp->module->nchannels; channel++) |
0 | 1466 jmpProcessNewRow(mp, channel); |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1467 } // patternDelay |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1468 } // tick |
0 | 1469 else |
1470 { | |
1471 // Implement FT2's pattern delay-effect: don't update effects while on patdelay | |
1472 if (!JMPGETMODFLAGS(mp, jmdfFT2Replay) || | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1473 (JMPGETMODFLAGS(mp, jmdfFT2Replay) && mp->patternDelay <= 0)) |
0 | 1474 { |
1475 // TICK n: Process the effects | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1476 for (channel = 0; channel < mp->module->nchannels; channel++) |
0 | 1477 jmpProcessEffects(mp, channel); |
1478 } | |
1479 } | |
1480 | |
1481 // Check if playing has stopped | |
1482 if (!mp->isPlaying) | |
1483 goto out; | |
1484 | |
1485 // Update player data to audio device/mixer | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1486 for (channel = 0; channel < mp->module->nchannels; channel++) |
0 | 1487 { |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1488 JSSPlayerChannel *chn = &mp->channels[channel]; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1489 |
0 | 1490 // Process extended instruments |
61
a33e47232161
Silence some "unused parameter" warnings.
Matti Hamalainen <ccr@tnsp.org>
parents:
55
diff
changeset
|
1491 jmpProcessExtInstrument(chn, channel); |
0 | 1492 |
1493 // Check NDFlags and update channel data | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1494 flags = chn->iCNewDataFlags; |
0 | 1495 if (flags) |
1496 { | |
1497 // Check if we stop? | |
1498 if (flags & cdfStop) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1499 { |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1500 jvmStop(mp->device, channel); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1501 } |
0 | 1502 else |
1503 { | |
1504 // No, handle other flags | |
1505 if (flags & cdfNewInstr) | |
1506 { | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1507 JSSInstrument *instr = chn->iCInstrument; |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1508 if (instr != NULL) |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1509 { |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1510 jvmSetSample(mp->device, channel, |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1511 instr->data, instr->size, |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1512 instr->loopS, instr->loopE, |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1513 instr->flags); |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1514 } |
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1515 jvmPlay(mp->device, channel); |
0 | 1516 } |
1517 | |
1518 if (flags & cdfNewPitch) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1519 jmpCSetPitch(mp, channel, chn->iCPitch); |
0 | 1520 |
1521 if (flags & cdfNewPos) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1522 jmpCSetPosition(mp, channel, chn->iCPosition); |
0 | 1523 |
1524 if (flags & cdfNewVolume) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1525 jmpCSetVolume(mp, chn, channel, chn->iCVolume); |
0 | 1526 |
1527 if (flags & cdfNewPanPos) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1528 jmpCSetPanning(mp, chn, channel, chn->iCPanning); |
0 | 1529 |
1530 if (flags & cdfNewGlobalVol) | |
55
e0e470c3fc8e
Initial round of cleaning up the player code a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
1531 jvmSetGlobalVol(mp->device, mp->globalVol); |
0 | 1532 } |
1533 } | |
1534 } | |
1535 | |
1536 out: | |
1537 JSS_UNLOCK(mp); | |
1538 } |