Mercurial > hg > dmlib
annotate jssplr.c @ 135:ff0fe1d1ab3d
Implement using of volume ramps in the player code. This MAY or MAY NOT be
correct, as we are setting the new value as the current value and target as
the new value. Needs to be tested / verified against FT2 .. did it this way
because it was easiest (no need to compute future values by peeking upcoming
data.)
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 05 Oct 2012 02:49:13 +0300 |
parents | a33e47232161 |
children | 8ac24d753304 |
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 */ | |
39 int jmpNoteToAmigaPeriod(int note, int finetune) | |
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 */ | |
487 void jmpSetTempo(JSSPlayer * mp, int tempo) | |
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 | |
499 void jmpClearChannels(JSSPlayer * mp) | |
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 } |