gosu 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/dependencies/SDL/include/SDL.h +108 -14
  3. data/dependencies/SDL/include/SDL_assert.h +81 -50
  4. data/dependencies/SDL/include/SDL_atomic.h +135 -35
  5. data/dependencies/SDL/include/SDL_audio.h +960 -355
  6. data/dependencies/SDL/include/SDL_bits.h +11 -6
  7. data/dependencies/SDL/include/SDL_blendmode.h +91 -14
  8. data/dependencies/SDL/include/SDL_clipboard.h +30 -7
  9. data/dependencies/SDL/include/SDL_config.h +277 -27
  10. data/dependencies/SDL/include/SDL_config_android.h +13 -38
  11. data/dependencies/SDL/include/SDL_config_iphoneos.h +21 -62
  12. data/dependencies/SDL/include/SDL_config_macosx.h +23 -92
  13. data/dependencies/SDL/include/SDL_config_minimal.h +1 -4
  14. data/dependencies/SDL/include/SDL_config_pandora.h +15 -22
  15. data/dependencies/SDL/include/SDL_config_psp.h +16 -37
  16. data/dependencies/SDL/include/SDL_config_windows.h +28 -91
  17. data/dependencies/SDL/include/SDL_config_winrt.h +33 -61
  18. data/dependencies/SDL/include/SDL_config_wiz.h +28 -56
  19. data/dependencies/SDL/include/SDL_copying.h +1 -1
  20. data/dependencies/SDL/include/SDL_cpuinfo.h +331 -71
  21. data/dependencies/SDL/include/SDL_egl.h +906 -280
  22. data/dependencies/SDL/include/SDL_endian.h +101 -47
  23. data/dependencies/SDL/include/SDL_error.h +70 -19
  24. data/dependencies/SDL/include/SDL_events.h +387 -79
  25. data/dependencies/SDL/include/SDL_filesystem.h +73 -64
  26. data/dependencies/SDL/include/SDL_gamecontroller.h +585 -125
  27. data/dependencies/SDL/include/SDL_gesture.h +36 -6
  28. data/dependencies/SDL/include/SDL_haptic.h +304 -210
  29. data/dependencies/SDL/include/SDL_hidapi.h +451 -0
  30. data/dependencies/SDL/include/SDL_hints.h +1286 -897
  31. data/dependencies/SDL/include/SDL_joystick.h +577 -130
  32. data/dependencies/SDL/include/SDL_keyboard.h +162 -63
  33. data/dependencies/SDL/include/SDL_keycode.h +7 -5
  34. data/dependencies/SDL/include/SDL_loadso.h +42 -8
  35. data/dependencies/SDL/include/SDL_locale.h +34 -32
  36. data/dependencies/SDL/include/SDL_log.h +212 -19
  37. data/dependencies/SDL/include/SDL_main.h +72 -17
  38. data/dependencies/SDL/include/SDL_messagebox.h +70 -23
  39. data/dependencies/SDL/include/SDL_metal.h +27 -32
  40. data/dependencies/SDL/include/SDL_misc.h +19 -15
  41. data/dependencies/SDL/include/SDL_mouse.h +262 -110
  42. data/dependencies/SDL/include/SDL_mutex.h +286 -66
  43. data/dependencies/SDL/include/SDL_name.h +1 -1
  44. data/dependencies/SDL/include/SDL_opengl.h +1 -1
  45. data/dependencies/SDL/include/SDL_opengles.h +1 -1
  46. data/dependencies/SDL/include/SDL_opengles2.h +2 -2
  47. data/dependencies/SDL/include/SDL_pixels.h +199 -34
  48. data/dependencies/SDL/include/SDL_platform.h +39 -2
  49. data/dependencies/SDL/include/SDL_power.h +23 -10
  50. data/dependencies/SDL/include/SDL_quit.h +1 -1
  51. data/dependencies/SDL/include/SDL_rect.h +78 -28
  52. data/dependencies/SDL/include/SDL_render.h +1204 -472
  53. data/dependencies/SDL/include/SDL_revision.h +2 -2
  54. data/dependencies/SDL/include/SDL_rwops.h +605 -33
  55. data/dependencies/SDL/include/SDL_scancode.h +1 -1
  56. data/dependencies/SDL/include/SDL_sensor.h +76 -42
  57. data/dependencies/SDL/include/SDL_shape.h +38 -27
  58. data/dependencies/SDL/include/SDL_stdinc.h +96 -24
  59. data/dependencies/SDL/include/SDL_surface.h +571 -139
  60. data/dependencies/SDL/include/SDL_system.h +339 -101
  61. data/dependencies/SDL/include/SDL_syswm.h +50 -20
  62. data/dependencies/SDL/include/SDL_test.h +1 -1
  63. data/dependencies/SDL/include/SDL_test_assert.h +2 -2
  64. data/dependencies/SDL/include/SDL_test_common.h +23 -6
  65. data/dependencies/SDL/include/SDL_test_compare.h +1 -1
  66. data/dependencies/SDL/include/SDL_test_crc32.h +1 -1
  67. data/dependencies/SDL/include/SDL_test_font.h +3 -3
  68. data/dependencies/SDL/include/SDL_test_fuzzer.h +28 -26
  69. data/dependencies/SDL/include/SDL_test_harness.h +6 -6
  70. data/dependencies/SDL/include/SDL_test_images.h +1 -1
  71. data/dependencies/SDL/include/SDL_test_log.h +1 -1
  72. data/dependencies/SDL/include/SDL_test_md5.h +1 -1
  73. data/dependencies/SDL/include/SDL_test_memory.h +1 -1
  74. data/dependencies/SDL/include/SDL_test_random.h +2 -2
  75. data/dependencies/SDL/include/SDL_thread.h +226 -128
  76. data/dependencies/SDL/include/SDL_timer.h +129 -22
  77. data/dependencies/SDL/include/SDL_touch.h +48 -8
  78. data/dependencies/SDL/include/SDL_types.h +1 -1
  79. data/dependencies/SDL/include/SDL_version.h +72 -46
  80. data/dependencies/SDL/include/SDL_video.h +1266 -460
  81. data/dependencies/SDL/include/SDL_vulkan.h +100 -161
  82. data/dependencies/SDL/include/begin_code.h +22 -1
  83. data/dependencies/SDL/include/close_code.h +1 -1
  84. data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
  85. data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
  86. data/dependencies/SDL_sound/SDL_sound.c +83 -7
  87. data/dependencies/SDL_sound/SDL_sound.h +4 -4
  88. data/dependencies/SDL_sound/SDL_sound_aiff.c +9 -12
  89. data/dependencies/SDL_sound/SDL_sound_au.c +7 -7
  90. data/dependencies/SDL_sound/SDL_sound_coreaudio.c +3 -3
  91. data/dependencies/SDL_sound/SDL_sound_flac.c +1 -1
  92. data/dependencies/SDL_sound/SDL_sound_internal.h +17 -10
  93. data/dependencies/SDL_sound/SDL_sound_modplug.c +25 -27
  94. data/dependencies/SDL_sound/SDL_sound_mp3.c +5 -17
  95. data/dependencies/SDL_sound/SDL_sound_raw.c +11 -11
  96. data/dependencies/SDL_sound/SDL_sound_shn.c +8 -7
  97. data/dependencies/SDL_sound/SDL_sound_voc.c +6 -4
  98. data/dependencies/SDL_sound/SDL_sound_vorbis.c +6 -11
  99. data/dependencies/SDL_sound/SDL_sound_wav.c +35 -29
  100. data/dependencies/SDL_sound/dr_flac.h +618 -220
  101. data/dependencies/SDL_sound/dr_mp3.h +263 -94
  102. data/dependencies/SDL_sound/libmodplug/fastmix.c +58 -64
  103. data/dependencies/SDL_sound/libmodplug/libmodplug.h +25 -103
  104. data/dependencies/SDL_sound/libmodplug/load_669.c +14 -17
  105. data/dependencies/SDL_sound/libmodplug/load_amf.c +11 -7
  106. data/dependencies/SDL_sound/libmodplug/load_ams.c +65 -22
  107. data/dependencies/SDL_sound/libmodplug/load_dbm.c +8 -4
  108. data/dependencies/SDL_sound/libmodplug/load_dmf.c +55 -25
  109. data/dependencies/SDL_sound/libmodplug/load_far.c +9 -13
  110. data/dependencies/SDL_sound/libmodplug/load_gdm.c +448 -0
  111. data/dependencies/SDL_sound/libmodplug/load_it.c +45 -49
  112. data/dependencies/SDL_sound/libmodplug/load_mdl.c +80 -53
  113. data/dependencies/SDL_sound/libmodplug/load_med.c +20 -12
  114. data/dependencies/SDL_sound/libmodplug/load_mod.c +40 -15
  115. data/dependencies/SDL_sound/libmodplug/load_mt2.c +29 -17
  116. data/dependencies/SDL_sound/libmodplug/load_okt.c +12 -8
  117. data/dependencies/SDL_sound/libmodplug/load_psm.c +101 -78
  118. data/dependencies/SDL_sound/libmodplug/load_ptm.c +18 -17
  119. data/dependencies/SDL_sound/libmodplug/load_s3m.c +9 -7
  120. data/dependencies/SDL_sound/libmodplug/load_stm.c +3 -2
  121. data/dependencies/SDL_sound/libmodplug/load_ult.c +2 -2
  122. data/dependencies/SDL_sound/libmodplug/load_umx.c +315 -35
  123. data/dependencies/SDL_sound/libmodplug/load_xm.c +25 -21
  124. data/dependencies/SDL_sound/libmodplug/mmcmp.c +295 -149
  125. data/dependencies/SDL_sound/libmodplug/modplug.c +7 -123
  126. data/dependencies/SDL_sound/libmodplug/modplug.h +32 -29
  127. data/dependencies/SDL_sound/libmodplug/snd_dsp.c +0 -1
  128. data/dependencies/SDL_sound/libmodplug/snd_flt.c +2 -2
  129. data/dependencies/SDL_sound/libmodplug/snd_fx.c +24 -18
  130. data/dependencies/SDL_sound/libmodplug/sndfile.c +55 -156
  131. data/dependencies/SDL_sound/libmodplug/sndmix.c +7 -12
  132. data/dependencies/SDL_sound/libmodplug/tables.h +10 -15
  133. data/dependencies/SDL_sound/stb_vorbis.h +508 -325
  134. data/dependencies/{al_soft → mojoAL}/AL/al.h +38 -30
  135. data/dependencies/{al_soft → mojoAL}/AL/alc.h +27 -56
  136. data/dependencies/mojoAL/mojoal.c +4594 -0
  137. data/ext/gosu/extconf.rb +29 -30
  138. data/include/Gosu/Audio.hpp +70 -85
  139. data/include/Gosu/Color.hpp +19 -11
  140. data/include/Gosu/Font.hpp +40 -44
  141. data/include/Gosu/Graphics.hpp +58 -71
  142. data/include/Gosu/GraphicsBase.hpp +26 -33
  143. data/include/Gosu/Image.hpp +56 -62
  144. data/include/Gosu/ImageData.hpp +23 -27
  145. data/include/Gosu/Inspection.hpp +1 -4
  146. data/include/Gosu/TextInput.hpp +34 -40
  147. data/include/Gosu/Version.hpp +1 -1
  148. data/include/Gosu/Window.hpp +71 -70
  149. data/lib/SDL2.dll +0 -0
  150. data/lib/gosu/compat.rb +24 -37
  151. data/lib/gosu.rb +2 -2
  152. data/lib64/SDL2.dll +0 -0
  153. data/src/Audio.cpp +86 -86
  154. data/src/AudioFile.hpp +6 -6
  155. data/src/AudioFileAudioToolbox.cpp +1 -1
  156. data/src/AudioFileSDLSound.cpp +1 -1
  157. data/src/AudioImpl.hpp +5 -5
  158. data/src/BitmapIO.cpp +0 -20
  159. data/src/BlockAllocator.cpp +2 -1
  160. data/src/Channel.cpp +22 -20
  161. data/src/Color.cpp +12 -9
  162. data/src/EmptyImageData.hpp +15 -17
  163. data/src/FileUnix.cpp +1 -1
  164. data/src/FileWin.cpp +1 -1
  165. data/src/Font.cpp +48 -53
  166. data/src/Graphics.cpp +135 -143
  167. data/src/Image.cpp +41 -42
  168. data/src/Input.cpp +1 -1
  169. data/src/InputUIKit.cpp +1 -1
  170. data/src/LargeImageData.cpp +108 -101
  171. data/src/LargeImageData.hpp +17 -15
  172. data/src/Log.hpp +6 -6
  173. data/src/Macro.cpp +35 -37
  174. data/src/Macro.hpp +11 -11
  175. data/src/Math.cpp +8 -1
  176. data/src/Resolution.cpp +12 -7
  177. data/src/RubyGosu.cxx +5 -5
  178. data/src/TexChunk.cpp +50 -41
  179. data/src/TexChunk.hpp +22 -22
  180. data/src/Text.cpp +37 -37
  181. data/src/TextBuilder.cpp +60 -57
  182. data/src/TextBuilder.hpp +20 -20
  183. data/src/TextInput.cpp +127 -135
  184. data/src/TrueTypeFont.cpp +107 -107
  185. data/src/TrueTypeFont.hpp +39 -38
  186. data/src/TrueTypeFontApple.cpp +19 -22
  187. data/src/TrueTypeFontUnix.cpp +21 -26
  188. data/src/TrueTypeFontWin.cpp +30 -30
  189. data/src/Window.cpp +95 -86
  190. data/src/WindowUIKit.cpp +46 -49
  191. metadata +7 -17
  192. data/dependencies/SDL/include/SDL_config_os2.h +0 -188
  193. data/dependencies/SDL_sound/libmodplug/load_abc.c +0 -4725
  194. data/dependencies/SDL_sound/libmodplug/load_mid.c +0 -1405
  195. data/dependencies/SDL_sound/libmodplug/load_pat.c +0 -1143
  196. data/dependencies/SDL_sound/libmodplug/load_pat.h +0 -25
  197. data/dependencies/al_soft/AL/alext.h +0 -585
  198. data/dependencies/al_soft/AL/efx-creative.h +0 -3
  199. data/dependencies/al_soft/AL/efx-presets.h +0 -402
  200. data/dependencies/al_soft/AL/efx.h +0 -762
  201. data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
  202. data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
  203. data/lib/OpenAL32.dll +0 -0
  204. data/lib64/OpenAL32.dll +0 -0
