Mercurial > hg > dmlib
annotate jssmix.c @ 49:033c660c25f5
Restructure module playing, removing 8bit sample mixing (output can still be
8bit, but samples are internally upconverted to 16bit after module loading.)
Also prepare for floating point mixing support.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 01 Oct 2012 02:51:41 +0300 |
parents | f3407a58e01e |
children | 36e2f910219c |
rev | line source |
---|---|
0 | 1 /* |
2 * miniJSS - Mixing device and channel handling | |
3 * Programmed and designed by Matti 'ccr' Hamalainen | |
4 * (C) Copyright 2006-2012 Tecnic Software productions (TNSP) | |
5 */ | |
6 #include "jssmix.h" | |
7 #include <string.h> | |
8 | |
9 | |
10 #ifdef DM_USE_C | |
11 #define JMIXER_HEADER | |
49
033c660c25f5
Restructure module playing, removing 8bit sample mixing (output can still be
Matti Hamalainen <ccr@tnsp.org>
parents:
36
diff
changeset
|
12 #include "jmix_c_in.c" |
0 | 13 #undef JMIXER_HEADER |
14 #endif | |
15 | |
16 #undef DM_USE_SIMD | |
17 | |
18 #ifdef DM_USE_SIMD | |
19 #define JMIXER_HEADER | |
49
033c660c25f5
Restructure module playing, removing 8bit sample mixing (output can still be
Matti Hamalainen <ccr@tnsp.org>
parents:
36
diff
changeset
|
20 #include "jmix_mmx_in.c" |
0 | 21 #undef JMIXER_HEADER |
22 #endif | |
23 | |
24 | |
25 typedef struct | |
26 { | |
27 int mixerID; | |
28 int outFormat; | |
29 int outChannels; | |
36
f3407a58e01e
Change DMFixedPoint types and appropriate JSS functions back to using signed
Matti Hamalainen <ccr@tnsp.org>
parents:
34
diff
changeset
|
30 int (*jvmMixChannel_FW)(JSSMixer *, JSSChannel *, Sint32 *, const int, const Sint32); |
f3407a58e01e
Change DMFixedPoint types and appropriate JSS functions back to using signed
Matti Hamalainen <ccr@tnsp.org>
parents:
34
diff
changeset
|
31 int (*jvmMixChannel_BW)(JSSMixer *, JSSChannel *, Sint32 *, const int, const Sint32); |
0 | 32 void (*jvmPostProcess)(Sint32 *, void *, const int); |
33 } JSSMixingRoutine; | |
34 | |
35 | |
36 /* This table should be sorted from fastest to slowest, e.g. MMX/x86 | |
37 * optimized routines first, pure C versions last. | |
38 */ | |
39 static JSSMixingRoutine jvmMixRoutines[] = | |
40 { | |
41 #ifdef DM_USE_SIMD | |
42 { JMIX_MMX, JSS_AUDIO_U8, JSS_AUDIO_MONO, jvmMix_Mono_MMX_FW, jvmMix_Mono_MMX_BW, jvmPostProcess_U8_MMX }, | |
43 { JMIX_MMX, JSS_AUDIO_S8, JSS_AUDIO_MONO, jvmMix_Mono_MMX_FW, jvmMix_Mono_MMX_BW, jvmPostProcess_S8_MMX }, | |
44 { JMIX_MMX, JSS_AUDIO_U8, JSS_AUDIO_STEREO, jvmMix_Stereo_MMX_FW, jvmMix_Stereo_MMX_BW, jvmPostProcess_U8_MMX }, | |
45 { JMIX_MMX, JSS_AUDIO_S8, JSS_AUDIO_STEREO, jvmMix_Stereo_MMX_FW, jvmMix_Stereo_MMX_BW, jvmPostProcess_S8_MMX }, | |
46 | |
47 { JMIX_MMX, JSS_AUDIO_U16, JSS_AUDIO_MONO, jvmMix_Mono_MMX_FW, jvmMix_Mono_MMX_BW, jvmPostProcess_U16_MMX }, | |
48 { JMIX_MMX, JSS_AUDIO_S16, JSS_AUDIO_MONO, jvmMix_Mono_MMX_FW, jvmMix_Mono_MMX_BW, jvmPostProcess_S16_MMX }, | |
49 { JMIX_MMX, JSS_AUDIO_U16, JSS_AUDIO_STEREO, jvmMix_Stereo_MMX_FW, jvmMix_Stereo_MMX_BW, jvmPostProcess_U16_MMX }, | |
50 { JMIX_MMX, JSS_AUDIO_S16, JSS_AUDIO_STEREO, jvmMix_Stereo_MMX_FW, jvmMix_Stereo_MMX_BW, jvmPostProcess_S16_MMX }, | |
51 #endif | |
52 | |
53 #ifdef DM_USE_C | |
54 { JMIX_C, JSS_AUDIO_U8, JSS_AUDIO_MONO, jvmMix_Mono_C_FW, jvmMix_Mono_C_BW, jvmPostProcess_U8_C }, | |
55 { JMIX_C, JSS_AUDIO_S8, JSS_AUDIO_MONO, jvmMix_Mono_C_FW, jvmMix_Mono_C_BW, jvmPostProcess_S8_C }, | |
56 { JMIX_C, JSS_AUDIO_U8, JSS_AUDIO_STEREO, jvmMix_Stereo_C_FW, jvmMix_Stereo_C_BW, jvmPostProcess_U8_C }, | |
57 { JMIX_C, JSS_AUDIO_S8, JSS_AUDIO_STEREO, jvmMix_Stereo_C_FW, jvmMix_Stereo_C_BW, jvmPostProcess_S8_C }, | |
58 | |
59 { JMIX_C, JSS_AUDIO_U16, JSS_AUDIO_MONO, jvmMix_Mono_C_FW, jvmMix_Mono_C_BW, jvmPostProcess_U16_C }, | |
60 { JMIX_C, JSS_AUDIO_S16, JSS_AUDIO_MONO, jvmMix_Mono_C_FW, jvmMix_Mono_C_BW, jvmPostProcess_S16_C }, | |
61 { JMIX_C, JSS_AUDIO_U16, JSS_AUDIO_STEREO, jvmMix_Stereo_C_FW, jvmMix_Stereo_C_BW, jvmPostProcess_U16_C }, | |
62 { JMIX_C, JSS_AUDIO_S16, JSS_AUDIO_STEREO, jvmMix_Stereo_C_FW, jvmMix_Stereo_C_BW, jvmPostProcess_S16_C }, | |
63 #endif | |
64 }; | |
65 | |
66 static const int jvmNMixRoutines = sizeof(jvmMixRoutines) / sizeof(jvmMixRoutines[0]); | |
67 | |
68 | |
69 static int jvmFindMixRoutine(int outFormat, int outChannels, int mixerID) | |
70 { | |
71 int i; | |
72 | |
73 for (i = 0; i < jvmNMixRoutines; i++) | |
74 { | |
75 if (jvmMixRoutines[i].outFormat == outFormat && | |
76 jvmMixRoutines[i].outChannels == outChannels && | |
77 (mixerID == JMIX_AUTO || jvmMixRoutines[i].mixerID == mixerID)) | |
78 return i; | |
79 } | |
80 | |
81 return -1; | |
82 } | |
83 | |
84 | |
85 JSSMixer *jvmInit(const int outFormat, const int outChannels, const int outFreq, const int mixerID) | |
86 { | |
87 JSSMixer *mixer; | |
49
033c660c25f5
Restructure module playing, removing 8bit sample mixing (output can still be
Matti Hamalainen <ccr@tnsp.org>
parents:
36
diff
changeset
|
88 int mixerIdx; |
0 | 89 |
90 // Check settings | |
91 if (outChannels < 1) | |
92 { | |
93 JSSERROR(DMERR_INVALID_ARGS, NULL, | |
94 "Invalid number of channels %d\n", outChannels); | |
95 } | |
96 | |
97 if (outFreq < 4000) | |
98 { | |
99 JSSERROR(DMERR_INVALID_ARGS, NULL, | |
100 "Invalid mixing frequency %d\n", outFreq); | |
101 } | |
102 | |
103 /* Select mixing routines: | |
104 * Here we try to choose the most fitting mixing routines | |
105 * from the compiled in routines, unless caller is forcing | |
106 * us to select specific ones. | |
107 */ | |
108 if (mixerID == JMIX_AUTO) | |
109 { | |
110 mixerIdx = jvmFindMixRoutine(outFormat, outChannels, JMIX_SSE); | |
111 if (mixerIdx < 0) | |
112 mixerIdx = jvmFindMixRoutine(outFormat, outChannels, JMIX_MMX); | |
113 if (mixerIdx < 0) | |
114 mixerIdx = jvmFindMixRoutine(outFormat, outChannels, JMIX_AUTO); | |
115 } | |
116 else | |
117 { | |
118 mixerIdx = jvmFindMixRoutine(outFormat, outChannels, mixerID); | |
119 } | |
120 | |
121 if (mixerIdx < 0) | |
122 { | |
123 JSSERROR(DMERR_INVALID_ARGS, NULL, | |
124 "Could not find mixing routine for outFormat=%d, outChannels=%d, outFreq=%d.\n", | |
125 outFormat, outChannels, outFreq); | |
126 return NULL; | |
127 } | |
128 | |
129 // Allocate a mixer device structure | |
130 mixer = dmMalloc0(sizeof(JSSMixer)); | |
131 if (mixer == NULL) | |
132 { | |
133 JSSERROR(DMERR_MALLOC, NULL, | |
134 "Could not allocate mixing device structure.\n"); | |
135 } | |
136 | |
137 // Initialize variables | |
138 #ifdef JSS_SUP_THREADS | |
139 mixer->mutex = dmCreateMutex(); | |
140 #endif | |
141 mixer->outFormat = outFormat; | |
142 mixer->outFreq = outFreq; | |
143 mixer->outChannels = outChannels; | |
144 | |
145 mixer->jvmMixChannel_FW = jvmMixRoutines[mixerIdx].jvmMixChannel_FW; | |
146 mixer->jvmMixChannel_BW = jvmMixRoutines[mixerIdx].jvmMixChannel_BW; | |
147 mixer->jvmPostProcess = jvmMixRoutines[mixerIdx].jvmPostProcess; | |
148 | |
149 // Allocate addBuffer | |
150 mixer->addBufSize = outChannels * outFreq; | |
151 mixer->addBuffer = dmCalloc(mixer->addBufSize, sizeof(Sint32)); | |
152 if (mixer->addBuffer == NULL) | |
153 { | |
154 JSSERROR(DMERR_MALLOC, NULL, | |
155 "Could not allocate mixing addition buffer.\n"); | |
156 } | |
157 | |
158 return mixer; | |
159 } | |
160 | |
161 | |
162 int jvmClose(JSSMixer * mixer) | |
163 { | |
164 if (mixer == NULL) | |
165 return DMERR_NULLPTR; | |
166 | |
167 // Deallocate resources | |
168 #ifdef JSS_SUP_THREADS | |
169 dmDestroyMutex(mixer->mutex); | |
170 #endif | |
171 dmFree(mixer->addBuffer); | |
172 | |
173 memset(mixer, 0, sizeof(JSSMixer)); | |
174 dmFree(mixer); | |
175 | |
176 return DMERR_OK; | |
177 } | |
178 | |
179 | |
180 int jvmGetSampleSize(JSSMixer *mixer) | |
181 { | |
182 int sampSize = 1; | |
183 assert(mixer); | |
184 | |
185 switch (mixer->outChannels) | |
186 { | |
187 case JSS_AUDIO_STEREO: | |
188 case JSS_AUDIO_MONO: | |
189 sampSize = mixer->outChannels; | |
190 break; | |
191 default: | |
192 JSSERROR(DMERR_INVALID_ARGS, -1, | |
193 "outChannels=%d not stereo or mono!\n", mixer->outChannels); | |
194 break; | |
195 } | |
196 | |
197 switch (mixer->outFormat) | |
198 { | |
199 case JSS_AUDIO_U16: sampSize *= sizeof(Uint16); break; | |
200 case JSS_AUDIO_S16: sampSize *= sizeof(Sint16); break; | |
201 case JSS_AUDIO_U8: sampSize *= sizeof(Uint8); break; | |
202 case JSS_AUDIO_S8: sampSize *= sizeof(Sint8); break; | |
203 default: | |
204 JSSERROR(DMERR_INVALID_ARGS, -1, | |
205 "outFormat=%d is not supported!\n", mixer->outFormat); | |
206 } | |
207 | |
208 return sampSize; | |
209 } | |
210 | |
211 | |
212 int jvmGetSampleRes(JSSMixer *mixer) | |
213 { | |
214 int sampRes = 1; | |
215 | |
216 assert(mixer); | |
217 | |
218 switch (mixer->outFormat) | |
219 { | |
220 case JSS_AUDIO_U16: case JSS_AUDIO_S16: sampRes = 16; break; | |
221 case JSS_AUDIO_U8: case JSS_AUDIO_S8: sampRes = 8; break; | |
222 default: | |
223 JSSERROR(DMERR_INVALID_ARGS, -1, | |
224 "outFormat=%d is not supported!\n", mixer->outFormat); | |
225 } | |
226 | |
227 return sampRes; | |
228 } | |
229 | |
230 | |
231 static void jvmMixChannel(JSSMixer *mixer, JSSChannel *chn, Sint32 *addBuffer, const int mixLength) | |
232 { | |
233 int mixDone = mixLength, mixResult; | |
234 Sint32 *ab = addBuffer; | |
235 | |
236 if (!chn->chPlaying || chn->chMute) | |
237 return; | |
238 | |
239 DBG("%s(%p, %d)\n", __FUNCTION__, chn, mixLength); | |
240 | |
241 while (mixDone > 0) | |
242 { | |
243 if (chn->chDirection) | |
244 { | |
245 // Channel is playing FORWARDS | |
246 if (chn->chFlags & jsfLooped) | |
247 { | |
248 // Sample is looped | |
249 if (chn->chFlags & jsfBiDi) | |
250 { | |
251 // Bi-directional loop | |
252 if (FP_GETH(chn->chPos) >= chn->chLoopE) | |
253 { | |
254 FP_SETH(chn->chPos, chn->chLoopE - 1); | |
255 FP_SETL(chn->chPos, 0); | |
256 chn->chDirection = FALSE; | |
257 } | |
258 } | |
259 else | |
260 { | |
261 // Normal forward loop | |
262 if (FP_GETH(chn->chPos) >= chn->chLoopE) | |
263 { | |
264 FP_SETH(chn->chPos, chn->chLoopS /* + (FP_GETH(chn->chPos) - chn->chLoopE) */); | |
265 FP_SETL(chn->chPos, 0); | |
266 } | |
267 } | |
268 } | |
269 else | |
270 { | |
271 // Normal (non-looped) sample | |
272 if (FP_GETH(chn->chPos) >= chn->chSize) | |
273 { | |
274 chn->chPlaying = FALSE; | |
275 return; | |
276 } | |
277 } | |
278 } | |
279 else | |
280 { | |
281 // Channel is playing BACKWARDS | |
282 if (chn->chFlags & jsfLooped) | |
283 { | |
284 // Sample is looped | |
285 if (chn->chFlags & jsfBiDi) | |
286 { | |
287 // Bi-directional loop | |
288 if (FP_GETH(chn->chPos) <= chn->chLoopS) | |
289 { | |
290 FP_SETH(chn->chPos, chn->chLoopS); | |
291 FP_SETL(chn->chPos, 0); | |
292 chn->chDirection = TRUE; | |
293 } | |
294 } | |
295 else | |
296 { | |
297 // Normal forward loop | |
298 if (FP_GETH(chn->chPos) <= chn->chLoopS) | |
299 { | |
300 FP_SETH(chn->chPos, chn->chLoopE - 1); | |
301 FP_SETL(chn->chPos, 0); | |
302 } | |
303 } | |
304 } | |
305 else | |
306 { | |
307 // Normal (non-looped) sample | |
308 if (FP_GETH(chn->chPos) <= 0) | |
309 { | |
310 chn->chPlaying = FALSE; | |
311 return; | |
312 } | |
313 } | |
314 } | |
315 | |
316 // Call the mixing innerloop functions | |
317 if (chn->chDirection) | |
318 { | |
319 DBG("MIX_FW[%p : %d : ", ab, mixDone); | |
320 if (chn->chFlags & jsfLooped) | |
321 { | |
322 DBG("%d (%x)] {loop}\n", chn->chLoopE, chn->chLoopE); | |
323 mixResult = mixer->jvmMixChannel_FW((void *) mixer, chn, | |
324 ab, mixDone, chn->chLoopE); | |
325 } | |
326 else | |
327 { | |
328 DBG("%d (%x)]\n", chn->chSize, chn->chSize); | |
329 mixResult = mixer->jvmMixChannel_FW((void *) mixer, chn, | |
330 ab, mixDone, chn->chSize); | |
331 } | |
332 } | |
333 else | |
334 { | |
335 DBG("MIX_BW[%p : %d : ", ab, mixDone); | |
336 if (chn->chFlags & jsfLooped) | |
337 { | |
338 DBG("%d (%x)] {loop}\n", chn->chLoopS, chn->chLoopS); | |
339 mixResult = mixer->jvmMixChannel_BW(mixer, chn, | |
340 ab, mixDone, chn->chLoopS); | |
341 } | |
342 else | |
343 { | |
344 DBG("%d (%x)]\n", 0, 0); | |
345 mixResult = mixer->jvmMixChannel_BW(mixer, chn, | |
346 ab, mixDone, 0); | |
347 } | |
348 } | |
349 | |
350 mixDone -= mixResult; | |
351 ab += mixResult * mixer->outChannels; | |
352 } | |
353 | |
354 #ifdef JSS_DEBUG | |
355 if (mixDone < 0) | |
356 JSSWARNING(DMERR_BOUNDS,, "mixDone < 0 in mixing logic loop.\n"); | |
357 #endif | |
358 } | |
359 | |
360 | |
361 void jvmRenderAudio(JSSMixer *mixer, void *mixBuffer, const int mixLength) | |
362 { | |
363 int i, blockLength, mixLeft; | |
364 Sint32 *ab; | |
365 | |
366 JSS_LOCK(mixer); | |
367 | |
368 assert(mixer != NULL); | |
369 assert(mixBuffer != NULL); | |
370 assert(mixLength > 0); | |
371 assert(mixLength * mixer->outChannels < mixer->addBufSize); | |
372 | |
373 // Clear mixer->addBuffer | |
374 memset(mixer->addBuffer, 0, mixLength * mixer->outChannels * sizeof(Sint32)); | |
375 | |
376 ab = mixer->addBuffer; | |
377 mixLeft = mixLength; | |
378 while (mixLeft > 0) | |
379 { | |
380 // Check for callbacks | |
381 blockLength = mixLeft; | |
382 | |
383 if (mixer->cbFunction) | |
384 { | |
385 if (mixer->cbCounter <= 0) | |
386 { | |
387 mixer->cbFunction(mixer, mixer->cbData); | |
388 mixer->cbCounter = mixer->cbFreq; | |
389 } | |
390 | |
391 if (mixer->cbCounter < blockLength) | |
392 blockLength = mixer->cbCounter; | |
393 } | |
394 | |
395 // Do mixing | |
396 for (i = 0; i < jsetNChannels; i++) | |
397 { | |
398 JSSChannel *chn = &(mixer->channels[i]); | |
399 if (chn->chPlaying && !chn->chMute) | |
400 jvmMixChannel(mixer, chn, ab, blockLength); | |
401 } | |
402 | |
403 /* | |
404 if (chn->chPlaying) | |
405 { | |
406 if (!chn->chMute) | |
407 jvmMixChannel(mixer, chn, ab, blockLength); | |
408 else | |
409 jvmAdvanceChannel(mixer, chn, blockLength); | |
410 } | |
411 */ | |
412 | |
413 ab += blockLength * mixer->outChannels; | |
414 mixLeft -= blockLength; | |
415 mixer->cbCounter -= blockLength; | |
416 } | |
417 | |
418 // Post-process | |
419 mixer->jvmPostProcess(mixer->addBuffer, mixBuffer, mixLength * mixer->outChannels); | |
420 | |
421 JSS_UNLOCK(mixer); | |
422 } | |
423 | |
424 | |
425 int jvmSetCallback(JSSMixer * mixer, void (*cbFunction) (void *, void *), void *cbData) | |
426 { | |
427 assert(mixer); | |
428 | |
429 if (cbFunction == NULL) | |
430 JSSERROR(DMERR_NULLPTR, DMERR_NULLPTR, "NULL pointer given as cbFunction"); | |
431 | |
432 JSS_LOCK(mixer); | |
433 | |
434 mixer->cbFunction = cbFunction; | |
435 mixer->cbData = cbData; | |
436 | |
437 JSS_UNLOCK(mixer); | |
438 | |
439 return DMERR_OK; | |
440 } | |
441 | |
442 | |
443 void jvmRemoveCallback(JSSMixer * mixer) | |
444 { | |
445 assert(mixer); | |
446 | |
447 JSS_LOCK(mixer); | |
448 | |
449 mixer->cbFunction = NULL; | |
450 mixer->cbData = NULL; | |
451 mixer->cbFreq = mixer->cbCounter = 0; | |
452 | |
453 JSS_UNLOCK(mixer); | |
454 } | |
455 | |
456 | |
457 int jvmSetCallbackFreq(JSSMixer * mixer, const int cbFreq) | |
458 { | |
459 assert(mixer); | |
460 | |
461 if ((cbFreq < 1) || (cbFreq >= mixer->outFreq)) | |
462 JSSERROR(DMERR_INVALID_ARGS, DMERR_INVALID_ARGS, | |
463 "Invalid callback frequency given (%i / %i)\n", cbFreq, mixer->outFreq); | |
464 | |
465 JSS_LOCK(mixer); | |
466 | |
467 mixer->cbFreq = (mixer->outFreq / cbFreq); | |
468 mixer->cbCounter = 0; | |
469 | |
470 //fprintf(stderr, "set(outFreq = %d, cbFreq = %d) = %d\n", mixer->outFreq, cbFreq, mixer->cbFreq); | |
471 | |
472 JSS_UNLOCK(mixer); | |
473 return DMERR_OK; | |
474 } | |
475 | |
476 | |
477 /* Channel manipulation routines | |
478 */ | |
479 void jvmPlay(JSSMixer * mixer, const int channel) | |
480 { | |
481 JSS_LOCK(mixer); | |
482 mixer->channels[channel].chPlaying = TRUE; | |
483 JSS_UNLOCK(mixer); | |
484 } | |
485 | |
486 | |
487 void jvmStop(JSSMixer * mixer, const int channel) | |
488 { | |
489 JSS_LOCK(mixer); | |
490 mixer->channels[channel].chPlaying = FALSE; | |
491 JSS_UNLOCK(mixer); | |
492 } | |
493 | |
494 | |
495 void jvmSetSample(JSSMixer * mixer, const int channel, | |
36
f3407a58e01e
Change DMFixedPoint types and appropriate JSS functions back to using signed
Matti Hamalainen <ccr@tnsp.org>
parents:
34
diff
changeset
|
496 void *data, const Sint32 size, const Sint32 loopS, |
f3407a58e01e
Change DMFixedPoint types and appropriate JSS functions back to using signed
Matti Hamalainen <ccr@tnsp.org>
parents:
34
diff
changeset
|
497 const Sint32 loopE, const int flags) |
0 | 498 { |
499 JSSChannel *c; | |
500 | |
501 JSS_LOCK(mixer); | |
502 c = &mixer->channels[channel]; | |
503 | |
504 c->chData = data; | |
505 c->chSize = size; | |
506 c->chLoopS = loopS; | |
507 c->chLoopE = loopE; | |
508 c->chFlags = flags; | |
509 c->chDirection = TRUE; | |
510 c->chPrevL = c->chPrevR = 0; | |
511 c->chPos.dw = c->chDeltaO.dw = 0; | |
512 | |
513 JSS_UNLOCK(mixer); | |
514 } | |
515 | |
516 | |
517 void jvmSetFreq(JSSMixer * mixer, const int channel, const int freq) | |
518 { | |
519 JSS_LOCK(mixer); | |
520 | |
521 mixer->channels[channel].chFreq = freq; | |
522 | |
523 if (mixer->outFreq > 0) | |
524 { | |
525 DMFixedPoint a, b; | |
526 FP_SETHL(a, freq, 0); | |
527 FP_CONV(b, mixer->outFreq); | |
528 FP_DIV_R(mixer->channels[channel].chDeltaO, a, b); | |
529 } | |
530 else | |
531 { | |
532 FP_SET(mixer->channels[channel].chDeltaO, 0); | |
533 } | |
534 | |
535 JSS_UNLOCK(mixer); | |
536 } | |
537 | |
538 | |
539 int jvmGetFreq(JSSMixer * mixer, const int channel) | |
540 { | |
541 int tmp; | |
542 | |
543 JSS_LOCK(mixer); | |
544 tmp = mixer->channels[channel].chFreq; | |
545 JSS_UNLOCK(mixer); | |
546 | |
547 return tmp; | |
548 } | |
549 | |
550 | |
551 void jvmSetVolume(JSSMixer * mixer, const int channel, const int volume) | |
552 { | |
553 JSS_LOCK(mixer); | |
554 mixer->channels[channel].chVolume = volume; | |
555 JSS_UNLOCK(mixer); | |
556 } | |
557 | |
558 | |
559 int jvmGetVolume(JSSMixer * mixer, const int channel) | |
560 { | |
561 int tmp; | |
562 | |
563 JSS_LOCK(mixer); | |
564 tmp = mixer->channels[channel].chVolume; | |
565 JSS_UNLOCK(mixer); | |
566 | |
567 return tmp; | |
568 } | |
569 | |
570 | |
36
f3407a58e01e
Change DMFixedPoint types and appropriate JSS functions back to using signed
Matti Hamalainen <ccr@tnsp.org>
parents:
34
diff
changeset
|
571 void jvmSetPos(JSSMixer * mixer, const int channel, const Sint32 pos) |
0 | 572 { |
573 JSS_LOCK(mixer); | |
574 FP_SETH(mixer->channels[channel].chPos, pos); | |
575 FP_SETL(mixer->channels[channel].chPos, 0); | |
576 JSS_UNLOCK(mixer); | |
577 } | |
578 | |
579 | |
36
f3407a58e01e
Change DMFixedPoint types and appropriate JSS functions back to using signed
Matti Hamalainen <ccr@tnsp.org>
parents:
34
diff
changeset
|
580 Sint32 jvmGetPos(JSSMixer * mixer, const int channel) |
0 | 581 { |
36
f3407a58e01e
Change DMFixedPoint types and appropriate JSS functions back to using signed
Matti Hamalainen <ccr@tnsp.org>
parents:
34
diff
changeset
|
582 Sint32 tmp; |
0 | 583 |
584 JSS_LOCK(mixer); | |
585 tmp = FP_GETH(mixer->channels[channel].chPos); | |
586 JSS_UNLOCK(mixer); | |
587 | |
588 return tmp; | |
589 } | |
590 | |
591 | |
592 void jvmSetPan(JSSMixer * mixer, const int channel, const int panning) | |
593 { | |
594 JSS_LOCK(mixer); | |
595 mixer->channels[channel].chPanning = panning; | |
596 JSS_UNLOCK(mixer); | |
597 } | |
598 | |
599 | |
600 int jvmGetPan(JSSMixer * mixer, const int channel) | |
601 { | |
602 int tmp; | |
603 | |
604 JSS_LOCK(mixer); | |
605 tmp = mixer->channels[channel].chPanning; | |
606 JSS_UNLOCK(mixer); | |
607 | |
608 return tmp; | |
609 } | |
610 | |
611 | |
612 void jvmMute(JSSMixer * mixer, const int channel, const BOOL mute) | |
613 { | |
614 JSS_LOCK(mixer); | |
615 mixer->channels[channel].chMute = mute; | |
616 JSS_UNLOCK(mixer); | |
617 } | |
618 | |
619 | |
620 void jvmClear(JSSMixer * mixer, const int channel) | |
621 { | |
622 JSS_LOCK(mixer); | |
623 memset(&mixer->channels[channel], 0, sizeof(JSSChannel)); | |
624 JSS_UNLOCK(mixer); | |
625 } | |
626 | |
627 | |
628 void jvmSetGlobalVol(JSSMixer * mixer, const int volume) | |
629 { | |
630 JSS_LOCK(mixer); | |
631 mixer->globalVol = volume; | |
632 JSS_UNLOCK(mixer); | |
633 } | |
634 | |
635 | |
636 int jvmGetGlobalVol(JSSMixer * mixer) | |
637 { | |
638 int tmp; | |
639 | |
640 JSS_LOCK(mixer); | |
641 tmp = mixer->globalVol; | |
642 JSS_UNLOCK(mixer); | |
643 | |
644 return tmp; | |
645 } |