aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorNorbert Lange2009-07-08 22:59:50 +0000
committerNorbert Lange2009-07-08 22:59:50 +0000
commita9d9de7db4eeacab240a76bd29ed8e95316546c9 (patch)
tree1763e458e9a089f3e1d89c83074fba9331590106 /sound
parenta2e46b76f3d1308b6e65aa9109f44428473dff2b (diff)
downloadscummvm-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.cpp66
-rw-r--r--sound/mods/maxtrax.h4
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);