[Scummvm-cvs-logs] SF.net SVN: scummvm:[42454] scummvm/branches/gsoc2009-mods/sound/mods
nolange at users.sourceforge.net
nolange at users.sourceforge.net
Mon Jul 13 23:27:59 CEST 2009
Revision: 42454
http://scummvm.svn.sourceforge.net/scummvm/?rev=42454&view=rev
Author: nolange
Date: 2009-07-13 21:27:58 +0000 (Mon, 13 Jul 2009)
Log Message:
-----------
added routine pickvoice to dinamically choose a fitting channel
use similar FP-rounding as the original player
Modified Paths:
--------------
scummvm/branches/gsoc2009-mods/sound/mods/maxtrax.cpp
scummvm/branches/gsoc2009-mods/sound/mods/maxtrax.h
Modified: scummvm/branches/gsoc2009-mods/sound/mods/maxtrax.cpp
===================================================================
--- scummvm/branches/gsoc2009-mods/sound/mods/maxtrax.cpp 2009-07-13 21:20:24 UTC (rev 42453)
+++ scummvm/branches/gsoc2009-mods/sound/mods/maxtrax.cpp 2009-07-13 21:27:58 UTC (rev 42454)
@@ -340,6 +340,50 @@
Paula::setChannelVolume(num, 0);
}
+int8 MaxTrax::pickvoice(const VoiceContext voices[4], uint pick, int16 pri) {
+ pick &= 3;
+ enum { kPrioFlagFixedSide = 1 << 3 };
+ if ((pri & (kPrioFlagFixedSide)) == 0) {
+ const bool leftSide = (uint)(pick - 1) > 1;
+ const int leftBest = MIN(voices[0].status, voices[3].status);
+ const int rightBest = MIN(voices[1].status, voices[2].status);
+ const int sameSide = (leftSide) ? leftBest : rightBest;
+ const int otherSide = leftBest + rightBest - sameSide;
+
+ if (sameSide > VoiceContext::kStatusRelease && otherSide <= VoiceContext::kStatusRelease) {
+ pick ^= 1; // switches sides
+ }
+ }
+ pri &= ~kPrioFlagFixedSide;
+
+ for (int i = 1; i > 0; --i) {
+ const VoiceContext *voice = &voices[pick];
+ const VoiceContext *alternate = &voices[pick ^ 3];
+
+ if (voice->status > alternate->status
+ || (voice->status == alternate->status && voice->lastVolume > alternate->lastVolume)) {
+ // TODO: tiebreaking
+ pick ^= 3; // switch channels
+ const VoiceContext *tmp = voice;
+ voice = alternate;
+ alternate = tmp;
+ }
+
+ if ((voice->flags & VoiceContext::kFlagBlocked) != 0 || voice->priority > pri) {
+ pick ^= 3; // switch channels
+ if ((alternate->flags & VoiceContext::kFlagBlocked) != 0 || alternate->priority > pri) {
+ // if not already done, switch sides and try again
+ pick ^= 1;
+ continue;
+ }
+ }
+ // succeded
+ return (int8)pick;
+ }
+ // failed
+ return -1;
+}
+
int MaxTrax::calcNote(VoiceContext &voice) {
const ChannelContext &channel = *voice.channel;
voice.lastPeriod = 0;
@@ -381,9 +425,12 @@
voice.periodOffset = octave << 16;
}
tone -= voice.periodOffset;
- if (tone >= PERIOD_LIMIT)
- // we need to scale with log(2)
- voice.lastPeriod = (uint16)expf((float)tone * (float)(0.69314718055994530942 / (1 << 16)));
+ if (tone >= PERIOD_LIMIT) {
+ // calculate 2^tone and round towards nearest integer
+ // 2*2^tone = exp((tone+1) * ln(2))
+ const uint16 periodX2 = (uint16)expf((float)(tone + (1 << 16)) * (float)(0.69314718055994530942 / (1 << 16)));
+ voice.lastPeriod = (periodX2 + 1) / 2;
+ }
return octave;
}
@@ -417,12 +464,9 @@
return voiceNum;
}
} else {
- // TODO:
- // pickvoice based on channel.isRightChannel
- // return if no channel found
- voiceNum = (channel.flags & ChannelContext::kFlagRightChannel) != 0 ? 0 : 1;
- static int c = 0;
- voiceNum = (&channel - _channelCtx) % 4;
+ voiceNum = pickvoice(_voiceCtx, (channel.flags & ChannelContext::kFlagRightChannel) != 0 ? 1 : 0, pri);
+ if (voiceNum < 0)
+ return voiceNum;
}
assert(voiceNum >= 0 && voiceNum < ARRAYSIZE(_voiceCtx));
@@ -453,6 +497,7 @@
if (!period)
period = 1000;
+ // TODO: since the original player is using the OS-functions, more than 1 sample could be queued up already
// get samplestart for the given octave
const int8 *samplePtr = patch.samplePtr + (patch.sampleTotalLen << useOctave) - patch.sampleTotalLen;
if (patch.sampleAttackLen) {
@@ -463,6 +508,11 @@
Paula::enableChannel(voiceNum);
// wait for dma-clear
+ // FIXME: this is a workaround to enable oneshot-samples and it currently might crash Paula
+ if (patch.sampleTotalLen == patch.sampleAttackLen) {
+ Paula::setChannelSampleStart(voiceNum, 0);
+ Paula::setChannelSampleLen(voiceNum, 0);
+ }
}
if (patch.sampleTotalLen > patch.sampleAttackLen) {
Modified: scummvm/branches/gsoc2009-mods/sound/mods/maxtrax.h
===================================================================
--- scummvm/branches/gsoc2009-mods/sound/mods/maxtrax.h 2009-07-13 21:20:24 UTC (rev 42453)
+++ scummvm/branches/gsoc2009-mods/sound/mods/maxtrax.h 2009-07-13 21:27:58 UTC (rev 42454)
@@ -204,6 +204,7 @@
void freeScores();
void resetChannel(ChannelContext &chan, bool rightChannel);
+ static int8 MaxTrax::pickvoice(const VoiceContext voice[4], uint pick, int16 pri);
int calcNote(VoiceContext &voice);
int8 noteOn(ChannelContext &channel, byte note, uint16 volume, uint16 pri);
void noteOff(ChannelContext &channel, byte note);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list