Mercurial > hg > dmlib
diff jssplr.c @ 144:22e1be63f6af
Various improvements in XM replay: implement the 5ms volume fadein and
improved volume ramping, etc.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 05 Oct 2012 09:37:39 +0300 |
parents | 69e3041032e9 |
children | e4d6947c2606 |
line wrap: on
line diff
--- a/jssplr.c Fri Oct 05 09:33:42 2012 +0300 +++ b/jssplr.c Fri Oct 05 09:37:39 2012 +0300 @@ -111,7 +111,7 @@ } -static void jmpCSetVolume(JSSPlayer * mp, JSSPlayerChannel *chn, int channel, int volume) +static void jmpCSetVolume(JSSPlayer * mp, JSSPlayerChannel *chn, int channel, int volume, int init) { assert(mp != NULL); assert(mp->device != NULL); @@ -120,12 +120,29 @@ if (volume > mpMaxVol) volume = mpMaxVol; //fprintf(stderr, "chn %d: vol=%d, fad=%d, env=%d\n", channel, volume, chn->iCFadeOutVol, chn->iCVolEnv); -/* +#if 0 jvmSetVolume(mp->device, channel, (chn->iCFadeOutVol * chn->iCVolEnv * volume) / (16 * 65536)); -*/ - jvmSetVolumeRamp(mp->device, channel, jvmGetVolume(mp->device, channel), - (chn->iCFadeOutVol * chn->iCVolEnv * volume) / (16 * 65536)); +#else + if (mp->future == NULL) + { + jvmSetVolume(mp->device, channel, + (chn->iCFadeOutVol * chn->iCVolEnv * volume) / (16 * 65536)); + } + else + if (init) + { + jvmSetVolumeRamp(mp->device, channel, + 0, + jvmGetVolume(mp->future->device, channel), 5); + } + else + { + jvmSetVolumeRamp(mp->device, channel, + (chn->iCFadeOutVol * chn->iCVolEnv * volume) / (16 * 65536), + jvmGetVolume(mp->future->device, channel), 0); + } +#endif } @@ -134,8 +151,17 @@ assert(mp != NULL); assert(mp->device != NULL); - jvmSetPan(mp->device, channel, - panning + (((chn->iCPanEnv - 32) * (128 - abs(panning - 128))) / 32)); + if (mp->future == NULL) + { + jvmSetPan(mp->device, channel, + panning + (((chn->iCPanEnv - 32) * (128 - abs(panning - 128))) / 32)); + } + else + { + jvmSetPanRamp(mp->device, channel, + panning + (((chn->iCPanEnv - 32) * (128 - abs(panning - 128))) / 32), + jvmGetPan(mp->future->device, channel), 0); + } } @@ -304,13 +330,22 @@ // Allocate a player structure mp = dmMalloc0(sizeof(JSSPlayer)); - if (!mp) + if (mp == NULL) + JSSERROR(DMERR_MALLOC, NULL, "Could not allocate memory for player structure.\n"); + + mp->future = dmMalloc0(sizeof(JSSPlayer)); + if (mp->future == NULL) JSSERROR(DMERR_MALLOC, NULL, "Could not allocate memory for player structure.\n"); // Set variables mp->device = pDevice; + mp->future->device = jvmInit(pDevice->outFormat, pDevice->outChannels, pDevice->outFreq, JMIX_AUTO); + if (mp->future->device == NULL) + JSSERROR(DMERR_INIT_FAIL, NULL, "Could not initialize shadow mixing device.\n"); + #ifdef JSS_SUP_THREADS mp->mutex = dmCreateMutex(); + mp->future->mutex = dmCreateMutex(); #endif return mp; @@ -330,6 +365,15 @@ dmDestroyMutex(mp->mutex); #endif + if (mp->future != NULL) + { +#ifdef JSS_SUP_THREADS + dmDestroyMutex(mp->future->mutex); +#endif + jvmClose(mp->future->device); + dmFree(mp->future); + } + // Clear structure memset(mp, 0, sizeof(JSSPlayer)); dmFree(mp); @@ -393,7 +437,7 @@ jmpStop(mp); jmpClearPlayer(mp); - mp->module = module; + mp->future->module = mp->module = module; JSS_UNLOCK(mp); } @@ -410,6 +454,9 @@ { jvmRemoveCallback(mp->device); mp->isPlaying = FALSE; + + if (mp->future != NULL) + jmpStop(mp->future); } JSS_UNLOCK(mp); @@ -430,6 +477,8 @@ JSSERROR(result,, "Could not initialize callback for player.\n"); mp->isPlaying = TRUE; + if (mp->future != NULL) + jmpResume(mp->future); } JSS_UNLOCK(mp); @@ -560,6 +609,12 @@ mp->isPlaying = TRUE; + if (mp->future != NULL) + { + jmpPlayOrder(mp->future, order); + jmpExec(mp->future->device, mp->future); + } + JSS_UNLOCK(mp); return 0; } @@ -595,6 +650,12 @@ mp->isPlaying = TRUE; + if (mp->future != NULL) + { + jmpPlayPattern(mp->future, pattern); + jmpExec(mp->future->device, mp->future); + } + JSS_UNLOCK(mp); return 0; } @@ -705,7 +766,7 @@ } // Set the new volume - jmpCSetVolume(mp, chn, channel, chn->iCVolume + delta); + jmpCSetVolume(mp, chn, channel, chn->iCVolume + delta, FALSE); // Advance tremolo waveform position chn->iTremoloPos += chn->iTremoloSpeed; @@ -1348,9 +1409,9 @@ paramY++; tmp = (chn->iTremorCount % (paramX + paramY)); if (tmp < paramX) - jmpCSetVolume(mp, chn, channel, chn->iCVolume); + jmpCSetVolume(mp, chn, channel, chn->iCVolume, FALSE); else - jmpCSetVolume(mp, chn, channel, jsetMinVol); + jmpCSetVolume(mp, chn, channel, jsetMinVol, FALSE); chn->iTremorCount = (tmp + 1); break; @@ -1369,13 +1430,16 @@ int channel, flags; // Check some things via assert() - assert(pMP != NULL); mp = (JSSPlayer *) pMP; JSS_LOCK(mp); dev = (JSSMixer *) pDEV; - assert(mp->device == dev); - assert(mp->module != NULL); + + // Futures + if (mp->future != NULL) + { + jmpExec(mp->future->device, mp->future); + } // Check if we are playing if (!mp->isPlaying) @@ -1492,44 +1556,44 @@ // Check NDFlags and update channel data flags = chn->iCNewDataFlags; - if (flags) + if (!flags) + continue; + + // Check if we stop? + if (flags & cdfStop) { - // Check if we stop? - if (flags & cdfStop) + jvmStop(mp->device, channel); + } + else + { + // No, handle other flags + if (flags & cdfNewInstr) { - jvmStop(mp->device, channel); - } - else - { - // No, handle other flags - if (flags & cdfNewInstr) + JSSInstrument *instr = chn->iCInstrument; + if (instr != NULL) { - JSSInstrument *instr = chn->iCInstrument; - if (instr != NULL) - { - jvmSetSample(mp->device, channel, - instr->data, instr->size, - instr->loopS, instr->loopE, - instr->flags); - } - jvmPlay(mp->device, channel); + jvmSetSample(mp->device, channel, + instr->data, instr->size, + instr->loopS, instr->loopE, + instr->flags); } + jvmPlay(mp->device, channel); + } + + if (flags & cdfNewPitch) + jmpCSetPitch(mp, channel, chn->iCPitch); - if (flags & cdfNewPitch) - jmpCSetPitch(mp, channel, chn->iCPitch); + if (flags & cdfNewPos) + jmpCSetPosition(mp, channel, chn->iCPosition); - if (flags & cdfNewPos) - jmpCSetPosition(mp, channel, chn->iCPosition); + if (flags & cdfNewVolume) + jmpCSetVolume(mp, chn, channel, chn->iCVolume, flags & cdfNewInstr); - if (flags & cdfNewVolume) - jmpCSetVolume(mp, chn, channel, chn->iCVolume); + if (flags & cdfNewPanPos) + jmpCSetPanning(mp, chn, channel, chn->iCPanning); - if (flags & cdfNewPanPos) - jmpCSetPanning(mp, chn, channel, chn->iCPanning); - - if (flags & cdfNewGlobalVol) - jvmSetGlobalVol(mp->device, mp->globalVol); - } + if (flags & cdfNewGlobalVol) + jvmSetGlobalVol(mp->device, mp->globalVol); } }