gosu 0.15.2 → 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (234) hide show
  1. checksums.yaml +4 -4
  2. data/dependencies/SDL/include/SDL.h +138 -0
  3. data/dependencies/SDL/include/SDL_assert.h +293 -0
  4. data/dependencies/SDL/include/SDL_atomic.h +295 -0
  5. data/dependencies/SDL/include/SDL_audio.h +859 -0
  6. data/dependencies/SDL/include/SDL_bits.h +121 -0
  7. data/dependencies/SDL/include/SDL_blendmode.h +123 -0
  8. data/dependencies/SDL/include/SDL_clipboard.h +71 -0
  9. data/dependencies/SDL/include/SDL_config.h +55 -0
  10. data/dependencies/SDL/include/SDL_config_android.h +182 -0
  11. data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
  12. data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
  13. data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
  14. data/dependencies/SDL/include/SDL_config_os2.h +188 -0
  15. data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
  16. data/dependencies/SDL/include/SDL_config_psp.h +165 -0
  17. data/dependencies/SDL/include/SDL_config_windows.h +288 -0
  18. data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
  19. data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
  20. data/dependencies/SDL/include/SDL_copying.h +20 -0
  21. data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
  22. data/dependencies/SDL/include/SDL_egl.h +1676 -0
  23. data/dependencies/SDL/include/SDL_endian.h +263 -0
  24. data/dependencies/SDL/include/SDL_error.h +112 -0
  25. data/dependencies/SDL/include/SDL_events.h +827 -0
  26. data/dependencies/SDL/include/SDL_filesystem.h +136 -0
  27. data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
  28. data/dependencies/SDL/include/SDL_gesture.h +87 -0
  29. data/dependencies/SDL/include/SDL_haptic.h +1247 -0
  30. data/dependencies/SDL/include/SDL_hints.h +1578 -0
  31. data/dependencies/SDL/include/SDL_joystick.h +499 -0
  32. data/dependencies/SDL/include/SDL_keyboard.h +217 -0
  33. data/dependencies/SDL/include/SDL_keycode.h +351 -0
  34. data/dependencies/SDL/include/SDL_loadso.h +81 -0
  35. data/dependencies/SDL/include/SDL_locale.h +101 -0
  36. data/dependencies/SDL/include/SDL_log.h +211 -0
  37. data/dependencies/SDL/include/SDL_main.h +180 -0
  38. data/dependencies/SDL/include/SDL_messagebox.h +146 -0
  39. data/dependencies/SDL/include/SDL_metal.h +117 -0
  40. data/dependencies/SDL/include/SDL_misc.h +75 -0
  41. data/dependencies/SDL/include/SDL_mouse.h +302 -0
  42. data/dependencies/SDL/include/SDL_mutex.h +251 -0
  43. data/dependencies/SDL/include/SDL_name.h +33 -0
  44. data/dependencies/SDL/include/SDL_opengl.h +2183 -0
  45. data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
  46. data/dependencies/SDL/include/SDL_opengles.h +39 -0
  47. data/dependencies/SDL/include/SDL_opengles2.h +52 -0
  48. data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
  49. data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
  50. data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
  51. data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
  52. data/dependencies/SDL/include/SDL_pixels.h +479 -0
  53. data/dependencies/SDL/include/SDL_platform.h +198 -0
  54. data/dependencies/SDL/include/SDL_power.h +75 -0
  55. data/dependencies/SDL/include/SDL_quit.h +58 -0
  56. data/dependencies/SDL/include/SDL_rect.h +174 -0
  57. data/dependencies/SDL/include/SDL_render.h +1158 -0
  58. data/dependencies/SDL/include/SDL_revision.h +2 -0
  59. data/dependencies/SDL/include/SDL_rwops.h +283 -0
  60. data/dependencies/SDL/include/SDL_scancode.h +413 -0
  61. data/dependencies/SDL/include/SDL_sensor.h +267 -0
  62. data/dependencies/SDL/include/SDL_shape.h +144 -0
  63. data/dependencies/SDL/include/SDL_stdinc.h +647 -0
  64. data/dependencies/SDL/include/SDL_surface.h +563 -0
  65. data/dependencies/SDL/include/SDL_system.h +325 -0
  66. data/dependencies/SDL/include/SDL_syswm.h +354 -0
  67. data/dependencies/SDL/include/SDL_test.h +69 -0
  68. data/dependencies/SDL/include/SDL_test_assert.h +105 -0
  69. data/dependencies/SDL/include/SDL_test_common.h +218 -0
  70. data/dependencies/SDL/include/SDL_test_compare.h +69 -0
  71. data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
  72. data/dependencies/SDL/include/SDL_test_font.h +81 -0
  73. data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
  74. data/dependencies/SDL/include/SDL_test_harness.h +134 -0
  75. data/dependencies/SDL/include/SDL_test_images.h +78 -0
  76. data/dependencies/SDL/include/SDL_test_log.h +67 -0
  77. data/dependencies/SDL/include/SDL_test_md5.h +129 -0
  78. data/dependencies/SDL/include/SDL_test_memory.h +63 -0
  79. data/dependencies/SDL/include/SDL_test_random.h +115 -0
  80. data/dependencies/SDL/include/SDL_thread.h +366 -0
  81. data/dependencies/SDL/include/SDL_timer.h +115 -0
  82. data/dependencies/SDL/include/SDL_touch.h +102 -0
  83. data/dependencies/SDL/include/SDL_types.h +29 -0
  84. data/dependencies/SDL/include/SDL_version.h +162 -0
  85. data/dependencies/SDL/include/SDL_video.h +1282 -0
  86. data/dependencies/SDL/include/SDL_vulkan.h +276 -0
  87. data/dependencies/SDL/include/begin_code.h +166 -0
  88. data/dependencies/SDL/include/close_code.h +40 -0
  89. data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
  90. data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
  91. data/dependencies/SDL_sound/SDL_sound.c +795 -0
  92. data/dependencies/SDL_sound/SDL_sound.h +725 -0
  93. data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
  94. data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
  95. data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
  96. data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
  97. data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
  98. data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
  99. data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
  100. data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
  101. data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
  102. data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
  103. data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
  104. data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
  105. data/dependencies/SDL_sound/dr_flac.h +5906 -0
  106. data/dependencies/SDL_sound/dr_mp3.h +2832 -0
  107. data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
  108. data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
  109. data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
  110. data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
  111. data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
  112. data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
  113. data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
  114. data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
  115. data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
  116. data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
  117. data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
  118. data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
  119. data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
  120. data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
  121. data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
  122. data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
  123. data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
  124. data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
  125. data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
  126. data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
  127. data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
  128. data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
  129. data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
  130. data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
  131. data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
  132. data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
  133. data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
  134. data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
  135. data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
  136. data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
  137. data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
  138. data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
  139. data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
  140. data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
  141. data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
  142. data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
  143. data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
  144. data/dependencies/al_soft/AL/al.h +655 -0
  145. data/dependencies/al_soft/AL/alc.h +270 -0
  146. data/dependencies/al_soft/AL/alext.h +585 -0
  147. data/dependencies/al_soft/AL/efx-creative.h +3 -0
  148. data/dependencies/al_soft/AL/efx-presets.h +402 -0
  149. data/dependencies/al_soft/AL/efx.h +762 -0
  150. data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
  151. data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
  152. data/{src → dependencies/stb}/stb_image.h +330 -127
  153. data/{src → dependencies/stb}/stb_image_write.h +156 -85
  154. data/{src → dependencies/stb}/stb_truetype.h +192 -69
  155. data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
  156. data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
  157. data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
  158. data/ext/gosu/extconf.rb +56 -22
  159. data/{Gosu → include/Gosu}/Audio.hpp +6 -8
  160. data/{Gosu → include/Gosu}/AutoLink.hpp +0 -0
  161. data/include/Gosu/Bitmap.hpp +100 -0
  162. data/{Gosu → include/Gosu}/Buttons.hpp +94 -35
  163. data/{Gosu → include/Gosu}/Channel.h +0 -0
  164. data/{Gosu → include/Gosu}/Color.h +0 -0
  165. data/{Gosu → include/Gosu}/Color.hpp +0 -0
  166. data/{Gosu → include/Gosu}/Directories.hpp +0 -0
  167. data/{Gosu → include/Gosu}/Font.h +0 -0
  168. data/{Gosu → include/Gosu}/Font.hpp +0 -0
  169. data/{Gosu → include/Gosu}/Fwd.hpp +0 -0
  170. data/{Gosu → include/Gosu}/Gosu.h +3 -0
  171. data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
  172. data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
  173. data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
  174. data/{Gosu → include/Gosu}/IO.hpp +0 -0
  175. data/{Gosu → include/Gosu}/Image.h +0 -0
  176. data/{Gosu → include/Gosu}/Image.hpp +7 -6
  177. data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
  178. data/{Gosu → include/Gosu}/Input.hpp +30 -15
  179. data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
  180. data/{Gosu → include/Gosu}/Math.hpp +0 -0
  181. data/{Gosu → include/Gosu}/Platform.hpp +0 -0
  182. data/{Gosu → include/Gosu}/Sample.h +0 -0
  183. data/{Gosu → include/Gosu}/Song.h +0 -0
  184. data/{Gosu → include/Gosu}/Text.hpp +0 -0
  185. data/{Gosu → include/Gosu}/TextInput.h +0 -0
  186. data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
  187. data/{Gosu → include/Gosu}/Timing.hpp +0 -0
  188. data/{Gosu → include/Gosu}/Utility.hpp +1 -1
  189. data/{Gosu → include/Gosu}/Version.hpp +0 -0
  190. data/{Gosu → include/Gosu}/Window.h +2 -0
  191. data/{Gosu → include/Gosu}/Window.hpp +21 -13
  192. data/lib/OpenAL32.dll +0 -0
  193. data/lib/SDL2.dll +0 -0
  194. data/lib/gosu.rb +0 -3
  195. data/lib/gosu/patches.rb +0 -9
  196. data/lib/gosu/swig_patches.rb +3 -2
  197. data/lib/libmpg123.dll +0 -0
  198. data/lib/libsndfile.dll +0 -0
  199. data/lib64/OpenAL32.dll +0 -0
  200. data/lib64/SDL2.dll +0 -0
  201. data/lib64/libmpg123.dll +0 -0
  202. data/lib64/libsndfile.dll +0 -0
  203. data/rdoc/gosu.rb +95 -20
  204. data/src/Audio.cpp +50 -224
  205. data/src/AudioFile.hpp +17 -37
  206. data/src/AudioFileAudioToolbox.cpp +237 -0
  207. data/src/AudioFileSDLSound.cpp +147 -0
  208. data/src/AudioImpl.cpp +3 -12
  209. data/src/AudioImpl.hpp +3 -1
  210. data/src/Bitmap.cpp +85 -83
  211. data/src/BitmapIO.cpp +52 -58
  212. data/src/Constants.cpp +80 -33
  213. data/src/Font.cpp +3 -1
  214. data/src/GosuWrapper.cpp +19 -0
  215. data/src/Graphics.cpp +7 -4
  216. data/src/Image.cpp +13 -16
  217. data/src/Input.cpp +408 -159
  218. data/src/LargeImageData.cpp +1 -1
  219. data/src/MarkupParser.cpp +2 -1
  220. data/src/RubyGosu.cxx +349 -83
  221. data/src/RubyGosu.h +4 -2
  222. data/src/TexChunk.cpp +1 -1
  223. data/src/TextBuilder.cpp +3 -1
  224. data/src/Texture.cpp +1 -1
  225. data/src/TrueTypeFont.cpp +1 -1
  226. data/src/Utility.cpp +11 -7
  227. data/src/Window.cpp +30 -39
  228. data/src/WindowWrapper.cpp +28 -0
  229. metadata +207 -52
  230. data/Gosu/Bitmap.hpp +0 -113
  231. data/src/AudioToolboxFile.hpp +0 -210
  232. data/src/OggFile.hpp +0 -92
  233. data/src/SndFile.hpp +0 -174
  234. data/src/WinMain.cpp +0 -64