@@ -1,1405 +0,0 @@
1
- /*
2
-
3
- MikMod Sound System
4
-
5
- By Jake Stine of Divine Entertainment (1996-2000)
6
-
7
- Support:
8
- If you find problems with this code, send mail to:
9
- air@divent.org
10
-
11
- Distribution / Code rights:
12
- Use this source code in any fashion you see fit. Giving me credit where
13
- credit is due is optional, depending on your own levels of integrity and
14
- honesty.
15
-
16
- -----------------------------------------
17
- Module: LOAD_MID
18
-
19
- MID module loader.
20
- by Peter Grootswagers (2006)
21
- <email:pgrootswagers@planet.nl>
22
-
23
- Portability:
24
- All systems - all compilers (hopefully)
25
- */
26
-
27
- #include <stdlib.h>
28
- #include <time.h>
29
- #include <string.h>
30
- #include <math.h>
31
- #include <ctype.h>
32
-
33
- #include "libmodplug.h"
34
- #define PAN_LEFT 0x30
35
- #define PAN_RIGHT 0xD0
36
- #define MAX_POLYPHONY 16 // max notes in one midi channel
37
- #define MAX_TRACKS (MAX_BASECHANNELS-6) // max mod tracks
38
- #define WHEELSHIFT 10 // how many bits the 13bit midi wheel value must shift right
39
-
40
- #include "load_pat.h"
41
-
42
- #define ROWSPERNOTE 16
43
- #define ENV_MMMID_SPEED "MMMID_SPEED"
44
-
45
- /**************************************************************************
46
- **************************************************************************/
47
-
48
- typedef enum {
49
- none,
50
- wheeldown,
51
- wheelup,
52
- fxbrk,
53
- tmpo,
54
- fxsync,
55
- modwheel,
56
- mainvol,
57
- prog
58
- } MIDEVENT_X_EFFECT;
59
-
60
- typedef struct _MIDEVENT
61
- {
62
- struct _MIDEVENT *next;
63
- ULONG tracktick;
64
- BYTE flg; // 1 = note present
65
- BYTE note;
66
- BYTE volume;
67
- BYTE smpno;
68
- BYTE fx;
69
- BYTE fxparam;
70
- } MIDEVENT;
71
-
72
- typedef struct _MIDTRACK
73
- {
74
- struct _MIDTRACK *next;
75
- MIDEVENT *head;
76
- MIDEVENT *tail;
77
- MIDEVENT *workevent; // keeps track of events in track
78
- int balance; // last balance on this track
79
- ULONG vtracktick; // tracktick of last note event (on or off)
80
- BYTE chan;
81
- BYTE vpos; // 0xff is track is free for use, otherwise it's the note playing on this track
82
- BYTE volume; // last note volume on this track
83
- BYTE instr; // current instrument for this track
84
- } MIDTRACK;
85
-
86
- /**************************************************************************
87
- **************************************************************************/
88
-
89
- typedef struct _MIDHANDLE
90
- {
91
- MMFILE *mmf;
92
- MIDTRACK *track;
93
- MIDTRACK *tp;
94
- ULONG tracktime;
95
- int speed;
96
- int midispeed;
97
- int midiformat;
98
- int resolution;
99
- int miditracks;
100
- int divider;
101
- int tempo;
102
- int percussion;
103
- long deltatime;
104
- } MIDHANDLE;
105
-
106
- static void mid_message(const char *s1, const char *s2)
107
- {
108
- char txt[256];
109
- if( SDL_strlen(s1) + SDL_strlen(s2) > 255 ) return;
110
- SDL_snprintf(txt, sizeof (txt), s1, s2);
111
- SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "load_mid > %s\n", txt);
112
- }
113
-
114
- static ULONG miditicks(MIDHANDLE *h, ULONG modtick)
115
- {
116
- return modtick * h->divider / ROWSPERNOTE / h->speed;
117
- }
118
-
119
- static ULONG modticks(MIDHANDLE *h, ULONG miditick)
120
- {
121
- return miditick * ROWSPERNOTE * h->speed / h->divider;
122
- }
123
-
124
- static void mid_adjust_for_optimal_tempo(MIDHANDLE *h, int maxtempo)
125
- {
126
- // the tempo is adjusted so that the maximum tempo is 255
127
- // this way we have the biggest change that very short notes get played
128
- // and we make sure the tempo doesn't become too large or too small
129
- // if the piece in hand isn't so weird it changes tempo from 20 to 255, that is.
130
- // tempo is only registered in first track (h->track) because it is a global event
131
- MIDEVENT *e;
132
- int d, t;
133
- if( maxtempo < 1 ) return;
134
- d = h->divider;
135
- t = maxtempo;
136
- h->divider = (t * d) / 255;
137
- while( (h->midispeed = miditicks(h, h->speed)) < h->speed ) {
138
- ++t;
139
- h->divider = (t * d) / 255;
140
- }
141
- if( h->track ) {
142
- for( e=h->track->head; e; e=e->next ) {
143
- if( e->fx == tmpo )
144
- e->fxparam = (255 * e->fxparam ) / t;
145
- }
146
- }
147
- }
148
-
149
- // =====================================================================================
150
- static MIDEVENT *mid_new_event(MIDHANDLE *h)
151
- // =====================================================================================
152
- {
153
- MIDEVENT *retval;
154
-
155
- retval = (MIDEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(MIDEVENT));
156
- retval->next = NULL;
157
- retval->tracktick = h->tracktime;
158
- retval->flg = 0;
159
- retval->note = 0;
160
- retval->volume = 0;
161
- retval->smpno = 0;
162
- retval->fx = none;
163
- retval->fxparam = 0;
164
- return retval;
165
- }
166
-
167
- // =====================================================================================
168
- static MIDTRACK *mid_new_track(MIDHANDLE *h, int mch, int pos)
169
- // =====================================================================================
170
- {
171
- MIDTRACK *retval;
172
- retval = (MIDTRACK *)_mm_calloc(h->trackhandle, 1,sizeof(MIDTRACK));
173
- retval->next = NULL;
174
- retval->vpos = pos;
175
- retval->instr = 1;
176
- retval->chan = mch;
177
- retval->head = NULL;
178
- retval->tail = NULL;
179
- retval->workevent = NULL;
180
- retval->vtracktick = 0;
181
- retval->volume = h->track? h->track->volume: 120;
182
- retval->balance = 64;
183
- return retval;
184
- }
185
-
186
- static int mid_numtracks(MIDHANDLE *h)
187
- {
188
- int n;
189
- MIDTRACK *t;
190
- n=0;
191
- for( t = h->track; t; t=t->next )
192
- n++;
193
- return n;
194
- }
195
-
196
- // find out how many midichannel we have
197
- static int mid_numchans(MIDHANDLE *h)
198
- {
199
- int i,c,n;
200
- MIDTRACK *t;
201
- c = 0;
202
- for( t = h->track; t; t=t->next )
203
- c |= (1<<t->chan);
204
- n = 0;
205
- for( i=0; i<16; i++ )
206
- if( c & (1<<i) ) n++;
207
- return n;
208
- }
209
-
210
- // find out which ordinal a midichannel has
211
- static int mid_ordchan(MIDHANDLE *h, int mch)
212
- {
213
- int i,c,n;
214
- MIDTRACK *t;
215
- c = 0;
216
- for( t = h->track; t; t=t->next )
217
- c |= (1<<t->chan);
218
- n = 0;
219
- for( i=0; i<mch; i++ )
220
- if( c & (1<<i) ) n++;
221
- return n;
222
- }
223
-
224
- static void mid_rewind_tracks(MIDHANDLE *h)
225
- {
226
- MIDTRACK *tr;
227
- h->tracktime = 0;
228
- for( tr = h->track; tr; tr = tr->next ) {
229
- tr->vpos = 0xff;
230
- tr->workevent = tr->head;
231
- tr->vtracktick = 0;
232
- }
233
- }
234
-
235
- static void mid_update_track(MIDTRACK *tr)
236
- {
237
- MIDEVENT *e;
238
- e = tr->workevent;
239
- if( e->flg ) {
240
- if( e->volume ) tr->vpos = e->note;
241
- else tr->vpos = 0xff;
242
- tr->volume = e->volume;
243
- tr->vtracktick = e->tracktick;
244
- }
245
- if( e->fx == prog ) tr->instr = e->fxparam;
246
- }
247
-
248
- static void mid_sync_track(MIDTRACK *tr, ULONG tracktime)
249
- {
250
- MIDEVENT *e;
251
- e = tr->workevent;
252
- if( e && e->tracktick > tracktime ) e = tr->head; // start again....
253
- for( ; e && e->tracktick <= tracktime; e=e->next ) {
254
- tr->workevent = e;
255
- mid_update_track(tr);
256
- }
257
- }
258
-
259
- // =====================================================================================
260
- static MIDTRACK *mid_find_track(MIDHANDLE *h, int mch, int pos)
261
- // =====================================================================================
262
- {
263
- MIDTRACK *tr;
264
- for( tr=h->track; tr; tr=tr->next ) {
265
- mid_sync_track(tr, h->tracktime);
266
- if( tr->chan == mch && tr->vpos == pos )
267
- return tr;
268
- }
269
- return NULL;
270
- }
271
-
272
- // =====================================================================================
273
- static MIDTRACK *mid_locate_track(MIDHANDLE *h, int mch, int pos)
274
- // =====================================================================================
275
- {
276
- MIDTRACK *tr, *prev, *trunused;
277
- MIDEVENT *e;
278
- int instrno = 1;
279
- int polyphony;
280
- int vol = 0, bal = 0;
281
- int numtracks;
282
- ULONG tmin;
283
- prev = NULL;
284
- trunused = NULL;
285
- polyphony = 0;
286
- numtracks = 0;
287
- tmin = h->midispeed; // minimal distance between note events in track
288
- // look up track with desired channel and pos (note)
289
- for( tr=h->track; tr; tr=tr->next ) {
290
- mid_sync_track(tr, h->tracktime);
291
- if( tr->chan == mch ) {
292
- if( tr->vpos == pos )
293
- return tr;
294
- if( tr->vpos == 0xff ) {
295
- // check if track with silence is quiet long enough
296
- if( h->tracktime > tr->vtracktick + tmin ) trunused = tr;
297
- }
298
- else vol = tr->volume;
299
- instrno = tr->instr;
300
- bal = tr->balance;
301
- polyphony++;
302
- }
303
- numtracks++;
304
- prev = tr;
305
- }
306
- if( trunused ) {
307
- trunused->vpos = pos;
308
- return trunused;
309
- }
310
- if( polyphony > MAX_POLYPHONY || (polyphony > 0 && numtracks > MAX_TRACKS) ) { // do not use up too much channels
311
- for( tr=h->track; tr; tr=tr->next ) {
312
- if( tr->chan == mch ) {
313
- e = tr->workevent;
314
- if( h->tracktime > e->tracktick + tmin ) {
315
- tmin = h->tracktime - e->tracktick;
316
- trunused = tr;
317
- }
318
- }
319
- }
320
- if( trunused ) {
321
- trunused->vpos = pos;
322
- return trunused;
323
- }
324
- }
325
- if( numtracks > MAX_TRACKS ) { // we can not allocate new tracks
326
- tmin = 0;
327
- for( tr=h->track; tr; tr=tr->next ) {
328
- if( tr->chan == mch ) {
329
- e = tr->workevent;
330
- if( h->tracktime >= e->tracktick + tmin ) {
331
- tmin = h->tracktime - e->tracktick;
332
- trunused = tr;
333
- }
334
- }
335
- }
336
- if( trunused ) {
337
- trunused->vpos = pos;
338
- return trunused;
339
- }
340
- tmin = 0;
341
- for( tr=h->track; tr; tr=tr->next ) {
342
- e = tr->workevent;
343
- if( h->tracktime >= e->tracktick + tmin ) {
344
- tmin = h->tracktime - e->tracktick;
345
- trunused = tr;
346
- }
347
- }
348
- if( trunused ) {
349
- trunused->vpos = pos;
350
- trunused->chan = mch;
351
- return trunused;
352
- }
353
- }
354
- tr = mid_new_track(h, mch, pos);
355
- tr->instr = instrno;
356
- tr->volume = vol;
357
- tr->balance = bal;
358
- if( prev ) prev->next = tr;
359
- else h->track = tr;
360
- return tr;
361
- }
362
-
363
- static void mid_add_event(MIDHANDLE *h, MIDTRACK *tp, MIDEVENT *e)
364
- {
365
- MIDEVENT *ew, *ep;
366
- ep = NULL;
367
- ew = tp->workevent;
368
- if( ew && ew->tracktick > e->tracktick ) ew = tp->head; // start again from the beginning...
369
- for( ; ew && ew->tracktick <= e->tracktick; ew = ew->next ) {
370
- ep = ew;
371
- tp->workevent = ew;
372
- mid_update_track(tp);
373
- }
374
- if( ep ) {
375
- ep->next = e;
376
- e->next = ew;
377
- }
378
- else {
379
- e->next = tp->head;
380
- tp->head = e;
381
- }
382
- if( !e->next )
383
- tp->tail = e;
384
- tp->workevent = e;
385
- mid_update_track(tp);
386
- }
387
-
388
- static void mid_add_tempo_event(MIDHANDLE *h, int tempo)
389
- {
390
- MIDEVENT *e;
391
- e = mid_new_event(h);
392
- e->flg = 0;
393
- e->fx = tmpo;
394
- e->fxparam = tempo;
395
- mid_add_event(h, h->track, e);
396
- }
397
-
398
- static void mid_add_partbreak(MIDHANDLE *h)
399
- {
400
- MIDEVENT *e;
401
- e = mid_new_event(h);
402
- e->flg = 0;
403
- e->fx = fxbrk;
404
- mid_add_event(h, h->track, e);
405
- }
406
-
407
- static void mid_add_noteoff(MIDHANDLE *h, MIDTRACK *tp)
408
- {
409
- MIDEVENT *e;
410
- e = mid_new_event(h);
411
- e->flg = 1;
412
- e->note = tp->vpos;
413
- e->smpno = tp->instr;
414
- mid_add_event(h, tp, e);
415
- }
416
-
417
- static void mid_add_noteon(MIDHANDLE *h, MIDTRACK *tp, int n, int vol)
418
- {
419
- MIDEVENT *e;
420
- e = mid_new_event(h);
421
- e->flg = 1;
422
- e->note = n;
423
- e->smpno = tp->instr;
424
- e->volume = vol;
425
- mid_add_event(h, tp, e);
426
- }
427
-
428
- static BYTE modtremolo(int midimod)
429
- {
430
- int m;
431
- if( midimod == 0 ) return 0;
432
- if( midimod > 63 ) {
433
- m = (128 - midimod) / 4;
434
- if( m==0 ) m = 1;
435
- return m|0xf0; // find slide down
436
- }
437
- m = midimod / 4;
438
- if( m==0 ) m = 1;
439
- return (m<<4)|0x0f; // find slide up
440
- }
441
-
442
- // =====================================================================================
443
- static void mid_mod_wheel(MIDHANDLE *h, int mch, int mod)
444
- // =====================================================================================
445
- {
446
- MIDTRACK *tr;
447
- MIDEVENT *e;
448
- for( tr=h->track; tr; tr=tr->next ) {
449
- if( tr->chan == mch ) {
450
- mid_sync_track(tr, h->tracktime);
451
- if( tr->vpos != 0xff ) { // only on tracks with notes on...
452
- e = mid_new_event(h);
453
- e->flg = 0;
454
- e->fx = modwheel;
455
- e->fxparam = modtremolo(mod);
456
- mid_add_event(h, tr, e);
457
- }
458
- }
459
- }
460
- }
461
-
462
- // =====================================================================================
463
- static void mid_main_volume(MIDHANDLE *h, int mch, int vol)
464
- // =====================================================================================
465
- {
466
- MIDTRACK *tr;
467
- MIDEVENT *e;
468
- for( tr=h->track; tr; tr=tr->next ) {
469
- if( tr->chan == mch ) {
470
- e = mid_new_event(h);
471
- e->flg = 0;
472
- e->fx = mainvol;
473
- e->fxparam = vol;
474
- mid_add_event(h, tr, e);
475
- }
476
- }
477
- }
478
-
479
- // transform 0..63..127 to left..center..right in 2n+1 areas
480
- static int modpan(int midipan, int n)
481
- {
482
- int npan, area, x;
483
- x = 2 * n + 1;
484
- area = (midipan * x * (PAN_RIGHT - PAN_LEFT))>>7;
485
- npan = (PAN_LEFT * x + area) / x;
486
- return npan;
487
- }
488
-
489
- // =====================================================================================
490
- static void mid_pan(MIDHANDLE *h, int mch, int pan)
491
- // =====================================================================================
492
- {
493
- MIDTRACK *tr;
494
- int hits;
495
- hits = 0;
496
- for( tr=h->track; tr; tr=tr->next ) {
497
- if( tr->chan == mch ) {
498
- hits++;
499
- tr->balance = pan;
500
- }
501
- }
502
- if( !hits ) {
503
- tr = mid_locate_track(h, mch, 0xff);
504
- tr->balance = pan;
505
- }
506
- }
507
-
508
- // =====================================================================================
509
- static void mid_add_program(MIDHANDLE *h, int mch, int pr)
510
- // =====================================================================================
511
- {
512
- MIDTRACK *tr;
513
- MIDEVENT *e;
514
- int hits;
515
- hits = 0;
516
- for( tr=h->track; tr; tr=tr->next ) {
517
- if( tr->chan == mch ) {
518
- hits++;
519
- e = mid_new_event(h);
520
- e->flg = 0;
521
- e->fx = prog;
522
- e->fxparam = pat_gmtosmp(pr + 1);
523
- mid_add_event(h, tr, e);
524
- }
525
- }
526
- if( !hits ) {
527
- tr = mid_locate_track(h, mch, 0xff);
528
- e = mid_new_event(h);
529
- e->flg = 0;
530
- e->fx = prog;
531
- e->fxparam = pat_gmtosmp(pr + 1);
532
- mid_add_event(h, tr, e);
533
- }
534
- }
535
-
536
- // =====================================================================================
537
- static void mid_all_notes_off(MIDHANDLE *h, int mch)
538
- // =====================================================================================
539
- {
540
- MIDTRACK *tr;
541
- for( tr=h->track; tr; tr=tr->next ) {
542
- if( tr->chan == mch || mch == -1 ) {
543
- mid_sync_track(tr, h->tracktime);
544
- if( tr->vpos != 0xff )
545
- mid_add_noteoff(h, tr);
546
- }
547
- }
548
- }
549
-
550
- static void mid_add_sync(MIDHANDLE *h, MIDTRACK *tp)
551
- {
552
- MIDEVENT *e;
553
- e = mid_new_event(h);
554
- e->flg = 0;
555
- e->fx = fxsync;
556
- mid_add_event(h, tp, e);
557
- }
558
-
559
- static BYTE mid_to_mod_wheel(unsigned int midwheel)
560
- {
561
- unsigned int i;
562
- if( midwheel == 0 ) return 0;
563
- i = midwheel >> WHEELSHIFT;
564
- return i+1;
565
- }
566
-
567
- static void mid_add_wheel(MIDHANDLE *h, MIDTRACK *tp, int wheel)
568
- {
569
- MIDEVENT *e;
570
- e = mid_new_event(h);
571
- e->flg = 0;
572
- if( wheel < 0 ) {
573
- e->fx = wheeldown;
574
- e->fxparam = mid_to_mod_wheel(-wheel);
575
- }
576
- else {
577
- e->fx = wheelup;
578
- e->fxparam = mid_to_mod_wheel(wheel);
579
- }
580
- mid_add_event(h, tp, e);
581
- }
582
-
583
- static void mid_add_pitchwheel(MIDHANDLE *h, int mch, int wheel)
584
- {
585
- MIDTRACK *tr;
586
- int hits;
587
- hits = 0;
588
- for( tr=h->track; tr; tr=tr->next ) {
589
- if( tr->chan == mch ) {
590
- hits++;
591
- mid_sync_track(tr, h->tracktime);
592
- if( tr->vpos != 0xff ) // only on tracks with notes on...
593
- mid_add_wheel(h, tr, wheel);
594
- }
595
- }
596
- if( !hits ) { // special case in midiformat 1 events in first track...
597
- tr = mid_locate_track(h, mch, 0xff);
598
- mid_add_wheel(h, tr, wheel);
599
- }
600
- }
601
-
602
- static uint32_t mid_read_long(MIDHANDLE *h)
603
- {
604
- BYTE buf[4];
605
- mmreadUBYTES(buf, 4, h->mmf);
606
- return (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3];
607
- }
608
-
609
- static short int mid_read_short(MIDHANDLE *h)
610
- {
611
- BYTE buf[2];
612
- mmreadUBYTES(buf, 2, h->mmf);
613
- return (buf[0]<<8)|buf[1];
614
- }
615
-
616
- static BYTE mid_read_byte(MIDHANDLE *h)
617
- {
618
- return mmreadUBYTE(h->mmf);
619
- }
620
-
621
- static int mid_read_delta(MIDHANDLE *h)
622
- {
623
- BYTE bits;
624
- int i, d;
625
- d = 0;
626
- for( i=0; i<4; ) {
627
- bits = mid_read_byte(h);
628
- i++;
629
- d = (d<<7)|(bits&0x7f);
630
- if( !(bits & 0x80) )
631
- break;
632
- }
633
- h->deltatime = d;
634
- return i;
635
- }
636
-
637
- // =====================================================================================
638
- BOOL CSoundFile_TestMID(const BYTE *lpStream, DWORD dwMemLength)
639
- // =====================================================================================
640
- {
641
- char id[5];
642
- MIDHANDLE h;
643
- MMFILE mm;
644
- mm.mm = (char *)lpStream;
645
- mm.sz = dwMemLength;
646
- h.mmf = &mm;
647
- mmfseek(h.mmf,0,SEEK_SET);
648
- mmreadSBYTES(id, 4, h.mmf);
649
- id[4] = '\0';
650
- return !SDL_strcmp(id,"MThd") && mid_read_long(&h) == 6;
651
- }
652
-
653
- // =====================================================================================
654
- static MIDHANDLE *MID_Init(void)
655
- {
656
- MIDHANDLE *retval;
657
- retval = (MIDHANDLE *)SDL_calloc(1,sizeof(MIDHANDLE));
658
- if( !retval ) return NULL;
659
- retval->track = NULL;
660
- retval->percussion = 0;
661
- return retval;
662
- }
663
-
664
- static void MID_CleanupTrack(MIDTRACK *tp)
665
- {
666
- MIDEVENT *ep, *en;
667
- if( tp ) {
668
- for( ep=tp->head; ep; ep = en ) {
669
- en=ep->next;
670
- SDL_free(ep);
671
- }
672
- tp->head = NULL;
673
- }
674
- }
675
-
676
- // =====================================================================================
677
- static void MID_CleanupTracks(MIDHANDLE *handle)
678
- // =====================================================================================
679
- {
680
- MIDTRACK *tp, *tn;
681
- if(handle) {
682
- for( tp=handle->track; tp; tp = tn ) {
683
- tn=tp->next;
684
- MID_CleanupTrack(tp);
685
- }
686
- handle->track = NULL;
687
- }
688
- }
689
-
690
- // =====================================================================================
691
- static void MID_Cleanup(MIDHANDLE *handle)
692
- // =====================================================================================
693
- {
694
- if(handle) {
695
- MID_CleanupTracks(handle);
696
- SDL_free(handle);
697
- handle = 0;
698
- }
699
- }
700
-
701
- static int mid_is_global_event(MIDEVENT *e)
702
- {
703
- return (e->fx == tmpo || e->fx == fxbrk);
704
- }
705
-
706
- static MIDEVENT *mid_next_global(MIDEVENT *e)
707
- {
708
- for( ; e && !mid_is_global_event(e); e=e->next ) ;
709
- return e;
710
- }
711
-
712
- static MIDEVENT *mid_next_fx(MIDEVENT *e)
713
- {
714
- for( ; e && e->fx == none; e=e->next ) ;
715
- return e;
716
- }
717
-
718
- static int mid_is_note_event(MIDEVENT *e)
719
- {
720
- #ifdef LOOPED_NOTES_OFF
721
- return (e->flg == 0);
722
- #else
723
- if( e->flg == 0 ) return 0;
724
- if( e->volume ) return 1;
725
- return pat_smplooped(e->smpno); // let non looping samples die out...
726
- #endif
727
- }
728
-
729
- static MIDEVENT *mid_next_note(MIDEVENT *e)
730
- {
731
- for( ; e && !mid_is_note_event(e); e=e->next ) ;
732
- return e;
733
- }
734
-
735
- static int MID_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], MIDHANDLE *h, int numpat, int channels)
736
- // =====================================================================================
737
- {
738
- int pat,row,i,ch;
739
- BYTE n,ins,vol;
740
- MIDTRACK *t;
741
- MIDEVENT *e, *en, *ef, *el;
742
- ULONG tt1, tt2;
743
- MODCOMMAND *m;
744
- int patbrk, tempo;
745
- if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS;
746
-
747
- // initialize start points of event list in tracks
748
- for( t = h->track; t; t = t->next ) t->workevent = t->head;
749
- for( pat = 0; pat < numpat; pat++ ) {
750
- pattern[pat] = CSoundFile_AllocatePattern(64, channels);
751
- if( !pattern[pat] ) return 0;
752
- psize[pat] = 64;
753
- for( row = 0; row < 64; row++ ) {
754
- tt1 = miditicks(h, (pat * 64 + row ) * h->speed);
755
- tt2 = tt1 + h->midispeed;
756
- ch = 0;
757
- tempo = 0;
758
- patbrk = 0;
759
- if ( h->track )
760
- for( e=mid_next_global(h->track->workevent); e && e->tracktick < tt2; e=mid_next_global(e->next) ) {
761
- if( e && e->tracktick >= tt1 ) { // we have a controller event in this row
762
- switch( e->fx ) {
763
- case tmpo:
764
- tempo = e->fxparam;
765
- break;
766
- case fxbrk:
767
- patbrk = 1;
768
- break;
769
- }
770
- }
771
- }
772
- for( t = h->track; t; t = t->next ) {
773
- m = &pattern[pat][row * channels + ch];
774
- m->param = 0;
775
- m->command = CMD_NONE;
776
- for( e=mid_next_fx(t->workevent); e && e->tracktick < tt2; e=mid_next_fx(e->next) ) {
777
- if( e && e->tracktick >= tt1 ) { // we have a controller event in this row
778
- switch( e->fx ) {
779
- case modwheel:
780
- m->param = e->fxparam;
781
- m->command = CMD_VOLUMESLIDE;
782
- break;
783
- case wheelup:
784
- m->param = e->fxparam|0x10;
785
- m->command = CMD_XFINEPORTAUPDOWN;
786
- break;
787
- case wheeldown:
788
- m->param = e->fxparam|0x20;
789
- m->command = CMD_XFINEPORTAUPDOWN;
790
- break;
791
- }
792
- }
793
- }
794
- for( e=mid_next_note(t->workevent); e && e->tracktick < tt1; e=mid_next_note(e->next) )
795
- t->workevent = e;
796
- i = 0;
797
- ef = NULL;
798
- en = e;
799
- el = e;
800
- for( ; e && e->tracktick < tt2; e=mid_next_note(e->next) ) { // we have a note event in this row
801
- t->workevent = e;
802
- i++;
803
- if( e->volume ) {
804
- if( !ef ) ef = e;
805
- el = e;
806
- }
807
- }
808
- if( i ) {
809
- if( i == 1 || ef == el || !ef ) { // only one event in this row or a note on with some note off
810
- if( ef ) e = ef;
811
- else e = en;
812
- el = t->workevent;
813
- n = pat_modnote(e->note);
814
- ins = e->smpno;
815
- if( e->volume == 0 ) {
816
- m->param = (BYTE)modticks(h, e->tracktick - tt1);
817
- if( m->param ) { // note cut
818
- m->command = CMD_S3MCMDEX;
819
- m->param |= 0xC0;
820
- }
821
- else {
822
- m->param = 0;
823
- m->command = CMD_KEYOFF;
824
- }
825
- vol = 0;
826
- }
827
- else {
828
- vol = e->volume/2;
829
- if( el->volume == 0 ) {
830
- m->param = (BYTE)modticks(h, el->tracktick - tt1);
831
- if( m->param ) { // note cut
832
- m->command = CMD_S3MCMDEX;
833
- m->param |= 0xC0;
834
- }
835
- }
836
- else {
837
- m->param = (BYTE)modticks(h, e->tracktick - tt1);
838
- if( m->param ) { // note delay
839
- m->command = CMD_S3MCMDEX;
840
- m->param |= 0xD0;
841
- }
842
- }
843
- }
844
- m->instr = ins;
845
- m->note = n; // <- normal note
846
- m->volcmd = VOLCMD_VOLUME;
847
- m->vol = vol;
848
- }
849
- else {
850
- // two notes in one row, use FINEPITCHSLIDE runonce effect
851
- // start first note on first tick and framedly runonce on seconds note tick
852
- // use volume and instrument of last note
853
- n = pat_modnote(ef->note);
854
- i = pat_modnote(el->note);
855
- ins = el->smpno;
856
- vol = el->volume/2;
857
- if( vol > 64 ) vol = 64;
858
- m->instr = ins;
859
- m->note = n; // <- normal note
860
- m->volcmd = VOLCMD_VOLUME;
861
- m->vol = vol;
862
- m->param = ((i > n)?i-n:n-i);
863
- if( m->param < 16 ) {
864
- if( m->param ) {
865
- m->command = CMD_XFINEPORTAUPDOWN;
866
- m->param |= (i > n)? 0x10: 0x20;
867
- }
868
- else { // retrigger same note...
869
- m->command = CMD_RETRIG;
870
- m->param = (BYTE)modticks(h, el->tracktick - tt1);
871
- }
872
- }
873
- else
874
- m->command = (i > n)? CMD_PORTAMENTOUP: CMD_PORTAMENTODOWN;
875
- }
876
- }
877
- if( m->param == 0 && m->command == CMD_NONE ) {
878
- if( tempo ) {
879
- m->command = CMD_TEMPO;
880
- m->param = tempo;
881
- tempo = 0;
882
- }
883
- else {
884
- if( patbrk ) {
885
- m->command = CMD_PATTERNBREAK;
886
- patbrk = 0;
887
- }
888
- }
889
- }
890
- ch++;
891
- }
892
- if( tempo || patbrk ) return 1;
893
- }
894
- }
895
- return 0;
896
- }
897
-
898
- static ULONG mid_next_tracktick(MIDEVENT *e)
899
- {
900
- MIDEVENT *en;
901
- en = e->next;
902
- if( en ) return en->tracktick;
903
- return 0x7fffffff; // practically indefinite
904
- }
905
-
906
- // cut off alle events that follow the given event
907
- static void mid_stripoff(MIDTRACK *tp, MIDEVENT *e)
908
- {
909
- MIDEVENT *ep, *en;
910
- for( ep=e->next; ep; ep = en ) {
911
- en=ep->next;
912
- SDL_free(ep);
913
- }
914
- e->next = NULL;
915
- tp->tail = e;
916
- tp->workevent = tp->head;
917
- mid_sync_track(tp, e->tracktick);
918
- }
919
-
920
- static void mid_notes_to_percussion(MIDTRACK *tp, ULONG adjust, ULONG tmin)
921
- {
922
- MIDEVENT *e, *lno = 0;
923
- int n = 0,v;
924
- ULONG ton, toff = 0, tnext;
925
- v = 0x7f; // as loud as it gets
926
- ton = 0;
927
- for( e=tp->head; e; e=e->next ) {
928
- if( e->tracktick < adjust ) e->tracktick = 0;
929
- else e->tracktick -= adjust;
930
- if( e->flg == 1 ) {
931
- if( e->volume > 0 ) {
932
- n = e->note;
933
- e->smpno = pat_gmtosmp(pat_gm_drumnr(n));
934
- e->note = pat_gm_drumnote(n);
935
- e->volume = (v * e->volume) / 128;
936
- if( v && !e->volume ) e->volume = 1;
937
- ton = e->tracktick;
938
- }
939
- else {
940
- toff = ton + tmin;
941
- if( toff > e->tracktick ) {
942
- tnext = mid_next_tracktick(e);
943
- if( toff + tmin < tnext ) e->tracktick = toff;
944
- else {
945
- if( toff < tnext ) e->tracktick = toff - 1;
946
- else e->tracktick = tnext - 1;
947
- }
948
- }
949
- toff = e->tracktick;
950
- lno = e;
951
- }
952
- }
953
- else {
954
- if( e->fx == mainvol ) {
955
- v = e->fxparam;
956
- if( !v && ton > toff ) {
957
- e->flg = 1;
958
- e->volume = 0;
959
- e->note = pat_gm_drumnote(n);
960
- toff = e->tracktick;
961
- lno = e;
962
- }
963
- }
964
- }
965
- }
966
- if( ton > toff ) {
967
- char info[32];
968
- SDL_snprintf(info,sizeof (info),"%ld > %ld note %d", (long)ton, (long)toff, n);
969
- mid_message("drum track ends with note on (%s)", info);
970
- }
971
- if( lno && lno->next ) mid_stripoff(tp, lno);
972
- }
973
-
974
- static void mid_prog_to_notes(MIDTRACK *tp, ULONG adjust, ULONG tmin)
975
- {
976
- MIDEVENT *e, *lno = 0;
977
- int i = 0, n = 0, v = 0x7f;
978
- ULONG ton, toff = 0, tnext;
979
- ton = 0;
980
- for( e=tp->head; e; e=e->next ) {
981
- if( e->tracktick < adjust ) e->tracktick = 0;
982
- else e->tracktick -= adjust;
983
- if( e->flg == 1 ) {
984
- if( !i ) i = pat_gmtosmp(1); // happens in eternal2.mid
985
- e->smpno = i;
986
- n = e->note;
987
- if( e->volume > 0 ) {
988
- e->volume = (v * e->volume) / 128;
989
- if( v && !e->volume ) e->volume = 1;
990
- ton = e->tracktick;
991
- }
992
- else {
993
- toff = ton + tmin;
994
- if( toff > e->tracktick ) {
995
- tnext = mid_next_tracktick(e);
996
- if( toff + tmin < tnext ) e->tracktick = toff;
997
- else {
998
- if( toff < tnext ) e->tracktick = toff - 1;
999
- else e->tracktick = tnext - 1;
1000
- }
1001
- }
1002
- toff = e->tracktick;
1003
- lno = e;
1004
- }
1005
- }
1006
- else {
1007
- if( e->fx == prog ) i = e->fxparam;
1008
- if( e->fx == mainvol ) {
1009
- v = e->fxparam;
1010
- if( !v && ton > toff ) {
1011
- e->flg = 1;
1012
- e->volume = 0;
1013
- e->note = n;
1014
- toff = e->tracktick;
1015
- lno = e;
1016
- }
1017
- }
1018
- }
1019
- }
1020
- if( ton > toff ) {
1021
- char info[40];
1022
- SDL_snprintf(info,sizeof (info),"channel %d, %ld > %ld note %d", tp->chan + 1, (long)ton, (long)toff, n);
1023
- mid_message("melody track ends with note on (%s)", info);
1024
- }
1025
- if( lno && lno->next ) mid_stripoff(tp, lno);
1026
- }
1027
-
1028
- static int midiword(BYTE *b)
1029
- {
1030
- int i;
1031
- i = (b[0]&0x7f)|((b[1]&0x7f)<<7);
1032
- return i;
1033
- }
1034
-
1035
- static int midishort(BYTE *b)
1036
- {
1037
- return midiword(b) - 0x2000;
1038
- }
1039
-
1040
- ULONG mid_first_noteonevent_tick(MIDEVENT *e)
1041
- {
1042
- while( e && (e->flg == 0 || e->volume == 0) ) e=e->next;
1043
- if( !e ) return 0x7fffffff;
1044
- return e->tracktick;
1045
- }
1046
-
1047
- // =====================================================================================
1048
- BOOL CSoundFile_ReadMID(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLength)
1049
- {
1050
- static int avoid_reentry = 0;
1051
- MIDHANDLE *h;
1052
- MMFILE mm;
1053
- int ch, dmulti, maxtempo, panlow, panhigh, numchans, numtracks;
1054
- MIDTRACK *ttp;
1055
- uint32_t t, numpats;
1056
- char buf[256];
1057
- uint32_t miditracklen;
1058
- BYTE runningstatus;
1059
- BYTE cmd;
1060
- BYTE midibyte[2];
1061
- long metalen, delta;
1062
- BYTE *p;
1063
- while( avoid_reentry ) SDL_Delay(1);
1064
- avoid_reentry = 1;
1065
- if( !CSoundFile_TestMID(lpStream, dwMemLength) ) {
1066
- avoid_reentry = 0;
1067
- return FALSE;
1068
- }
1069
- h = MID_Init();
1070
- if( !h ) {
1071
- avoid_reentry = 0;
1072
- return FALSE;
1073
- }
1074
- h->mmf = &mm;
1075
- mm.mm = (char *)lpStream;
1076
- mm.sz = dwMemLength;
1077
- mm.pos = 0;
1078
- pat_resetsmp();
1079
- pat_init_patnames();
1080
- mmfseek(h->mmf,8,SEEK_SET);
1081
- h->midiformat = mid_read_short(h);
1082
- h->miditracks = mid_read_short(h);
1083
- h->resolution = mid_read_short(h);
1084
- // at this point the h->mmf is positioned at first miditrack
1085
- if( h->midiformat == 0 ) h->miditracks = 1;
1086
- if( h->resolution & 0x8000 )
1087
- h->divider = ((h->resolution & 0x7f00)>>8)*(h->resolution & 0xff);
1088
- else
1089
- h->divider = h->resolution;
1090
- h->divider <<= 2; // ticks per quartnote ==> ticks per note
1091
- if (!h->divider) h->divider = 1;
1092
- h->tempo = 122;
1093
- _this->m_nDefaultTempo = 0;
1094
- h->tracktime = 0;
1095
- h->speed = 6;
1096
- if (h->miditracks == 0) {
1097
- MID_Cleanup(h);
1098
- avoid_reentry = 0;
1099
- return FALSE;
1100
- }
1101
- p = (BYTE *)SDL_getenv(ENV_MMMID_SPEED);
1102
- if( p && SDL_isdigit(*p) && p[0] != '0' && p[1] == '\0' ) {
1103
- // transform speed
1104
- t = *p - '0';
1105
- h->speed *= t;
1106
- h->divider *= t;
1107
- h->speed /= 6;
1108
- h->divider /= 6;
1109
- }
1110
- // calculate optimal delta multiplier dmulti keeping tempo adjustments
1111
- // from 10 to 255 in mind (hoping there will be no midi's with tempo's
1112
- // lower than 10, that is sooo sick...)
1113
- // this is necessary for the tracks to patterns routine
1114
- dmulti = 1;
1115
- maxtempo = h->divider;
1116
- while( (h->midispeed = miditicks(h, h->speed)) * 10 < 255 * h->speed ) {
1117
- ++dmulti;
1118
- h->divider = maxtempo * dmulti;
1119
- }
1120
- h->tp = NULL;
1121
- SDL_memset(buf,0,sizeof(buf));
1122
- maxtempo = 0;
1123
- panlow = 64;
1124
- panhigh = 64;
1125
- for( t=0; t<(uint32_t)h->miditracks; t++ ) {
1126
- mmreadSBYTES(buf,4,h->mmf);
1127
- buf[4] = '\0';
1128
- if( SDL_strcmp(buf,"MTrk") ) {
1129
- mid_message("invalid track-chunk '%s' is not 'MTrk'",buf);
1130
- MID_Cleanup(h);
1131
- avoid_reentry = 0;
1132
- return FALSE;
1133
- }
1134
- miditracklen = mid_read_long(h);
1135
- runningstatus = 0;
1136
- if( t && h->midiformat == 1 ) mid_rewind_tracks(h); // tracks sound simultaneously
1137
- while( miditracklen > 0 ) {
1138
- miditracklen -= mid_read_delta(h);
1139
- midibyte[0] = mid_read_byte(h);
1140
- miditracklen--;
1141
- if( midibyte[0] & 0x80 ) {
1142
- runningstatus = midibyte[0];
1143
- switch( runningstatus ) {
1144
- case 0xf1:
1145
- case 0xf4:
1146
- case 0xf5:
1147
- case 0xf6:
1148
- case 0xf7:
1149
- case 0xf8:
1150
- case 0xf9:
1151
- case 0xfa:
1152
- case 0xfb:
1153
- case 0xfc:
1154
- case 0xfd:
1155
- case 0xfe:
1156
- break;
1157
- default:
1158
- midibyte[0] = mid_read_byte(h);
1159
- miditracklen--;
1160
- break;
1161
- }
1162
- }
1163
- h->tracktime += dmulti * h->deltatime;
1164
- ch = runningstatus & 0x0f;
1165
- cmd = runningstatus & 0xf0;
1166
- switch( cmd ) {
1167
- case 0x80: // note off
1168
- midibyte[1] = mid_read_byte(h);
1169
- miditracklen--;
1170
- ttp = mid_find_track(h, ch, midibyte[0]);
1171
- if( ttp ) mid_add_noteoff(h, ttp);
1172
- break;
1173
- case 0x90: // note on
1174
- midibyte[1] = mid_read_byte(h);
1175
- miditracklen--;
1176
- if( midibyte[1] ) {
1177
- ttp = mid_locate_track(h, ch, midibyte[0]);
1178
- mid_add_noteon(h, ttp, midibyte[0], midibyte[1]);
1179
- }
1180
- else {
1181
- ttp = mid_find_track(h, ch, midibyte[0]);
1182
- if( ttp ) mid_add_noteoff(h, ttp);
1183
- }
1184
- break;
1185
- case 0xa0: // polyphonic key pressure
1186
- midibyte[1] = mid_read_byte(h);
1187
- miditracklen--;
1188
- break;
1189
- case 0xb0: // control change
1190
- midibyte[1] = mid_read_byte(h);
1191
- miditracklen--;
1192
- switch(midibyte[0]) {
1193
- case 0x01: // mod wheel
1194
- mid_mod_wheel(h, ch, midibyte[1]);
1195
- break;
1196
- case 0x07: // main volume
1197
- mid_main_volume(h, ch, midibyte[1]);
1198
- break;
1199
- case 0x0a: // pan
1200
- if( midibyte[1] < panlow ) panlow = midibyte[1];
1201
- if( midibyte[1] > panhigh ) panhigh = midibyte[1];
1202
- mid_pan(h, ch, midibyte[1]);
1203
- break;
1204
- case 0x0b: // expression
1205
- break;
1206
- case 0x7b:
1207
- if( midibyte[1] == 0x00 ) // all notes off
1208
- mid_all_notes_off(h, ch);
1209
- break;
1210
- default:
1211
- break;
1212
- }
1213
- break;
1214
- case 0xc0: // program change
1215
- mid_add_program(h, ch, midibyte[0]);
1216
- break;
1217
- case 0xd0: // channel pressure
1218
- break;
1219
- case 0xe0: // pitch wheel change
1220
- midibyte[1] = mid_read_byte(h);
1221
- miditracklen--;
1222
- mid_add_pitchwheel(h, ch, midishort(midibyte));
1223
- break;
1224
- case 0xf0: // system & realtime
1225
- switch( runningstatus ) {
1226
- case 0xf0: // sysex
1227
- while( midibyte[0] != 0xf7 ) {
1228
- midibyte[0] = mid_read_byte(h);
1229
- miditracklen--;
1230
- }
1231
- break;
1232
- case 0xf2: // song position pointer
1233
- midibyte[1] = mid_read_byte(h);
1234
- miditracklen--;
1235
- break;
1236
- case 0xf7:
1237
- delta = h->deltatime;
1238
- miditracklen -= mid_read_delta(h);
1239
- metalen = h->deltatime;
1240
- while( metalen > 0 ) {
1241
- midibyte[1] = mid_read_byte(h);
1242
- metalen--;
1243
- miditracklen--;
1244
- }
1245
- h->deltatime = delta;
1246
- break;
1247
- case 0xff: // meta event
1248
- delta = h->deltatime;
1249
- miditracklen -= mid_read_delta(h);
1250
- metalen = h->deltatime;
1251
- if( metalen > 31 ) metalen = 31;
1252
- if( metalen ) {
1253
- mmreadSBYTES(buf, metalen, h->mmf);
1254
- miditracklen -= metalen;
1255
- }
1256
- buf[metalen] = '\0';
1257
- metalen = h->deltatime - metalen;
1258
- while( metalen > 0 ) {
1259
- midibyte[1] = mid_read_byte(h);
1260
- metalen--;
1261
- miditracklen--;
1262
- }
1263
- h->deltatime = delta;
1264
- switch( midibyte[0] ) {
1265
- case 0x51: // type: tempo
1266
- p=(BYTE *)buf;
1267
- delta = (p[0]<<16)|(p[1]<<8)|p[2];
1268
- if( delta )
1269
- h->tempo = 60000000 / delta;
1270
- if( _this->m_nDefaultTempo == 0 ) _this->m_nDefaultTempo = h->tempo;
1271
- else {
1272
- ttp = h->track;
1273
- if( !ttp ) mid_locate_track(h, 0, 0xff);
1274
- mid_add_tempo_event(h,h->tempo);
1275
- }
1276
- if( h->tempo > maxtempo ) maxtempo = h->tempo;
1277
- break;
1278
- case 0x2f: // type: end of track
1279
- if( miditracklen > 0 ) {
1280
- SDL_snprintf(buf,sizeof (buf), "%u", miditracklen);
1281
- mid_message("Meta event not at end of track, %s bytes left in track", buf);
1282
- miditracklen = 0;
1283
- }
1284
- break;
1285
- default:
1286
- break;
1287
- }
1288
- break;
1289
- default:
1290
- break;
1291
- }
1292
- break;
1293
- default: // no running status, just skip it...
1294
- break;
1295
- }
1296
- if( miditracklen < 1 && (runningstatus != 0xff || midibyte[0] != 0x2f) ) {
1297
- delta = mmftell(h->mmf);
1298
- mmreadSBYTES(buf,4,h->mmf);
1299
- buf[4] = '\0';
1300
- if( SDL_strcmp(buf,"MTrk") ) {
1301
- miditracklen = 0x7fffffff;
1302
- mid_message("Meta event not at end of track, %s bytes left in track", "superfluous");
1303
- }
1304
- else
1305
- mid_message("Meta event not at end of track, %s bytes left in track", "no");
1306
- mmfseek(h->mmf,delta,SEEK_SET);
1307
- }
1308
- }
1309
- }
1310
- // get the lowest event time and the used channels
1311
- delta = 0x7fffffff;
1312
- metalen = 0; // use as bit bucket for used channels
1313
- for( ttp=h->track; ttp; ttp=ttp->next ) {
1314
- metalen |= (1<<ttp->chan);
1315
- if( ttp->head ) {
1316
- ULONG tt;
1317
- tt = mid_first_noteonevent_tick(ttp->head);
1318
- if( tt < (ULONG)delta )
1319
- delta = tt;
1320
- }
1321
- }
1322
- if( metalen & 0x03ff ) {
1323
- if( (metalen & 0x0f00) == 0x0400 )
1324
- h->percussion = 10; // buggy sng2mid uses channel 10
1325
- else
1326
- h->percussion = 9;
1327
- }
1328
- else h->percussion = 15;
1329
- // last but not least shut off all pending events, transform drumnotes when appropriate
1330
- // strip off silences at begin and end and get the greatest tracktime
1331
- h->tracktime = 0;
1332
- metalen = h->midispeed;
1333
- for( ttp=h->track; ttp; ttp=ttp->next ) {
1334
- if( ttp->chan == h->percussion )
1335
- mid_notes_to_percussion(ttp, delta, metalen);
1336
- else
1337
- mid_prog_to_notes(ttp, delta, metalen);
1338
- if( ttp->tail && ttp->tail->tracktick > h->tracktime )
1339
- h->tracktime = ttp->tail->tracktick;
1340
- }
1341
-
1342
- h->tracktime += h->divider >> 2; // add one quartnote to the song for silence
1343
- if ( h->track )
1344
- mid_add_partbreak(h);
1345
- numchans = mid_numchans(h);
1346
- if( panlow > 48 || panhigh < 80 ) {
1347
- for( ttp=h->track; ttp; ttp=ttp->next ) {
1348
- ttp->balance = ((0x40*numchans+0x80*mid_ordchan(h, ttp->chan))/numchans)&0x7f;
1349
- }
1350
- }
1351
- // set module variables
1352
- numtracks = mid_numtracks(h);
1353
- if( _this->m_nDefaultTempo == 0 ) _this->m_nDefaultTempo = h->tempo;
1354
- if( maxtempo == 0 ) maxtempo = h->tempo;
1355
- if( maxtempo != 255 ) {
1356
- mid_adjust_for_optimal_tempo(h, maxtempo);
1357
- }
1358
- if( maxtempo > 0 ) _this->m_nDefaultTempo = (255 * _this->m_nDefaultTempo) / maxtempo;
1359
-
1360
- numpats = 1 + (modticks(h, h->tracktime) / h->speed / 64 );
1361
- if (numpats > MAX_PATTERNS) numpats = MAX_PATTERNS;
1362
-
1363
- _this->m_nType = MOD_TYPE_MID;
1364
- _this->m_nDefaultSpeed = h->speed;
1365
- _this->m_nChannels = numtracks;
1366
- _this->m_dwSongFlags = SONG_LINEARSLIDES;
1367
- _this->m_nMinPeriod = 28 << 2;
1368
- _this->m_nMaxPeriod = 1712 << 3;
1369
- if (_this->m_nChannels == 0)
1370
- return FALSE;
1371
- // orderlist
1372
- for(t=0; t < numpats; t++)
1373
- _this->Order[t] = t;
1374
- if( !PAT_Load_Instruments(_this) ) {
1375
- avoid_reentry = 0;
1376
- return FALSE;
1377
- }
1378
- // ==============================
1379
- // Load the pattern info now!
1380
- if( MID_ReadPatterns(_this->Patterns, _this->PatternSize, h, numpats, _this->m_nChannels) ) {
1381
- // :^( need one more channel to handle the global events ;^b
1382
- _this->m_nChannels++;
1383
- h->tp = mid_new_track(h, h->track->chan, 0xff);
1384
- for( ttp=h->track; ttp->next; ttp=ttp->next ) ;
1385
- ttp->next = h->tp;
1386
- mid_add_sync(h, h->tp);
1387
- for( t=0; t<numpats; t++ ) {
1388
- CSoundFile_FreePattern(_this->Patterns[t]);
1389
- _this->Patterns[t] = NULL;
1390
- }
1391
- MID_ReadPatterns(_this->Patterns, _this->PatternSize, h, numpats, _this->m_nChannels);
1392
- }
1393
- // ============================================================
1394
- // set panning positions
1395
- t = 0;
1396
- for( ttp=h->track; ttp; ttp=ttp->next ) {
1397
- _this->ChnSettings[t].nPan = modpan(ttp->balance, numchans / 2);
1398
- _this->ChnSettings[t].nVolume = 64;
1399
- t++;
1400
- }
1401
- MID_Cleanup(h); // we dont need it anymore
1402
- avoid_reentry = 0; // it is safe now, I'm finished
1403
- return TRUE;
1404
- }
1405
-