diff options
author | Norbert Lange | 2009-07-08 22:59:50 +0000 |
---|---|---|
committer | Norbert Lange | 2009-07-08 22:59:50 +0000 |
commit | a9d9de7db4eeacab240a76bd29ed8e95316546c9 (patch) | |
tree | 1763e458e9a089f3e1d89c83074fba9331590106 /sound | |
parent | a2e46b76f3d1308b6e65aa9109f44428473dff2b (diff) | |
download | scummvm-rg350-a9d9de7db4eeacab240a76bd29ed8e95316546c9.tar.gz scummvm-rg350-a9d9de7db4eeacab240a76bd29ed8e95316546c9.tar.bz2 scummvm-rg350-a9d9de7db4eeacab240a76bd29ed8e95316546c9.zip |
implemented setting note-periods, likely still somewhat wrong.
reversed the log functions which does exactly the inverse as the name implies (its refered as "antilog" in the sources *rollseyes*)
svn-id: r42273
Diffstat (limited to 'sound')
-rw-r--r-- | sound/mods/maxtrax.cpp | 66 | ||||
-rw-r--r-- | sound/mods/maxtrax.h | 4 |
2 files changed, 63 insertions, 7 deletions
diff --git a/sound/mods/maxtrax.cpp b/sound/mods/maxtrax.cpp index 2359cc92cc..4f863ee7ba 100644 --- a/sound/mods/maxtrax.cpp +++ b/sound/mods/maxtrax.cpp @@ -22,7 +22,6 @@ * $Id$ * */ - #include "common/scummsys.h" #include "common/endian.h" #include "common/stream.h" @@ -124,7 +123,8 @@ void MaxTrax::interrupt() { break; case 0xE0: // BEND channel.pitchBend = ((stopTime & 0x7F00) >> 1) | (stopTime & 0x7f); - channel.pitchReal = ((int32)(channel.pitchBendRange << 8) * (channel.pitchBend - (64 << 7))) / (64 << 7); + // channel.pitchReal = ((int32)(channel.pitchBendRange << 8) * (channel.pitchBend - (64 << 7))) / (64 << 7); + channel.pitchReal = ((channel.pitchBendRange * channel.pitchBend) >> 5) - (channel.pitchBendRange << 8); channel.flags |= ChannelContext::kFlagAltered; break; case 0xFF: // END @@ -165,6 +165,13 @@ void MaxTrax::interrupt() { } +int32 MaxTrax::omgItsAntiLog(uint32 val) { + // some really weird exponential function, and some also very nonstandard "standard format" floats + // format is 16? bit exponent, 16 bit mantissa. and we need to scale with log(2) + const float v = ldexp((float)((val & 0xFFFF) + 0x10000) * (float)(0.69314718055994530942 / 65536), val >> 16); + return (uint32)exp(v); +} + void MaxTrax::stopMusic() { } @@ -199,6 +206,54 @@ void MaxTrax::killVoice(byte num) { Paula::setChannelVolume(num, 0); } +int MaxTrax::calcNote(VoiceContext &voice) { + ChannelContext &channel = *voice.channel; + voice.lastPeriod = 0; + + int16 bend = 0; + if ((voice.flags & VoiceContext::kFlagPortamento) != 0) { + // microtonal crap + + bend = (int16)((int8)(voice.endNote - voice.baseNote) * voice.portaTicks) / channel.portamento; + } + // modulation + if (channel.modulation && (channel.flags & ChannelContext::kFlagModVolume) == 0) { + // TODO get sine + int32 sinevalue = 0; + // TODO + } + + int32 tone = bend + channel.pitchReal; + // more it-never-worked microtonal code + tone += voice.baseNote << 8; + + Patch &patch = *voice.patch; + tone += ((int16)patch.tune << 8) / 24; + + tone -= 45 << 8; // MIDI note 45 + + tone = (((tone * 4) / 3) << 4); + enum { K_VALUE = 0x9fd77, PREF_PERIOD = 0x8fd77, PERIOD_LIMIT = 0x6f73d }; + + tone = K_VALUE - tone; + int octave = 0; + + if ((voice.flags & VoiceContext::kFlagRecalc) == 0) { + voice.periodOffset = 0; + const int maxOctave = patch.sampleOctaves - 1; + while (tone > PREF_PERIOD && octave < maxOctave) { + tone -= 1 << 4; + voice.periodOffset += 1 <<4; + octave++; + } + tone -= voice.periodOffset; + } + if (tone < PERIOD_LIMIT) + voice.lastPeriod = (uint16)omgItsAntiLog((float)tone); + + return octave; +} + int8 MaxTrax::noteOn(ChannelContext &channel, const byte note, uint16 volume, uint16 pri) { if (channel.microtonal >= 0) _microtonal[note % 127] = channel.microtonal; @@ -246,7 +301,7 @@ int8 MaxTrax::noteOn(ChannelContext &channel, const byte note, uint16 volume, ui voice.patch = &patch; voice.baseNote = note; - // calc note period + int useOctave = calcNote(voice); voice.priority = (byte)pri; voice.status = VoiceContext::kStatusStart; @@ -263,14 +318,13 @@ int8 MaxTrax::noteOn(ChannelContext &channel, const byte note, uint16 volume, ui if (!period) period = 1000; - int useOctave = 0; // get samplestart for the given octave const int8 *samplePtr = patch.samplePtr + (patch.sampleTotalLen << useOctave) - patch.sampleTotalLen; if (patch.sampleAttackLen) { Paula::setChannelSampleStart(voiceNum, samplePtr); Paula::setChannelSampleLen(voiceNum, patch.sampleAttackLen << useOctave); Paula::setChannelPeriod(voiceNum, period); - Paula::setChannelVolume(voiceNum, 0); + Paula::setChannelVolume(voiceNum, 0x64); Paula::enableChannel(voiceNum); // wait for dma-clear @@ -282,7 +336,7 @@ int8 MaxTrax::noteOn(ChannelContext &channel, const byte note, uint16 volume, ui if (!patch.sampleAttackLen) { // need to enable channel Paula::setChannelPeriod(voiceNum, period); - Paula::setChannelVolume(voiceNum, 0); + Paula::setChannelVolume(voiceNum, 0x64); Paula::enableChannel(voiceNum); } diff --git a/sound/mods/maxtrax.h b/sound/mods/maxtrax.h index 4055c750aa..3efed92954 100644 --- a/sound/mods/maxtrax.h +++ b/sound/mods/maxtrax.h @@ -156,7 +156,7 @@ public: uint32 uinqueId; uint32 lastTicks; uint32 tocksLeft; - uint32 portaTicks; + int32 portaTicks; uint32 incrVolume; uint32 periodOffset; /*ifne FASTSOUND @@ -205,6 +205,8 @@ public: void freePatches(); void freeScores(); + static int32 omgItsAntiLog(uint32 val); + int calcNote(VoiceContext &voice); int8 noteOn(ChannelContext &channel, byte note, uint16 volume, uint16 pri); void noteOff(ChannelContext &channel, byte note); void killVoice(byte num); |