@@ -0,0 +1,188 @@
1
+ /*
2
+ * This source code is public domain.
3
+ *
4
+ * Authors: Olivier Lapicque <olivierl@jps.net>,
5
+ * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
6
+ */
7
+
8
+ ////////////////////////////////////////////////////////////
9
+ // 669 Composer / UNIS 669 module loader
10
+ ////////////////////////////////////////////////////////////
11
+
12
+ #include "libmodplug.h"
13
+
14
+ //#pragma warning(disable:4244)
15
+
16
+ typedef struct tagFILEHEADER669
17
+ {
18
+ WORD sig; // 'if' or 'JN'
19
+ signed char songmessage[108]; // Song Message
20
+ BYTE samples; // number of samples (1-64)
21
+ BYTE patterns; // number of patterns (1-128)
22
+ BYTE restartpos;
23
+ BYTE orders[128];
24
+ BYTE tempolist[128];
25
+ BYTE breaks[128];
26
+ } FILEHEADER669;
27
+
28
+
29
+ typedef struct tagSAMPLE669
30
+ {
31
+ BYTE filename[13];
32
+ BYTE length[4]; // when will somebody think about DWORD align ???
33
+ BYTE loopstart[4];
34
+ BYTE loopend[4];
35
+ } SAMPLE669;
36
+
37
+ DWORD lengthArrayToDWORD(const BYTE length[4]) {
38
+ DWORD len = (length[3] << 24) +
39
+ (length[2] << 16) +
40
+ (length[1] << 8) +
41
+ (length[0]);
42
+
43
+ return(len);
44
+ }
45
+
46
+
47
+ BOOL CSoundFile_Read669(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLength)
48
+ //---------------------------------------------------------------
49
+ {
50
+ BOOL b669Ext;
51
+ const FILEHEADER669 *pfh = (const FILEHEADER669 *)lpStream;
52
+ const SAMPLE669 *psmp = (const SAMPLE669 *)(lpStream + 0x1F1);
53
+ DWORD dwMemPos = 0;
54
+
55
+ if ((!lpStream) || (dwMemLength < sizeof(FILEHEADER669))) return FALSE;
56
+ if ((bswapLE16(pfh->sig) != 0x6669) && (bswapLE16(pfh->sig) != 0x4E4A)) return FALSE;
57
+ b669Ext = (bswapLE16(pfh->sig) == 0x4E4A) ? TRUE : FALSE;
58
+ if ((!pfh->samples) || (pfh->samples > 64) || (pfh->restartpos >= 128)
59
+ || (!pfh->patterns) || (pfh->patterns > 128)) return FALSE;
60
+ DWORD donttouchme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600;
61
+ if (donttouchme > dwMemLength) return FALSE;
62
+ for (UINT ichk=0; ichk<pfh->samples; ichk++)
63
+ {
64
+ DWORD len = lengthArrayToDWORD(psmp[ichk].length);
65
+ donttouchme += len;
66
+ }
67
+ if (donttouchme > dwMemLength) return FALSE;
68
+ // That should be enough checking: this must be a 669 module.
69
+ _this->m_nType = MOD_TYPE_669;
70
+ _this->m_dwSongFlags |= SONG_LINEARSLIDES;
71
+ _this->m_nMinPeriod = 28 << 2;
72
+ _this->m_nMaxPeriod = 1712 << 3;
73
+ _this->m_nDefaultTempo = 125;
74
+ _this->m_nDefaultSpeed = 6;
75
+ _this->m_nChannels = 8;
76
+ _this->m_nSamples = pfh->samples;
77
+ for (UINT nins=1; nins<=_this->m_nSamples; nins++, psmp++)
78
+ {
79
+ DWORD len = lengthArrayToDWORD(psmp->length);
80
+ DWORD loopstart = lengthArrayToDWORD(psmp->loopstart);
81
+ DWORD loopend = lengthArrayToDWORD(psmp->loopend);
82
+ if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH;
83
+ if ((loopend > len) && (!loopstart)) loopend = 0;
84
+ if (loopend > len) loopend = len;
85
+ if (loopstart + 4 >= loopend) loopstart = loopend = 0;
86
+ _this->Ins[nins].nLength = len;
87
+ _this->Ins[nins].nLoopStart = loopstart;
88
+ _this->Ins[nins].nLoopEnd = loopend;
89
+ if (loopend) _this->Ins[nins].uFlags |= CHN_LOOP;
90
+ _this->Ins[nins].nVolume = 256;
91
+ _this->Ins[nins].nGlobalVol = 64;
92
+ _this->Ins[nins].nPan = 128;
93
+ }
94
+ // Reading Orders
95
+ SDL_memcpy(_this->Order, pfh->orders, 128);
96
+ _this->m_nRestartPos = pfh->restartpos;
97
+ if (_this->Order[_this->m_nRestartPos] >= pfh->patterns) _this->m_nRestartPos = 0;
98
+ // Reading Pattern Break Locations
99
+ for (UINT npan=0; npan<8; npan++)
100
+ {
101
+ _this->ChnSettings[npan].nPan = (npan & 1) ? 0x30 : 0xD0;
102
+ _this->ChnSettings[npan].nVolume = 64;
103
+ }
104
+ // Reading Patterns
105
+ dwMemPos = 0x1F1 + pfh->samples * 25;
106
+ for (UINT npat=0; npat<pfh->patterns; npat++)
107
+ {
108
+ _this->Patterns[npat] = CSoundFile_AllocatePattern(64, _this->m_nChannels);
109
+ if (!_this->Patterns[npat]) break;
110
+ _this->PatternSize[npat] = 64;
111
+ MODCOMMAND *m = _this->Patterns[npat];
112
+ const BYTE *p = lpStream + dwMemPos;
113
+ for (UINT row=0; row<64; row++)
114
+ {
115
+ MODCOMMAND *mspeed = m;
116
+ if ((row == pfh->breaks[npat]) && (row != 63))
117
+ {
118
+ for (UINT i=0; i<8; i++)
119
+ {
120
+ m[i].command = CMD_PATTERNBREAK;
121
+ m[i].param = 0;
122
+ }
123
+ }
124
+ for (UINT n=0; n<8; n++, m++, p+=3)
125
+ {
126
+ UINT note = p[0] >> 2;
127
+ UINT instr = ((p[0] & 0x03) << 4) | (p[1] >> 4);
128
+ UINT vol = p[1] & 0x0F;
129
+ if (p[0] < 0xFE)
130
+ {
131
+ m->note = note + 37;
132
+ m->instr = instr + 1;
133
+ }
134
+ if (p[0] <= 0xFE)
135
+ {
136
+ m->volcmd = VOLCMD_VOLUME;
137
+ m->vol = (vol << 2) + 2;
138
+ }
139
+ if (p[2] != 0xFF)
140
+ {
141
+ UINT command = p[2] >> 4;
142
+ UINT param = p[2] & 0x0F;
143
+ switch(command)
144
+ {
145
+ case 0x00: command = CMD_PORTAMENTOUP; break;
146
+ case 0x01: command = CMD_PORTAMENTODOWN; break;
147
+ case 0x02: command = CMD_TONEPORTAMENTO; break;
148
+ case 0x03: command = CMD_MODCMDEX; param |= 0x50; break;
149
+ case 0x04: command = CMD_VIBRATO; param |= 0x40; break;
150
+ case 0x05: if (param) command = CMD_SPEED; else command = 0; param += 2; break;
151
+ case 0x06: if (param == 0) { command = CMD_PANNINGSLIDE; param = 0xFE; } else
152
+ if (param == 1) { command = CMD_PANNINGSLIDE; param = 0xEF; } else
153
+ command = 0;
154
+ break;
155
+ default: command = 0;
156
+ }
157
+ if (command)
158
+ {
159
+ if (command == CMD_SPEED) mspeed = NULL;
160
+ m->command = command;
161
+ m->param = param;
162
+ }
163
+ }
164
+ }
165
+ if ((!row) && (mspeed))
166
+ {
167
+ for (UINT i=0; i<8; i++) if (!mspeed[i].command)
168
+ {
169
+ mspeed[i].command = CMD_SPEED;
170
+ mspeed[i].param = pfh->tempolist[npat] + 2;
171
+ break;
172
+ }
173
+ }
174
+ }
175
+ dwMemPos += 0x600;
176
+ }
177
+ // Reading Samples
178
+ for (UINT n=1; n<=_this->m_nSamples; n++)
179
+ {
180
+ UINT len = _this->Ins[n].nLength;
181
+ if (dwMemPos >= dwMemLength) break;
182
+ if (len > 4) CSoundFile_ReadSample(_this, &_this->Ins[n], RS_PCM8U, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
183
+ dwMemPos += len;
184
+ }
185
+ return TRUE;
186
+ }
187
+
188
+
@@ -0,0 +1,4725 @@
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_ABC
18
+
19
+ ABC 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 <limits.h>
28
+ #include <stdlib.h>
29
+ #include <time.h>
30
+ #include <string.h>
31
+ #include <math.h>
32
+ #include <ctype.h>
33
+
34
+ #include "libmodplug.h"
35
+
36
+ #include "load_pat.h"
37
+
38
+ #define MAXABCINCLUDES 8
39
+ #define MAXCHORDNAMES 80
40
+ #define ABC_ENV_DUMPTRACKS "MMABC_DUMPTRACKS"
41
+ #define ABC_ENV_NORANDOMPICK "MMABC_NO_RANDOM_PICK"
42
+
43
+ // gchords use tracks with vpos 1 thru 7
44
+ // drums use track with vpos 8
45
+ // voice chords use vpos 0 and vpos from 11 up
46
+ #define GCHORDBPOS 1
47
+ #define GCHORDFPOS 2
48
+ #define GCHORDCPOS 3
49
+ #define DRUMPOS 8
50
+ #define DRONEPOS1 9
51
+ #define DRONEPOS2 10
52
+
53
+ // in the patterns a whole note at unmodified tempo is 16 rows
54
+ #define ROWSPERNOTE 16
55
+ // a 1/64-th note played in triool equals a 1/96-th note, to be able
56
+ // to play them and also to play the 1/64-th we need a resolution of 192
57
+ // because 2/192 = 1/96 and 3/192 = 1/64
58
+ #define RESOLUTION 192
59
+
60
+ #pragma pack(1)
61
+
62
+ /**************************************************************************
63
+ **************************************************************************/
64
+ typedef enum {
65
+ note,
66
+ octave,
67
+ smpno,
68
+ volume,
69
+ effect,
70
+ effoper
71
+ } ABCEVENT_X_NOTE;
72
+
73
+ typedef enum {
74
+ none,
75
+ trill,
76
+ bow,
77
+ accent
78
+ } ABCEVENT_X_EFFECT;
79
+
80
+ typedef enum {
81
+ cmdflag,
82
+ command,
83
+ chordnum,
84
+ chordnote,
85
+ chordbase,
86
+ jumptype
87
+ } ABCEVENT_X_CMD;
88
+
89
+ typedef enum {
90
+ cmdsegno = '$',
91
+ cmdcapo = 'B',
92
+ cmdchord = 'C',
93
+ cmdfine = 'F',
94
+ cmdhide = 'H',
95
+ cmdjump = 'J',
96
+ cmdloop = 'L',
97
+ cmdcoda = 'O',
98
+ cmdpartbrk = 'P',
99
+ cmdsync = 'S',
100
+ cmdtempo = 'T',
101
+ cmdvariant = 'V',
102
+ cmdtocoda = 'X'
103
+ } ABCEVENT_CMD;
104
+
105
+ typedef enum {
106
+ jumpnormal,
107
+ jumpfade,
108
+ jumpdacapo,
109
+ jumpdcfade,
110
+ jumpdasegno,
111
+ jumpdsfade,
112
+ jumpfine,
113
+ jumptocoda,
114
+ jumpvariant,
115
+ jumpnot
116
+ } ABCEVENT_JUMPTYPE;
117
+
118
+ typedef struct _ABCEVENT
119
+ {
120
+ struct _ABCEVENT *next;
121
+ uint32_t tracktick;
122
+ union {
123
+ uint8_t par[6];
124
+ struct {
125
+ uint8_t flg;
126
+ uint8_t cmd;
127
+ uint32_t lpar; // for variant selections, bit pattern
128
+ };
129
+ };
130
+ uint8_t part;
131
+ uint8_t tiednote;
132
+ } ABCEVENT;
133
+
134
+ typedef struct _ABCTRACK
135
+ {
136
+ struct _ABCTRACK *next;
137
+ ABCEVENT *head;
138
+ ABCEVENT *tail;
139
+ ABCEVENT *capostart;
140
+ ABCEVENT *tienote;
141
+ int transpose;
142
+ int octave_shift;
143
+ uint32_t slidevoltime; // for crescendo and diminuendo
144
+ int slidevol; // -2:fade away, -1:diminuendo, 0:none, +1:crescendo
145
+ uint8_t vno; // 0 is track is free for use, from previous song in multi-songbook
146
+ uint8_t vpos; // 0 is main voice, other is subtrack for gchords, gchords or drumnotes
147
+ uint8_t tiedvpos;
148
+ uint8_t mute;
149
+ uint8_t chan; // 10 is percussion channel, any other is melodic channel
150
+ uint8_t volume;
151
+ uint8_t instr; // current instrument for this track
152
+ uint8_t legato;
153
+ char v[22]; // first twenty characters are significant
154
+ } ABCTRACK;
155
+
156
+ typedef struct _ABCMACRO
157
+ {
158
+ struct _ABCMACRO *next;
159
+ char *name;
160
+ char *subst;
161
+ char *n;
162
+ } ABCMACRO;
163
+
164
+ /**************************************************************************
165
+ **************************************************************************/
166
+
167
+ typedef struct _ABCHANDLE
168
+ {
169
+ ABCMACRO *macro;
170
+ ABCMACRO *umacro;
171
+ ABCTRACK *track;
172
+ long int pickrandom;
173
+ unsigned int len;
174
+ int speed;
175
+ char *line;
176
+ char *beatstring;
177
+ uint8_t beat[4]; // a:first note, b:strong notes, c:weak notes, n:strong note every n
178
+ char gchord[80]; // last setting for gchord
179
+ char drum[80]; // last setting for drum
180
+ char drumins[80]; // last setting for drum
181
+ char drumvol[80]; // last setting for drum
182
+ uint32_t barticks;
183
+ // parse variables, declared here to avoid parameter pollution
184
+ int abcchordvol, abcchordprog, abcbassvol, abcbassprog;
185
+ int ktrans;
186
+ int drumon, gchordon, droneon;
187
+ int dronegm, dronepitch[2], dronevol[2];
188
+ ABCTRACK *tp, *tpc, *tpr;
189
+ uint32_t tracktime;
190
+ } ABCHANDLE;
191
+
192
+ /* !!! FIXME: global state */
193
+ static int global_voiceno, global_octave_shift, global_tempo_factor, global_tempo_divider;
194
+ static char global_part;
195
+ static uint32_t global_songstart;
196
+ /* Named guitar chords */
197
+ static char chordname[MAXCHORDNAMES][8];
198
+ static int chordnotes[MAXCHORDNAMES][6];
199
+ static int chordlen[MAXCHORDNAMES];
200
+ static int chordsnamed = 0;
201
+
202
+ static const char *sig[] = {
203
+ " C D EF G A Bc d ef g a b", // 7 sharps C#
204
+ " C D EF G AB c d ef g ab ", // 6 sharps F#
205
+ " C DE F G AB c de f g ab ", // 5 sharps B
206
+ " C DE F GA B c de f ga b ", // 4 sharps E
207
+ " CD E F GA B cd e f ga b ", // 3 sharps A
208
+ " CD E FG A B cd e fg a b ", // 2 sharps D
209
+ " C D E FG A Bc d e fg a b", // 1 sharps G
210
+ " C D EF G A Bc d ef g a b", // 0 sharps C
211
+ " C D EF G AB c d ef g ab ", // 1 flats F
212
+ " C DE F G AB c de f g ab ", // 2 flats Bb
213
+ " C DE F GA B c de f ga b ", // 3 flats Eb
214
+ " CD E F GA B cd e f ga b ", // 4 flats Ab
215
+ " CD E FG A B cd e fg a b ", // 5 flats Db
216
+ "C D E FG A Bc d e fg a b ", // 6 flats Gb
217
+ "C D EF G A Bc d ef g a b ", // 7 flats Cb
218
+ // 0123456789012345678901234
219
+ };
220
+
221
+ static const char *keySigs[] = {
222
+ /* 0....:....1....:....2....:....3....:....4....:....5. */
223
+ "7 sharps: C# A#m G#Mix D#Dor E#Phr F#Lyd B#Loc ",
224
+ "6 sharps: F# D#m C#Mix G#Dor A#Phr BLyd E#Loc ",
225
+ "5 sharps: B G#m F#Mix C#Dor D#Phr ELyd A#Loc ",
226
+ "4 sharps: E C#m BMix F#Dor G#Phr ALyd D#Loc ",
227
+ "3 sharps: A F#m EMix BDor C#Phr DLyd G#Loc ",
228
+ "2 sharps: D Bm AMix EDor F#Phr GLyd C#Loc ",
229
+ "1 sharp : G Em DMix ADor BPhr CLyd F#Loc ",
230
+ "0 sharps: C Am GMix DDor EPhr FLyd BLoc ",
231
+ "1 flat : F Dm CMix GDor APhr BbLyd ELoc ",
232
+ "2 flats : Bb Gm FMix CDor DPhr EbLyd ALoc ",
233
+ "3 flats : Eb Cm BbMix FDor GPhr AbLyd DLoc ",
234
+ "4 flats : Ab Fm EbMix BbDor CPhr DbLyd GLoc ",
235
+ "5 flats : Db Bbm AbMix EbDor FPhr GbLyd CLoc ",
236
+ "6 flats : Gb Ebm DbMix AbDor BbPhr CbLyd FLoc ",
237
+ "7 flats : Cb Abm GbMix DbDor EbPhr FbLyd BbLoc ",
238
+ 0
239
+ };
240
+
241
+ // local prototypes
242
+ static int abc_getnumber(const char *p, int *number);
243
+ static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos);
244
+ static void abc_add_event(ABCHANDLE *h, ABCTRACK *tp, ABCEVENT *e);
245
+ static void abc_add_setloop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime);
246
+ static void abc_add_setjumploop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, ABCEVENT_JUMPTYPE j);
247
+ static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime);
248
+ static int abc_patno(ABCHANDLE *h, uint32_t tracktime);
249
+
250
+ static SDL_INLINE int IsAlpha(const char c) {
251
+ return ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) );
252
+ }
253
+
254
+ static SDL_INLINE int IsUpper(const char c) {
255
+ return ( (c >= 'A') && (c <= 'Z') );
256
+ }
257
+
258
+ static SDL_INLINE int IsLower(const char c) {
259
+ return ( (c >= 'a') && (c <= 'z') );
260
+ }
261
+
262
+ static int abc_isvalidchar(char c) {
263
+ return(IsAlpha(c) || SDL_isdigit(c) || SDL_isspace(c) || c == '%' || c == ':');
264
+ }
265
+
266
+ static const char *abc_skipspace(const char *p)
267
+ {
268
+ while (*p && SDL_isspace(*p))
269
+ p++;
270
+ return p;
271
+ }
272
+
273
+ static void abc_extractkeyvalue(char *key, size_t key_max,
274
+ char *value, size_t value_max, const char *src)
275
+ {
276
+ while (*src && SDL_isspace(*src))
277
+ src++;
278
+
279
+ size_t key_size;
280
+ for (key_size = 0; key_size < key_max - 1 && *src;) {
281
+ if (*src == '=') {
282
+ src++;
283
+ break;
284
+ }
285
+ key[key_size++] = *src++;
286
+ }
287
+ while (key_size > 0 && SDL_isspace(key[key_size - 1]))
288
+ key_size--;
289
+ key[key_size] = '\0';
290
+
291
+ while (*src && SDL_isspace(*src))
292
+ src++;
293
+
294
+ size_t value_size;
295
+ for (value_size = 0; value_size < value_max - 1 && *src;)
296
+ value[value_size++] = *src++;
297
+ while (value_size > 0 && SDL_isspace(value[value_size - 1]))
298
+ value_size--;
299
+ value[value_size] = '\0';
300
+ }
301
+
302
+ static void abc_message(const char *s1, const char *s2)
303
+ {
304
+ char txt[256];
305
+ if( SDL_strlen(s1) + SDL_strlen(s2) > 255 ) return;
306
+ SDL_snprintf(txt, sizeof (txt), s1, s2);
307
+ SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "load_abc > %s\n", txt);
308
+ }
309
+
310
+ static uint32_t modticks(uint32_t abcticks)
311
+ {
312
+ return abcticks / RESOLUTION;
313
+ }
314
+
315
+ static uint32_t abcticks(uint32_t modticks)
316
+ {
317
+ return modticks * RESOLUTION;
318
+ }
319
+
320
+ static uint32_t notelen_notediv_to_ticks(int speed, int len, int div)
321
+ {
322
+ uint32_t u;
323
+ if (div == 0) return 0;
324
+ u = (ROWSPERNOTE * RESOLUTION * speed * len * global_tempo_factor) / (div * global_tempo_divider);
325
+ return u;
326
+ }
327
+
328
+ static void abc_dumptracks(ABCHANDLE *h, const char *p)
329
+ {
330
+ #if 0
331
+ ABCTRACK *t;
332
+ ABCEVENT *e;
333
+ int n,pat,row,tck;
334
+ char nn[3];
335
+ if( !h ) return;
336
+ for( t=h->track; t; t=t->next ) {
337
+ printf("track %d.%d chan=%d %s\n", (int)(t->vno), (int)(t->vpos),
338
+ (int)(t->chan), (char *)(t->v));
339
+ if( SDL_strcmp(p,"nonotes") )
340
+ n = 1;
341
+ else
342
+ n = 0;
343
+ for( e=t->head; e; e=e->next ) {
344
+ tck = modticks(e->tracktick);
345
+ row = tck / h->speed;
346
+ pat = row / 64;
347
+ tck = tck % h->speed;
348
+ row = row % 64;
349
+ nn[0] = ( e->tracktick % abcticks(h->speed * 64) ) ? ' ': '-';
350
+ if( e->flg == 1 ) {
351
+ printf(" %6d.%02d.%d%c%c %d.%d %s ",
352
+ pat, row, tck, nn[0], (int)(e->part), (int)(t->vno),
353
+ (int)(t->vpos), (char *)(t->v));
354
+ if( e->cmd == cmdchord ) {
355
+ nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[chordnote]];
356
+ nn[1] = "b # # # # # # # # # # #"[e->par[chordnote]];
357
+ nn[2] = '\0';
358
+ if( SDL_isspace(nn[1]) ) nn[1] = '\0';
359
+ printf("CMD %c: gchord %s%s",
360
+ (char)(e->cmd), nn, chordname[e->par[chordnum]]);
361
+ if( e->par[chordbase] != e->par[chordnote] ) {
362
+ nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[chordbase]];
363
+ nn[1] = "b # # # # # # # # # # #"[e->par[chordbase]];
364
+ nn[2] = '\0';
365
+ printf("/%s", nn);
366
+ }
367
+ printf("\n");
368
+ }
369
+ else
370
+ printf("CMD %c @%p 0x%08lX\n",
371
+ (char)(e->cmd), e,
372
+ (unsigned long)(e->lpar));
373
+ if( SDL_strcmp(p,"nonotes") )
374
+ n = 1;
375
+ else
376
+ n = 0;
377
+ }
378
+ else if( n ) {
379
+ printf(" %6d.%02d.%d%c%c %d.%d %s ", pat, row, tck, nn[0], e->part, t->vno, t->vpos, t->v);
380
+ if( e->par[note] ) {
381
+ nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[note]-23];
382
+ nn[1] = "b # # # # # # # # # # #"[e->par[note]-23];
383
+ nn[2] = '\0';
384
+ }
385
+ else SDL_strlcpy(nn,"--",sizeof (nn));
386
+ printf("NOTE %s octave %d inst %s vol %03d\n",
387
+ nn, e->par[octave], pat_gm_name(pat_smptogm(e->par[smpno])),e->par[volume]);
388
+ if( SDL_strcmp(p,"all") )
389
+ n = 0;
390
+ }
391
+ }
392
+ }
393
+ #endif
394
+ }
395
+
396
+
397
+ // =====================================================================================
398
+ static ABCEVENT *abc_new_event(ABCHANDLE *h, uint32_t abctick, const char data[])
399
+ // =====================================================================================
400
+ {
401
+ ABCEVENT *retval;
402
+ int i;
403
+
404
+ retval = (ABCEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(ABCEVENT));
405
+ retval->next = NULL;
406
+ retval->tracktick = abctick;
407
+ for( i=0; i<6; i++ )
408
+ retval->par[i] = data[i];
409
+ retval->part = global_part;
410
+ retval->tiednote = 0;
411
+ return retval;
412
+ }
413
+
414
+ // =============================================================================
415
+ static ABCEVENT *abc_copy_event(ABCHANDLE *h, ABCEVENT *se)
416
+ // =============================================================================
417
+ {
418
+ ABCEVENT *e;
419
+ e = (ABCEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(ABCEVENT));
420
+ e->next = NULL;
421
+ e->tracktick = se->tracktick;
422
+ e->flg = se->flg;
423
+ e->cmd = se->cmd;
424
+ e->lpar = se->lpar;
425
+ e->part = se->part;
426
+ return e;
427
+ }
428
+
429
+ // =============================================================================
430
+ static void abc_new_macro(ABCHANDLE *h, const char *m)
431
+ // =============================================================================
432
+ {
433
+ ABCMACRO *retval;
434
+ char key[256], value[256];
435
+ abc_extractkeyvalue(key, sizeof(key), value, sizeof(value), m);
436
+
437
+ retval = (ABCMACRO *)_mm_calloc(h->macrohandle, 1,sizeof(ABCMACRO));
438
+ retval->name = DupStr(h->macrohandle, key, SDL_strlen(key));
439
+ retval->n = SDL_strrchr(retval->name, 'n'); // for transposing macro's
440
+ retval->subst = DupStr(h->macrohandle, value, SDL_strlen(value));
441
+ retval->next = h->macro;
442
+ h->macro = retval;
443
+ }
444
+
445
+ // =============================================================================
446
+ static void abc_new_umacro(ABCHANDLE *h, const char *m)
447
+ // =============================================================================
448
+ {
449
+ ABCMACRO *retval, *mp;
450
+ char *q;
451
+
452
+ char key[256], value[256];
453
+ abc_extractkeyvalue(key, sizeof(key), value, sizeof(value), m);
454
+ if( SDL_strlen(key) > 1 || SDL_strchr("~HIJKLMNOPQRSTUVWXY",SDL_toupper(key[0])) == 0 ) return;
455
+ while( (q = SDL_strchr(key, '!')) != NULL )
456
+ *q = '+'; // translate oldstyle to newstyle
457
+ if( !SDL_strcmp(key,"+nil+") ) { // delete a macro
458
+ mp = NULL;
459
+ for( retval=h->umacro; retval; retval = retval->next ) {
460
+ if( retval->name[0] == key[0] ) { // delete this one
461
+ if( mp ) mp->next = retval->next;
462
+ else h->umacro = retval->next;
463
+ _mm_free(h->macrohandle, retval);
464
+ return;
465
+ }
466
+ mp = retval;
467
+ }
468
+ return;
469
+ }
470
+ retval = (ABCMACRO *)_mm_calloc(h->macrohandle, 1,sizeof(ABCMACRO));
471
+ retval->name = DupStr(h->macrohandle, key, 1);
472
+ retval->subst = DupStr(h->macrohandle, value, SDL_strlen(value));
473
+ retval->n = 0;
474
+ retval->next = h->umacro; // by placing it up front we mask out the old macro until we +nil+ it
475
+ h->umacro = retval;
476
+ }
477
+
478
+ // =============================================================================
479
+ static ABCTRACK *abc_new_track(ABCHANDLE *h, const char *voice, int pos)
480
+ // =============================================================================
481
+ {
482
+ ABCTRACK *retval;
483
+ if( !pos ) global_voiceno++;
484
+ retval = (ABCTRACK *)_mm_calloc(h->trackhandle, 1,sizeof(ABCTRACK));
485
+ retval->next = NULL;
486
+ retval->vno = global_voiceno;
487
+ retval->vpos = pos;
488
+ retval->tiedvpos = pos;
489
+ retval->instr = 1;
490
+ SDL_strlcpy(retval->v, voice, 20);
491
+ retval->v[20] = '\0';
492
+ retval->head = NULL;
493
+ retval->tail = NULL;
494
+ retval->capostart = NULL;
495
+ retval->tienote = NULL;
496
+ retval->mute = 0;
497
+ retval->chan = 0;
498
+ retval->transpose = 0;
499
+ retval->volume = h->track? h->track->volume: 120;
500
+ retval->slidevoltime = 0;
501
+ retval->slidevol = 0;
502
+ retval->legato = 0;
503
+ return retval;
504
+ }
505
+
506
+ static int abc_numtracks(ABCHANDLE *h)
507
+ {
508
+ int n;
509
+ ABCTRACK *t;
510
+ n=0;
511
+ for( t = h->track; t; t=t->next )
512
+ n++;
513
+ return n;
514
+ }
515
+
516
+ static int abc_interval(const char *s, const char *d)
517
+ {
518
+ const char *p;
519
+ int i,j,k;
520
+ int n,oct,m[2];
521
+ for( j=0; j<2; j++ ) {
522
+ if( j ) p = d;
523
+ else p = s;
524
+ switch(p[0]) {
525
+ case '^':
526
+ n = p[1];
527
+ i = 2;
528
+ break;
529
+ case '_':
530
+ n = p[1];
531
+ i = 2;
532
+ break;
533
+ case '=':
534
+ n = p[1];
535
+ i = 2;
536
+ break;
537
+ default:
538
+ n = p[0];
539
+ i = 1;
540
+ break;
541
+ }
542
+ for( k=0; k<25; k++ )
543
+ if( n == sig[7][k] )
544
+ break;
545
+ oct = 4; // ABC note pitch C is C4 and pitch c is C5
546
+ if( k > 12 ) {
547
+ oct++;
548
+ k -= 12;
549
+ }
550
+ while( p[i] == ',' || p[i] == '\'' ) {
551
+ if( p[i] == ',' )
552
+ oct--;
553
+ else
554
+ oct++;
555
+ i++;
556
+ }
557
+ m[j] = k + 12 * oct;
558
+ }
559
+ return m[0] - m[1];
560
+ }
561
+
562
+ static int abc_transpose(const char *v)
563
+ {
564
+ int i,j,t;
565
+ const char *m = "B", *mv = "";
566
+ t = 0;
567
+ global_octave_shift = 99;
568
+ for( ; *v && *v != ']'; v++ ) {
569
+ if( !SDL_strncasecmp(v,"t=",2) ) {
570
+ v+=2;
571
+ if( *v=='-' ) {
572
+ j = -1;
573
+ v++;
574
+ }
575
+ else j = 1;
576
+ v+=abc_getnumber(v,&i);
577
+ t += i * j;
578
+ global_octave_shift = 0;
579
+ }
580
+ if( !SDL_strncasecmp(v,"octave=",7) ) {
581
+ v+=7;
582
+ if( *v=='-' ) {
583
+ j = -1;
584
+ v++;
585
+ }
586
+ else j = 1;
587
+ v+=abc_getnumber(v,&i);
588
+ t += i * j * 12;
589
+ global_octave_shift = 0;
590
+ }
591
+ if( !SDL_strncasecmp(v,"transpose=",10) ) {
592
+ v+=10;
593
+ if( *v=='-' ) {
594
+ j = -1;
595
+ v++;
596
+ }
597
+ else j = 1;
598
+ v+=abc_getnumber(v,&i);
599
+ t += i * j;
600
+ global_octave_shift = 0;
601
+ }
602
+ if( !SDL_strncasecmp(v,"octave=",7) ) { // used in kv304*.abc
603
+ v+=7;
604
+ if( *v=='-' ) {
605
+ j = -1;
606
+ v++;
607
+ }
608
+ else j = 1;
609
+ v+=abc_getnumber(v,&i);
610
+ t += i * j * 12;
611
+ global_octave_shift = 0;
612
+ }
613
+ if( !SDL_strncasecmp(v,"m=",2) ) {
614
+ v += 2;
615
+ mv = v; // get the pitch for the middle staff line
616
+ while( *v && *v != ' ' && *v != ']' ) v++;
617
+ global_octave_shift = 0;
618
+ }
619
+ if( !SDL_strncasecmp(v,"middle=",7) ) {
620
+ v += 7;
621
+ mv = v; // get the pitch for the middle staff line
622
+ while( *v && *v != ' ' && *v != ']' ) v++;
623
+ global_octave_shift = 0;
624
+ }
625
+ if( !SDL_strncasecmp(v,"clef=",5) )
626
+ v += 5;
627
+ j = 1;
628
+ if( !SDL_strncasecmp(v,"treble",6) ) {
629
+ j = 0;
630
+ v += 6;
631
+ switch( *v ) {
632
+ case '1': v++; m = "d"; break;
633
+ case '2': v++;
634
+ default: m = "B"; break;
635
+ case '3': v++; m = "G"; break;
636
+ case '4': v++; m = "E"; break;
637
+ case '5': v++; m = "C"; break;
638
+ }
639
+ global_octave_shift = 0;
640
+ }
641
+ if( j && !SDL_strncasecmp(v,"bass",4) ) {
642
+ j = 0;
643
+ v += 4;
644
+ switch( *v ) {
645
+ case '1': v++; m = "C"; break;
646
+ case '2': v++; m = "A,"; break;
647
+ case '3': v++; m = "F,"; break;
648
+ case '4': v++;
649
+ default: m = "D,"; break;
650
+ case '5': v++; m = "B,,"; break;
651
+ }
652
+ if( global_octave_shift == 99 )
653
+ global_octave_shift = -2;
654
+ }
655
+ if( j && !SDL_strncasecmp(v,"tenor",5) ) {
656
+ j = 0;
657
+ v += 5;
658
+ switch( *v ) {
659
+ case '1': v++; m = "G"; break;
660
+ case '2': v++; m = "E"; break;
661
+ case '3': v++; m = "C"; break;
662
+ case '4': v++;
663
+ default: m = "A,"; break;
664
+ case '5': v++; m = "F,"; break;
665
+ }
666
+ if( global_octave_shift == 99 )
667
+ global_octave_shift = 1;
668
+ }
669
+ if( j && !SDL_strncasecmp(v,"alto",4) ) {
670
+ j = 0;
671
+ v += 4;
672
+ switch( *v ) {
673
+ case '1': v++; m = "G"; break;
674
+ case '2': v++; m = "E"; break;
675
+ case '3': v++;
676
+ default: m = "C"; break;
677
+ case '4': v++; m = "A,"; break;
678
+ case '5': v++; m = "F,"; break;
679
+ }
680
+ if( global_octave_shift == 99 )
681
+ global_octave_shift = 1;
682
+ }
683
+ if( j && SDL_strchr("+-",*v) && *v && v[1]=='8' ) {
684
+ switch(*v) {
685
+ case '+':
686
+ t += 12;
687
+ break;
688
+ case '-':
689
+ t -= 12;
690
+ break;
691
+ }
692
+ v += 2;
693
+ if( !SDL_strncasecmp(v,"va",2) ) v += 2;
694
+ global_octave_shift = 0;
695
+ j = 0;
696
+ }
697
+ if( j ) {
698
+ while( *v && *v != ' ' && *v != ']' ) v++;
699
+ }
700
+ }
701
+ if( SDL_strlen(mv) > 0 ) // someone set the middle note
702
+ t += abc_interval(mv, m);
703
+ if( global_octave_shift == 99 )
704
+ global_octave_shift = 0;
705
+ return t;
706
+ }
707
+
708
+ // =============================================================================
709
+ static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos)
710
+ // =============================================================================
711
+ {
712
+ ABCTRACK *tr, *prev, *trunused;
713
+ char vc[21];
714
+ int i, trans=0, voiceno=0, instrno = 1, channo = 0;
715
+ for( ; *voice == ' '; voice++ ) ; // skip leading spaces
716
+ for( i=0; i+1 < sizeof(vc) && *voice && *voice != ']' && *voice != '%' && !SDL_isspace(*voice); voice++ ) // can work with inline voice instructions
717
+ vc[i++] = *voice;
718
+ vc[i] = '\0';
719
+ prev = NULL;
720
+ trunused = NULL;
721
+ if( !pos ) trans = abc_transpose(voice);
722
+ for( tr=h->track; tr; tr=tr->next ) {
723
+ if( tr->vno == 0 ) {
724
+ if( !trunused ) trunused = tr; // must reuse mastertrack (h->track) as first
725
+ }
726
+ else {
727
+ if( !SDL_strncasecmp(tr->v, vc, 20) ) {
728
+ if( tr->vpos == pos )
729
+ return tr;
730
+ trans = tr->transpose;
731
+ global_octave_shift = tr->octave_shift;
732
+ voiceno = tr->vno;
733
+ instrno = tr->instr;
734
+ channo = tr->chan;
735
+ }
736
+ }
737
+ prev = tr;
738
+ }
739
+ if( trunused ) {
740
+ tr = trunused;
741
+ if( pos ) {
742
+ tr->vno = voiceno;
743
+ tr->instr = instrno;
744
+ tr->chan = channo;
745
+ }
746
+ else {
747
+ global_voiceno++;
748
+ tr->vno = global_voiceno;
749
+ tr->instr = 1;
750
+ tr->chan = 0;
751
+ }
752
+ tr->vpos = pos;
753
+ tr->tiedvpos = pos;
754
+ SDL_strlcpy(tr->v, vc, 20);
755
+ tr->v[20] = '\0';
756
+ tr->mute = 0;
757
+ tr->transpose = trans;
758
+ tr->octave_shift = global_octave_shift;
759
+ tr->volume = h->track->volume;
760
+ tr->tienote = NULL;
761
+ tr->legato = 0;
762
+ return tr;
763
+ }
764
+ tr = abc_new_track(h, vc, pos);
765
+ if( pos ) {
766
+ tr->vno = voiceno;
767
+ tr->instr = instrno;
768
+ tr->chan = channo;
769
+ }
770
+ tr->transpose = trans;
771
+ tr->octave_shift = global_octave_shift;
772
+ if( prev ) prev->next = tr;
773
+ else h->track = tr;
774
+ return tr;
775
+ }
776
+
777
+ // =============================================================================
778
+ static ABCTRACK *abc_check_track(ABCHANDLE *h, ABCTRACK *tp)
779
+ // =============================================================================
780
+ {
781
+ if( !tp ) {
782
+ tp = abc_locate_track(h, "", 0); // must work for voiceless abc too...
783
+ tp->transpose = h->ktrans;
784
+ }
785
+ return tp;
786
+ }
787
+
788
+ static void abc_add_capo(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
789
+ {
790
+ ABCEVENT *e;
791
+ char d[6];
792
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
793
+ d[cmdflag] = 1;
794
+ d[command] = cmdcapo;
795
+ e = abc_new_event(h, tracktime, d);
796
+ tp->capostart = e;
797
+ abc_add_event(h, tp, e); // do this last (recursion danger)
798
+ }
799
+
800
+ static void abc_add_segno(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
801
+ {
802
+ ABCEVENT *e;
803
+ char d[6];
804
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
805
+ d[cmdflag] = 1;
806
+ d[command] = cmdsegno;
807
+ e = abc_new_event(h, tracktime, d);
808
+ abc_add_event(h, tp, e);
809
+ }
810
+
811
+ static void abc_add_coda(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
812
+ {
813
+ ABCEVENT *e;
814
+ char d[6];
815
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
816
+ d[cmdflag] = 1;
817
+ d[command] = cmdcoda;
818
+ e = abc_new_event(h, tracktime, d);
819
+ abc_add_event(h, tp, e);
820
+ }
821
+
822
+ static void abc_add_fine(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
823
+ {
824
+ ABCEVENT *e;
825
+ char d[6];
826
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
827
+ d[cmdflag] = 1;
828
+ d[command] = cmdfine;
829
+ e = abc_new_event(h, tracktime, d);
830
+ abc_add_event(h, tp, e);
831
+ }
832
+
833
+ static void abc_add_tocoda(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
834
+ {
835
+ ABCEVENT *e;
836
+ char d[6];
837
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
838
+ d[cmdflag] = 1;
839
+ d[command] = cmdtocoda;
840
+ e = abc_new_event(h, tracktime, d);
841
+ abc_add_event(h, tp, e);
842
+ }
843
+
844
+ // first track is dirigent, remove all control events from other tracks
845
+ // to keep the information where the events should be relative to note events
846
+ // in the same tick the ticks are octated and four added for note events
847
+ // the control events that come before the note events get a decremented tick,
848
+ // those that come after get an incremented tick, for example:
849
+ // ctrl ctrl note ctrl ctrl note
850
+ // original: t t t t t+1 t+1
851
+ // recoded: 8t+1 8t+2 8t+4 8t+5 8t+11 8t+12
852
+ static void abc_remove_unnecessary_events(ABCHANDLE *h)
853
+ {
854
+ ABCTRACK *tp,*ptp;
855
+ ABCEVENT *ep, *el;
856
+ uint32_t ct, et;
857
+ int d;
858
+ ptp = NULL;
859
+ for( tp=h->track; tp; tp=tp->next ) {
860
+ el = NULL;
861
+ ep = tp->head;
862
+ ct = 0;
863
+ d = -3;
864
+ while( ep ) {
865
+ et = ep->tracktick;
866
+ ep->tracktick <<= 3;
867
+ ep->tracktick += 4;
868
+ if( ep->flg == 1 ) {
869
+ ep->tracktick += d;
870
+ d++;
871
+ if( d == 0 ) d = -1;
872
+ if( d == 4 ) d = 3;
873
+ if( tp!=h->track ) ep->cmd = cmdhide;
874
+ switch( ep->cmd ) {
875
+ case cmdhide:
876
+ case cmdsync:
877
+ if( el ) {
878
+ el->next = ep->next;
879
+ if( !el->next )
880
+ tp->tail = el;
881
+ _mm_free(h->trackhandle,ep);
882
+ ep = el->next;
883
+ }
884
+ else {
885
+ tp->head = ep->next;
886
+ if( !tp->head )
887
+ tp->tail = NULL;
888
+ _mm_free(h->trackhandle,ep);
889
+ ep = tp->head;
890
+ }
891
+ break;
892
+ default:
893
+ el = ep;
894
+ ep = ep->next;
895
+ break;
896
+ }
897
+ }
898
+ else {
899
+ el = ep;
900
+ ep = ep->next;
901
+ d = 1;
902
+ }
903
+ if( et > ct )
904
+ d = -3;
905
+ ct = et;
906
+ }
907
+ if( !tp->head ) { // no need to keep empty tracks...
908
+ if( ptp ) {
909
+ ptp->next = tp->next;
910
+ _mm_free(h->trackhandle,tp);
911
+ tp = ptp;
912
+ }
913
+ else if (tp->next) {
914
+ h->track = tp->next;
915
+ _mm_free(h->trackhandle,tp);
916
+ tp = h->track;
917
+ } else {
918
+ break;
919
+ }
920
+ }
921
+ ptp = tp; // remember previous track
922
+ }
923
+ }
924
+
925
+ // set ticks back, and handle partbreaks
926
+ static void abc_retick_events(ABCHANDLE *h)
927
+ {
928
+ ABCTRACK *tp;
929
+ ABCEVENT *ep;
930
+ uint32_t et, tt=0, at = abcticks(64 * h->speed);
931
+ for( tp=h->track; tp; tp=tp->next ) {
932
+ // make ticks relative
933
+ tt = 0;
934
+ for( ep=tp->head; ep; ep=ep->next ) {
935
+ et = ep->tracktick >> 3;
936
+ ep->tracktick = et - tt;
937
+ tt = et;
938
+ }
939
+ // make ticks absolute again, skipping no-op partbreaks
940
+ tt = 0;
941
+ for( ep=tp->head; ep; ep=ep->next ) {
942
+ ep->tracktick += tt;
943
+ tt = ep->tracktick;
944
+ if( ep->flg == 1 && ep->cmd == cmdpartbrk ) {
945
+ if( tt % at ) {
946
+ tt += at;
947
+ tt /= at;
948
+ tt *= at;
949
+ ep->tracktick -= abcticks(h->speed); // break plays current row
950
+ }
951
+ else ep->cmd = cmdhide;
952
+ }
953
+ }
954
+ }
955
+ }
956
+
957
+ // make sure every track has the control events it needs, this way it is not
958
+ // necessary to have redundant +segno+ +D.C.+ etc in the voices, the first voice
959
+ // is the master, it is pointed to by the member 'track' in the ABCHANDLE
960
+ static void abc_synchronise_tracks(ABCHANDLE *h)
961
+ {
962
+ ABCTRACK *tp;
963
+ uint32_t tm; // tracktime in master
964
+ ABCEVENT *em, *es, *et, *ec; // events in master, slave, slave temporary and copied event
965
+ if( !h || !h->track ) return;
966
+ abc_remove_unnecessary_events(h);
967
+ for( tp = h->track->next; tp; tp = tp->next ) {
968
+ for( em=h->track->head; em; em=em->next ) {
969
+ if( em->flg == 1 ) { // some kind of control event
970
+ switch( em->cmd ) {
971
+ case cmdchord:
972
+ case cmdhide:
973
+ case cmdtempo:
974
+ case cmdsync:
975
+ break;
976
+ default: // check to see if copy is necessary
977
+ ec = abc_copy_event(h, em);
978
+ tm = em->tracktick;
979
+ es = tp->head; // allways search from the begin...
980
+ for( et=es; et && et->tracktick <= tm; et=et->next )
981
+ es = et;
982
+ if( es == NULL || es->tracktick > tm ) { // special case: head of track
983
+ ec->next = es;
984
+ tp->head = ec;
985
+ }
986
+ else {
987
+ ec->next = es->next;
988
+ es->next = ec;
989
+ }
990
+ break;
991
+ }
992
+ }
993
+ }
994
+ }
995
+ abc_retick_events(h);
996
+ }
997
+
998
+ static void abc_add_event(ABCHANDLE *h, ABCTRACK *tp, ABCEVENT *e)
999
+ {
1000
+ if( !tp->capostart ) abc_add_capo(h, tp, global_songstart);
1001
+ if( tp->tail ) {
1002
+ tp->tail->next = e;
1003
+ tp->tail = e;
1004
+ }
1005
+ else {
1006
+ tp->head = e;
1007
+ tp->tail = e;
1008
+ }
1009
+ }
1010
+
1011
+ static void abc_add_partbreak(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
1012
+ {
1013
+ ABCEVENT *e;
1014
+ char d[6];
1015
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
1016
+ d[cmdflag] = 1;
1017
+ d[command] = cmdpartbrk;
1018
+ e = abc_new_event(h, tracktime, d);
1019
+ abc_add_event(h, tp, e);
1020
+ }
1021
+
1022
+ static void abc_add_tempo_event(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int tempo)
1023
+ {
1024
+ ABCEVENT *e;
1025
+ char d[6];
1026
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
1027
+ d[cmdflag] = 1;
1028
+ d[command] = cmdtempo;
1029
+ e = abc_new_event(h, tracktime, d);
1030
+ e->lpar = tempo;
1031
+ abc_add_event(h, tp, e);
1032
+ }
1033
+
1034
+ static void abc_add_noteoff(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
1035
+ {
1036
+ ABCEVENT *e;
1037
+ char d[6];
1038
+ d[note] = 0;
1039
+ d[octave] = 0;
1040
+ d[smpno] = pat_gmtosmp(tp->instr);
1041
+ d[volume] = 0;
1042
+ d[effect] = 0;
1043
+ d[effoper] = 0;
1044
+ e = abc_new_event(h, tracktime, d);
1045
+ abc_add_event(h, tp, e);
1046
+ }
1047
+
1048
+ static int abc_dynamic_volume(ABCTRACK *tp, uint32_t tracktime, int vol)
1049
+ {
1050
+ uint32_t slidetime;
1051
+ int voldelta;
1052
+ if( tp->mute ) return 0;
1053
+ if( tp->slidevol == 0 ) return vol;
1054
+ if( tracktime < tp->slidevoltime ) return vol;
1055
+ slidetime = modticks(tracktime - tp->slidevoltime);
1056
+ voldelta = (slidetime * 15) / 64 / 6; // slide from say mf up to f in one pattern's time
1057
+ if( tp->slidevol > -2 && voldelta > 15 ) voldelta = 15; // never to much dynamics
1058
+ if( tp->slidevol > 0 ) vol += voldelta;
1059
+ else vol -= voldelta;
1060
+ if( vol < 2 ) vol = 2; // xmms divides this by 2....
1061
+ if( vol > 127 ) vol = 127;
1062
+ return vol;
1063
+ }
1064
+
1065
+ static void abc_track_untie_short_chordnotes(ABCHANDLE *h)
1066
+ {
1067
+ ABCTRACK *tp;
1068
+ int vn;
1069
+ tp = h->tp;
1070
+ vn = tp->vno;
1071
+ for( tp = h->track; tp; tp = tp->next )
1072
+ if( tp != h->tp && tp->vno == vn && tp->tienote ) {
1073
+ abc_message("short notes in chord can not be tied:\n%s", h->line);
1074
+ tp->tienote = 0;
1075
+ }
1076
+ }
1077
+
1078
+ static void abc_track_clear_tiednote(ABCHANDLE *h)
1079
+ {
1080
+ ABCTRACK *tp;
1081
+ int vn;
1082
+ tp = h->tp;
1083
+ vn = tp->vno;
1084
+ for( tp = h->track; tp; tp = tp->next )
1085
+ if( tp->vno == vn ) tp->tienote = 0;
1086
+ }
1087
+
1088
+ static void abc_track_clear_tiedvpos(ABCHANDLE *h)
1089
+ {
1090
+ ABCTRACK *tp;
1091
+ int vn;
1092
+ tp = h->tp;
1093
+ vn = tp->vno;
1094
+ for( tp = h->track; tp; tp = tp->next )
1095
+ if( tp->vno == vn ) tp->tiedvpos = tp->vpos;
1096
+ }
1097
+
1098
+ static ABCTRACK *abc_track_with_note_tied(ABCHANDLE *h, uint32_t tracktime, int n, int oct)
1099
+ {
1100
+ int vn, vp;
1101
+ ABCTRACK *tp;
1102
+ ABCEVENT *e;
1103
+ tp = h->tp;
1104
+ vn = tp->vno;
1105
+ vp = tp->vpos;
1106
+ for( tp = h->track; tp; tp = tp->next ) {
1107
+ if( tp->vno == vn ) {
1108
+ e = tp->tienote;
1109
+ if( e && e->tracktick < tracktime
1110
+ && e->par[octave] == oct && SDL_abs(e->par[note] - n) < 3 ) {
1111
+ if( tp->vpos != vp ) tp->tiedvpos = vp;
1112
+ h->tp = tp;
1113
+ return tp;
1114
+ }
1115
+ }
1116
+ }
1117
+ tp = h->tp;
1118
+ vp = tp->tiedvpos;
1119
+ if( tp->vpos != vp ) {
1120
+ // chord note track already returned in previous call
1121
+ for( tp = h->track; tp; tp = tp->next ) {
1122
+ if( tp->vno == vn && tp->vpos == vp ) {
1123
+ tp->tiedvpos = h->tp->vpos;
1124
+ h->tp = tp;
1125
+ return tp;
1126
+ }
1127
+ }
1128
+ }
1129
+ return h->tp;
1130
+ }
1131
+
1132
+ static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktime, char *barkey, int vol, ABCEVENT_X_EFFECT fx, int fxop)
1133
+ {
1134
+ ABCEVENT *e;
1135
+ ABCTRACK *tp;
1136
+ int i,j,k;
1137
+ int n,oct;
1138
+ char d[6];
1139
+ tp = h->tp;
1140
+ switch(ch) {
1141
+ case '^':
1142
+ if( p[0] == '^' ) {
1143
+ n = p[1];
1144
+ i = 2;
1145
+ ch = 'x';
1146
+ }
1147
+ else {
1148
+ n = p[0];
1149
+ i = 1;
1150
+ }
1151
+ break;
1152
+ case '_':
1153
+ if( p[0] == '_' ) {
1154
+ n = p[1];
1155
+ i = 2;
1156
+ ch = 'b';
1157
+ }
1158
+ else {
1159
+ n = p[0];
1160
+ i = 1;
1161
+ }
1162
+ break;
1163
+ case '=':
1164
+ n = p[0];
1165
+ i = 1;
1166
+ break;
1167
+ default:
1168
+ n = ch;
1169
+ i = 0;
1170
+ break;
1171
+ }
1172
+ for( k=0; k<51; k++ ) {
1173
+ if( n == barkey[k] )
1174
+ break;
1175
+ }
1176
+ j = k;
1177
+ if( k > 24 )
1178
+ k -= 25; // had something like A# over Bb key F signature....
1179
+ if( i ) {
1180
+ // propagate accidentals if necessary
1181
+ // DON'T do redundant accidentals they're always relative to C-scale
1182
+ for( k=0; k<25; k++ ) {
1183
+ if( n == sig[7][k] )
1184
+ break;
1185
+ }
1186
+ if( k < 25 ) { // only do real notes...
1187
+ switch(ch) {
1188
+ case 'x':
1189
+ k++;
1190
+ case '^':
1191
+ k++;
1192
+ break;
1193
+ case 'b':
1194
+ k--;
1195
+ case '_':
1196
+ k--;
1197
+ break;
1198
+ case '=':
1199
+ break;
1200
+ }
1201
+ if( j < 25 ) // was it not A# over Bb?
1202
+ barkey[j] = ' ';
1203
+ barkey[k] = n;
1204
+ }
1205
+ }
1206
+ oct = 3; // ABC note pitch C is C4 and pitch c is C5
1207
+ if( k < 25 ) {
1208
+ k += tp->transpose;
1209
+ while( k > 12 ) {
1210
+ oct++;
1211
+ k -= 12;
1212
+ }
1213
+ while( k < 0 ) {
1214
+ oct--;
1215
+ k += 12;
1216
+ }
1217
+ d[note] = 23 + k; // C0 is midi notenumber 24
1218
+ }
1219
+ else
1220
+ d[note] = 0; // someone has doen ^X3 or something like it...
1221
+ while( p[i] && SDL_strchr(",'",p[i]) ) {
1222
+ if( p[i]==',' ) oct--;
1223
+ else oct++;
1224
+ i++;
1225
+ tp->octave_shift = 0; // forget we ever had to look at it
1226
+ }
1227
+ if( tp->octave_shift )
1228
+ tp->transpose += 12 * tp->octave_shift;
1229
+ oct += tp->octave_shift;
1230
+ tp->octave_shift = 0; // after the first note we never have to look at it again
1231
+ if( oct < 0 ) oct = 0;
1232
+ if( oct > 9 ) oct = 9;
1233
+ d[octave] = oct;
1234
+ d[smpno] = pat_gmtosmp(tp->instr);
1235
+ d[volume] = abc_dynamic_volume(tp, tracktime, vol);
1236
+ d[effect] = fx; // effect
1237
+ d[effoper] = fxop;
1238
+ tp = abc_track_with_note_tied(h, tracktime, d[note], oct);
1239
+ if( tp->tienote ) {
1240
+ if( tp->tienote->par[note] != d[note] ) {
1241
+ if( SDL_abs(tp->tienote->par[note] - d[note]) < 3 ) {
1242
+ // may be tied over bar symbol, recover local accidental to barkey
1243
+ k = tp->tienote->par[note] - 23 - tp->transpose;
1244
+ while( k < 0 ) k += 12;
1245
+ while( k > 12 ) k -= 12;
1246
+ if( (IsUpper(n) && barkey[k+12] == ' ') || (IsLower(n) && barkey[k] == ' ') ) {
1247
+ barkey[j] = ' ';
1248
+ if( IsUpper(n) )
1249
+ barkey[k] = n;
1250
+ else
1251
+ barkey[k+12] = n;
1252
+ d[note] = tp->tienote->par[note];
1253
+ d[octave] = tp->tienote->par[octave];
1254
+ }
1255
+ }
1256
+ }
1257
+ }
1258
+ if( tp->tienote
1259
+ && tp->tienote->par[note] == d[note]
1260
+ && tp->tienote->par[octave] == d[octave] ) {
1261
+ for( e = tp->tienote; e; e = e->next ) {
1262
+ if( e->par[note] == 0 && e->par[octave] == 0 ) { // undo noteoff
1263
+ e->flg = 1;
1264
+ e->cmd = cmdhide;
1265
+ e->lpar = 0;
1266
+ break;
1267
+ }
1268
+ }
1269
+ tp->tienote->tiednote = 1; // mark him for the pattern writers
1270
+ for( j=i; SDL_isdigit(p[j]) || p[j]=='/'; j++ ) ; // look ahead to see if this one is tied too
1271
+ if( p[j] != '-' ) // is this note tied too?
1272
+ tp->tienote = NULL; // if not the tie ends here...
1273
+ return i;
1274
+ }
1275
+ tp->tienote = NULL;
1276
+ if( tp->tail
1277
+ && tp->tail->tracktick == tracktime
1278
+ && tp->tail->par[note] == 0
1279
+ && tp->tail->par[octave] == 0 ) {
1280
+ for( j=0; j<6; j++ )
1281
+ tp->tail->par[j] = d[j];
1282
+ }
1283
+ else {
1284
+ e = abc_new_event(h, tracktime, d);
1285
+ abc_add_event(h, tp, e);
1286
+ }
1287
+ if( i > 0 && p[i-1] == '"' ) {
1288
+ i--; // someone coded a weird note like ^"E"
1289
+ abc_message("strange note encountered scanning %s", h->line);
1290
+ }
1291
+ return i;
1292
+ }
1293
+
1294
+ static void abc_add_dronenote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol)
1295
+ {
1296
+ ABCEVENT *e;
1297
+ int j,k;
1298
+ int oct;
1299
+ char d[6];
1300
+ oct = -1; // ABC note pitch C is C4 and pitch c is C5
1301
+ k = nnum + 1;
1302
+ while( k > 12 ) {
1303
+ oct++;
1304
+ k -= 12;
1305
+ }
1306
+ while( k < 0 ) {
1307
+ oct--;
1308
+ k += 12;
1309
+ }
1310
+ if( oct < 0 ) oct = 0;
1311
+ d[note] = 23 + k; // C0 is midi notenumber 24
1312
+ d[octave] = oct;
1313
+ d[smpno] = pat_gmtosmp(tp->instr);
1314
+ d[volume] = abc_dynamic_volume(tp, tracktime, vol);
1315
+ d[effect] = 0; // effect
1316
+ d[effoper] = 0;
1317
+ if( tp->tail
1318
+ && tp->tail->tracktick == tracktime
1319
+ && tp->tail->par[note] == 0
1320
+ && tp->tail->par[octave] == 0 ) {
1321
+ for( j=0; j<6; j++ )
1322
+ tp->tail->par[j] = d[j];
1323
+ }
1324
+ else {
1325
+ e = abc_new_event(h, tracktime, d);
1326
+ abc_add_event(h, tp, e);
1327
+ }
1328
+ }
1329
+
1330
+ static void abc_add_chordnote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol)
1331
+ {
1332
+ abc_add_dronenote(h, tp, tracktime, nnum + 23, tp->mute? 0: vol);
1333
+ }
1334
+
1335
+ static void abc_add_drumnote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol)
1336
+ {
1337
+ abc_add_dronenote(h, tp, tracktime, nnum, tp->mute? 0: vol);
1338
+ }
1339
+
1340
+ static void abc_add_variant_start(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int n)
1341
+ {
1342
+ ABCEVENT *e;
1343
+ char d[6];
1344
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
1345
+ d[cmdflag] = 1;
1346
+ d[command] = cmdvariant;
1347
+ e = abc_new_event(h, tracktime, d);
1348
+ e->lpar = 1<<n;
1349
+ abc_add_event(h, tp, e);
1350
+ }
1351
+
1352
+ static void abc_add_variant_choise(ABCTRACK *tp, int n)
1353
+ {
1354
+ tp->tail->lpar |= 1<<n;
1355
+ }
1356
+
1357
+ static void abc_add_chord(const char *p, ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
1358
+ {
1359
+ ABCEVENT *e;
1360
+ char d[6];
1361
+ char s[8];
1362
+ int i;
1363
+ const char *n = " C D EF G A Bc d ef g a b";
1364
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
1365
+ d[cmdflag] = 1;
1366
+ d[command] = cmdchord;
1367
+ if( p[0] == '(' ) p++; // chord between parens like: (C)
1368
+ for( i=0; n[i]; i++ )
1369
+ if( *p == n[i] ) {
1370
+ d[chordnote] = i;
1371
+ break;
1372
+ }
1373
+ p++;
1374
+ switch(*p) {
1375
+ case 'b':
1376
+ d[chordnote]--;
1377
+ p++;
1378
+ break;
1379
+ case '#':
1380
+ d[chordnote]++;
1381
+ p++;
1382
+ break;
1383
+ }
1384
+ d[chordbase] = d[chordnote];
1385
+ for( i=0; i < sizeof(s) - 1 && p[i] && p[i] != '"' && p[i] != '/' && p[i] != '(' && p[i] != ')' && p[i] != ' '; i++ ) s[i] = p[i];
1386
+ s[i] = '\0';
1387
+ p = &p[i];
1388
+ if( *p=='/' ) {
1389
+ p++;
1390
+ for( i=0; n[i]; i++ )
1391
+ if( *p == n[i] ) {
1392
+ d[chordbase] = i;
1393
+ break;
1394
+ }
1395
+ p++;
1396
+ switch(*p) {
1397
+ case 'b':
1398
+ d[chordbase]--;
1399
+ p++;
1400
+ break;
1401
+ case '#':
1402
+ d[chordbase]++;
1403
+ p++;
1404
+ break;
1405
+ }
1406
+ }
1407
+ for( i=0; i<chordsnamed; i++ )
1408
+ if( !SDL_strcmp(s, chordname[i]) ) {
1409
+ d[chordnum] = i;
1410
+ break;
1411
+ }
1412
+ if( i==chordsnamed ) {
1413
+ abc_message("Failure: unrecognized chordname %s",s);
1414
+ return;
1415
+ }
1416
+ e = abc_new_event(h, tracktime, d);
1417
+ abc_add_event(h, tp, e);
1418
+ }
1419
+
1420
+ static void abc_add_setloop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
1421
+ {
1422
+ ABCEVENT *e;
1423
+ char d[6];
1424
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
1425
+ d[cmdflag] = 1;
1426
+ d[command] = cmdloop;
1427
+ e = abc_new_event(h, tracktime, d);
1428
+ abc_add_event(h, tp, e);
1429
+ }
1430
+
1431
+ static void abc_fade_track(ABCTRACK *tp, ABCEVENT *e)
1432
+ {
1433
+ while(e) {
1434
+ if( e->flg != 1 && e->par[note] != 0 )
1435
+ e->par[volume] = abc_dynamic_volume(tp, e->tracktick, e->par[volume]);
1436
+ e = e->next;
1437
+ }
1438
+ }
1439
+
1440
+ static void abc_add_setjumploop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, ABCEVENT_JUMPTYPE j)
1441
+ {
1442
+ ABCEVENT *e;
1443
+ char d[8];
1444
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
1445
+ d[cmdflag] = 1;
1446
+ d[command] = cmdjump;
1447
+ d[jumptype] = j;
1448
+ e = abc_new_event(h, tracktime, d);
1449
+ abc_add_event(h, tp, e);
1450
+ }
1451
+
1452
+ static void abc_add_sync(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime)
1453
+ {
1454
+ ABCEVENT *e;
1455
+ char d[6];
1456
+ e = tp->tail;
1457
+ if( e && e->tracktick == tracktime ) return;
1458
+ if( e && e->flg == 1 && e->cmd == cmdsync ) {
1459
+ e->tracktick = tracktime;
1460
+ return;
1461
+ }
1462
+ d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0;
1463
+ d[cmdflag] = 1;
1464
+ d[command] = cmdsync;
1465
+ e = abc_new_event(h, tracktime, d);
1466
+ abc_add_event(h, tp, e);
1467
+ }
1468
+
1469
+ static void abc_add_gchord_syncs(ABCHANDLE *h, ABCTRACK *tpc, uint32_t tracktime)
1470
+ {
1471
+ ABCTRACK *tp;
1472
+ int i;
1473
+ for( i = GCHORDBPOS; i < DRUMPOS; i++ ) {
1474
+ tp = abc_locate_track(h, tpc->v, i);
1475
+ abc_add_sync(h,tp,tracktime);
1476
+ }
1477
+ }
1478
+
1479
+ static void abc_add_drum_sync(ABCHANDLE *h, ABCTRACK *tpr, uint32_t tracktime)
1480
+ {
1481
+ ABCTRACK *tp;
1482
+ tp = abc_locate_track(h, tpr->v, DRUMPOS);
1483
+ abc_add_sync(h,tp,tracktime);
1484
+ }
1485
+
1486
+ static int abc_getnumber(const char *p, int *number)
1487
+ {
1488
+ int i,h;
1489
+ i = 0;
1490
+ h = 0;
1491
+ while( SDL_isdigit(p[i]) ) {
1492
+ h = 10 * h + p[i] - '0';
1493
+ i++;
1494
+ }
1495
+ if( i==0 )
1496
+ *number = 1;
1497
+ else
1498
+ *number = h;
1499
+ return i;
1500
+ }
1501
+
1502
+ static int abc_getexpr(const char *p, int *number)
1503
+ {
1504
+ int i, term, total;
1505
+ i = 0;
1506
+ while( SDL_isspace(p[i]) )
1507
+ i++;
1508
+ if( p[i] == '(' ) {
1509
+ i += abc_getexpr(p+i+1, number);
1510
+ while( p[i] && (p[i] != ')') )
1511
+ i++;
1512
+ return i;
1513
+ }
1514
+ i += abc_getnumber(p+i, &total);
1515
+ while( SDL_isspace(p[i]) )
1516
+ i++;
1517
+ while( p[i] == '+' ) {
1518
+ i += 1 + abc_getexpr(p+i+1, &term);
1519
+ total += term;
1520
+ while( SDL_isspace(p[i]) )
1521
+ i++;
1522
+ }
1523
+ *number = total;
1524
+ return i;
1525
+ }
1526
+
1527
+ static int abc_notelen(const char *p, int *len, int *div)
1528
+ {
1529
+ int i,h,k;
1530
+ i = abc_getnumber(p,len);
1531
+ h = 1;
1532
+ while( p[i] == '/' ) {
1533
+ h *= 2;
1534
+ i++;
1535
+ }
1536
+ if( SDL_isdigit(p[i]) ) {
1537
+ h /= 2;
1538
+ i += abc_getnumber(p+i,&k);
1539
+ }
1540
+ else k = 1;
1541
+ *div = h * k;
1542
+ return i;
1543
+ }
1544
+
1545
+ static int abc_brokenrithm(const char *p, int *nl, int *nd, int *b, int hornpipe)
1546
+ {
1547
+ switch( *b ) {
1548
+ case '<':
1549
+ *nl *= 3;
1550
+ *nd *= 2;
1551
+ hornpipe = 0;
1552
+ break;
1553
+ case '>':
1554
+ *nd *= 2;
1555
+ hornpipe = 0;
1556
+ break;
1557
+ }
1558
+ *b = *p;
1559
+ switch( *b ) {
1560
+ case '>':
1561
+ *nl *= 3;
1562
+ *nd *= 2;
1563
+ return 1;
1564
+ case '<':
1565
+ *nd *= 2;
1566
+ return 1;
1567
+ default:
1568
+ *b = 0;
1569
+ break;
1570
+ }
1571
+ if( hornpipe ) { // still true then make 1/8 notes broken rithme
1572
+ if( *nl == 1 && *nd == 1 ) {
1573
+ *b = '>';
1574
+ *nl = 3;
1575
+ *nd = 2;
1576
+ }
1577
+ }
1578
+ return 0;
1579
+ }
1580
+
1581
+ // put p notes in the time q for the next r notes
1582
+ static int abc_tuplet(int *nl, int *nd, int p, int q, int r)
1583
+ {
1584
+ if( !r ) return 0;
1585
+ *nl *= q;
1586
+ *nd *= p;
1587
+ return r - 1;
1588
+ }
1589
+
1590
+ // evaluate [Q:"string" n1/m1 n2/m2 n3/m3 n4/m4=bpm "string"]
1591
+ // minimal form [Q:"string"]
1592
+ // most used form [Q: 1/4=120]
1593
+ static int abc_extract_tempo(const char *p, int invoice)
1594
+ {
1595
+ int nl, nd, ns, in, tempo;
1596
+ int nl1=0, nd1, notes, state;
1597
+ const char *q;
1598
+ in = 0;
1599
+ nl = 0;
1600
+ nd = 1;
1601
+ ns = 120;
1602
+ notes = 0;
1603
+ state = 0;
1604
+ for( q=p; *q; q++ ) {
1605
+ if( in ) {
1606
+ if( *q=='"' )
1607
+ in = 0;
1608
+ }
1609
+ else {
1610
+ if( *q == ']' ) break;
1611
+ switch( *q ) {
1612
+ case '"':
1613
+ in = 1;
1614
+ break;
1615
+ case '/':
1616
+ notes++;
1617
+ state = 1;
1618
+ nl1 = ns;
1619
+ break;
1620
+ case '=':
1621
+ break;
1622
+ default:
1623
+ if( SDL_isdigit(*q) ) {
1624
+ if( state ) {
1625
+ q+=abc_getnumber(q,&nd1)-1;
1626
+ state = 0;
1627
+ nl = nl * nd1 + nl1 * nd;
1628
+ nd = nd * nd1;
1629
+ }
1630
+ else
1631
+ q+=abc_getnumber(q,&ns)-1;
1632
+ }
1633
+ break;
1634
+ }
1635
+ }
1636
+ }
1637
+ if( !notes ) {
1638
+ nl = 1;
1639
+ nd = 4;
1640
+ }
1641
+ if( !nd ) tempo = 120;
1642
+ else tempo = ns * nl * 4 / nd; // mod tempo is really BPM where one B is equal to a quartnote
1643
+ if( tempo <= 0 )
1644
+ tempo = 120;
1645
+ if( invoice ) {
1646
+ nl = global_tempo_factor;
1647
+ nd = global_tempo_divider;
1648
+ }
1649
+ global_tempo_factor = 1;
1650
+ global_tempo_divider = 1;
1651
+ while( tempo/global_tempo_divider > 255 )
1652
+ global_tempo_divider++;
1653
+ tempo /= global_tempo_divider;
1654
+ while( tempo * global_tempo_factor < 256 )
1655
+ global_tempo_factor++;
1656
+ global_tempo_factor--;
1657
+ tempo *= global_tempo_factor;
1658
+ if( tempo * 3 < 512 ) {
1659
+ global_tempo_factor *= 3;
1660
+ global_tempo_divider *= 2;
1661
+ tempo = (tempo * 3) / 2;
1662
+ }
1663
+ if( invoice ) {
1664
+ if( nl != global_tempo_factor || nd != global_tempo_divider ) {
1665
+ ns = (tempo * nl * global_tempo_divider) / (nd * global_tempo_factor);
1666
+ if( ns > 31 && ns < 256 ) {
1667
+ tempo = ns;
1668
+ global_tempo_factor = nl;
1669
+ global_tempo_divider = nd;
1670
+ }
1671
+ else
1672
+ abc_message("Failure: inconvenient tempo change in middle of voice (%s)", p);
1673
+ }
1674
+ }
1675
+ return tempo;
1676
+ }
1677
+
1678
+ static void abc_set_parts(char **d, char *p)
1679
+ {
1680
+ int i,k,m,n;
1681
+ size_t j, size;
1682
+ char *q;
1683
+ if( *d ) SDL_free(*d);
1684
+ *d = 0;
1685
+ if( !p ) return;
1686
+ for( i=0; p[i] && p[i] != '%'; i++ ) {
1687
+ if( !SDL_strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ().0123456789 ",p[i]) ) {
1688
+ abc_message("invalid characters in part string scanning P:%s", p);
1689
+ return;
1690
+ }
1691
+ }
1692
+ // decode constructs like "((AB)2.(CD)2)3.(AB)E2" to "ABABCDCDABABCDCDABABCDCDABEE"
1693
+ // first compute needed storage...
1694
+ j=0;
1695
+ k=0;
1696
+ for( i=0; p[i] && p[i] != '%'; i++ ) {
1697
+ if( IsUpper(p[i]) ) {
1698
+ j++;
1699
+ }
1700
+ if( SDL_isdigit(p[i]) ) {
1701
+ n=abc_getnumber(p+i,&k);
1702
+ if( k == 0 )
1703
+ k = 1;
1704
+ if( p[i-1] == ')' )
1705
+ j *= k; // never mind multiple parens, just take the worst case
1706
+ else
1707
+ j += k-1;
1708
+ i += n-1;
1709
+ }
1710
+ }
1711
+ // even if j overflows above, it will only wrap around and still be okay
1712
+ size = ( j >= INT_MAX )? INT_MAX - 1 : j;
1713
+ q = (char *)_mm_calloc(h, size + 1, sizeof(char)); // enough storage for the worst case
1714
+ // now copy bytes from p to *d, taking parens and digits in account
1715
+ j = 0;
1716
+ for( i=0; p[i] && p[i] != '%' && j < size && i < size; i++ ) {
1717
+ if( SDL_isdigit(p[i]) || IsUpper(p[i]) || p[i] == '(' || p[i] == ')' ) {
1718
+ if( p[i] == ')' ) {
1719
+ for( n=j; n > 0 && q[n-1] != '('; n-- ) ; // find open paren in q
1720
+ // q[n+1] to q[j] contains the substring that must be repeated
1721
+ if( n > 0 ) {
1722
+ for( k = n; k<j; k++ ) q[k-1] = q[k]; // shift to the left...
1723
+ j--;
1724
+ }
1725
+ else {
1726
+ abc_message("Warning: Unbalanced right parens in P: definition %s",p);
1727
+ break;
1728
+ }
1729
+ n = j - n + 1; // number of repeatable characters
1730
+ i += abc_getnumber(p+i+1,&k);
1731
+ while( k-- > 1 ) {
1732
+ for( m=0; m<n; m++ ) {
1733
+ q[j] = q[j-n];
1734
+ j++;
1735
+ }
1736
+ }
1737
+ continue;
1738
+ }
1739
+ if( SDL_isdigit(p[i]) ) {
1740
+ n = abc_getnumber(p+i,&k);
1741
+ i += n - 1;
1742
+ while( k-- > 1 ) {
1743
+ q[j] = q[j-1];
1744
+ j++;
1745
+ }
1746
+ continue;
1747
+ }
1748
+ q[j] = p[i];
1749
+ j++;
1750
+ }
1751
+ }
1752
+ q[j] = '\0';
1753
+ // remove any left over parens
1754
+ for( i=0; i<j; i++ ) {
1755
+ if( q[i] == '(' ) {
1756
+ abc_message("Warning: Unbalanced left parens in P: definition %s",p);
1757
+ for( k=i; k<j; k++ ) q[k] = q[k+1];
1758
+ j--;
1759
+ }
1760
+ }
1761
+ *d = q;
1762
+ }
1763
+
1764
+ static void abc_appendpart(ABCHANDLE *h, ABCTRACK *tp, uint32_t pt1, uint32_t pt2)
1765
+ {
1766
+ ABCEVENT *e, *ec;
1767
+ uint32_t dt;
1768
+ dt = tp->tail->tracktick - pt1;
1769
+ for( e=tp->head; e && e->tracktick <= pt2; e=e->next ) {
1770
+ if( e->tracktick >= pt1 ) {
1771
+ if( e->flg != 1 || e->cmd == cmdsync || e->cmd == cmdchord ) {
1772
+ if( e != tp->tail ) {
1773
+ // copy this event at tail
1774
+ ec = abc_copy_event(h,e);
1775
+ ec->tracktick += dt;
1776
+ ec->part = '*';
1777
+ tp->tail->next = ec;
1778
+ tp->tail = ec;
1779
+ }
1780
+ }
1781
+ }
1782
+ }
1783
+ abc_add_sync(h, tp, pt2 + dt); // make sure there is progression...
1784
+ }
1785
+
1786
+ static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime)
1787
+ {
1788
+ ABCEVENT *e;
1789
+ uint32_t dt,et,pt=abcticks(64 * h->speed);
1790
+ if(!h || !h->track || !h->track->head ) return 0;
1791
+ dt = 0;
1792
+ for( e=h->track->head; e && e->tracktick <= tracktime; e=e->next ) {
1793
+ if( e->flg == 1 && e->cmd == cmdpartbrk ) {
1794
+ et = e->tracktick + dt;
1795
+ if( et % pt ) {
1796
+ et += pt;
1797
+ et /= pt;
1798
+ et *= pt;
1799
+ dt = et - e->tracktick;
1800
+ }
1801
+ }
1802
+ }
1803
+ return (tracktime + dt);
1804
+ }
1805
+
1806
+ static int abc_patno(ABCHANDLE *h, uint32_t tracktime)
1807
+ {
1808
+ return modticks(abc_pattracktime(h, tracktime)) / 64 / h->speed;
1809
+ }
1810
+
1811
+ static void abc_stripoff(ABCHANDLE *h, ABCTRACK *tp, uint32_t tt)
1812
+ {
1813
+ ABCEVENT *e1, *e2;
1814
+ e2 = NULL;
1815
+ for( e1 = tp->head; e1 && e1->tracktick <= tt; e1=e1->next )
1816
+ e2 = e1;
1817
+ if( e2 ) {
1818
+ e1 = e2->next;
1819
+ tp->tail = e2;
1820
+ e2->next = NULL;
1821
+ }
1822
+ else {
1823
+ e1 = tp->tail;
1824
+ tp->head = NULL;
1825
+ tp->tail = NULL;
1826
+ }
1827
+ while( e1 ) {
1828
+ e2 = e1->next;
1829
+ _mm_free(h->trackhandle,e1);
1830
+ e1 = e2;
1831
+ }
1832
+ }
1833
+
1834
+ static void abc_keeptiednotes(ABCHANDLE *h, uint32_t fromtime, uint32_t totime) {
1835
+ ABCTRACK *tp;
1836
+ ABCEVENT *e,*n,*f;
1837
+ if( totime <= fromtime ) return;
1838
+ for( tp=h->track; tp; tp=tp->next ) {
1839
+ if( tp->vno ) { // if track is in use...
1840
+ n = NULL;
1841
+ for( e=tp->head; e && e->tracktick < fromtime; e = e->next )
1842
+ if( e->flg != 1 ) n = e; // remember it when it is a note event
1843
+ if( n && n->tiednote ) { // we've a candidate to tie over the break
1844
+ while( e && e->tracktick < totime ) e=e->next; // skip to other part
1845
+ if( e && e->tracktick == totime ) { // if this is on begin row of this part
1846
+ f = NULL;
1847
+ while( !f && e && e->tracktick == totime ) {
1848
+ if( e->flg != 1 ) f = e;
1849
+ e = e->next;
1850
+ }
1851
+ if( f && f->par[note] ) { // pfoeie, we've found a candidate
1852
+ if( SDL_abs(n->par[note] - f->par[note]) < 3 ) { // undo the note on
1853
+ f->flg = 1;
1854
+ f->cmd = cmdhide;
1855
+ f->lpar = 0;
1856
+ }
1857
+ }
1858
+ }
1859
+ }
1860
+ }
1861
+ }
1862
+ }
1863
+
1864
+ static uint32_t abc_fade_tracks(ABCHANDLE *h, char *abcparts, uint32_t ptt[27])
1865
+ {
1866
+ ABCTRACK *tp;
1867
+ ABCEVENT *e0;
1868
+ char *p;
1869
+ int vol;
1870
+ uint32_t pt1, pt2;
1871
+ uint32_t tt;
1872
+ tt = h->track->tail->tracktick;
1873
+ for( tp=h->track->next; tp; tp=tp->next ) {
1874
+ if( !tp->tail ) abc_add_sync(h, tp, tt); // no empty tracks please...
1875
+ if( tp->tail->tracktick > tt ) abc_stripoff(h, tp, tt); // should not happen....
1876
+ if( tp->tail->tracktick < tt ) abc_add_sync(h, tp, tt);
1877
+ }
1878
+ for( tp=h->track; tp; tp=tp->next ) {
1879
+ vol = 127;
1880
+ e0 = tp->tail;
1881
+ if( tp->slidevol != -2 ) {
1882
+ tp->slidevol = -2;
1883
+ tp->slidevoltime = e0->tracktick;
1884
+ }
1885
+ tp->mute = 0; // unmute track for safety, notes in a muted track already have zero volume...
1886
+ while( vol > 5 ) {
1887
+ for( p=abcparts; *p && vol > 5; p++ ) {
1888
+ pt1 = ptt[*p-'A'];
1889
+ pt2 = ptt[*p-'A'+1];
1890
+ abc_appendpart(h, tp, pt1, pt2);
1891
+ vol = abc_dynamic_volume(tp, tp->tail->tracktick, 127);
1892
+ }
1893
+ }
1894
+ abc_fade_track(tp,e0);
1895
+ }
1896
+ return h->track->tail->tracktick;
1897
+ }
1898
+
1899
+ static void abc_song_to_parts(ABCHANDLE *h, char **abcparts, BYTE partp[27][2])
1900
+ {
1901
+ uint32_t starttick;
1902
+ ABCEVENT *e;
1903
+ int i, fading, loop, normal, partno, partsegno, partloop, partcoda, parttocoda, partfine, skip, x, y;
1904
+ int vmask[27],nextp[27];
1905
+ uint32_t ptt[27];
1906
+ char buf[256]; // must be enough, mod's cannot handle more than 240 patterns
1907
+ char *pfade;
1908
+ if( !h || !h->track || !h->track->capostart ) return;
1909
+ SDL_strlcpy(buf,"A",sizeof (buf)); // initialize our temporary array
1910
+ i = 1;
1911
+ loop = 1;
1912
+ partno = 0;
1913
+ partsegno = 0;
1914
+ partloop = 0;
1915
+ partcoda = -1;
1916
+ parttocoda = -1;
1917
+ partfine = -1;
1918
+ starttick = h->track->capostart->tracktick;
1919
+ ptt[0] = starttick;
1920
+ vmask[0] = -1;
1921
+ nextp[0] = 1;
1922
+ for( e=h->track->capostart; e; e=e->next ) {
1923
+ if( e->flg == 1 ) {
1924
+ switch( e->cmd ) {
1925
+ case cmdpartbrk:
1926
+ if( e->tracktick > starttick) {
1927
+ starttick = e->tracktick; // do not make empty parts
1928
+ if( partno < 26 ) {
1929
+ partno++;
1930
+ ptt[partno] = starttick;
1931
+ }
1932
+ if( i < 255 ) buf[i++] = partno+'A';
1933
+ vmask[partno] = -1;
1934
+ nextp[partno] = partno+1;
1935
+ }
1936
+ break;
1937
+ case cmdloop:
1938
+ partloop = partno;
1939
+ loop = 1; // start counting anew...
1940
+ break;
1941
+ case cmdvariant:
1942
+ vmask[partno] = e->lpar;
1943
+ break;
1944
+ case cmdjump:
1945
+ x = 0;
1946
+ fading = 0;
1947
+ normal = 0;
1948
+ skip = 0;
1949
+ pfade = &buf[i];
1950
+ switch( e->par[jumptype] ) {
1951
+ case jumpfade:
1952
+ fading = 1;
1953
+ case jumpnormal:
1954
+ normal = 1;
1955
+ x = partloop;
1956
+ loop++;
1957
+ break;
1958
+ case jumpdsfade:
1959
+ fading = 1;
1960
+ case jumpdasegno:
1961
+ x = partsegno;
1962
+ break;
1963
+ case jumpdcfade:
1964
+ fading = 1;
1965
+ case jumpdacapo:
1966
+ x = 0;
1967
+ break;
1968
+ default:
1969
+ // defaults set above.
1970
+ break;
1971
+ }
1972
+ if( vmask[partno] != -1 ) nextp[partno] = x;
1973
+ if( partno < 26 ) ptt[partno+1] = e->tracktick; // for handling ties over breaks
1974
+ while( x <= partno ) {
1975
+ if( skip == 1 && x == partcoda ) skip = 0;
1976
+ y = !skip;
1977
+ if( y ) {
1978
+ if( !normal ) {
1979
+ if( x == partfine ) skip = 2;
1980
+ if( x == parttocoda ) skip = 1;
1981
+ y = !skip;
1982
+ }
1983
+ if( !(vmask[x] & (1<<loop)) ) y = 0;
1984
+ }
1985
+ if( y ) {
1986
+ if( i < 255 ) buf[i++] = x+'A';
1987
+ if( nextp[x] != x + 1 ) loop++;
1988
+ x = nextp[x];
1989
+ }
1990
+ else
1991
+ x++;
1992
+ }
1993
+ if( fading && partno < 25 && i < 254 ) { // add single part with fading tracks
1994
+ partno++;
1995
+ ptt[partno] = e->tracktick;
1996
+ buf[i] = '\0'; // close up pfade with zero byte
1997
+ starttick = abc_fade_tracks(h, pfade, ptt);
1998
+ buf[i++] = partno+'A';
1999
+ partno++;
2000
+ ptt[partno] = starttick;
2001
+ buf[i++] = partno+'A'; // one extra to throw away...
2002
+ e = h->track->tail; // this is the edge of the world captain...
2003
+ }
2004
+ break;
2005
+ case cmdtocoda:
2006
+ parttocoda = partno;
2007
+ break;
2008
+ case cmdcoda:
2009
+ partcoda = partno;
2010
+ break;
2011
+ case cmdfine:
2012
+ partfine = partno;
2013
+ break;
2014
+ case cmdsegno:
2015
+ partsegno = partno;
2016
+ break;
2017
+ }
2018
+ }
2019
+ e->part = partno+'a'; // small caps for generated parts...
2020
+ }
2021
+ i--; // strip off last partno
2022
+ if( partno > 0 ) partno--;
2023
+ buf[i] = '\0';
2024
+ if( i > 1 ) {
2025
+ for( i=1; buf[i]; i++ ) {
2026
+ if( buf[i] != buf[i-1] + 1 ) {
2027
+ x = buf[i-1] - 'A';
2028
+ y = buf[i] - 'A';
2029
+ abc_keeptiednotes(h, ptt[x+1], ptt[y]);
2030
+ }
2031
+ }
2032
+ }
2033
+ starttick = h->track->tail->tracktick;
2034
+ ptt[partno+1] = starttick;
2035
+ for( i=0; i<=partno; i++ ) {
2036
+ partp[i][0] = abc_patno(h, ptt[i]);
2037
+ partp[i][1] = abc_patno(h, ptt[i+1]);
2038
+ }
2039
+ // calculate end point of last part
2040
+ starttick = abc_pattracktime(h, starttick);
2041
+ if( starttick % abcticks(64 * h->speed) )
2042
+ partp[partno][1]++;
2043
+ abc_set_parts(abcparts, buf);
2044
+ }
2045
+
2046
+ // =====================================================================================
2047
+ static char *abc_fgets(MMFILE *mmfile, char buf[], unsigned int bufsz)
2048
+ // =====================================================================================
2049
+ {
2050
+ if( mmfeof(mmfile) ) return NULL;
2051
+ mmfgets(buf,bufsz,mmfile);
2052
+ return buf;
2053
+ }
2054
+
2055
+ // =====================================================================================
2056
+ static char *abc_fgetbytes(MMFILE *mmfile, char buf[], unsigned int bufsz)
2057
+ // =====================================================================================
2058
+ {
2059
+ unsigned int i;
2060
+ long pos;
2061
+ if( mmfeof(mmfile) ) return NULL;
2062
+ for( i=0; i<bufsz-2; i++ ) {
2063
+ buf[i] = (char)mmfgetc(mmfile);
2064
+ if( buf[i] == '\n' ) break;
2065
+ if( buf[i] == '\r' ) {
2066
+ pos = mmftell(mmfile);
2067
+ if( mmfgetc(mmfile) != '\n' ) mmfseek(mmfile, pos, SEEK_SET);
2068
+ buf[i] = '\n';
2069
+ break;
2070
+ }
2071
+ }
2072
+ if( i != bufsz-2 && buf[i] == '\n' ) i++;
2073
+ buf[i] = '\0';
2074
+ return buf;
2075
+ }
2076
+
2077
+ static void abc_substitute(ABCHANDLE *h, char *target, char *s)
2078
+ {
2079
+ char *p, *q;
2080
+ int i;
2081
+ int l = SDL_strlen(target);
2082
+ int n = SDL_strlen(s);
2083
+ if (l <= 0 ||n <= 0 || SDL_strstr(s, target))
2084
+ return;
2085
+ while( (p=SDL_strstr(h->line, target)) ) {
2086
+ if( (i=SDL_strlen(h->line)) + n - l >= (int)h->len ) {
2087
+ h->line = (char *)_mm_recalloc(h->allochandle, h->line, h->len<<1, sizeof(char));
2088
+ h->len <<= 1;
2089
+ p=SDL_strstr(h->line, target);
2090
+ }
2091
+ if( n > l ) {
2092
+ for( q=&h->line[i]; q>p; q-- ) q[n-l] = q[0];
2093
+ for( q=s; *q; q++ ) *p++ = *q;
2094
+ }
2095
+ else {
2096
+ const size_t buflen = h->len - ((size_t) (p - h->line));
2097
+ SDL_strlcpy(p,s,buflen);
2098
+ SDL_strlcat(p,p+l,buflen);
2099
+ }
2100
+ }
2101
+ }
2102
+
2103
+ static void abc_preprocess(ABCHANDLE *h, ABCMACRO *m)
2104
+ {
2105
+ int i, j, k, l, a, b;
2106
+ if( m->n ) {
2107
+ k = m->n - m->name;
2108
+ for( i=0; i<14; i++ ) {
2109
+ const size_t tlen = SDL_strlen(m->name) + 1;
2110
+ char *t = alloca(tlen);
2111
+ SDL_strlcpy(t, m->name, tlen);
2112
+ t[k] = "CDEFGABcdefgab"[i];
2113
+ l = SDL_strlen(m->subst);
2114
+ char *s = alloca(2 * l + 1);
2115
+ char *p = s;
2116
+ for( j=0; j<l; j++ ) {
2117
+ a = m->subst[j];
2118
+ if( a > 'g' && IsLower(a) ) {
2119
+ b = a - 'n';
2120
+ a = "CDEFGABCDEFGABcdefgabcdefgab"[i+b+7];
2121
+ *p++ = a;
2122
+ if( i+b < 0 )
2123
+ *p++ = ',';
2124
+ else if( i+b > 13 )
2125
+ *p++ = '\'';
2126
+ }
2127
+ else *p++ = a;
2128
+ }
2129
+ *p = '\0';
2130
+ abc_substitute(h, t, s);
2131
+ }
2132
+ }
2133
+ else
2134
+ abc_substitute(h, m->name, m->subst);
2135
+ }
2136
+
2137
+ static char *abc_gets(ABCHANDLE *h, MMFILE *mmfile)
2138
+ {
2139
+ int i;
2140
+ ABCMACRO *mp;
2141
+ if( !h->len ) {
2142
+ h->len = 64; // initial line size, adequate for most abc's
2143
+ h->line = (char *)_mm_calloc(h->allochandle, h->len, sizeof(char));
2144
+ }
2145
+ if( abc_fgetbytes(mmfile, h->line, h->len) ) {
2146
+ while( (i=SDL_strlen(h->line)) > (int)(h->len - 3) ) {
2147
+ // line too short, double it
2148
+ h->line = (char *)_mm_recalloc(h->allochandle, h->line, h->len<<1, sizeof(char));
2149
+ if( h->line[i-1] != '\n' )
2150
+ abc_fgetbytes(mmfile, &h->line[i], h->len);
2151
+ h->len <<= 1;
2152
+ }
2153
+ h->line[i-1] = '\0'; // strip off newline
2154
+ for( mp=h->macro; mp; mp=mp->next )
2155
+ abc_preprocess(h,mp);
2156
+ return h->line;
2157
+ }
2158
+ return NULL;
2159
+ }
2160
+
2161
+ static int abc_parse_decorations(ABCHANDLE *h, ABCTRACK *tp, const char *p)
2162
+ {
2163
+ int vol=0;
2164
+ if( !SDL_strncmp(p,"mp",2) ) vol = 75;
2165
+ if( !SDL_strncmp(p,"mf",2) ) vol = 90;
2166
+ if( !SDL_strncmp(p,"sfz",3) ) vol = 100;
2167
+ if( *p == 'p' ) {
2168
+ vol = 60;
2169
+ while( *p++ == 'p' ) vol -= 15;
2170
+ if( vol < 1 ) vol = 1;
2171
+ }
2172
+ if( *p == 'f' ) {
2173
+ vol = 105;
2174
+ while( *p++ == 'f' ) vol += 15;
2175
+ if( vol > 135 ) vol = 127; // ffff
2176
+ if( vol > 127 ) vol = 125; // fff
2177
+ }
2178
+ if( vol ) {
2179
+ tp->volume = vol;
2180
+ if( tp == h->track ) { // copy volume over to all voice tracks
2181
+ for( ; tp; tp=tp->next ) {
2182
+ if( tp->vpos == 0 || tp->vpos > DRONEPOS2 ) tp->volume = vol;
2183
+ }
2184
+ tp = h->track;
2185
+ }
2186
+ }
2187
+ return tp->volume;
2188
+ }
2189
+
2190
+ // =====================================================================================
2191
+ BOOL CSoundFile_TestABC(const BYTE *lpStream, DWORD dwMemLength)
2192
+ // =====================================================================================
2193
+ {
2194
+ char id[128];
2195
+ int hasText = 0;
2196
+ // scan file for first K: line (last in header)
2197
+ MMFILE mmfile;
2198
+ mmfile.mm = (char *)lpStream;
2199
+ mmfile.sz = dwMemLength;
2200
+ mmfseek(&mmfile,0,SEEK_SET);
2201
+ int ppos = mmfile.pos;
2202
+
2203
+ while(abc_fgets(&mmfile,id,128)) {
2204
+
2205
+ if (id[0] == 0 && hasText == 0 && mmfile.pos < ppos + 120) return(0); //probably binary
2206
+ if (id[0] == 0) continue; // blank line.
2207
+
2208
+ if (!abc_isvalidchar(id[0]) || !abc_isvalidchar(id[1])) {
2209
+ return(0); // probably not an ABC.
2210
+ }
2211
+ if(id[0]=='K'
2212
+ && id[1]==':'
2213
+ && (IsAlpha(id[2]) || SDL_isspace(id[2])) ) return 1;
2214
+ // disable binary error if have any "tag"
2215
+ if((id[0]>='A' && id[0]<='Z')
2216
+ && id[1]==':'
2217
+ && (IsAlpha(id[2]) || SDL_isspace(id[2])) ) hasText = 1;
2218
+ }
2219
+ return 0;
2220
+ }
2221
+
2222
+ // =====================================================================================
2223
+ static ABCHANDLE *ABC_Init(void)
2224
+ {
2225
+ ABCHANDLE *retval;
2226
+ char *p;
2227
+ char buf[10];
2228
+ retval = (ABCHANDLE *)SDL_calloc(1,sizeof(ABCHANDLE));
2229
+ if( !retval ) return NULL;
2230
+
2231
+ retval->track = NULL;
2232
+ retval->macro = NULL;
2233
+ retval->umacro = NULL;
2234
+ retval->beatstring = NULL;
2235
+ retval->pickrandom = 0;
2236
+ retval->len = 0;
2237
+ retval->line = NULL;
2238
+ retval->gchord[0] = 0;
2239
+ retval->barticks = 0;
2240
+ p = SDL_getenv(ABC_ENV_NORANDOMPICK);
2241
+ if( p ) {
2242
+ if( SDL_isdigit(*p) )
2243
+ retval->pickrandom = SDL_atoi(p);
2244
+ if( *p == '-' ) {
2245
+ retval->pickrandom = SDL_atoi(p+1)-1; // xmms preloads the file
2246
+ SDL_snprintf(buf,sizeof(buf),"-%ld",retval->pickrandom+2);
2247
+ SDL_setenv(ABC_ENV_NORANDOMPICK, buf, 1);
2248
+ }
2249
+ }
2250
+ else {
2251
+ srandom((uint32_t)time(0)); // initialize random generator with seed
2252
+ retval->pickrandom = 1+(int)(10000.0*random()/(RAND_MAX+1.0));
2253
+ // can handle pickin' from songbooks with 10.000 songs
2254
+ SDL_snprintf(buf,sizeof(buf),"-%ld",retval->pickrandom); // xmms preloads the file
2255
+ SDL_setenv(ABC_ENV_NORANDOMPICK, buf, 1);
2256
+ }
2257
+ return retval;
2258
+ }
2259
+
2260
+ static void ABC_CleanupTrack(ABCTRACK *tp)
2261
+ {
2262
+ ABCEVENT *ep, *en;
2263
+ if( tp ) {
2264
+ for( ep=tp->head; ep; ep = en ) {
2265
+ en=ep->next;
2266
+ SDL_free(ep);
2267
+ }
2268
+ tp->head = NULL;
2269
+ }
2270
+ }
2271
+
2272
+ static void ABC_CleanupMacro(ABCMACRO *m)
2273
+ {
2274
+ if( m->name )
2275
+ SDL_free(m->name);
2276
+ if( m->subst )
2277
+ SDL_free(m->subst);
2278
+ SDL_free(m);
2279
+ }
2280
+
2281
+ // =====================================================================================
2282
+ static void ABC_CleanupTracks(ABCHANDLE *handle)
2283
+ // =====================================================================================
2284
+ {
2285
+ ABCTRACK *tp, *tn;
2286
+ if(handle) {
2287
+ for( tp=handle->track; tp; tp = tn ) {
2288
+ tn=tp->next;
2289
+ ABC_CleanupTrack(tp);
2290
+ }
2291
+ handle->track = NULL;
2292
+ }
2293
+ }
2294
+
2295
+ // =====================================================================================
2296
+ static void ABC_CleanupMacros(ABCHANDLE *handle)
2297
+ // =====================================================================================
2298
+ {
2299
+ ABCMACRO *mp, *mn;
2300
+ if(handle) {
2301
+ for( mp=handle->macro; mp; mp = mn ) {
2302
+ mn=mp->next;
2303
+ ABC_CleanupMacro(mp);
2304
+ }
2305
+ for( mp=handle->umacro; mp; mp = mn ) {
2306
+ mn=mp->next;
2307
+ ABC_CleanupMacro(mp);
2308
+ }
2309
+ handle->macro = NULL;
2310
+ handle->umacro = NULL;
2311
+ }
2312
+ }
2313
+
2314
+ // =====================================================================================
2315
+ static void ABC_Cleanup(ABCHANDLE *handle)
2316
+ // =====================================================================================
2317
+ {
2318
+ if(handle) {
2319
+ ABC_CleanupMacros(handle);
2320
+ ABC_CleanupTracks(handle);
2321
+ if( handle->line )
2322
+ SDL_free(handle->line);
2323
+ if( handle->beatstring )
2324
+ SDL_free(handle->beatstring);
2325
+ SDL_free(handle);
2326
+ }
2327
+ }
2328
+
2329
+ static int abc_is_global_event(ABCEVENT *e)
2330
+ {
2331
+ return e->flg == 1 && (e->cmd == cmdtempo || e->cmd == cmdpartbrk);
2332
+ }
2333
+
2334
+ static ABCEVENT *abc_next_global(ABCEVENT *e)
2335
+ {
2336
+ for( ; e && !abc_is_global_event(e); e=e->next ) ;
2337
+ return e;
2338
+ }
2339
+
2340
+ static ABCEVENT *abc_next_note(ABCEVENT *e)
2341
+ {
2342
+ for( ; e && e->flg == 1; e=e->next ) ;
2343
+ return e;
2344
+ }
2345
+
2346
+ static int ABC_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], ABCHANDLE *h, int numpat, int channels)
2347
+ // =====================================================================================
2348
+ {
2349
+ int pat,row,i,ch,trillbits;
2350
+ BYTE n,ins,vol;
2351
+ ABCTRACK *t;
2352
+ ABCEVENT *e, *en, *ef, *el;
2353
+ uint32_t tt1, tt2;
2354
+ MODCOMMAND *m;
2355
+ int patbrk, tempo;
2356
+ if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS;
2357
+
2358
+ // initialize start points of event list in tracks
2359
+ for( t = h->track; t; t = t->next ) t->capostart = t->head;
2360
+ trillbits = 0; // trill effect admininstration: one bit per channel, max 32 channnels
2361
+ for( pat = 0; pat < numpat; pat++ ) {
2362
+ pattern[pat] = CSoundFile_AllocatePattern(64, channels);
2363
+ if( !pattern[pat] ) return 0;
2364
+ psize[pat] = 64;
2365
+ for( row = 0; row < 64; row++ ) {
2366
+ tt1 = abcticks((pat * 64 + row ) * h->speed);
2367
+ tt2 = tt1 + abcticks(h->speed);
2368
+ ch = 0;
2369
+ tempo = 0;
2370
+ patbrk = 0;
2371
+ if ( h->track )
2372
+ for( e=abc_next_global(h->track->capostart); e && e->tracktick < tt2; e=abc_next_global(e->next) ) {
2373
+ if( e && e->tracktick >= tt1 ) { // we have a tempo event in this row
2374
+ switch( e->cmd ) {
2375
+ case cmdtempo:
2376
+ tempo = e->lpar;
2377
+ break;
2378
+ case cmdpartbrk:
2379
+ patbrk = 1;
2380
+ break;
2381
+ }
2382
+ }
2383
+ }
2384
+ for( t = h->track; t; t = t->next ) {
2385
+ for( e=abc_next_note(t->capostart); e && e->tracktick < tt1; e=abc_next_note(e->next) ) ;
2386
+ i = 0;
2387
+ ef = NULL;
2388
+ en = e;
2389
+ el = e;
2390
+ for( ; e && e->tracktick < tt2; e=abc_next_note(e->next) ) { // we have a note event in this row
2391
+ t->capostart = e;
2392
+ i++;
2393
+ if( e->par[volume] ) {
2394
+ if( !ef ) ef = e;
2395
+ el = e;
2396
+ }
2397
+ }
2398
+ m = &pattern[pat][row * channels + ch];
2399
+ m->param = 0;
2400
+ m->command = CMD_NONE;
2401
+ if( i ) {
2402
+ trillbits &= ~(1<<ch);
2403
+ if( i == 1 || ef == el || !ef ) { // only one event in this row
2404
+ if( ef ) e = ef;
2405
+ else e = en;
2406
+ el = t->capostart;
2407
+ i = e->par[note] + ((e->par[octave])*12);
2408
+ if( t->chan == 10 ) {
2409
+ n = pat_gm_drumnote(i) + 23;
2410
+ ins = pat_gmtosmp(pat_gm_drumnr(i));
2411
+ }
2412
+ else {
2413
+ n = pat_modnote(i);
2414
+ ins = e->par[smpno];
2415
+ }
2416
+ vol = e->par[volume]/2;
2417
+ if( e->par[volume] > 0 ) {
2418
+ if( e->par[effect] == accent ) vol += vol / 20;
2419
+ if( vol > 64 ) vol = 64;
2420
+ if( el->par[volume] == 0 ) { // note cut
2421
+ m->param = el->tracktick - tt1;
2422
+ m->command = CMD_S3MCMDEX;
2423
+ m->param |= 0xC0;
2424
+ }
2425
+ else {
2426
+ switch( e->par[effect] ) {
2427
+ case trill:
2428
+ m->command = CMD_VIBRATO;
2429
+ m->param = 0xC2; // speed 12 depth 2
2430
+ trillbits |= (1<<ch);
2431
+ break;
2432
+ case bow:
2433
+ m->command = CMD_XFINEPORTAUPDOWN;
2434
+ m->param |= (e->par[effoper])? 0x12: 0x22;
2435
+ break;
2436
+ default:
2437
+ m->param = modticks(e->tracktick - tt1);
2438
+ if( m->param ) { // note delay
2439
+ m->command = CMD_S3MCMDEX;
2440
+ m->param |= 0xD0;
2441
+ }
2442
+ break;
2443
+ }
2444
+ }
2445
+ }
2446
+ m->instr = ins;
2447
+ m->note = n; // <- normal note
2448
+ m->volcmd = VOLCMD_VOLUME;
2449
+ m->vol = vol;
2450
+ }
2451
+ else {
2452
+ // two notes in one row, use FINEPITCHSLIDE runonce effect
2453
+ // start first note on first tick and framedly runonce on seconds note tick
2454
+ // use volume and instrument of last note
2455
+ if( t->chan == 10 ) {
2456
+ i = el->par[note] + ((el->par[octave])*12);
2457
+ n = pat_gm_drumnote(i) + 23;
2458
+ ins = pat_gmtosmp(pat_gm_drumnr(i));
2459
+ i = n; // cannot change instrument here..
2460
+ }
2461
+ else {
2462
+ i = ef->par[note] + ((ef->par[octave])*12);
2463
+ n = pat_modnote(i);
2464
+ ins = el->par[smpno];
2465
+ i = pat_modnote(el->par[note] + ((el->par[octave])*12));
2466
+ }
2467
+ vol = el->par[volume]/2;
2468
+ if( vol > 64 ) vol = 64;
2469
+ m->instr = ins;
2470
+ m->note = n; // <- normal note
2471
+ m->volcmd = VOLCMD_VOLUME;
2472
+ m->vol = vol;
2473
+ m->param = ((i > n)?i-n:n-i);
2474
+ if( m->param < 16 ) {
2475
+ if( m->param ) {
2476
+ m->command = CMD_XFINEPORTAUPDOWN;
2477
+ m->param |= (i > n)? 0x10: 0x20;
2478
+ }
2479
+ else { // retrigger same note...
2480
+ m->command = CMD_RETRIG;
2481
+ m->param = modticks(el->tracktick - tt1);
2482
+ }
2483
+ }
2484
+ else
2485
+ m->command = (i > n)? CMD_PORTAMENTOUP: CMD_PORTAMENTODOWN;
2486
+ }
2487
+ }
2488
+ else { // no new notes, keep on trilling...
2489
+ if( trillbits & (1<<ch) ) {
2490
+ m = &pattern[pat][row * channels + ch];
2491
+ m->command = CMD_VIBRATO;
2492
+ m->param = 0; // inherited from first effect
2493
+ m->instr = 0;
2494
+ m->note = 0;
2495
+ m->volcmd = 0;
2496
+ m->vol = 0;
2497
+ }
2498
+ }
2499
+ if( m->param == 0 && m->command == CMD_NONE ) {
2500
+ if( tempo ) {
2501
+ m->command = CMD_TEMPO;
2502
+ m->param = tempo;
2503
+ tempo = 0;
2504
+ }
2505
+ else {
2506
+ if( patbrk ) {
2507
+ m->command = CMD_PATTERNBREAK;
2508
+ patbrk = 0;
2509
+ }
2510
+ }
2511
+ }
2512
+ ch++;
2513
+ }
2514
+ if( tempo || patbrk ) return 1;
2515
+ }
2516
+ }
2517
+ return 0;
2518
+ }
2519
+
2520
+ static int ABC_Key(const char *p)
2521
+ {
2522
+ int i,j;
2523
+ char c[8];
2524
+ SDL_memset(c, 0, sizeof (c));
2525
+ const char *q;
2526
+ while( SDL_isspace(*p) ) p++;
2527
+ q = p;
2528
+ for( i=0; i<8 && *p && *p != ']'; p++ ) {
2529
+ if( SDL_isspace(*p) ) {
2530
+ while( SDL_isspace(*p) ) p++;
2531
+ if( SDL_strncasecmp(p, "min", 3) && SDL_strncasecmp(p, "maj", 3) )
2532
+ break;
2533
+ }
2534
+ c[i] = *p;
2535
+ i++;
2536
+ }
2537
+ if( !SDL_strcmp(c,"Hp") || !SDL_strcmp(c,"HP") ) // highland pipes
2538
+ SDL_strlcpy(c,"Bm",sizeof (c)); // two sharps at c and f
2539
+ if( !SDL_strcasecmp(c+1, "minor") ) i=2;
2540
+ if( !SDL_strcasecmp(c+2, "minor") ) i=3;
2541
+ if( !SDL_strcasecmp(c+1, "major") ) i=1;
2542
+ if( !SDL_strcasecmp(c+2, "major") ) i=2;
2543
+ if( !SDL_strcasecmp(c+1, "min") ) i=2;
2544
+ if( !SDL_strcasecmp(c+2, "min") ) i=3;
2545
+ if( !SDL_strcasecmp(c+1, "maj") ) i=1;
2546
+ if( !SDL_strcasecmp(c+2, "maj") ) i=2;
2547
+ for( ; i<6; i++ )
2548
+ c[i] = ' ';
2549
+ for( i=0; keySigs[i]; i++ ) {
2550
+ for( j=10; j<46; j+=6 )
2551
+ if( !SDL_strncasecmp(keySigs[i]+j, c, 6) )
2552
+ return i;
2553
+ }
2554
+ abc_message("Failure: Unrecognised K: field %s", q);
2555
+ return 7;
2556
+ }
2557
+
2558
+ static char *abc_skip_word(char *p)
2559
+ {
2560
+ while( SDL_isspace(*p) ) p++;
2561
+ while( *p && !SDL_isspace(*p) && *p != ']') p++;
2562
+ while( SDL_isspace(*p) ) p++;
2563
+ return p;
2564
+ }
2565
+
2566
+ static uint32_t abc_tracktime(ABCTRACK *tp)
2567
+ {
2568
+ uint32_t tracktime;
2569
+ if( tp->tail ) tracktime = tp->tail->tracktick;
2570
+ else tracktime = 0;
2571
+ if( tracktime < global_songstart )
2572
+ tracktime = global_songstart;
2573
+ return tracktime;
2574
+ }
2575
+
2576
+ static void abc_addchordname(const char *s, int len, const int *notes)
2577
+ // adds chord name and note set to list of known chords
2578
+ {
2579
+ int i, j;
2580
+ if(SDL_strlen(s) > 7) {
2581
+ abc_message("Failure: Chord name cannot exceed 7 characters, %s", s);
2582
+ return;
2583
+ }
2584
+ if(len > 6) {
2585
+ abc_message("Failure: Named chord cannot have more than 6 notes, %s", s);
2586
+ return;
2587
+ }
2588
+ for( i=0; i < chordsnamed; i++ ) {
2589
+ if(SDL_strcmp(s, chordname[i]) == 0) {
2590
+ /* change chord */
2591
+ chordlen[i] = len;
2592
+ for(j = 0; j < len; j++) chordnotes[i][j] = notes[j];
2593
+ return;
2594
+ }
2595
+ }
2596
+ if(chordsnamed > MAXCHORDNAMES - 1)
2597
+ abc_message("Failure: Too many Guitar Chord Names used, %s", s);
2598
+ else {
2599
+ SDL_strlcpy(chordname[chordsnamed], s, 8);
2600
+ chordlen[chordsnamed] = len;
2601
+ for(j = 0; j < len; j++) chordnotes[chordsnamed][j] = notes[j];
2602
+ chordsnamed++;
2603
+ }
2604
+ }
2605
+
2606
+ static void abc_setup_chordnames()
2607
+ // set up named guitar chords
2608
+ {
2609
+ static const int list_Maj[3] = { 0, 4, 7 };
2610
+ static const int list_m[3] = { 0, 3, 7 };
2611
+ static const int list_7[4] = { 0, 4, 7, 10 };
2612
+ static const int list_m7[4] = { 0, 3, 7, 10 };
2613
+ static const int list_maj7[4] = { 0, 4, 7, 11 };
2614
+ static const int list_M7[4] = { 0, 4, 7, 11 };
2615
+ static const int list_6[4] = { 0, 4, 7, 9 };
2616
+ static const int list_m6[4] = { 0, 3, 7, 9 };
2617
+ static const int list_aug[3] = { 0, 4, 8 };
2618
+ static const int list_plus[3] = { 0, 4, 8 };
2619
+ static const int list_aug7[4] = { 0, 4, 8, 10 };
2620
+ static const int list_dim[3] = { 0, 3, 6 };
2621
+ static const int list_dim7[4] = { 0, 3, 6, 9 };
2622
+ static const int list_9[5] = { 0, 4, 7, 10, 2 };
2623
+ static const int list_m9[5] = { 0, 3, 7, 10, 2 };
2624
+ static const int list_maj9[5] = { 0, 4, 7, 11, 2 };
2625
+ static const int list_M9[5] = { 0, 4, 7, 11, 2 };
2626
+ static const int list_11[6] = { 0, 4, 7, 10, 2, 5 };
2627
+ static const int list_dim9[5] = { 0, 4, 7, 10, 13 };
2628
+ static const int list_sus[3] = { 0, 5, 7 };
2629
+ static const int list_sus9[3] = { 0, 2, 7 };
2630
+ static const int list_7sus[4] = { 0, 5, 7, 10 };
2631
+ static const int list_7sus4[4] = { 0, 5, 7, 10 };
2632
+ static const int list_7sus9[4] = { 0, 2, 7, 10 };
2633
+ static const int list_9sus4[5] = { 0, 5, 10, 14, 19 };
2634
+ static const int list_5[2] = { 0, 7 };
2635
+ static const int list_13[6] = { 0, 4, 7, 10, 16, 21 };
2636
+
2637
+ chordsnamed = 0;
2638
+ abc_addchordname("", 3, list_Maj);
2639
+ abc_addchordname("m", 3, list_m);
2640
+ abc_addchordname("7", 4, list_7);
2641
+ abc_addchordname("m7", 4, list_m7);
2642
+ abc_addchordname("maj7", 4, list_maj7);
2643
+ abc_addchordname("M7", 4, list_M7);
2644
+ abc_addchordname("6", 4, list_6);
2645
+ abc_addchordname("m6", 4, list_m6);
2646
+ abc_addchordname("aug", 3, list_aug);
2647
+ abc_addchordname("+", 3, list_plus);
2648
+ abc_addchordname("aug7", 4, list_aug7);
2649
+ abc_addchordname("7+", 4, list_aug7);
2650
+ abc_addchordname("dim", 3, list_dim);
2651
+ abc_addchordname("dim7", 4, list_dim7);
2652
+ abc_addchordname("9", 5, list_9);
2653
+ abc_addchordname("m9", 5, list_m9);
2654
+ abc_addchordname("maj9", 5, list_maj9);
2655
+ abc_addchordname("M9", 5, list_M9);
2656
+ abc_addchordname("11", 6, list_11);
2657
+ abc_addchordname("dim9", 5, list_dim9);
2658
+ abc_addchordname("sus", 3, list_sus);
2659
+ abc_addchordname("sus9", 3, list_sus9);
2660
+ abc_addchordname("7sus", 4, list_7sus);
2661
+ abc_addchordname("7sus4", 4, list_7sus4);
2662
+ abc_addchordname("7sus9", 4, list_7sus9);
2663
+ abc_addchordname("9sus4", 5, list_9sus4);
2664
+ abc_addchordname("5", 2, list_5);
2665
+ abc_addchordname("13", 6, list_13);
2666
+ }
2667
+
2668
+ static int abc_MIDI_getnumber(const char *p)
2669
+ {
2670
+ int n;
2671
+ while( SDL_isspace(*p) ) p++;
2672
+ abc_getnumber(p, &n);
2673
+ if( n < 0 ) n = 0;
2674
+ if( n > 127 ) n = 127;
2675
+ return n;
2676
+ }
2677
+
2678
+ static int abc_MIDI_getprog(const char *p)
2679
+ {
2680
+ int n;
2681
+ while( SDL_isspace(*p) ) p++;
2682
+ abc_getnumber(p, &n);
2683
+ if( n < 1 ) n = 1;
2684
+ if( n > 128 ) n = 128;
2685
+ return n;
2686
+ }
2687
+
2688
+ // MIDI drone <instr0> <pitch1> <pitch2> <vel1> <vel2>
2689
+ static void abc_MIDI_drone(const char *p, int *gm, int *ptch, int *vol)
2690
+ {
2691
+ int i;
2692
+ while( SDL_isspace(*p) ) p++;
2693
+ p += abc_getnumber(p, &i);
2694
+ i++; // adjust for 1..128
2695
+ if( i>0 && i < 129 )
2696
+ *gm = i;
2697
+ else
2698
+ *gm = 71; // bassoon
2699
+ while( SDL_isspace(*p) ) p++;
2700
+ p += abc_getnumber(p, &i);
2701
+ if( i>0 && i < 127 )
2702
+ ptch[0] = i;
2703
+ else
2704
+ ptch[0] = 45;
2705
+ while( SDL_isspace(*p) ) p++;
2706
+ p += abc_getnumber(p, &i);
2707
+ if( i>0 && i < 127 )
2708
+ ptch[1] = i;
2709
+ else
2710
+ ptch[1] = 33;
2711
+ while( SDL_isspace(*p) ) p++;
2712
+ p += abc_getnumber(p, &i);
2713
+ if( i>0 && i < 127 )
2714
+ vol[0] = i;
2715
+ else
2716
+ vol[0] = 80;
2717
+ while( SDL_isspace(*p) ) p++;
2718
+ p += abc_getnumber(p, &i);
2719
+ if( i>0 && i < 127 )
2720
+ vol[1] = i;
2721
+ else
2722
+ vol[1] = 80;
2723
+ }
2724
+
2725
+ static void abc_chan_to_tracks(ABCHANDLE *h, int tno, int ch)
2726
+ {
2727
+ ABCTRACK *tp;
2728
+ if( tno>0 && tno<33 ) {
2729
+ for( tp=h->track; tp; tp=tp->next ) {
2730
+ if( tp->vno == tno && (tp->vpos < GCHORDBPOS || tp->vpos > DRONEPOS2) )
2731
+ tp->chan = ch;
2732
+ }
2733
+ }
2734
+ }
2735
+
2736
+ // %%MIDI channel int1
2737
+ // channel numbers are 1-16
2738
+ static void abc_MIDI_channel(const char *p, ABCTRACK *tp, ABCHANDLE *h)
2739
+ {
2740
+ int i1, i2;
2741
+ i1 = tp? tp->vno: 1;
2742
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2743
+ if( SDL_isdigit(*p) ) {
2744
+ p += abc_getnumber(p, &i2);
2745
+ if( i2 >= 1 && i2 <= 16 )
2746
+ abc_chan_to_tracks(h, i1, i2); // we start at 1
2747
+ }
2748
+ }
2749
+
2750
+ static void abc_instr_to_tracks(ABCHANDLE *h, int tno, int gm)
2751
+ {
2752
+ ABCTRACK *tp;
2753
+ if( tno>0 && tno<33 && gm>0 && gm<129 ) {
2754
+ for( tp=h->track; tp; tp=tp->next ) {
2755
+ if( tp->vno == tno && (tp->vpos < GCHORDBPOS || tp->vpos > DRONEPOS2) )
2756
+ tp->instr = gm;
2757
+ }
2758
+ }
2759
+ }
2760
+
2761
+ // %%MIDI program [int1] <int2>
2762
+ // instrument numbers are 0-127
2763
+ static void abc_MIDI_program(const char *p, ABCTRACK *tp, ABCHANDLE *h)
2764
+ {
2765
+ int i1, i2;
2766
+ i1 = tp? tp->vno: 1;
2767
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2768
+ if( SDL_isdigit(*p) ) {
2769
+ p += abc_getnumber(p, &i2);
2770
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2771
+ if( SDL_isdigit(*p) ) {
2772
+ i1 = i2;
2773
+ p += abc_getnumber(p, &i2);
2774
+ }
2775
+ abc_instr_to_tracks(h, i1, i2 + 1); // we start at 1
2776
+ }
2777
+ }
2778
+
2779
+ static void abc_mute_voice(ABCHANDLE *h, ABCTRACK *tp, int m)
2780
+ {
2781
+ ABCTRACK *t;
2782
+ for( t=h->track; t; t=t->next ) {
2783
+ if( t->vno == tp->vno ) t->mute = m;
2784
+ }
2785
+ }
2786
+
2787
+ // %%MIDI voice [<ID>] [instrument=<integer> [bank=<integer>]] [mute]
2788
+ // instrument numbers are 1-128
2789
+ static void abc_MIDI_voice(const char *p, ABCTRACK *tp, ABCHANDLE *h)
2790
+ {
2791
+ int i1, i2;
2792
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2793
+ if( SDL_strncmp(p,"instrument=",11) && SDL_strncmp(p,"mute",4) ) {
2794
+ tp = abc_locate_track(h, p, 0);
2795
+ for( ; *p && !SDL_isspace(*p); p++ ) ;
2796
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2797
+ }
2798
+ i1 = tp? tp->vno: 1;
2799
+ i2 = 0;
2800
+ if( !SDL_strncmp(p,"instrument=",11) && SDL_isdigit(p[11]) ) {
2801
+ p += 11;
2802
+ p += abc_getnumber(p, &i2);
2803
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2804
+ if( !SDL_strncmp(p,"bank=",5) && SDL_isdigit(p[5]) ) {
2805
+ for( ; *p && !SDL_isspace(*p); p++ ) ;
2806
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2807
+ }
2808
+ }
2809
+ if( tp ) abc_mute_voice(h,tp,0);
2810
+ if( !SDL_strncmp(p,"mute",4) && (p[4]=='\0' || p[4]=='%' || SDL_isspace(p[4])) ) {
2811
+ if( tp ) abc_mute_voice(h,tp,1);
2812
+ }
2813
+ abc_instr_to_tracks(h, i1, i2); // starts already at 1 (draft 4.0)
2814
+ }
2815
+
2816
+ // %%MIDI chordname <string> <int1> <int2> ... <int6>
2817
+ static void abc_MIDI_chordname(const char *p)
2818
+ {
2819
+ char name[20];
2820
+ int i, notes[6];
2821
+ SDL_memset(notes, 0, sizeof (notes));
2822
+
2823
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2824
+ i = 0;
2825
+ while ((i < 19) && (*p != ' ') && (*p != '\0')) {
2826
+ name[i] = *p;
2827
+ p = p + 1;
2828
+ i = i + 1;
2829
+ }
2830
+ name[i] = '\0';
2831
+ if(*p != ' ') {
2832
+ abc_message("Failure: Bad format for chordname command, %s", p);
2833
+ }
2834
+ else {
2835
+ i = 0;
2836
+ while ((i < 6) && SDL_isspace(*p)) {
2837
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2838
+ p += abc_getnumber(p, &notes[i]);
2839
+ i = i + 1;
2840
+ }
2841
+ abc_addchordname(name, i, notes);
2842
+ }
2843
+ }
2844
+
2845
+ // %%MIDI drum <string> <inst 1> ... <inst n> <vol 1> ... <vol n>
2846
+ // instrument numbers are 0-127
2847
+ static int abc_MIDI_drum(const char *p, ABCHANDLE *h)
2848
+ {
2849
+ char *q;
2850
+ int i, n, m;
2851
+ uint32_t len;
2852
+ while( SDL_isspace(*p) ) p++;
2853
+ if( !SDL_strncmp(p,"on",2) && (SDL_isspace(p[2]) || p[2] == '\0') ) return 2;
2854
+ if( !SDL_strncmp(p,"off",3) && (SDL_isspace(p[3]) || p[3] == '\0') ) return 1;
2855
+ n = 0; len = 0;
2856
+ for( q = h->drum; *p && !SDL_isspace(*p); p++ ) {
2857
+ if( !SDL_strchr("dz0123456789",*p) ) break;
2858
+ *q++ = *p; len++;
2859
+ if( !SDL_isdigit(*p) && len < sizeof(h->drum)-1 ) {
2860
+ if( !SDL_isdigit(p[1]) ) { *q++ = '1'; len ++; }
2861
+ n++; // count the silences too....
2862
+ }
2863
+ if (len >= sizeof(h->drum)-1) {
2864
+ // consume the rest of the input
2865
+ // definitely enough "drum last state" stored.
2866
+ while ( *p && !SDL_isspace(*p) ) p++;
2867
+ break;
2868
+ }
2869
+ }
2870
+ *q = '\0';
2871
+ q = h->drumins;
2872
+ for( i = 0; i<n; i++ ) {
2873
+ if( h->drum[i*2] == 'd' ) {
2874
+ while( *p && SDL_isspace(*p) ) p++;
2875
+ if( !SDL_isdigit(*p) ) {
2876
+ m = 0;
2877
+ while( *p && !SDL_isspace(*p) ) p++;
2878
+ }
2879
+ else
2880
+ p += abc_getnumber(p,&m);
2881
+ q[i] = m + 1; // we start at 1
2882
+ }
2883
+ else q[i] = 0;
2884
+ }
2885
+ q = h->drumvol;
2886
+ for( i = 0; i<n; i++ ) {
2887
+ if( h->drum[i*2] == 'd' ) {
2888
+ while( *p && SDL_isspace(*p) ) p++;
2889
+ if( !SDL_isdigit(*p) ) {
2890
+ m = 0;
2891
+ while( *p && !SDL_isspace(*p) ) p++;
2892
+ }
2893
+ else
2894
+ p += abc_getnumber(p,&m);
2895
+ q[i] = m;
2896
+ }
2897
+ else q[i] = 0;
2898
+ }
2899
+ return 0;
2900
+ }
2901
+
2902
+ // %%MIDI gchord <string>
2903
+ static int abc_MIDI_gchord(const char *p, ABCHANDLE *h)
2904
+ {
2905
+ char *q;
2906
+ uint32_t len = 0;
2907
+ while( SDL_isspace(*p) ) p++;
2908
+ if( !SDL_strncmp(p,"on",2) && (SDL_isspace(p[2]) || p[2] == '\0') ) return 2;
2909
+ if( !SDL_strncmp(p,"off",3) && (SDL_isspace(p[3]) || p[3] == '\0') ) return 1;
2910
+ for( q = h->gchord; *p && !SDL_isspace(*p); p++ ) {
2911
+ if( !SDL_strchr("fbcz0123456789ghijGHIJ",*p) ) break;
2912
+ *q++ = *p; len++;
2913
+ if( !SDL_isdigit(*p) && len < sizeof(h->gchord)-1 && !SDL_isdigit(p[1]) ) { *q++ = '1'; len ++; }
2914
+ if (len >= sizeof(h->gchord)-1) {
2915
+ // consume the rest of the input
2916
+ // definitely enough "drum last state" stored.
2917
+ while ( *p && !SDL_isspace(*p) ) p++;
2918
+ break;
2919
+ }
2920
+ }
2921
+ *q = '\0';
2922
+ return 0;
2923
+ }
2924
+
2925
+ static void abc_metric_gchord(ABCHANDLE *h, int mlen, int mdiv)
2926
+ {
2927
+ switch( 16 * mlen + mdiv ) {
2928
+ case 0x24:
2929
+ case 0x44:
2930
+ case 0x22:
2931
+ abc_MIDI_gchord("fzczfzcz", h);
2932
+ break;
2933
+ case 0x64:
2934
+ case 0x32:
2935
+ abc_MIDI_gchord("fzczczfzczcz", h);
2936
+ break;
2937
+ case 0x34:
2938
+ case 0x38:
2939
+ abc_MIDI_gchord("fzczcz", h);
2940
+ break;
2941
+ case 0x68:
2942
+ abc_MIDI_gchord("fzcfzc", h);
2943
+ break;
2944
+ case 0x98:
2945
+ abc_MIDI_gchord("fzcfzcfzc", h);
2946
+ break;
2947
+ case 0xc8:
2948
+ abc_MIDI_gchord("fzcfzcfzcfzc", h);
2949
+ break;
2950
+ default:
2951
+ if( mlen % 3 == 0 )
2952
+ abc_MIDI_gchord("fzcfzcfzcfzcfzcfzcfzcfzcfzc", h);
2953
+ else
2954
+ abc_MIDI_gchord("fzczfzczfzczfzczfzczfzczfzcz", h);
2955
+ if( mdiv == 8 ) h->gchord[mlen*2] = '\0';
2956
+ else h->gchord[mlen*4] = '\0';
2957
+ break;
2958
+ }
2959
+ }
2960
+
2961
+ static void abc_MIDI_legato(const char *p, ABCTRACK *tp)
2962
+ {
2963
+ for( ; *p && SDL_isspace(*p); p++ ) ;
2964
+ if( !SDL_strncmp(p,"off",3) ) tp->legato = 0;
2965
+ else tp->legato = 1;
2966
+ }
2967
+
2968
+ static void abc_M_field(const char *p, int *mlen, int *mdiv)
2969
+ {
2970
+ if( !SDL_strncmp(p,"none",4) ) {
2971
+ *mlen = 1;
2972
+ *mdiv = 1;
2973
+ return;
2974
+ }
2975
+ if( !SDL_strncmp(p,"C|",2) ) {
2976
+ *mlen = 2;
2977
+ *mdiv = 2;
2978
+ return;
2979
+ }
2980
+ if( *p == 'C' ) {
2981
+ *mlen = 4;
2982
+ *mdiv = 4;
2983
+ return;
2984
+ }
2985
+ p += abc_getexpr(p,mlen);
2986
+ SDL_sscanf(p," / %d", mdiv);
2987
+ }
2988
+
2989
+ static int abc_drum_steps(const char *dch)
2990
+ {
2991
+ const char *p;
2992
+ int i=0;
2993
+ for( p=dch; *p; p++ ) {
2994
+ if( SDL_isdigit(*p) ) i += *p - '0';;
2995
+ }
2996
+ return i;
2997
+ }
2998
+
2999
+ static void abc_add_drum(ABCHANDLE *h, uint32_t tracktime, uint32_t bartime)
3000
+ {
3001
+ ABCEVENT *e;
3002
+ ABCTRACK *tp;
3003
+ uint32_t etime, ctime , rtime, stime;
3004
+ int i, g, steps, gnote, gsteps, nnum;
3005
+ steps = abc_drum_steps(h->drum);
3006
+ ctime = h->barticks;
3007
+ // look up the last event in tpr drumtrack
3008
+ tp = abc_locate_track(h, h->tpr->v, DRUMPOS);
3009
+ e = tp->tail;
3010
+ etime = e? e->tracktick: bartime;
3011
+ if( etime > tracktime ) return;
3012
+ if( etime < bartime ) rtime = h->barticks - ((bartime - etime) % h->barticks);
3013
+ else rtime = (etime - bartime) % h->barticks;
3014
+ stime = ctime*steps;
3015
+ rtime *= steps;
3016
+ rtime += stime;
3017
+ gsteps = SDL_strlen(h->drum)/2;
3018
+ g = 0;
3019
+ while( rtime > stime ) {
3020
+ rtime -= ctime*(h->drum[g*2+1] - '0');
3021
+ if( ++g == gsteps ) g = 0;
3022
+ }
3023
+ stime = (tracktime - etime) * steps;
3024
+ rtime = 0;
3025
+
3026
+ // if no drumsteps, there is nothing we can do anyway.
3027
+ if( steps == 0 )
3028
+ return;
3029
+
3030
+ while( rtime < stime ) {
3031
+ gnote = h->drum[g*2];
3032
+ i = h->drum[g*2+1] - '0';
3033
+ if( gnote=='d') {
3034
+ tp->instr = pat_gm_drumnr(h->drumins[g]-1);
3035
+ nnum = pat_gm_drumnote(h->drumins[g]);
3036
+ abc_add_drumnote(h, tp, etime + rtime/steps, nnum, h->drumvol[g]);
3037
+ abc_add_noteoff(h,tp,etime + ( rtime + ctime * i )/steps);
3038
+ }
3039
+ if( ++g == gsteps ) g = 0;
3040
+ rtime += ctime * i;
3041
+ }
3042
+ }
3043
+
3044
+ static int abc_gchord_steps(const char *gch)
3045
+ {
3046
+ const char *p;
3047
+ int i=0;
3048
+ for( p=gch; *p; p++ )
3049
+ if( SDL_isdigit(*p) ) i += *p - '0';
3050
+ return i;
3051
+ }
3052
+
3053
+ static void abc_add_gchord(ABCHANDLE *h, uint32_t tracktime, uint32_t bartime)
3054
+ {
3055
+ ABCEVENT *e, *c;
3056
+ ABCTRACK *tp;
3057
+ uint32_t etime, ctime , rtime, stime;
3058
+ int i, g, steps, gnote, gcnum, gsteps, nnum, glen;
3059
+ // look up the last chord event in tpc
3060
+ c = 0;
3061
+ for( e = h->tpc->head; e; e = e->next )
3062
+ if( e->flg == 1 && e->cmd == cmdchord )
3063
+ c = e;
3064
+ if( !c ) return;
3065
+ gcnum = c->par[chordnum];
3066
+ steps = abc_gchord_steps(h->gchord);
3067
+ ctime = h->barticks;
3068
+ etime = 0;
3069
+ for( i = GCHORDBPOS; i < DRUMPOS; i++ ) {
3070
+ tp = abc_locate_track(h, h->tpc->v, i);
3071
+ e = tp->tail;
3072
+ if( !e ) e = c;
3073
+ stime = e->tracktick;
3074
+ if( stime > etime ) etime = stime;
3075
+ }
3076
+ if( etime > tracktime ) return;
3077
+ if( etime < bartime ) rtime = h->barticks - ((bartime - etime) % h->barticks);
3078
+ else rtime = (etime - bartime) % h->barticks;
3079
+ stime = ctime * steps;
3080
+ rtime *= steps;
3081
+ rtime += stime;
3082
+ gsteps = SDL_strlen(h->gchord);
3083
+ g = 0;
3084
+ while( rtime > stime ) {
3085
+ glen = h->gchord[2*g+1] - '0';
3086
+ rtime -= ctime * glen;
3087
+ if( ++g == gsteps ) g = 0;
3088
+ }
3089
+ stime = (tracktime - etime) * steps;
3090
+ rtime = 0;
3091
+ while( rtime < stime ) {
3092
+ gnote = h->gchord[2*g];
3093
+ glen = h->gchord[2*g+1] - '0';
3094
+ if( ++g == gsteps ) g = 0;
3095
+ switch(gnote) {
3096
+ case 'b':
3097
+ tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS);
3098
+ tp->instr = h->abcbassprog;
3099
+ nnum = c->par[chordnote]+chordnotes[gcnum][0]+24;
3100
+ abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcbassvol);
3101
+ abc_add_noteoff(h,tp,etime + ( rtime + ctime * glen )/steps);
3102
+ case 'c':
3103
+ for( i = 1; i < chordlen[gcnum]; i++ ) {
3104
+ tp = abc_locate_track(h, h->tpc->v, i+GCHORDFPOS);
3105
+ tp->instr = h->abcchordprog;
3106
+ nnum = c->par[chordnote]+chordnotes[gcnum][i]+24;
3107
+ abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcchordvol);
3108
+ abc_add_noteoff(h,tp,etime + ( rtime + ctime * glen )/steps);
3109
+ }
3110
+ rtime += ctime * glen;
3111
+ break;
3112
+ case 'f':
3113
+ tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS);
3114
+ tp->instr = h->abcbassprog;
3115
+ nnum = c->par[chordbase]+12;
3116
+ abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcbassvol);
3117
+ rtime += ctime * glen;
3118
+ abc_add_noteoff(h,tp,etime + rtime/steps);
3119
+ break;
3120
+ case 'g':
3121
+ case 'h':
3122
+ case 'i':
3123
+ case 'j':
3124
+ case 'G':
3125
+ case 'H':
3126
+ case 'I':
3127
+ case 'J':
3128
+ i = SDL_toupper(gnote) - 'G';
3129
+ nnum = 0;
3130
+ if( i < chordlen[gcnum] ) {
3131
+ tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS+i+1);
3132
+ tp->instr = h->abcchordprog;
3133
+ nnum = c->par[chordnote]+chordnotes[gcnum][i]+24;
3134
+ if( IsUpper(gnote) ) nnum -= 12;
3135
+ abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcchordvol);
3136
+ }
3137
+ rtime += ctime * glen;
3138
+ if( nnum ) abc_add_noteoff(h,tp,etime + rtime/steps);
3139
+ break;
3140
+ case 'z':
3141
+ rtime += ctime * glen;
3142
+ break;
3143
+ }
3144
+ }
3145
+ }
3146
+
3147
+ // %%MIDI beat a b c n
3148
+ //
3149
+ // controls the way note velocities are selected. The first note in a bar has
3150
+ // velocity a. Other "strong" notes have velocity b and all the rest have velocity
3151
+ // c. a, b and c must be in the range 0-128. The parameter n determines which
3152
+ // notes are "strong". If the time signature is x/y, then each note is given
3153
+ // a position number k = 0, 1, 2 .. x-1 within each bar. Note that the units for
3154
+ // n are not the unit note length. If k is a multiple of n, then the note is
3155
+ // "strong". The volume specifiers !ppp! to !fff! are equivalent to the
3156
+ // following :
3157
+ //
3158
+ // !ppp! = %%MIDI beat 30 20 10 1
3159
+ // !pp! = %%MIDI beat 45 35 20 1
3160
+ // !p! = %%MIDI beat 60 50 35 1
3161
+ // !mp! = %%MIDI beat 75 65 50 1
3162
+ // !mf! = %%MIDI beat 90 80 65 1
3163
+ // !f! = %%MIDI beat 105 95 80 1
3164
+ // !ff! = %%MIDI beat 120 110 95 1
3165
+ // !fff! = %%MIDI beat 127 125 110 1
3166
+ static void abc_MIDI_beat(ABCHANDLE *h, const char *p)
3167
+ {
3168
+ int i,j;
3169
+ h->beat[0] = 127;
3170
+ h->beat[1] = 125;
3171
+ h->beat[2] = 110;
3172
+ h->beat[3] = 1;
3173
+ for( j=0; j<4; j++ ) {
3174
+ while( SDL_isspace(*p) ) p++;
3175
+ if( *p ) {
3176
+ p += abc_getnumber(p, &i);
3177
+ if( i < 0 ) i = 0;
3178
+ if( i > 127 ) i = 127;
3179
+ h->beat[j] = i;
3180
+ }
3181
+ }
3182
+ if( h->beat[3] == 0 ) h->beat[3] = 1; // BB Ruud says: do not let you make mad
3183
+ }
3184
+
3185
+ //
3186
+ // %%MIDI beatstring <string of f, m and p>
3187
+ //
3188
+ // This provides an alternative way of specifying where the strong and weak
3189
+ // stresses fall within a bar. 'f' means velocity a (normally strong), 'm'
3190
+ // means velocity b (medium velocity) and 'p' means velocity c (soft velocity).
3191
+ // For example, if the time signature is 7/8 with stresses on the first, fourth
3192
+ // and sixth notes in the bar, we could use the following
3193
+ //
3194
+ // %%MIDI beatstring fppmpmp
3195
+ static void abc_MIDI_beatstring(ABCHANDLE *h, const char *p)
3196
+ {
3197
+ while( SDL_isspace(*p) ) p++;
3198
+ if( h->beatstring ) _mm_free(h->allochandle, h->beatstring);
3199
+ if( SDL_strlen(p) )
3200
+ h->beatstring = DupStr(h->allochandle,p,SDL_strlen(p)+1);
3201
+ else
3202
+ h->beatstring = NULL;
3203
+ }
3204
+
3205
+ static int abc_beat_vol(ABCHANDLE *h, int abcvol, int barpos)
3206
+ {
3207
+ int vol;
3208
+ if( h->beatstring ) {
3209
+ vol = (h->beat[2] * 9) / 10;
3210
+ if( barpos < (int)SDL_strlen(h->beatstring) ) {
3211
+ switch(h->beatstring[barpos]) {
3212
+ case 'f':
3213
+ vol = h->beat[0];
3214
+ break;
3215
+ case 'm':
3216
+ vol = h->beat[1];
3217
+ break;
3218
+ case 'p':
3219
+ vol = h->beat[2];
3220
+ break;
3221
+ default:
3222
+ break;
3223
+ }
3224
+ }
3225
+ }
3226
+ else {
3227
+ if( (barpos % h->beat[3]) == 0 ) {
3228
+ if( barpos )
3229
+ vol = h->beat[1];
3230
+ else
3231
+ vol = h->beat[0];
3232
+ }
3233
+ else
3234
+ vol = h->beat[2];
3235
+ }
3236
+ vol *= abcvol;
3237
+ vol /= 128;
3238
+ return vol;
3239
+ }
3240
+
3241
+ static void abc_init_partpat(BYTE partp[27][2])
3242
+ {
3243
+ int i;
3244
+ for( i=0; i<27; i++ ) {
3245
+ partp[i][0] = 0xff;
3246
+ partp[i][1] = 0;
3247
+ }
3248
+ }
3249
+
3250
+ static int abc_partpat_to_orderlist(BYTE partp[27][2], const char *abcparts, ABCHANDLE *h, BYTE **list, int orderlen)
3251
+ {
3252
+ int t, partsused;
3253
+ const char *p;
3254
+ BYTE *orderlist = *list;
3255
+ static int ordersize = 0;
3256
+ if( *list == NULL ) {
3257
+ ordersize = 128;
3258
+ orderlist = (BYTE *)_mm_calloc(h->ho, ordersize, sizeof(BYTE));
3259
+ *list = orderlist;
3260
+ }
3261
+ if( abcparts ) {
3262
+ partsused = 0;
3263
+ for( p = abcparts; *p; p++ ) {
3264
+ for( t = partp[*p - 'A'][0]; t < partp[*p - 'A'][1]; t++ ) {
3265
+ if( orderlen == ordersize ) {
3266
+ ordersize <<= 1;
3267
+ if (ordersize == 0) ordersize = 2;
3268
+ orderlist = (BYTE *)_mm_recalloc(h->ho, orderlist, ordersize, sizeof(BYTE));
3269
+ *list = orderlist;
3270
+ }
3271
+ orderlist[orderlen] = t;
3272
+ orderlen++;
3273
+ partsused++;
3274
+ }
3275
+ }
3276
+ if( partsused ) return orderlen;
3277
+ }
3278
+ // some fool wrote a P: string in the header but didn't use P: in the body
3279
+ for( t = partp[26][0]; t < partp[26][1]; t++ ) {
3280
+ if( orderlen == ordersize ) {
3281
+ ordersize <<= 1;
3282
+ if (ordersize == 0) ordersize = 2;
3283
+ orderlist = (BYTE *)_mm_recalloc(h->ho, orderlist, ordersize, sizeof(BYTE));
3284
+ *list = orderlist;
3285
+ }
3286
+ orderlist[orderlen] = t;
3287
+ orderlen++;
3288
+ }
3289
+ return orderlen;
3290
+ }
3291
+
3292
+ static void abc_globalslide(ABCHANDLE *h, uint32_t tracktime, int slide)
3293
+ {
3294
+ ABCTRACK *tp;
3295
+ ABCEVENT *e;
3296
+ int hslide;
3297
+ hslide = h->track? h->track->slidevol: slide;
3298
+ for( tp=h->track; tp; tp = tp->next ) {
3299
+ if( slide ) {
3300
+ tp->slidevoltime = tracktime;
3301
+ if( slide == 2 )
3302
+ tp->slidevol = 0;
3303
+ }
3304
+ if( tp->slidevol > -2 && slide < 2 )
3305
+ tp->slidevol = slide;
3306
+ }
3307
+ if( h->track && h->track->tail
3308
+ && hslide != slide && slide == -2
3309
+ && h->track->tail->tracktick >= tracktime ) {
3310
+ // need to update jumptypes in mastertrack from tracktime on...
3311
+ for( e=h->track->head; e; e=e->next ) {
3312
+ if( e->flg == 1 && e->cmd == cmdjump && e->tracktick >= tracktime ) {
3313
+ switch( e->par[jumptype] ) {
3314
+ case jumpnormal:
3315
+ case jumpfade:
3316
+ e->par[jumptype] = jumpfade;
3317
+ break;
3318
+ case jumpdacapo:
3319
+ case jumpdcfade:
3320
+ e->par[jumptype] = jumpdcfade;
3321
+ break;
3322
+ case jumpdasegno:
3323
+ case jumpdsfade:
3324
+ e->par[jumptype] = jumpdsfade;
3325
+ break;
3326
+ }
3327
+ }
3328
+ }
3329
+ }
3330
+ }
3331
+
3332
+ static void abc_recalculate_tracktime(ABCHANDLE *h) {
3333
+ ABCTRACK *ttp;
3334
+ h->tracktime = 0;
3335
+ for( ttp=h->track; ttp; ttp=ttp->next )
3336
+ if( ttp->tail && ttp->tail->tracktick > h->tracktime )
3337
+ h->tracktime = ttp->tail->tracktick;
3338
+ }
3339
+
3340
+ static void abc_MIDI_command(ABCHANDLE *h, char *p, char delim) {
3341
+ int t;
3342
+ // interpret some of the possibilitys
3343
+ if( !SDL_strncmp(p,"bassprog",8) && SDL_isspace(p[8]) ) h->abcbassprog = abc_MIDI_getprog(p+8)+1;
3344
+ if( !SDL_strncmp(p,"bassvol",7) && SDL_isspace(p[7]) ) h->abcbassvol = abc_MIDI_getnumber(p+7);
3345
+ if( !SDL_strncmp(p,"beat",4) && SDL_isspace(p[4]) ) abc_MIDI_beat(h, p+4);
3346
+ if( !SDL_strncmp(p,"beatstring",10) && SDL_isspace(p[10]) ) abc_MIDI_beatstring(h, p+4);
3347
+ if( !SDL_strncmp(p,"chordname",9) && SDL_isspace(p[9]) ) abc_MIDI_chordname(p+9);
3348
+ if( !SDL_strncmp(p,"chordprog",9) && SDL_isspace(p[9]) ) h->abcchordprog = abc_MIDI_getprog(p+9)+1;
3349
+ if( !SDL_strncmp(p,"chordvol",8) && SDL_isspace(p[8]) ) h->abcchordvol = abc_MIDI_getnumber(p+8);
3350
+ if( !SDL_strncmp(p,"drone",5) && SDL_isspace(p[5]) ) abc_MIDI_drone(p+5, &h->dronegm, h->dronepitch, h->dronevol);
3351
+ if( !SDL_strncmp(p,"droneoff",8) && (p[8]=='\0' || p[8]==delim || SDL_isspace(p[8])) ) h->droneon = 0;
3352
+ if( !SDL_strncmp(p,"droneon",7) && (p[7]=='\0' || p[7]==delim || SDL_isspace(p[7])) ) h->droneon = 1;
3353
+ t = h->drumon;
3354
+ if( !SDL_strncmp(p,"drum",4) && SDL_isspace(p[4]) ) {
3355
+ h->drumon = abc_MIDI_drum(p+4, h);
3356
+ if( h->drumon ) --h->drumon;
3357
+ else h->drumon = t;
3358
+ }
3359
+ if( !SDL_strncmp(p,"drumoff",7) && (p[7]=='\0' || p[7]==delim || SDL_isspace(p[7])) ) h->drumon = 0;
3360
+ if( !SDL_strncmp(p,"drumon",6) && (p[6]=='\0' || p[6]==delim || SDL_isspace(p[6])) ) h->drumon = 1;
3361
+ if( t != h->drumon ) {
3362
+ if( h->drumon && !h->tpr ) h->tpr = h->track;
3363
+ if( h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); // don't start drumming from the beginning of time!
3364
+ if( h->tpr && !h->drumon ) h->tpr = NULL;
3365
+ }
3366
+ t = h->gchordon;
3367
+ if( !SDL_strncmp(p,"gchord",6) && (p[6]=='\0' || p[6]==delim || SDL_isspace(p[6])) ) {
3368
+ h->gchordon = abc_MIDI_gchord(p+6, h);
3369
+ if( h->gchordon ) --h->gchordon;
3370
+ else h->gchordon = t;
3371
+ }
3372
+ if( !SDL_strncmp(p,"gchordoff",9) && (p[9]=='\0' || p[9]==delim || SDL_isspace(p[9])) ) h->gchordon = 0;
3373
+ if( !SDL_strncmp(p,"gchordon",8) && (p[8]=='\0' || p[8]==delim || SDL_isspace(p[8])) ) h->gchordon = 1;
3374
+ if( t != h->gchordon ) {
3375
+ if( h->tpc ) abc_add_gchord_syncs(h, h->tpc, h->tracktime);
3376
+ }
3377
+ if( !SDL_strncmp(p,"channel",7) && SDL_isspace(p[7]) )
3378
+ abc_MIDI_channel(p+8, h->tp = abc_check_track(h, h->tp), h);
3379
+ if( !SDL_strncmp(p,"program",7) && SDL_isspace(p[7]) )
3380
+ abc_MIDI_program(p+8, h->tp = abc_check_track(h, h->tp), h);
3381
+ if( !SDL_strncmp(p,"voice",5) && SDL_isspace(p[5]) )
3382
+ abc_MIDI_voice(p+6, h->tp = abc_check_track(h, h->tp), h);
3383
+ if( !SDL_strncmp(p,"legato",6) && (p[6]=='\0' || p[6]==delim || SDL_isspace(p[6])) )
3384
+ abc_MIDI_legato(p+6, h->tp = abc_check_track(h, h->tp));
3385
+ }
3386
+
3387
+ // continuate line that ends with a backslash, can't do this in abc_gets because voice lines
3388
+ // can have comment lines in between that must be parsed properly, for example:
3389
+ // [V:1] cdef gabc' |\ << continuation backslash
3390
+ // %%MIDI program 25
3391
+ // c'bag fedc |
3392
+ // informational lines can have this too, so it is rather convoluted code...
3393
+ static char *abc_continuated(ABCHANDLE *h, MMFILE *mmf, char *p) {
3394
+ char *pm, *p1, *p2 = 0;
3395
+ int continued;
3396
+ pm = p;
3397
+ while( pm[SDL_strlen(pm)-1]=='\\' ) {
3398
+ p1 = SDL_strdup(pm);
3399
+ if( p2 ) SDL_free(p2);
3400
+ continued = 1;
3401
+ while( continued ) {
3402
+ continued = 0;
3403
+ pm = abc_gets(h, mmf);
3404
+ if( !pm ) {
3405
+ abc_message("line not properly continued\n%s", p1);
3406
+ return p1;
3407
+ }
3408
+ while( *pm && SDL_isspace(*pm) ) ++pm;
3409
+ if( !SDL_strncmp(pm,"%%",2) ) {
3410
+ for( p2 = pm+2; *p2 && SDL_isspace(*p2); p2++ ) ;
3411
+ if( !SDL_strncmp(p2,"MIDI",4) && (p2[4]=='=' || SDL_isspace(p2[4])) ) {
3412
+ for( p2+=5; *p2 && SDL_isspace(*p2); p2++ ) ;
3413
+ if( *p2 == '=' )
3414
+ for( p2+=1; *p2 && SDL_isspace(*p2); p2++ ) ;
3415
+ abc_MIDI_command(h,p2,'%');
3416
+ }
3417
+ continued = 1;
3418
+ }
3419
+ }
3420
+ const size_t macrolinelen = SDL_strlen(p1)+SDL_strlen(pm)+1;
3421
+ p2 = (char *)SDL_malloc(macrolinelen);
3422
+ if( !p2 ) {
3423
+ abc_message("macro line too long\n%s", p1);
3424
+ return p1;
3425
+ }
3426
+ p1[SDL_strlen(p1)-1] = '\0'; // strip off the backslash
3427
+ SDL_strlcpy(p2,p1,macrolinelen);
3428
+ SDL_strlcat(p2,pm,macrolinelen);
3429
+ pm = p2;
3430
+ SDL_free(p1);
3431
+ }
3432
+ return pm;
3433
+ }
3434
+
3435
+ // =====================================================================================
3436
+ BOOL CSoundFile_ReadABC(CSoundFile *_this, const uint8_t *lpStream, DWORD dwMemLength)
3437
+ {
3438
+ static int avoid_reentry = 0;
3439
+ ABCHANDLE *h;
3440
+ uint32_t numpat;
3441
+ MMFILE mm, *mmfile;
3442
+ uint32_t t;
3443
+ char *line, *p, *pp, ch, ch0=0;
3444
+ char barsig[52]; // for propagated accidental key signature within bar
3445
+ char *abcparts;
3446
+ uint8_t partpat[27][2], *orderlist;
3447
+ int orderlen;
3448
+ enum { NOWHERE, INBETWEEN, INHEAD, INBODY, INSKIPFORX, INSKIPFORQUOTE } abcstate;
3449
+ ABCEVENT_JUMPTYPE j;
3450
+ ABCEVENT_X_EFFECT abceffect;
3451
+ int abceffoper;
3452
+ int abcxcount=0, abcxwanted=0, abcxnumber=1;
3453
+ int abckey, abcrate, abcchord, abcvol, abcbeatvol, abcnoslurs, abcnolegato, abcfermata, abcarpeggio, abcto;
3454
+ int abctempo;
3455
+ int cnotelen=0, cnotediv=0, snotelen, snotediv, mnotelen, mnotediv, notelen, notediv;
3456
+ // c for chords, s for standard L: setting, m for M: barlength
3457
+ int abchornpipe, brokenrithm, tupletp, tupletq, tupletr;
3458
+ int ktempo;
3459
+ uint32_t abcgrace=0, bartime, thistime=0;
3460
+ ABCTRACK *tpd, *ttp;
3461
+ ABCMACRO *mp;
3462
+ int mmsp;
3463
+ MMFILE *mmstack[MAXABCINCLUDES];
3464
+ if( !CSoundFile_TestABC(lpStream, dwMemLength) ) return FALSE;
3465
+ h = ABC_Init();
3466
+ if( !h ) return FALSE;
3467
+ mmfile = &mm;
3468
+ mm.mm = (char *)lpStream;
3469
+ mm.sz = dwMemLength;
3470
+ mm.pos = 0;
3471
+ while( avoid_reentry ) SDL_Delay(1);
3472
+ avoid_reentry = 1;
3473
+ pat_resetsmp();
3474
+ pat_init_patnames();
3475
+ _this->m_nDefaultTempo = 0;
3476
+ global_voiceno = 0;
3477
+ abckey = 0;
3478
+ h->tracktime = 0;
3479
+ global_songstart = 0;
3480
+ h->speed = 6;
3481
+ abcrate = 240;
3482
+ global_tempo_factor = 2;
3483
+ global_tempo_divider = 1;
3484
+ abctempo = 0;
3485
+ ktempo = 0;
3486
+ abceffect = none;
3487
+ abceffoper = 0;
3488
+ abcvol = 120;
3489
+ h->abcchordvol = abcvol;
3490
+ h->abcbassvol = abcvol;
3491
+ h->abcchordprog = 25; // acoustic guitar
3492
+ h->abcbassprog = 33; // acoustic bass
3493
+ abcparts = 0;
3494
+ abcnoslurs = 1;
3495
+ abcnolegato = 1;
3496
+ abcfermata = 0;
3497
+ abcarpeggio = 0;
3498
+ abcto = 0;
3499
+ snotelen = 0;
3500
+ snotediv = 0;
3501
+ mnotelen = 1;
3502
+ mnotediv = 1;
3503
+ abchornpipe = 0;
3504
+ brokenrithm = 0;
3505
+ tupletp = 0;
3506
+ tupletq = 0;
3507
+ tupletr = 0;
3508
+ h->ktrans = 0;
3509
+ h->drumon = 0;
3510
+ h->gchordon = 1;
3511
+ h->droneon = 0;
3512
+ h->tracktime = 0;
3513
+ bartime = 0;
3514
+ h->tp = NULL;
3515
+ h->tpc = NULL;
3516
+ h->tpr = NULL;
3517
+ tpd = NULL;
3518
+ h->dronegm = 71;
3519
+ h->dronepitch[0] = 45;
3520
+ h->dronepitch[1] = 33;
3521
+ h->dronevol[0] = 80;
3522
+ h->dronevol[1] = 80;
3523
+ abc_new_umacro(h, "v = +downbow+");
3524
+ abc_new_umacro(h, "u = +upbow+");
3525
+ abc_new_umacro(h, "O = +coda+");
3526
+ abc_new_umacro(h, "S = +segno+");
3527
+ abc_new_umacro(h, "P = +uppermordent+");
3528
+ abc_new_umacro(h, "M = +lowermordent+");
3529
+ abc_new_umacro(h, "L = +emphasis+");
3530
+ abc_new_umacro(h, "H = +fermata+");
3531
+ abc_new_umacro(h, "T = +trill+");
3532
+ abc_new_umacro(h, "~ = +roll+");
3533
+ abc_setup_chordnames();
3534
+ abc_init_partpat(partpat);
3535
+ abc_MIDI_beat(h, ""); // reset beat array
3536
+ abc_MIDI_beatstring(h, ""); // reset beatstring
3537
+ orderlist = NULL;
3538
+ orderlen = 0;
3539
+ mmsp = 1;
3540
+ mmstack[0] = mmfile;
3541
+ mmfseek(mmfile,0,SEEK_SET);
3542
+ abcstate = NOWHERE;
3543
+ if( h->pickrandom ) {
3544
+ abcstate = INSKIPFORX;
3545
+ abcxcount = 0;
3546
+ mmfseek(mmfile,0,SEEK_SET);
3547
+ while( (line=abc_gets(h, mmfile)) ) {
3548
+ for( p=line; SDL_isspace(*p); p++ ) ;
3549
+ if( !SDL_strncmp(p,"X:",2) ) abcxcount++;
3550
+ }
3551
+ if( abcxcount == 0 )
3552
+ abcstate = NOWHERE;
3553
+ else
3554
+ abcxwanted = (h->pickrandom - 1) % abcxcount;
3555
+ abcxcount = 0;
3556
+ mmfseek(mmfile,0,SEEK_SET);
3557
+ }
3558
+ while( mmsp > 0 ) {
3559
+ mmsp--;
3560
+ while((line=abc_gets(h, mmstack[mmsp]))) {
3561
+ for( p=line; SDL_isspace(*p); p++ ) ;
3562
+ switch(abcstate) {
3563
+ case INSKIPFORX:
3564
+ if( !SDL_strncmp(p,"X:",2) ) {
3565
+ if( abcxcount++ != abcxwanted )
3566
+ break;
3567
+ }
3568
+ // fall through
3569
+ case INBETWEEN:
3570
+ if( !SDL_strncmp(p,"X:",2) ) {
3571
+ abcstate = INHEAD;
3572
+ for( p+=2; SDL_isspace(*p); p++ ) ;
3573
+ abcxnumber = SDL_atoi(p);
3574
+ abchornpipe = 0;
3575
+ h->droneon = 0;
3576
+ h->dronegm = 71;
3577
+ h->dronepitch[0] = 45;
3578
+ h->dronepitch[1] = 33;
3579
+ h->dronevol[0] = 80;
3580
+ h->dronevol[1] = 80;
3581
+ for( ttp = h->track; ttp; ttp=ttp->next ) {
3582
+ ttp->vno = 0; // mark track unused
3583
+ ttp->capostart = NULL;
3584
+ }
3585
+ h->tp = NULL; // forget old voices
3586
+ h->tpc = NULL;
3587
+ h->tpr = NULL;
3588
+ global_voiceno = 0;
3589
+ abc_set_parts(&abcparts, 0);
3590
+ abcgrace = 0;
3591
+ h->ktrans = 0;
3592
+ ktempo = 0;
3593
+ h->gchordon = 1;
3594
+ h->drumon = 0;
3595
+ global_songstart = h->tracktime;
3596
+ abc_MIDI_beat(h, ""); // reset beat array
3597
+ abc_MIDI_beatstring(h, ""); // reset beatstring
3598
+ h->gchord[0] = 0; // reset gchord string
3599
+ abcnolegato = 1; // reset legato switch
3600
+ }
3601
+ break;
3602
+ case NOWHERE:
3603
+ if( p[0] != '\0' && p[1] == ':' ) {
3604
+ abcstate = INHEAD;
3605
+ abc_set_parts(&abcparts, 0);
3606
+ h->gchord[0] = 0;
3607
+ if( h->drumon && h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime);
3608
+ if( h->tpc && !h->gchordon ) abc_add_gchord_syncs(h, h->tpc, h->tracktime);
3609
+ h->gchordon = 1;
3610
+ h->drumon = 0;
3611
+ }
3612
+ else
3613
+ break;
3614
+ case INHEAD:
3615
+ if( !SDL_strncmp(p,"L:",2) ) {
3616
+ SDL_sscanf(p+2," %d / %d", &snotelen, &snotediv);
3617
+ break;
3618
+ }
3619
+ if( !SDL_strncmp(p,"M:",2) ) {
3620
+ abc_M_field(p+2, &mnotelen, &mnotediv);
3621
+ break;
3622
+ }
3623
+ if( !SDL_strncmp(p,"P:",2) ) {
3624
+ abc_set_parts(&abcparts, p+2);
3625
+ break;
3626
+ }
3627
+ if( !SDL_strncmp(p,"Q:",2) ) {
3628
+ abctempo = abc_extract_tempo(p+2,0);
3629
+ ktempo = 1;
3630
+ if( h->track ) {
3631
+ // make h->tracktime start of a new age...
3632
+ abc_add_partbreak(h, h->track, h->tracktime);
3633
+ abc_add_tempo_event(h, h->track, h->tracktime, abctempo);
3634
+ }
3635
+ if( _this->m_nDefaultTempo == 0 ) _this->m_nDefaultTempo = abctempo;
3636
+ break;
3637
+ }
3638
+ if( !SDL_strncmp(p,"T:",2) ) {
3639
+ break;
3640
+ }
3641
+ if( !SDL_strncmp(p,"R:",2) ) {
3642
+ for( p+=2; SDL_isspace(*p); p++ ) ;
3643
+ if( !SDL_strncmp(p,"hornpipe",8) && (SDL_isspace(p[8]) || p[8]=='\0') ) abchornpipe = 1;
3644
+ else abchornpipe = 0;
3645
+ break;
3646
+ }
3647
+ if( !SDL_strncmp(p,"V:",2) ) {
3648
+ for( t=2; p[t]==' '; t++ ) ;
3649
+ h->tp = abc_locate_track(h, p+t, 0);
3650
+ abcvol = h->tp->volume;
3651
+ abcnolegato = !h->tp->legato;
3652
+ if( !abcnolegato ) abcnoslurs = 0;
3653
+ break;
3654
+ }
3655
+ if( !SDL_strncmp(p,"K:",2) ) {
3656
+ abcstate = INBODY;
3657
+ abckey = ABC_Key(p+2);
3658
+ SDL_snprintf(barsig, sizeof (barsig), "%s%s", sig[abckey], sig[abckey]); // reset the key signature
3659
+ p = abc_skip_word(p+2);
3660
+ h->ktrans = abc_transpose(p);
3661
+ *p = '%'; // force skip rest of line
3662
+ if( snotelen == 0 ) { // calculate default notelen from meter M:
3663
+ if( mnotediv == 0 ) mnotediv = mnotelen = 1; // do'nt get nuked
3664
+ snotelen = 100 * mnotelen / mnotediv;
3665
+ if( snotelen > 74 )
3666
+ snotediv = 8;
3667
+ else
3668
+ snotediv = 16;
3669
+ snotelen = 1;
3670
+ }
3671
+ abceffect = none;
3672
+ abceffoper = 0;
3673
+ if( !(snotelen == 1 && snotediv == 8) ) abchornpipe = 0; // no matter what they said at R:
3674
+ brokenrithm = 0;
3675
+ global_part = ' ';
3676
+ abcgrace = 0;
3677
+ abcnoslurs = abcnolegato;
3678
+ abcto = 0;
3679
+ h->tpc = NULL; // reset chord track
3680
+ tpd = NULL; // reset drone track
3681
+ h->tpr = NULL; // reset drum track
3682
+ if( !SDL_strlen(h->gchord) ) abc_metric_gchord(h, mnotelen, mnotediv);
3683
+ h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv);
3684
+ if( abctempo && !ktempo ) { // did not set tempo in this songpiece so reset to abcrate
3685
+ abctempo = 0;
3686
+ global_tempo_factor = 2;
3687
+ global_tempo_divider = 1;
3688
+ if( h->track ) {
3689
+ // make h->tracktime start of a new age...
3690
+ abc_add_partbreak(h, h->track, h->tracktime);
3691
+ abc_add_tempo_event(h, h->track, h->tracktime, abcrate);
3692
+ }
3693
+ if( _this->m_nDefaultTempo == 0 ) _this->m_nDefaultTempo = abcrate;
3694
+ }
3695
+ abc_init_partpat(partpat);
3696
+ partpat[26][0] = abc_patno(h, h->tracktime);
3697
+ partpat[26][1] = 0;
3698
+ abc_globalslide(h, h->tracktime, 2); // reset all volumeslides
3699
+ break;
3700
+ }
3701
+ if( !SDL_strlen(p) )
3702
+ abcstate = INBETWEEN;
3703
+ break;
3704
+ case INSKIPFORQUOTE:
3705
+ while( *p && *p != '"' )
3706
+ p++;
3707
+ if( *p == '\0' )
3708
+ break;
3709
+ abcstate = INBODY;
3710
+ // fall through
3711
+ case INBODY:
3712
+ if( !SDL_strlen(p) && h->track ) { // end of this song
3713
+ abcstate = h->pickrandom? INSKIPFORX: INBETWEEN;
3714
+ // last but not least shut off all pending events
3715
+ abc_recalculate_tracktime(h);
3716
+ for( ttp=h->track; ttp; ttp=ttp->next )
3717
+ abc_add_noteoff(h,ttp,h->tracktime);
3718
+ abc_add_partbreak(h, h->track, h->tracktime);
3719
+ t = abc_patno(h, h->tracktime);
3720
+ if( abc_pattracktime(h, h->tracktime) % abcticks(64 * h->speed) ) t++;
3721
+ if( global_part == ' ' ) {
3722
+ partpat[26][1] = t;
3723
+ if( abcparts ) {
3724
+ for( t=0; t<26; t++ )
3725
+ if( partpat[t][0] < partpat[t][1] ) break;
3726
+ if( t == 26 ) {
3727
+ abc_message("parts (%s) set but not used", abcparts);
3728
+ abc_set_parts(&abcparts, 0); // forget the parts array
3729
+ }
3730
+ }
3731
+ }
3732
+ else
3733
+ partpat[global_part - 'A'][1] = t;
3734
+ if( !abcparts ) abc_song_to_parts(h, &abcparts, partpat);
3735
+ orderlen = abc_partpat_to_orderlist(partpat, abcparts, h, &orderlist, orderlen);
3736
+ }
3737
+ if( !SDL_strncmp(p,"V:",2) ) {
3738
+ for( t=2; p[t]==' '; t++ ) ;
3739
+ h->tp = abc_locate_track(h, p+t, 0);
3740
+ SDL_snprintf(barsig, sizeof (barsig), "%s%s", sig[abckey], sig[abckey]); // reset the key signature
3741
+ abcgrace = 0;
3742
+ brokenrithm = 0;
3743
+ h->tracktime = abc_tracktime(h->tp);
3744
+ bartime = h->tracktime; // it is not friendly to break voices in the middle of a track...
3745
+ abcnolegato = !h->tp->legato;
3746
+ if( !abcnolegato ) abcnoslurs = 0;
3747
+ *p = '%'; // make me skip the rest of the line....
3748
+ }
3749
+ if( !SDL_strncmp(p,"K:",2) ) {
3750
+ abckey = ABC_Key(p+2);
3751
+ SDL_snprintf(barsig, sizeof (barsig), "%s%s", sig[abckey], sig[abckey]); // reset the key signature
3752
+ p = abc_skip_word(p+2);
3753
+ h->ktrans = abc_transpose(p);
3754
+ *p = '%'; // make me skip the rest of the line....
3755
+ }
3756
+ if( !SDL_strncmp(p,"L:",2) ) {
3757
+ SDL_sscanf(p+2," %d / %d", &snotelen, &snotediv);
3758
+ *p = '%'; // make me skip the rest of the line....
3759
+ }
3760
+ if( !SDL_strncmp(p,"M:",2) ) {
3761
+ abc_M_field(p+2, &mnotelen, &mnotediv);
3762
+ h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv);
3763
+ *p = '%'; // make me skip the rest of the line....
3764
+ }
3765
+ if( !SDL_strncmp(p,"Q:",2) ) {
3766
+ abctempo = abc_extract_tempo(p+2,ch0=='\\');
3767
+ if( !h->track ) {
3768
+ h->tp = abc_check_track(h, h->track);
3769
+ h->tp->vno = 0; // mark reuseable (temporarely, until first notes come up)
3770
+ }
3771
+ abc_add_tempo_event(h, h->track, h->tracktime, abctempo);
3772
+ *p = '%'; // make me skip the rest of the line....
3773
+ }
3774
+ if( !SDL_strncmp(p,"T:",2) ) {
3775
+ *p = '%'; // make me skip the rest of the line....
3776
+ }
3777
+ break;
3778
+ }
3779
+ if( !SDL_strncmp(p,"m:",2) ) {
3780
+ if( abcstate != INSKIPFORX ) {
3781
+ char *pm;
3782
+ pm = abc_continuated(h, mmstack[mmsp], p);
3783
+ abc_new_macro(h, pm+2);
3784
+ if( pm != p ) {
3785
+ SDL_free(pm);
3786
+ if( h->tp ) abcnolegato = !h->tp->legato;
3787
+ if( !abcnolegato ) abcnoslurs = 0;
3788
+ }
3789
+ }
3790
+ *p = '%'; // skip rest of line
3791
+ }
3792
+ if( !SDL_strncmp(p,"U:",2) ) {
3793
+ abc_new_umacro(h, p+2);
3794
+ *p = '%'; // skip rest of line
3795
+ }
3796
+ if( !SDL_strncmp(p,"w:",2) ) { // inline lyrics
3797
+ *p = '%'; // skip rest of line
3798
+ }
3799
+ if( !SDL_strncmp(p,"W:",2) ) { // lyrics at end of song body
3800
+ *p = '%'; // skip rest of line
3801
+ }
3802
+ if( !SDL_strncmp(p,"d:",2) ) { // oldstyle decorations
3803
+ abc_message("warning: old style decorations not handled\n%s", p);
3804
+ *p = '%'; // skip rest of line
3805
+ }
3806
+ if( !SDL_strncmp(p,"s:",2) ) { // newstyle decorations (symbols)
3807
+ abc_message("warning: new style decorations not handled\n%s", p);
3808
+ *p = '%'; // skip rest of line
3809
+ }
3810
+ if( !SDL_strncmp(p,"I:",2) && abcstate != INSKIPFORX ) { // handle like oldstyle '%%command' lines
3811
+ p[0]= '%';
3812
+ p[1]= '%';
3813
+ }
3814
+ if( !SDL_strncmp(p,"%%",2) ) {
3815
+ for( p+=2; *p && SDL_isspace(*p); p++ ) ;
3816
+ if( !SDL_strncmp(p,"abc-include",11) && SDL_isspace(p[11]) ) {
3817
+ for( t=12; SDL_isspace(p[t]); t++ ) ;
3818
+ if( p[t] ) {
3819
+ #if 1 // we don't want people opening arbitrary files.
3820
+ abc_message("failure: abc-include unsupported, %s", &p[t]);
3821
+ #else
3822
+ mmsp++;
3823
+ if( mmsp == MAXABCINCLUDES ) {
3824
+ mmsp--;
3825
+ abc_message("failure: too many abc-include's, %s", &p[t]);
3826
+ } else {
3827
+ mmstack[mmsp] = mmfopen(&p[t], "r");
3828
+ if( !mmstack[mmsp] ) {
3829
+ mmsp--;
3830
+ abc_message("failure: abc-include file %s not found", &p[t]);
3831
+ }
3832
+ }
3833
+ #endif
3834
+ }
3835
+ else abc_message("failure: abc-include missing file name, %s", p);
3836
+ }
3837
+ if( !SDL_strncmp(p,"MIDI",4) && (p[4]=='=' || SDL_isspace(p[4])) && abcstate != INSKIPFORX ) {
3838
+ for( p+=5; *p && SDL_isspace(*p); p++ ) ;
3839
+ if( *p == '=' )
3840
+ for( p+=1; *p && SDL_isspace(*p); p++ ) ;
3841
+ abc_MIDI_command(h,p,'%');
3842
+ if( h->tp ) abcnolegato = !h->tp->legato;
3843
+ if( !abcnolegato ) abcnoslurs = 0;
3844
+ }
3845
+ if(*p) *p = '%'; // skip rest of line
3846
+ }
3847
+ if( abcstate == INBODY ) {
3848
+ if( *p == 'P' && p[1] == ':' ) { // a line with a part indication
3849
+ if( abcparts != NULL ) {
3850
+ // make h->tracktime start of a new age...
3851
+ if( !h->track ) {
3852
+ h->tp = abc_check_track(h, h->track);
3853
+ h->tp->vno = 0; // mark reuseable (temporarely, until first notes come up)
3854
+ }
3855
+ h->tracktime = h->track? abc_tracktime(h->track): 0; // global parts are voice independent
3856
+ abc_add_partbreak(h, h->track, h->tracktime);
3857
+ t = abc_patno(h, h->tracktime);
3858
+ if( global_part == ' ' ) {
3859
+ partpat[26][1] = t;
3860
+ if( abcparts ) {
3861
+ for( t=0; t<26; t++ )
3862
+ if( partpat[t][0] < partpat[t][1] ) break;
3863
+ if( t == 26 ) {
3864
+ abc_message("parts (%s) set but not used", abcparts);
3865
+ abc_set_parts(&abcparts, 0); // forget the parts array
3866
+ }
3867
+ }
3868
+ }
3869
+ else
3870
+ partpat[global_part - 'A'][1] = t;
3871
+ // give every new coming abcevent the desired part indication
3872
+ while( p[2]==' ' || p[2]=='.' ) p++; // skip blancs and dots
3873
+ if( IsUpper(p[2]) )
3874
+ global_part = p[2];
3875
+ else
3876
+ global_part = ' ';
3877
+ if( global_part == ' ' )
3878
+ partpat[26][0] = t;
3879
+ else
3880
+ partpat[global_part - 'A'][0] = t;
3881
+ }
3882
+ *p = '%'; // make me skip the rest of the line....
3883
+ }
3884
+ if( h->droneon && !tpd ) {
3885
+ tpd = h->track;
3886
+ if( tpd ) {
3887
+ tpd = abc_locate_track(h, tpd->v, DRONEPOS1);
3888
+ tpd->instr = h->dronegm;
3889
+ abc_add_dronenote(h, tpd, h->tracktime, h->dronepitch[0], h->dronevol[0]);
3890
+ tpd = abc_locate_track(h, tpd->v, DRONEPOS2);
3891
+ tpd->instr = h->dronegm;
3892
+ abc_add_dronenote(h, tpd, h->tracktime, h->dronepitch[1], h->dronevol[1]);
3893
+ }
3894
+ }
3895
+ if( tpd && !h->droneon ) {
3896
+ tpd = abc_locate_track(h, tpd->v, DRONEPOS1);
3897
+ abc_add_noteoff(h, tpd, h->tracktime);
3898
+ tpd = abc_locate_track(h, tpd->v, DRONEPOS2);
3899
+ abc_add_noteoff(h, tpd, h->tracktime);
3900
+ tpd = NULL;
3901
+ }
3902
+ if( h->drumon && !h->tpr ) {
3903
+ h->tpr = h->track;
3904
+ if( h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); // don't start drumming from the beginning of time!
3905
+ }
3906
+ if( h->tpr && !h->drumon ) h->tpr = NULL;
3907
+ if( *p && *p != '%' ) { // skip uninteresting lines
3908
+ // plough thru the songline gathering mos....
3909
+ ch0 = ' ';
3910
+ pp = 0;
3911
+ while( (ch = *p++) ) {
3912
+ if( !pp && IsAlpha(ch) && *p != ':' ) { // maybe a macro
3913
+ for( mp=h->umacro; mp; mp=mp->next ) {
3914
+ if( ch == mp->name[0] ) {
3915
+ pp = p;
3916
+ p = mp->subst;
3917
+ ch = *p;
3918
+ if( ch ) p++;
3919
+ break;
3920
+ }
3921
+ }
3922
+ }
3923
+ switch(ch) {
3924
+ case '%':
3925
+ abcto = 0;
3926
+ while( *p ) p++;
3927
+ break;
3928
+ case '[': // chord follows or some inline field
3929
+ abcto = 0;
3930
+ if( *p=='|' ) break; // [| a thick-thin bar line, loop around and let case '|' handle it
3931
+ if( !SDL_strncmp(p,"V:",2) ) { // inline voice change
3932
+ for( t=2; SDL_isspace(p[t]); t++ ) ;
3933
+ h->tp = abc_locate_track(h, p+t, 0);
3934
+ for( ; *p && *p != ']'; p++ ) ;
3935
+ abcgrace = 0;
3936
+ brokenrithm = 0;
3937
+ SDL_snprintf(barsig, sizeof (barsig), "%s%s", sig[abckey], sig[abckey]); // reset the key signature
3938
+ h->tracktime = abc_tracktime(h->tp);
3939
+ bartime = h->tracktime; // it is not wise to break voices in the middle of a track...
3940
+ abcvol = h->tp->volume;
3941
+ abcnolegato = !h->tp->legato;
3942
+ if( !abcnolegato ) abcnoslurs = 0;
3943
+ break;
3944
+ }
3945
+ if( !SDL_strncmp(p,"K:",2) ) {
3946
+ abckey = ABC_Key(p+2);
3947
+ SDL_snprintf(barsig, sizeof (barsig), "%s%s", sig[abckey], sig[abckey]); // reset the key signature
3948
+ p = abc_skip_word(p+2);
3949
+ h->ktrans = abc_transpose(p);
3950
+ for( ; *p && *p != ']'; p++ ) ;
3951
+ break;
3952
+ }
3953
+ if( !SDL_strncmp(p,"M:",2) ) {
3954
+ abc_M_field(p+2, &mnotelen, &mnotediv);
3955
+ for( ; *p && *p != ']'; p++ ) ;
3956
+ h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv);
3957
+ break;
3958
+ }
3959
+ if( !SDL_strncmp(p,"P:",2) ) { // a [P:X] field inline
3960
+ if( abcparts != NULL ) {
3961
+ // make h->tracktime start of a new age...
3962
+ if( h->track )
3963
+ abc_add_partbreak(h, h->track, h->tracktime);
3964
+ t = abc_patno(h, h->tracktime);
3965
+ if( global_part == ' ' )
3966
+ partpat[26][1] = t;
3967
+ else
3968
+ partpat[global_part - 'A'][1] = t;
3969
+ // give every new coming abcevent the desired part indication
3970
+ while( SDL_isspace(p[2]) || p[2]=='.' ) p++; // skip blancs and dots
3971
+ if( IsUpper(p[2]) )
3972
+ global_part = p[2];
3973
+ else
3974
+ global_part = ' ';
3975
+ if( global_part == ' ' )
3976
+ partpat[26][0] = t;
3977
+ else
3978
+ partpat[global_part - 'A'][0] = t;
3979
+ }
3980
+ for( ; *p && *p != ']'; p++ ) ;
3981
+ break;
3982
+ }
3983
+ if( !SDL_strncmp(p,"Q:",2) ) {
3984
+ abctempo = abc_extract_tempo(p+2,1);
3985
+ for( ; *p && *p != ']'; p++ ) ;
3986
+ if( h->track )
3987
+ abc_add_tempo_event(h, h->track, h->tracktime, abctempo);
3988
+ break;
3989
+ }
3990
+ if( !SDL_strncmp(p,"I:",2) ) { // interpret some of the possibilitys
3991
+ for( p += 2; SDL_isspace(*p); p++ ) ;
3992
+ if( !SDL_strncmp(p,"MIDI",4) && (p[4]=='=' || SDL_isspace(p[4])) ) { // interpret some of the possibilitys
3993
+ for( p += 4; SDL_isspace(*p); p++ ) ;
3994
+ if( *p == '=' )
3995
+ for( p += 1; SDL_isspace(*p); p++ ) ;
3996
+ abc_MIDI_command(h, p, ']');
3997
+ if( h->tp ) abcnolegato = !h->tp->legato;
3998
+ if( !abcnolegato ) abcnoslurs = 0;
3999
+ }
4000
+ for( ; *p && *p != ']'; p++ ) ; // skip rest of inline field
4001
+ }
4002
+ if( *p && p[1] == ':' ) { // some other kind of inline field
4003
+ for( ; *p && *p != ']'; p++ ) ;
4004
+ break;
4005
+ }
4006
+ if( *p && SDL_strchr("abcdefgABCDEFG^_=",*p) ) {
4007
+ int cnl[8],cnd[8],vnl,nl0=0,nd0=0; // for chords with notes of varying length
4008
+ abcchord = 0;
4009
+ vnl = 0;
4010
+ h->tp = abc_check_track(h, h->tp);
4011
+ abc_track_clear_tiedvpos(h);
4012
+ abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv));
4013
+ while( (ch=*p++) && (ch != ']') ) {
4014
+ h->tp = abc_locate_track(h, h->tp->v, abcchord? abcchord+DRONEPOS2: 0);
4015
+ p += abc_add_noteon(h, ch, p, h->tracktime, barsig, abcbeatvol, abceffect, abceffoper);
4016
+ p += abc_notelen(p, &notelen, &notediv);
4017
+ if( *p == '-' ) {
4018
+ p++;
4019
+ if( h->tp->tail && h->tp->tail->flg != 1 )
4020
+ h->tp->tienote = h->tp->tail;
4021
+ }
4022
+ if( abcchord<8 ) {
4023
+ cnl[abcchord] = notelen;
4024
+ cnd[abcchord] = notediv;
4025
+ }
4026
+ if( abcchord==0 ) {
4027
+ cnotelen = notelen;
4028
+ cnotediv = notediv;
4029
+ nl0 = notelen;
4030
+ nd0 = notediv;
4031
+ }
4032
+ else {
4033
+ if( cnotelen != notelen || cnotediv != notediv ) {
4034
+ vnl = 1;
4035
+ // update to longest duration
4036
+ if( cnotelen * notediv < notelen * cnotediv ) {
4037
+ cnotelen = notelen;
4038
+ cnotediv = notediv;
4039
+ abc_track_untie_short_chordnotes(h);
4040
+ }
4041
+ if( cnotelen * notediv > notelen * cnotediv ) {
4042
+ if( h->tp->tienote ) {
4043
+ abc_message("short notes in chord can not be tied:\n%s", h->line);
4044
+ h->tp->tienote = 0; // short chord notes cannot be tied...
4045
+ }
4046
+ }
4047
+ // update to shortest duration
4048
+ if( nl0 * notediv > notelen * nd0 ) {
4049
+ nl0 = notelen;
4050
+ nd0 = notediv;
4051
+ }
4052
+ }
4053
+ }
4054
+ abcchord++;
4055
+ }
4056
+ p += abc_notelen(p, &notelen, &notediv);
4057
+ if( (ch = *p) == '-' ) p++; // tied chord...
4058
+ if( abcarpeggio ) { // update starttime in the noteon events...
4059
+ thistime = notelen_notediv_to_ticks(h->speed, nl0*notelen*snotelen, nd0*notediv*snotediv)/abcchord;
4060
+ if( thistime > abcticks(h->speed) ) thistime = abcticks(h->speed);
4061
+ for( nl0=1; nl0<abcchord; nl0++ ) {
4062
+ h->tp = abc_locate_track(h, h->tp->v, nl0+DRONEPOS2);
4063
+ if( h->tp->tail )
4064
+ h->tp->tail->tracktick = h->tracktime + thistime * nl0;
4065
+ }
4066
+ }
4067
+ notelen *= cnotelen;
4068
+ notediv *= cnotediv;
4069
+ tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
4070
+ while( SDL_isspace(*p) ) p++; // allow spacing in broken rithm notation
4071
+ p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
4072
+ thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
4073
+ if( abcfermata ) {
4074
+ thistime <<= 1;
4075
+ abcfermata = 0;
4076
+ }
4077
+ if( thistime > abcgrace ) {
4078
+ thistime -= abcgrace;
4079
+ abcgrace = 0;
4080
+ }
4081
+ else {
4082
+ abcgrace -= thistime;
4083
+ thistime = abcticks(h->speed);
4084
+ abcgrace += abcticks(h->speed);
4085
+ }
4086
+ h->tracktime += thistime;
4087
+ while( abcchord>0 ) {
4088
+ abcchord--;
4089
+ h->tp = abc_locate_track(h, h->tp->v, abcchord? abcchord+DRONEPOS2: 0);
4090
+ if( vnl && (abcchord < 8) && (cnl[abcchord] != cnotelen || cnd[abcchord] != cnotediv) ) {
4091
+ abc_add_noteoff(h, h->tp,
4092
+ h->tracktime - thistime
4093
+ + (thistime * cnl[abcchord] * cnotediv)/(cnd[abcchord] * cnotelen) );
4094
+ }
4095
+ else {
4096
+ if( ch=='-' && h->tp->tail && h->tp->tail->flg != 1 )
4097
+ h->tp->tienote = h->tp->tail; // copy noteon event to tienote in track
4098
+ if( thistime > abcticks(h->speed) )
4099
+ abc_add_noteoff(h, h->tp, h->tracktime - abcnoslurs);
4100
+ else
4101
+ abc_add_noteoff(h, h->tp, h->tracktime);
4102
+ }
4103
+ }
4104
+ if( h->gchordon && (h->tp == h->tpc) )
4105
+ abc_add_gchord(h, h->tracktime, bartime);
4106
+ if( h->drumon && (h->tp == h->tpr) )
4107
+ abc_add_drum(h, h->tracktime, bartime);
4108
+ abcarpeggio = 0;
4109
+ if( abceffoper != 255 ) abceffect = none;
4110
+ break;
4111
+ }
4112
+ if( SDL_isdigit(*p) ) { // different endings in repeats [i,j,n-r,s,...
4113
+ h->tp = abc_check_track(h, h->tp);
4114
+ abc_add_partbreak(h, h->tp, h->tracktime);
4115
+ p += abc_getnumber(p, &notelen);
4116
+ abc_add_variant_start(h, h->tp, h->tracktime, notelen);
4117
+ while( *p==',' || *p=='-' ) {
4118
+ if( *p==',' ) {
4119
+ p++;
4120
+ p += abc_getnumber(p, &notelen);
4121
+ abc_add_variant_choise(h->tp, notelen);
4122
+ }
4123
+ else {
4124
+ p++;
4125
+ p += abc_getnumber(p, &notediv);
4126
+ while( notelen < notediv ) {
4127
+ notelen++;
4128
+ abc_add_variant_choise(h->tp, notelen);
4129
+ }
4130
+ }
4131
+ }
4132
+ break;
4133
+ }
4134
+ // collect the notes in the chord
4135
+ break;
4136
+ case '(': // slurs follow or some tuplet (duplet, triplet etc.)
4137
+ abcto = 0;
4138
+ if( SDL_isdigit(*p) ) {
4139
+ p += abc_getnumber(p,&tupletp);
4140
+ tupletr = tupletp; // ABC draft 2.0 (4.13): if r is not given it defaults to p
4141
+ switch( tupletp ) { // ABC draft 2.0 (4.13): q defaults depending on p and time signature
4142
+ case 2: case 4: case 8:
4143
+ tupletq = 3;
4144
+ break;
4145
+ case 3: case 6:
4146
+ tupletq = 2;
4147
+ break;
4148
+ default:
4149
+ if( snotediv == 8 )
4150
+ tupletq = 3;
4151
+ else
4152
+ tupletq = 2;
4153
+ break;
4154
+ }
4155
+ if( *p==':' ) {
4156
+ p++;
4157
+ if( SDL_isdigit(*p) ) p += abc_getnumber(p,&tupletq);
4158
+ if( *p==':' ) {
4159
+ p++;
4160
+ if( SDL_isdigit(*p) ) p += abc_getnumber(p,&tupletr);
4161
+ }
4162
+ }
4163
+ }
4164
+ else
4165
+ abcnoslurs=0;
4166
+ break;
4167
+ case ')': // end of slurs
4168
+ abcto = 0;
4169
+ abcnoslurs = abcnolegato;
4170
+ break;
4171
+ case '{': // grace notes follow
4172
+ abcto = 0;
4173
+ h->tp = abc_check_track(h, h->tp);
4174
+ abc_track_clear_tiedvpos(h);
4175
+ abcgrace = 0;
4176
+ abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv));
4177
+ while( (ch=*p++) && (ch != '}') ) {
4178
+ p += abc_add_noteon(h, ch, p, h->tracktime+abcgrace, barsig, abcbeatvol, none, 0);
4179
+ p += abc_notelen(p, &notelen, &notediv);
4180
+ if( *p=='-' ) {
4181
+ p++;
4182
+ if( h->tp->tail->flg != 1 )
4183
+ h->tp->tienote = h->tp->tail;
4184
+ }
4185
+ notediv *= 4; // grace notes factor 4 shorter (1/8 => 1/32)
4186
+ abcgrace += notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
4187
+ abc_add_noteoff(h, h->tp, h->tracktime + abcgrace);
4188
+ }
4189
+ h->tracktime += abcgrace;
4190
+ abc_add_sync(h, h->tp, h->tracktime);
4191
+ if( h->gchordon && (h->tp == h->tpc) )
4192
+ abc_add_gchord(h, h->tracktime, bartime);
4193
+ if( h->drumon && (h->tp == h->tpr) )
4194
+ abc_add_drum(h, h->tracktime, bartime);
4195
+ break;
4196
+ case '|': // bar symbols
4197
+ abcto = 0;
4198
+ if( h->gchordon && h->tp && (h->tp == h->tpc) )
4199
+ abc_add_gchord(h, h->tracktime, bartime);
4200
+ if( h->drumon && (h->tp == h->tpr) )
4201
+ abc_add_drum(h, h->tracktime, bartime);
4202
+ SDL_snprintf(barsig, sizeof (barsig), "%s%s", sig[abckey], sig[abckey]); // reset the key signature
4203
+ bartime = h->tracktime;
4204
+ if( h->tp && h->tp->vpos ) h->tp = abc_locate_track(h, h->tp->v, 0); // reset from voice overlay
4205
+ if( SDL_isdigit(*p) ) { // different endings in repeats |i,j,n-r,s,...
4206
+ h->tp = abc_check_track(h, h->tp);
4207
+ abc_add_partbreak(h, h->tp, h->tracktime);
4208
+ p += abc_getnumber(p, &notelen);
4209
+ abc_add_variant_start(h, h->tp, h->tracktime, notelen);
4210
+ while( *p==',' || *p=='-' ) {
4211
+ if( *p==',' ) {
4212
+ p++;
4213
+ p += abc_getnumber(p, &notelen);
4214
+ abc_add_variant_choise(h->tp, notelen);
4215
+ }
4216
+ else {
4217
+ p++;
4218
+ p += abc_getnumber(p, &notediv);
4219
+ while( notelen < notediv ) {
4220
+ notelen++;
4221
+ abc_add_variant_choise(h->tp, notelen);
4222
+ }
4223
+ }
4224
+ }
4225
+ break;
4226
+ }
4227
+ if( *p==':' ) { // repeat start
4228
+ p++;
4229
+ h->tp = abc_check_track(h, h->tp);
4230
+ abc_add_partbreak(h, h->tp, h->tracktime);
4231
+ abc_add_setloop(h, h->tp, h->tracktime);
4232
+ }
4233
+ break;
4234
+ case '&': // voice overlay
4235
+ abcto = 0;
4236
+ h->tracktime = bartime;
4237
+ h->tp = abc_check_track(h, h->tp);
4238
+ t = h->tp->vpos;
4239
+ h->tp = abc_locate_track(h, h->tp->v, t? t+1: DRONEPOS2+1);
4240
+ break;
4241
+ case ']': // staff break, end of song
4242
+ abcto = 0;
4243
+ break;
4244
+ case ':': // repeat jump
4245
+ abcto = 0;
4246
+ h->tp = abc_check_track(h, h->tp);
4247
+ j = (h->tp->slidevol == -2)? jumpfade: jumpnormal;
4248
+ abc_add_setjumploop(h, h->tp, h->tracktime, j);
4249
+ abc_add_partbreak(h, h->tp, h->tracktime);
4250
+ if( *p==':' ) { // repeat start without intermediate bar symbol
4251
+ p++;
4252
+ abc_add_setloop(h, h->tp, h->tracktime);
4253
+ }
4254
+ break;
4255
+ case '"': // chord notation
4256
+ if( !SDL_strchr("_^<>@", *p) && !SDL_isdigit(*p) ) { // if it's not a annotation string
4257
+ h->tp = abc_check_track(h, h->tp);
4258
+ if( !h->tpc ) h->tpc = abc_locate_track(h, h->tp->v, 0);
4259
+ if( h->tp == h->tpc ) abc_add_chord(p, h, h->tpc, h->tracktime); // only do chords for one voice
4260
+ }
4261
+ abcto = 0;
4262
+ while( (ch=*p++) && (ch != '"') ) {
4263
+ if( !SDL_strncasecmp(p,"fade",4) && h->track && h->track->slidevol > -2 )
4264
+ abc_globalslide(h, h->tracktime, -2); // set volumeslide to fade away...
4265
+ if( !SDL_strncasecmp(p,"to coda",7) ) {
4266
+ h->tp = abc_check_track(h, h->tp);
4267
+ abc_add_partbreak(h, h->tp, h->tracktime);
4268
+ abc_add_tocoda(h, h->tp, h->tracktime);
4269
+ p+=7;
4270
+ abcto = -1;
4271
+ }
4272
+ else
4273
+ if( !SDL_isspace(*p) ) abcto = 0;
4274
+ if( !SDL_strncasecmp(p,"to",2) && (SDL_isspace(p[2]) || p[2] == '"') ) abcto = 1;
4275
+ }
4276
+ if( !ch ) abcstate = INSKIPFORQUOTE;
4277
+ break;
4278
+ case '\\': // skip the rest of this line, should be the end of the line anyway
4279
+ while( *p ) p++;
4280
+ ch = '\\'; // remember for invoice tempo changes....
4281
+ break;
4282
+ case '!': // line break, or deprecated old style decoration
4283
+ case '+': // decorations new style
4284
+ if( !SDL_strncmp(p,"coda",4) && p[4] == ch ) {
4285
+ h->tp = abc_check_track(h, h->tp);
4286
+ if( abcto ) {
4287
+ if( abcto > 0 ) {
4288
+ abc_add_partbreak(h, h->tp, h->tracktime);
4289
+ abc_add_tocoda(h, h->tp, h->tracktime);
4290
+ }
4291
+ }
4292
+ else {
4293
+ abc_add_partbreak(h, h->tp, h->tracktime);
4294
+ abc_add_coda(h, h->tp, h->tracktime);
4295
+ }
4296
+ p += 5;
4297
+ abcto = 0;
4298
+ break;
4299
+ }
4300
+ abcto = 0;
4301
+ if( !SDL_strncmp(p,"arpeggio",8) && p[8] == ch ) {
4302
+ abcarpeggio = 1;
4303
+ p += 9;
4304
+ break;
4305
+ }
4306
+ if( !SDL_strncmp(p,"crescendo(",10) && p[10] == ch ) {
4307
+ h->tp = abc_check_track(h, h->tp);
4308
+ abc_globalslide(h, h->tracktime, 1);
4309
+ p += 11;
4310
+ break;
4311
+ }
4312
+ if( !SDL_strncmp(p,"crescendo)",10) && p[10] == ch ) {
4313
+ h->tp = abc_check_track(h, h->tp);
4314
+ abc_globalslide(h, h->tracktime, 0);
4315
+ p += 11;
4316
+ break;
4317
+ }
4318
+ if( !SDL_strncmp(p,"<(",2) && p[2] == ch ) {
4319
+ h->tp = abc_check_track(h, h->tp);
4320
+ abc_globalslide(h, h->tracktime, 1);
4321
+ p += 3;
4322
+ break;
4323
+ }
4324
+ if( !SDL_strncmp(p,"<)",2) && p[2] == ch ) {
4325
+ h->tp = abc_check_track(h, h->tp);
4326
+ abc_globalslide(h, h->tracktime, 0);
4327
+ p += 3;
4328
+ break;
4329
+ }
4330
+ if( !SDL_strncmp(p,"dimimuendo(",11) && p[11] == ch ) {
4331
+ h->tp = abc_check_track(h, h->tp);
4332
+ abc_globalslide(h, h->tracktime, -1);
4333
+ p += 12;
4334
+ break;
4335
+ }
4336
+ if( !SDL_strncmp(p,"diminuendo)",11) && p[11] == ch ) {
4337
+ h->tp = abc_check_track(h, h->tp);
4338
+ abc_globalslide(h, h->tracktime, 0);
4339
+ p += 12;
4340
+ break;
4341
+ }
4342
+ if( !SDL_strncmp(p,">(",2) && p[2] == ch ) {
4343
+ h->tp = abc_check_track(h, h->tp);
4344
+ abc_globalslide(h, h->tracktime, -1);
4345
+ p += 3;
4346
+ break;
4347
+ }
4348
+ if( !SDL_strncmp(p,">)",2) && p[2] == ch ) {
4349
+ h->tp = abc_check_track(h, h->tp);
4350
+ abc_globalslide(h, h->tracktime, 0);
4351
+ p += 3;
4352
+ break;
4353
+ }
4354
+ if( !SDL_strncmp(p,"upbow",5) && p[5] == ch ) {
4355
+ abceffect = bow;
4356
+ abceffoper = 1;
4357
+ p += 6;
4358
+ break;
4359
+ }
4360
+ if( !SDL_strncmp(p,"downbow",7) && p[7] == ch ) {
4361
+ abceffect = bow;
4362
+ abceffoper = 0;
4363
+ p += 8;
4364
+ break;
4365
+ }
4366
+ if( !SDL_strncmp(p,"trill",5) && p[5] == ch ) {
4367
+ abceffect = trill;
4368
+ abceffoper = 0;
4369
+ p += 6;
4370
+ break;
4371
+ }
4372
+ if( !SDL_strncmp(p,"trill(",6) && p[6] == ch ) {
4373
+ abceffect = trill;
4374
+ abceffoper = 255;
4375
+ p += 7;
4376
+ break;
4377
+ }
4378
+ if( !SDL_strncmp(p,"trill)",6) && p[6] == ch ) {
4379
+ abceffect = none;
4380
+ abceffoper = 0;
4381
+ p += 7;
4382
+ break;
4383
+ }
4384
+ if( !SDL_strncmp(p,"accent",6) && p[6] == ch ) {
4385
+ abceffect = accent;
4386
+ abceffoper = 0;
4387
+ p += 7;
4388
+ break;
4389
+ }
4390
+ if( !SDL_strncmp(p,"emphasis",8) && p[8] == ch ) {
4391
+ abceffect = accent;
4392
+ abceffoper = 0;
4393
+ p += 9;
4394
+ break;
4395
+ }
4396
+ if( !SDL_strncmp(p,">",1) && p[1] == ch ) {
4397
+ abceffect = accent;
4398
+ abceffoper = 0;
4399
+ p += 2;
4400
+ break;
4401
+ }
4402
+ if( !SDL_strncmp(p,"fermata",7) && p[7] == ch ) {
4403
+ abcfermata = 1;
4404
+ p += 8;
4405
+ break;
4406
+ }
4407
+ if( !SDL_strncmp(p,"fine",4) && p[4] == ch ) {
4408
+ h->tp = abc_check_track(h, h->tp);
4409
+ abc_add_partbreak(h, h->tp, h->tracktime);
4410
+ abc_add_fine(h, h->tp, h->tracktime);
4411
+ p += 5;
4412
+ break;
4413
+ }
4414
+ if( !SDL_strncmp(p,"segno",5) && p[5] == ch ) {
4415
+ h->tp = abc_check_track(h, h->tp);
4416
+ abc_add_partbreak(h, h->tp, h->tracktime);
4417
+ abc_add_segno(h, h->tp, h->tracktime);
4418
+ p += 6;
4419
+ break;
4420
+ }
4421
+ if( !SDL_strncmp(p,"tocoda",6) && p[6] == ch ) {
4422
+ h->tp = abc_check_track(h, h->tp);
4423
+ abc_add_partbreak(h, h->tp, h->tracktime);
4424
+ abc_add_tocoda(h, h->tp, h->tracktime);
4425
+ p += 7;
4426
+ break;
4427
+ }
4428
+ if( !SDL_strncmp(p,"D.C.",4) && p[4] == ch ) {
4429
+ h->tp = abc_check_track(h, h->tp);
4430
+ j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo;
4431
+ abc_add_setjumploop(h, h->tp, h->tracktime, j);
4432
+ abc_add_partbreak(h, h->tp, h->tracktime);
4433
+ p += 5;
4434
+ break;
4435
+ }
4436
+ if( !SDL_strncmp(p,"D.S.",4) && p[4] == ch ) {
4437
+ h->tp = abc_check_track(h, h->tp);
4438
+ j = (h->tp->slidevol == -2)? jumpdsfade: jumpdasegno;
4439
+ abc_add_setjumploop(h, h->tp, h->tracktime, j);
4440
+ abc_add_partbreak(h, h->tp, h->tracktime);
4441
+ p += 5;
4442
+ break;
4443
+ }
4444
+ if( !SDL_strncmp(p,"dacapo",6) && p[6] == ch ) {
4445
+ h->tp = abc_check_track(h, h->tp);
4446
+ j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo;
4447
+ abc_add_setjumploop(h, h->tp, h->tracktime, j);
4448
+ abc_add_partbreak(h, h->tp, h->tracktime);
4449
+ p += 7;
4450
+ break;
4451
+ }
4452
+ if( !SDL_strncmp(p,"dacoda",6) && p[6] == ch ) {
4453
+ h->tp = abc_check_track(h, h->tp);
4454
+ j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo;
4455
+ abc_add_setjumploop(h, h->tp, h->tracktime, j);
4456
+ abc_add_partbreak(h, h->tp, h->tracktime);
4457
+ p += 7;
4458
+ break;
4459
+ }
4460
+ if( ch == '!' ) {
4461
+ for( t=0; p[t] && SDL_strchr("|[:]!",p[t])==0 && !SDL_isspace(p[t]); t++ ) ;
4462
+ if( p[t] == '!' ) { // volume and other decorations, deprecated
4463
+ h->tp = abc_check_track(h, h->tp);
4464
+ abcvol = abc_parse_decorations(h, h->tp, p);
4465
+ p = &p[t+1];
4466
+ }
4467
+ }
4468
+ else {
4469
+ h->tp = abc_check_track(h, h->tp);
4470
+ abcvol = abc_parse_decorations(h, h->tp, p);
4471
+ while( (ch=*p++) && (ch != '+') )
4472
+ ;
4473
+ }
4474
+ break;
4475
+ case '`': // back quotes are for readability
4476
+ break;
4477
+ case '.': // staccato marks
4478
+ break;
4479
+ default: // some kinda note must follow
4480
+ if( SDL_strchr("abcdefgABCDEFG^_=X",ch) ) {
4481
+ h->tp = abc_check_track(h, h->tp);
4482
+ abc_track_clear_tiedvpos(h);
4483
+ abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv));
4484
+ p += abc_add_noteon(h, ch, p, h->tracktime, barsig, abcbeatvol, abceffect, abceffoper);
4485
+ if( abceffoper != 255 ) abceffect = none;
4486
+ p += abc_notelen(p, &notelen, &notediv);
4487
+ if( *p=='-' ) {
4488
+ p++;
4489
+ if( h->tp->tail && h->tp->tail->flg != 1 )
4490
+ h->tp->tienote = h->tp->tail;
4491
+ }
4492
+ tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
4493
+ while( SDL_isspace(*p) ) p++; // allow spacing in broken rithm notation
4494
+ p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
4495
+ thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
4496
+ if( abcfermata ) {
4497
+ thistime <<= 1;
4498
+ abcfermata = 0;
4499
+ }
4500
+ if( thistime > abcgrace ) {
4501
+ thistime -= abcgrace;
4502
+ abcgrace = 0;
4503
+ }
4504
+ else {
4505
+ abcgrace -= thistime;
4506
+ thistime = abcticks(h->speed);
4507
+ abcgrace += abcticks(h->speed);
4508
+ }
4509
+ h->tracktime += thistime;
4510
+ if( thistime > abcticks(h->speed) )
4511
+ abc_add_noteoff(h, h->tp, h->tracktime - abcnoslurs - (( ch0 == '.')? thistime / 2: 0));
4512
+ else
4513
+ abc_add_noteoff(h, h->tp, h->tracktime);
4514
+ abc_add_sync(h, h->tp, h->tracktime);
4515
+ if( h->gchordon && (h->tp == h->tpc) )
4516
+ abc_add_gchord(h, h->tracktime, bartime);
4517
+ if( h->drumon && (h->tp == h->tpr) )
4518
+ abc_add_drum(h, h->tracktime, bartime);
4519
+ abcarpeggio = 0;
4520
+ break;
4521
+ }
4522
+ if( SDL_strchr("zx",ch) ) {
4523
+ h->tp = abc_check_track(h, h->tp);
4524
+ abc_track_clear_tiednote(h);
4525
+ p += abc_notelen(p, &notelen, &notediv);
4526
+ tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
4527
+ while( SDL_isspace(*p) ) p++; // allow spacing in broken rithm notation
4528
+ p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
4529
+ thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
4530
+ if( abcfermata ) {
4531
+ thistime <<= 1;
4532
+ abcfermata = 0;
4533
+ }
4534
+ if( thistime > abcgrace ) {
4535
+ thistime -= abcgrace;
4536
+ abcgrace = 0;
4537
+ }
4538
+ else {
4539
+ abcgrace -= thistime;
4540
+ thistime = abcticks(h->speed);
4541
+ abcgrace += abcticks(h->speed);
4542
+ }
4543
+ h->tracktime += thistime;
4544
+ abc_add_sync(h, h->tp, h->tracktime);
4545
+ if( h->gchordon && (h->tp == h->tpc) )
4546
+ abc_add_gchord(h, h->tracktime, bartime);
4547
+ if( h->drumon && (h->tp == h->tpr) )
4548
+ abc_add_drum(h, h->tracktime, bartime);
4549
+ abcarpeggio = 0;
4550
+ break;
4551
+ }
4552
+ if( SDL_strchr("Z",ch) ) {
4553
+ h->tp = abc_check_track(h, h->tp);
4554
+ abc_track_clear_tiednote(h);
4555
+ p += abc_notelen(p, &notelen, &notediv);
4556
+ thistime = notelen_notediv_to_ticks(h->speed, notelen*mnotelen, notediv*mnotediv);
4557
+ if( abcfermata ) {
4558
+ thistime <<= 1;
4559
+ abcfermata = 0;
4560
+ }
4561
+ if( thistime > abcgrace ) {
4562
+ thistime -= abcgrace;
4563
+ abcgrace = 0;
4564
+ }
4565
+ else {
4566
+ abcgrace -= thistime;
4567
+ thistime = abcticks(h->speed);
4568
+ abcgrace += abcticks(h->speed);
4569
+ }
4570
+ h->tracktime += thistime;
4571
+ SDL_snprintf(barsig, sizeof (barsig), "%s%s", sig[abckey], sig[abckey]); // reset the key signature
4572
+ abc_add_sync(h, h->tp, h->tracktime);
4573
+ if( h->gchordon && (h->tp == h->tpc) )
4574
+ abc_add_gchord(h, h->tracktime, bartime);
4575
+ if( h->drumon && (h->tp == h->tpr) )
4576
+ abc_add_drum(h, h->tracktime, bartime);
4577
+ abcarpeggio = 0;
4578
+ break;
4579
+ }
4580
+ if( IsAlpha(ch) && *p==':' ) {
4581
+ // some unprocessed field line?
4582
+ while( *p ) p++; // skip it
4583
+ break;
4584
+ }
4585
+ break;
4586
+ }
4587
+ ch0 = ch; // remember previous char, can be staccato dot...
4588
+ if( pp ) { // did we have a U: macro substitution?
4589
+ if( !*p ) {
4590
+ p = pp;
4591
+ pp = 0;
4592
+ }
4593
+ }
4594
+ }
4595
+ }
4596
+ }
4597
+ }
4598
+ if( mmsp ) mmfclose(mmstack[mmsp]);
4599
+ }
4600
+ ABC_CleanupMacros(h); // we dont need them anymore
4601
+ if( !h->track ) {
4602
+ char buf[10];
4603
+ SDL_snprintf(buf,sizeof (buf),"%u",abcxnumber);
4604
+ abc_message("abc X:%s has no body", buf);
4605
+ h->track = abc_check_track(h, h->track); // for sanity...
4606
+ }
4607
+ if( abcstate == INBODY ) {
4608
+ // last but not least shut off all pending events
4609
+ abc_recalculate_tracktime(h);
4610
+ for( ttp=h->track; ttp; ttp=ttp->next )
4611
+ abc_add_noteoff(h,ttp,h->tracktime);
4612
+ abc_add_partbreak(h, h->track, h->tracktime);
4613
+ t = abc_patno(h, h->tracktime);
4614
+ if( abc_pattracktime(h, h->tracktime) % abcticks(64 * h->speed) ) t++;
4615
+ if( global_part == ' ' ) {
4616
+ partpat[26][1] = t;
4617
+ if( abcparts ) {
4618
+ for( t=0; t<26; t++ )
4619
+ if( partpat[t][0] < partpat[t][1] ) break;
4620
+ if( t == 26 ) {
4621
+ abc_message("parts (%s) set but not used", abcparts);
4622
+ abc_set_parts(&abcparts, 0); // forget the parts array
4623
+ }
4624
+ }
4625
+ }
4626
+ else
4627
+ partpat[global_part - 'A'][1] = t;
4628
+ if( !abcparts ) abc_song_to_parts(h, &abcparts, partpat);
4629
+ orderlen = abc_partpat_to_orderlist(partpat, abcparts, h, &orderlist, orderlen);
4630
+ }
4631
+ abc_synchronise_tracks(h); // distribute all control events
4632
+ abc_recalculate_tracktime(h);
4633
+ /*
4634
+
4635
+ abctrack:
4636
+ tracktick long
4637
+ note byte
4638
+ octave byte
4639
+ instrument byte
4640
+ effects byte
4641
+
4642
+ tick = tracktick modulo speed
4643
+ row = (tracktick div speed) modulo 64
4644
+ pat = (tracktick div speed) div 64
4645
+ ord = calculated
4646
+
4647
+ */
4648
+ #if 0
4649
+ if( (p=SDL_getenv(ABC_ENV_DUMPTRACKS)) ) {
4650
+ printf("P:%s\n",abcparts);
4651
+ for( t=0; t<26; t++ )
4652
+ if( partpat[t][1] >= partpat[t][0] )
4653
+ printf(" %c ",t+'A');
4654
+ if( partpat[26][1] >= partpat[26][0] )
4655
+ printf("All");
4656
+ printf("\n");
4657
+ for( t=0; t<27; t++ )
4658
+ if( partpat[t][1] >= partpat[t][0] )
4659
+ printf("%3d ",partpat[t][0]);
4660
+ printf("\n");
4661
+ for( t=0; t<27; t++ )
4662
+ if( partpat[t][1] >= partpat[t][0] )
4663
+ printf("%3d ",partpat[t][1]);
4664
+ printf("\n");
4665
+ for( t=0; (int)t<orderlen; t++ )
4666
+ printf("%3d ",t);
4667
+ printf("\n");
4668
+ for( t=0; (int)t<orderlen; t++ )
4669
+ printf("%3d ",orderlist[t]);
4670
+ printf("\n");
4671
+ abc_dumptracks(h,p);
4672
+ }
4673
+ #endif
4674
+
4675
+ // set module variables
4676
+ if( abctempo == 0 ) abctempo = abcrate;
4677
+ if( _this->m_nDefaultTempo == 0 ) _this->m_nDefaultTempo = abctempo;
4678
+ _this->m_nType = MOD_TYPE_ABC;
4679
+ numpat = 1+(modticks(h->tracktime) / h->speed / 64);
4680
+ if( numpat > MAX_PATTERNS )
4681
+ numpat = MAX_PATTERNS;
4682
+ _this->m_nDefaultSpeed = h->speed;
4683
+ _this->m_nChannels = abc_numtracks(h);
4684
+ _this->m_dwSongFlags = SONG_LINEARSLIDES;
4685
+ _this->m_nMinPeriod = 28 << 2;
4686
+ _this->m_nMaxPeriod = 1712 << 3;
4687
+ // orderlist
4688
+ for(t=0; t < (uint32_t)orderlen; t++){
4689
+ if( t >= MAX_ORDERS )
4690
+ break;
4691
+ _this->Order[t] = orderlist[t];
4692
+ }
4693
+ SDL_free(orderlist); // get rid of orderlist memory
4694
+ // ==============================
4695
+ // Load the pattern info now!
4696
+ if( ABC_ReadPatterns(_this->Patterns, _this->PatternSize, h, numpat, _this->m_nChannels) ) {
4697
+ // :^( need one more channel to handle the global events ;^b
4698
+ _this->m_nChannels++;
4699
+ h->tp = abc_locate_track(h, "", 99);
4700
+ abc_add_sync(h, h->tp, h->tracktime);
4701
+ for( t=0; t<numpat; t++ ) {
4702
+ CSoundFile_FreePattern(_this->Patterns[t]);
4703
+ _this->Patterns[t] = NULL;
4704
+ }
4705
+ ABC_ReadPatterns(_this->Patterns, _this->PatternSize, h, numpat, _this->m_nChannels);
4706
+ }
4707
+ // load instruments after building the patterns (chan == 10 track handling)
4708
+ if( !PAT_Load_Instruments(_this) ) {
4709
+ avoid_reentry = 0;
4710
+ return FALSE;
4711
+ }
4712
+ // ============================================================
4713
+ // set panning positions
4714
+ if( _this->m_nChannels > MAX_BASECHANNELS )
4715
+ _this->m_nChannels = MAX_BASECHANNELS;
4716
+ for(t=0; t<_this->m_nChannels; t++) {
4717
+ _this->ChnSettings[t].nPan = 0x30+((t+2)%5)*((0xD0 - 0x30)/5); // 0x30 = std s3m val
4718
+ _this->ChnSettings[t].nVolume = 64;
4719
+ }
4720
+ avoid_reentry = 0; // it is safe now, I'm finished
4721
+ abc_set_parts(&abcparts, 0); // free the parts array
4722
+ ABC_Cleanup(h); // we dont need it anymore
4723
+ return 1;
4724
+ }
4725
+