gosu 0.15.2 → 1.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/dependencies/SDL/include/SDL.h +138 -0
- data/dependencies/SDL/include/SDL_assert.h +293 -0
- data/dependencies/SDL/include/SDL_atomic.h +295 -0
- data/dependencies/SDL/include/SDL_audio.h +859 -0
- data/dependencies/SDL/include/SDL_bits.h +121 -0
- data/dependencies/SDL/include/SDL_blendmode.h +123 -0
- data/dependencies/SDL/include/SDL_clipboard.h +71 -0
- data/dependencies/SDL/include/SDL_config.h +55 -0
- data/dependencies/SDL/include/SDL_config_android.h +182 -0
- data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
- data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
- data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
- data/dependencies/SDL/include/SDL_config_os2.h +188 -0
- data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
- data/dependencies/SDL/include/SDL_config_psp.h +165 -0
- data/dependencies/SDL/include/SDL_config_windows.h +288 -0
- data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
- data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
- data/dependencies/SDL/include/SDL_copying.h +20 -0
- data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
- data/dependencies/SDL/include/SDL_egl.h +1676 -0
- data/dependencies/SDL/include/SDL_endian.h +263 -0
- data/dependencies/SDL/include/SDL_error.h +112 -0
- data/dependencies/SDL/include/SDL_events.h +827 -0
- data/dependencies/SDL/include/SDL_filesystem.h +136 -0
- data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
- data/dependencies/SDL/include/SDL_gesture.h +87 -0
- data/dependencies/SDL/include/SDL_haptic.h +1247 -0
- data/dependencies/SDL/include/SDL_hints.h +1578 -0
- data/dependencies/SDL/include/SDL_joystick.h +499 -0
- data/dependencies/SDL/include/SDL_keyboard.h +217 -0
- data/dependencies/SDL/include/SDL_keycode.h +351 -0
- data/dependencies/SDL/include/SDL_loadso.h +81 -0
- data/dependencies/SDL/include/SDL_locale.h +101 -0
- data/dependencies/SDL/include/SDL_log.h +211 -0
- data/dependencies/SDL/include/SDL_main.h +180 -0
- data/dependencies/SDL/include/SDL_messagebox.h +146 -0
- data/dependencies/SDL/include/SDL_metal.h +117 -0
- data/dependencies/SDL/include/SDL_misc.h +75 -0
- data/dependencies/SDL/include/SDL_mouse.h +302 -0
- data/dependencies/SDL/include/SDL_mutex.h +251 -0
- data/dependencies/SDL/include/SDL_name.h +33 -0
- data/dependencies/SDL/include/SDL_opengl.h +2183 -0
- data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
- data/dependencies/SDL/include/SDL_opengles.h +39 -0
- data/dependencies/SDL/include/SDL_opengles2.h +52 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
- data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
- data/dependencies/SDL/include/SDL_pixels.h +479 -0
- data/dependencies/SDL/include/SDL_platform.h +198 -0
- data/dependencies/SDL/include/SDL_power.h +75 -0
- data/dependencies/SDL/include/SDL_quit.h +58 -0
- data/dependencies/SDL/include/SDL_rect.h +174 -0
- data/dependencies/SDL/include/SDL_render.h +1158 -0
- data/dependencies/SDL/include/SDL_revision.h +2 -0
- data/dependencies/SDL/include/SDL_rwops.h +283 -0
- data/dependencies/SDL/include/SDL_scancode.h +413 -0
- data/dependencies/SDL/include/SDL_sensor.h +267 -0
- data/dependencies/SDL/include/SDL_shape.h +144 -0
- data/dependencies/SDL/include/SDL_stdinc.h +647 -0
- data/dependencies/SDL/include/SDL_surface.h +563 -0
- data/dependencies/SDL/include/SDL_system.h +325 -0
- data/dependencies/SDL/include/SDL_syswm.h +354 -0
- data/dependencies/SDL/include/SDL_test.h +69 -0
- data/dependencies/SDL/include/SDL_test_assert.h +105 -0
- data/dependencies/SDL/include/SDL_test_common.h +218 -0
- data/dependencies/SDL/include/SDL_test_compare.h +69 -0
- data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
- data/dependencies/SDL/include/SDL_test_font.h +81 -0
- data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
- data/dependencies/SDL/include/SDL_test_harness.h +134 -0
- data/dependencies/SDL/include/SDL_test_images.h +78 -0
- data/dependencies/SDL/include/SDL_test_log.h +67 -0
- data/dependencies/SDL/include/SDL_test_md5.h +129 -0
- data/dependencies/SDL/include/SDL_test_memory.h +63 -0
- data/dependencies/SDL/include/SDL_test_random.h +115 -0
- data/dependencies/SDL/include/SDL_thread.h +366 -0
- data/dependencies/SDL/include/SDL_timer.h +115 -0
- data/dependencies/SDL/include/SDL_touch.h +102 -0
- data/dependencies/SDL/include/SDL_types.h +29 -0
- data/dependencies/SDL/include/SDL_version.h +162 -0
- data/dependencies/SDL/include/SDL_video.h +1282 -0
- data/dependencies/SDL/include/SDL_vulkan.h +276 -0
- data/dependencies/SDL/include/begin_code.h +166 -0
- data/dependencies/SDL/include/close_code.h +40 -0
- data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
- data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
- data/dependencies/SDL_sound/SDL_sound.c +795 -0
- data/dependencies/SDL_sound/SDL_sound.h +725 -0
- data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
- data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
- data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
- data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
- data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
- data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
- data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
- data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
- data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
- data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
- data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
- data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
- data/dependencies/SDL_sound/dr_flac.h +5906 -0
- data/dependencies/SDL_sound/dr_mp3.h +2832 -0
- data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
- data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
- data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
- data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
- data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
- data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
- data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
- data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
- data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
- data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
- data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
- data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
- data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
- data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
- data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
- data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
- data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
- data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
- data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
- data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
- data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
- data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
- data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
- data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
- data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
- data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
- data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
- data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
- data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
- data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
- data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
- data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
- data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
- data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
- data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
- data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
- data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
- data/dependencies/al_soft/AL/al.h +655 -0
- data/dependencies/al_soft/AL/alc.h +270 -0
- data/dependencies/al_soft/AL/alext.h +585 -0
- data/dependencies/al_soft/AL/efx-creative.h +3 -0
- data/dependencies/al_soft/AL/efx-presets.h +402 -0
- data/dependencies/al_soft/AL/efx.h +762 -0
- data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
- data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
- data/{src → dependencies/stb}/stb_image.h +330 -127
- data/{src → dependencies/stb}/stb_image_write.h +156 -85
- data/{src → dependencies/stb}/stb_truetype.h +192 -69
- data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
- data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
- data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
- data/ext/gosu/extconf.rb +53 -39
- data/{Gosu → include/Gosu}/Audio.hpp +6 -8
- data/include/Gosu/Bitmap.hpp +100 -0
- data/{Gosu → include/Gosu}/Buttons.hpp +104 -44
- data/{Gosu → include/Gosu}/Color.hpp +0 -0
- data/{Gosu → include/Gosu}/Directories.hpp +0 -0
- data/{Gosu → include/Gosu}/Font.hpp +1 -1
- data/{Gosu → include/Gosu}/Fwd.hpp +0 -5
- data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
- data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
- data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
- data/{Gosu → include/Gosu}/IO.hpp +0 -0
- data/{Gosu → include/Gosu}/Image.hpp +7 -6
- data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
- data/{Gosu → include/Gosu}/Input.hpp +39 -51
- data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
- data/{Gosu → include/Gosu}/Math.hpp +0 -0
- data/{Gosu → include/Gosu}/Platform.hpp +0 -0
- data/{Gosu → include/Gosu}/Text.hpp +0 -0
- data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
- data/{Gosu → include/Gosu}/Timing.hpp +0 -0
- data/{Gosu → include/Gosu}/Utility.hpp +15 -4
- data/{Gosu → include/Gosu}/Version.hpp +3 -3
- data/{Gosu → include/Gosu}/Window.hpp +46 -34
- data/lib/OpenAL32.dll +0 -0
- data/lib/SDL2.dll +0 -0
- data/lib/gosu.rb +0 -3
- data/lib/gosu/patches.rb +0 -23
- data/lib/gosu/preview.rb +1 -3
- data/lib/gosu/swig_patches.rb +14 -12
- data/lib64/OpenAL32.dll +0 -0
- data/lib64/SDL2.dll +0 -0
- data/rdoc/gosu.rb +112 -23
- data/src/Audio.cpp +50 -224
- data/src/AudioFile.hpp +20 -37
- data/src/AudioFileAudioToolbox.cpp +237 -0
- data/src/AudioFileSDLSound.cpp +147 -0
- data/src/AudioImpl.cpp +3 -12
- data/src/AudioImpl.hpp +3 -1
- data/src/Bitmap.cpp +85 -83
- data/src/BitmapIO.cpp +52 -58
- data/src/Font.cpp +3 -1
- data/src/Graphics.cpp +7 -4
- data/src/Image.cpp +13 -16
- data/src/Input.cpp +412 -164
- data/src/LargeImageData.cpp +1 -1
- data/src/MarkupParser.cpp +2 -1
- data/src/Resolution.cpp +8 -8
- data/src/RubyGosu.cxx +1017 -196
- data/src/RubyGosu.h +4 -2
- data/src/TexChunk.cpp +1 -1
- data/src/TextBuilder.cpp +3 -1
- data/src/Texture.cpp +1 -1
- data/src/TrueTypeFont.cpp +1 -1
- data/src/TrueTypeFontWin.cpp +3 -3
- data/src/Utility.cpp +11 -7
- data/src/Window.cpp +90 -62
- data/src/WindowUIKit.cpp +21 -9
- metadata +194 -65
- data/Gosu/AutoLink.hpp +0 -14
- data/Gosu/Bitmap.hpp +0 -113
- data/Gosu/Channel.h +0 -25
- data/Gosu/Color.h +0 -38
- data/Gosu/Font.h +0 -36
- data/Gosu/Gosu.h +0 -79
- data/Gosu/Image.h +0 -54
- data/Gosu/Sample.h +0 -19
- data/Gosu/Song.h +0 -24
- data/Gosu/TextInput.h +0 -30
- data/Gosu/Window.h +0 -61
- data/lib/gosu/zen.rb +0 -89
- data/src/AudioToolboxFile.hpp +0 -210
- data/src/ChannelWrapper.cpp +0 -50
- data/src/ColorWrapper.cpp +0 -126
- data/src/Constants.cpp +0 -287
- data/src/FontWrapper.cpp +0 -74
- data/src/GosuWrapper.cpp +0 -232
- data/src/ImageWrapper.cpp +0 -168
- data/src/MPEGFile.hpp +0 -90
- data/src/OggFile.hpp +0 -92
- data/src/SampleWrapper.cpp +0 -30
- data/src/SndFile.hpp +0 -174
- data/src/SongWrapper.cpp +0 -52
- data/src/TextInputWrapper.cpp +0 -101
- data/src/WinMain.cpp +0 -64
- data/src/WindowWrapper.cpp +0 -289
@@ -0,0 +1,2350 @@
|
|
1
|
+
/*
|
2
|
+
* This source code is public domain.
|
3
|
+
*
|
4
|
+
* Authors: Olivier Lapicque <olivierl@jps.net>
|
5
|
+
*/
|
6
|
+
|
7
|
+
#include "libmodplug.h"
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include "tables.h"
|
10
|
+
|
11
|
+
DWORD CSoundFile_GetLength(CSoundFile *_this, BOOL bAdjust, BOOL bTotal)
|
12
|
+
//----------------------------------------------------
|
13
|
+
{
|
14
|
+
UINT dwElapsedTime=0, nRow=0, nCurrentPattern=0, nNextPattern=0, nPattern=0;
|
15
|
+
UINT nMusicSpeed=_this->m_nDefaultSpeed, nMusicTempo=_this->m_nDefaultTempo, nNextRow=0;
|
16
|
+
UINT nMaxRow = 0, nMaxPattern = 0;
|
17
|
+
LONG nGlbVol = _this->m_nDefaultGlobalVolume, nOldGlbVolSlide = 0;
|
18
|
+
BYTE samples[MAX_CHANNELS];
|
19
|
+
BYTE instr[MAX_CHANNELS];
|
20
|
+
BYTE notes[MAX_CHANNELS];
|
21
|
+
BYTE vols[MAX_CHANNELS];
|
22
|
+
BYTE oldparam[MAX_CHANNELS];
|
23
|
+
BYTE chnvols[MAX_CHANNELS];
|
24
|
+
DWORD patloop[MAX_CHANNELS];
|
25
|
+
|
26
|
+
SDL_memset(instr, 0, sizeof(instr));
|
27
|
+
SDL_memset(notes, 0, sizeof(notes));
|
28
|
+
SDL_memset(vols, 0xFF, sizeof(vols));
|
29
|
+
SDL_memset(patloop, 0, sizeof(patloop));
|
30
|
+
SDL_memset(oldparam, 0, sizeof(oldparam));
|
31
|
+
SDL_memset(chnvols, 64, sizeof(chnvols));
|
32
|
+
SDL_memset(samples, 0, sizeof(samples));
|
33
|
+
for (UINT icv=0; icv<_this->m_nChannels; icv++)
|
34
|
+
chnvols[icv] = _this->ChnSettings[icv].nVolume;
|
35
|
+
nMaxRow = _this->m_nNextRow;
|
36
|
+
nMaxPattern = _this->m_nNextPattern;
|
37
|
+
for (;;)
|
38
|
+
{
|
39
|
+
UINT nSpeedCount = 0;
|
40
|
+
nRow = nNextRow;
|
41
|
+
nCurrentPattern = nNextPattern;
|
42
|
+
// Check if pattern is valid
|
43
|
+
nPattern = _this->Order[nCurrentPattern];
|
44
|
+
while (nPattern >= MAX_PATTERNS)
|
45
|
+
{
|
46
|
+
// End of song ?
|
47
|
+
if ((nPattern == 0xFF) || (nCurrentPattern >= MAX_ORDERS))
|
48
|
+
{
|
49
|
+
goto EndMod;
|
50
|
+
} else
|
51
|
+
{
|
52
|
+
nCurrentPattern++;
|
53
|
+
nPattern = (nCurrentPattern < MAX_ORDERS) ? _this->Order[nCurrentPattern] : 0xFF;
|
54
|
+
}
|
55
|
+
nNextPattern = nCurrentPattern;
|
56
|
+
}
|
57
|
+
// Weird stuff?
|
58
|
+
if ((nPattern >= MAX_PATTERNS) || (!_this->Patterns[nPattern])) break;
|
59
|
+
// Should never happen
|
60
|
+
if (nRow >= _this->PatternSize[nPattern]) nRow = 0;
|
61
|
+
// Update next position
|
62
|
+
nNextRow = nRow + 1;
|
63
|
+
if (nNextRow >= _this->PatternSize[nPattern])
|
64
|
+
{
|
65
|
+
nNextPattern = nCurrentPattern + 1;
|
66
|
+
nNextRow = 0;
|
67
|
+
}
|
68
|
+
if (!nRow)
|
69
|
+
{
|
70
|
+
for (UINT ipck=0; ipck<_this->m_nChannels; ipck++) patloop[ipck] = dwElapsedTime;
|
71
|
+
}
|
72
|
+
if (!bTotal)
|
73
|
+
{
|
74
|
+
if ((nCurrentPattern > nMaxPattern) || ((nCurrentPattern == nMaxPattern) && (nRow >= nMaxRow)))
|
75
|
+
{
|
76
|
+
if (bAdjust)
|
77
|
+
{
|
78
|
+
_this->m_nMusicSpeed = nMusicSpeed;
|
79
|
+
_this->m_nMusicTempo = nMusicTempo;
|
80
|
+
}
|
81
|
+
break;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
MODCHANNEL *pChn = _this->Chn;
|
85
|
+
MODCOMMAND *p = _this->Patterns[nPattern] + nRow * _this->m_nChannels;
|
86
|
+
for (UINT nChn=0; nChn<_this->m_nChannels; p++,pChn++, nChn++) if (*((DWORD *)p))
|
87
|
+
{
|
88
|
+
UINT command = p->command;
|
89
|
+
UINT param = p->param;
|
90
|
+
UINT note = p->note;
|
91
|
+
if (p->instr) { instr[nChn] = p->instr; notes[nChn] = 0; vols[nChn] = 0xFF; }
|
92
|
+
if ((note) && (note <= NOTE_MAX)) notes[nChn] = note;
|
93
|
+
if (p->volcmd == VOLCMD_VOLUME) { vols[nChn] = p->vol; }
|
94
|
+
if (command) switch (command)
|
95
|
+
{
|
96
|
+
// Position Jump
|
97
|
+
case CMD_POSITIONJUMP:
|
98
|
+
if (param <= nCurrentPattern) goto EndMod;
|
99
|
+
nNextPattern = param;
|
100
|
+
nNextRow = 0;
|
101
|
+
if (bAdjust)
|
102
|
+
{
|
103
|
+
pChn->nPatternLoopCount = 0;
|
104
|
+
pChn->nPatternLoop = 0;
|
105
|
+
}
|
106
|
+
break;
|
107
|
+
// Pattern Break
|
108
|
+
case CMD_PATTERNBREAK:
|
109
|
+
nNextRow = param;
|
110
|
+
nNextPattern = nCurrentPattern + 1;
|
111
|
+
if (bAdjust)
|
112
|
+
{
|
113
|
+
pChn->nPatternLoopCount = 0;
|
114
|
+
pChn->nPatternLoop = 0;
|
115
|
+
}
|
116
|
+
break;
|
117
|
+
// Set Speed
|
118
|
+
case CMD_SPEED:
|
119
|
+
if (!param) break;
|
120
|
+
if ((param <= 0x20) || (_this->m_nType != MOD_TYPE_MOD))
|
121
|
+
{
|
122
|
+
if (param < 128) nMusicSpeed = param;
|
123
|
+
}
|
124
|
+
break;
|
125
|
+
// Set Tempo
|
126
|
+
case CMD_TEMPO:
|
127
|
+
if ((bAdjust) && (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))
|
128
|
+
{
|
129
|
+
if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo;
|
130
|
+
}
|
131
|
+
if (param >= 0x20) nMusicTempo = param; else
|
132
|
+
// Tempo Slide
|
133
|
+
if ((param & 0xF0) == 0x10)
|
134
|
+
{
|
135
|
+
nMusicTempo += param & 0x0F;
|
136
|
+
if (nMusicTempo > 255) nMusicTempo = 255;
|
137
|
+
} else
|
138
|
+
{
|
139
|
+
nMusicTempo -= param & 0x0F;
|
140
|
+
if (nMusicTempo < 32) nMusicTempo = 32;
|
141
|
+
}
|
142
|
+
break;
|
143
|
+
// Pattern Delay
|
144
|
+
case CMD_S3MCMDEX:
|
145
|
+
if ((param & 0xF0) == 0x60) { nSpeedCount = param & 0x0F; break; } else
|
146
|
+
if ((param & 0xF0) == 0xB0) { param &= 0x0F; param |= 0x60; }
|
147
|
+
case CMD_MODCMDEX:
|
148
|
+
if ((param & 0xF0) == 0xE0) nSpeedCount = (param & 0x0F) * nMusicSpeed; else
|
149
|
+
if ((param & 0xF0) == 0x60)
|
150
|
+
{
|
151
|
+
if (param & 0x0F) dwElapsedTime += (dwElapsedTime - patloop[nChn]) * (param & 0x0F);
|
152
|
+
else patloop[nChn] = dwElapsedTime;
|
153
|
+
}
|
154
|
+
break;
|
155
|
+
}
|
156
|
+
if (!bAdjust) continue;
|
157
|
+
switch(command)
|
158
|
+
{
|
159
|
+
// Portamento Up/Down
|
160
|
+
case CMD_PORTAMENTOUP:
|
161
|
+
case CMD_PORTAMENTODOWN:
|
162
|
+
if (param) pChn->nOldPortaUpDown = param;
|
163
|
+
break;
|
164
|
+
// Tone-Portamento
|
165
|
+
case CMD_TONEPORTAMENTO:
|
166
|
+
if (param) pChn->nPortamentoSlide = param << 2;
|
167
|
+
break;
|
168
|
+
// Offset
|
169
|
+
case CMD_OFFSET:
|
170
|
+
if (param) pChn->nOldOffset = param;
|
171
|
+
break;
|
172
|
+
// Volume Slide
|
173
|
+
case CMD_VOLUMESLIDE:
|
174
|
+
case CMD_TONEPORTAVOL:
|
175
|
+
case CMD_VIBRATOVOL:
|
176
|
+
if (param) pChn->nOldVolumeSlide = param;
|
177
|
+
break;
|
178
|
+
// Set Volume
|
179
|
+
case CMD_VOLUME:
|
180
|
+
vols[nChn] = param;
|
181
|
+
break;
|
182
|
+
// Global Volume
|
183
|
+
case CMD_GLOBALVOLUME:
|
184
|
+
if (!(_this->m_nType & (MOD_TYPE_IT))) param <<= 1;
|
185
|
+
if (param > 128) param = 128;
|
186
|
+
nGlbVol = param << 1;
|
187
|
+
break;
|
188
|
+
// Global Volume Slide
|
189
|
+
case CMD_GLOBALVOLSLIDE:
|
190
|
+
if (param) nOldGlbVolSlide = param; else param = nOldGlbVolSlide;
|
191
|
+
if (((param & 0x0F) == 0x0F) && (param & 0xF0))
|
192
|
+
{
|
193
|
+
param >>= 4;
|
194
|
+
if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
|
195
|
+
nGlbVol += param << 1;
|
196
|
+
} else
|
197
|
+
if (((param & 0xF0) == 0xF0) && (param & 0x0F))
|
198
|
+
{
|
199
|
+
param = (param & 0x0F) << 1;
|
200
|
+
if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
|
201
|
+
nGlbVol -= param;
|
202
|
+
} else
|
203
|
+
if (param & 0xF0)
|
204
|
+
{
|
205
|
+
param >>= 4;
|
206
|
+
param <<= 1;
|
207
|
+
if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
|
208
|
+
nGlbVol += param * nMusicSpeed;
|
209
|
+
} else
|
210
|
+
{
|
211
|
+
param = (param & 0x0F) << 1;
|
212
|
+
if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
|
213
|
+
nGlbVol -= param * nMusicSpeed;
|
214
|
+
}
|
215
|
+
if (nGlbVol < 0) nGlbVol = 0;
|
216
|
+
if (nGlbVol > 256) nGlbVol = 256;
|
217
|
+
break;
|
218
|
+
case CMD_CHANNELVOLUME:
|
219
|
+
if (param <= 64) chnvols[nChn] = param;
|
220
|
+
break;
|
221
|
+
case CMD_CHANNELVOLSLIDE:
|
222
|
+
if (param) oldparam[nChn] = param; else param = oldparam[nChn];
|
223
|
+
pChn->nOldChnVolSlide = param;
|
224
|
+
if (((param & 0x0F) == 0x0F) && (param & 0xF0))
|
225
|
+
{
|
226
|
+
param = (param >> 4) + chnvols[nChn];
|
227
|
+
} else
|
228
|
+
if (((param & 0xF0) == 0xF0) && (param & 0x0F))
|
229
|
+
{
|
230
|
+
if (chnvols[nChn] > (int)(param & 0x0F)) param = chnvols[nChn] - (param & 0x0F);
|
231
|
+
else param = 0;
|
232
|
+
} else
|
233
|
+
if (param & 0x0F)
|
234
|
+
{
|
235
|
+
param = (param & 0x0F) * nMusicSpeed;
|
236
|
+
param = (chnvols[nChn] > param) ? chnvols[nChn] - param : 0;
|
237
|
+
} else param = ((param & 0xF0) >> 4) * nMusicSpeed + chnvols[nChn];
|
238
|
+
if (param > 64) param = 64;
|
239
|
+
chnvols[nChn] = param;
|
240
|
+
break;
|
241
|
+
}
|
242
|
+
}
|
243
|
+
nSpeedCount += nMusicSpeed;
|
244
|
+
dwElapsedTime += (2500 * nSpeedCount) / nMusicTempo;
|
245
|
+
}
|
246
|
+
EndMod:
|
247
|
+
if ((bAdjust) && (!bTotal))
|
248
|
+
{
|
249
|
+
_this->m_nGlobalVolume = nGlbVol;
|
250
|
+
_this->m_nOldGlbVolSlide = nOldGlbVolSlide;
|
251
|
+
for (UINT n=0; n<_this->m_nChannels; n++)
|
252
|
+
{
|
253
|
+
_this->Chn[n].nGlobalVol = chnvols[n];
|
254
|
+
if (notes[n]) _this->Chn[n].nNewNote = notes[n];
|
255
|
+
if (instr[n]) _this->Chn[n].nNewIns = instr[n];
|
256
|
+
if (vols[n] != 0xFF)
|
257
|
+
{
|
258
|
+
if (vols[n] > 64) vols[n] = 64;
|
259
|
+
_this->Chn[n].nVolume = vols[n] << 2;
|
260
|
+
}
|
261
|
+
}
|
262
|
+
}
|
263
|
+
return (dwElapsedTime+500) / 1000;
|
264
|
+
}
|
265
|
+
|
266
|
+
|
267
|
+
//////////////////////////////////////////////////////////////////////////////////////////////////
|
268
|
+
// Effects
|
269
|
+
|
270
|
+
void CSoundFile_InstrumentChange(CSoundFile *_this, MODCHANNEL *pChn, UINT instr, BOOL bPorta, BOOL bUpdVol, BOOL bResetEnv)
|
271
|
+
//--------------------------------------------------------------------------------------------------------
|
272
|
+
{
|
273
|
+
BOOL bInstrumentChanged = FALSE;
|
274
|
+
|
275
|
+
if (instr >= MAX_INSTRUMENTS) return;
|
276
|
+
INSTRUMENTHEADER *penv = _this->Headers[instr];
|
277
|
+
MODINSTRUMENT *psmp = &_this->Ins[instr];
|
278
|
+
UINT note = pChn->nNewNote;
|
279
|
+
if ((penv) && (note) && (note <= 128))
|
280
|
+
{
|
281
|
+
if (penv->NoteMap[note-1] >= 0xFE) return;
|
282
|
+
UINT n = penv->Keyboard[note-1];
|
283
|
+
psmp = ((n) && (n < MAX_SAMPLES)) ? &_this->Ins[n] : NULL;
|
284
|
+
} else
|
285
|
+
if (_this->m_nInstruments)
|
286
|
+
{
|
287
|
+
if (note >= 0xFE) return;
|
288
|
+
psmp = NULL;
|
289
|
+
}
|
290
|
+
// Update Volume
|
291
|
+
if (bUpdVol) pChn->nVolume = (psmp) ? psmp->nVolume : 0;
|
292
|
+
// bInstrumentChanged is used for IT carry-on env option
|
293
|
+
if (penv != pChn->pHeader)
|
294
|
+
{
|
295
|
+
bInstrumentChanged = TRUE;
|
296
|
+
pChn->pHeader = penv;
|
297
|
+
} else
|
298
|
+
{
|
299
|
+
// Special XM hack
|
300
|
+
if ((bPorta) && (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (penv)
|
301
|
+
&& (pChn->pInstrument) && (psmp != pChn->pInstrument))
|
302
|
+
{
|
303
|
+
// FT2 doesn't change the sample in this case,
|
304
|
+
// but still uses the sample info from the old one (bug?)
|
305
|
+
return;
|
306
|
+
}
|
307
|
+
}
|
308
|
+
// Instrument adjust
|
309
|
+
pChn->nNewIns = 0;
|
310
|
+
if (psmp)
|
311
|
+
{
|
312
|
+
if (penv)
|
313
|
+
{
|
314
|
+
pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 6;
|
315
|
+
if (penv->dwFlags & ENV_SETPANNING) pChn->nPan = penv->nPan;
|
316
|
+
pChn->nNNA = penv->nNNA;
|
317
|
+
} else
|
318
|
+
{
|
319
|
+
pChn->nInsVol = psmp->nGlobalVol;
|
320
|
+
}
|
321
|
+
if (psmp->uFlags & CHN_PANNING) pChn->nPan = psmp->nPan;
|
322
|
+
}
|
323
|
+
// Reset envelopes
|
324
|
+
if (bResetEnv)
|
325
|
+
{
|
326
|
+
if ((!bPorta) || (!(_this->m_nType & MOD_TYPE_IT)) || (_this->m_dwSongFlags & SONG_ITCOMPATMODE)
|
327
|
+
|| (!pChn->nLength) || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol)))
|
328
|
+
{
|
329
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
330
|
+
if ((_this->m_nType & MOD_TYPE_IT) && (!bInstrumentChanged) && (penv) && (!(pChn->dwFlags & (CHN_KEYOFF|CHN_NOTEFADE))))
|
331
|
+
{
|
332
|
+
if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0;
|
333
|
+
if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0;
|
334
|
+
if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0;
|
335
|
+
} else
|
336
|
+
{
|
337
|
+
pChn->nVolEnvPosition = 0;
|
338
|
+
pChn->nPanEnvPosition = 0;
|
339
|
+
pChn->nPitchEnvPosition = 0;
|
340
|
+
}
|
341
|
+
pChn->nAutoVibDepth = 0;
|
342
|
+
pChn->nAutoVibPos = 0;
|
343
|
+
} else
|
344
|
+
if ((penv) && (!(penv->dwFlags & ENV_VOLUME)))
|
345
|
+
{
|
346
|
+
pChn->nVolEnvPosition = 0;
|
347
|
+
pChn->nAutoVibDepth = 0;
|
348
|
+
pChn->nAutoVibPos = 0;
|
349
|
+
}
|
350
|
+
}
|
351
|
+
// Invalid sample ?
|
352
|
+
if (!psmp)
|
353
|
+
{
|
354
|
+
pChn->pInstrument = NULL;
|
355
|
+
pChn->nInsVol = 0;
|
356
|
+
return;
|
357
|
+
}
|
358
|
+
// Tone-Portamento doesn't reset the pingpong direction flag
|
359
|
+
if ((bPorta) && (psmp == pChn->pInstrument))
|
360
|
+
{
|
361
|
+
if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) return;
|
362
|
+
pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE);
|
363
|
+
pChn->dwFlags = (pChn->dwFlags & (0xFFFFFF00 | CHN_PINGPONGFLAG)) | (psmp->uFlags);
|
364
|
+
} else
|
365
|
+
{
|
366
|
+
pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE|CHN_VOLENV|CHN_PANENV|CHN_PITCHENV);
|
367
|
+
pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (psmp->uFlags);
|
368
|
+
if (penv)
|
369
|
+
{
|
370
|
+
if (penv->dwFlags & ENV_VOLUME) pChn->dwFlags |= CHN_VOLENV;
|
371
|
+
if (penv->dwFlags & ENV_PANNING) pChn->dwFlags |= CHN_PANENV;
|
372
|
+
if (penv->dwFlags & ENV_PITCH) pChn->dwFlags |= CHN_PITCHENV;
|
373
|
+
if ((penv->dwFlags & ENV_PITCH) && (penv->dwFlags & ENV_FILTER))
|
374
|
+
{
|
375
|
+
if (!pChn->nCutOff) pChn->nCutOff = 0x7F;
|
376
|
+
}
|
377
|
+
if (penv->nIFC & 0x80) pChn->nCutOff = penv->nIFC & 0x7F;
|
378
|
+
if (penv->nIFR & 0x80) pChn->nResonance = penv->nIFR & 0x7F;
|
379
|
+
}
|
380
|
+
pChn->nVolSwing = pChn->nPanSwing = 0;
|
381
|
+
}
|
382
|
+
pChn->pInstrument = psmp;
|
383
|
+
pChn->nLength = psmp->nLength;
|
384
|
+
pChn->nLoopStart = psmp->nLoopStart;
|
385
|
+
pChn->nLoopEnd = psmp->nLoopEnd;
|
386
|
+
pChn->nC4Speed = psmp->nC4Speed;
|
387
|
+
pChn->pSample = psmp->pSample;
|
388
|
+
pChn->nTranspose = psmp->RelativeTone;
|
389
|
+
pChn->nFineTune = psmp->nFineTune;
|
390
|
+
if (pChn->dwFlags & CHN_SUSTAINLOOP)
|
391
|
+
{
|
392
|
+
pChn->nLoopStart = psmp->nSustainStart;
|
393
|
+
pChn->nLoopEnd = psmp->nSustainEnd;
|
394
|
+
pChn->dwFlags |= CHN_LOOP;
|
395
|
+
if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP;
|
396
|
+
}
|
397
|
+
if ((pChn->dwFlags & CHN_LOOP) && (pChn->nLoopEnd < pChn->nLength)) pChn->nLength = pChn->nLoopEnd;
|
398
|
+
}
|
399
|
+
|
400
|
+
|
401
|
+
void CSoundFile_NoteChange(CSoundFile *_this, UINT nChn, int note, BOOL bPorta, BOOL bResetEnv)
|
402
|
+
//---------------------------------------------------------------------------
|
403
|
+
{
|
404
|
+
if (note < 1) return;
|
405
|
+
MODCHANNEL * const pChn = &_this->Chn[nChn];
|
406
|
+
MODINSTRUMENT *pins = pChn->pInstrument;
|
407
|
+
INSTRUMENTHEADER *penv = pChn->pHeader;
|
408
|
+
if ((penv) && (note <= 0x80))
|
409
|
+
{
|
410
|
+
UINT n = penv->Keyboard[note - 1];
|
411
|
+
if ((n) && (n < MAX_SAMPLES)) pins = &_this->Ins[n];
|
412
|
+
note = penv->NoteMap[note-1];
|
413
|
+
}
|
414
|
+
// Key Off
|
415
|
+
if (note >= 0x80) // 0xFE or invalid note => key off
|
416
|
+
{
|
417
|
+
// Key Off
|
418
|
+
CSoundFile_KeyOff(_this, nChn);
|
419
|
+
// Note Cut
|
420
|
+
if (note == 0xFE)
|
421
|
+
{
|
422
|
+
pChn->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
|
423
|
+
if ((!(_this->m_nType & MOD_TYPE_IT)) || (_this->m_nInstruments)) pChn->nVolume = 0;
|
424
|
+
pChn->nFadeOutVol = 0;
|
425
|
+
}
|
426
|
+
return;
|
427
|
+
}
|
428
|
+
if (!pins) return;
|
429
|
+
if ((!bPorta) && (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MT2)))
|
430
|
+
{
|
431
|
+
pChn->nTranspose = pins->RelativeTone;
|
432
|
+
pChn->nFineTune = pins->nFineTune;
|
433
|
+
}
|
434
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2|MOD_TYPE_MED)) note += pChn->nTranspose;
|
435
|
+
if (note < 1) note = 1;
|
436
|
+
if (note > 132) note = 132;
|
437
|
+
pChn->nNote = note;
|
438
|
+
if ((!bPorta) || (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) pChn->nNewIns = 0;
|
439
|
+
UINT period = CSoundFile_GetPeriodFromNote(_this, note, pChn->nFineTune, pChn->nC4Speed);
|
440
|
+
if (period)
|
441
|
+
{
|
442
|
+
if ((!bPorta) || (!pChn->nPeriod)) pChn->nPeriod = period;
|
443
|
+
pChn->nPortamentoDest = period;
|
444
|
+
if ((!bPorta) || ((!pChn->nLength) && (!(_this->m_nType & MOD_TYPE_S3M))))
|
445
|
+
{
|
446
|
+
pChn->pInstrument = pins;
|
447
|
+
pChn->pSample = pins->pSample;
|
448
|
+
pChn->nLength = pins->nLength;
|
449
|
+
pChn->nLoopEnd = pins->nLength;
|
450
|
+
pChn->nLoopStart = 0;
|
451
|
+
pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (pins->uFlags);
|
452
|
+
if (pChn->dwFlags & CHN_SUSTAINLOOP)
|
453
|
+
{
|
454
|
+
pChn->nLoopStart = pins->nSustainStart;
|
455
|
+
pChn->nLoopEnd = pins->nSustainEnd;
|
456
|
+
pChn->dwFlags &= ~CHN_PINGPONGLOOP;
|
457
|
+
pChn->dwFlags |= CHN_LOOP;
|
458
|
+
if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP;
|
459
|
+
if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
|
460
|
+
} else
|
461
|
+
if (pChn->dwFlags & CHN_LOOP)
|
462
|
+
{
|
463
|
+
pChn->nLoopStart = pins->nLoopStart;
|
464
|
+
pChn->nLoopEnd = pins->nLoopEnd;
|
465
|
+
if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
|
466
|
+
}
|
467
|
+
pChn->nPos = 0;
|
468
|
+
pChn->nPosLo = 0;
|
469
|
+
if (pChn->nVibratoType < 4) pChn->nVibratoPos = ((_this->m_nType & MOD_TYPE_IT) && (!(_this->m_dwSongFlags & SONG_ITOLDEFFECTS))) ? 0x10 : 0;
|
470
|
+
if (pChn->nTremoloType < 4) pChn->nTremoloPos = 0;
|
471
|
+
}
|
472
|
+
if (pChn->nPos >= pChn->nLength) pChn->nPos = pChn->nLoopStart;
|
473
|
+
} else bPorta = FALSE;
|
474
|
+
if ((!bPorta) || (!(_this->m_nType & MOD_TYPE_IT))
|
475
|
+
|| ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol))
|
476
|
+
|| ((_this->m_dwSongFlags & SONG_ITCOMPATMODE) && (pChn->nRowInstr)))
|
477
|
+
{
|
478
|
+
if ((_this->m_nType & MOD_TYPE_IT) && (pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol))
|
479
|
+
{
|
480
|
+
pChn->nVolEnvPosition = 0;
|
481
|
+
pChn->nPanEnvPosition = 0;
|
482
|
+
pChn->nPitchEnvPosition = 0;
|
483
|
+
pChn->nAutoVibDepth = 0;
|
484
|
+
pChn->nAutoVibPos = 0;
|
485
|
+
pChn->dwFlags &= ~CHN_NOTEFADE;
|
486
|
+
pChn->nFadeOutVol = 65536;
|
487
|
+
}
|
488
|
+
if ((!bPorta) || (!(_this->m_dwSongFlags & SONG_ITCOMPATMODE)) || (pChn->nRowInstr))
|
489
|
+
{
|
490
|
+
if ((!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) || (pChn->nRowInstr))
|
491
|
+
{
|
492
|
+
pChn->dwFlags &= ~CHN_NOTEFADE;
|
493
|
+
pChn->nFadeOutVol = 65536;
|
494
|
+
}
|
495
|
+
}
|
496
|
+
}
|
497
|
+
pChn->dwFlags &= ~(CHN_EXTRALOUD|CHN_KEYOFF);
|
498
|
+
// Enable Ramping
|
499
|
+
if (!bPorta)
|
500
|
+
{
|
501
|
+
pChn->dwFlags &= ~CHN_FILTER;
|
502
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
503
|
+
pChn->nRetrigCount = 0;
|
504
|
+
pChn->nTremorCount = 0;
|
505
|
+
if (bResetEnv)
|
506
|
+
{
|
507
|
+
pChn->nVolSwing = pChn->nPanSwing = 0;
|
508
|
+
if (penv)
|
509
|
+
{
|
510
|
+
if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0;
|
511
|
+
if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0;
|
512
|
+
if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0;
|
513
|
+
if (_this->m_nType & MOD_TYPE_IT)
|
514
|
+
{
|
515
|
+
// Volume Swing
|
516
|
+
if (penv->nVolSwing)
|
517
|
+
{
|
518
|
+
int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128;
|
519
|
+
pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128);
|
520
|
+
}
|
521
|
+
// Pan Swing
|
522
|
+
if (penv->nPanSwing)
|
523
|
+
{
|
524
|
+
int d = ((LONG)penv->nPanSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128;
|
525
|
+
pChn->nPanSwing = (signed short)d;
|
526
|
+
}
|
527
|
+
}
|
528
|
+
}
|
529
|
+
pChn->nAutoVibDepth = 0;
|
530
|
+
pChn->nAutoVibPos = 0;
|
531
|
+
}
|
532
|
+
pChn->nLeftVol = pChn->nRightVol = 0;
|
533
|
+
BOOL bFlt = (_this->m_dwSongFlags & SONG_MPTFILTERMODE) ? FALSE : TRUE;
|
534
|
+
// Setup Initial Filter for this note
|
535
|
+
if (penv)
|
536
|
+
{
|
537
|
+
if (penv->nIFR & 0x80) { pChn->nResonance = penv->nIFR & 0x7F; bFlt = TRUE; }
|
538
|
+
if (penv->nIFC & 0x80) { pChn->nCutOff = penv->nIFC & 0x7F; bFlt = TRUE; }
|
539
|
+
} else
|
540
|
+
{
|
541
|
+
pChn->nVolSwing = pChn->nPanSwing = 0;
|
542
|
+
}
|
543
|
+
#ifndef NO_FILTER
|
544
|
+
if ((pChn->nCutOff < 0x7F) && (bFlt)) CSoundFile_SetupChannelFilter(_this, pChn, TRUE, 256);
|
545
|
+
#endif // NO_FILTER
|
546
|
+
}
|
547
|
+
}
|
548
|
+
|
549
|
+
|
550
|
+
UINT CSoundFile_GetNNAChannel(CSoundFile *_this, UINT nChn)
|
551
|
+
//---------------------------------------------
|
552
|
+
{
|
553
|
+
const MODCHANNEL *pChn = &_this->Chn[nChn];
|
554
|
+
// Check for empty channel
|
555
|
+
const MODCHANNEL *pi = &_this->Chn[_this->m_nChannels];
|
556
|
+
for (UINT i=_this->m_nChannels; i<MAX_CHANNELS; i++, pi++) if (!pi->nLength) return i;
|
557
|
+
if (!pChn->nFadeOutVol) return 0;
|
558
|
+
// All channels are used: check for lowest volume
|
559
|
+
UINT result = 0;
|
560
|
+
DWORD vol = 64*65536; // 25%
|
561
|
+
DWORD envpos = 0xFFFFFF;
|
562
|
+
const MODCHANNEL *pj = &_this->Chn[_this->m_nChannels];
|
563
|
+
for (UINT j=_this->m_nChannels; j<MAX_CHANNELS; j++, pj++)
|
564
|
+
{
|
565
|
+
if (!pj->nFadeOutVol) return j;
|
566
|
+
DWORD v = pj->nVolume;
|
567
|
+
if (pj->dwFlags & CHN_NOTEFADE)
|
568
|
+
v = v * pj->nFadeOutVol;
|
569
|
+
else
|
570
|
+
v <<= 16;
|
571
|
+
if (pj->dwFlags & CHN_LOOP) v >>= 1;
|
572
|
+
if ((v < vol) || ((v == vol) && (pj->nVolEnvPosition > envpos)))
|
573
|
+
{
|
574
|
+
envpos = pj->nVolEnvPosition;
|
575
|
+
vol = v;
|
576
|
+
result = j;
|
577
|
+
}
|
578
|
+
}
|
579
|
+
return result;
|
580
|
+
}
|
581
|
+
|
582
|
+
|
583
|
+
void CSoundFile_CheckNNA(CSoundFile *_this, UINT nChn, UINT instr, int note, BOOL bForceCut)
|
584
|
+
//------------------------------------------------------------------------
|
585
|
+
{
|
586
|
+
MODCHANNEL *pChn = &_this->Chn[nChn];
|
587
|
+
INSTRUMENTHEADER *penv = pChn->pHeader, *pHeader = 0;
|
588
|
+
signed char *pSample;
|
589
|
+
if (note > 0x80) note = 0;
|
590
|
+
if (note < 1) return;
|
591
|
+
// Always NNA cut - using
|
592
|
+
if ((!(_this->m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!_this->m_nInstruments) || (bForceCut))
|
593
|
+
{
|
594
|
+
if ((_this->m_dwSongFlags & SONG_CPUVERYHIGH)
|
595
|
+
|| (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE)
|
596
|
+
|| ((!pChn->nLeftVol) && (!pChn->nRightVol))) return;
|
597
|
+
UINT n = CSoundFile_GetNNAChannel(_this, nChn);
|
598
|
+
if (!n) return;
|
599
|
+
MODCHANNEL *p = &_this->Chn[n];
|
600
|
+
// Copy Channel
|
601
|
+
SDL_memcpy(p, pChn, sizeof (*p));
|
602
|
+
p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO);
|
603
|
+
p->nMasterChn = nChn+1;
|
604
|
+
p->nCommand = 0;
|
605
|
+
// Cut the note
|
606
|
+
p->nFadeOutVol = 0;
|
607
|
+
p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
|
608
|
+
// Stop this channel
|
609
|
+
pChn->nLength = pChn->nPos = pChn->nPosLo = 0;
|
610
|
+
pChn->nROfs = pChn->nLOfs = 0;
|
611
|
+
pChn->nLeftVol = pChn->nRightVol = 0;
|
612
|
+
return;
|
613
|
+
}
|
614
|
+
if (instr >= MAX_INSTRUMENTS) instr = 0;
|
615
|
+
pSample = pChn->pSample;
|
616
|
+
pHeader = pChn->pHeader;
|
617
|
+
if ((instr) && (note))
|
618
|
+
{
|
619
|
+
pHeader = _this->Headers[instr];
|
620
|
+
if (pHeader)
|
621
|
+
{
|
622
|
+
UINT n = 0;
|
623
|
+
if (note <= 0x80)
|
624
|
+
{
|
625
|
+
n = pHeader->Keyboard[note-1];
|
626
|
+
note = pHeader->NoteMap[note-1];
|
627
|
+
if ((n) && (n < MAX_SAMPLES)) pSample = _this->Ins[n].pSample;
|
628
|
+
}
|
629
|
+
} else pSample = NULL;
|
630
|
+
}
|
631
|
+
if (!penv) return;
|
632
|
+
MODCHANNEL *p = pChn;
|
633
|
+
for (UINT i=nChn; i<MAX_CHANNELS; p++, i++)
|
634
|
+
if ((i >= _this->m_nChannels) || (p == pChn))
|
635
|
+
{
|
636
|
+
if (((p->nMasterChn == nChn+1) || (p == pChn)) && (p->pHeader))
|
637
|
+
{
|
638
|
+
BOOL bOk = FALSE;
|
639
|
+
// Duplicate Check Type
|
640
|
+
switch(p->pHeader->nDCT)
|
641
|
+
{
|
642
|
+
// Note
|
643
|
+
case DCT_NOTE:
|
644
|
+
if ((note) && (p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE;
|
645
|
+
break;
|
646
|
+
// Sample
|
647
|
+
case DCT_SAMPLE:
|
648
|
+
if ((pSample) && (pSample == p->pSample)) bOk = TRUE;
|
649
|
+
break;
|
650
|
+
// Instrument
|
651
|
+
case DCT_INSTRUMENT:
|
652
|
+
if (pHeader == p->pHeader) bOk = TRUE;
|
653
|
+
break;
|
654
|
+
}
|
655
|
+
// Duplicate Note Action
|
656
|
+
if (bOk)
|
657
|
+
{
|
658
|
+
switch(p->pHeader->nDNA)
|
659
|
+
{
|
660
|
+
// Cut
|
661
|
+
case DNA_NOTECUT:
|
662
|
+
CSoundFile_KeyOff(_this, i);
|
663
|
+
p->nVolume = 0;
|
664
|
+
break;
|
665
|
+
// Note Off
|
666
|
+
case DNA_NOTEOFF:
|
667
|
+
CSoundFile_KeyOff(_this, i);
|
668
|
+
break;
|
669
|
+
// Note Fade
|
670
|
+
case DNA_NOTEFADE:
|
671
|
+
p->dwFlags |= CHN_NOTEFADE;
|
672
|
+
break;
|
673
|
+
}
|
674
|
+
if (!p->nVolume)
|
675
|
+
{
|
676
|
+
p->nFadeOutVol = 0;
|
677
|
+
p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
|
678
|
+
}
|
679
|
+
}
|
680
|
+
}
|
681
|
+
}
|
682
|
+
if (pChn->dwFlags & CHN_MUTE) return;
|
683
|
+
// New Note Action
|
684
|
+
if ((pChn->nVolume) && (pChn->nLength))
|
685
|
+
{
|
686
|
+
UINT n = CSoundFile_GetNNAChannel(_this, nChn);
|
687
|
+
if (n)
|
688
|
+
{
|
689
|
+
MODCHANNEL *p = &_this->Chn[n];
|
690
|
+
// Copy Channel
|
691
|
+
SDL_memcpy(p, pChn, sizeof (*p));
|
692
|
+
p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO);
|
693
|
+
p->nMasterChn = nChn+1;
|
694
|
+
p->nCommand = 0;
|
695
|
+
// Key Off the note
|
696
|
+
switch(pChn->nNNA)
|
697
|
+
{
|
698
|
+
case NNA_NOTEOFF: CSoundFile_KeyOff(_this, n); break;
|
699
|
+
case NNA_NOTECUT:
|
700
|
+
p->nFadeOutVol = 0;
|
701
|
+
case NNA_NOTEFADE: p->dwFlags |= CHN_NOTEFADE; break;
|
702
|
+
}
|
703
|
+
if (!p->nVolume)
|
704
|
+
{
|
705
|
+
p->nFadeOutVol = 0;
|
706
|
+
p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
|
707
|
+
}
|
708
|
+
// Stop this channel
|
709
|
+
pChn->nLength = pChn->nPos = pChn->nPosLo = 0;
|
710
|
+
pChn->nROfs = pChn->nLOfs = 0;
|
711
|
+
}
|
712
|
+
}
|
713
|
+
}
|
714
|
+
|
715
|
+
|
716
|
+
BOOL CSoundFile_ProcessEffects(CSoundFile *_this)
|
717
|
+
//-------------------------------
|
718
|
+
{
|
719
|
+
MODCHANNEL *pChn = _this->Chn;
|
720
|
+
int nBreakRow = -1, nPosJump = -1, nPatLoopRow = -1;
|
721
|
+
|
722
|
+
for (UINT nChn=0; nChn<_this->m_nChannels; nChn++, pChn++)
|
723
|
+
{
|
724
|
+
UINT instr = pChn->nRowInstr;
|
725
|
+
UINT volcmd = pChn->nRowVolCmd;
|
726
|
+
UINT vol = pChn->nRowVolume;
|
727
|
+
UINT cmd = pChn->nRowCommand;
|
728
|
+
UINT param = pChn->nRowParam;
|
729
|
+
int bPorta = ((cmd != CMD_TONEPORTAMENTO) && (cmd != CMD_TONEPORTAVOL) && (volcmd != VOLCMD_TONEPORTAMENTO)) ? FALSE : TRUE;
|
730
|
+
UINT nStartTick = 0;
|
731
|
+
|
732
|
+
pChn->dwFlags &= ~CHN_FASTVOLRAMP;
|
733
|
+
// Process special effects (note delay, pattern delay, pattern loop)
|
734
|
+
if ((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX))
|
735
|
+
{
|
736
|
+
if ((!param) && (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) param = pChn->nOldCmdEx; else pChn->nOldCmdEx = param;
|
737
|
+
// Note Delay ?
|
738
|
+
if ((param & 0xF0) == 0xD0)
|
739
|
+
{
|
740
|
+
nStartTick = param & 0x0F;
|
741
|
+
} else
|
742
|
+
if (!_this->m_nTickCount)
|
743
|
+
{
|
744
|
+
// Pattern Loop ?
|
745
|
+
if ((((param & 0xF0) == 0x60) && (cmd == CMD_MODCMDEX))
|
746
|
+
|| (((param & 0xF0) == 0xB0) && (cmd == CMD_S3MCMDEX)))
|
747
|
+
{
|
748
|
+
int nloop = CSoundFile_PatternLoop(_this, pChn, param & 0x0F);
|
749
|
+
if (nloop >= 0) nPatLoopRow = nloop;
|
750
|
+
} else
|
751
|
+
// Pattern Delay
|
752
|
+
if ((param & 0xF0) == 0xE0)
|
753
|
+
{
|
754
|
+
_this->m_nPatternDelay = param & 0x0F;
|
755
|
+
}
|
756
|
+
}
|
757
|
+
}
|
758
|
+
|
759
|
+
// Handles note/instrument/volume changes
|
760
|
+
if (_this->m_nTickCount == nStartTick) // can be delayed by a note delay effect
|
761
|
+
{
|
762
|
+
UINT note = pChn->nRowNote;
|
763
|
+
if (instr) pChn->nNewIns = instr;
|
764
|
+
// XM: Key-Off + Sample == Note Cut
|
765
|
+
if (_this->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2))
|
766
|
+
{
|
767
|
+
if ((note == 0xFF) && ((!pChn->pHeader) || (!(pChn->pHeader->dwFlags & ENV_VOLUME))))
|
768
|
+
{
|
769
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
770
|
+
pChn->nVolume = 0;
|
771
|
+
note = instr = 0;
|
772
|
+
}
|
773
|
+
}
|
774
|
+
if ((!note) && (instr))
|
775
|
+
{
|
776
|
+
if (_this->m_nInstruments)
|
777
|
+
{
|
778
|
+
if (pChn->pInstrument) pChn->nVolume = pChn->pInstrument->nVolume;
|
779
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
780
|
+
{
|
781
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
782
|
+
pChn->nVolEnvPosition = 0;
|
783
|
+
pChn->nPanEnvPosition = 0;
|
784
|
+
pChn->nPitchEnvPosition = 0;
|
785
|
+
pChn->nAutoVibDepth = 0;
|
786
|
+
pChn->nAutoVibPos = 0;
|
787
|
+
pChn->dwFlags &= ~CHN_NOTEFADE;
|
788
|
+
pChn->nFadeOutVol = 65536;
|
789
|
+
}
|
790
|
+
} else
|
791
|
+
{
|
792
|
+
if (instr < MAX_SAMPLES) pChn->nVolume = _this->Ins[instr].nVolume;
|
793
|
+
}
|
794
|
+
if (!(_this->m_nType & MOD_TYPE_IT)) instr = 0;
|
795
|
+
}
|
796
|
+
// Invalid Instrument ?
|
797
|
+
if (instr >= MAX_INSTRUMENTS) instr = 0;
|
798
|
+
// Note Cut/Off => ignore instrument
|
799
|
+
if (note >= 0xFE) instr = 0;
|
800
|
+
if ((note) && (note <= 128)) pChn->nNewNote = note;
|
801
|
+
// New Note Action ?
|
802
|
+
if ((note) && (note <= 128) && (!bPorta))
|
803
|
+
{
|
804
|
+
CSoundFile_CheckNNA(_this, nChn, instr, note, FALSE);
|
805
|
+
}
|
806
|
+
// Instrument Change ?
|
807
|
+
if (instr)
|
808
|
+
{
|
809
|
+
MODINSTRUMENT *psmp = pChn->pInstrument;
|
810
|
+
CSoundFile_InstrumentChange(_this, pChn, instr, bPorta, TRUE, TRUE);
|
811
|
+
pChn->nNewIns = 0;
|
812
|
+
// Special IT case: portamento+note causes sample change -> ignore portamento
|
813
|
+
if ((_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
|
814
|
+
&& (psmp != pChn->pInstrument) && (note) && (note < 0x80))
|
815
|
+
{
|
816
|
+
bPorta = FALSE;
|
817
|
+
}
|
818
|
+
}
|
819
|
+
// New Note ?
|
820
|
+
if (note)
|
821
|
+
{
|
822
|
+
if ((!instr) && (pChn->nNewIns) && (note < 0x80))
|
823
|
+
{
|
824
|
+
CSoundFile_InstrumentChange(_this, pChn, pChn->nNewIns, bPorta, FALSE, (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE);
|
825
|
+
pChn->nNewIns = 0;
|
826
|
+
}
|
827
|
+
CSoundFile_NoteChange(_this, nChn, note, bPorta, (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE);
|
828
|
+
if ((bPorta) && (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (instr))
|
829
|
+
{
|
830
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
831
|
+
pChn->nVolEnvPosition = 0;
|
832
|
+
pChn->nPanEnvPosition = 0;
|
833
|
+
pChn->nPitchEnvPosition = 0;
|
834
|
+
pChn->nAutoVibDepth = 0;
|
835
|
+
pChn->nAutoVibPos = 0;
|
836
|
+
}
|
837
|
+
}
|
838
|
+
// Tick-0 only volume commands
|
839
|
+
if (volcmd == VOLCMD_VOLUME)
|
840
|
+
{
|
841
|
+
if (vol > 64) vol = 64;
|
842
|
+
pChn->nVolume = vol << 2;
|
843
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
844
|
+
} else
|
845
|
+
if (volcmd == VOLCMD_PANNING)
|
846
|
+
{
|
847
|
+
if (vol > 64) vol = 64;
|
848
|
+
pChn->nPan = vol << 2;
|
849
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
850
|
+
}
|
851
|
+
}
|
852
|
+
|
853
|
+
// Volume Column Effect (except volume & panning)
|
854
|
+
if ((volcmd > VOLCMD_PANNING) && (_this->m_nTickCount >= nStartTick))
|
855
|
+
{
|
856
|
+
if (volcmd == VOLCMD_TONEPORTAMENTO)
|
857
|
+
{
|
858
|
+
if (_this->m_nType & MOD_TYPE_IT)
|
859
|
+
CSoundFile_TonePortamento(_this, pChn, ImpulseTrackerPortaVolCmd[vol & 0x0F]);
|
860
|
+
else
|
861
|
+
CSoundFile_TonePortamento(_this, pChn, vol * 16);
|
862
|
+
} else
|
863
|
+
{
|
864
|
+
if (vol) pChn->nOldVolParam = vol; else vol = pChn->nOldVolParam;
|
865
|
+
switch(volcmd)
|
866
|
+
{
|
867
|
+
case VOLCMD_VOLSLIDEUP:
|
868
|
+
CSoundFile_VolumeSlide(_this, pChn, vol << 4);
|
869
|
+
break;
|
870
|
+
|
871
|
+
case VOLCMD_VOLSLIDEDOWN:
|
872
|
+
CSoundFile_VolumeSlide(_this, pChn, vol);
|
873
|
+
break;
|
874
|
+
|
875
|
+
case VOLCMD_FINEVOLUP:
|
876
|
+
if (_this->m_nType & MOD_TYPE_IT)
|
877
|
+
{
|
878
|
+
if (_this->m_nTickCount == nStartTick) CSoundFile_VolumeSlide(_this, pChn, (vol << 4) | 0x0F);
|
879
|
+
} else
|
880
|
+
CSoundFile_FineVolumeUp(_this, pChn, vol);
|
881
|
+
break;
|
882
|
+
|
883
|
+
case VOLCMD_FINEVOLDOWN:
|
884
|
+
if (_this->m_nType & MOD_TYPE_IT)
|
885
|
+
{
|
886
|
+
if (_this->m_nTickCount == nStartTick) CSoundFile_VolumeSlide(_this, pChn, 0xF0 | vol);
|
887
|
+
} else
|
888
|
+
CSoundFile_FineVolumeDown(_this, pChn, vol);
|
889
|
+
break;
|
890
|
+
|
891
|
+
case VOLCMD_VIBRATOSPEED:
|
892
|
+
CSoundFile_Vibrato(_this, pChn, vol << 4);
|
893
|
+
break;
|
894
|
+
|
895
|
+
case VOLCMD_VIBRATO:
|
896
|
+
CSoundFile_Vibrato(_this, pChn, vol);
|
897
|
+
break;
|
898
|
+
|
899
|
+
case VOLCMD_PANSLIDELEFT:
|
900
|
+
CSoundFile_PanningSlide(_this, pChn, vol);
|
901
|
+
break;
|
902
|
+
|
903
|
+
case VOLCMD_PANSLIDERIGHT:
|
904
|
+
CSoundFile_PanningSlide(_this, pChn, vol << 4);
|
905
|
+
break;
|
906
|
+
|
907
|
+
case VOLCMD_PORTAUP:
|
908
|
+
CSoundFile_PortamentoUp(_this, pChn, vol << 2);
|
909
|
+
break;
|
910
|
+
|
911
|
+
case VOLCMD_PORTADOWN:
|
912
|
+
CSoundFile_PortamentoDown(_this, pChn, vol << 2);
|
913
|
+
break;
|
914
|
+
}
|
915
|
+
}
|
916
|
+
}
|
917
|
+
|
918
|
+
// Effects
|
919
|
+
if (cmd) switch (cmd)
|
920
|
+
{
|
921
|
+
// Set Volume
|
922
|
+
case CMD_VOLUME:
|
923
|
+
if (!_this->m_nTickCount)
|
924
|
+
{
|
925
|
+
pChn->nVolume = (param < 64) ? param*4 : 256;
|
926
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
927
|
+
}
|
928
|
+
break;
|
929
|
+
|
930
|
+
// Portamento Up
|
931
|
+
case CMD_PORTAMENTOUP:
|
932
|
+
if ((!param) && (_this->m_nType & MOD_TYPE_MOD)) break;
|
933
|
+
CSoundFile_PortamentoUp(_this, pChn, param);
|
934
|
+
break;
|
935
|
+
|
936
|
+
// Portamento Down
|
937
|
+
case CMD_PORTAMENTODOWN:
|
938
|
+
if ((!param) && (_this->m_nType & MOD_TYPE_MOD)) break;
|
939
|
+
CSoundFile_PortamentoDown(_this, pChn, param);
|
940
|
+
break;
|
941
|
+
|
942
|
+
// Volume Slide
|
943
|
+
case CMD_VOLUMESLIDE:
|
944
|
+
if ((param) || (_this->m_nType != MOD_TYPE_MOD)) CSoundFile_VolumeSlide(_this, pChn, param);
|
945
|
+
break;
|
946
|
+
|
947
|
+
// Tone-Portamento
|
948
|
+
case CMD_TONEPORTAMENTO:
|
949
|
+
CSoundFile_TonePortamento(_this, pChn, param);
|
950
|
+
break;
|
951
|
+
|
952
|
+
// Tone-Portamento + Volume Slide
|
953
|
+
case CMD_TONEPORTAVOL:
|
954
|
+
if ((param) || (_this->m_nType != MOD_TYPE_MOD)) CSoundFile_VolumeSlide(_this, pChn, param);
|
955
|
+
CSoundFile_TonePortamento(_this, pChn, 0);
|
956
|
+
break;
|
957
|
+
|
958
|
+
// Vibrato
|
959
|
+
case CMD_VIBRATO:
|
960
|
+
CSoundFile_Vibrato(_this, pChn, param);
|
961
|
+
break;
|
962
|
+
|
963
|
+
// Vibrato + Volume Slide
|
964
|
+
case CMD_VIBRATOVOL:
|
965
|
+
if ((param) || (_this->m_nType != MOD_TYPE_MOD)) CSoundFile_VolumeSlide(_this, pChn, param);
|
966
|
+
CSoundFile_Vibrato(_this, pChn, 0);
|
967
|
+
break;
|
968
|
+
|
969
|
+
// Set Speed
|
970
|
+
case CMD_SPEED:
|
971
|
+
if (!_this->m_nTickCount) CSoundFile_SetSpeed(_this, param);
|
972
|
+
break;
|
973
|
+
|
974
|
+
// Set Tempo
|
975
|
+
case CMD_TEMPO:
|
976
|
+
if (!_this->m_nTickCount)
|
977
|
+
{
|
978
|
+
if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
|
979
|
+
{
|
980
|
+
if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo;
|
981
|
+
}
|
982
|
+
CSoundFile_SetTempo(_this, param);
|
983
|
+
}
|
984
|
+
break;
|
985
|
+
|
986
|
+
// Set Offset
|
987
|
+
case CMD_OFFSET:
|
988
|
+
if (_this->m_nTickCount) break;
|
989
|
+
if (param) pChn->nOldOffset = param; else param = pChn->nOldOffset;
|
990
|
+
param <<= 8;
|
991
|
+
param |= (UINT)(pChn->nOldHiOffset) << 16;
|
992
|
+
if ((pChn->nRowNote) && (pChn->nRowNote < 0x80))
|
993
|
+
{
|
994
|
+
if (bPorta)
|
995
|
+
pChn->nPos = param;
|
996
|
+
else
|
997
|
+
pChn->nPos += param;
|
998
|
+
if (pChn->nPos >= pChn->nLength)
|
999
|
+
{
|
1000
|
+
if (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))
|
1001
|
+
{
|
1002
|
+
pChn->nPos = pChn->nLoopStart;
|
1003
|
+
if ((_this->m_dwSongFlags & SONG_ITOLDEFFECTS) && (pChn->nLength > 4))
|
1004
|
+
{
|
1005
|
+
pChn->nPos = pChn->nLength - 2;
|
1006
|
+
}
|
1007
|
+
}
|
1008
|
+
}
|
1009
|
+
} else
|
1010
|
+
if ((param < pChn->nLength) && (_this->m_nType & (MOD_TYPE_MTM|MOD_TYPE_DMF)))
|
1011
|
+
{
|
1012
|
+
pChn->nPos = param;
|
1013
|
+
}
|
1014
|
+
break;
|
1015
|
+
|
1016
|
+
// Arpeggio
|
1017
|
+
case CMD_ARPEGGIO:
|
1018
|
+
if ((_this->m_nTickCount) || (!pChn->nPeriod) || (!pChn->nNote)) break;
|
1019
|
+
if ((!param) && (!(_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))) break;
|
1020
|
+
pChn->nCommand = CMD_ARPEGGIO;
|
1021
|
+
if (param) pChn->nArpeggio = param;
|
1022
|
+
break;
|
1023
|
+
|
1024
|
+
// Retrig
|
1025
|
+
case CMD_RETRIG:
|
1026
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
1027
|
+
{
|
1028
|
+
if (!(param & 0xF0)) param |= pChn->nRetrigParam & 0xF0;
|
1029
|
+
if (!(param & 0x0F)) param |= pChn->nRetrigParam & 0x0F;
|
1030
|
+
param |= 0x100; // increment retrig count on first row
|
1031
|
+
}
|
1032
|
+
if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam;
|
1033
|
+
CSoundFile_RetrigNote(_this, nChn, param);
|
1034
|
+
break;
|
1035
|
+
|
1036
|
+
// Tremor
|
1037
|
+
case CMD_TREMOR:
|
1038
|
+
if (_this->m_nTickCount) break;
|
1039
|
+
pChn->nCommand = CMD_TREMOR;
|
1040
|
+
if (param) pChn->nTremorParam = param;
|
1041
|
+
break;
|
1042
|
+
|
1043
|
+
// Set Global Volume
|
1044
|
+
case CMD_GLOBALVOLUME:
|
1045
|
+
if (_this->m_nTickCount) break;
|
1046
|
+
if (_this->m_nType != MOD_TYPE_IT) param <<= 1;
|
1047
|
+
if (param > 128) param = 128;
|
1048
|
+
_this->m_nGlobalVolume = param << 1;
|
1049
|
+
break;
|
1050
|
+
|
1051
|
+
// Global Volume Slide
|
1052
|
+
case CMD_GLOBALVOLSLIDE:
|
1053
|
+
CSoundFile_GlobalVolSlide(_this, param);
|
1054
|
+
break;
|
1055
|
+
|
1056
|
+
// Set 8-bit Panning
|
1057
|
+
case CMD_PANNING8:
|
1058
|
+
if (_this->m_nTickCount) break;
|
1059
|
+
if (!(_this->m_dwSongFlags & SONG_SURROUNDPAN)) pChn->dwFlags &= ~CHN_SURROUND;
|
1060
|
+
if (_this->m_nType & (MOD_TYPE_IT|MOD_TYPE_XM|MOD_TYPE_MT2))
|
1061
|
+
{
|
1062
|
+
pChn->nPan = param;
|
1063
|
+
} else
|
1064
|
+
if (param <= 0x80)
|
1065
|
+
{
|
1066
|
+
pChn->nPan = param << 1;
|
1067
|
+
} else
|
1068
|
+
if (param == 0xA4)
|
1069
|
+
{
|
1070
|
+
pChn->dwFlags |= CHN_SURROUND;
|
1071
|
+
pChn->nPan = 0x80;
|
1072
|
+
}
|
1073
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
1074
|
+
break;
|
1075
|
+
|
1076
|
+
// Panning Slide
|
1077
|
+
case CMD_PANNINGSLIDE:
|
1078
|
+
CSoundFile_PanningSlide(_this, pChn, param);
|
1079
|
+
break;
|
1080
|
+
|
1081
|
+
// Tremolo
|
1082
|
+
case CMD_TREMOLO:
|
1083
|
+
CSoundFile_Tremolo(_this, pChn, param);
|
1084
|
+
break;
|
1085
|
+
|
1086
|
+
// Fine Vibrato
|
1087
|
+
case CMD_FINEVIBRATO:
|
1088
|
+
CSoundFile_FineVibrato(_this, pChn, param);
|
1089
|
+
break;
|
1090
|
+
|
1091
|
+
// MOD/XM Exx Extended Commands
|
1092
|
+
case CMD_MODCMDEX:
|
1093
|
+
CSoundFile_ExtendedMODCommands(_this, nChn, param);
|
1094
|
+
break;
|
1095
|
+
|
1096
|
+
// S3M/IT Sxx Extended Commands
|
1097
|
+
case CMD_S3MCMDEX:
|
1098
|
+
CSoundFile_ExtendedS3MCommands(_this, nChn, param);
|
1099
|
+
break;
|
1100
|
+
|
1101
|
+
// Key Off
|
1102
|
+
case CMD_KEYOFF:
|
1103
|
+
if (!_this->m_nTickCount) CSoundFile_KeyOff(_this, nChn);
|
1104
|
+
break;
|
1105
|
+
|
1106
|
+
// Extra-fine porta up/down
|
1107
|
+
case CMD_XFINEPORTAUPDOWN:
|
1108
|
+
switch(param & 0xF0)
|
1109
|
+
{
|
1110
|
+
case 0x10: CSoundFile_ExtraFinePortamentoUp(_this, pChn, param & 0x0F); break;
|
1111
|
+
case 0x20: CSoundFile_ExtraFinePortamentoDown(_this, pChn, param & 0x0F); break;
|
1112
|
+
// Modplug XM Extensions
|
1113
|
+
case 0x50:
|
1114
|
+
case 0x60:
|
1115
|
+
case 0x70:
|
1116
|
+
case 0x90:
|
1117
|
+
case 0xA0: CSoundFile_ExtendedS3MCommands(_this, nChn, param); break;
|
1118
|
+
}
|
1119
|
+
break;
|
1120
|
+
|
1121
|
+
// Set Channel Global Volume
|
1122
|
+
case CMD_CHANNELVOLUME:
|
1123
|
+
if (_this->m_nTickCount) break;
|
1124
|
+
if (param <= 64)
|
1125
|
+
{
|
1126
|
+
pChn->nGlobalVol = param;
|
1127
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
1128
|
+
}
|
1129
|
+
break;
|
1130
|
+
|
1131
|
+
// Channel volume slide
|
1132
|
+
case CMD_CHANNELVOLSLIDE:
|
1133
|
+
CSoundFile_ChannelVolSlide(_this, pChn, param);
|
1134
|
+
break;
|
1135
|
+
|
1136
|
+
// Panbrello (IT)
|
1137
|
+
case CMD_PANBRELLO:
|
1138
|
+
CSoundFile_Panbrello(_this, pChn, param);
|
1139
|
+
break;
|
1140
|
+
|
1141
|
+
// Set Envelope Position
|
1142
|
+
case CMD_SETENVPOSITION:
|
1143
|
+
if (!_this->m_nTickCount)
|
1144
|
+
{
|
1145
|
+
pChn->nVolEnvPosition = param;
|
1146
|
+
pChn->nPanEnvPosition = param;
|
1147
|
+
pChn->nPitchEnvPosition = param;
|
1148
|
+
if (pChn->pHeader)
|
1149
|
+
{
|
1150
|
+
INSTRUMENTHEADER *penv = pChn->pHeader;
|
1151
|
+
if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1]))
|
1152
|
+
{
|
1153
|
+
pChn->dwFlags &= ~CHN_PANENV;
|
1154
|
+
}
|
1155
|
+
}
|
1156
|
+
}
|
1157
|
+
break;
|
1158
|
+
|
1159
|
+
// Position Jump
|
1160
|
+
case CMD_POSITIONJUMP:
|
1161
|
+
nPosJump = param;
|
1162
|
+
break;
|
1163
|
+
|
1164
|
+
// Pattern Break
|
1165
|
+
case CMD_PATTERNBREAK:
|
1166
|
+
nBreakRow = param;
|
1167
|
+
break;
|
1168
|
+
|
1169
|
+
// Midi Controller
|
1170
|
+
case CMD_MIDI:
|
1171
|
+
if (_this->m_nTickCount) break;
|
1172
|
+
if (param < 0x80){
|
1173
|
+
CSoundFile_ProcessMidiMacro(_this, nChn, &_this->m_MidiCfg.szMidiSFXExt[pChn->nActiveMacro << 5], param);
|
1174
|
+
} else {
|
1175
|
+
CSoundFile_ProcessMidiMacro(_this, nChn, &_this->m_MidiCfg.szMidiZXXExt[(param & 0x7F) << 5], 0);
|
1176
|
+
}
|
1177
|
+
break;
|
1178
|
+
}
|
1179
|
+
}
|
1180
|
+
|
1181
|
+
// Navigation Effects
|
1182
|
+
if (!_this->m_nTickCount)
|
1183
|
+
{
|
1184
|
+
// Pattern Loop
|
1185
|
+
if (nPatLoopRow >= 0)
|
1186
|
+
{
|
1187
|
+
_this->m_nNextPattern = _this->m_nCurrentPattern;
|
1188
|
+
_this->m_nNextRow = nPatLoopRow;
|
1189
|
+
if (_this->m_nPatternDelay) _this->m_nNextRow++;
|
1190
|
+
} else
|
1191
|
+
// Pattern Break / Position Jump only if no loop running
|
1192
|
+
if ((nBreakRow >= 0) || (nPosJump >= 0))
|
1193
|
+
{
|
1194
|
+
BOOL bNoLoop = FALSE;
|
1195
|
+
if (nPosJump < 0) nPosJump = _this->m_nCurrentPattern+1;
|
1196
|
+
if (nBreakRow < 0) nBreakRow = 0;
|
1197
|
+
// Modplug Tracker & ModPlugin allow backward jumps
|
1198
|
+
if ((nPosJump < (int)_this->m_nCurrentPattern)
|
1199
|
+
|| ((nPosJump == (int)_this->m_nCurrentPattern) && (nBreakRow <= (int)_this->m_nRow)))
|
1200
|
+
{
|
1201
|
+
if (!CSoundFile_IsValidBackwardJump(_this, _this->m_nCurrentPattern, _this->m_nRow, nPosJump, nBreakRow))
|
1202
|
+
{
|
1203
|
+
if (_this->m_nRepeatCount)
|
1204
|
+
{
|
1205
|
+
if (_this->m_nRepeatCount > 0) _this->m_nRepeatCount--;
|
1206
|
+
} else
|
1207
|
+
{
|
1208
|
+
#ifdef MODPLUG_TRACKER
|
1209
|
+
if (_this->gdwSoundSetup & SNDMIX_NOBACKWARDJUMPS)
|
1210
|
+
#endif
|
1211
|
+
// Backward jump disabled
|
1212
|
+
bNoLoop = TRUE;
|
1213
|
+
//reset repeat count incase there are multiple loops.
|
1214
|
+
//(i.e. Unreal tracks)
|
1215
|
+
_this->m_nRepeatCount = _this->m_nInitialRepeatCount;
|
1216
|
+
}
|
1217
|
+
}
|
1218
|
+
}
|
1219
|
+
if (((!bNoLoop) && (nPosJump < MAX_ORDERS))
|
1220
|
+
&& ((nPosJump != (int)_this->m_nCurrentPattern) || (nBreakRow != (int)_this->m_nRow)))
|
1221
|
+
{
|
1222
|
+
if (nPosJump != (int)_this->m_nCurrentPattern)
|
1223
|
+
{
|
1224
|
+
for (UINT i=0; i<_this->m_nChannels; i++) _this->Chn[i].nPatternLoopCount = 0;
|
1225
|
+
}
|
1226
|
+
_this->m_nNextPattern = nPosJump;
|
1227
|
+
_this->m_nNextRow = (UINT)nBreakRow;
|
1228
|
+
}
|
1229
|
+
}
|
1230
|
+
}
|
1231
|
+
return TRUE;
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
|
1235
|
+
////////////////////////////////////////////////////////////
|
1236
|
+
// Channels effects
|
1237
|
+
|
1238
|
+
void CSoundFile_PortamentoUp(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1239
|
+
//---------------------------------------------------------
|
1240
|
+
{
|
1241
|
+
if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown;
|
1242
|
+
if ((_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0))
|
1243
|
+
{
|
1244
|
+
if (param & 0x0F)
|
1245
|
+
{
|
1246
|
+
if ((param & 0xF0) == 0xF0)
|
1247
|
+
{
|
1248
|
+
CSoundFile_FinePortamentoUp(_this, pChn, param & 0x0F);
|
1249
|
+
} else
|
1250
|
+
if ((param & 0xF0) == 0xE0)
|
1251
|
+
{
|
1252
|
+
CSoundFile_ExtraFinePortamentoUp(_this, pChn, param & 0x0F);
|
1253
|
+
}
|
1254
|
+
}
|
1255
|
+
return;
|
1256
|
+
}
|
1257
|
+
// Regular Slide
|
1258
|
+
if (!(_this->m_dwSongFlags & SONG_FIRSTTICK) || (_this->m_nMusicSpeed == 1)) //rewbs.PortaA01fix
|
1259
|
+
{
|
1260
|
+
CSoundFile_DoFreqSlide(_this, pChn, -(int)(param * 4));
|
1261
|
+
}
|
1262
|
+
}
|
1263
|
+
|
1264
|
+
|
1265
|
+
void CSoundFile_PortamentoDown(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1266
|
+
//-----------------------------------------------------------
|
1267
|
+
{
|
1268
|
+
if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown;
|
1269
|
+
if ((_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0))
|
1270
|
+
{
|
1271
|
+
if (param & 0x0F)
|
1272
|
+
{
|
1273
|
+
if ((param & 0xF0) == 0xF0)
|
1274
|
+
{
|
1275
|
+
CSoundFile_FinePortamentoDown(_this, pChn, param & 0x0F);
|
1276
|
+
} else
|
1277
|
+
if ((param & 0xF0) == 0xE0)
|
1278
|
+
{
|
1279
|
+
CSoundFile_ExtraFinePortamentoDown(_this, pChn, param & 0x0F);
|
1280
|
+
}
|
1281
|
+
}
|
1282
|
+
return;
|
1283
|
+
}
|
1284
|
+
if (!(_this->m_dwSongFlags & SONG_FIRSTTICK) || (_this->m_nMusicSpeed == 1)) { //rewbs.PortaA01fix
|
1285
|
+
CSoundFile_DoFreqSlide(_this, pChn, (int)(param << 2));
|
1286
|
+
}
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
|
1290
|
+
void CSoundFile_FinePortamentoUp(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1291
|
+
//-------------------------------------------------------------
|
1292
|
+
{
|
1293
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
1294
|
+
{
|
1295
|
+
if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
|
1296
|
+
}
|
1297
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK)
|
1298
|
+
{
|
1299
|
+
if ((pChn->nPeriod) && (param))
|
1300
|
+
{
|
1301
|
+
if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
|
1302
|
+
{
|
1303
|
+
pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[param & 0x0F], 65536);
|
1304
|
+
} else
|
1305
|
+
{
|
1306
|
+
pChn->nPeriod -= (int)(param * 4);
|
1307
|
+
}
|
1308
|
+
if (pChn->nPeriod < 1) pChn->nPeriod = 1;
|
1309
|
+
}
|
1310
|
+
}
|
1311
|
+
}
|
1312
|
+
|
1313
|
+
|
1314
|
+
void CSoundFile_FinePortamentoDown(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1315
|
+
//---------------------------------------------------------------
|
1316
|
+
{
|
1317
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
1318
|
+
{
|
1319
|
+
if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
|
1320
|
+
}
|
1321
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK)
|
1322
|
+
{
|
1323
|
+
if ((pChn->nPeriod) && (param))
|
1324
|
+
{
|
1325
|
+
if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
|
1326
|
+
{
|
1327
|
+
pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[param & 0x0F], 65536);
|
1328
|
+
} else
|
1329
|
+
{
|
1330
|
+
pChn->nPeriod += (int)(param * 4);
|
1331
|
+
}
|
1332
|
+
if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF;
|
1333
|
+
}
|
1334
|
+
}
|
1335
|
+
}
|
1336
|
+
|
1337
|
+
|
1338
|
+
void CSoundFile_ExtraFinePortamentoUp(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1339
|
+
//------------------------------------------------------------------
|
1340
|
+
{
|
1341
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
1342
|
+
{
|
1343
|
+
if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
|
1344
|
+
}
|
1345
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK)
|
1346
|
+
{
|
1347
|
+
if ((pChn->nPeriod) && (param))
|
1348
|
+
{
|
1349
|
+
if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
|
1350
|
+
{
|
1351
|
+
pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideDownTable[param & 0x0F], 65536);
|
1352
|
+
} else
|
1353
|
+
{
|
1354
|
+
pChn->nPeriod -= (int)(param);
|
1355
|
+
}
|
1356
|
+
if (pChn->nPeriod < 1) pChn->nPeriod = 1;
|
1357
|
+
}
|
1358
|
+
}
|
1359
|
+
}
|
1360
|
+
|
1361
|
+
|
1362
|
+
void CSoundFile_ExtraFinePortamentoDown(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1363
|
+
//--------------------------------------------------------------------
|
1364
|
+
{
|
1365
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
1366
|
+
{
|
1367
|
+
if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
|
1368
|
+
}
|
1369
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK)
|
1370
|
+
{
|
1371
|
+
if ((pChn->nPeriod) && (param))
|
1372
|
+
{
|
1373
|
+
if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
|
1374
|
+
{
|
1375
|
+
pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideUpTable[param & 0x0F], 65536);
|
1376
|
+
} else
|
1377
|
+
{
|
1378
|
+
pChn->nPeriod += (int)(param);
|
1379
|
+
}
|
1380
|
+
if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF;
|
1381
|
+
}
|
1382
|
+
}
|
1383
|
+
}
|
1384
|
+
|
1385
|
+
|
1386
|
+
// Portamento Slide
|
1387
|
+
void CSoundFile_TonePortamento(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1388
|
+
//-----------------------------------------------------------
|
1389
|
+
{
|
1390
|
+
if (param) pChn->nPortamentoSlide = param * 4;
|
1391
|
+
pChn->dwFlags |= CHN_PORTAMENTO;
|
1392
|
+
if ((pChn->nPeriod) && (pChn->nPortamentoDest) && (!(_this->m_dwSongFlags & SONG_FIRSTTICK)))
|
1393
|
+
{
|
1394
|
+
if (pChn->nPeriod < pChn->nPortamentoDest)
|
1395
|
+
{
|
1396
|
+
LONG delta = (int)pChn->nPortamentoSlide;
|
1397
|
+
if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
|
1398
|
+
{
|
1399
|
+
UINT n = pChn->nPortamentoSlide >> 2;
|
1400
|
+
if (n > 255) n = 255;
|
1401
|
+
delta = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536) - pChn->nPeriod;
|
1402
|
+
if (delta < 1) delta = 1;
|
1403
|
+
}
|
1404
|
+
pChn->nPeriod += delta;
|
1405
|
+
if (pChn->nPeriod > pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest;
|
1406
|
+
} else
|
1407
|
+
if (pChn->nPeriod > pChn->nPortamentoDest)
|
1408
|
+
{
|
1409
|
+
LONG delta = - (int)pChn->nPortamentoSlide;
|
1410
|
+
if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
|
1411
|
+
{
|
1412
|
+
UINT n = pChn->nPortamentoSlide >> 2;
|
1413
|
+
if (n > 255) n = 255;
|
1414
|
+
delta = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536) - pChn->nPeriod;
|
1415
|
+
if (delta > -1) delta = -1;
|
1416
|
+
}
|
1417
|
+
pChn->nPeriod += delta;
|
1418
|
+
if (pChn->nPeriod < pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest;
|
1419
|
+
}
|
1420
|
+
}
|
1421
|
+
}
|
1422
|
+
|
1423
|
+
|
1424
|
+
void CSoundFile_Vibrato(CSoundFile *_this, MODCHANNEL *p, UINT param)
|
1425
|
+
//-------------------------------------------------
|
1426
|
+
{
|
1427
|
+
if (param & 0x0F) p->nVibratoDepth = (param & 0x0F) * 4;
|
1428
|
+
if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F;
|
1429
|
+
p->dwFlags |= CHN_VIBRATO;
|
1430
|
+
}
|
1431
|
+
|
1432
|
+
|
1433
|
+
void CSoundFile_FineVibrato(CSoundFile *_this, MODCHANNEL *p, UINT param)
|
1434
|
+
//-----------------------------------------------------
|
1435
|
+
{
|
1436
|
+
if (param & 0x0F) p->nVibratoDepth = param & 0x0F;
|
1437
|
+
if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F;
|
1438
|
+
p->dwFlags |= CHN_VIBRATO;
|
1439
|
+
}
|
1440
|
+
|
1441
|
+
|
1442
|
+
void CSoundFile_Panbrello(CSoundFile *_this, MODCHANNEL *p, UINT param)
|
1443
|
+
//---------------------------------------------------
|
1444
|
+
{
|
1445
|
+
if (param & 0x0F) p->nPanbrelloDepth = param & 0x0F;
|
1446
|
+
if (param & 0xF0) p->nPanbrelloSpeed = (param >> 4) & 0x0F;
|
1447
|
+
p->dwFlags |= CHN_PANBRELLO;
|
1448
|
+
}
|
1449
|
+
|
1450
|
+
|
1451
|
+
void CSoundFile_VolumeSlide(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1452
|
+
//--------------------------------------------------------
|
1453
|
+
{
|
1454
|
+
if (param) pChn->nOldVolumeSlide = param; else param = pChn->nOldVolumeSlide;
|
1455
|
+
LONG newvolume = pChn->nVolume;
|
1456
|
+
if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM|MOD_TYPE_AMF))
|
1457
|
+
{
|
1458
|
+
if ((param & 0x0F) == 0x0F)
|
1459
|
+
{
|
1460
|
+
if (param & 0xF0)
|
1461
|
+
{
|
1462
|
+
CSoundFile_FineVolumeUp(_this, pChn, (param >> 4));
|
1463
|
+
return;
|
1464
|
+
} else
|
1465
|
+
{
|
1466
|
+
if ((_this->m_dwSongFlags & SONG_FIRSTTICK) && (!(_this->m_dwSongFlags & SONG_FASTVOLSLIDES)))
|
1467
|
+
{
|
1468
|
+
newvolume -= 0x0F * 4;
|
1469
|
+
}
|
1470
|
+
}
|
1471
|
+
} else
|
1472
|
+
if ((param & 0xF0) == 0xF0)
|
1473
|
+
{
|
1474
|
+
if (param & 0x0F)
|
1475
|
+
{
|
1476
|
+
CSoundFile_FineVolumeDown(_this, pChn, (param & 0x0F));
|
1477
|
+
return;
|
1478
|
+
} else
|
1479
|
+
{
|
1480
|
+
if ((_this->m_dwSongFlags & SONG_FIRSTTICK) && (!(_this->m_dwSongFlags & SONG_FASTVOLSLIDES)))
|
1481
|
+
{
|
1482
|
+
newvolume += 0x0F * 4;
|
1483
|
+
}
|
1484
|
+
}
|
1485
|
+
}
|
1486
|
+
}
|
1487
|
+
if ((!(_this->m_dwSongFlags & SONG_FIRSTTICK)) || (_this->m_dwSongFlags & SONG_FASTVOLSLIDES))
|
1488
|
+
{
|
1489
|
+
if (param & 0x0F) newvolume -= (int)((param & 0x0F) * 4);
|
1490
|
+
else newvolume += (int)((param & 0xF0) >> 2);
|
1491
|
+
if (_this->m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
|
1492
|
+
}
|
1493
|
+
if (newvolume < 0) newvolume = 0;
|
1494
|
+
if (newvolume > 256) newvolume = 256;
|
1495
|
+
pChn->nVolume = newvolume;
|
1496
|
+
}
|
1497
|
+
|
1498
|
+
|
1499
|
+
void CSoundFile_PanningSlide(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1500
|
+
//---------------------------------------------------------
|
1501
|
+
{
|
1502
|
+
LONG nPanSlide = 0;
|
1503
|
+
if (param) pChn->nOldPanSlide = param; else param = pChn->nOldPanSlide;
|
1504
|
+
if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM))
|
1505
|
+
{
|
1506
|
+
if (((param & 0x0F) == 0x0F) && (param & 0xF0))
|
1507
|
+
{
|
1508
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK)
|
1509
|
+
{
|
1510
|
+
param = (param & 0xF0) >> 2;
|
1511
|
+
nPanSlide = - (int)param;
|
1512
|
+
}
|
1513
|
+
} else
|
1514
|
+
if (((param & 0xF0) == 0xF0) && (param & 0x0F))
|
1515
|
+
{
|
1516
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK)
|
1517
|
+
{
|
1518
|
+
nPanSlide = (param & 0x0F) << 2;
|
1519
|
+
}
|
1520
|
+
} else
|
1521
|
+
{
|
1522
|
+
if (!(_this->m_dwSongFlags & SONG_FIRSTTICK))
|
1523
|
+
{
|
1524
|
+
if (param & 0x0F) nPanSlide = (int)((param & 0x0F) << 2);
|
1525
|
+
else nPanSlide = -(int)((param & 0xF0) >> 2);
|
1526
|
+
}
|
1527
|
+
}
|
1528
|
+
} else
|
1529
|
+
{
|
1530
|
+
if (!(_this->m_dwSongFlags & SONG_FIRSTTICK))
|
1531
|
+
{
|
1532
|
+
if (param & 0x0F) nPanSlide = -(int)((param & 0x0F) << 2);
|
1533
|
+
else nPanSlide = (int)((param & 0xF0) >> 2);
|
1534
|
+
}
|
1535
|
+
}
|
1536
|
+
if (nPanSlide)
|
1537
|
+
{
|
1538
|
+
nPanSlide += pChn->nPan;
|
1539
|
+
if (nPanSlide < 0) nPanSlide = 0;
|
1540
|
+
if (nPanSlide > 256) nPanSlide = 256;
|
1541
|
+
pChn->nPan = nPanSlide;
|
1542
|
+
}
|
1543
|
+
}
|
1544
|
+
|
1545
|
+
|
1546
|
+
void CSoundFile_FineVolumeUp(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1547
|
+
//---------------------------------------------------------
|
1548
|
+
{
|
1549
|
+
if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown;
|
1550
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK)
|
1551
|
+
{
|
1552
|
+
pChn->nVolume += param * 4;
|
1553
|
+
if (pChn->nVolume > 256) pChn->nVolume = 256;
|
1554
|
+
if (_this->m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
|
1555
|
+
}
|
1556
|
+
}
|
1557
|
+
|
1558
|
+
|
1559
|
+
void CSoundFile_FineVolumeDown(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1560
|
+
//-----------------------------------------------------------
|
1561
|
+
{
|
1562
|
+
if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown;
|
1563
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK)
|
1564
|
+
{
|
1565
|
+
pChn->nVolume -= param * 4;
|
1566
|
+
if (pChn->nVolume < 0) pChn->nVolume = 0;
|
1567
|
+
if (_this->m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
|
1568
|
+
}
|
1569
|
+
}
|
1570
|
+
|
1571
|
+
|
1572
|
+
void CSoundFile_Tremolo(CSoundFile *_this, MODCHANNEL *p, UINT param)
|
1573
|
+
//-------------------------------------------------
|
1574
|
+
{
|
1575
|
+
if (param & 0x0F) p->nTremoloDepth = (param & 0x0F) << 2;
|
1576
|
+
if (param & 0xF0) p->nTremoloSpeed = (param >> 4) & 0x0F;
|
1577
|
+
p->dwFlags |= CHN_TREMOLO;
|
1578
|
+
}
|
1579
|
+
|
1580
|
+
|
1581
|
+
void CSoundFile_ChannelVolSlide(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1582
|
+
//------------------------------------------------------------
|
1583
|
+
{
|
1584
|
+
LONG nChnSlide = 0;
|
1585
|
+
if (param) pChn->nOldChnVolSlide = param; else param = pChn->nOldChnVolSlide;
|
1586
|
+
if (((param & 0x0F) == 0x0F) && (param & 0xF0))
|
1587
|
+
{
|
1588
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = param >> 4;
|
1589
|
+
} else
|
1590
|
+
if (((param & 0xF0) == 0xF0) && (param & 0x0F))
|
1591
|
+
{
|
1592
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = - (int)(param & 0x0F);
|
1593
|
+
} else
|
1594
|
+
{
|
1595
|
+
if (!(_this->m_dwSongFlags & SONG_FIRSTTICK))
|
1596
|
+
{
|
1597
|
+
if (param & 0x0F) nChnSlide = -(int)(param & 0x0F);
|
1598
|
+
else nChnSlide = (int)((param & 0xF0) >> 4);
|
1599
|
+
}
|
1600
|
+
}
|
1601
|
+
if (nChnSlide)
|
1602
|
+
{
|
1603
|
+
nChnSlide += pChn->nGlobalVol;
|
1604
|
+
if (nChnSlide < 0) nChnSlide = 0;
|
1605
|
+
if (nChnSlide > 64) nChnSlide = 64;
|
1606
|
+
pChn->nGlobalVol = nChnSlide;
|
1607
|
+
}
|
1608
|
+
}
|
1609
|
+
|
1610
|
+
|
1611
|
+
void CSoundFile_ExtendedMODCommands(CSoundFile *_this, UINT nChn, UINT param)
|
1612
|
+
//---------------------------------------------------------
|
1613
|
+
{
|
1614
|
+
MODCHANNEL *pChn = &_this->Chn[nChn];
|
1615
|
+
UINT command = param & 0xF0;
|
1616
|
+
param &= 0x0F;
|
1617
|
+
switch(command)
|
1618
|
+
{
|
1619
|
+
// E0x: Set Filter
|
1620
|
+
// E1x: Fine Portamento Up
|
1621
|
+
case 0x10: if ((param) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) CSoundFile_FinePortamentoUp(_this, pChn, param); break;
|
1622
|
+
// E2x: Fine Portamento Down
|
1623
|
+
case 0x20: if ((param) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) CSoundFile_FinePortamentoDown(_this, pChn, param); break;
|
1624
|
+
// E3x: Set Glissando Control
|
1625
|
+
case 0x30: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break;
|
1626
|
+
// E4x: Set Vibrato WaveForm
|
1627
|
+
case 0x40: pChn->nVibratoType = param & 0x07; break;
|
1628
|
+
// E5x: Set FineTune
|
1629
|
+
case 0x50: if (_this->m_nTickCount) break;
|
1630
|
+
pChn->nC4Speed = S3MFineTuneTable[param];
|
1631
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
1632
|
+
pChn->nFineTune = param*2;
|
1633
|
+
else
|
1634
|
+
pChn->nFineTune = MOD2XMFineTune(param);
|
1635
|
+
if (pChn->nPeriod) pChn->nPeriod = CSoundFile_GetPeriodFromNote(_this, pChn->nNote, pChn->nFineTune, pChn->nC4Speed);
|
1636
|
+
break;
|
1637
|
+
// E6x: Pattern Loop
|
1638
|
+
// E7x: Set Tremolo WaveForm
|
1639
|
+
case 0x70: pChn->nTremoloType = param & 0x07; break;
|
1640
|
+
// E8x: Set 4-bit Panning
|
1641
|
+
case 0x80: if (!_this->m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break;
|
1642
|
+
// E9x: Retrig
|
1643
|
+
case 0x90: CSoundFile_RetrigNote(_this, nChn, param); break;
|
1644
|
+
// EAx: Fine Volume Up
|
1645
|
+
case 0xA0: if ((param) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) CSoundFile_FineVolumeUp(_this, pChn, param); break;
|
1646
|
+
// EBx: Fine Volume Down
|
1647
|
+
case 0xB0: if ((param) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) CSoundFile_FineVolumeDown(_this, pChn, param); break;
|
1648
|
+
// ECx: Note Cut
|
1649
|
+
case 0xC0: CSoundFile_NoteCut(_this, nChn, param); break;
|
1650
|
+
// EDx: Note Delay
|
1651
|
+
// EEx: Pattern Delay
|
1652
|
+
// EFx: MOD: Invert Loop, XM: Set Active Midi Macro
|
1653
|
+
case 0xF0: pChn->nActiveMacro = param; break;
|
1654
|
+
}
|
1655
|
+
}
|
1656
|
+
|
1657
|
+
|
1658
|
+
void CSoundFile_ExtendedS3MCommands(CSoundFile *_this, UINT nChn, UINT param)
|
1659
|
+
//---------------------------------------------------------
|
1660
|
+
{
|
1661
|
+
MODCHANNEL *pChn = &_this->Chn[nChn];
|
1662
|
+
UINT command = param & 0xF0;
|
1663
|
+
param &= 0x0F;
|
1664
|
+
switch(command)
|
1665
|
+
{
|
1666
|
+
// S0x: Set Filter
|
1667
|
+
// S1x: Set Glissando Control
|
1668
|
+
case 0x10: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break;
|
1669
|
+
// S2x: Set FineTune
|
1670
|
+
case 0x20: if (_this->m_nTickCount) break;
|
1671
|
+
pChn->nC4Speed = S3MFineTuneTable[param & 0x0F];
|
1672
|
+
pChn->nFineTune = MOD2XMFineTune(param);
|
1673
|
+
if (pChn->nPeriod) pChn->nPeriod = CSoundFile_GetPeriodFromNote(_this, pChn->nNote, pChn->nFineTune, pChn->nC4Speed);
|
1674
|
+
break;
|
1675
|
+
// S3x: Set Vibrato WaveForm
|
1676
|
+
case 0x30: pChn->nVibratoType = param & 0x07; break;
|
1677
|
+
// S4x: Set Tremolo WaveForm
|
1678
|
+
case 0x40: pChn->nTremoloType = param & 0x07; break;
|
1679
|
+
// S5x: Set Panbrello WaveForm
|
1680
|
+
case 0x50: pChn->nPanbrelloType = param & 0x07; break;
|
1681
|
+
// S6x: Pattern Delay for x frames
|
1682
|
+
case 0x60: _this->m_nFrameDelay = param; break;
|
1683
|
+
// S7x: Envelope Control
|
1684
|
+
case 0x70: if (_this->m_nTickCount) break;
|
1685
|
+
switch(param)
|
1686
|
+
{
|
1687
|
+
case 0:
|
1688
|
+
case 1:
|
1689
|
+
case 2:
|
1690
|
+
{
|
1691
|
+
MODCHANNEL *bkp = &_this->Chn[_this->m_nChannels];
|
1692
|
+
for (UINT i=_this->m_nChannels; i<MAX_CHANNELS; i++, bkp++)
|
1693
|
+
{
|
1694
|
+
if (bkp->nMasterChn == nChn+1)
|
1695
|
+
{
|
1696
|
+
if (param == 1) CSoundFile_KeyOff(_this, i); else
|
1697
|
+
if (param == 2) bkp->dwFlags |= CHN_NOTEFADE; else
|
1698
|
+
{ bkp->dwFlags |= CHN_NOTEFADE; bkp->nFadeOutVol = 0; }
|
1699
|
+
}
|
1700
|
+
}
|
1701
|
+
}
|
1702
|
+
break;
|
1703
|
+
case 3: pChn->nNNA = NNA_NOTECUT; break;
|
1704
|
+
case 4: pChn->nNNA = NNA_CONTINUE; break;
|
1705
|
+
case 5: pChn->nNNA = NNA_NOTEOFF; break;
|
1706
|
+
case 6: pChn->nNNA = NNA_NOTEFADE; break;
|
1707
|
+
case 7: pChn->dwFlags &= ~CHN_VOLENV; break;
|
1708
|
+
case 8: pChn->dwFlags |= CHN_VOLENV; break;
|
1709
|
+
case 9: pChn->dwFlags &= ~CHN_PANENV; break;
|
1710
|
+
case 10: pChn->dwFlags |= CHN_PANENV; break;
|
1711
|
+
case 11: pChn->dwFlags &= ~CHN_PITCHENV; break;
|
1712
|
+
case 12: pChn->dwFlags |= CHN_PITCHENV; break;
|
1713
|
+
}
|
1714
|
+
break;
|
1715
|
+
// S8x: Set 4-bit Panning
|
1716
|
+
case 0x80: if (!_this->m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break;
|
1717
|
+
// S9x: Set Surround
|
1718
|
+
case 0x90: CSoundFile_ExtendedChannelEffect(_this, pChn, param & 0x0F); break;
|
1719
|
+
// SAx: Set 64k Offset
|
1720
|
+
case 0xA0: if (!_this->m_nTickCount)
|
1721
|
+
{
|
1722
|
+
pChn->nOldHiOffset = param;
|
1723
|
+
if ((pChn->nRowNote) && (pChn->nRowNote < 0x80))
|
1724
|
+
{
|
1725
|
+
DWORD pos = param << 16;
|
1726
|
+
if (pos < pChn->nLength) pChn->nPos = pos;
|
1727
|
+
}
|
1728
|
+
}
|
1729
|
+
break;
|
1730
|
+
// SBx: Pattern Loop
|
1731
|
+
// SCx: Note Cut
|
1732
|
+
case 0xC0: CSoundFile_NoteCut(_this, nChn, param); break;
|
1733
|
+
// SDx: Note Delay
|
1734
|
+
// case 0xD0: break;
|
1735
|
+
// SEx: Pattern Delay for x rows
|
1736
|
+
// SFx: S3M: Funk Repeat, IT: Set Active Midi Macro
|
1737
|
+
case 0xF0: pChn->nActiveMacro = param; break;
|
1738
|
+
}
|
1739
|
+
}
|
1740
|
+
|
1741
|
+
|
1742
|
+
void CSoundFile_ExtendedChannelEffect(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
1743
|
+
//------------------------------------------------------------------
|
1744
|
+
{
|
1745
|
+
// S9x and X9x commands (S3M/XM/IT only)
|
1746
|
+
if (_this->m_nTickCount) return;
|
1747
|
+
switch(param & 0x0F)
|
1748
|
+
{
|
1749
|
+
// S90: Surround Off
|
1750
|
+
case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break;
|
1751
|
+
// S91: Surround On
|
1752
|
+
case 0x01: pChn->dwFlags |= CHN_SURROUND; pChn->nPan = 128; break;
|
1753
|
+
////////////////////////////////////////////////////////////
|
1754
|
+
// Modplug Extensions
|
1755
|
+
// S98: Reverb Off
|
1756
|
+
case 0x08:
|
1757
|
+
pChn->dwFlags &= ~CHN_REVERB;
|
1758
|
+
pChn->dwFlags |= CHN_NOREVERB;
|
1759
|
+
break;
|
1760
|
+
// S99: Reverb On
|
1761
|
+
case 0x09:
|
1762
|
+
pChn->dwFlags &= ~CHN_NOREVERB;
|
1763
|
+
pChn->dwFlags |= CHN_REVERB;
|
1764
|
+
break;
|
1765
|
+
// S9A: 2-Channels surround mode
|
1766
|
+
case 0x0A:
|
1767
|
+
_this->m_dwSongFlags &= ~SONG_SURROUNDPAN;
|
1768
|
+
break;
|
1769
|
+
// S9B: 4-Channels surround mode
|
1770
|
+
case 0x0B:
|
1771
|
+
_this->m_dwSongFlags |= SONG_SURROUNDPAN;
|
1772
|
+
break;
|
1773
|
+
// S9C: IT Filter Mode
|
1774
|
+
case 0x0C:
|
1775
|
+
_this->m_dwSongFlags &= ~SONG_MPTFILTERMODE;
|
1776
|
+
break;
|
1777
|
+
// S9D: MPT Filter Mode
|
1778
|
+
case 0x0D:
|
1779
|
+
_this->m_dwSongFlags |= SONG_MPTFILTERMODE;
|
1780
|
+
break;
|
1781
|
+
// S9E: Go forward
|
1782
|
+
case 0x0E:
|
1783
|
+
pChn->dwFlags &= ~(CHN_PINGPONGFLAG);
|
1784
|
+
break;
|
1785
|
+
// S9F: Go backward (set position at the end for non-looping samples)
|
1786
|
+
case 0x0F:
|
1787
|
+
if ((!(pChn->dwFlags & CHN_LOOP)) && (!pChn->nPos) && (pChn->nLength))
|
1788
|
+
{
|
1789
|
+
pChn->nPos = pChn->nLength - 1;
|
1790
|
+
pChn->nPosLo = 0xFFFF;
|
1791
|
+
}
|
1792
|
+
pChn->dwFlags |= CHN_PINGPONGFLAG;
|
1793
|
+
break;
|
1794
|
+
}
|
1795
|
+
}
|
1796
|
+
|
1797
|
+
|
1798
|
+
void CSoundFile_ProcessMidiMacro(CSoundFile *_this, UINT nChn, LPCSTR pszMidiMacro, UINT param)
|
1799
|
+
//---------------------------------------------------------------------------
|
1800
|
+
{
|
1801
|
+
MODCHANNEL *pChn = &_this->Chn[nChn];
|
1802
|
+
DWORD dwMacro = (*((LPDWORD)pszMidiMacro)) & 0x7F5F7F5F;
|
1803
|
+
// Not Internal Device ?
|
1804
|
+
if (dwMacro != 0x30463046 && dwMacro != 0x31463046)
|
1805
|
+
{
|
1806
|
+
UINT pos = 0, nNib = 0, nBytes = 0;
|
1807
|
+
DWORD dwMidiCode = 0, dwByteCode = 0;
|
1808
|
+
while (pos+6 <= 32)
|
1809
|
+
{
|
1810
|
+
CHAR cData = pszMidiMacro[pos++];
|
1811
|
+
if (!cData) break;
|
1812
|
+
if ((cData >= '0') && (cData <= '9')) { dwByteCode = (dwByteCode<<4) | (cData-'0'); nNib++; } else
|
1813
|
+
if ((cData >= 'A') && (cData <= 'F')) { dwByteCode = (dwByteCode<<4) | (cData-'A'+10); nNib++; } else
|
1814
|
+
if ((cData >= 'a') && (cData <= 'f')) { dwByteCode = (dwByteCode<<4) | (cData-'a'+10); nNib++; } else
|
1815
|
+
if ((cData == 'z') || (cData == 'Z')) { dwByteCode = param & 0x7f; nNib = 2; } else
|
1816
|
+
if ((cData == 'x') || (cData == 'X')) { dwByteCode = param & 0x70; nNib = 2; } else
|
1817
|
+
if ((cData == 'y') || (cData == 'Y')) { dwByteCode = (param & 0x0f)<<3; nNib = 2; } else
|
1818
|
+
if (nNib >= 2)
|
1819
|
+
{
|
1820
|
+
nNib = 0;
|
1821
|
+
dwMidiCode |= dwByteCode << (nBytes*8);
|
1822
|
+
dwByteCode = 0;
|
1823
|
+
nBytes++;
|
1824
|
+
if (nBytes >= 3)
|
1825
|
+
{
|
1826
|
+
nBytes = 0;
|
1827
|
+
dwMidiCode = 0;
|
1828
|
+
}
|
1829
|
+
}
|
1830
|
+
|
1831
|
+
}
|
1832
|
+
return;
|
1833
|
+
}
|
1834
|
+
// Internal device
|
1835
|
+
pszMidiMacro += 4;
|
1836
|
+
// Filter ?
|
1837
|
+
if (pszMidiMacro[0] == '0')
|
1838
|
+
{
|
1839
|
+
CHAR cData1 = pszMidiMacro[2];
|
1840
|
+
DWORD dwParam = 0;
|
1841
|
+
if ((cData1 == 'z') || (cData1 == 'Z'))
|
1842
|
+
{
|
1843
|
+
dwParam = param;
|
1844
|
+
} else
|
1845
|
+
{
|
1846
|
+
CHAR cData2 = pszMidiMacro[3];
|
1847
|
+
if ((cData1 >= '0') && (cData1 <= '9')) dwParam += (cData1 - '0') << 4; else
|
1848
|
+
if ((cData1 >= 'A') && (cData1 <= 'F')) dwParam += (cData1 - 'A' + 0x0A) << 4;
|
1849
|
+
if ((cData2 >= '0') && (cData2 <= '9')) dwParam += (cData2 - '0'); else
|
1850
|
+
if ((cData2 >= 'A') && (cData2 <= 'F')) dwParam += (cData2 - 'A' + 0x0A);
|
1851
|
+
}
|
1852
|
+
switch(pszMidiMacro[1])
|
1853
|
+
{
|
1854
|
+
// F0.F0.00.xx: Set CutOff
|
1855
|
+
case '0':
|
1856
|
+
{
|
1857
|
+
int oldcutoff = pChn->nCutOff;
|
1858
|
+
if (dwParam < 0x80) pChn->nCutOff = (BYTE)dwParam;
|
1859
|
+
#ifndef NO_FILTER
|
1860
|
+
oldcutoff -= pChn->nCutOff;
|
1861
|
+
|
1862
|
+
if (oldcutoff < 0) oldcutoff = -oldcutoff;
|
1863
|
+
if ((pChn->nVolume > 0) || (oldcutoff < 0x10)
|
1864
|
+
|| (!(pChn->dwFlags & CHN_FILTER)) || (!(pChn->nLeftVol|pChn->nRightVol)))
|
1865
|
+
CSoundFile_SetupChannelFilter(_this, pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, 256);
|
1866
|
+
#endif // NO_FILTER
|
1867
|
+
}
|
1868
|
+
break;
|
1869
|
+
|
1870
|
+
// F0.F0.01.xx: Set Resonance
|
1871
|
+
case '1':
|
1872
|
+
if (dwParam < 0x80) pChn->nResonance = (BYTE)dwParam;
|
1873
|
+
#ifndef NO_FILTER
|
1874
|
+
CSoundFile_SetupChannelFilter(_this, pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, 256);
|
1875
|
+
#endif // NO_FILTER
|
1876
|
+
|
1877
|
+
break;
|
1878
|
+
}
|
1879
|
+
|
1880
|
+
}
|
1881
|
+
}
|
1882
|
+
|
1883
|
+
|
1884
|
+
void CSoundFile_RetrigNote(CSoundFile *_this, UINT nChn, UINT param)
|
1885
|
+
//------------------------------------------------
|
1886
|
+
{
|
1887
|
+
// Retrig: bit 8 is set if it's the new XM retrig
|
1888
|
+
MODCHANNEL *pChn = &_this->Chn[nChn];
|
1889
|
+
UINT nRetrigSpeed = param & 0x0F;
|
1890
|
+
UINT nRetrigCount = pChn->nRetrigCount;
|
1891
|
+
BOOL bDoRetrig = FALSE;
|
1892
|
+
|
1893
|
+
if (_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
|
1894
|
+
{
|
1895
|
+
if (!nRetrigSpeed) nRetrigSpeed = 1;
|
1896
|
+
if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE;
|
1897
|
+
nRetrigCount++;
|
1898
|
+
} else
|
1899
|
+
{
|
1900
|
+
UINT realspeed = nRetrigSpeed;
|
1901
|
+
if ((param & 0x100) && (pChn->nRowVolCmd == VOLCMD_VOLUME) && (pChn->nRowParam & 0xF0)) realspeed++;
|
1902
|
+
if ((_this->m_nTickCount) || (param & 0x100))
|
1903
|
+
{
|
1904
|
+
if (!realspeed) realspeed = 1;
|
1905
|
+
if ((!(param & 0x100)) && (_this->m_nMusicSpeed) && (!(_this->m_nTickCount % realspeed))) bDoRetrig = TRUE;
|
1906
|
+
nRetrigCount++;
|
1907
|
+
} else if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) nRetrigCount = 0;
|
1908
|
+
if (nRetrigCount >= realspeed)
|
1909
|
+
{
|
1910
|
+
if ((_this->m_nTickCount) || ((param & 0x100) && (!pChn->nRowNote))) bDoRetrig = TRUE;
|
1911
|
+
}
|
1912
|
+
}
|
1913
|
+
if (bDoRetrig)
|
1914
|
+
{
|
1915
|
+
UINT dv = (param >> 4) & 0x0F;
|
1916
|
+
if (dv)
|
1917
|
+
{
|
1918
|
+
int vol = pChn->nVolume;
|
1919
|
+
if (retrigTable1[dv])
|
1920
|
+
vol = (vol * retrigTable1[dv]) >> 4;
|
1921
|
+
else
|
1922
|
+
vol += ((int)retrigTable2[dv]) << 2;
|
1923
|
+
if (vol < 0) vol = 0;
|
1924
|
+
if (vol > 256) vol = 256;
|
1925
|
+
pChn->nVolume = vol;
|
1926
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
1927
|
+
}
|
1928
|
+
UINT nNote = pChn->nNewNote;
|
1929
|
+
LONG nOldPeriod = pChn->nPeriod;
|
1930
|
+
if ((nNote) && (nNote <= NOTE_MAX) && (pChn->nLength)) CSoundFile_CheckNNA(_this, nChn, 0, nNote, TRUE);
|
1931
|
+
BOOL bResetEnv = FALSE;
|
1932
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
1933
|
+
{
|
1934
|
+
if ((pChn->nRowInstr) && (param < 0x100)) { CSoundFile_InstrumentChange(_this, pChn, pChn->nRowInstr, FALSE, FALSE, TRUE); bResetEnv = TRUE; }
|
1935
|
+
if (param < 0x100) bResetEnv = TRUE;
|
1936
|
+
}
|
1937
|
+
CSoundFile_NoteChange(_this, nChn, nNote, FALSE, bResetEnv);
|
1938
|
+
if ((_this->m_nType & MOD_TYPE_IT) && (!pChn->nRowNote) && (nOldPeriod)) pChn->nPeriod = nOldPeriod;
|
1939
|
+
if (!(_this->m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) nRetrigCount = 0;
|
1940
|
+
}
|
1941
|
+
pChn->nRetrigCount = (BYTE)nRetrigCount;
|
1942
|
+
}
|
1943
|
+
|
1944
|
+
|
1945
|
+
void CSoundFile_DoFreqSlide(CSoundFile *_this, MODCHANNEL *pChn, LONG nFreqSlide)
|
1946
|
+
//-------------------------------------------------------------
|
1947
|
+
{
|
1948
|
+
// IT Linear slides
|
1949
|
+
if (!pChn->nPeriod) return;
|
1950
|
+
if ((_this->m_dwSongFlags & SONG_LINEARSLIDES) && (!(_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
|
1951
|
+
{
|
1952
|
+
if (nFreqSlide < 0)
|
1953
|
+
{
|
1954
|
+
UINT n = (- nFreqSlide) >> 2;
|
1955
|
+
if (n > 255) n = 255;
|
1956
|
+
pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536);
|
1957
|
+
} else
|
1958
|
+
{
|
1959
|
+
UINT n = (nFreqSlide) >> 2;
|
1960
|
+
|
1961
|
+
if (n > 255) n = 255;
|
1962
|
+
pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536);
|
1963
|
+
}
|
1964
|
+
} else
|
1965
|
+
{
|
1966
|
+
pChn->nPeriod += nFreqSlide;
|
1967
|
+
}
|
1968
|
+
if (pChn->nPeriod < 1)
|
1969
|
+
{
|
1970
|
+
pChn->nPeriod = 1;
|
1971
|
+
if (_this->m_nType & MOD_TYPE_IT)
|
1972
|
+
{
|
1973
|
+
pChn->dwFlags |= CHN_NOTEFADE;
|
1974
|
+
pChn->nFadeOutVol = 0;
|
1975
|
+
}
|
1976
|
+
}
|
1977
|
+
}
|
1978
|
+
|
1979
|
+
|
1980
|
+
void CSoundFile_NoteCut(CSoundFile *_this, UINT nChn, UINT nTick)
|
1981
|
+
//---------------------------------------------
|
1982
|
+
{
|
1983
|
+
if (_this->m_nTickCount == nTick)
|
1984
|
+
{
|
1985
|
+
MODCHANNEL *pChn = &_this->Chn[nChn];
|
1986
|
+
// if (_this->m_nInstruments) CSoundFile_KeyOff(_this, pChn); ?
|
1987
|
+
pChn->nVolume = 0;
|
1988
|
+
pChn->dwFlags |= CHN_FASTVOLRAMP;
|
1989
|
+
}
|
1990
|
+
}
|
1991
|
+
|
1992
|
+
|
1993
|
+
void CSoundFile_KeyOff(CSoundFile *_this, UINT nChn)
|
1994
|
+
//--------------------------------
|
1995
|
+
{
|
1996
|
+
MODCHANNEL *pChn = &_this->Chn[nChn];
|
1997
|
+
BOOL bKeyOn = (pChn->dwFlags & CHN_KEYOFF) ? FALSE : TRUE;
|
1998
|
+
pChn->dwFlags |= CHN_KEYOFF;
|
1999
|
+
//if ((!pChn->pHeader) || (!(pChn->dwFlags & CHN_VOLENV)))
|
2000
|
+
if ((pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV)))
|
2001
|
+
{
|
2002
|
+
pChn->dwFlags |= CHN_NOTEFADE;
|
2003
|
+
}
|
2004
|
+
if (!pChn->nLength) return;
|
2005
|
+
if ((pChn->dwFlags & CHN_SUSTAINLOOP) && (pChn->pInstrument) && (bKeyOn))
|
2006
|
+
{
|
2007
|
+
MODINSTRUMENT *psmp = pChn->pInstrument;
|
2008
|
+
if (psmp->uFlags & CHN_LOOP)
|
2009
|
+
{
|
2010
|
+
if (psmp->uFlags & CHN_PINGPONGLOOP)
|
2011
|
+
pChn->dwFlags |= CHN_PINGPONGLOOP;
|
2012
|
+
else
|
2013
|
+
pChn->dwFlags &= ~(CHN_PINGPONGLOOP|CHN_PINGPONGFLAG);
|
2014
|
+
pChn->dwFlags |= CHN_LOOP;
|
2015
|
+
pChn->nLength = psmp->nLength;
|
2016
|
+
pChn->nLoopStart = psmp->nLoopStart;
|
2017
|
+
pChn->nLoopEnd = psmp->nLoopEnd;
|
2018
|
+
if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
|
2019
|
+
} else
|
2020
|
+
{
|
2021
|
+
pChn->dwFlags &= ~(CHN_LOOP|CHN_PINGPONGLOOP|CHN_PINGPONGFLAG);
|
2022
|
+
pChn->nLength = psmp->nLength;
|
2023
|
+
}
|
2024
|
+
}
|
2025
|
+
if (pChn->pHeader)
|
2026
|
+
{
|
2027
|
+
INSTRUMENTHEADER *penv = pChn->pHeader;
|
2028
|
+
if (((penv->dwFlags & ENV_VOLLOOP) || (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (penv->nFadeOut))
|
2029
|
+
pChn->dwFlags |= CHN_NOTEFADE;
|
2030
|
+
}
|
2031
|
+
}
|
2032
|
+
|
2033
|
+
|
2034
|
+
//////////////////////////////////////////////////////////
|
2035
|
+
// CSoundFile: Global Effects
|
2036
|
+
|
2037
|
+
|
2038
|
+
void CSoundFile_SetSpeed(CSoundFile *_this, UINT param)
|
2039
|
+
//-----------------------------------
|
2040
|
+
{
|
2041
|
+
UINT max = (_this->m_nType == MOD_TYPE_IT) ? 256 : 128;
|
2042
|
+
// Modplug Tracker and Mod-Plugin don't do this check
|
2043
|
+
#ifndef MODPLUG_TRACKER
|
2044
|
+
// Big Hack!!!
|
2045
|
+
if ((!param) || (param >= 0x80) || ((_this->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) && (param >= 0x1E)))
|
2046
|
+
{
|
2047
|
+
if (CSoundFile_IsSongFinished(_this, _this->m_nCurrentPattern, _this->m_nRow+1))
|
2048
|
+
{
|
2049
|
+
CSoundFile_GlobalFadeSong(_this, 1000);
|
2050
|
+
}
|
2051
|
+
}
|
2052
|
+
#endif // MODPLUG_TRACKER
|
2053
|
+
if ((_this->m_nType & MOD_TYPE_S3M) && (param > 0x80)) param -= 0x80;
|
2054
|
+
if ((param) && (param <= max)) _this->m_nMusicSpeed = param;
|
2055
|
+
}
|
2056
|
+
|
2057
|
+
|
2058
|
+
void CSoundFile_SetTempo(CSoundFile *_this, UINT param)
|
2059
|
+
//-----------------------------------
|
2060
|
+
{
|
2061
|
+
if (param < 0x20)
|
2062
|
+
{
|
2063
|
+
// Tempo Slide
|
2064
|
+
if ((param & 0xF0) == 0x10)
|
2065
|
+
{
|
2066
|
+
_this->m_nMusicTempo += (param & 0x0F) * 2;
|
2067
|
+
if (_this->m_nMusicTempo > 255) _this->m_nMusicTempo = 255;
|
2068
|
+
} else
|
2069
|
+
{
|
2070
|
+
_this->m_nMusicTempo -= (param & 0x0F) * 2;
|
2071
|
+
if ((LONG)_this->m_nMusicTempo < 32) _this->m_nMusicTempo = 32;
|
2072
|
+
}
|
2073
|
+
} else
|
2074
|
+
{
|
2075
|
+
_this->m_nMusicTempo = param;
|
2076
|
+
}
|
2077
|
+
}
|
2078
|
+
|
2079
|
+
|
2080
|
+
int CSoundFile_PatternLoop(CSoundFile *_this, MODCHANNEL *pChn, UINT param)
|
2081
|
+
//-------------------------------------------------------
|
2082
|
+
{
|
2083
|
+
if (param)
|
2084
|
+
{
|
2085
|
+
if (pChn->nPatternLoopCount)
|
2086
|
+
{
|
2087
|
+
pChn->nPatternLoopCount--;
|
2088
|
+
if (!pChn->nPatternLoopCount) return -1;
|
2089
|
+
} else
|
2090
|
+
{
|
2091
|
+
MODCHANNEL *p = _this->Chn;
|
2092
|
+
for (UINT i=0; i<_this->m_nChannels; i++, p++) if (p != pChn)
|
2093
|
+
{
|
2094
|
+
// Loop already done
|
2095
|
+
if (p->nPatternLoopCount) return -1;
|
2096
|
+
}
|
2097
|
+
pChn->nPatternLoopCount = param;
|
2098
|
+
}
|
2099
|
+
return pChn->nPatternLoop;
|
2100
|
+
} else
|
2101
|
+
{
|
2102
|
+
pChn->nPatternLoop = _this->m_nRow;
|
2103
|
+
}
|
2104
|
+
return -1;
|
2105
|
+
}
|
2106
|
+
|
2107
|
+
|
2108
|
+
void CSoundFile_GlobalVolSlide(CSoundFile *_this, UINT param)
|
2109
|
+
//-----------------------------------------
|
2110
|
+
{
|
2111
|
+
LONG nGlbSlide = 0;
|
2112
|
+
if (param) _this->m_nOldGlbVolSlide = param; else param = _this->m_nOldGlbVolSlide;
|
2113
|
+
if (((param & 0x0F) == 0x0F) && (param & 0xF0))
|
2114
|
+
{
|
2115
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = (param >> 4) * 2;
|
2116
|
+
} else
|
2117
|
+
if (((param & 0xF0) == 0xF0) && (param & 0x0F))
|
2118
|
+
{
|
2119
|
+
if (_this->m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = - (int)((param & 0x0F) * 2);
|
2120
|
+
} else
|
2121
|
+
{
|
2122
|
+
if (!(_this->m_dwSongFlags & SONG_FIRSTTICK))
|
2123
|
+
{
|
2124
|
+
if (param & 0xF0) nGlbSlide = (int)((param & 0xF0) >> 4) * 2;
|
2125
|
+
else nGlbSlide = -(int)((param & 0x0F) * 2);
|
2126
|
+
}
|
2127
|
+
}
|
2128
|
+
if (nGlbSlide)
|
2129
|
+
{
|
2130
|
+
if (_this->m_nType != MOD_TYPE_IT) nGlbSlide *= 2;
|
2131
|
+
nGlbSlide += _this->m_nGlobalVolume;
|
2132
|
+
if (nGlbSlide < 0) nGlbSlide = 0;
|
2133
|
+
if (nGlbSlide > 256) nGlbSlide = 256;
|
2134
|
+
_this->m_nGlobalVolume = nGlbSlide;
|
2135
|
+
}
|
2136
|
+
}
|
2137
|
+
|
2138
|
+
|
2139
|
+
DWORD CSoundFile_IsSongFinished(CSoundFile *_this, UINT nStartOrder, UINT nStartRow)
|
2140
|
+
//----------------------------------------------------------------------
|
2141
|
+
{
|
2142
|
+
UINT nOrd;
|
2143
|
+
|
2144
|
+
for (nOrd=nStartOrder; nOrd<MAX_ORDERS; nOrd++)
|
2145
|
+
{
|
2146
|
+
UINT nPat = _this->Order[nOrd];
|
2147
|
+
if (nPat != 0xFE)
|
2148
|
+
{
|
2149
|
+
MODCOMMAND *p;
|
2150
|
+
|
2151
|
+
if (nPat >= MAX_PATTERNS) break;
|
2152
|
+
p = _this->Patterns[nPat];
|
2153
|
+
if (p)
|
2154
|
+
{
|
2155
|
+
UINT len = _this->PatternSize[nPat] * _this->m_nChannels;
|
2156
|
+
UINT pos = (nOrd == nStartOrder) ? nStartRow : 0;
|
2157
|
+
pos *= _this->m_nChannels;
|
2158
|
+
while (pos < len)
|
2159
|
+
{
|
2160
|
+
UINT cmd;
|
2161
|
+
if ((p[pos].note) || (p[pos].volcmd)) return 0;
|
2162
|
+
cmd = p[pos].command;
|
2163
|
+
if (cmd == CMD_MODCMDEX)
|
2164
|
+
{
|
2165
|
+
UINT cmdex = p[pos].param & 0xF0;
|
2166
|
+
if ((!cmdex) || (cmdex == 0x60) || (cmdex == 0xE0) || (cmdex == 0xF0)) cmd = 0;
|
2167
|
+
}
|
2168
|
+
if ((cmd) && (cmd != CMD_SPEED) && (cmd != CMD_TEMPO)) return 0;
|
2169
|
+
pos++;
|
2170
|
+
}
|
2171
|
+
}
|
2172
|
+
}
|
2173
|
+
}
|
2174
|
+
return (nOrd < MAX_ORDERS) ? nOrd : MAX_ORDERS-1;
|
2175
|
+
}
|
2176
|
+
|
2177
|
+
|
2178
|
+
BOOL CSoundFile_IsValidBackwardJump(CSoundFile *_this, UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow)
|
2179
|
+
//----------------------------------------------------------------------------------------------------------
|
2180
|
+
{
|
2181
|
+
while ((nJumpOrder < MAX_PATTERNS) && (_this->Order[nJumpOrder] == 0xFE)) nJumpOrder++;
|
2182
|
+
if ((nStartOrder >= MAX_PATTERNS) || (nJumpOrder >= MAX_PATTERNS)) return FALSE;
|
2183
|
+
// Treat only case with jumps in the same pattern
|
2184
|
+
if (nJumpOrder > nStartOrder) return TRUE;
|
2185
|
+
if ((nJumpOrder < nStartOrder) || (nJumpRow >= _this->PatternSize[nStartOrder])
|
2186
|
+
|| (!_this->Patterns[nStartOrder]) || (nStartRow >= 256) || (nJumpRow >= 256)) return FALSE;
|
2187
|
+
// See if the pattern is being played backward
|
2188
|
+
BYTE row_hist[256];
|
2189
|
+
SDL_memset(row_hist, 0, sizeof(row_hist));
|
2190
|
+
UINT nRows = _this->PatternSize[nStartOrder], row = nJumpRow;
|
2191
|
+
if (nRows > 256) nRows = 256;
|
2192
|
+
row_hist[nStartRow] = TRUE;
|
2193
|
+
while ((row < 256) && (!row_hist[row]))
|
2194
|
+
{
|
2195
|
+
if (row >= nRows) return TRUE;
|
2196
|
+
row_hist[row] = TRUE;
|
2197
|
+
MODCOMMAND *p = _this->Patterns[nStartOrder] + row * _this->m_nChannels;
|
2198
|
+
row++;
|
2199
|
+
int breakrow = -1, posjump = 0;
|
2200
|
+
for (UINT i=0; i<_this->m_nChannels; i++, p++)
|
2201
|
+
{
|
2202
|
+
if (p->command == CMD_POSITIONJUMP)
|
2203
|
+
{
|
2204
|
+
if (p->param < nStartOrder) return FALSE;
|
2205
|
+
if (p->param > nStartOrder) return TRUE;
|
2206
|
+
posjump = TRUE;
|
2207
|
+
} else
|
2208
|
+
if (p->command == CMD_PATTERNBREAK)
|
2209
|
+
{
|
2210
|
+
breakrow = p->param;
|
2211
|
+
}
|
2212
|
+
}
|
2213
|
+
if (breakrow >= 0)
|
2214
|
+
{
|
2215
|
+
if (!posjump) return TRUE;
|
2216
|
+
row = breakrow;
|
2217
|
+
}
|
2218
|
+
if (row >= nRows) return TRUE;
|
2219
|
+
}
|
2220
|
+
return FALSE;
|
2221
|
+
}
|
2222
|
+
|
2223
|
+
|
2224
|
+
//////////////////////////////////////////////////////
|
2225
|
+
// Note/Period/Frequency functions
|
2226
|
+
|
2227
|
+
UINT CSoundFile_GetNoteFromPeriod(CSoundFile *_this, UINT period)
|
2228
|
+
//---------------------------------------------------
|
2229
|
+
{
|
2230
|
+
if (!period) return 0;
|
2231
|
+
if (_this->m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0))
|
2232
|
+
{
|
2233
|
+
period >>= 2;
|
2234
|
+
for (UINT i=0; i<6*12; i++)
|
2235
|
+
{
|
2236
|
+
if (period >= ProTrackerPeriodTable[i])
|
2237
|
+
{
|
2238
|
+
if ((period != ProTrackerPeriodTable[i]) && (i))
|
2239
|
+
{
|
2240
|
+
UINT p1 = ProTrackerPeriodTable[i-1];
|
2241
|
+
UINT p2 = ProTrackerPeriodTable[i];
|
2242
|
+
if (p1 - period < (period - p2)) return i+36;
|
2243
|
+
}
|
2244
|
+
return i+1+36;
|
2245
|
+
}
|
2246
|
+
}
|
2247
|
+
return 6*12+36;
|
2248
|
+
} else
|
2249
|
+
{
|
2250
|
+
for (UINT i=1; i<NOTE_MAX; i++)
|
2251
|
+
{
|
2252
|
+
LONG n = CSoundFile_GetPeriodFromNote(_this, i, 0, 0);
|
2253
|
+
if ((n > 0) && (n <= (LONG)period)) return i;
|
2254
|
+
}
|
2255
|
+
return NOTE_MAX;
|
2256
|
+
}
|
2257
|
+
}
|
2258
|
+
|
2259
|
+
|
2260
|
+
|
2261
|
+
UINT CSoundFile_GetPeriodFromNote(CSoundFile *_this, UINT note, int nFineTune, UINT nC4Speed)
|
2262
|
+
//-------------------------------------------------------------------------------
|
2263
|
+
{
|
2264
|
+
if ((!note) || (note > 0xF0)) return 0;
|
2265
|
+
if (_this->m_nType & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV
|
2266
|
+
|MOD_TYPE_FAR|MOD_TYPE_DMF|MOD_TYPE_PTM|MOD_TYPE_AMS|MOD_TYPE_DBM|MOD_TYPE_AMF|MOD_TYPE_PSM))
|
2267
|
+
{
|
2268
|
+
note--;
|
2269
|
+
if (_this->m_dwSongFlags & SONG_LINEARSLIDES)
|
2270
|
+
{
|
2271
|
+
return (FreqS3MTable[note % 12] << 5) >> (note / 12);
|
2272
|
+
} else
|
2273
|
+
{
|
2274
|
+
if (!nC4Speed) nC4Speed = 8363;
|
2275
|
+
return _muldiv(8363, (FreqS3MTable[note % 12] << 5), nC4Speed << (note / 12));
|
2276
|
+
}
|
2277
|
+
} else
|
2278
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
2279
|
+
{
|
2280
|
+
if (note < 13) note = 13;
|
2281
|
+
note -= 13;
|
2282
|
+
if (_this->m_dwSongFlags & SONG_LINEARSLIDES)
|
2283
|
+
{
|
2284
|
+
LONG l = ((NOTE_MAX - note) << 6) - (nFineTune / 2);
|
2285
|
+
if (l < 1) l = 1;
|
2286
|
+
return (UINT)l;
|
2287
|
+
} else
|
2288
|
+
{
|
2289
|
+
int finetune = nFineTune;
|
2290
|
+
UINT rnote = (note % 12) << 3;
|
2291
|
+
UINT roct = note / 12;
|
2292
|
+
int rfine = finetune / 16;
|
2293
|
+
int i = rnote + rfine + 8;
|
2294
|
+
if (i < 0) i = 0;
|
2295
|
+
if (i >= 104) i = 103;
|
2296
|
+
UINT per1 = XMPeriodTable[i];
|
2297
|
+
if ( finetune < 0 )
|
2298
|
+
{
|
2299
|
+
rfine--;
|
2300
|
+
finetune = -finetune;
|
2301
|
+
} else rfine++;
|
2302
|
+
i = rnote+rfine+8;
|
2303
|
+
if (i < 0) i = 0;
|
2304
|
+
if (i >= 104) i = 103;
|
2305
|
+
UINT per2 = XMPeriodTable[i];
|
2306
|
+
rfine = finetune & 0x0F;
|
2307
|
+
per1 *= 16-rfine;
|
2308
|
+
per2 *= rfine;
|
2309
|
+
return ((per1 + per2) << 1) >> roct;
|
2310
|
+
}
|
2311
|
+
} else
|
2312
|
+
{
|
2313
|
+
note--;
|
2314
|
+
nFineTune = XM2MODFineTune(nFineTune);
|
2315
|
+
if ((nFineTune) || (note < 36) || (note >= 36+6*12))
|
2316
|
+
return (ProTrackerTunedPeriods[nFineTune*12 + note % 12] << 5) >> (note / 12);
|
2317
|
+
else
|
2318
|
+
return (ProTrackerPeriodTable[note-36] << 2);
|
2319
|
+
}
|
2320
|
+
}
|
2321
|
+
|
2322
|
+
|
2323
|
+
UINT CSoundFile_GetFreqFromPeriod(CSoundFile *_this, UINT period, UINT nC4Speed, int nPeriodFrac)
|
2324
|
+
//-----------------------------------------------------------------------------------
|
2325
|
+
{
|
2326
|
+
if (!period) return 0;
|
2327
|
+
if (_this->m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0))
|
2328
|
+
{
|
2329
|
+
return (3546895L*4) / period;
|
2330
|
+
} else
|
2331
|
+
if (_this->m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
|
2332
|
+
{
|
2333
|
+
if (_this->m_dwSongFlags & SONG_LINEARSLIDES)
|
2334
|
+
return XMLinearTable[period % 768] >> (period / 768);
|
2335
|
+
else
|
2336
|
+
return 8363 * 1712L / period;
|
2337
|
+
} else
|
2338
|
+
{
|
2339
|
+
if (_this->m_dwSongFlags & SONG_LINEARSLIDES)
|
2340
|
+
{
|
2341
|
+
if (!nC4Speed) nC4Speed = 8363;
|
2342
|
+
return _muldiv(nC4Speed, 1712L << 8, (period << 8)+nPeriodFrac);
|
2343
|
+
} else
|
2344
|
+
{
|
2345
|
+
return _muldiv(8363, 1712L << 8, (period << 8)+nPeriodFrac);
|
2346
|
+
}
|
2347
|
+
}
|
2348
|
+
}
|
2349
|
+
|
2350
|
+
|