History

Merge remote-tracking branch 'upstream/master'

# Conflicts: # dumb/src/it/itrender.c # src/helpers/resampler.c

dmitrykos committed 8 years ago

Commit fb758de2 parents ad75b32 8430c5c182 files · +26832 −25858Browse files

Unified · Split

182 files
  1. .clang-format +3 −0
  2. .gitignore +3 −2
  3. CHANGELOG.md +59 −24
  4. CMakeLists.txt +234 −0
  5. COMPILING.md +35 −0
  6. DUMBFILE_SYSTEM.md +226 −0
  7. LICENSE +0 −0
  8. README.md +96 −0
  9. UPDATING_YOUR_PROJECTS.md +16 −0
  10. cmake-scripts/FindAllegro4.cmake +41 −0
  11. cmake-scripts/FindSDL2.cmake +0 −0
  12. cmake-scripts/Findargtable2.cmake +0 −0
  13. dumb/cmake/CMakeLists.txt +0 −149
  14. dumb/cmake/readme.txt +0 −31
  15. dumb/include/dumb.h +0 −824
  16. dumb/include/internal/barray.h +0 −43
  17. dumb/include/internal/fir_resampler.h +0 −18
  18. dumb/include/internal/it.h +0 −926
  19. dumb/include/internal/resampler.h +0 −60
  20. dumb/include/internal/riff.h +0 −24
  21. dumb/include/internal/tarray.h +0 −31
  22. dumb/prj/.gitignore +0 −3
  23. dumb/prj/dumb/dumb.pro +0 −130
  24. dumb/readme.txt +0 −541
  25. dumb/src/core/dumbfile.c +0 −418
  26. dumb/src/core/makeduh.c +0 −151
  27. dumb/src/core/readduh.c +0 −107
  28. dumb/src/core/rendduh.c +0 −331
  29. dumb/src/core/rendsig.c +0 −352
  30. dumb/src/helpers/barray.c +0 −189
  31. dumb/src/helpers/clickrem.c +0 −281
  32. dumb/src/helpers/fir_resampler.c +0 −281
  33. dumb/src/helpers/lpc.c +0 −320
  34. dumb/src/helpers/memfile.c +0 −117
  35. dumb/src/helpers/resamp2.inc +0 −162
  36. dumb/src/helpers/resamp3.inc +0 −258
  37. dumb/src/helpers/resample.c +0 −330
  38. dumb/src/helpers/resample.inc +0 −256
  39. dumb/src/helpers/riff.c +0 −85
  40. dumb/src/helpers/stdfile.c +0 −146
  41. dumb/src/helpers/tarray.c +0 −175
  42. dumb/src/it/itmisc.c +0 −249
  43. dumb/src/it/itread.c +0 −1416
  44. dumb/src/it/itrender.c +0 −6102
  45. dumb/src/it/itunload.c +0 −72
  46. dumb/src/it/ptmeffect.c +0 −125
  47. dumb/src/it/read669.c +0 −448
  48. dumb/src/it/readam.c +0 −789
  49. dumb/src/it/readamf.c +0 −559
  50. dumb/src/it/readany.c +0 −132
  51. dumb/src/it/readasy.c +0 −339
  52. dumb/src/it/readdsmf.c +0 −383
  53. dumb/src/it/readmod.c +0 −637
  54. dumb/src/it/readmtm.c +0 −413
  55. dumb/src/it/readokt.c +0 −558
  56. dumb/src/it/readoldpsm.c +0 −689
  57. dumb/src/it/readpsm.c +0 −1289
  58. dumb/src/it/readptm.c +0 −554
  59. dumb/src/it/reads3m.c +0 −766
  60. dumb/src/it/readstm.c +0 −397
  61. dumb/src/it/readxm.c +0 −1428
  62. dumb/src/it/xmeffect.c +0 −245
  63. examples/README.md +19 −0
  64. examples/dumbout.c +110 −79
  65. examples/dumbplay.c +88 −57
  66. include/aldumb.h +83 −0
  67. include/dumb.h +819 −0
  68. include/internal/aldumb.h +0 −2
  69. include/internal/barray.h +43 −0
  70. include/internal/dumb.h +35 −21
  71. include/internal/dumbfile.h +1 −2
  72. include/internal/it.h +874 −0
  73. include/internal/lpc.h +1 −1
  74. include/internal/resampler.h +70 −0
  75. include/internal/riff.h +22 −0
  76. include/internal/stack_alloc.h +17 −12
  77. include/internal/tarray.h +20 −0
  78. pkg-config.pc.in +12 −0
  79. src/allegro/alplay.c +217 −0
  80. src/allegro/datduh.c +50 −0
  81. src/allegro/datit.c +51 −0
  82. src/allegro/datitq.c +54 −0
  83. src/allegro/datmod.c +51 −0
  84. src/allegro/datmodq.c +54 −0
  85. src/allegro/dats3m.c +51 −0
  86. src/allegro/dats3mq.c +54 −0
  87. src/allegro/datunld.c +25 −0
  88. src/allegro/datxm.c +51 −0
  89. src/allegro/datxmq.c +54 −0
  90. src/allegro/packfile.c +119 −0
  91. src/core/atexit.c +25 −36
  92. src/core/duhlen.c +4 −12
  93. src/core/duhtag.c +20 −25
  94. src/core/dumbfile.c +373 −0
  95. src/core/loadduh.c +8 −11
  96. src/core/makeduh.c +146 −0
  97. src/core/rawsig.c +25 −30
  98. src/core/readduh.c +101 −0
  99. src/core/register.c +45 −53
  100. src/core/rendduh.c +261 −0
  101. src/core/rendsig.c +242 −0
  102. src/core/unload.c +24 −30
  103. src/helpers/barray.c +155 −0
  104. src/helpers/clickrem.c +257 −0
  105. src/helpers/lpc.c +340 −0
  106. src/helpers/memfile.c +94 −0
  107. src/helpers/resamp2.inc +178 −0
  108. src/helpers/resamp3.inc +278 −0
  109. src/helpers/resample.c +332 −0
  110. src/helpers/resample.inc +288 −0
  111. src/helpers/resampler.c +606 −669
  112. src/helpers/riff.c +88 −0
  113. src/helpers/sampbuf.c +18 −39
  114. src/helpers/silence.c +2 −6
  115. src/helpers/stdfile.c +113 −0
  116. src/helpers/tarray.c +180 −0
  117. src/it/itload.c +8 −12
  118. src/it/itload2.c +4 −7
  119. src/it/itmisc.c +169 −0
  120. src/it/itorder.c +34 −32
  121. src/it/itread.c +1468 −0
  122. src/it/itread2.c +4 −7
  123. src/it/itrender.c +6595 −0
  124. src/it/itunload.c +69 −0
  125. src/it/load669.c +9 −12
  126. src/it/load6692.c +5 −8
  127. src/it/loadamf.c +9 −12
  128. src/it/loadamf2.c +5 −8
  129. src/it/loadany.c +8 −11
  130. src/it/loadany2.c +4 −7
  131. src/it/loadasy.c +9 −12
  132. src/it/loadasy2.c +5 −8
  133. src/it/loadmod.c +8 −11
  134. src/it/loadmod2.c +4 −7
  135. src/it/loadmtm.c +9 −12
  136. src/it/loadmtm2.c +5 −8
  137. src/it/loadokt.c +9 −12
  138. src/it/loadokt2.c +5 −8
  139. src/it/loadoldpsm.c +9 −12
  140. src/it/loadoldpsm2.c +5 −8
  141. src/it/loadpsm.c +9 −12
  142. src/it/loadpsm2.c +5 −8
  143. src/it/loadptm.c +9 −12
  144. src/it/loadptm2.c +5 −8
  145. src/it/loadriff.c +9 −12
  146. src/it/loadriff2.c +5 −8
  147. src/it/loads3m.c +8 −11
  148. src/it/loads3m2.c +4 −7
  149. src/it/loadstm.c +9 −12
  150. src/it/loadstm2.c +5 −8
  151. src/it/loadxm.c +8 −11
  152. src/it/loadxm2.c +4 −7
  153. src/it/ptmeffect.c +174 −0
  154. src/it/read669.c +454 −0
  155. src/it/read6692.c +2 −5
  156. src/it/readam.c +805 −0
  157. src/it/readamf.c +597 −0
  158. src/it/readamf2.c +4 −7
  159. src/it/readany.c +103 −0
  160. src/it/readany2.c +4 −7
  161. src/it/readasy.c +344 −0
  162. src/it/readdsmf.c +395 −0
  163. src/it/readmod.c +651 −0
  164. src/it/readmod2.c +4 −7
  165. src/it/readmtm.c +458 −0
  166. src/it/readokt.c +605 −0
  167. src/it/readokt2.c +5 −8
  168. src/it/readoldpsm.c +745 −0
  169. src/it/readpsm.c +1418 −0
  170. src/it/readptm.c +565 −0
  171. src/it/readriff.c +22 −21
  172. src/it/reads3m.c +780 −0
  173. src/it/reads3m2.c +4 −7
  174. src/it/readstm.c +404 −0
  175. src/it/readstm2.c +5 −8
  176. src/it/readxm.c +1431 −0
  177. src/it/readxm2.c +4 −7
  178. src/it/xmeffect.c +305 −0
  179. vc6/.gitignore +0 −0
  180. vc6/dumb/dumb.vcproj +2 −2
  181. vc6/dumb/dumb.vcxproj +42 −9
  182. vc6/dumb/dumb.vcxproj.filters +0 −0
.clang-format+3−0
@@ -0,0 +1,3 @@
1BasedOnStyle: LLVM
2IndentWidth: 4
3SortIncludes: false
.gitignore+3−2
@@ -1,11 +1,12 @@
1### CMake template1
2# Cmake files
2CMakeCache.txt3CMakeCache.txt
3CMakeFiles4CMakeFiles
4CMakeScripts5CMakeScripts
5Makefile6Makefile
6cmake_install.cmake7cmake_install.cmake
7install_manifest.txt8install_manifest.txt
8### C template9
9# Object files10# Object files
10*.o11*.o
11*.ko12*.ko
CHANGELOG.mdrenamed from dumb/release.txt+59−24
@@ -1,3 +1,4 @@
1```
1/* _______ ____ __ ___ ___2/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '3 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .4 * | | \ \ | | || | \/ | . .
@@ -8,7 +9,7 @@ · 4 unmodified lines
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque9 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \10 * / \
10 * / . \11 * / . \
11 * release.txt - Release notes for DUMB. / / \ \12 * CHANGELOG.md - Release notes for DUMB. / / \ \
12 * | < / \_13 * | < / \_
13 * | \/ /\ /14 * | \/ /\ /
14 * \_ / > /15 * \_ / > /
@@ -16,11 +17,57 @@ · 1 unmodified line
16 * | ' /17 * | ' /
17 * \__/18 * \__/
18 */19 */
19 20 ```
20 21
21*******************************************22# DUMB Changelog
22*** DUMB v0.9.3, released 7 August 2005 ***23
23*******************************************24## v2.0.2, released 9 October 2017
25
26* Amended order scanner to also look for blank type patterns that would
27 cause problems with the renderer.
28* Changed all format readers to check order scanner for errors and return
29 them to the caller.
30* Changed all credits references to the correct name, now that it's more
31 widely known.
32
33## v2.0.1, released 9 October 2017
34
35* #66, Can't Use DUMB_OFF_T_CUSTOM to Fix Static Assertion On 32-Bit System
36* #69, Make LFS-checks work with MinGW.org-MinGW
37* #70, Fix internal getnc to return dumb_ssize_t
38* #71, PSM Playback Has Garbled Sound
39* Documentation updates
40* More fuzz testing revealed places where order counts were allowed
41 to be extremely high, blowing out the memory requested for the
42 timekeeping arrays. This has been severely limited now to throw errors
43 on load.
44* Added some considerations to a porting document.
45
46## v2.0.0, released 26 September 2017
47
48* Memory leak and bug fixes
49* Audio playback quality improvements for STM
50* Added support for FEST MOD files
51* Default resampling quality is now cubic
52* Allegro 4 support
53* New dumbplay, dumbout examples
54* Multiple cmake fixes
55* Deprecated `duh_render()`, use `duh_render_float()` and `duh_render_int()`
56* Removed API deprecated since 0.9.3, see the
57 [DUMB 0.9.3 deprecation reference](http://dumb.sourceforge.net/index.php?page=docs&doc=deprec)
58
59## v1.0.0, released 17 January 2015
60
61* Support newer compilers
62* Better audio playback quality
63* More supported formats
64* SSE optimizations support
65* CMake support
66* New resamplers
67* Seek support
68* Fixes, cleanups, speedups.
69
70## v0.9.3, released 7 August 2005
24 71
25Hello! Welcome to a long-awaited-or-probably-just-given-up-on-by-everybody72Hello! Welcome to a long-awaited-or-probably-just-given-up-on-by-everybody
26release! New to this release are lower memory usage, faster mixing loops,73release! New to this release are lower memory usage, faster mixing loops,
@@ -173,9 +220,7 @@ That's it! I hope you enjoy this long-awaited-or-probably-just-given-up-on- · 146 unmodified lines
173by-everybody release of DUMB!220by-everybody release of DUMB!
174 221
175 222
176******************************************223## v0.9.2, released 2 April 2003
177*** DUMB v0.9.2, released 2 April 2003 ***
178******************************************
179 224
180Yes, there really has been a release. This is not a day-late April fools'225Yes, there really has been a release. This is not a day-late April fools'
181joke.226joke.
@@ -272,9 +317,7 @@ explained in licence.txt. However, the request is still there ... · 90 unmodified lines
272As usual, enjoy!317As usual, enjoy!
273 318
274 319
275**********************************************320## v0.9.1, released 19 December 2002
276*** DUMB v0.9.1, released 19 December 2002 ***
277**********************************************
278 321
279Hi again! Lots to say this time, so I shall cut right to the chase.322Hi again! Lots to say this time, so I shall cut right to the chase.
280 323
@@ -355,9 +398,7 @@ the last release; they are relevant for this release too. · 74 unmodified lines
355That's all folks! Until next time.398That's all folks! Until next time.
356 399
357 400
358*******************************************401## v0.9, released 16 October 2002
359*** DUMB v0.9, released 16 October 2002 ***
360*******************************************
361 402
362MOD support is here! DUMB now supports all four of the common module formats.403MOD support is here! DUMB now supports all four of the common module formats.
363As usual, there have also been some improvements to the way modules are404As usual, there have also been some improvements to the way modules are
@@ -431,9 +472,7 @@ Off you go. · 67 unmodified lines
431Bye.472Bye.
432 473
433 474
434********************************************475## v0.8.1, released 11 August 2002
435*** DUMB v0.8.1, released 11 August 2002 ***
436********************************************
437 476
438This is a minor release that fixes a few bugs. One of these bugs, however,477This is a minor release that fixes a few bugs. One of these bugs, however,
439was pretty serious. dumb_register_dat_xm() was never coded! It was prototyped478was pretty serious. dumb_register_dat_xm() was never coded! It was prototyped
@@ -487,9 +526,7 @@ The point about length not being calculated also applies to XM files. · 47 unmodified lines
487Enjoy :)526Enjoy :)
488 527
489 528
490****************************************529## v0.8, released 14 June 2002
491*** DUMB v0.8, released 14 June 2002 ***
492****************************************
493 530
494Welcome to the second release of DUMB!531Welcome to the second release of DUMB!
495 532
@@ -530,9 +567,7 @@ going myself (72 GBP, and I'd have to wear a suit, ugh), but with all the · 34 unmodified lines
530noise outside I shall enjoy pumping up the speakers tonight!567noise outside I shall enjoy pumping up the speakers tonight!
531 568
532 569
533****************************************570## DUMB v0.7, released 2 March 2002
534*** DUMB v0.7, released 2 March 2002 ***
535****************************************
536 571
537This is the first release of DUMB, and parts of the library are not572This is the first release of DUMB, and parts of the library are not
538crystallised. Don't let this put you off! Provided you don't try to use any573crystallised. Don't let this put you off! Provided you don't try to use any
CMakeLists.txt+234−0
@@ -0,0 +1,234 @@
1cmake_minimum_required(VERSION 3.1)
2project(libdumb C)
3include(GNUInstallDirs)
4include(CheckCCompilerFlag)
5
6# Bump major (== soversion) on API breakages
7set(DUMB_VERSION_MAJOR 2)
8set(DUMB_VERSION_MINOR 0)
9set(DUMB_VERSION ${DUMB_VERSION_MAJOR}.${DUMB_VERSION_MINOR})
10
11set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake-scripts)
12
13option(BUILD_EXAMPLES "Build example binaries" ON)
14option(BUILD_ALLEGRO4 "Build Allegro4 support" ON)
15option(USE_SSE "Use SSE instructions" ON)
16
17function(check_and_add_c_compiler_flag flag flag_variable_to_add_to)
18 string(TOUPPER "${flag}" check_name)
19 string(MAKE_C_IDENTIFIER "CC_HAS${check_name}" check_name)
20 check_c_compiler_flag("${flag}" "${check_name}")
21 if(${check_name})
22 set(${flag_variable_to_add_to} "${flag} ${${flag_variable_to_add_to}}" PARENT_SCOPE)
23 endif()
24endfunction()
25
26check_and_add_c_compiler_flag("-Wno-unused-variable" CMAKE_C_FLAGS)
27check_and_add_c_compiler_flag("-Wno-unused-but-set-variable" CMAKE_C_FLAGS)
28check_and_add_c_compiler_flag("-Wall" CMAKE_C_FLAGS)
29add_definitions("-D_FILE_OFFSET_BITS=64")
30add_definitions("-DDUMB_DECLARE_DEPRECATED")
31
32set(CMAKE_C_FLAGS_DEBUG "-DDEBUGMODE=1 -D_DEBUG")
33check_and_add_c_compiler_flag("-ggdb" CMAKE_C_FLAGS_DEBUG)
34check_and_add_c_compiler_flag("-Zi" CMAKE_C_FLAGS_DEBUG)
35
36set(CMAKE_C_FLAGS_RELEASE "-ffast-math -O2 -DNDEBUG")
37
38set(CMAKE_C_FLAGS_RELWITHDEBINFO "-ffast-math -O2 -DNDEBUG")
39check_and_add_c_compiler_flag("-g" CMAKE_C_FLAGS_RELWITHDEBINFO)
40check_and_add_c_compiler_flag("-Zi" CMAKE_C_FLAGS_RELWITHDEBINFO)
41
42set(CMAKE_C_FLAGS_MINSIZEREL "-ffast-math -Os -DNDEBUG")
43
44if(USE_SSE)
45 check_c_compiler_flag("-msse" "CC_HAS_MSSE")
46 if(CC_HAS_MSSE)
47 message(STATUS "Compiling with SSE support")
48 set(CMAKE_C_FLAGS "-msse ${CMAKE_C_FLAGS}")
49 add_definitions("-D_USE_SSE")
50 else()
51 message(STATUS "Compiling without SSE support")
52 endif()
53endif()
54
55link_directories(${CMAKE_CURRENT_BINARY_DIR})
56include_directories(include/)
57
58if(BUILD_EXAMPLES)
59 find_package(argtable2)
60 find_package(SDL2)
61else()
62 message(STATUS "Not building examples")
63endif()
64
65if(BUILD_ALLEGRO4)
66 find_package(Allegro4)
67else()
68 message(STATUS "Not building Allegro 4 support")
69endif()
70
71SET(SOURCES
72 src/core/unload.c
73 src/core/rendsig.c
74 src/core/rendduh.c
75 src/core/register.c
76 src/core/readduh.c
77 src/core/rawsig.c
78 src/core/makeduh.c
79 src/core/loadduh.c
80 src/core/dumbfile.c
81 src/core/duhtag.c
82 src/core/duhlen.c
83 src/core/atexit.c
84 src/helpers/stdfile.c
85 src/helpers/silence.c
86 src/helpers/sampbuf.c
87 src/helpers/riff.c
88 src/helpers/resample.c
89 src/helpers/memfile.c
90 src/helpers/clickrem.c
91 src/helpers/barray.c
92 src/helpers/tarray.c
93 src/it/xmeffect.c
94 src/it/readxm2.c
95 src/it/readxm.c
96 src/it/readstm2.c
97 src/it/readstm.c
98 src/it/reads3m2.c
99 src/it/reads3m.c
100 src/it/readriff.c
101 src/it/readptm.c
102 src/it/readpsm.c
103 src/it/readoldpsm.c
104 src/it/readokt2.c
105 src/it/readokt.c
106 src/it/readmtm.c
107 src/it/readmod2.c
108 src/it/readmod.c
109 src/it/readdsmf.c
110 src/it/readasy.c
111 src/it/readamf2.c
112 src/it/readamf.c
113 src/it/readam.c
114 src/it/read6692.c
115 src/it/read669.c
116 src/it/ptmeffect.c
117 src/it/loadxm2.c
118 src/it/loadxm.c
119 src/it/loadstm2.c
120 src/it/loadstm.c
121 src/it/loads3m2.c
122 src/it/loads3m.c
123 src/it/loadriff2.c
124 src/it/loadriff.c
125 src/it/loadptm2.c
126 src/it/loadptm.c
127 src/it/loadpsm2.c
128 src/it/loadpsm.c
129 src/it/loadoldpsm2.c
130 src/it/loadoldpsm.c
131 src/it/loadokt2.c
132 src/it/loadokt.c
133 src/it/loadmtm2.c
134 src/it/loadmtm.c
135 src/it/loadmod2.c
136 src/it/loadmod.c
137 src/it/loadasy2.c
138 src/it/loadasy.c
139 src/it/loadamf2.c
140 src/it/loadamf.c
141 src/it/load6692.c
142 src/it/load669.c
143 src/it/itunload.c
144 src/it/itrender.c
145 src/it/itread2.c
146 src/it/itread.c
147 src/it/itorder.c
148 src/it/itmisc.c
149 src/it/itload2.c
150 src/it/itload.c
151 src/it/readany.c
152 src/it/loadany2.c
153 src/it/loadany.c
154 src/it/readany2.c
155 src/helpers/resampler.c
156 src/helpers/lpc.c
157)
158
159set(INSTALL_HEADERS
160 include/dumb.h
161)
162
163set(ALLEGRO_SOURCES
164 src/allegro/alplay.c
165 src/allegro/datitq.c
166 src/allegro/dats3m.c
167 src/allegro/datxm.c
168 src/allegro/datduh.c
169 src/allegro/datmod.c
170 src/allegro/dats3mq.c
171 src/allegro/datxmq.c
172 src/allegro/datit.c
173 src/allegro/datmodq.c
174 src/allegro/datunld.c
175 src/allegro/packfile.c
176)
177
178
179set(PKG_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/dumb.pc")
180
181configure_file(
182 "${CMAKE_CURRENT_SOURCE_DIR}/pkg-config.pc.in"
183 ${PKG_CONFIG_FILE}
184 @ONLY
185)
186
187add_library(dumb ${SOURCES})
188set_target_properties(dumb PROPERTIES DEBUG_POSTFIX d)
189set_target_properties(dumb PROPERTIES VERSION ${DUMB_VERSION})
190set_target_properties(dumb PROPERTIES SOVERSION ${DUMB_VERSION_MAJOR})
191
192if(BUILD_ALLEGRO4)
193 add_library(aldmb ${ALLEGRO_SOURCES})
194 set_target_properties(aldmb PROPERTIES DEBUG_POSTFIX d)
195 set_target_properties(aldmb PROPERTIES VERSION ${DUMB_VERSION})
196 set_target_properties(aldmb PROPERTIES SOVERSION ${DUMB_VERSION_MAJOR})
197 list(APPEND DUMB_TARGETS aldmb)
198 list(APPEND INSTALL_HEADERS include/aldumb.h)
199 target_include_directories(aldmb PUBLIC ${ALLEGRO_INCLUDE_DIR})
200 target_link_libraries(aldmb ${ALLEGRO_LIBRARIES} dumb)
201endif()
202
203if(BUILD_EXAMPLES)
204 add_executable(dumbout examples/dumbout.c)
205 add_executable(dumbplay examples/dumbplay.c)
206 set_property(TARGET dumbout PROPERTY C_STANDARD 99)
207 set_property(TARGET dumbplay PROPERTY C_STANDARD 99)
208 if(MINGW)
209 target_link_libraries(dumbplay mingw32)
210 endif()
211
212 target_include_directories(dumbout PRIVATE ${ARGTABLE2_INCLUDE_DIR})
213 target_link_libraries(dumbout ${ARGTABLE2_LIBRARY} m dumb)
214
215 target_include_directories(dumbplay PRIVATE ${ARGTABLE2_INCLUDE_DIR} ${SDL2_INCLUDE_DIR})
216 target_link_libraries(dumbplay ${ARGTABLE2_LIBRARY} ${SDL2_LIBRARY} dumb)
217
218 list(APPEND DUMB_TARGETS "dumbout" "dumbplay")
219endif()
220
221# Make sure the dylib install name path is set on OSX so you can include dumb in app bundles
222IF(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
223 set_target_properties(dumb PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
224ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
225
226target_link_libraries(dumb m)
227
228install(FILES ${PKG_CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
229install(FILES ${INSTALL_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
230install(TARGETS dumb ${DUMB_TARGETS}
231 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
232 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
233 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
234)
COMPILING.md+35−0
@@ -0,0 +1,35 @@
1# Compiling
2
3## 1. CMake
4
5### 1.1. Example
6
7In libdumb project root, run:
8```
9mkdir -p build
10cd build
11cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_SHARED_LIBS:BOOL=ON -DBUILD_ALLEGRO4:BOOL=ON ..
12make
13make install
14```
15
16### 1.2. Steps
17
181. Create a new temporary build directory and cd into it
192. Run libdumb cmake file with cmake (eg. `cmake -DCMAKE_INSTALL_PREFIX=/install/dir -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE=Release path/to/dumb/cmake/dir`).
203. Run make (eg. just `make` or `mingw32-make` or something).
214. If needed, run make install.
22
23### 1.3. Flags
24
25* `CMAKE_INSTALL_PREFIX` sets the installation path prefix.
26* `CMAKE_BUILD_TYPE` chooses the build type: `Release`, `Debug`, `RelWithDebInfo`, or `MinSizeRel`. Debug libraries will be named `libdumbd`, release libraries `libdumb`. Default is `Release`.
27* `BUILD_SHARED_LIBS` selects whether cmake should build a dynamic (`ON`) or static (`OFF`) library. Default is `OFF`.
28* `BUILD_ALLEGRO4` enables (`ON`) or disables (`OFF`) the optional Allegro 4 support. This requires Allegro 4 installed on the system. Default is `ON`.
29* `BUILD_EXAMPLES` selects example binaries. These example binaries require argtable2 and SDL2 libraries. Default is `ON`.
30* `USE_SSE` enables or disables SSE support. Default is `ON`.
31* You may also need to tell cmake what kind of makefiles to create with the "-G" flag. Eg. for MSYS one would say something like `cmake -G "MSYS Makefiles" .`.
32
33## 2. Visual Studio
34
35TODO
DUMBFILE_SYSTEM.md+226−0
@@ -0,0 +1,226 @@
1Specification of DUMBFILE_SYSTEM
2================================
3
4DUMB is designed filesystem-agnostic, even though the C standard library
5already defines an abstraction over files on a disk. This is useful because
6Allegro 4 and 5 define their own abstractions.
7
8To register your own filesystem abstraction with DUMB, you must create an
9instance of struct `DUMBFILE_SYSTEM`, fill in your own function pointers
10according to the specification below, and call `register_dumbfile_system` on
11your instance.
12
13The header `dumb.h` defines `DUMBFILE_SYSTEM` as a struct of function pointers:
14
15```
16typedef struct DUMBFILE_SYSTEM
17{
18 void *(*open)(const char *filename);
19 int (*skip)(void *f, dumb_off_t n);
20 int (*getc)(void *f);
21 dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
22 void (*close)(void *f);
23 int (*seek)(void *f, dumb_off_t n);
24 dumb_off_t (*get_size)(void *f);
25}
26DUMBFILE_SYSTEM;
27```
28
29Here, `dumb_off_t` is a signed integer at least 64 bits wide, it is intended
30to measure file offsets. The return type `dumb_ssize_t` is a signed integer
31exactly as wide as `size_t`, it is intended to store either a `size_t` or a
32negative error code. Both `dumb_*_t` are defined in `dumb.h`.
33
34The function pointers `skip` and `getnc` are optional, i.e., you may set
35some of these to `NULL` in your struct instance. DUMB will then try to
36mimick the missing functions' behavior by calling your `getc` several times.
37If DUMB is built with debugging flags, it will assert that all other
38functions are not `NULL`. In release mode, DUMB will silently fail.
39
40Your non-`NULL` function pointers must conform to the following specification.
41
42
43
44open
45----
46
47```
48void *(*open)(const char *filename);
49```
50
51Open a file for reading.
52
53Arguments:
54
55* `const char *filename`: A normal filename as understood by the operating
56 system. Will be opened for reading.
57
58Returns as `void *`:
59
60* the address of a file handle on successfully opening the file.
61 DUMB will pass this file handle as argument to other functions of
62 the `DUMBFILE_SYSTEM`.
63
64* `NULL` on error during opening the file.
65
66Each file has a *position* internally managed by DUMB. A newly opened file
67has a position of 0. Other functions from the `DUMBFILE_SYSTEM` can move
68this position around.
69
70DUMB allocates memory for the successfully opened file, and will store opaque
71information in that memory, e.g., the DUMB-internal file position. This memory
72be freed when DUMB calls `close` on the file's handle. The memory is separate
73from your own filesystem implementation: You are responsible for supplying the
74data, and DUMB is responsible for storing anything about interpreting that
75data.
76
77
78
79skip
80----
81
82```
83int (*skip)(void *f, dumb_off_t n);
84```
85
86Advance the position in the file.
87
88Arguments:
89
90* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
91
92* `dumb_off_t n`: Number of bytes to advance in the file. DUMB will only
93call this with `n >= 0`. For `n < 0`, the behavior of `skip` is undefined.
94
95Returns as `int`:
96
97* `0` on successfully skipping ahead by `n` bytes.
98
99* `-1` on error.
100
101It is legal to set `skip = NULL` in a `DUMBFILE_SYSTEM`. DUMB will then call
102`getc` a total of `n` times to skip ahead in a file. For speed, it is
103advisable to supply a proper `skip` implementation.
104
105
106
107getc
108----
109
110```
111int (*getc)(void *f);
112```
113
114Read a byte from the file.
115
116Arguments:
117
118* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
119
120Returns as `int`:
121
122* the value of the byte read, on successfully reading one byte.
123
124* `-1` on error.
125
126After a succesful read, DUMB will treat the file as advanced by one byte.
127
128
129
130getnc
131-----
132
133```
134dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
135```
136
137Read up to the given number of bytes from the file into a given buffer.
138
139* `char *ptr`: The start of a buffer provided by DUMB.
140
141* `size_t n`: The length of the number of bytes to be read.
142
143* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
144
145Returns as `dumb_ssize_t`:
146
147* the number of bytes successfully read, if it was possible to read at least
148one byte.
149
150* `-1` on error, when it was not possible to read even a single byte.
151
152This function shall bytes from the file `f` and store them in sequence in the
153buffer beginning at `ptr`. It shall read fewer than `n` bytes if end of file
154is encountered before `n` bytes could have been read, otherwise it should read
155`n` bytes.
156
157It is legal to set `skip = NULL` in a `DUMBFILE_SYSTEM`. DUMB will then call
158`getc` a total of `n` times and store the results in its buffer.
159
160
161
162close
163-----
164
165```
166void (*close)(void *f);
167```
168
169Closes a file that has been opened before with `open`.
170
171Arguments:
172
173* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
174
175DUMB will deallocate the memory that it used to interpret the file. You are
176free to treat your resource however you would like: You may deallocate it, or
177keep it around for other things. For example, Allegro 5's implementation
178of `close` takes a void pointer and does nothing with it at all.
179
180
181
182seek
183----
184
185```
186int (*seek)(void *f, dumb_off_t n);
187```
188
189Jump to an arbitrary position in the file.
190
191Arguments:
192
193* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
194
195* `dumb_off_t n`: The position in the file, relative to the beginning.
196 There is no guarantee whether `n >= 0`.
197
198Returns as `int`:
199
200* `0` on successfully seeking in the file.
201
202* `-1` on error.
203
204DUMB will modify its internal position of the file accordingly.
205
206A value of `n < 0` shall set the file into an erroneous state from which no
207bytes can be read.
208
209
210
211get_size
212--------
213
214```
215dumb_off_t (*get_size)(void *f);
216```
217
218Get the length in bytes, i.e., the position after the final byte, of a file.
219
220Arguments:
221
222* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
223
224Returns as `dumb_off_t`:
225
226* the length of the file in bytes.
LICENSErenamed from dumb/licence.txt+0−0

File renamed without changes.

README.md+96−0
@@ -0,0 +1,96 @@
1# Dynamic Universal Music Bibliotheque (libdumb)
2
3 _______ ____ __ ___ ___
4 \ _ \ \ / \ / \ \ / / ' ' '
5 | | \ \ | | || | \/ | . .
6 | | | | | | || ||\ /| |
7 | | | | | | || || \/ | | ' ' '
8 | | | | | | || || | | . .
9 | |_/ / \ \__// || | |
10 /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
11 / \
12 / . \
13 / / \ \
14 | < / \_
15 | \/ /\ /
16 \_ / > /
17 | \ / /
18 | ' /
19 \__/
20
21
22
23## Introduction
24
25DUMB is a module audio renderer library. It reads module files and
26outputs audio that can be dumped to the actual audio playback library.
27
28This is a fork of the original dumb (http://dumb.sf.net/) by Ben Davis.
29
30## Features
31
32- Supports playback of the following module formats. The tracker software or
33 library the format is known for is given in parentheses. This does not mean
34 that DUMB does not support files created by other trackers provided that they
35 output files in one of those formats.
36
37 * IT (Impulse Tracker)
38 * XM (Fasttracker II)
39 * MOD (Ultimate SoundTracker, ProTracker)
40 * STM (Scream Tracker)
41 * S3M (Scream Tracker 3)
42 * 669 (Composer 669)
43 * AMF Asylum Music Format
44 * AMF Digital Sound and Music Interface Advanced Music Format
45 * DSM Digital Sound Interface Kit module format
46 * MTM (MultiTracker)
47 * OKT (Oktalyzer)
48 * PSM (Protracker Studio)
49 Both the older PSM16 and the newer PSM format is supported.
50 * PTM (PolyTracker)
51 * RIFF AM/AMFF (Galaxy Music System internal format)
52
53- Audio generated can be used in any way; DUMB does not necessarily send it
54 straight to a sound output system
55
56- Portable
57
58- Faithful to the original trackers, especially IT; if it plays a module
59 wrongly, it is considered a bug
60
61- Accurate support for low-pass resonant filters for IT files
62
63- Very accurate timing and pitching; completely deterministic playback
64
65- Click removal
66
67- Six resampling quality settings: aliasing, aliasing with bandwidth limiting,
68 linear interpolation, linear interpolation with bandwidth limiting, cubic
69 interpolation, and a compile-time-configurable fast sinc resampler
70
71- Number of samples playing at once can be limited to reduce processor usage,
72 but samples will come back in when other louder ones stop
73
74- Option to take longer loading but seek fast to any point before the music
75 first loops (seeking time increases beyond this point)
76
77- All notes will be present and correct even if a module's playback is started
78 in the middle
79
80- Optional Allegro 4 or Allegro 5 integration support
81
82- Facility to embed music files in other files (e.g. Allegro datafiles)
83
84
85## Installation
86
87Currently you need to compile libdumb yourself. For more details, please see
88the file [COMPILING.md](COMPILING.md).
89
90## License
91
92See [LICENSE](LICENSE) for license details.
93
94## Contributing
95
96Bugs, feature requests and patches can be submitted at https://github.com/kode54/dumb/.
UPDATING_YOUR_PROJECTS.md+16−0
@@ -0,0 +1,16 @@
1# Updating your projects
2
3## Transition from 0.9.3 to 2.0.0 and beyond
4
5### The Basics
6
7* Build your DUMB-using project with warnings that show function pointer mismatches. Treat these warnings extremely carefully, most of them imply porting work.
8* `DUMBFILE_SYSTEM` needs 7 pointers instead of 5, and the signatures have changed. Look in include/dumb.h for a quick overview, and in DUMBFILE_SYSTEM.md for a more complete spec. Notable changes include seeking support, file length reporting, and using 64-bit safe seek offsets and file sizes.
9* Some functions return `dumb_off_t` instead of `long`. Most of that is backwards compatible unless you have function pointers to these.
10
11### Shortcomings of the 2.0 API
12
13* `DUH.length` is `dumb_off_t`, but this is not the clearest type. It's good that this is 64-bit, but it doesn't measure disk file offsets. `length` measures the total time of the DUH in 65536-ths of a second, where a DUH is a format-agnostic abstraction of a tracked song.
14* A sigrenderer is like a slider, or iterator, that moves along a DUH and decodes the music. The *position* of a sigrenderer is stored in `pos`, and this is exposed in the API as `long`. It should ideally have the same type as `DUH.length`.
15
16What's the worst impact of these shortcomings? If your `long` is 32-bit (should only happen on Windows when targeting 32-bit processors), your `pos` might be broken 2^15 seconds into a song, which is about 9 hours. It's really minimal impact, and this bug was already in DUMB 0.9.3. As of DUMB 2.0.0, this is even less of an impact, since the newer timekeeping arrays will automatically keep the `pos` within the actual detected length of a song, dropping back down to 0 again if it loops completely, or slightly higher if the loop is partway into the song. It's not perfect, but at least I tried, right?
cmake-scripts/FindAllegro4.cmake+41−0
@@ -0,0 +1,41 @@
1# - Find allegro
2# Find the native ALLEGRO includes and library
3#
4# ALLEGRO_INCLUDE_DIR - where to find allegro.h, etc.
5# ALLEGRO_LIBRARIES - List of libraries when using allegro.
6# ALLEGRO_FOUND - True if allegro found.
7
8FIND_PATH(ALLEGRO_INCLUDE_DIR allegro.h
9/usr/local/include
10/usr/include
11$ENV{MINGDIR}/include
12)
13
14if(UNIX AND NOT CYGWIN)
15 exec_program(allegro-config ARGS --libs OUTPUT_VARIABLE ALLEGRO_LIBRARY)
16else(UNIX AND NOT CYGWIN)
17 SET(ALLEGRO_NAMES alleg alleglib alleg41 alleg42 allegdll)
18 FIND_LIBRARY(ALLEGRO_LIBRARY
19 NAMES ${ALLEGRO_NAMES}
20 PATHS /usr/lib /usr/local/lib $ENV{MINGDIR}/lib)
21endif(UNIX AND NOT CYGWIN)
22
23IF (ALLEGRO_INCLUDE_DIR AND ALLEGRO_LIBRARY)
24 SET(ALLEGRO_FOUND TRUE)
25 SET( ALLEGRO_LIBRARIES ${ALLEGRO_LIBRARY} )
26ELSE (ALLEGRO_INCLUDE_DIR AND ALLEGRO_LIBRARY)
27 SET(ALLEGRO_FOUND FALSE)
28 SET( ALLEGRO_LIBRARIES )
29ENDIF (ALLEGRO_INCLUDE_DIR AND ALLEGRO_LIBRARY)
30
31IF (ALLEGRO_FOUND)
32 MESSAGE(STATUS "Found Allegro: ${ALLEGRO_LIBRARY}")
33ELSE (ALLEGRO_FOUND)
34 MESSAGE(STATUS "Looked for Allegro libraries named ${ALLEGRO_NAMES}.")
35 MESSAGE(FATAL_ERROR "Could NOT find Allegro library")
36ENDIF (ALLEGRO_FOUND)
37
38MARK_AS_ADVANCED(
39ALLEGRO_LIBRARY
40ALLEGRO_INCLUDE_DIR
41)
cmake-scripts/FindSDL2.cmakerenamed from dumb/cmake/cmake-scripts/FindSDL2.cmake+0−0

File renamed without changes.

cmake-scripts/Findargtable2.cmakerenamed from dumb/cmake/cmake-scripts/Findargtable2.cmake+0−0

File renamed without changes.

dumb/cmake/CMakeLists.txt+0−149
@@ -1,149 +0,0 @@
1cmake_minimum_required(VERSION 3.1)
2project(libdumb C)
3
4set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake-scripts)
5
6option(BUILD_EXAMPLES "Build example binaries" ON)
7
8set(CMAKE_C_FLAGS "-Wall -DDUMB_DECLARE_DEPRECATED -D_USE_SSE -msse -Wno-unused-variable -Wno-unused-but-set-variable")
9set(CMAKE_C_FLAGS_DEBUG "-ggdb -DDEBUGMODE=1 -D_DEBUG")
10set(CMAKE_C_FLAGS_RELEASE "-ffast-math -O2 -DNDEBUG")
11set(CMAKE_C_FLAGS_RELWITHDEBINFO "-ffast-math -g -O2 -DNDEBUG")
12set(CMAKE_C_FLAGS_MINSIZEREL "-ffast-math -Os -DNDEBUG")
13
14link_directories(${CMAKE_CURRENT_BINARY_DIR})
15include_directories(../include/)
16
17if(BUILD_EXAMPLES)
18 find_package(argtable2)
19 find_package(SDL2)
20else()
21 message(STATUS "Not building examples")
22endif()
23
24SET(SOURCES
25 ../src/core/unload.c
26 ../src/core/rendsig.c
27 ../src/core/rendduh.c
28 ../src/core/register.c
29 ../src/core/readduh.c
30 ../src/core/rawsig.c
31 ../src/core/makeduh.c
32 ../src/core/loadduh.c
33 ../src/core/dumbfile.c
34 ../src/core/duhtag.c
35 ../src/core/duhlen.c
36 ../src/core/atexit.c
37 ../src/helpers/stdfile.c
38 ../src/helpers/silence.c
39 ../src/helpers/sampbuf.c
40 ../src/helpers/riff.c
41 ../src/helpers/resample.c
42 ../src/helpers/memfile.c
43 ../src/helpers/clickrem.c
44 ../src/helpers/barray.c
45 ../src/helpers/tarray.c
46 ../src/it/xmeffect.c
47 ../src/it/readxm2.c
48 ../src/it/readxm.c
49 ../src/it/readstm2.c
50 ../src/it/readstm.c
51 ../src/it/reads3m2.c
52 ../src/it/reads3m.c
53 ../src/it/readriff.c
54 ../src/it/readptm.c
55 ../src/it/readpsm.c
56 ../src/it/readoldpsm.c
57 ../src/it/readokt2.c
58 ../src/it/readokt.c
59 ../src/it/readmtm.c
60 ../src/it/readmod2.c
61 ../src/it/readmod.c
62 ../src/it/readdsmf.c
63 ../src/it/readasy.c
64 ../src/it/readamf2.c
65 ../src/it/readamf.c
66 ../src/it/readam.c
67 ../src/it/read6692.c
68 ../src/it/read669.c
69 ../src/it/ptmeffect.c
70 ../src/it/loadxm2.c
71 ../src/it/loadxm.c
72 ../src/it/loadstm2.c
73 ../src/it/loadstm.c
74 ../src/it/loads3m2.c
75 ../src/it/loads3m.c
76 ../src/it/loadriff2.c
77 ../src/it/loadriff.c
78 ../src/it/loadptm2.c
79 ../src/it/loadptm.c
80 ../src/it/loadpsm2.c
81 ../src/it/loadpsm.c
82 ../src/it/loadoldpsm2.c
83 ../src/it/loadoldpsm.c
84 ../src/it/loadokt2.c
85 ../src/it/loadokt.c
86 ../src/it/loadmtm2.c
87 ../src/it/loadmtm.c
88 ../src/it/loadmod2.c
89 ../src/it/loadmod.c
90 ../src/it/loadasy2.c
91 ../src/it/loadasy.c
92 ../src/it/loadamf2.c
93 ../src/it/loadamf.c
94 ../src/it/load6692.c
95 ../src/it/load669.c
96 ../src/it/itunload.c
97 ../src/it/itrender.c
98 ../src/it/itread2.c
99 ../src/it/itread.c
100 ../src/it/itorder.c
101 ../src/it/itmisc.c
102 ../src/it/itload2.c
103 ../src/it/itload.c
104 ../src/it/readany.c
105 ../src/it/loadany2.c
106 ../src/it/loadany.c
107 ../src/it/readany2.c
108 ../src/helpers/resampler.c
109 ../src/helpers/lpc.c
110)
111
112set(INSTALL_HEADERS
113 ../include/dumb.h
114)
115
116add_library(dumb ${SOURCES})
117set_target_properties(dumb PROPERTIES DEBUG_POSTFIX d)
118
119set(EXAMPLE_TARGETS "")
120
121if(BUILD_EXAMPLES)
122 add_executable(dumbout ../examples/dumbout.c)
123 add_executable(dumbplay ../examples/dumbplay.c)
124 set_property(TARGET dumbout PROPERTY C_STANDARD 99)
125 set_property(TARGET dumbplay PROPERTY C_STANDARD 99)
126 if(MINGW)
127 target_link_libraries(dumbplay mingw32)
128 endif()
129
130 target_link_libraries(dumbout ${ARGTABLE2_LIBRARY} m dumb)
131 target_link_libraries(dumbplay ${ARGTABLE2_LIBRARY} ${SDL2_LIBRARY} dumb)
132
133 include_directories(${ARGTABLE2_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} "../examples/")
134 set(EXAMPLE_TARGETS ${EXAMPLE_TARGETS} "dumbout" "dumbplay")
135endif()
136
137# Make sure the dylib install name path is set on OSX so you can include dumb in app bundles
138IF(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
139 set_target_properties(dumb PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/lib)
140ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
141
142target_link_libraries(dumb m)
143
144INSTALL(FILES ${INSTALL_HEADERS} DESTINATION include/)
145INSTALL(TARGETS dumb ${EXAMPLE_TARGETS}
146 RUNTIME DESTINATION bin
147 LIBRARY DESTINATION lib${LIB_SUFFIX}
148 ARCHIVE DESTINATION lib${LIB_SUFFIX}
149)
dumb/cmake/readme.txt+0−31
@@ -1,31 +0,0 @@
1Howto build libdumb with cmake
2==============================
3
4A quick example
5---------------
6
7In libdumb cmake directory (dumb/cmake/), run:
8```
9mkdir -p build
10cd build
11cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_SHARED_LIBS:BOOL=ON ..
12make
13make install
14```
15
16Steps
17-----
18
191. Create a new temporary build directory and cd into it
202. Run libdumb cmake file with cmake (eg. `cmake -DCMAKE_INSTALL_PREFIX=/install/dir -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE=Release path/to/dumb/cmake/dir`).
213. Run make (eg. just `make` or `mingw32-make` or something).
224. If needed, run make install.
23
24Flags
25-----
26
27* CMAKE_INSTALL_PREFIX sets the installation path prefix
28* CMAKE_BUILD_TYPE sets the build type (eg. Release, Debug, RelWithDebInfo, MinSizeRel). Debug libraries will be named libdumbd, release libraries libdumb.
29* BUILD_SHARED_LIBS selects whether cmake should build dynamic or static library. On by default. (On=shared, OFF=static)
30* BUILD_EXAMPLES selects example binaries. Note that example binaries require argtable2 and SDL2 libraries. On by default.
31* You may also need to tell cmake what kind of makefiles to create with the "-G" flag. Eg. for MSYS one would say something like `cmake -G "MSYS Makefiles" .`.
dumb/include/dumb.h+0−824
@@ -1,824 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * dumb.h - The user header file for DUMB. / / \ \
12 * | < / \_
13 * Include this file in any of your files in | \/ /\ /
14 * which you wish to use the DUMB functions \_ / > /
15 * and variables. | \ / /
16 * | ' /
17 * Allegro users, you will probably want aldumb.h. \__/
18 */
19
20#ifndef DUMB_H
21#define DUMB_H
22
23
24#include <stdlib.h>
25#include <stdio.h>
26
27#ifdef _DEBUG
28#ifdef _MSC_VER
29#define _CRTDBG_MAP_ALLOC
30#include <crtdbg.h>
31#endif
32#endif
33
34#ifdef __cplusplus
35 extern "C" {
36#endif
37
38
39#define DUMB_MAJOR_VERSION 1
40#define DUMB_MINOR_VERSION 0
41#define DUMB_REVISION_VERSION 0
42
43#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION)
44
45#define DUMB_VERSION_STR "1.0.0"
46
47#define DUMB_NAME "DUMB v" DUMB_VERSION_STR
48
49#define DUMB_YEAR 2015
50#define DUMB_MONTH 1
51#define DUMB_DAY 17
52
53#define DUMB_YEAR_STR2 "15"
54#define DUMB_YEAR_STR4 "2015"
55#define DUMB_MONTH_STR1 "1"
56#define DUMB_DAY_STR1 "17"
57
58#if DUMB_MONTH < 10
59#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1
60#else
61#define DUMB_MONTH_STR2 DUMB_MONTH_STR1
62#endif
63
64#if DUMB_DAY < 10
65#define DUMB_DAY_STR2 "0" DUMB_DAY_STR1
66#else
67#define DUMB_DAY_STR2 DUMB_DAY_STR1
68#endif
69
70
71/* WARNING: The month and day were inadvertently swapped in the v0.8 release.
72 * Please do not compare this constant against any date in 2002. In
73 * any case, DUMB_VERSION is probably more useful for this purpose.
74 */
75#define DUMB_DATE (DUMB_YEAR*10000 + DUMB_MONTH*100 + DUMB_DAY)
76
77#define DUMB_DATE_STR DUMB_DAY_STR1 "." DUMB_MONTH_STR1 "." DUMB_YEAR_STR4
78
79
80#undef MIN
81#undef MAX
82#undef MID
83
84#define MIN(x,y) (((x) < (y)) ? (x) : (y))
85#define MAX(x,y) (((x) > (y)) ? (x) : (y))
86#define MID(x,y,z) MAX((x), MIN((y), (z)))
87
88#undef ABS
89#define ABS(x) (((x) >= 0) ? (x) : (-(x)))
90
91
92#ifdef DEBUGMODE
93
94#ifndef ASSERT
95#include <assert.h>
96#define ASSERT(n) assert(n)
97#endif
98#ifndef TRACE
99// it would be nice if this did actually trace ...
100#define TRACE 1 ? (void)0 : (void)printf
101#endif
102
103#else
104
105#ifndef ASSERT
106#define ASSERT(n)
107#endif
108#ifndef TRACE
109#define TRACE 1 ? (void)0 : (void)printf
110#endif
111
112#endif
113
114
115#define DUMB_ID(a,b,c,d) (((unsigned int)(a) << 24) | \
116 ((unsigned int)(b) << 16) | \
117 ((unsigned int)(c) << 8) | \
118 ((unsigned int)(d) ))
119
120
121
122#ifndef LONG_LONG
123#if defined __GNUC__ || defined __INTEL_COMPILER || defined __MWERKS__
124#define LONG_LONG long long
125#elif defined _MSC_VER || defined __WATCOMC__
126#define LONG_LONG __int64
127#elif defined __sgi
128#define LONG_LONG long long
129#else
130#error 64-bit integer type unknown
131#endif
132#endif
133
134#if __GNUC__ * 100 + __GNUC_MINOR__ >= 301 /* GCC 3.1+ */
135#ifndef DUMB_DECLARE_DEPRECATED
136#define DUMB_DECLARE_DEPRECATED
137#endif
138#define DUMB_DEPRECATED __attribute__((__deprecated__))
139#else
140#define DUMB_DEPRECATED
141#endif
142
143
144/* Basic Sample Type. Normal range is -0x800000 to 0x7FFFFF. */
145
146typedef int sample_t;
147
148
149/* Library Clean-up Management */
150
151int dumb_atexit(void (*proc)(void));
152
153void dumb_exit(void);
154
155
156/* File Input Functions */
157
158typedef struct DUMBFILE_SYSTEM
159{
160 void *(*open)(const char *filename);
161 int (*skip)(void *f, long n);
162 int (*getc)(void *f);
163 long (*getnc)(char *ptr, long n, void *f);
164 void (*close)(void *f);
165 int (*seek)(void *f, long n);
166 long (*get_size)(void *f);
167}
168DUMBFILE_SYSTEM;
169
170typedef struct DUMBFILE DUMBFILE;
171
172void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs);
173
174DUMBFILE *dumbfile_open(const char *filename);
175DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs);
176
177long dumbfile_pos(DUMBFILE *f);
178int dumbfile_skip(DUMBFILE *f, long n);
179
180#define DFS_SEEK_SET 0
181#define DFS_SEEK_CUR 1
182#define DFS_SEEK_END 2
183
184int dumbfile_seek(DUMBFILE *f, long n, int origin);
185
186long dumbfile_get_size(DUMBFILE *f);
187
188int dumbfile_getc(DUMBFILE *f);
189
190int dumbfile_igetw(DUMBFILE *f);
191int dumbfile_mgetw(DUMBFILE *f);
192
193long dumbfile_igetl(DUMBFILE *f);
194long dumbfile_mgetl(DUMBFILE *f);
195
196unsigned long dumbfile_cgetul(DUMBFILE *f);
197signed long dumbfile_cgetsl(DUMBFILE *f);
198
199long dumbfile_getnc(char *ptr, long n, DUMBFILE *f);
200
201int dumbfile_error(DUMBFILE *f);
202int dumbfile_close(DUMBFILE *f);
203
204
205/* stdio File Input Module */
206
207void dumb_register_stdfiles(void);
208
209DUMBFILE *dumbfile_open_stdfile(FILE *p);
210
211
212/* Memory File Input Module */
213
214DUMBFILE *dumbfile_open_memory(const char *data, long size);
215
216
217/* DUH Management */
218
219typedef struct DUH DUH;
220
221#define DUH_SIGNATURE DUMB_ID('D','U','H','!')
222
223void unload_duh(DUH *duh);
224
225DUH *load_duh(const char *filename);
226DUH *read_duh(DUMBFILE *f);
227
228long duh_get_length(DUH *duh);
229
230const char *duh_get_tag(DUH *duh, const char *key);
231int duh_get_tag_iterator_size(DUH *duh);
232int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i);
233
234/* Signal Rendering Functions */
235
236typedef struct DUH_SIGRENDERER DUH_SIGRENDERER;
237
238DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos);
239
240#ifdef DUMB_DECLARE_DEPRECATED
241typedef void (*DUH_SIGRENDERER_CALLBACK)(void *data, sample_t **samples, int n_channels, long length);
242/* This is deprecated, but is not marked as such because GCC tends to
243 * complain spuriously when the typedef is used later. See comments below.
244 */
245
246void duh_sigrenderer_set_callback(
247 DUH_SIGRENDERER *sigrenderer,
248 DUH_SIGRENDERER_CALLBACK callback, void *data
249) DUMB_DEPRECATED;
250/* The 'callback' argument's type has changed for const-correctness. See the
251 * DUH_SIGRENDERER_CALLBACK definition just above. Also note that the samples
252 * in the buffer are now 256 times as large; the normal range is -0x800000 to
253 * 0x7FFFFF. The function has been renamed partly because its functionality
254 * has changed slightly and partly so that its name is more meaningful. The
255 * new one is duh_sigrenderer_set_analyser_callback(), and the typedef for
256 * the function pointer has also changed, from DUH_SIGRENDERER_CALLBACK to
257 * DUH_SIGRENDERER_ANALYSER_CALLBACK. (If you wanted to use this callback to
258 * apply a DSP effect, don't worry; there is a better way of doing this. It
259 * is undocumented, so contact me and I shall try to help. Contact details
260 * are in readme.txt.)
261 */
262
263typedef void (*DUH_SIGRENDERER_ANALYSER_CALLBACK)(void *data, const sample_t *const *samples, int n_channels, long length);
264/* This is deprecated, but is not marked as such because GCC tends to
265 * complain spuriously when the typedef is used later. See comments below.
266 */
267
268void duh_sigrenderer_set_analyser_callback(
269 DUH_SIGRENDERER *sigrenderer,
270 DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data
271) DUMB_DEPRECATED;
272/* This is deprecated because the meaning of the 'samples' parameter in the
273 * callback needed to change. For stereo applications, the array used to be
274 * indexed with samples[channel][pos]. It is now indexed with
275 * samples[0][pos*2+channel]. Mono sample data are still indexed with
276 * samples[0][pos]. The array is still 2D because samples will probably only
277 * ever be interleaved in twos. In order to fix your code, adapt it to the
278 * new sample layout and then call
279 * duh_sigrenderer_set_sample_analyser_callback below instead of this
280 * function.
281 */
282#endif
283
284typedef void (*DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK)(void *data, const sample_t *const *samples, int n_channels, long length);
285
286void duh_sigrenderer_set_sample_analyser_callback(
287 DUH_SIGRENDERER *sigrenderer,
288 DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data
289);
290
291int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer);
292long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer);
293
294void duh_sigrenderer_set_sigparam(DUH_SIGRENDERER *sigrenderer, unsigned char id, long value);
295
296#ifdef DUMB_DECLARE_DEPRECATED
297long duh_sigrenderer_get_samples(
298 DUH_SIGRENDERER *sigrenderer,
299 float volume, float delta,
300 long size, sample_t **samples
301) DUMB_DEPRECATED;
302/* The sample format has changed, so if you were using this function,
303 * you should switch to duh_sigrenderer_generate_samples() and change
304 * how you interpret the samples array. See the comments for
305 * duh_sigrenderer_set_analyser_callback().
306 */
307#endif
308
309long duh_sigrenderer_generate_samples(
310 DUH_SIGRENDERER *sigrenderer,
311 float volume, float delta,
312 long size, sample_t **samples
313);
314
315void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples);
316
317void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer);
318
319
320/* DUH Rendering Functions */
321
322/* For packed integers: 8, 16, 24-bit wide.
323 * Intermediary buffer sig_samples must be freed with destroy_sample_buffer()
324 * in the end of the rendering loop.
325 */
326long duh_render_int(
327 DUH_SIGRENDERER *sigrenderer,
328 sample_t ***sig_samples,
329 long *sig_samples_size,
330 int bits, int unsign,
331 float volume, float delta,
332 long size, void *sptr
333);
334
335/* For floats: 32, 64-bit wide.
336 * Intermediary buffer sig_samples must be freed with destroy_sample_buffer()
337 * in the end of the rendering loop.
338 */
339long duh_render_float(
340 DUH_SIGRENDERER *sigrenderer,
341 sample_t ***sig_samples,
342 long *sig_samples_size,
343 int bits,
344 float volume, float delta,
345 long size, void *sptr
346);
347
348#ifdef DUMB_DECLARE_DEPRECATED
349
350long duh_render(
351 DUH_SIGRENDERER *sigrenderer,
352 int bits, int unsign,
353 float volume, float delta,
354 long size, void *sptr
355) DUMB_DEPRECATED;
356
357long duh_render_signal(
358 DUH_SIGRENDERER *sigrenderer,
359 float volume, float delta,
360 long size, sample_t **samples
361) DUMB_DEPRECATED;
362/* Please use duh_sigrenderer_generate_samples(), and see the
363 * comments for the deprecated duh_sigrenderer_get_samples() too.
364 */
365
366typedef DUH_SIGRENDERER DUH_RENDERER DUMB_DEPRECATED;
367/* Please use DUH_SIGRENDERER instead of DUH_RENDERER. */
368
369DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) DUMB_DEPRECATED;
370/* Please use duh_start_sigrenderer() instead. Pass 0 for 'sig'. */
371
372int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
373long duh_renderer_get_position(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
374/* Please use the duh_sigrenderer_*() equivalents of these two functions. */
375
376void duh_end_renderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
377/* Please use duh_end_sigrenderer() instead. */
378
379DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer) DUMB_DEPRECATED;
380DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
381DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
382/* These functions have become no-ops that just return the parameter.
383 * So, for instance, replace
384 * duh_renderer_encapsulate_sigrenderer(my_sigrenderer)
385 * with
386 * my_sigrenderer
387 */
388
389#endif
390
391
392/* Impulse Tracker Support */
393
394extern int dumb_it_max_to_mix;
395
396typedef struct DUMB_IT_SIGDATA DUMB_IT_SIGDATA;
397typedef struct DUMB_IT_SIGRENDERER DUMB_IT_SIGRENDERER;
398
399DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh);
400DUH_SIGRENDERER *duh_encapsulate_it_sigrenderer(DUMB_IT_SIGRENDERER *it_sigrenderer, int n_channels, long pos);
401DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer);
402
403int dumb_it_trim_silent_patterns(DUH * duh);
404
405typedef int (*dumb_scan_callback)(void *, int, long);
406int dumb_it_scan_for_playable_orders(DUMB_IT_SIGDATA *sigdata, dumb_scan_callback callback, void * callback_data);
407
408DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels, int startorder);
409
410enum
411{
412 DUMB_IT_RAMP_NONE = 0,
413 DUMB_IT_RAMP_ONOFF_ONLY = 1,
414 DUMB_IT_RAMP_FULL = 2
415};
416
417void dumb_it_set_ramp_style(DUMB_IT_SIGRENDERER * sigrenderer, int ramp_style);
418
419void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data);
420void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data);
421void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data, int channel, unsigned char midi_byte), void *data);
422void dumb_it_set_global_volume_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data);
423
424int dumb_it_callback_terminate(void *data);
425int dumb_it_callback_midi_block(void *data, int channel, unsigned char midi_byte);
426
427/* dumb_*_mod*: restrict_ |= 1-Don't read 15 sample files / 2-Use old pattern counting method */
428
429DUH *dumb_load_it(const char *filename);
430DUH *dumb_load_xm(const char *filename);
431DUH *dumb_load_s3m(const char *filename);
432DUH *dumb_load_stm(const char *filename);
433DUH *dumb_load_mod(const char *filename, int restrict_);
434DUH *dumb_load_ptm(const char *filename);
435DUH *dumb_load_669(const char *filename);
436DUH *dumb_load_psm(const char *filename, int subsong);
437DUH *dumb_load_old_psm(const char * filename);
438DUH *dumb_load_mtm(const char *filename);
439DUH *dumb_load_riff(const char *filename);
440DUH *dumb_load_asy(const char *filename);
441DUH *dumb_load_amf(const char *filename);
442DUH *dumb_load_okt(const char *filename);
443
444DUH *dumb_read_it(DUMBFILE *f);
445DUH *dumb_read_xm(DUMBFILE *f);
446DUH *dumb_read_s3m(DUMBFILE *f);
447DUH *dumb_read_stm(DUMBFILE *f);
448DUH *dumb_read_mod(DUMBFILE *f, int restrict_);
449DUH *dumb_read_ptm(DUMBFILE *f);
450DUH *dumb_read_669(DUMBFILE *f);
451DUH *dumb_read_psm(DUMBFILE *f, int subsong);
452DUH *dumb_read_old_psm(DUMBFILE *f);
453DUH *dumb_read_mtm(DUMBFILE *f);
454DUH *dumb_read_riff(DUMBFILE *f);
455DUH *dumb_read_asy(DUMBFILE *f);
456DUH *dumb_read_amf(DUMBFILE *f);
457DUH *dumb_read_okt(DUMBFILE *f);
458
459DUH *dumb_load_it_quick(const char *filename);
460DUH *dumb_load_xm_quick(const char *filename);
461DUH *dumb_load_s3m_quick(const char *filename);
462DUH *dumb_load_stm_quick(const char *filename);
463DUH *dumb_load_mod_quick(const char *filename, int restrict_);
464DUH *dumb_load_ptm_quick(const char *filename);
465DUH *dumb_load_669_quick(const char *filename);
466DUH *dumb_load_psm_quick(const char *filename, int subsong);
467DUH *dumb_load_old_psm_quick(const char * filename);
468DUH *dumb_load_mtm_quick(const char *filename);
469DUH *dumb_load_riff_quick(const char *filename);
470DUH *dumb_load_asy_quick(const char *filename);
471DUH *dumb_load_amf_quick(const char *filename);
472DUH *dumb_load_okt_quick(const char *filename);
473
474DUH *dumb_read_it_quick(DUMBFILE *f);
475DUH *dumb_read_xm_quick(DUMBFILE *f);
476DUH *dumb_read_s3m_quick(DUMBFILE *f);
477DUH *dumb_read_stm_quick(DUMBFILE *f);
478DUH *dumb_read_mod_quick(DUMBFILE *f, int restrict_);
479DUH *dumb_read_ptm_quick(DUMBFILE *f);
480DUH *dumb_read_669_quick(DUMBFILE *f);
481DUH *dumb_read_psm_quick(DUMBFILE *f, int subsong);
482DUH *dumb_read_old_psm_quick(DUMBFILE *f);
483DUH *dumb_read_mtm_quick(DUMBFILE *f);
484DUH *dumb_read_riff_quick(DUMBFILE *f);
485DUH *dumb_read_asy_quick(DUMBFILE *f);
486DUH *dumb_read_amf_quick(DUMBFILE *f);
487DUH *dumb_read_okt_quick(DUMBFILE *f);
488
489DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong);
490DUH *dumb_read_any(DUMBFILE *f, int restrict_, int subsong);
491
492DUH *dumb_load_any_quick(const char *filename, int restrict_, int subsong);
493DUH *dumb_load_any(const char *filename, int restrict_, int subsong);
494
495long dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata, int startorder);
496void dumb_it_do_initial_runthrough(DUH *duh);
497
498int dumb_get_psm_subsong_count(DUMBFILE *f);
499
500const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd);
501
502int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd);
503int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd);
504int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd);
505
506const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i);
507const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i);
508const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i);
509const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd, int i);
510
511int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd);
512void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv);
513
514int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd);
515void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv);
516
517int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd);
518void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed);
519
520int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd);
521void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo);
522
523int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel);
524void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume);
525
526int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr);
527int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr);
528
529int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr);
530void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv);
531
532int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr);
533void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo);
534
535int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr);
536void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed);
537
538#define DUMB_IT_N_CHANNELS 64
539#define DUMB_IT_N_NNA_CHANNELS 192
540#define DUMB_IT_TOTAL_CHANNELS (DUMB_IT_N_CHANNELS + DUMB_IT_N_NNA_CHANNELS)
541
542/* Channels passed to any of these functions are 0-based */
543int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel);
544void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume);
545
546int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel);
547void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted);
548
549typedef struct DUMB_IT_CHANNEL_STATE DUMB_IT_CHANNEL_STATE;
550
551struct DUMB_IT_CHANNEL_STATE
552{
553 int channel; /* 0-based; meaningful for NNA channels */
554 int sample; /* 1-based; 0 if nothing playing, then other fields undef */
555 int freq; /* in Hz */
556 float volume; /* 1.0 maximum; affected by ALL factors, inc. mixing vol */
557 unsigned char pan; /* 0-64, 100 for surround */
558 signed char subpan; /* use (pan + subpan/256.0f) or ((pan<<8)+subpan) */
559 unsigned char filter_cutoff; /* 0-127 cutoff=127 AND resonance=0 */
560 unsigned char filter_subcutoff; /* 0-255 -> no filters (subcutoff */
561 unsigned char filter_resonance; /* 0-127 always 0 in this case) */
562 /* subcutoff only changes from zero if filter envelopes are in use. The
563 * calculation (filter_cutoff + filter_subcutoff/256.0f) gives a more
564 * accurate filter cutoff measurement as a float. It would often be more
565 * useful to use a scaled int such as ((cutoff<<8) + subcutoff).
566 */
567};
568
569/* Values of 64 or more will access NNA channels here. */
570void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel, DUMB_IT_CHANNEL_STATE *state);
571
572
573/* Signal Design Helper Values */
574
575/* Use pow(DUMB_SEMITONE_BASE, n) to get the 'delta' value to transpose up by
576 * n semitones. To transpose down, use negative n.
577 */
578#define DUMB_SEMITONE_BASE 1.059463094359295309843105314939748495817
579
580/* Use pow(DUMB_QUARTERTONE_BASE, n) to get the 'delta' value to transpose up
581 * by n quartertones. To transpose down, use negative n.
582 */
583#define DUMB_QUARTERTONE_BASE 1.029302236643492074463779317738953977823
584
585/* Use pow(DUMB_PITCH_BASE, n) to get the 'delta' value to transpose up by n
586 * units. In this case, 256 units represent one semitone; 3072 units
587 * represent one octave. These units are used by the sequence signal (SEQU).
588 */
589#define DUMB_PITCH_BASE 1.000225659305069791926712241547647863626
590
591
592/* Signal Design Function Types */
593
594typedef void sigdata_t;
595typedef void sigrenderer_t;
596
597typedef sigdata_t *(*DUH_LOAD_SIGDATA)(DUH *duh, DUMBFILE *file);
598
599typedef sigrenderer_t *(*DUH_START_SIGRENDERER)(
600 DUH *duh,
601 sigdata_t *sigdata,
602 int n_channels,
603 long pos
604);
605
606typedef void (*DUH_SIGRENDERER_SET_SIGPARAM)(
607 sigrenderer_t *sigrenderer,
608 unsigned char id, long value
609);
610
611typedef long (*DUH_SIGRENDERER_GENERATE_SAMPLES)(
612 sigrenderer_t *sigrenderer,
613 float volume, float delta,
614 long size, sample_t **samples
615);
616
617typedef void (*DUH_SIGRENDERER_GET_CURRENT_SAMPLE)(
618 sigrenderer_t *sigrenderer,
619 float volume,
620 sample_t *samples
621);
622
623typedef long (*DUH_SIGRENDERER_GET_POSITION)(
624 sigrenderer_t *sigrenderer
625);
626
627typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer);
628
629typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata);
630
631
632/* Signal Design Function Registration */
633
634typedef struct DUH_SIGTYPE_DESC
635{
636 long type;
637 DUH_LOAD_SIGDATA load_sigdata;
638 DUH_START_SIGRENDERER start_sigrenderer;
639 DUH_SIGRENDERER_SET_SIGPARAM sigrenderer_set_sigparam;
640 DUH_SIGRENDERER_GENERATE_SAMPLES sigrenderer_generate_samples;
641 DUH_SIGRENDERER_GET_CURRENT_SAMPLE sigrenderer_get_current_sample;
642 DUH_SIGRENDERER_GET_POSITION sigrenderer_get_position;
643 DUH_END_SIGRENDERER end_sigrenderer;
644 DUH_UNLOAD_SIGDATA unload_sigdata;
645}
646DUH_SIGTYPE_DESC;
647
648void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc);
649
650int duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata);
651
652
653// Decide where to put these functions; new heading?
654
655sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type);
656
657DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos);
658sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type);
659
660
661/* Standard Signal Types */
662
663//void dumb_register_sigtype_sample(void);
664
665
666/* Sample Buffer Allocation Helpers */
667
668#ifdef DUMB_DECLARE_DEPRECATED
669sample_t **create_sample_buffer(int n_channels, long length) DUMB_DEPRECATED;
670/* DUMB has been changed to interleave stereo samples. Use
671 * allocate_sample_buffer() instead, and see the comments for
672 * duh_sigrenderer_set_analyser_callback().
673 */
674#endif
675sample_t **allocate_sample_buffer(int n_channels, long length);
676void destroy_sample_buffer(sample_t **samples);
677
678
679/* Silencing Helper */
680
681void dumb_silence(sample_t *samples, long length);
682
683
684/* Click Removal Helpers */
685
686typedef struct DUMB_CLICK_REMOVER DUMB_CLICK_REMOVER;
687
688DUMB_CLICK_REMOVER *dumb_create_click_remover(void);
689void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step);
690void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife);
691sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr);
692void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr);
693
694DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n);
695void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step);
696void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step);
697void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife);
698void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset);
699void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr);
700
701
702/* Resampling Helpers */
703
704#define DUMB_RQ_ALIASING 0
705#define DUMB_RQ_BLEP 1
706#define DUMB_RQ_LINEAR 2
707#define DUMB_RQ_BLAM 3
708#define DUMB_RQ_CUBIC 4
709#define DUMB_RQ_FIR 5
710#define DUMB_RQ_N_LEVELS 6
711
712extern int dumb_resampling_quality; /* This specifies the default */
713void dumb_it_set_resampling_quality(DUMB_IT_SIGRENDERER * sigrenderer, int quality); /* This overrides it */
714
715typedef struct DUMB_RESAMPLER DUMB_RESAMPLER;
716
717typedef struct DUMB_VOLUME_RAMP_INFO DUMB_VOLUME_RAMP_INFO;
718
719typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data);
720
721struct DUMB_RESAMPLER
722{
723 void *src;
724 long pos;
725 int subpos;
726 long start, end;
727 int dir;
728 DUMB_RESAMPLE_PICKUP pickup;
729 void *pickup_data;
730 int quality;
731 /* Everything below this point is internal: do not use. */
732 union {
733 sample_t x24[3*2];
734 short x16[3*2];
735 signed char x8[3*2];
736 } x;
737 int overshot;
738 double fir_resampler_ratio;
739 void* fir_resampler[2];
740};
741
742struct DUMB_VOLUME_RAMP_INFO
743{
744 float volume;
745 float delta;
746 float target;
747 float mix;
748 unsigned char declick_stage;
749};
750
751void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, int src_channels, long pos, long start, long end, int quality);
752DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, int src_channels, long pos, long start, long end, int quality);
753long dumb_resample_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta);
754long dumb_resample_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
755long dumb_resample_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
756long dumb_resample_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
757void dumb_resample_get_current_sample_1_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst);
758void dumb_resample_get_current_sample_1_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
759void dumb_resample_get_current_sample_2_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
760void dumb_resample_get_current_sample_2_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
761void dumb_end_resampler(DUMB_RESAMPLER *resampler);
762
763void dumb_reset_resampler_16(DUMB_RESAMPLER *resampler, short *src, int src_channels, long pos, long start, long end, int quality);
764DUMB_RESAMPLER *dumb_start_resampler_16(short *src, int src_channels, long pos, long start, long end, int quality);
765long dumb_resample_16_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta);
766long dumb_resample_16_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
767long dumb_resample_16_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
768long dumb_resample_16_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
769void dumb_resample_get_current_sample_16_1_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst);
770void dumb_resample_get_current_sample_16_1_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
771void dumb_resample_get_current_sample_16_2_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
772void dumb_resample_get_current_sample_16_2_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
773void dumb_end_resampler_16(DUMB_RESAMPLER *resampler);
774
775void dumb_reset_resampler_8(DUMB_RESAMPLER *resampler, signed char *src, int src_channels, long pos, long start, long end, int quality);
776DUMB_RESAMPLER *dumb_start_resampler_8(signed char *src, int src_channels, long pos, long start, long end, int quality);
777long dumb_resample_8_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta);
778long dumb_resample_8_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
779long dumb_resample_8_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
780long dumb_resample_8_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
781void dumb_resample_get_current_sample_8_1_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst);
782void dumb_resample_get_current_sample_8_1_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
783void dumb_resample_get_current_sample_8_2_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
784void dumb_resample_get_current_sample_8_2_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
785void dumb_end_resampler_8(DUMB_RESAMPLER *resampler);
786
787void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, long pos, long start, long end, int quality);
788DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, long pos, long start, long end, int quality);
789long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta);
790long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
791long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
792long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta);
793void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst);
794void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
795void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
796void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
797void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler);
798
799/* This sets the default panning separation for hard panned formats,
800 or for formats with default panning information. This must be set
801 before using any readers or loaders, and is not really thread safe. */
802
803extern int dumb_it_default_panning_separation; /* in percent, default 25 */
804
805/* DUH Construction */
806
807DUH *make_duh(
808 long length,
809 int n_tags,
810 const char *const tag[][2],
811 int n_signals,
812 DUH_SIGTYPE_DESC *desc[],
813 sigdata_t *sigdata[]
814);
815
816void duh_set_length(DUH *duh, long length);
817
818
819#ifdef __cplusplus
820 }
821#endif
822
823
824#endif /* DUMB_H */
dumb/include/internal/barray.h+0−43
@@ -1,43 +0,0 @@
1#ifndef _B_ARRAY_H_
2#define _B_ARRAY_H_
3
4#include <stdlib.h>
5
6#ifdef BARRAY_DECORATE
7#undef PASTE
8#undef EVALUATE
9#define PASTE(a,b) a ## b
10#define EVALUATE(a,b) PASTE(a,b)
11#define bit_array_create EVALUATE(BARRAY_DECORATE,_bit_array_create)
12#define bit_array_destroy EVALUATE(BARRAY_DECORATE,_bit_array_destroy)
13#define bit_array_dup EVALUATE(BARRAY_DECORATE,_bit_array_dup)
14#define bit_array_reset EVALUATE(BARRAY_DECORATE,_bit_array_reset)
15#define bit_array_set EVALUATE(BARRAY_DECORATE,_bit_array_set)
16#define bit_array_set_range EVALUATE(BARRAY_DECORATE,_bit_array_set_range)
17#define bit_array_test EVALUATE(BARRAY_DECORATE,_bit_array_test)
18#define bit_array_test_range EVALUATE(BARRAY_DECORATE,_bit_array_test_range)
19#define bit_array_clear EVALUATE(BARRAY_DECORATE,_bit_array_clear)
20#define bit_array_clear_range EVALUATE(BARRAY_DECORATE,_bit_array_clear_range)
21#define bit_array_merge EVALUATE(BARRAY_DECORATE,_bit_array_merge)
22#define bit_array_mask EVALUATE(BARRAY_DECORATE,_bit_array_mask)
23#endif
24
25void * bit_array_create(size_t size);
26void bit_array_destroy(void * array);
27void * bit_array_dup(void * array);
28
29void bit_array_reset(void * array);
30
31void bit_array_set(void * array, size_t bit);
32void bit_array_set_range(void * array, size_t bit, size_t count);
33
34int bit_array_test(void * array, size_t bit);
35int bit_array_test_range(void * array, size_t bit, size_t count);
36
37void bit_array_clear(void * array, size_t bit);
38void bit_array_clear_range(void * array, size_t bit, size_t count);
39
40void bit_array_merge(void * array, void * source, size_t offset);
41void bit_array_mask(void * array, void * source, size_t offset);
42
43#endif
dumb/include/internal/fir_resampler.h+0−18
@@ -1,18 +0,0 @@
1#ifndef _FIR_RESAMPLER_H_
2#define _FIR_RESAMPLER_H_
3
4void fir_init();
5
6void * fir_resampler_create();
7void fir_resampler_delete(void *);
8void * fir_resampler_dup(void *);
9
10int fir_resampler_get_free_count(void *);
11void fir_resampler_write_sample(void *, short sample);
12void fir_resampler_set_rate( void *, double new_factor );
13int fir_resampler_ready(void *);
14void fir_resampler_clear(void *);
15int fir_resampler_get_sample(void *);
16void fir_resampler_remove_sample(void *);
17
18#endif
dumb/include/internal/it.h+0−926
@@ -1,926 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * internal/it.h - Internal stuff for IT playback / / \ \
12 * and MOD/XM/S3M conversion. | < / \_
13 * | \/ /\ /
14 * This header file provides access to the \_ / > /
15 * internal structure of DUMB, and is liable | \ / /
16 * to change, mutate or cease to exist at any | ' /
17 * moment. Include it at your own peril. \__/
18 *
19 * ...
20 *
21 * Seriously. You don't need access to anything in this file. All right, you
22 * probably do actually. But if you use it, you will be relying on a specific
23 * version of DUMB, so please check DUMB_VERSION defined in dumb.h. Please
24 * contact the authors so that we can provide a public API for what you need.
25 */
26
27#ifndef INTERNAL_IT_H
28#define INTERNAL_IT_H
29
30
31#define BIT_ARRAY_BULLSHIT
32
33#include <stddef.h>
34
35#include "barray.h"
36#include "tarray.h"
37
38
39/** TO DO: THINK ABOUT THE FOLLOWING:
40
41sigdata->flags & IT_COMPATIBLE_GXX
42
43 Bit 5: On = Link Effect G's memory with Effect E/F. Also
44 Gxx with an instrument present will cause the
45 envelopes to be retriggered. If you change a
46 sample on a row with Gxx, it'll adjust the
47 frequency of the current note according to:
48
49 NewFrequency = OldFrequency * NewC5 / OldC5;
50*/
51
52
53
54/* These #defines are TEMPORARY. They are used to write alternative code to
55 * handle ambiguities in the format specification. The correct code in each
56 * case will be determined most likely by experimentation.
57 */
58//#define STEREO_SAMPLES_COUNT_AS_TWO
59#define INVALID_ORDERS_END_SONG
60#define SUSTAIN_LOOP_OVERRIDES_NORMAL_LOOP
61#define VOLUME_OUT_OF_RANGE_SETS_MAXIMUM
62
63
64
65#define SIGTYPE_IT DUMB_ID('I', 'T', ' ', ' ')
66
67#define IT_SIGNATURE DUMB_ID('I', 'M', 'P', 'M')
68#define IT_INSTRUMENT_SIGNATURE DUMB_ID('I', 'M', 'P', 'I')
69#define IT_SAMPLE_SIGNATURE DUMB_ID('I', 'M', 'P', 'S')
70
71// olivier sux
72#define IT_MPTX_SIGNATURE DUMB_ID('X', 'T', 'P', 'M')
73#define IT_INSM_SIGNATURE DUMB_ID('M', 'S', 'N', 'I')
74
75
76/* This is divided by the tempo times 256 to get the interval between ticks.
77 */
78#define TICK_TIME_DIVIDEND (65536 * 5 * 128)
79
80
81
82/* I'm not going to try to explain this, because I didn't derive it very
83 * formally ;)
84 */
85/* #define AMIGA_DIVISOR ((float)(4.0 * 14317056.0)) */
86/* I believe the following one to be more accurate. */
87//#define AMIGA_DIVISOR ((float)(8.0 * 7159090.5))
88#define AMIGA_CLOCK 3546895
89#define AMIGA_DIVISOR ((float)(16.0 * AMIGA_CLOCK))
90
91
92
93typedef struct IT_MIDI IT_MIDI;
94typedef struct IT_FILTER_STATE IT_FILTER_STATE;
95typedef struct IT_ENVELOPE IT_ENVELOPE;
96typedef struct IT_INSTRUMENT IT_INSTRUMENT;
97typedef struct IT_SAMPLE IT_SAMPLE;
98typedef struct IT_ENTRY IT_ENTRY;
99typedef struct IT_PATTERN IT_PATTERN;
100typedef struct IT_PLAYING_ENVELOPE IT_PLAYING_ENVELOPE;
101typedef struct IT_PLAYING IT_PLAYING;
102typedef struct IT_CHANNEL IT_CHANNEL;
103typedef struct IT_CHECKPOINT IT_CHECKPOINT;
104typedef struct IT_CALLBACKS IT_CALLBACKS;
105
106
107
108struct IT_MIDI
109{
110 unsigned char SFmacro[16][16]; // read these from 0x120
111 unsigned char SFmacrolen[16];
112 unsigned short SFmacroz[16]; /* Bitfield; bit 0 set = z in first position */
113 unsigned char Zmacro[128][16]; // read these from 0x320
114 unsigned char Zmacrolen[128];
115};
116
117
118
119struct IT_FILTER_STATE
120{
121 sample_t currsample, prevsample;
122};
123
124
125
126#define IT_ENVELOPE_ON 1
127#define IT_ENVELOPE_LOOP_ON 2
128#define IT_ENVELOPE_SUSTAIN_LOOP 4
129#define IT_ENVELOPE_CARRY 8
130#define IT_ENVELOPE_PITCH_IS_FILTER 128
131
132struct IT_ENVELOPE
133{
134 unsigned char flags;
135 unsigned char n_nodes;
136 unsigned char loop_start;
137 unsigned char loop_end;
138 unsigned char sus_loop_start;
139 unsigned char sus_loop_end;
140 signed char node_y[25];
141 unsigned short node_t[25];
142};
143
144
145
146#define NNA_NOTE_CUT 0
147#define NNA_NOTE_CONTINUE 1
148#define NNA_NOTE_OFF 2
149#define NNA_NOTE_FADE 3
150
151#define DCT_OFF 0
152#define DCT_NOTE 1
153#define DCT_SAMPLE 2
154#define DCT_INSTRUMENT 3
155
156#define DCA_NOTE_CUT 0
157#define DCA_NOTE_OFF 1
158#define DCA_NOTE_FADE 2
159
160struct IT_INSTRUMENT
161{
162 unsigned char name[27];
163 unsigned char filename[14];
164
165 int fadeout;
166
167 IT_ENVELOPE volume_envelope;
168 IT_ENVELOPE pan_envelope;
169 IT_ENVELOPE pitch_envelope;
170
171 unsigned char new_note_action;
172 unsigned char dup_check_type;
173 unsigned char dup_check_action;
174 signed char pp_separation;
175 unsigned char pp_centre;
176 unsigned char global_volume;
177 unsigned char default_pan;
178 unsigned char random_volume;
179 unsigned char random_pan;
180
181 unsigned char filter_cutoff;
182 unsigned char filter_resonance;
183
184 unsigned char map_note[120];
185 unsigned short map_sample[120];
186
187 //int output;
188};
189
190
191
192#define IT_SAMPLE_EXISTS 1
193#define IT_SAMPLE_16BIT 2
194#define IT_SAMPLE_STEREO 4
195#define IT_SAMPLE_LOOP 16
196#define IT_SAMPLE_SUS_LOOP 32
197#define IT_SAMPLE_PINGPONG_LOOP 64
198#define IT_SAMPLE_PINGPONG_SUS_LOOP 128
199
200#define IT_VIBRATO_SINE 0
201#define IT_VIBRATO_SAWTOOTH 1
202#define IT_VIBRATO_SQUARE 2
203#define IT_VIBRATO_RANDOM 3
204#define IT_VIBRATO_XM_SQUARE 4
205#define IT_VIBRATO_RAMP_DOWN 5
206#define IT_VIBRATO_RAMP_UP 6
207
208struct IT_SAMPLE
209{
210 unsigned char name[35];
211 unsigned char filename[15];
212 unsigned char flags;
213 unsigned char global_volume;
214 unsigned char default_volume;
215 unsigned char default_pan;
216 /* default_pan:
217 * 0-255 for XM
218 * ignored for MOD
219 * otherwise, 0-64, and add 128 to enable
220 */
221
222 long length;
223 long loop_start;
224 long loop_end;
225 long C5_speed;
226 long sus_loop_start;
227 long sus_loop_end;
228
229 unsigned char vibrato_speed;
230 unsigned char vibrato_depth;
231 unsigned char vibrato_rate;
232 unsigned char vibrato_waveform;
233
234 signed short finetune;
235
236 void *data;
237
238 int max_resampling_quality;
239};
240
241
242
243#define IT_ENTRY_NOTE 1
244#define IT_ENTRY_INSTRUMENT 2
245#define IT_ENTRY_VOLPAN 4
246#define IT_ENTRY_EFFECT 8
247
248#define IT_SET_END_ROW(entry) ((entry)->channel = 255)
249#define IT_IS_END_ROW(entry) ((entry)->channel >= DUMB_IT_N_CHANNELS)
250
251#define IT_NOTE_OFF 255
252#define IT_NOTE_CUT 254
253
254#define IT_ENVELOPE_SHIFT 8
255
256#define IT_SURROUND 100
257#define IT_IS_SURROUND(pan) ((pan) > 64)
258#define IT_IS_SURROUND_SHIFTED(pan) ((pan) > 64 << IT_ENVELOPE_SHIFT)
259
260#define IT_SET_SPEED 1
261#define IT_JUMP_TO_ORDER 2
262#define IT_BREAK_TO_ROW 3
263#define IT_VOLUME_SLIDE 4
264#define IT_PORTAMENTO_DOWN 5
265#define IT_PORTAMENTO_UP 6
266#define IT_TONE_PORTAMENTO 7
267#define IT_VIBRATO 8
268#define IT_TREMOR 9
269#define IT_ARPEGGIO 10
270#define IT_VOLSLIDE_VIBRATO 11
271#define IT_VOLSLIDE_TONEPORTA 12
272#define IT_SET_CHANNEL_VOLUME 13
273#define IT_CHANNEL_VOLUME_SLIDE 14
274#define IT_SET_SAMPLE_OFFSET 15
275#define IT_PANNING_SLIDE 16
276#define IT_RETRIGGER_NOTE 17
277#define IT_TREMOLO 18
278#define IT_S 19
279#define IT_SET_SONG_TEMPO 20
280#define IT_FINE_VIBRATO 21
281#define IT_SET_GLOBAL_VOLUME 22
282#define IT_GLOBAL_VOLUME_SLIDE 23
283#define IT_SET_PANNING 24
284#define IT_PANBRELLO 25
285#define IT_MIDI_MACRO 26 //see MIDI.TXT
286
287/* Some effects needed for XM compatibility */
288#define IT_XM_PORTAMENTO_DOWN 27
289#define IT_XM_PORTAMENTO_UP 28
290#define IT_XM_FINE_VOLSLIDE_DOWN 29
291#define IT_XM_FINE_VOLSLIDE_UP 30
292#define IT_XM_RETRIGGER_NOTE 31
293#define IT_XM_KEY_OFF 32
294#define IT_XM_SET_ENVELOPE_POSITION 33
295
296/* More effects needed for PTM compatibility */
297#define IT_PTM_NOTE_SLIDE_DOWN 34
298#define IT_PTM_NOTE_SLIDE_UP 35
299#define IT_PTM_NOTE_SLIDE_DOWN_RETRIG 36
300#define IT_PTM_NOTE_SLIDE_UP_RETRIG 37
301
302/* More effects needed for OKT compatibility */
303#define IT_OKT_NOTE_SLIDE_DOWN 38
304#define IT_OKT_NOTE_SLIDE_DOWN_ROW 39
305#define IT_OKT_NOTE_SLIDE_UP 40
306#define IT_OKT_NOTE_SLIDE_UP_ROW 41
307#define IT_OKT_ARPEGGIO_3 42
308#define IT_OKT_ARPEGGIO_4 43
309#define IT_OKT_ARPEGGIO_5 44
310#define IT_OKT_VOLUME_SLIDE_DOWN 45
311#define IT_OKT_VOLUME_SLIDE_UP 46
312
313#define IT_N_EFFECTS 47
314
315/* These represent the top nibble of the command value. */
316#define IT_S_SET_FILTER 0 /* Greyed out in IT... */
317#define IT_S_SET_GLISSANDO_CONTROL 1 /* Greyed out in IT... */
318#define IT_S_FINETUNE 2 /* Greyed out in IT... */
319#define IT_S_SET_VIBRATO_WAVEFORM 3
320#define IT_S_SET_TREMOLO_WAVEFORM 4
321#define IT_S_SET_PANBRELLO_WAVEFORM 5
322#define IT_S_FINE_PATTERN_DELAY 6
323#define IT_S7 7
324#define IT_S_SET_PAN 8
325#define IT_S_SET_SURROUND_SOUND 9
326#define IT_S_SET_HIGH_OFFSET 10
327#define IT_S_PATTERN_LOOP 11
328#define IT_S_DELAYED_NOTE_CUT 12
329#define IT_S_NOTE_DELAY 13
330#define IT_S_PATTERN_DELAY 14
331#define IT_S_SET_MIDI_MACRO 15
332
333/*
334S0x Set filter
335S1x Set glissando control
336S2x Set finetune
337
338
339S3x Set vibrato waveform to type x
340S4x Set tremelo waveform to type x
341S5x Set panbrello waveform to type x
342 Waveforms for commands S3x, S4x and S5x:
343 0: Sine wave
344 1: Ramp down
345 2: Square wave
346 3: Random wave
347S6x Pattern delay for x ticks
348S70 Past note cut
349S71 Past note off
350S72 Past note fade
351S73 Set NNA to note cut
352S74 Set NNA to continue
353S75 Set NNA to note off
354S76 Set NNA to note fade
355S77 Turn off volume envelope
356S78 Turn on volume envelope
357S79 Turn off panning envelope
358S7A Turn on panning envelope
359S7B Turn off pitch envelope
360S7C Turn on pitch envelope
361S8x Set panning position
362S91 Set surround sound
363SAy Set high value of sample offset yxx00h
364SB0 Set loopback point
365SBx Loop x times to loopback point
366SCx Note cut after x ticks
367SDx Note delay for x ticks
368SEx Pattern delay for x rows
369SFx Set parameterised MIDI Macro
370*/
371
372struct IT_ENTRY
373{
374 unsigned char channel; /* End of row if channel >= DUMB_IT_N_CHANNELS */
375 unsigned char mask;
376 unsigned char note;
377 unsigned char instrument;
378 unsigned char volpan;
379 unsigned char effect;
380 unsigned char effectvalue;
381};
382
383
384
385struct IT_PATTERN
386{
387 int n_rows;
388 int n_entries;
389 IT_ENTRY *entry;
390};
391
392
393
394#define IT_STEREO 1
395#define IT_USE_INSTRUMENTS 4
396#define IT_LINEAR_SLIDES 8 /* If not set, use Amiga slides */
397#define IT_OLD_EFFECTS 16
398#define IT_COMPATIBLE_GXX 32
399
400/* Make sure IT_WAS_AN_XM and IT_WAS_A_MOD aren't set accidentally */
401#define IT_REAL_FLAGS 63
402
403#define IT_WAS_AN_XM 64 /* Set for both XMs and MODs */
404#define IT_WAS_A_MOD 128
405
406#define IT_WAS_AN_S3M 256
407
408#define IT_WAS_A_PTM 512
409
410#define IT_WAS_A_669 1024
411
412#define IT_WAS_AN_OKT 2048
413
414#define IT_WAS_AN_STM 4096
415
416#define IT_WAS_PROCESSED 8192 /* Will be set the first time a sigdata passes through a sigrenderer */
417
418#define IT_ORDER_END 255
419#define IT_ORDER_SKIP 254
420
421struct DUMB_IT_SIGDATA
422{
423 unsigned char name[65];
424
425 unsigned char *song_message;
426
427 int n_orders;
428 int n_instruments;
429 int n_samples;
430 int n_patterns;
431 int n_pchannels;
432
433 int flags;
434
435 int global_volume;
436 int mixing_volume;
437 int speed;
438 int tempo;
439 int pan_separation;
440
441 unsigned char channel_pan[DUMB_IT_N_CHANNELS];
442 unsigned char channel_volume[DUMB_IT_N_CHANNELS];
443
444 unsigned char *order;
445 unsigned char restart_position; /* for XM compatiblity */
446
447 IT_INSTRUMENT *instrument;
448 IT_SAMPLE *sample;
449 IT_PATTERN *pattern;
450
451 IT_MIDI *midi;
452
453 IT_CHECKPOINT *checkpoint;
454};
455
456
457
458struct IT_PLAYING_ENVELOPE
459{
460 int next_node;
461 int tick;
462 int value;
463};
464
465
466
467#define IT_PLAYING_BACKGROUND 1
468#define IT_PLAYING_SUSTAINOFF 2
469#define IT_PLAYING_FADING 4
470#define IT_PLAYING_DEAD 8
471#define IT_PLAYING_REVERSE 16
472
473struct IT_PLAYING
474{
475 int flags;
476
477 int resampling_quality;
478
479 IT_CHANNEL *channel;
480 IT_SAMPLE *sample;
481 IT_INSTRUMENT *instrument;
482 IT_INSTRUMENT *env_instrument;
483
484 unsigned short sampnum;
485 unsigned char instnum;
486
487 unsigned char declick_stage;
488
489 float float_volume[2];
490 float ramp_volume[2];
491 float ramp_delta[2];
492
493 unsigned char channel_volume;
494
495 unsigned char volume;
496 unsigned short pan;
497
498 signed char volume_offset, panning_offset;
499
500 unsigned char note;
501
502 unsigned char enabled_envelopes;
503
504 unsigned char filter_cutoff;
505 unsigned char filter_resonance;
506
507 unsigned short true_filter_cutoff; /* These incorporate the filter envelope, and will not */
508 unsigned char true_filter_resonance; /* be changed if they would be set to 127<<8 and 0. */
509
510 unsigned char vibrato_speed;
511 unsigned char vibrato_depth;
512 unsigned char vibrato_n; /* May be specified twice: volpan & effect. */
513 unsigned char vibrato_time;
514 unsigned char vibrato_waveform;
515
516 unsigned char tremolo_speed;
517 unsigned char tremolo_depth;
518 unsigned char tremolo_time;
519 unsigned char tremolo_waveform;
520
521 unsigned char panbrello_speed;
522 unsigned char panbrello_depth;
523 unsigned char panbrello_time;
524 unsigned char panbrello_waveform;
525 signed char panbrello_random;
526
527 unsigned char sample_vibrato_time;
528 unsigned char sample_vibrato_waveform;
529 int sample_vibrato_depth; /* Starts at rate?0:depth, increases by rate */
530
531 int slide;
532 float delta;
533 int finetune;
534
535 IT_PLAYING_ENVELOPE volume_envelope;
536 IT_PLAYING_ENVELOPE pan_envelope;
537 IT_PLAYING_ENVELOPE pitch_envelope;
538
539 int fadeoutcount;
540
541 IT_FILTER_STATE filter_state[2]; /* Left and right */
542
543 DUMB_RESAMPLER resampler;
544
545 /* time_lost is used to emulate Impulse Tracker's sample looping
546 * characteristics. When time_lost is added to pos, the result represents
547 * the position in the theoretical version of the sample where all loops
548 * have been expanded. If this is stored, the resampling helpers will
549 * safely convert it for use with new loop boundaries. The situation is
550 * slightly more complicated if dir == -1 when the change takes place; we
551 * must reflect pos off the loop end point and set dir to 1 before
552 * proceeding.
553 */
554 long time_lost;
555
556 //int output;
557};
558
559
560
561#define IT_CHANNEL_MUTED 1
562
563#define IT_ENV_VOLUME 1
564#define IT_ENV_PANNING 2
565#define IT_ENV_PITCH 4
566
567struct IT_CHANNEL
568{
569 int flags;
570
571 unsigned char volume;
572 signed char volslide;
573 signed char xm_volslide;
574 signed char panslide;
575
576 /* xm_volslide is used for volume slides done in the volume column in an
577 * XM file, since it seems the volume column slide is applied first,
578 * followed by clamping, followed by the effects column slide. IT does
579 * not exhibit this behaviour, so xm_volslide is maintained at zero.
580 */
581
582 unsigned char pan;
583 unsigned short truepan;
584
585 unsigned char channelvolume;
586 signed char channelvolslide;
587
588 unsigned char instrument;
589 unsigned char note;
590
591 unsigned char SFmacro;
592
593 unsigned char filter_cutoff;
594 unsigned char filter_resonance;
595
596 unsigned char key_off_count;
597 unsigned char note_cut_count;
598 unsigned char note_delay_count;
599 IT_ENTRY *note_delay_entry;
600
601 unsigned char new_note_action;
602
603 unsigned char const* arpeggio_table;
604 signed char arpeggio_offsets[3];
605
606 int arpeggio_shift;
607 unsigned char retrig;
608 unsigned char xm_retrig;
609 int retrig_tick;
610
611 unsigned char tremor;
612 unsigned char tremor_time; /* Bit 6 set if note on; bit 7 set if tremor active. */
613
614 unsigned char vibrato_waveform;
615 unsigned char tremolo_waveform;
616 unsigned char panbrello_waveform;
617
618 int portamento;
619 int toneporta;
620 int toneslide;
621 unsigned char toneslide_tick, last_toneslide_tick, ptm_toneslide, ptm_last_toneslide, okt_toneslide;
622 unsigned char destnote;
623 unsigned char toneslide_retrig;
624
625 unsigned char glissando;
626
627 /** WARNING - for neatness, should one or both of these be in the IT_PLAYING struct? */
628 unsigned short sample;
629 unsigned char truenote;
630
631 unsigned char midi_state;
632
633 signed char lastvolslide;
634 unsigned char lastDKL;
635 unsigned char lastEF; /* Doubles as last portamento up for XM files */
636 unsigned char lastG;
637 unsigned char lastHspeed;
638 unsigned char lastHdepth;
639 unsigned char lastRspeed;
640 unsigned char lastRdepth;
641 unsigned char lastYspeed;
642 unsigned char lastYdepth;
643 unsigned char lastI;
644 unsigned char lastJ; /* Doubles as last portamento down for XM files */
645 unsigned char lastN;
646 unsigned char lastO;
647 unsigned char high_offset;
648 unsigned char lastP;
649 unsigned char lastQ;
650 unsigned char lastS;
651 unsigned char pat_loop_row;
652 unsigned char pat_loop_count;
653 unsigned char pat_loop_end_row; /* Used to catch infinite pattern loops */
654 unsigned char lastW;
655
656 unsigned char xm_lastE1;
657 unsigned char xm_lastE2;
658 unsigned char xm_lastEA;
659 unsigned char xm_lastEB;
660 unsigned char xm_lastX1;
661 unsigned char xm_lastX2;
662
663 unsigned char inv_loop_delay;
664 unsigned char inv_loop_speed;
665 int inv_loop_offset;
666
667 IT_PLAYING *playing;
668
669#ifdef BIT_ARRAY_BULLSHIT
670 void * played_patjump;
671 int played_patjump_order;
672#endif
673
674 //int output;
675};
676
677
678
679struct DUMB_IT_SIGRENDERER
680{
681 DUMB_IT_SIGDATA *sigdata;
682
683 int n_channels;
684
685 int resampling_quality;
686
687 unsigned char globalvolume;
688 signed char globalvolslide;
689
690 int tempo;
691 signed char temposlide;
692
693 IT_CHANNEL channel[DUMB_IT_N_CHANNELS];
694
695 IT_PLAYING *playing[DUMB_IT_N_NNA_CHANNELS];
696
697 int tick;
698 int speed;
699 int rowcount;
700
701 int order; /* Set to -1 if the song is terminated by a callback. */
702 int row;
703 int processorder;
704 int processrow;
705 int breakrow;
706
707 int restart_position;
708
709 int n_rows;
710
711 IT_ENTRY *entry_start;
712 IT_ENTRY *entry;
713 IT_ENTRY *entry_end;
714
715 long time_left; /* Time before the next tick is processed */
716 int sub_time_left;
717
718 DUMB_CLICK_REMOVER **click_remover;
719
720 IT_CALLBACKS *callbacks;
721
722#ifdef BIT_ARRAY_BULLSHIT
723 /* bit array, which rows are played, only checked by pattern break or loop commands */
724 void * played;
725
726 /*
727 Loop indicator for internal processes, may also be useful for external processes
728 0 - Not looped
729 1 - Looped
730 -1 - Continued past loop
731 */
732 int looped;
733
734 /*
735 Kept until looped
736 */
737 LONG_LONG time_played;
738
739 void * row_timekeeper;
740#endif
741
742 long gvz_time;
743 int gvz_sub_time;
744
745 int ramp_style;
746
747 //int max_output;
748};
749
750
751
752struct IT_CHECKPOINT
753{
754 IT_CHECKPOINT *next;
755 long time;
756 DUMB_IT_SIGRENDERER *sigrenderer;
757};
758
759
760
761struct IT_CALLBACKS
762{
763 int (*loop)(void *data);
764 void *loop_data;
765 /* Return 1 to prevent looping; the music will terminate abruptly. If you
766 * want to make the music stop but allow samples to fade (beware, as they
767 * might not fade at all!), use dumb_it_sr_set_speed() and set the speed
768 * to 0. Note that xm_speed_zero() will not be called if you set the
769 * speed manually, and also that this will work for IT and S3M files even
770 * though the music can't stop in this way by itself.
771 */
772
773 int (*xm_speed_zero)(void *data);
774 void *xm_speed_zero_data;
775 /* Return 1 to terminate the mod, without letting samples fade. */
776
777 int (*midi)(void *data, int channel, unsigned char byte);
778 void *midi_data;
779 /* Return 1 to prevent DUMB from subsequently interpreting the MIDI bytes
780 * itself. In other words, return 1 if the Zxx macros in an IT file are
781 * controlling filters and shouldn't be.
782 */
783
784 int (*global_volume_zero)(void *data);
785 void *global_volume_zero_data;
786 /* Return 1 to terminate the module when global volume is set to zero. */
787};
788
789
790
791void _dumb_it_end_sigrenderer(sigrenderer_t *sigrenderer);
792void _dumb_it_unload_sigdata(sigdata_t *vsigdata);
793
794extern DUH_SIGTYPE_DESC _dumb_sigtype_it;
795
796
797
798#define XM_APPREGIO 0
799#define XM_PORTAMENTO_UP 1
800#define XM_PORTAMENTO_DOWN 2
801#define XM_TONE_PORTAMENTO 3
802#define XM_VIBRATO 4
803#define XM_VOLSLIDE_TONEPORTA 5
804#define XM_VOLSLIDE_VIBRATO 6
805#define XM_TREMOLO 7
806#define XM_SET_PANNING 8
807#define XM_SAMPLE_OFFSET 9
808#define XM_VOLUME_SLIDE 10 /* A */
809#define XM_POSITION_JUMP 11 /* B */
810#define XM_SET_CHANNEL_VOLUME 12 /* C */
811#define XM_PATTERN_BREAK 13 /* D */
812#define XM_E 14 /* E */
813#define XM_SET_TEMPO_BPM 15 /* F */
814#define XM_SET_GLOBAL_VOLUME 16 /* G */
815#define XM_GLOBAL_VOLUME_SLIDE 17 /* H */
816#define XM_KEY_OFF 20 /* K (undocumented) */
817#define XM_SET_ENVELOPE_POSITION 21 /* L */
818#define XM_PANNING_SLIDE 25 /* P */
819#define XM_MULTI_RETRIG 27 /* R */
820#define XM_TREMOR 29 /* T */
821#define XM_X 33 /* X */
822#define XM_N_EFFECTS (10+26)
823
824#define XM_E_SET_FILTER 0x0
825#define XM_E_FINE_PORTA_UP 0x1
826#define XM_E_FINE_PORTA_DOWN 0x2
827#define XM_E_SET_GLISSANDO_CONTROL 0x3
828#define XM_E_SET_VIBRATO_CONTROL 0x4
829#define XM_E_SET_FINETUNE 0x5
830#define XM_E_SET_LOOP 0x6
831#define XM_E_SET_TREMOLO_CONTROL 0x7
832#define XM_E_SET_PANNING 0x8
833#define XM_E_RETRIG_NOTE 0x9
834#define XM_E_FINE_VOLSLIDE_UP 0xA
835#define XM_E_FINE_VOLSLIDE_DOWN 0xB
836#define XM_E_NOTE_CUT 0xC
837#define XM_E_NOTE_DELAY 0xD
838#define XM_E_PATTERN_DELAY 0xE
839#define XM_E_SET_MIDI_MACRO 0xF
840
841#define XM_X_EXTRAFINE_PORTA_UP 1
842#define XM_X_EXTRAFINE_PORTA_DOWN 2
843
844/* To make my life a bit simpler during conversion, effect E:xy is converted
845 * to effect number EBASE+x:y. The same applies to effect X, and IT's S. That
846 * way, these effects can be manipulated like regular effects.
847 */
848#define EBASE (XM_N_EFFECTS)
849#define XBASE (EBASE+16)
850#define SBASE (IT_N_EFFECTS)
851
852#define EFFECT_VALUE(x, y) (((x)<<4)|(y))
853#define HIGH(v) ((v)>>4)
854#define LOW(v) ((v)&0x0F)
855#define SET_HIGH(v, x) v = (((x)<<4)|((v)&0x0F))
856#define SET_LOW(v, y) v = (((v)&0xF0)|(y))
857#define BCD_TO_NORMAL(v) (HIGH(v)*10+LOW(v))
858
859
860
861#if 0
862unsigned char **_dumb_malloc2(int w, int h);
863void _dumb_free2(unsigned char **line);
864#endif
865
866void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry, int mod);
867int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata);
868
869
870#define PTM_APPREGIO 0
871#define PTM_PORTAMENTO_UP 1
872#define PTM_PORTAMENTO_DOWN 2
873#define PTM_TONE_PORTAMENTO 3
874#define PTM_VIBRATO 4
875#define PTM_VOLSLIDE_TONEPORTA 5
876#define PTM_VOLSLIDE_VIBRATO 6
877#define PTM_TREMOLO 7
878#define PTM_SAMPLE_OFFSET 9
879#define PTM_VOLUME_SLIDE 10 /* A */
880#define PTM_POSITION_JUMP 11 /* B */
881#define PTM_SET_CHANNEL_VOLUME 12 /* C */
882#define PTM_PATTERN_BREAK 13 /* D */
883#define PTM_E 14 /* E */
884#define PTM_SET_TEMPO_BPM 15 /* F */
885#define PTM_SET_GLOBAL_VOLUME 16 /* G */
886#define PTM_RETRIGGER 17 /* H */
887#define PTM_FINE_VIBRATO 18 /* I */
888#define PTM_NOTE_SLIDE_UP 19 /* J */
889#define PTM_NOTE_SLIDE_DOWN 20 /* K */
890#define PTM_NOTE_SLIDE_UP_RETRIG 21 /* L */
891#define PTM_NOTE_SLIDE_DOWN_RETRIG 22 /* M */
892#define PTM_N_EFFECTS 23
893
894#define PTM_E_FINE_PORTA_DOWN 0x1
895#define PTM_E_FINE_PORTA_UP 0x2
896#define PTM_E_SET_VIBRATO_CONTROL 0x4
897#define PTM_E_SET_FINETUNE 0x5
898#define PTM_E_SET_LOOP 0x6
899#define PTM_E_SET_TREMOLO_CONTROL 0x7
900#define PTM_E_SET_PANNING 0x8
901#define PTM_E_RETRIG_NOTE 0x9
902#define PTM_E_FINE_VOLSLIDE_UP 0xA
903#define PTM_E_FINE_VOLSLIDE_DOWN 0xB
904#define PTM_E_NOTE_CUT 0xC
905#define PTM_E_NOTE_DELAY 0xD
906#define PTM_E_PATTERN_DELAY 0xE
907
908/* To make my life a bit simpler during conversion, effect E:xy is converted
909 * to effect number EBASE+x:y. The same applies to effect X, and IT's S. That
910 * way, these effects can be manipulated like regular effects.
911 */
912#define PTM_EBASE (PTM_N_EFFECTS)
913
914void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry);
915
916long _dumb_it_read_sample_data_adpcm4(IT_SAMPLE *sample, DUMBFILE *f);
917
918void _dumb_it_interleave_stereo_sample(IT_SAMPLE *sample);
919
920/* Calling either of these is optional */
921void _dumb_init_cubic();
922#ifdef _USE_SSE
923void _dumb_init_sse();
924#endif
925
926#endif /* INTERNAL_IT_H */
dumb/include/internal/resampler.h+0−60
@@ -1,60 +0,0 @@
1#ifndef _RESAMPLER_H_
2#define _RESAMPLER_H_
3
4// Ugglay
5#ifdef RESAMPLER_DECORATE
6#undef PASTE
7#undef EVALUATE
8#define PASTE(a,b) a ## b
9#define EVALUATE(a,b) PASTE(a,b)
10#define resampler_init EVALUATE(RESAMPLER_DECORATE,_resampler_init)
11#define resampler_create EVALUATE(RESAMPLER_DECORATE,_resampler_create)
12#define resampler_delete EVALUATE(RESAMPLER_DECORATE,_resampler_delete)
13#define resampler_dup EVALUATE(RESAMPLER_DECORATE,_resampler_dup)
14#define resampler_dup_inplace EVALUATE(RESAMPLER_DECORATE,_resampler_dup_inplace)
15#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality)
16#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count)
17#define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample)
18#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed)
19#define resampler_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate)
20#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready)
21#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear)
22#define resampler_get_sample_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_count)
23#define resampler_get_sample EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample)
24#define resampler_get_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_float)
25#define resampler_remove_sample EVALUATE(RESAMPLER_DECORATE,_resampler_remove_sample)
26#endif
27
28void resampler_init(void);
29
30void * resampler_create(void);
31void resampler_delete(void *);
32void * resampler_dup(const void *);
33void resampler_dup_inplace(void *, const void *);
34
35enum
36{
37 RESAMPLER_QUALITY_MIN = 0,
38 RESAMPLER_QUALITY_ZOH = 0,
39 RESAMPLER_QUALITY_BLEP = 1,
40 RESAMPLER_QUALITY_LINEAR = 2,
41 RESAMPLER_QUALITY_BLAM = 3,
42 RESAMPLER_QUALITY_CUBIC = 4,
43 RESAMPLER_QUALITY_SINC = 5,
44 RESAMPLER_QUALITY_MAX = 5
45};
46
47void resampler_set_quality(void *, int quality);
48
49int resampler_get_free_count(void *);
50void resampler_write_sample(void *, short sample);
51void resampler_write_sample_fixed(void *, int sample, unsigned char depth);
52void resampler_set_rate( void *, double new_factor );
53int resampler_ready(void *);
54void resampler_clear(void *);
55int resampler_get_sample_count(void *);
56int resampler_get_sample(void *);
57float resampler_get_sample_float(void *);
58void resampler_remove_sample(void *, int decay);
59
60#endif
dumb/include/internal/riff.h+0−24
@@ -1,24 +0,0 @@
1#ifndef RIFF_H
2#define RIFF_H
3
4struct riff;
5
6struct riff_chunk
7{
8 unsigned type;
9 long offset;
10 unsigned size;
11 struct riff * nested;
12};
13
14struct riff
15{
16 unsigned type;
17 unsigned chunk_count;
18 struct riff_chunk * chunks;
19};
20
21struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper );
22void riff_free( struct riff * );
23
24#endif
dumb/include/internal/tarray.h+0−31
@@ -1,31 +0,0 @@
1#ifndef _T_ARRAY_H_
2#define _T_ARRAY_H_
3
4#include <stdlib.h>
5
6#ifndef LONG_LONG
7#if defined __GNUC__ || defined __INTEL_COMPILER || defined __MWERKS__
8#define LONG_LONG long long
9#elif defined _MSC_VER || defined __WATCOMC__
10#define LONG_LONG __int64
11#elif defined __sgi
12#define LONG_LONG long long
13#else
14#error 64-bit integer type unknown
15#endif
16#endif
17
18void * timekeeping_array_create(size_t size);
19void timekeeping_array_destroy(void * array);
20void * timekeeping_array_dup(void * array);
21
22void timekeeping_array_reset(void * array, size_t loop_start);
23
24void timekeeping_array_push(void * array, size_t index, LONG_LONG time);
25void timekeeping_array_bump(void * array, size_t index);
26
27unsigned int timekeeping_array_get_count(void * array, size_t index);
28
29LONG_LONG timekeeping_array_get_item(void * array, size_t index);
30
31#endif
dumb/prj/.gitignore+0−3
@@ -1,3 +0,0 @@
1dumb-build-Desktop-Release
2dumb-build-Desktop-Debug
3*.user
dumb/prj/dumb/dumb.pro+0−130
@@ -1,130 +0,0 @@
1#-------------------------------------------------
2#
3# Project created by QtCreator 2012-12-22T16:33:53
4#
5#-------------------------------------------------
6
7QT -= core gui
8
9TARGET = dumb
10TEMPLATE = lib
11CONFIG += staticlib
12
13DEFINES += _USE_SSE
14
15INCLUDEPATH += ../../include
16
17QMAKE_CFLAGS += -msse
18
19SOURCES += \
20 ../../src/core/unload.c \
21 ../../src/core/rendsig.c \
22 ../../src/core/rendduh.c \
23 ../../src/core/register.c \
24 ../../src/core/readduh.c \
25 ../../src/core/rawsig.c \
26 ../../src/core/makeduh.c \
27 ../../src/core/loadduh.c \
28 ../../src/core/dumbfile.c \
29 ../../src/core/duhtag.c \
30 ../../src/core/duhlen.c \
31 ../../src/core/atexit.c \
32 ../../src/helpers/stdfile.c \
33 ../../src/helpers/silence.c \
34 ../../src/helpers/sampbuf.c \
35 ../../src/helpers/riff.c \
36 ../../src/helpers/resample.c \
37 ../../src/helpers/memfile.c \
38 ../../src/helpers/clickrem.c \
39 ../../src/helpers/barray.c \
40 ../../src/helpers/tarray.c \
41 ../../src/it/xmeffect.c \
42 ../../src/it/readxm2.c \
43 ../../src/it/readxm.c \
44 ../../src/it/readstm2.c \
45 ../../src/it/readstm.c \
46 ../../src/it/reads3m2.c \
47 ../../src/it/reads3m.c \
48 ../../src/it/readriff.c \
49 ../../src/it/readptm.c \
50 ../../src/it/readpsm.c \
51 ../../src/it/readoldpsm.c \
52 ../../src/it/readokt2.c \
53 ../../src/it/readokt.c \
54 ../../src/it/readmtm.c \
55 ../../src/it/readmod2.c \
56 ../../src/it/readmod.c \
57 ../../src/it/readdsmf.c \
58 ../../src/it/readasy.c \
59 ../../src/it/readamf2.c \
60 ../../src/it/readamf.c \
61 ../../src/it/readam.c \
62 ../../src/it/read6692.c \
63 ../../src/it/read669.c \
64 ../../src/it/ptmeffect.c \
65 ../../src/it/loadxm2.c \
66 ../../src/it/loadxm.c \
67 ../../src/it/loadstm2.c \
68 ../../src/it/loadstm.c \
69 ../../src/it/loads3m2.c \
70 ../../src/it/loads3m.c \
71 ../../src/it/loadriff2.c \
72 ../../src/it/loadriff.c \
73 ../../src/it/loadptm2.c \
74 ../../src/it/loadptm.c \
75 ../../src/it/loadpsm2.c \
76 ../../src/it/loadpsm.c \
77 ../../src/it/loadoldpsm2.c \
78 ../../src/it/loadoldpsm.c \
79 ../../src/it/loadokt2.c \
80 ../../src/it/loadokt.c \
81 ../../src/it/loadmtm2.c \
82 ../../src/it/loadmtm.c \
83 ../../src/it/loadmod2.c \
84 ../../src/it/loadmod.c \
85 ../../src/it/loadasy2.c \
86 ../../src/it/loadasy.c \
87 ../../src/it/loadamf2.c \
88 ../../src/it/loadamf.c \
89 ../../src/it/load6692.c \
90 ../../src/it/load669.c \
91 ../../src/it/itunload.c \
92 ../../src/it/itrender.c \
93 ../../src/it/itread2.c \
94 ../../src/it/itread.c \
95 ../../src/it/itorder.c \
96 ../../src/it/itmisc.c \
97 ../../src/it/itload2.c \
98 ../../src/it/itload.c \
99 ../../src/it/readany.c \
100 ../../src/it/loadany2.c \
101 ../../src/it/loadany.c \
102 ../../src/it/readany2.c \
103 ../../src/helpers/sinc_resampler.c \
104 ../../src/helpers/lpc.c
105
106HEADERS += \
107 ../../include/dumb.h \
108 ../../include/internal/riff.h \
109 ../../include/internal/it.h \
110 ../../include/internal/dumb.h \
111 ../../include/internal/barray.h \
112 ../../include/internal/tarray.h \
113 ../../include/internal/aldumb.h \
114 ../../include/internal/sinc_resampler.h \
115 ../../include/internal/stack_alloc.h \
116 ../../include/internal/lpc.h \
117 ../../include/internal/dumbfile.h
118unix:!symbian {
119 maemo5 {
120 target.path = /opt/usr/lib
121 } else {
122 target.path = /usr/lib
123 }
124 INSTALLS += target
125}
126
127OTHER_FILES += \
128 ../../src/helpers/resample.inc \
129 ../../src/helpers/resamp3.inc \
130 ../../src/helpers/resamp2.inc
dumb/readme.txt+0−541
@@ -1,541 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readme.txt - General information on DUMB. / / \ \
12 * | < / \_
13 * | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21********************
22*** Introduction ***
23********************
24
25
26Thank you for downloading DUMB v0.9.3! You should have the following
27documentation:
28
29 readme.txt - This file
30 licence.txt - Conditions for the use of this software
31 release.txt - Release notes and changes for this and past releases
32 docs/
33 howto.txt - Step-by-step instructions on adding DUMB to your project
34 faq.txt - Frequently asked questions and answers to them
35 dumb.txt - DUMB library reference
36 deprec.txt - Information about deprecated parts of the API
37 ptr.txt - Quick introduction to pointers for those who need it
38 fnptr.txt - Explanation of function pointers for those who need it
39 modplug.txt - Our official position regarding ModPlug Tracker
40
41This file will help you get DUMB set up. If you have not yet done so, please
42read licence.txt and release.txt before proceeding. After you've got DUMB set
43up, please refer to the files in the docs/ directory at your convenience. I
44recommend you start with howto.txt.
45
46
47****************
48*** Features ***
49****************
50
51
52Here is the statutory feature list:
53
54- Freeware
55
56- Supports playback of IT, XM, S3M and MOD files
57
58- Faithful to the original trackers, especially IT; if it plays your module
59 wrongly, please tell me so I can fix the bug! (But please don't complain
60 about differences between DUMB and ModPlug Tracker; see docs/modplug.txt)
61
62- Accurate support for low-pass resonant filters for IT files
63
64- Very accurate timing and pitching; completely deterministic playback
65
66- Click removal
67
68- Facility to embed music files in other files (e.g. Allegro datafiles)
69
70- Three resampling quality settings: aliasing, linear interpolation and cubic
71 interpolation
72
73- Number of samples playing at once can be limited to reduce processor usage,
74 but samples will come back in when other louder ones stop
75
76- All notes will be present and correct even if you start a piece of music in
77 the middle
78
79- Option to take longer loading but seek fast to any point before the music
80 first loops (seeking time increases beyond this point)
81
82- Audio generated can be used in any way; DUMB does not necessarily send it
83 straight to a sound output system
84
85- Can be used with Allegro, can be used without (if you'd like to help make
86 DUMB more approachable to people who aren't using Allegro, please contact
87 me)
88
89- Makefile provided for DJGPP, MinGW, Linux, BeOS and Mac OS X
90
91- Project files provided for MSVC 6
92
93- Autotools-based configure script available as a separate download for
94 masochists
95
96- Code should port anywhere that has a 32-bit C compiler; instructions on
97 compiling it manually are available further down
98
99
100*********************
101*** What you need ***
102*********************
103
104
105To use DUMB, you need a 32-bit C compiler (GCC and MSVC are fine). If you
106have Allegro, DUMB can integrate with its audio streams and datafiles, making
107your life easier. If you do not wish to use Allegro, you will have to do some
108work to get music playing back. The 'dumbplay' example program requires
109Allegro.
110
111 Allegro - http://alleg.sf.net/
112
113
114**********************************************
115*** How to set DUMB up with DJGPP or MinGW ***
116**********************************************
117
118
119You should have got the .zip version. If for some reason you got the .tar.gz
120version instead, you may have to convert make/config.bat to DOS text file
121format. WinZip does this automatically by default. Otherwise, loading it into
122MS EDIT and saving it again should do the trick (but do not do this to the
123Makefiles as it destroys tabs). You will have to do the same for any files
124you want to view in Windows Notepad. If you have problems, just go and
125download the .zip instead.
126
127Make sure you preserved the directory structure when you extracted DUMB from
128the archive. Most unzipping programs will do this by default, but pkunzip
129requires you to pass -d. If not, please delete DUMB and extract it again
130properly.
131
132If you are using Windows, open an MS-DOS Prompt or a Windows Command Line.
133Change to the directory into which you unzipped DUMB.
134
135If you are using MinGW (and you haven't renamed 'mingw32-make'), type:
136
137 mingw32-make
138
139Otherwise, type the following:
140
141 make
142
143DUMB will ask you whether you wish to compile for DJGPP or MinGW. Then it
144will ask you whether you want support for Allegro. (You have to have made and
145installed Allegro's optimised library for this to work.) Finally, it will
146compile optimised and debugging builds of DUMB, along with the example
147programs. When it has finished, run one of the following to install the
148libraries:
149
150 make install
151 mingw32-make install
152
153All done! If you ever need the configuration again (e.g. if you compiled for
154DJGPP before and you want to compile for MinGW now), run one of the
155following:
156
157 make config
158 mingw32-make config
159
160See the comments in the Makefile for other targets.
161
162Note: the Makefile will only work properly if you have COMSPEC or ComSpec set
163to point to command.com or cmd.exe. If you set it to point to a Unix-style
164shell, the Makefile won't work.
165
166Please let me know if you have any trouble.
167
168As an alternative, MSYS users may attempt to use the configure script,
169available in dumb-0.9.3-autotools.tar.gz. This has been found to work without
170Allegro, and is untested with Allegro. I should appreciate feedback from
171anyone else who tries this. I do not recommend its use, partly because it
172creates dynamically linked libraries and I don't know how to stop it from
173doing that (see the section on compiling DUMB manually), and partly because
174autotools are plain evil.
175
176Scroll down for information on the example programs. Refer to docs/howto.txt
177when you are ready to start programming with DUMB. If you use DUMB in a game,
178let me know - I might decide to place a link to your game on DUMB's website!
179
180
181******************************************************
182*** How to set DUMB up with Microsoft Visual C++ 6 ***
183******************************************************
184
185
186If you have a newer version of Microsoft Visual C++ or Visual Something that
187supports C++, please try these instructions and let me know if it works.
188
189You should have got the .zip version. If for some reason you got the .tar.gz
190version instead, you may have to convert some files to DOS text file format.
191WinZip does this automatically by default. Otherwise, loading such files into
192MS EDIT and saving them again should do the trick. You will have to do this
193for any files you want to view in Windows Notepad. If you have problems, just
194go and download the .zip instead.
195
196Make sure you preserved the directory structure when you extracted DUMB from
197the archive. Most unzipping programs will do this by default, but pkunzip
198requires you to pass -d. If not, please delete DUMB and extract it again
199properly.
200
201DUMB comes with a workspace Microsoft Visual C++ 6, containing projects for
202the DUMB core, the Allegro interface library and each of the examples. The
203first thing you might want to do is load the workspace up and have a look
204around. You will find it in the dumb\vc6 directory under the name dumb.dsw.
205Note that the aldumb and dumbplay projects require Allegro, so they won't
206work if you don't have Allegro. Nevertheless, dumbplay is the best-commented
207of the examples, so do have a look.
208
209When you are ready to add DUMB to your project, follow these instructions:
210
2111. Open your project in VC++.
2122. Select Project|Insert Project into Workspace...
2133. Navigate to the dumb\vc6\dumb directory and select dumb.dsp.
214 Alternatively, if you know that you are statically linking with a library
215 that uses the statically linked multithreaded runtime (/MT), you may wish
216 to select dumb_static.dsp in the dumb_static subdirectory instead.
2174. Select Build|Set Active Configuration..., and reselect one of your
218 project's configurations.
2195. Select Project|Dependencies... and ensure your project is dependent on
220 DUMB.
2216. Select Project|Settings..., Settings for: All Configurations, C/C++ tab,
222 Preprocessor category. Add the DUMB include directory to the Additional
223 Include Directories box.
2247. Ensure that for all the projects in the workspace (or more likely just all
225 the projects in a particular dependency chain) the run-time libraries are
226 the same. That's in Project|Settings, C/C++ tab, Code generation category,
227 Use run-time library dropdown. The settings for Release and Debug are
228 separate, so you'll have to change them one at a time. Exactly which run-
229 time library you use will depend on what you need; it doesn't appear that
230 DUMB has any particular requirements, so set it to whatever you're using
231 now. (It will have to be /MD, the multithreaded DLL library, if you are
232 statically linking with Allegro. If you are dynamically linking with
233 Allegro than it doesn't matter.)
2348. If you are using Allegro, do some or all of the above for the aldumb.dsp
235 project in the aldumb directory too.
236
237Good thing you only have to do all that once ... or twice ...
238
239If you have the Intel compiler installed, it will - well, should - be used to
240compile DUMB. The only setting I [Tom Seddon] added is /QxiM. This allows the
241compiler to use PPro and MMX instructions, and so when compiling with Intel
242the resultant EXE will require a Pentium II or greater. I don't think this is
243unreasonable. After all, it is 2003 :)
244
245[Note from Ben: the Intel compiler is evil! It makes AMD processors look bad!
246Patch it or boycott it or something!]
247
248If you don't have the Intel compiler, VC will compile DUMB as normal.
249
250This project file and these instructions were provided by Tom Seddon (I hope
251I got his name right; I had to guess it from his e-mail address!). Chad
252Austin has since changed the project files around, and I've just attempted to
253hack them to incorporate new source files. I've also tried to update the
254instructions using guesswork and some knowledge of Visual J++ (you heard me).
255The instructions and the project files are to this day untested by me. If you
256have problems, check the download page at http://dumb.sf.net/ to see if they
257are addressed; failing that, direct queries to me and I'll try to figure them
258out.
259
260If you have any comments at all on how the VC6 projects are laid out, or how
261the instructions could be improved, I should be really grateful to hear them.
262I am a perfectionist, after all. :)
263
264Scroll down for information on the example programs. When you are ready to
265start using DUMB, refer to docs/howto.txt. If you use DUMB in a game, let me
266know - I might decide to place a link to your game on DUMB's website!
267
268
269******************************************************
270*** How to set DUMB up on Linux, BeOS and Mac OS X ***
271******************************************************
272
273
274You should have got the .tar.gz version. If for some reason you got the .zip
275version instead, you may have to strip all characters with ASCII code 13 from
276some of the text files. If you have problems, just go and download the
277.tar.gz instead.
278
279You have two options. There is a Makefile which should cope with most
280systems. The first option is to use this default Makefile, and the procedure
281is explained below. The second option is to download
282dumb-0.9.3-autotools.tar.gz, extract it over the installation, run
283./configure and use the generated Makefile. Users who choose to do this are
284left to their own devices but advised to read the information at the end of
285this section. I strongly recommend the first option.
286
287If you are not using the configure script, the procedure is as follows.
288
289First, run the following command as a normal user:
290
291 make
292
293You will be asked whether you want Allegro support. Then, unless you are on
294BeOS, you will be asked where you'd like DUMB to install its headers,
295libraries and examples (which will go in the include/, lib/ and bin/
296subdirectories of the prefix you specify). BeOS has fixed locations for these
297files. You may use shell variables here, e.g. $HOME or ${HOME}, but ~ will
298not work. Once you have specified these pieces of information, the optimised
299and debugging builds of DUMB will be compiled, along with the examples. When
300it has finished, you can install them with:
301
302 make install
303
304You may need to be root for this to work. It depends on the prefix you chose.
305
306Note: the Makefile will only work if COMSPEC and ComSpec are both undefined.
307If either of these is defined, the Makefile will try to build for a Windows
308system, and will fail.
309
310Please let me know if you have any trouble.
311
312Scroll down for information on the example programs. Refer to docs/howto.txt
313when you are ready to start programming with DUMB. If you use DUMB in a game,
314let me know - I might decide to place a link to your game on DUMB's website!
315
316Important information for users of the configure script follows.
317
318The Makefile generated by the configure script creates dynamically linked
319libraries, and I don't know how to stop it from doing so. See the section
320below on building DUMB manually for why I recommend linking DUMB statically.
321However, if you choose to use the configure script, note the following.
322
323The default Makefile is a copy of Makefile.rdy (short for 'ready'), and it
324must exist with the name Makefile.rdy in order to work. The configure script
325will overwrite Makefile, so if you want the default Makefile back, just run:
326
327 cp Makefile.rdy Makefile
328
329Do not use a symlink, as that would result in Makefile.rdy getting
330overwritten next time the configure script is run!
331
332You can also access the usual build system by passing '-f Makefile.rdy' to
333Make.
334
335
336********************************************************
337*** How to build DUMB manually if nothing else works ***
338********************************************************
339
340
341Those porting to platforms without floating point support should be aware
342that DUMB does use floating point operations but not in the inner loops. They
343are used for volume and note pitch calculations, and they are used when
344initialising the filter algorithm for given cut-off and resonance values.
345Please let me know if this is a problem for you. If there is enough demand, I
346may be able to eliminate one or both of these cases.
347
348All of the library source code may be found in the src/ subdirectory. There
349are headers in the include/ subdirectory, and src/helpers/resample.c also
350#includes some .inc files in its own directory.
351
352There are four subdirectories under src/. For projects not using Allegro, you
353will need all the files in src/core/, src/helpers/ and src/it/. If you are
354using Allegro, you will want the src/allegro/ subdirectory too. For
355consistency with the other build systems, the contents of src/allegro/ should
356be compiled into a separate library.
357
358I recommend static-linking DUMB, since the version information is done via
359macros and the API has a tendency to change. If you static-link, then once
360your program is in binary form, you can be sure that changes to the installed
361version of DUMB won't cause it to malfuction. It is my fault that the API has
362been so unstable. Sorry!
363
364Compile each .c file separately. As mentioned above, you will need to specify
365two places to look for #include files: the include/ directory and the source
366file's own directory. You will also need to define the symbol
367DUMB_DECLARE_DEPRECATED on the command line.
368
369Do not compile the .inc files separately.
370
371You may need to edit dumb.h and add your own definition for LONG_LONG. It
372should be a 64-bit integer. If you do this, please see if you can add a check
373for your compiler so that it still works with other compilers.
374
375DUMB has two build modes. If you define the symbol DEBUGMODE, some checks for
376programmer error will be incorporated into the library. Otherwise it will be
377built without any such checks. (DUMB will however always thoroughly check the
378validity of files it is loading. If you ever find a module file that crashes
379DUMB, please let me know!)
380
381I recommend building two versions of the library, one with DEBUGMODE defined
382and debugging information included, and the other with compiler optimisation
383enabled. If you can install DUMB system-wide so that your projects, and other
384people's, can simply #include <dumb.h> or <aldumb.h> and link with libraries
385by simple name with no path, then that is ideal.
386
387If you successfully port DUMB to a new platform, please let me know!
388
389
390****************************
391*** The example programs ***
392****************************
393
394
395Three example programs are provided. On DOS and Windows, you can find them in
396the examples subdirectory. On other systems they will be installed system-
397wide.
398
399dumbplay
400 This program will only be built if you have Allegro. Pass it the filename
401 of an IT, XM, S3M or MOD file, and it will play it. It's not a polished
402 player with real-time threading or anything - so don't complain about it
403 stuttering while you use other programs - but it does show DUMB's fidelity
404 nicely. You can control the playback quality by editing dumb.ini, which
405 must be in the current working directory. (This is a flaw for systems
406 where the program is installed system-wide, but it is non-fatal.) Have a
407 look at the examples/dumb.ini file for further information.
408
409dumbout
410 This program does not need Allegro. You can use it to stream an IT, XM,
411 S3M or MOD file to raw PCM. This can be used as input to an encoder like
412 oggenc (with appropriate command-line options), or it can be sent to a
413 .pcm file which can be read by any respectable waveform editor. This
414 program is also convenient for timing DUMB. Compare the time it takes to
415 render a module with the module's playing time! dumbout doesn't try to
416 read any configuration file; the options are set on the command line.
417
418dumb2wav
419 This program is much the same as dumbout, but it writes a .wav file with
420 the appropriate header. Thanks go to Chad Austin for this useful tool.
421
422
423*********************************************
424*** Downloading music or writing your own ***
425*********************************************
426
427
428If you would like to compose your own music modules, then this section should
429help get you started.
430
431The best programs for the job are the trackers that pioneered the file
432formats:
433
434 Impulse Tracker - IT files - http://www.lim.com.au/ImpulseTracker/
435 Fast Tracker II - XM files - http://www.fasttracker2.com/
436 Scream Tracker 3 - S3M files - No official site known, please use Google
437
438MOD files come from the Amiga; I do not know what PC tracker to recommend for
439editing these. If you know of one, let me know! In the meantime, I would
440recommend using a more advanced file format. However, don't convert your
441existing MODs just for the sake of it.
442
443Fast Tracker II is Shareware. It offers a very flashy interface and has a
444game embedded, but the IT file format is more powerful and better defined. By
445all means try them both and see which you prefer; it is largely a matter of
446taste (and, in some cases, religion). Impulse Tracker and Scream Tracker 3
447are Freeware, although you can donate to Impulse Tracker and receive a
448slightly upgraded version. DUMB is likely to be at its best with IT files.
449
450These editors are DOS programs. Users of DOS-incapable operating systems may
451like to try ModPlug Tracker, but should read docs/modplug.txt before using it
452for any serious work. If you use a different operating system, or if you know
453of any module editors for Windows that are more faithful to the original
454trackers' playback, please give me some links so I can put them here!
455
456 ModPlug Tracker - http://www.modplug.com/
457
458If you have an x86 Linux system with VGA-compatible hardware (which covers
459all PC graphics cards I've ever seen), you should be able to get Impulse
460Tracker running with DOSEMU. You will have to give it access to the VGA ports
461and run it in a true console, as it will not work with the X-based VGA
462emulation. I personally added the SB16 emulation to DOSEMU, so you can even
463use filters! However, it corrupts samples alarmingly often when saving on my
464system - probably a DOSEMU issue. If you set this up, I am curious to know
465whether it works for you.
466
467 DOSEMU - http://www.dosemu.org/
468
469BEWARE OF WINAMP! Although it's excellent for MP3s, it is notorious for being
470one of the worst module players in existence; very many modules play wrongly
471with it. There are plug-ins available to improve Winamp's module support, for
472example WSP.
473
474 Winamp - http://www.winamp.com/
475 WSP - http://www.spytech.cz/index.php?sec=demo
476
477(There is a Winamp plug-in that uses DUMB, but it is unreliable. If anyone
478would like to work on it, please get in touch.)
479
480While I am at it I should also point out that Winamp is notorious for
481containing security flaws. Install it at your own risk, and if it is your
482work computer, check with your boss first!
483
484Samples and instruments are the building blocks of music modules. You can
485download samples at
486
487 http://www.tump.net/
488
489If you would like to download module files composed by other people, check
490the following sites:
491
492 http://www.modarchive.com/
493 http://www.scene.org/
494 http://www.tump.net/
495 http://www.homemusic.cc/main.php
496 http://www.modplug.com/
497
498Once again, if you know of more sites where samples or module files are
499available for download, please let me know.
500
501If you wish to use someone's music in your game, please respect the
502composer's wishes. In general, you should ask the composer. Music that has
503been placed in the Public Domain can be used by anyone for anything, but it
504wouldn't do any harm to ask anyway if you know who the author is. In many
505cases the author will be thrilled, so don't hesitate!
506
507A note about converting modules from one format to another, or converting
508from MIDI: don't do it, unless you are a musician and are prepared to go
509through the file and make sure everything sounds the way it should! The
510module formats are all slightly different, and MIDI is very different;
511converting from one format to another will usually do some damage.
512
513Instead, it is recommended that you allow DUMB to interpret the original file
514as it sees fit. DUMB may make mistakes (it does a lot of conversion on
515loading), but future versions of DUMB will be able to rectify these mistakes.
516On the other hand, if you convert the file, the damage is permanent.
517
518
519***********************
520*** Contact details ***
521***********************
522
523
524If you have trouble with DUMB, or want to contact me for any other reason, my
525e-mail address is given below. Please do get in touch, even if I appear to
526have disappeared!
527
528If you wish to chat online about something, perhaps on IRC, that can most
529likely be arranged. Send me an e-mail.
530
531
532******************
533*** Conclusion ***
534******************
535
536
537This is the conclusion.
538
539
540Ben Davis
541entheh@users.sf.net
dumb/src/core/dumbfile.c+0−418
@@ -1,418 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * dumbfile.c - Hookable, strictly sequential / / \ \
12 * file input functions. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23
24
25
26static const DUMBFILE_SYSTEM *the_dfs = NULL;
27
28
29
30void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs)
31{
32 ASSERT(dfs);
33 ASSERT(dfs->open);
34 ASSERT(dfs->getc);
35 ASSERT(dfs->close);
36 ASSERT(dfs->seek);
37 ASSERT(dfs->get_size);
38 the_dfs = dfs;
39}
40
41
42
43#include "internal/dumbfile.h"
44
45
46
47DUMBFILE *dumbfile_open(const char *filename)
48{
49 DUMBFILE *f;
50
51 ASSERT(the_dfs);
52
53 f = (DUMBFILE *) malloc(sizeof(*f));
54
55 if (!f)
56 return NULL;
57
58 f->dfs = the_dfs;
59
60 f->file = (*the_dfs->open)(filename);
61
62 if (!f->file) {
63 free(f);
64 return NULL;
65 }
66
67 f->pos = 0;
68
69 return f;
70}
71
72
73
74DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs)
75{
76 DUMBFILE *f;
77
78 ASSERT(dfs);
79 ASSERT(dfs->getc);
80 ASSERT(file);
81
82 f = (DUMBFILE *) malloc(sizeof(*f));
83
84 if (!f) {
85 if (dfs->close)
86 (*dfs->close)(file);
87 return NULL;
88 }
89
90 f->dfs = dfs;
91 f->file = file;
92
93 f->pos = 0;
94
95 return f;
96}
97
98
99
100long dumbfile_pos(DUMBFILE *f)
101{
102 ASSERT(f);
103
104 return f->pos;
105}
106
107
108
109int dumbfile_skip(DUMBFILE *f, long n)
110{
111 int rv;
112
113 ASSERT(f);
114 ASSERT(n >= 0);
115
116 if (f->pos < 0)
117 return -1;
118
119 f->pos += n;
120
121 if (f->dfs->skip) {
122 rv = (*f->dfs->skip)(f->file, n);
123 if (rv) {
124 f->pos = -1;
125 return rv;
126 }
127 } else {
128 while (n) {
129 rv = (*f->dfs->getc)(f->file);
130 if (rv < 0) {
131 f->pos = -1;
132 return rv;
133 }
134 n--;
135 }
136 }
137
138 return 0;
139}
140
141
142
143int dumbfile_getc(DUMBFILE *f)
144{
145 int rv;
146
147 ASSERT(f);
148
149 if (f->pos < 0)
150 return -1;
151
152 rv = (*f->dfs->getc)(f->file);
153
154 if (rv < 0) {
155 f->pos = -1;
156 return rv;
157 }
158
159 f->pos++;
160
161 return rv;
162}
163
164
165
166int dumbfile_igetw(DUMBFILE *f)
167{
168 int l, h;
169
170 ASSERT(f);
171
172 if (f->pos < 0)
173 return -1;
174
175 l = (*f->dfs->getc)(f->file);
176 if (l < 0) {
177 f->pos = -1;
178 return l;
179 }
180
181 h = (*f->dfs->getc)(f->file);
182 if (h < 0) {
183 f->pos = -1;
184 return h;
185 }
186
187 f->pos += 2;
188
189 return l | (h << 8);
190}
191
192
193
194int dumbfile_mgetw(DUMBFILE *f)
195{
196 int l, h;
197
198 ASSERT(f);
199
200 if (f->pos < 0)
201 return -1;
202
203 h = (*f->dfs->getc)(f->file);
204 if (h < 0) {
205 f->pos = -1;
206 return h;
207 }
208
209 l = (*f->dfs->getc)(f->file);
210 if (l < 0) {
211 f->pos = -1;
212 return l;
213 }
214
215 f->pos += 2;
216
217 return l | (h << 8);
218}
219
220
221
222long dumbfile_igetl(DUMBFILE *f)
223{
224 unsigned long rv, b;
225
226 ASSERT(f);
227
228 if (f->pos < 0)
229 return -1;
230
231 rv = (*f->dfs->getc)(f->file);
232 if ((signed long)rv < 0) {
233 f->pos = -1;
234 return rv;
235 }
236
237 b = (*f->dfs->getc)(f->file);
238 if ((signed long)b < 0) {
239 f->pos = -1;
240 return b;
241 }
242 rv |= b << 8;
243
244 b = (*f->dfs->getc)(f->file);
245 if ((signed long)b < 0) {
246 f->pos = -1;
247 return b;
248 }
249 rv |= b << 16;
250
251 b = (*f->dfs->getc)(f->file);
252 if ((signed long)b < 0) {
253 f->pos = -1;
254 return b;
255 }
256 rv |= b << 24;
257
258 f->pos += 4;
259
260 return rv;
261}
262
263
264
265long dumbfile_mgetl(DUMBFILE *f)
266{
267 unsigned long rv, b;
268
269 ASSERT(f);
270
271 if (f->pos < 0)
272 return -1;
273
274 rv = (*f->dfs->getc)(f->file);
275 if ((signed long)rv < 0) {
276 f->pos = -1;
277 return rv;
278 }
279 rv <<= 24;
280
281 b = (*f->dfs->getc)(f->file);
282 if ((signed long)b < 0) {
283 f->pos = -1;
284 return b;
285 }
286 rv |= b << 16;
287
288 b = (*f->dfs->getc)(f->file);
289 if ((signed long)b < 0) {
290 f->pos = -1;
291 return b;
292 }
293 rv |= b << 8;
294
295 b = (*f->dfs->getc)(f->file);
296 if ((signed long)b < 0) {
297 f->pos = -1;
298 return b;
299 }
300 rv |= b;
301
302 f->pos += 4;
303
304 return rv;
305}
306
307
308
309unsigned long dumbfile_cgetul(DUMBFILE *f)
310{
311 unsigned long rv = 0;
312 int v;
313
314 do {
315 v = dumbfile_getc(f);
316
317 if (v < 0)
318 return v;
319
320 rv <<= 7;
321 rv |= v & 0x7F;
322 } while (v & 0x80);
323
324 return rv;
325}
326
327
328
329signed long dumbfile_cgetsl(DUMBFILE *f)
330{
331 unsigned long rv = dumbfile_cgetul(f);
332
333 if (f->pos < 0)
334 return rv;
335
336 return (rv >> 1) | (rv << 31);
337}
338
339
340
341long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
342{
343 long rv;
344
345 ASSERT(f);
346 ASSERT(n >= 0);
347
348 if (f->pos < 0)
349 return -1;
350
351 if (f->dfs->getnc) {
352 rv = (*f->dfs->getnc)(ptr, n, f->file);
353 if (rv < n) {
354 f->pos = -1;
355 return MAX(rv, 0);
356 }
357 } else {
358 for (rv = 0; rv < n; rv++) {
359 int c = (*f->dfs->getc)(f->file);
360 if (c < 0) {
361 f->pos = -1;
362 return rv;
363 }
364 *ptr++ = c;
365 }
366 }
367
368 f->pos += rv;
369
370 return rv;
371}
372
373
374
375int dumbfile_seek(DUMBFILE *f, long n, int origin)
376{
377 switch ( origin )
378 {
379 case DFS_SEEK_CUR: n += f->pos; break;
380 case DFS_SEEK_END: n += (*f->dfs->get_size)(f->file); break;
381 }
382 f->pos = n;
383 return (*f->dfs->seek)(f->file, n);
384}
385
386
387
388long dumbfile_get_size(DUMBFILE *f)
389{
390 return (*f->dfs->get_size)(f->file);
391}
392
393
394
395int dumbfile_error(DUMBFILE *f)
396{
397 ASSERT(f);
398
399 return f->pos < 0;
400}
401
402
403
404int dumbfile_close(DUMBFILE *f)
405{
406 int rv;
407
408 ASSERT(f);
409
410 rv = f->pos < 0;
411
412 if (f->dfs->close)
413 (*f->dfs->close)(f->file);
414
415 free(f);
416
417 return rv;
418}
dumb/src/core/makeduh.c+0−151
@@ -1,151 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * makeduh.c - Function to construct a DUH from / / \ \
12 * its components. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22
23#include "dumb.h"
24#include "internal/dumb.h"
25
26
27
28static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
29{
30 DUH_SIGNAL *signal;
31
32 ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
33 ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample);
34
35 signal = malloc(sizeof(*signal));
36
37 if (!signal) {
38 if (desc->unload_sigdata)
39 if (sigdata)
40 (*desc->unload_sigdata)(sigdata);
41 return NULL;
42 }
43
44 signal->desc = desc;
45 signal->sigdata = sigdata;
46
47 return signal;
48}
49
50
51
52DUH *make_duh(
53 long length,
54 int n_tags,
55 const char *const tags[][2],
56 int n_signals,
57 DUH_SIGTYPE_DESC *desc[],
58 sigdata_t *sigdata[]
59)
60{
61 DUH *duh = malloc(sizeof(*duh));
62 int i;
63 int fail;
64
65 if (duh) {
66 duh->n_signals = n_signals;
67
68 duh->signal = malloc(n_signals * sizeof(*duh->signal));
69
70 if (!duh->signal) {
71 free(duh);
72 duh = NULL;
73 }
74 }
75
76 if (!duh) {
77 for (i = 0; i < n_signals; i++)
78 if (desc[i]->unload_sigdata)
79 if (sigdata[i])
80 (*desc[i]->unload_sigdata)(sigdata[i]);
81 return NULL;
82 }
83
84 duh->n_tags = 0;
85 duh->tag = NULL;
86
87 fail = 0;
88
89 for (i = 0; i < n_signals; i++) {
90 duh->signal[i] = make_signal(desc[i], sigdata[i]);
91 if (!duh->signal[i])
92 fail = 1;
93 }
94
95 if (fail) {
96 unload_duh(duh);
97 return NULL;
98 }
99
100 duh->length = length;
101
102 {
103 int mem = n_tags * 2; /* account for NUL terminators here */
104 char *ptr;
105
106 for (i = 0; i < n_tags; i++)
107 mem += strlen(tags[i][0]) + strlen(tags[i][1]);
108
109 if (mem <= 0) return duh;
110
111 duh->tag = malloc(n_tags * sizeof(*duh->tag));
112 if (!duh->tag) return duh;
113 duh->tag[0][0] = malloc(mem);
114 if (!duh->tag[0][0]) {
115 free(duh->tag);
116 duh->tag = NULL;
117 return duh;
118 }
119 duh->n_tags = n_tags;
120 ptr = duh->tag[0][0];
121 for (i = 0; i < n_tags; i++) {
122 duh->tag[i][0] = ptr;
123 strcpy(ptr, tags[i][0]);
124 ptr += strlen(tags[i][0]) + 1;
125 duh->tag[i][1] = ptr;
126 strcpy(ptr, tags[i][1]);
127 ptr += strlen(tags[i][1]) + 1;
128 }
129 }
130
131 return duh;
132}
133
134int duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
135{
136 DUH_SIGNAL **signal;
137
138 if ( !duh || !desc || !sigdata ) return -1;
139
140 signal = ( DUH_SIGNAL ** ) realloc( duh->signal, ( duh->n_signals + 1 ) * sizeof( *duh->signal ) );
141 if ( !signal ) return -1;
142 duh->signal = signal;
143
144 memmove( signal + 1, signal, duh->n_signals * sizeof( *signal ) );
145 duh->n_signals++;
146
147 signal[ 0 ] = make_signal( desc, sigdata );
148 if ( !signal[ 0 ] ) return -1;
149
150 return 0;
151}
dumb/src/core/readduh.c+0−107
@@ -1,107 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readduh.c - Code to read a DUH from an open / / \ \
12 * file. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f)
28{
29 DUH_SIGNAL *signal;
30 long type;
31
32 signal = malloc(sizeof(*signal));
33
34 if (!signal)
35 return NULL;
36
37 type = dumbfile_mgetl(f);
38 if (dumbfile_error(f)) {
39 free(signal);
40 return NULL;
41 }
42
43 signal->desc = _dumb_get_sigtype_desc(type);
44 if (!signal->desc) {
45 free(signal);
46 return NULL;
47 }
48
49 if (signal->desc->load_sigdata) {
50 signal->sigdata = (*signal->desc->load_sigdata)(duh, f);
51 if (!signal->sigdata) {
52 free(signal);
53 return NULL;
54 }
55 } else
56 signal->sigdata = NULL;
57
58 return signal;
59}
60
61
62
63/* read_duh(): reads a DUH from an already open DUMBFILE, and returns its
64 * pointer, or null on error. The file is not closed.
65 */
66DUH *read_duh(DUMBFILE *f)
67{
68 DUH *duh;
69 int i;
70
71 if (dumbfile_mgetl(f) != DUH_SIGNATURE)
72 return NULL;
73
74 duh = malloc(sizeof(*duh));
75 if (!duh)
76 return NULL;
77
78 duh->length = dumbfile_igetl(f);
79 if (dumbfile_error(f) || duh->length <= 0) {
80 free(duh);
81 return NULL;
82 }
83
84 duh->n_signals = dumbfile_igetl(f);
85 if (dumbfile_error(f) || duh->n_signals <= 0) {
86 free(duh);
87 return NULL;
88 }
89
90 duh->signal = malloc(sizeof(*duh->signal) * duh->n_signals);
91 if (!duh->signal) {
92 free(duh);
93 return NULL;
94 }
95
96 for (i = 0; i < duh->n_signals; i++)
97 duh->signal[i] = NULL;
98
99 for (i = 0; i < duh->n_signals; i++) {
100 if (!(duh->signal[i] = read_signal(duh, f))) {
101 unload_duh(duh);
102 return NULL;
103 }
104 }
105
106 return duh;
107}
dumb/src/core/rendduh.c+0−331
@@ -1,331 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * rendduh.c - Functions for rendering a DUH into / / \ \
12 * an end-user sample format. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <limits.h>
22
23#include "dumb.h"
24#include "internal/dumb.h"
25
26
27
28/* On the x86, we can use some tricks to speed stuff up */
29#if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__)
30// Can't we detect Linux and other x86 platforms here? :/
31
32#define FAST_MID(var, min, max) { \
33 var -= (min); \
34 var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \
35 var += (min); \
36 var -= (max); \
37 var &= var >> (sizeof(var) * CHAR_BIT - 1); \
38 var += (max); \
39}
40
41#define CONVERT8(src, pos, signconv) { \
42 signed int f = (src + 0x8000) >> 16; \
43 FAST_MID(f, -128, 127); \
44 ((char*)sptr)[pos] = (char)f ^ signconv; \
45}
46
47#define CONVERT16(src, pos, signconv) { \
48 signed int f = (src + 0x80) >> 8; \
49 FAST_MID(f, -32768, 32767); \
50 ((short*)sptr)[pos] = (short)(f ^ signconv); \
51}
52
53#else
54
55#define CONVERT8(src, pos, signconv) \
56{ \
57 signed int f = (src + 0x8000) >> 16; \
58 f = MID(-128, f, 127); \
59 ((char *)sptr)[pos] = (char)f ^ signconv; \
60}
61
62
63
64#define CONVERT16(src, pos, signconv) \
65{ \
66 signed int f = (src + 0x80) >> 8; \
67 f = MID(-32768, f, 32767); \
68 ((short *)sptr)[pos] = (short)(f ^ signconv); \
69}
70
71#endif
72
73#define CONVERT24(src, pos) { \
74 signed int f = src; \
75 f = MID(-8388608, f, 8388607); \
76 ((unsigned char*)sptr)[pos ] = (f) & 0xFF; \
77 ((unsigned char*)sptr)[pos+1] = (f >> 8) & 0xFF; \
78 ((unsigned char*)sptr)[pos+2] = (f >> 16) & 0xFF; \
79}
80
81#define CONVERT32F(src, pos) { \
82 ((float*)sptr)[pos] = (float)((signed int)src) * (1.0f/(float)(0xffffff/2+1)); \
83}
84
85#define CONVERT64F(src, pos) { \
86 ((double*)sptr)[pos] = (double)((signed int)src) * (1.0/(double)(0xffffff/2+1)); \
87}
88
89
90/* DEPRECATED */
91DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos)
92{
93 return duh_start_sigrenderer(duh, 0, n_channels, pos);
94}
95
96
97/* DEPRECATED */
98long duh_render(
99 DUH_SIGRENDERER *sigrenderer,
100 int bits, int unsign,
101 float volume, float delta,
102 long size, void *sptr
103)
104{
105 long n;
106
107 sample_t **sampptr;
108
109 int n_channels;
110
111 ASSERT(bits == 8 || bits == 16);
112 ASSERT(sptr);
113
114 if (!sigrenderer)
115 return 0;
116
117 n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
118
119 ASSERT(n_channels > 0);
120 /* This restriction will be removed when need be. At the moment, tightly
121 * optimised loops exist for exactly one or two channels.
122 */
123 ASSERT(n_channels <= 2);
124
125 sampptr = allocate_sample_buffer(n_channels, size);
126
127 if (!sampptr)
128 return 0;
129
130 dumb_silence(sampptr[0], n_channels * size);
131
132 size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
133
134 if (bits == 16) {
135 int signconv = unsign ? 0x8000 : 0x0000;
136
137 for (n = 0; n < size * n_channels; n++) {
138 CONVERT16(sampptr[0][n], n, signconv);
139 }
140 } else {
141 char signconv = unsign ? 0x80 : 0x00;
142
143 for (n = 0; n < size * n_channels; n++) {
144 CONVERT8(sampptr[0][n], n, signconv);
145 }
146 }
147
148 destroy_sample_buffer(sampptr);
149
150 return size;
151}
152
153
154long duh_render_int(
155 DUH_SIGRENDERER *sigrenderer,
156 sample_t ***sig_samples,
157 long *sig_samples_size,
158 int bits, int unsign,
159 float volume, float delta,
160 long size, void *sptr
161)
162{
163 long n;
164
165 sample_t **sampptr;
166
167 int n_channels;
168
169 ASSERT(bits == 8 || bits == 16 || bits == 24);
170 ASSERT(sptr);
171 ASSERT(sig_samples);
172 ASSERT(sig_samples_size);
173
174 if (!sigrenderer)
175 return 0;
176
177 n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
178
179 ASSERT(n_channels > 0);
180 /* This restriction will be removed when need be. At the moment, tightly
181 * optimised loops exist for exactly one or two channels.
182 */
183 ASSERT(n_channels <= 2);
184
185 if ((*sig_samples == NULL) || (*sig_samples_size != size))
186 {
187 destroy_sample_buffer(*sig_samples);
188 *sig_samples = allocate_sample_buffer(n_channels, size);
189 *sig_samples_size = size;
190 }
191 sampptr = *sig_samples;
192
193 if (!sampptr)
194 return 0;
195
196 dumb_silence(sampptr[0], n_channels * size);
197
198 size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
199
200 if (bits == 24) {
201 long i = 0;
202 ASSERT(unsign == 0);
203
204 for (n = 0; n < size * n_channels; n++, i += 3) {
205 CONVERT24(sampptr[0][n], i);
206 }
207 } else
208 if (bits == 16) {
209 int signconv = unsign ? 0x8000 : 0x0000;
210
211 for (n = 0; n < size * n_channels; n++) {
212 CONVERT16(sampptr[0][n], n, signconv);
213 }
214 } else {
215 char signconv = unsign ? 0x80 : 0x00;
216
217 for (n = 0; n < size * n_channels; n++) {
218 CONVERT8(sampptr[0][n], n, signconv);
219 }
220 }
221
222 return size;
223}
224
225
226long duh_render_float(
227 DUH_SIGRENDERER *sigrenderer,
228 sample_t ***sig_samples,
229 long *sig_samples_size,
230 int bits,
231 float volume, float delta,
232 long size, void *sptr
233)
234{
235 long n;
236
237 sample_t **sampptr;
238
239 int n_channels;
240
241 ASSERT(bits == 32 || bits == 64);
242 ASSERT(sptr);
243 ASSERT(sig_samples);
244 ASSERT(sig_samples_size);
245
246 if (!sigrenderer)
247 return 0;
248
249 n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
250
251 ASSERT(n_channels > 0);
252 /* This restriction will be removed when need be. At the moment, tightly
253 * optimised loops exist for exactly one or two channels.
254 */
255 ASSERT(n_channels <= 2);
256
257 if ((*sig_samples == NULL) || (*sig_samples_size != size))
258 {
259 destroy_sample_buffer(*sig_samples);
260 *sig_samples = allocate_sample_buffer(n_channels, size);
261 *sig_samples_size = size;
262 }
263 sampptr = *sig_samples;
264
265 if (!sampptr)
266 return 0;
267
268 dumb_silence(sampptr[0], n_channels * size);
269
270 size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
271
272 if (bits == 64) {
273 for (n = 0; n < size * n_channels; n++) {
274 CONVERT64F(sampptr[0][n], n);
275 }
276 } else
277 if (bits == 32) {
278 for (n = 0; n < size * n_channels; n++) {
279 CONVERT32F(sampptr[0][n], n);
280 }
281 }
282
283 return size;
284}
285
286
287/* DEPRECATED */
288int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)
289{
290 return duh_sigrenderer_get_n_channels(dr);
291}
292
293
294
295/* DEPRECATED */
296long duh_renderer_get_position(DUH_SIGRENDERER *dr)
297{
298 return duh_sigrenderer_get_position(dr);
299}
300
301
302
303/* DEPRECATED */
304void duh_end_renderer(DUH_SIGRENDERER *dr)
305{
306 duh_end_sigrenderer(dr);
307}
308
309
310
311/* DEPRECATED */
312DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer)
313{
314 return sigrenderer;
315}
316
317
318
319/* DEPRECATED */
320DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr)
321{
322 return dr;
323}
324
325
326
327/* DEPRECATED */
328DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr)
329{
330 return dr;
331}
dumb/src/core/rendsig.c+0−352
@@ -1,352 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * rendsig.c - Wrappers to render samples from / / \ \
12 * the signals in a DUH. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27struct DUH_SIGRENDERER
28{
29 DUH_SIGTYPE_DESC *desc;
30
31 sigrenderer_t *sigrenderer;
32
33 int n_channels;
34
35 long pos;
36 int subpos;
37
38 DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback;
39 void *callback_data;
40};
41
42
43
44DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos)
45{
46 DUH_SIGRENDERER *sigrenderer;
47
48 DUH_SIGNAL *signal;
49 DUH_START_SIGRENDERER proc;
50
51 if (!duh)
52 return NULL;
53
54 if ((unsigned int)sig >= (unsigned int)duh->n_signals)
55 return NULL;
56
57 signal = duh->signal[sig];
58 if (!signal)
59 return NULL;
60
61 sigrenderer = malloc(sizeof(*sigrenderer));
62 if (!sigrenderer)
63 return NULL;
64
65 sigrenderer->desc = signal->desc;
66
67 proc = sigrenderer->desc->start_sigrenderer;
68
69 if (proc) {
70 duh->signal[sig] = NULL;
71 sigrenderer->sigrenderer = (*proc)(duh, signal->sigdata, n_channels, pos);
72 duh->signal[sig] = signal;
73
74 if (!sigrenderer->sigrenderer) {
75 free(sigrenderer);
76 return NULL;
77 }
78 } else
79 sigrenderer->sigrenderer = NULL;
80
81 sigrenderer->n_channels = n_channels;
82
83 sigrenderer->pos = pos;
84 sigrenderer->subpos = 0;
85
86 sigrenderer->callback = NULL;
87
88 return sigrenderer;
89}
90
91
92
93#include <stdio.h>
94void duh_sigrenderer_set_callback(
95 DUH_SIGRENDERER *sigrenderer,
96 DUH_SIGRENDERER_CALLBACK callback, void *data
97)
98{
99 (void)sigrenderer;
100 (void)callback;
101 (void)data;
102 /*fprintf(stderr,
103 "Call to deprecated function duh_sigrenderer_set_callback(). The callback\n"
104 "was not installed. See dumb/docs/deprec.txt for how to fix this.\n");*/
105}
106
107
108
109void duh_sigrenderer_set_analyser_callback(
110 DUH_SIGRENDERER *sigrenderer,
111 DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data
112)
113{
114 (void)sigrenderer;
115 (void)callback;
116 (void)data;
117 fprintf(stderr,
118 "Call to deprecated function duh_sigrenderer_set_analyser_callback(). The\n"
119 "callback was not installed. See dumb/docs/deprec.txt for how to fix this.\n");
120}
121
122
123
124void duh_sigrenderer_set_sample_analyser_callback(
125 DUH_SIGRENDERER *sigrenderer,
126 DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data
127)
128{
129 if (sigrenderer) {
130 sigrenderer->callback = callback;
131 sigrenderer->callback_data = data;
132 }
133}
134
135
136
137int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer)
138{
139 return sigrenderer ? sigrenderer->n_channels : 0;
140}
141
142
143
144long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
145{
146 DUH_SIGRENDERER_GET_POSITION proc;
147
148 if (!sigrenderer) return -1;
149
150 proc = sigrenderer->desc->sigrenderer_get_position;
151 if (proc)
152 return (*proc)(sigrenderer->sigrenderer);
153 else
154 return sigrenderer->pos;
155}
156
157
158
159void duh_sigrenderer_set_sigparam(
160 DUH_SIGRENDERER *sigrenderer,
161 unsigned char id, long value
162)
163{
164 DUH_SIGRENDERER_SET_SIGPARAM proc;
165
166 if (!sigrenderer) return;
167
168 proc = sigrenderer->desc->sigrenderer_set_sigparam;
169 if (proc)
170 (*proc)(sigrenderer->sigrenderer, id, value);
171 else
172 TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take parameters.\n",
173 (int)id,
174 value,
175 (int)(sigrenderer->desc->type >> 24),
176 (int)(sigrenderer->desc->type >> 16),
177 (int)(sigrenderer->desc->type >> 8),
178 (int)(sigrenderer->desc->type));
179}
180
181
182
183long duh_sigrenderer_generate_samples(
184 DUH_SIGRENDERER *sigrenderer,
185 float volume, float delta,
186 long size, sample_t **samples
187)
188{
189 long rendered;
190 LONG_LONG t;
191
192 if (!sigrenderer) return 0;
193
194 rendered = (*sigrenderer->desc->sigrenderer_generate_samples)
195 (sigrenderer->sigrenderer, volume, delta, size, samples);
196
197 if (rendered) {
198 if (sigrenderer->callback)
199 (*sigrenderer->callback)(sigrenderer->callback_data,
200 (const sample_t *const *)samples, sigrenderer->n_channels, rendered);
201
202 t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered;
203
204 sigrenderer->pos += (long)(t >> 16);
205 sigrenderer->subpos = (int)t & 65535;
206 }
207
208 return rendered;
209}
210
211
212
213/* DEPRECATED */
214long duh_sigrenderer_get_samples(
215 DUH_SIGRENDERER *sigrenderer,
216 float volume, float delta,
217 long size, sample_t **samples
218)
219{
220 sample_t **s;
221 long rendered;
222 long i;
223 int j;
224 if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
225 s = allocate_sample_buffer(sigrenderer->n_channels, size);
226 if (!s) return 0;
227 dumb_silence(s[0], sigrenderer->n_channels * size);
228 rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s);
229 for (j = 0; j < sigrenderer->n_channels; j++)
230 for (i = 0; i < rendered; i++)
231 samples[j][i] += s[0][i*sigrenderer->n_channels+j];
232 destroy_sample_buffer(s);
233 return rendered;
234}
235
236
237
238/* DEPRECATED */
239long duh_render_signal(
240 DUH_SIGRENDERER *sigrenderer,
241 float volume, float delta,
242 long size, sample_t **samples
243)
244{
245 sample_t **s;
246 long rendered;
247 long i;
248 int j;
249 if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
250 s = allocate_sample_buffer(sigrenderer->n_channels, size);
251 if (!s) return 0;
252 dumb_silence(s[0], sigrenderer->n_channels * size);
253 rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s);
254 for (j = 0; j < sigrenderer->n_channels; j++)
255 for (i = 0; i < rendered; i++)
256 samples[j][i] += s[0][i*sigrenderer->n_channels+j] >> 8;
257 destroy_sample_buffer(s);
258 return rendered;
259}
260
261
262
263void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples)
264{
265 if (sigrenderer)
266 (*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples);
267}
268
269
270
271void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer)
272{
273 if (sigrenderer) {
274 if (sigrenderer->desc->end_sigrenderer)
275 if (sigrenderer->sigrenderer)
276 (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
277
278 free(sigrenderer);
279 }
280}
281
282
283
284DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos)
285{
286 DUH_SIGRENDERER *sigrenderer;
287
288 if (desc->start_sigrenderer && !vsigrenderer) return NULL;
289
290 sigrenderer = malloc(sizeof(*sigrenderer));
291 if (!sigrenderer) {
292 if (desc->end_sigrenderer)
293 if (vsigrenderer)
294 (*desc->end_sigrenderer)(vsigrenderer);
295 return NULL;
296 }
297
298 sigrenderer->desc = desc;
299 sigrenderer->sigrenderer = vsigrenderer;
300
301 sigrenderer->n_channels = n_channels;
302
303 sigrenderer->pos = pos;
304 sigrenderer->subpos = 0;
305
306 sigrenderer->callback = NULL;
307
308 return sigrenderer;
309}
310
311
312
313sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
314{
315 if (sigrenderer && sigrenderer->desc->type == type)
316 return sigrenderer->sigrenderer;
317
318 return NULL;
319}
320
321
322
323#if 0
324// This function is disabled because we don't know whether we want to destroy
325// the sigrenderer if the type doesn't match. We don't even know if we need
326// the function at all. Who would want to keep an IT_SIGRENDERER (for
327// instance) without keeping the DUH_SIGRENDERER?
328sigrenderer_t *duh_decompose_to_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
329{
330 if (sigrenderer && sigrenderer->desc->type == type) {
331
332
333
334 if (sigrenderer) {
335 if (sigrenderer->desc->end_sigrenderer)
336 if (sigrenderer->sigrenderer)
337 (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
338
339 free(sigrenderer);
340 }
341
342
343
344
345
346
347 return sigrenderer->sigrenderer;
348 }
349
350 return NULL;
351}
352#endif
dumb/src/helpers/barray.c+0−189
@@ -1,189 +0,0 @@
1#include "internal/barray.h"
2
3#include <string.h>
4
5
6void * bit_array_create(size_t size)
7{
8 size_t bsize = ((size + 7) >> 3) + sizeof(size_t);
9 void * ret = calloc(1, bsize);
10 if (ret) *(size_t *)ret = size;
11 return ret;
12}
13
14void bit_array_destroy(void * array)
15{
16 if (array) free(array);
17}
18
19void * bit_array_dup(void * array)
20{
21 if (array)
22 {
23 size_t * size = (size_t *) array;
24 size_t bsize = ((*size + 7) >> 3) + sizeof(*size);
25 void * ret = malloc(bsize);
26 if (ret) memcpy(ret, array, bsize);
27 return ret;
28 }
29 return NULL;
30}
31
32void bit_array_reset(void * array)
33{
34 if (array)
35 {
36 size_t * size = (size_t *) array;
37 size_t bsize = (*size + 7) >> 3;
38 memset(size + 1, 0, bsize);
39 }
40}
41
42
43void bit_array_set(void * array, size_t bit)
44{
45 if (array)
46 {
47 size_t * size = (size_t *) array;
48 if (bit < *size)
49 {
50 unsigned char * ptr = (unsigned char *)(size + 1);
51 ptr[bit >> 3] |= (1U << (bit & 7));
52 }
53 }
54}
55
56void bit_array_set_range(void * array, size_t bit, size_t count)
57{
58 if (array && count)
59 {
60 size_t * size = (size_t *) array;
61 if (bit < *size)
62 {
63 unsigned char * ptr = (unsigned char *)(size + 1);
64 size_t i;
65 for (i = bit; i < *size && i < bit + count; ++i)
66 ptr[i >> 3] |= (1U << (i & 7));
67 }
68 }
69}
70
71int bit_array_test(void * array, size_t bit)
72{
73 if (array)
74 {
75 size_t * size = (size_t *) array;
76 if (bit < *size)
77 {
78 unsigned char * ptr = (unsigned char *)(size + 1);
79 if (ptr[bit >> 3] & (1U << (bit & 7)))
80 {
81 return 1;
82 }
83 }
84 }
85 return 0;
86}
87
88int bit_array_test_range(void * array, size_t bit, size_t count)
89{
90 if (array)
91 {
92 size_t * size = (size_t *) array;
93 if (bit < *size)
94 {
95 unsigned char * ptr = (unsigned char *)(size + 1);
96 if ((bit & 7) && (count > 8))
97 {
98 while ((bit < *size) && count && (bit & 7))
99 {
100 if (ptr[bit >> 3] & (1U << (bit & 7))) return 1;
101 bit++;
102 count--;
103 }
104 }
105 if (!(bit & 7))
106 {
107 while (((*size - bit) >= 8) && (count >= 8))
108 {
109 if (ptr[bit >> 3]) return 1;
110 bit += 8;
111 count -= 8;
112 }
113 }
114 while ((bit < *size) && count)
115 {
116 if (ptr[bit >> 3] & (1U << (bit & 7))) return 1;
117 bit++;
118 count--;
119 }
120 }
121 }
122 return 0;
123}
124
125void bit_array_clear(void * array, size_t bit)
126{
127 if (array)
128 {
129 size_t * size = (size_t *) array;
130 if (bit < *size)
131 {
132 unsigned char * ptr = (unsigned char *)(size + 1);
133 ptr[bit >> 3] &= ~(1U << (bit & 7));
134 }
135 }
136}
137
138void bit_array_clear_range(void * array, size_t bit, size_t count)
139{
140 if (array && count)
141 {
142 size_t * size = (size_t *) array;
143 if (bit < *size)
144 {
145 unsigned char * ptr = (unsigned char *)(size + 1);
146 size_t i;
147 for (i = bit; i < *size && i < bit + count; ++i)
148 ptr[i >> 3] &= ~(1U << (i & 7));
149 }
150 }
151}
152
153void bit_array_merge(void * dest, void * source, size_t offset)
154{
155 if (dest && source)
156 {
157 size_t * dsize = (size_t *) dest;
158 size_t * ssize = (size_t *) source;
159 size_t soffset = 0;
160 while (offset < *dsize && soffset < *ssize)
161 {
162 if (bit_array_test(source, soffset))
163 {
164 bit_array_set(dest, offset);
165 }
166 soffset++;
167 offset++;
168 }
169 }
170}
171
172void bit_array_mask(void * dest, void * source, size_t offset)
173{
174 if (dest && source)
175 {
176 size_t * dsize = (size_t *) dest;
177 size_t * ssize = (size_t *) source;
178 size_t soffset = 0;
179 while (offset < *dsize && soffset < *ssize)
180 {
181 if (bit_array_test(source, soffset))
182 {
183 bit_array_clear(dest, offset);
184 }
185 soffset++;
186 offset++;
187 }
188 }
189}
dumb/src/helpers/clickrem.c+0−281
@@ -1,281 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * clickrem.c - Click removal helpers. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <math.h>
22#include "dumb.h"
23
24
25
26typedef struct DUMB_CLICK DUMB_CLICK;
27
28
29struct DUMB_CLICK_REMOVER
30{
31 DUMB_CLICK *click;
32 int n_clicks;
33
34 int offset;
35};
36
37
38struct DUMB_CLICK
39{
40 DUMB_CLICK *next;
41 long pos;
42 sample_t step;
43};
44
45
46
47DUMB_CLICK_REMOVER *dumb_create_click_remover(void)
48{
49 DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr));
50 if (!cr) return NULL;
51
52 cr->click = NULL;
53 cr->n_clicks = 0;
54
55 cr->offset = 0;
56
57 return cr;
58}
59
60
61
62void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step)
63{
64 DUMB_CLICK *click;
65
66 ASSERT(pos >= 0);
67
68 if (!cr || !step) return;
69
70 if (pos == 0) {
71 cr->offset -= step;
72 return;
73 }
74
75 click = malloc(sizeof(*click));
76 if (!click) return;
77
78 click->pos = pos;
79 click->step = step;
80
81 click->next = cr->click;
82 cr->click = click;
83 cr->n_clicks++;
84}
85
86
87
88static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks)
89{
90 int i;
91 DUMB_CLICK *c1, *c2, **cp;
92
93 if (n_clicks <= 1) return click;
94
95 /* Split the list into two */
96 c1 = click;
97 cp = &c1;
98 for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next;
99 c2 = *cp;
100 *cp = NULL;
101
102 /* Sort the sublists */
103 c1 = dumb_click_mergesort(c1, (n_clicks + 1) >> 1);
104 c2 = dumb_click_mergesort(c2, n_clicks >> 1);
105
106 /* Merge them */
107 cp = &click;
108 while (c1 && c2) {
109 if (c1->pos > c2->pos) {
110 *cp = c2;
111 c2 = c2->next;
112 } else {
113 *cp = c1;
114 c1 = c1->next;
115 }
116 cp = &(*cp)->next;
117 }
118 if (c2)
119 *cp = c2;
120 else
121 *cp = c1;
122
123 return click;
124}
125
126
127
128void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife)
129{
130 DUMB_CLICK *click;
131 long pos = 0;
132 int offset;
133 int factor;
134
135 if (!cr) return;
136
137 factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31));
138
139 click = dumb_click_mergesort(cr->click, cr->n_clicks);
140 cr->click = NULL;
141 cr->n_clicks = 0;
142
143 length *= step;
144
145 while (click) {
146 DUMB_CLICK *next = click->next;
147 int end = click->pos * step;
148 ASSERT(end <= length);
149 offset = cr->offset;
150 if (offset < 0) {
151 offset = -offset;
152 while (pos < end) {
153 samples[pos] -= offset;
154 offset = (int)(((LONG_LONG)(offset << 1) * factor) >> 32);
155 pos += step;
156 }
157 offset = -offset;
158 } else {
159 while (pos < end) {
160 samples[pos] += offset;
161 offset = (int)(((LONG_LONG)(offset << 1) * factor) >> 32);
162 pos += step;
163 }
164 }
165 cr->offset = offset - click->step;
166 free(click);
167 click = next;
168 }
169
170 offset = cr->offset;
171 if (offset < 0) {
172 offset = -offset;
173 while (pos < length) {
174 samples[pos] -= offset;
175 offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
176 pos += step;
177 }
178 offset = -offset;
179 } else {
180 while (pos < length) {
181 samples[pos] += offset;
182 offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
183 pos += step;
184 }
185 }
186 cr->offset = offset;
187}
188
189
190
191sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr)
192{
193 return cr ? cr->offset : 0;
194}
195
196
197
198void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr)
199{
200 if (cr) {
201 DUMB_CLICK *click = cr->click;
202 while (click) {
203 DUMB_CLICK *next = click->next;
204 free(click);
205 click = next;
206 }
207 free(cr);
208 }
209}
210
211
212
213DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n)
214{
215 int i;
216 DUMB_CLICK_REMOVER **cr;
217 if (n <= 0) return NULL;
218 cr = malloc(n * sizeof(*cr));
219 if (!cr) return NULL;
220 for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover();
221 return cr;
222}
223
224
225
226void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
227{
228 if (cr) {
229 int i;
230 for (i = 0; i < n; i++)
231 dumb_record_click(cr[i], pos, step[i]);
232 }
233}
234
235
236
237void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
238{
239 if (cr) {
240 int i;
241 for (i = 0; i < n; i++)
242 dumb_record_click(cr[i], pos, -step[i]);
243 }
244}
245
246
247
248void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife)
249{
250 if (cr) {
251 int i;
252 for (i = 0; i < n >> 1; i++) {
253 dumb_remove_clicks(cr[i << 1], samples[i], length, 2, halflife);
254 dumb_remove_clicks(cr[(i << 1) + 1], samples[i] + 1, length, 2, halflife);
255 }
256 if (n & 1)
257 dumb_remove_clicks(cr[i << 1], samples[i], length, 1, halflife);
258 }
259}
260
261
262
263void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset)
264{
265 if (cr) {
266 int i;
267 for (i = 0; i < n; i++)
268 if (cr[i]) offset[i] += cr[i]->offset;
269 }
270}
271
272
273
274void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr)
275{
276 if (cr) {
277 int i;
278 for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]);
279 free(cr);
280 }
281}
dumb/src/helpers/fir_resampler.c+0−281
@@ -1,281 +0,0 @@
1#include <stdlib.h>
2#include <string.h>
3#include <math.h>
4
5#include "internal/fir_resampler.h"
6
7enum { fir_width = 16 };
8
9enum { fir_max_res = 1024 };
10enum { fir_min_width = (fir_width < 4 ? 4 : fir_width) };
11enum { fir_adj_width = fir_min_width / 4 * 4 + 2 };
12enum { fir_stereo = 1 }; /* channel count, not boolean value */
13enum { fir_write_offset = fir_adj_width * fir_stereo };
14
15enum { fir_buffer_size = fir_width * 2 };
16
17typedef short fir_impulse[fir_adj_width];
18
19/* exp slope to 31/32 of ln(8) */
20static const double fir_ratios[32] = {
21 1.000, 1.067, 1.139, 1.215, 1.297, 1.384, 1.477, 1.576,
22 1.682, 1.795, 1.915, 2.044, 2.181, 2.327, 2.484, 2.650,
23 2.828, 3.018, 3.221, 3.437, 3.668, 3.914, 4.177, 4.458,
24 4.757, 5.076, 5.417, 5.781, 6.169, 6.583, 7.025, 7.497
25};
26
27static fir_impulse fir_impulses[32][fir_max_res];
28
29#undef PI
30#define PI 3.1415926535897932384626433832795029
31
32static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale,
33 int count, short* out )
34{
35 double const maxh = 256;
36 double const step = PI / maxh * spacing;
37 double const to_w = maxh * 2 / width;
38 double const pow_a_n = pow( rolloff, maxh );
39
40 double angle = (count / 2 - 1 + offset) * -step;
41
42 scale /= maxh * 2;
43
44 while ( count-- )
45 {
46 double w;
47 *out++ = 0;
48 w = angle * to_w;
49 if ( fabs( w ) < PI )
50 {
51 double rolloff_cos_a = rolloff * cos( angle );
52 double num = 1 - rolloff_cos_a -
53 pow_a_n * cos( maxh * angle ) +
54 pow_a_n * rolloff * cos( (maxh - 1) * angle );
55 double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
56 double sinc = scale * num / den - scale;
57
58 out [-1] = (short) (cos( w ) * sinc + sinc);
59 }
60 angle += step;
61 }
62}
63
64typedef struct fir_resampler
65{
66 int write_pos, write_filled;
67 int read_pos, read_filled;
68 unsigned short phase;
69 unsigned int phase_inc;
70 unsigned int ratio_set;
71 int buffer_in[fir_buffer_size * 2];
72 int buffer_out[fir_buffer_size];
73} fir_resampler;
74
75void * fir_resampler_create()
76{
77 fir_resampler * r = ( fir_resampler * ) malloc( sizeof(fir_resampler) );
78 if ( !r ) return 0;
79
80 r->write_pos = 0;
81 r->write_filled = 0;
82 r->read_pos = 0;
83 r->read_filled = 0;
84 r->phase = 0;
85 r->phase_inc = 0;
86 r->ratio_set = 0;
87 memset( r->buffer_in, 0, sizeof(r->buffer_in) );
88 memset( r->buffer_out, 0, sizeof(r->buffer_out) );
89
90 return r;
91}
92
93void fir_resampler_delete(void * _r)
94{
95 free( _r );
96}
97
98void * fir_resampler_dup(void * _r)
99{
100 fir_resampler * r_in = ( fir_resampler * ) _r;
101 fir_resampler * r_out = ( fir_resampler * ) malloc( sizeof(fir_resampler) );
102 if ( !r_out ) return 0;
103
104 r_out->write_pos = r_in->write_pos;
105 r_out->write_filled = r_in->write_filled;
106 r_out->read_pos = r_in->read_pos;
107 r_out->read_filled = r_in->read_filled;
108 r_out->phase = r_in->phase;
109 r_out->phase_inc = r_in->phase_inc;
110 r_out->ratio_set = r_in->ratio_set;
111 memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) );
112 memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
113
114 return r_out;
115}
116
117int fir_resampler_get_free_count(void *_r)
118{
119 fir_resampler * r = ( fir_resampler * ) _r;
120 return fir_buffer_size - r->write_filled;
121}
122
123int fir_resampler_ready(void *_r)
124{
125 fir_resampler * r = ( fir_resampler * ) _r;
126 return r->write_filled > fir_adj_width;
127}
128
129void fir_resampler_clear(void *_r)
130{
131 fir_resampler * r = ( fir_resampler * ) _r;
132 r->write_pos = 0;
133 r->write_filled = 0;
134 r->read_pos = 0;
135 r->read_filled = 0;
136 r->phase = 0;
137 memset( r->buffer_in, 0, sizeof(r->buffer_in) );
138}
139
140void fir_resampler_set_rate(void *_r, double new_factor)
141{
142 fir_resampler * r = ( fir_resampler * ) _r;
143 r->phase_inc = (int)( new_factor * 65536.0 );
144 r->ratio_set = 0;
145 while ( r->ratio_set < 31 && new_factor > fir_ratios[ r->ratio_set ] ) r->ratio_set++;
146}
147
148void fir_resampler_write_sample(void *_r, short s)
149{
150 fir_resampler * r = ( fir_resampler * ) _r;
151
152 if ( r->write_filled < fir_buffer_size )
153 {
154 int s32 = s;
155
156 r->buffer_in[ r->write_pos ] = s32;
157 r->buffer_in[ r->write_pos + fir_buffer_size ] = s32;
158
159 ++r->write_filled;
160
161 r->write_pos = ( r->write_pos + 1 ) % fir_buffer_size;
162 }
163}
164
165void fir_init()
166{
167 double const rolloff = 0.999;
168 double const gain = 1.0;
169
170 int const res = fir_max_res;
171
172 int i;
173
174 for (i = 0; i < 32; i++)
175 {
176 double const ratio_ = fir_ratios[ i ];
177
178 double fraction = 1.0 / (double)fir_max_res;
179
180 double const filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
181 double pos = 0.0;
182 short* out = (short*) fir_impulses[ i ];
183 int n;
184 for ( n = res; --n >= 0; )
185 {
186 gen_sinc( rolloff, (int) (fir_adj_width * filter + 1) & ~1, pos, filter,
187 (double) (0x7FFF * gain * filter), (int) fir_adj_width, out );
188 out += fir_adj_width;
189
190 pos += fraction;
191 }
192 }
193}
194
195int fir_resampler_run(void *_r, int ** out_, int * out_end)
196{
197 fir_resampler * r = ( fir_resampler * ) _r;
198 int in_size = r->write_filled;
199 int const* in_ = r->buffer_in + fir_buffer_size + r->write_pos - r->write_filled;
200 int used = 0;
201 in_size -= fir_write_offset;
202 if ( in_size > 0 )
203 {
204 int* out = *out_;
205 int const* in = in_;
206 int const* const in_end = in + in_size;
207 int phase = r->phase;
208 int phase_inc = r->phase_inc;
209 int ratio_set = r->ratio_set;
210
211 do
212 {
213 // accumulate in extended precision
214 short const* imp = fir_impulses[ratio_set][(phase & 0xFFC0) >> 6];
215 int pt = imp [0];
216 int s = pt * in [0];
217 int n;
218 if ( out >= out_end )
219 break;
220 for ( n = (fir_adj_width - 2) / 2; n; --n )
221 {
222 pt = imp [1];
223 s += pt * in [1];
224
225 // pre-increment more efficient on some RISC processors
226 imp += 2;
227 pt = imp [0];
228 in += 2;
229 s += pt * in [0];
230 }
231 pt = imp [1];
232 s += pt * in [1];
233
234 phase += phase_inc;
235
236 in += (phase >> 16) - fir_adj_width + 2;
237
238 phase &= 65535;
239
240 *out++ = (int) (s >> 7);
241 }
242 while ( in < in_end );
243
244 r->phase = phase;
245 *out_ = out;
246
247 used = in - in_;
248
249 r->write_filled -= used;
250 }
251
252 return used;
253}
254
255int fir_resampler_get_sample(void *_r)
256{
257 fir_resampler * r = ( fir_resampler * ) _r;
258 if ( r->read_filled < 1 )
259 {
260 int write_pos = ( r->read_pos + r->read_filled ) % fir_buffer_size;
261 int write_size = fir_buffer_size - write_pos;
262 int * out = r->buffer_out + write_pos;
263 if ( write_size > ( fir_buffer_size - r->read_filled ) )
264 write_size = fir_buffer_size - r->read_filled;
265 fir_resampler_run( r, &out, out + write_size );
266 r->read_filled += out - r->buffer_out - write_pos;
267 }
268 if ( r->read_filled < 1 )
269 return 0;
270 return r->buffer_out[ r->read_pos ];
271}
272
273void fir_resampler_remove_sample(void *_r)
274{
275 fir_resampler * r = ( fir_resampler * ) _r;
276 if ( r->read_filled > 0 )
277 {
278 --r->read_filled;
279 r->read_pos = ( r->read_pos + 1 ) % fir_buffer_size;
280 }
281}
dumb/src/helpers/lpc.c+0−320
@@ -1,320 +0,0 @@
1/********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
7 * *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
10 * *
11 ********************************************************************
12
13 function: LPC low level routines
14 last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $
15
16 ********************************************************************/
17
18/* Some of these routines (autocorrelator, LPC coefficient estimator)
19 are derived from code written by Jutta Degener and Carsten Bormann;
20 thus we include their copyright below. The entirety of this file
21 is freely redistributable on the condition that both of these
22 copyright notices are preserved without modification. */
23
24/* Preserved Copyright: *********************************************/
25
26/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
27Technische Universita"t Berlin
28
29Any use of this software is permitted provided that this notice is not
30removed and that neither the authors nor the Technische Universita"t
31Berlin are deemed to have made any representations as to the
32suitability of this software for any purpose nor are held responsible
33for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
34THIS SOFTWARE.
35
36As a matter of courtesy, the authors request to be informed about uses
37this software has found, about bugs in this software, and about any
38improvements that may be of general interest.
39
40Berlin, 28.11.1994
41Jutta Degener
42Carsten Bormann
43
44*********************************************************************/
45
46#include <stdlib.h>
47#include <string.h>
48#include <math.h>
49#include "internal/stack_alloc.h"
50#include "internal/lpc.h"
51
52/* Autocorrelation LPC coeff generation algorithm invented by
53 N. Levinson in 1947, modified by J. Durbin in 1959. */
54
55/* Input : n elements of time doamin data
56 Output: m lpc coefficients, excitation energy */
57
58static float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
59 double *aut=alloca(sizeof(*aut)*(m+1));
60 double *lpc=alloca(sizeof(*lpc)*(m));
61 double error;
62 double epsilon;
63 int i,j;
64
65 /* autocorrelation, p+1 lag coefficients */
66 j=m+1;
67 while(j--){
68 double d=0; /* double needed for accumulator depth */
69 for(i=j;i<n;i++)d+=(double)data[i]*data[(i-j)];
70 aut[j]=d;
71 }
72
73 /* Generate lpc coefficients from autocorr values */
74
75 /* set our noise floor to about -100dB */
76 error=aut[0] * (1. + 1e-10);
77 epsilon=1e-9*aut[0]+1e-10;
78
79 for(i=0;i<m;i++){
80 double r= -aut[i+1];
81
82 if(error<epsilon){
83 memset(lpc+i,0,(m-i)*sizeof(*lpc));
84 goto done;
85 }
86
87 /* Sum up this iteration's reflection coefficient; note that in
88 Vorbis we don't save it. If anyone wants to recycle this code
89 and needs reflection coefficients, save the results of 'r' from
90 each iteration. */
91
92 for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
93 r/=error;
94
95 /* Update LPC coefficients and total error */
96
97 lpc[i]=r;
98 for(j=0;j<i/2;j++){
99 double tmp=lpc[j];
100
101 lpc[j]+=r*lpc[i-1-j];
102 lpc[i-1-j]+=r*tmp;
103 }
104 if(i&1)lpc[j]+=lpc[j]*r;
105
106 error*=1.-r*r;
107
108 }
109
110 done:
111
112 /* slightly damp the filter */
113 {
114 double g = .99;
115 double damp = g;
116 for(j=0;j<m;j++){
117 lpc[j]*=damp;
118 damp*=g;
119 }
120 }
121
122 for(j=0;j<m;j++)lpci[j]=(float)lpc[j];
123
124 /* we need the error value to know how big an impulse to hit the
125 filter with later */
126
127 return error;
128}
129
130static void vorbis_lpc_predict(float *coeff,float *prime,int m,
131 float *data,long n){
132
133 /* in: coeff[0...m-1] LPC coefficients
134 prime[0...m-1] initial values (allocated size of n+m-1)
135 out: data[0...n-1] data samples */
136
137 long i,j,o,p;
138 float y;
139 float *work=alloca(sizeof(*work)*(m+n));
140
141 if(!prime)
142 for(i=0;i<m;i++)
143 work[i]=0.f;
144 else
145 for(i=0;i<m;i++)
146 work[i]=prime[i];
147
148 for(i=0;i<n;i++){
149 y=0;
150 o=i;
151 p=m;
152 for(j=0;j<m;j++)
153 y-=work[o++]*coeff[--p];
154
155 data[i]=work[o]=y;
156 }
157}
158
159#include "dumb.h"
160#include "internal/dumb.h"
161#include "internal/it.h"
162
163enum { lpc_max = 256 }; /* Maximum number of input samples to train the function */
164enum { lpc_order = 32 }; /* Order of the filter */
165enum { lpc_extra = 64 }; /* How many samples of padding to predict or silence */
166
167
168/* This extra sample padding is really only needed by the FIR resampler, but it helps the other resamplers as well. */
169
170void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
171 float lpc[lpc_order * 2];
172 float lpc_input[lpc_max * 2];
173 float lpc_output[lpc_extra * 2];
174
175 signed char * s8;
176 signed short * s16;
177
178 int n, o, offset, lpc_samples;
179
180 for ( n = 0; n < sigdata->n_samples; n++ ) {
181 IT_SAMPLE * sample = sigdata->sample + n;
182 if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS ) {
183 /* If we have enough sample data to train the filter, use the filter to generate the padding */
184 if ( sample->length >= lpc_order ) {
185 lpc_samples = sample->length;
186 if (lpc_samples > lpc_max) lpc_samples = lpc_max;
187 offset = sample->length - lpc_samples;
188
189 if ( sample->flags & IT_SAMPLE_STEREO )
190 {
191 if ( sample->flags & IT_SAMPLE_16BIT )
192 {
193 s16 = ( signed short * ) sample->data;
194 s16 += offset * 2;
195 for ( o = 0; o < lpc_samples; o++ )
196 {
197 lpc_input[ o ] = s16[ o * 2 + 0 ];
198 lpc_input[ o + lpc_max ] = s16[ o * 2 + 1 ];
199 }
200 }
201 else
202 {
203 s8 = ( signed char * ) sample->data;
204 s8 += offset * 2;
205 for ( o = 0; o < lpc_samples; o++ )
206 {
207 lpc_input[ o ] = s8[ o * 2 + 0 ];
208 lpc_input[ o + lpc_max ] = s8[ o * 2 + 1 ];
209 }
210 }
211
212 vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order );
213 vorbis_lpc_from_data( lpc_input + lpc_max, lpc + lpc_order, lpc_samples, lpc_order );
214
215 vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra );
216 vorbis_lpc_predict( lpc + lpc_order, lpc_input + lpc_max + lpc_samples - lpc_order, lpc_order, lpc_output + lpc_extra, lpc_extra );
217
218 if ( sample->flags & IT_SAMPLE_16BIT )
219 {
220 s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) );
221 sample->data = s16;
222
223 s16 += sample->length * 2;
224 sample->length += lpc_extra;
225
226 for ( o = 0; o < lpc_extra; o++ )
227 {
228 s16[ o * 2 + 0 ] = lpc_output[ o ];
229 s16[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
230 }
231 }
232 else
233 {
234 s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 );
235 sample->data = s8;
236
237 s8 += sample->length * 2;
238 sample->length += lpc_extra;
239
240 for ( o = 0; o < lpc_extra; o++ )
241 {
242 s8[ o * 2 + 0 ] = lpc_output[ o ];
243 s8[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
244 }
245 }
246 }
247 else
248 {
249 if ( sample->flags & IT_SAMPLE_16BIT )
250 {
251 s16 = ( signed short * ) sample->data;
252 s16 += offset;
253 for ( o = 0; o < lpc_samples; o++ )
254 {
255 lpc_input[ o ] = s16[ o ];
256 }
257 }
258 else
259 {
260 s8 = ( signed char * ) sample->data;
261 s8 += offset;
262 for ( o = 0; o < lpc_samples; o++ )
263 {
264 lpc_input[ o ] = s8[ o ];
265 }
266 }
267
268 vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order );
269
270 vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra );
271
272 if ( sample->flags & IT_SAMPLE_16BIT )
273 {
274 s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) );
275 sample->data = s16;
276
277 s16 += sample->length;
278 sample->length += lpc_extra;
279
280 for ( o = 0; o < lpc_extra; o++ )
281 {
282 s16[ o ] = lpc_output[ o ];
283 }
284 }
285 else
286 {
287 s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra );
288 sample->data = s8;
289
290 s8 += sample->length;
291 sample->length += lpc_extra;
292
293 for ( o = 0; o < lpc_extra; o++ )
294 {
295 s8[ o ] = lpc_output[ o ];
296 }
297 }
298 }
299 }
300 else
301 /* Otherwise, pad with silence. */
302 {
303 offset = sample->length;
304 lpc_samples = lpc_extra;
305
306 sample->length += lpc_samples;
307
308 n = 1;
309 if ( sample->flags & IT_SAMPLE_STEREO ) n *= 2;
310 if ( sample->flags & IT_SAMPLE_16BIT ) n *= 2;
311
312 offset *= n;
313 lpc_samples *= n;
314
315 sample->data = realloc( sample->data, offset + lpc_samples );
316 memset( (char*)sample->data + offset, 0, lpc_samples );
317 }
318 }
319 }
320}
dumb/src/helpers/memfile.c+0−117
@@ -1,117 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * memfile.c - Module for reading data from / / \ \
12 * memory using a DUMBFILE. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22
23#include "dumb.h"
24
25
26
27typedef struct MEMFILE MEMFILE;
28
29struct MEMFILE
30{
31 const char *ptr, *ptr_begin;
32 long left, size;
33};
34
35
36
37static int dumb_memfile_skip(void *f, long n)
38{
39 MEMFILE *m = f;
40 if (n > m->left) return -1;
41 m->ptr += n;
42 m->left -= n;
43 return 0;
44}
45
46
47
48static int dumb_memfile_getc(void *f)
49{
50 MEMFILE *m = f;
51 if (m->left <= 0) return -1;
52 m->left--;
53 return *(const unsigned char *)m->ptr++;
54}
55
56
57
58static long dumb_memfile_getnc(char *ptr, long n, void *f)
59{
60 MEMFILE *m = f;
61 if (n > m->left) n = m->left;
62 memcpy(ptr, m->ptr, n);
63 m->ptr += n;
64 m->left -= n;
65 return n;
66}
67
68
69
70static void dumb_memfile_close(void *f)
71{
72 free(f);
73}
74
75
76static int dumb_memfile_seek(void *f, long n)
77{
78 MEMFILE *m = f;
79
80 m->ptr = m->ptr_begin + n;
81 m->left = m->size - n;
82
83 return 0;
84}
85
86
87static long dumb_memfile_get_size(void *f)
88{
89 MEMFILE *m = f;
90 return m->size;
91}
92
93
94static const DUMBFILE_SYSTEM memfile_dfs = {
95 NULL,
96 &dumb_memfile_skip,
97 &dumb_memfile_getc,
98 &dumb_memfile_getnc,
99 &dumb_memfile_close,
100 &dumb_memfile_seek,
101 &dumb_memfile_get_size
102};
103
104
105
106DUMBFILE *dumbfile_open_memory(const char *data, long size)
107{
108 MEMFILE *m = malloc(sizeof(*m));
109 if (!m) return NULL;
110
111 m->ptr_begin = data;
112 m->ptr = data;
113 m->left = size;
114 m->size = size;
115
116 return dumbfile_open_ex(m, &memfile_dfs);
117}
dumb/src/helpers/resamp2.inc+0−162
@@ -1,162 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * resamp2.inc - Resampling helper template. / / \ \
12 * | < / \_
13 * By Bob and entheh. | \/ /\ /
14 * \_ / > /
15 * In order to find a good trade-off between | \ / /
16 * speed and accuracy in this code, some tests | ' /
17 * were carried out regarding the behaviour of \__/
18 * long long ints with gcc. The following code
19 * was tested:
20 *
21 * int a, b, c;
22 * c = ((long long)a * b) >> 16;
23 *
24 * DJGPP GCC Version 3.0.3 generated the following assembly language code for
25 * the multiplication and scaling, leaving the 32-bit result in EAX.
26 *
27 * movl -8(%ebp), %eax ; read one int into EAX
28 * imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
29 * shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
30 *
31 * Note that a 32*32->64 multiplication is performed, allowing for high
32 * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
33 * so it is a minor concern when four multiplications are being performed
34 * (the cubic resampler). On the Pentium MMX and earlier, it takes four or
35 * more cycles, so this method is unsuitable for use in the low-quality
36 * resamplers.
37 *
38 * Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
39 * defined in dumb.h. We may investigate later what code MSVC generates, but
40 * if it seems too slow then we suggest you use a good compiler.
41 *
42 * FIXME: these comments are somewhat out of date now.
43 */
44
45
46
47#define SUFFIX3 _1
48
49/* For convenience, returns nonzero on stop. */
50static int process_pickup(DUMB_RESAMPLER *resampler)
51{
52 if (resampler->overshot < 0) {
53 resampler->overshot = 0;
54 dumb_resample(resampler, NULL, 2, MONO_DEST_VOLUME_ZEROS, 1.0f); /* Doesn't matter which SUFFIX3. */
55 COPYSRC(resampler->X, 0, resampler->X, 1);
56 }
57
58 for (;;) {
59 SRCTYPE *src = resampler->src;
60
61 if (resampler->dir < 0) {
62 if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) COPYSRC(resampler->X, 0, src, resampler->pos+3);
63 if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) COPYSRC(resampler->X, 1, src, resampler->pos+2);
64 if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) COPYSRC(resampler->X, 2, src, resampler->pos+1);
65 resampler->overshot = resampler->start - resampler->pos - 1;
66 } else {
67 if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) COPYSRC(resampler->X, 0, src, resampler->pos-3);
68 if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) COPYSRC(resampler->X, 1, src, resampler->pos-2);
69 if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) COPYSRC(resampler->X, 2, src, resampler->pos-1);
70 resampler->overshot = resampler->pos - resampler->end;
71 }
72
73 if (resampler->overshot < 0) {
74 resampler->overshot = 0;
75 return 0;
76 }
77
78 if (!resampler->pickup) {
79 resampler->dir = 0;
80 return 1;
81 }
82 (*resampler->pickup)(resampler, resampler->pickup_data);
83 if (resampler->dir == 0) return 1;
84 ASSERT(resampler->dir == -1 || resampler->dir == 1);
85 }
86}
87
88
89
90/* Create mono destination resampler. */
91/* SUFFIX3 was set above. */
92#define VOLUME_PARAMETERS MONO_DEST_VOLUME_PARAMETERS
93#define VOLUME_VARIABLES MONO_DEST_VOLUME_VARIABLES
94#define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
95#define RETURN_VOLUME_VARIABLES RETURN_MONO_DEST_VOLUME_VARIABLES
96#define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
97#define PEEK_FIR MONO_DEST_PEEK_FIR
98#define MIX_FIR MONO_DEST_MIX_FIR
99#define MIX_ZEROS(op) *dst++ op 0
100#include "resamp3.inc"
101
102/* Create stereo destination resampler. */
103#define SUFFIX3 _2
104#define VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right
105#define VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm
106#define SET_VOLUME_VARIABLES { \
107 if ( volume_left ) { \
108 lvolr = (int)(volume_left->volume * 16777216.0); \
109 lvold = (int)(volume_left->delta * 16777216.0); \
110 lvolt = (int)(volume_left->target * 16777216.0); \
111 lvolm = (int)(volume_left->mix * 16777216.0); \
112 lvol = MULSCV( lvolr, lvolm ); \
113 if ( lvolr == lvolt ) volume_left = NULL; \
114 } else { \
115 lvol = 0; \
116 lvold = 0; \
117 lvolt = 0; \
118 lvolm = 0; \
119 } \
120 if ( volume_right ) { \
121 rvolr = (int)(volume_right->volume * 16777216.0); \
122 rvold = (int)(volume_right->delta * 16777216.0); \
123 rvolt = (int)(volume_right->target * 16777216.0); \
124 rvolm = (int)(volume_right->mix * 16777216.0); \
125 rvol = MULSCV( rvolr, rvolm ); \
126 if ( rvolr == rvolt ) volume_right = NULL; \
127 } else { \
128 rvol = 0; \
129 rvold = 0; \
130 rvolt = 0; \
131 rvolm = 0; \
132 } \
133}
134#define RETURN_VOLUME_VARIABLES { \
135 if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \
136 if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
137}
138#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
139#define PEEK_FIR STEREO_DEST_PEEK_FIR
140#define MIX_FIR STEREO_DEST_MIX_FIR
141#define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; }
142#include "resamp3.inc"
143
144
145
146#undef MONO_DEST_VOLUMES_ARE_ZERO
147#undef SET_MONO_DEST_VOLUME_VARIABLES
148#undef RETURN_MONO_DEST_VOLUME_VARIABLES
149#undef MONO_DEST_VOLUME_ZEROS
150#undef MONO_DEST_VOLUME_VARIABLES
151#undef MONO_DEST_VOLUME_PARAMETERS
152#undef MONO_DEST_PEEK_FIR
153#undef STEREO_DEST_PEEK_FIR
154#undef MONO_DEST_MIX_FIR
155#undef STEREO_DEST_MIX_FIR
156#undef ADVANCE_FIR
157#undef POKE_FIR
158#undef COPYSRC2
159#undef COPYSRC
160#undef DIVIDE_BY_SRC_CHANNELS
161#undef SRC_CHANNELS
162#undef SUFFIX2
dumb/src/helpers/resamp3.inc+0−258
@@ -1,258 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * resamp3.inc - Resampling helper template. / / \ \
12 * | < / \_
13 * By Bob and entheh. | \/ /\ /
14 * \_ / > /
15 * In order to find a good trade-off between | \ / /
16 * speed and accuracy in this code, some tests | ' /
17 * were carried out regarding the behaviour of \__/
18 * long long ints with gcc. The following code
19 * was tested:
20 *
21 * int a, b, c;
22 * c = ((long long)a * b) >> 16;
23 *
24 * DJGPP GCC Version 3.0.3 generated the following assembly language code for
25 * the multiplication and scaling, leaving the 32-bit result in EAX.
26 *
27 * movl -8(%ebp), %eax ; read one int into EAX
28 * imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
29 * shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
30 *
31 * Note that a 32*32->64 multiplication is performed, allowing for high
32 * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
33 * so it is a minor concern when four multiplications are being performed
34 * (the cubic resampler). On the Pentium MMX and earlier, it takes four or
35 * more cycles, so this method is unsuitable for use in the low-quality
36 * resamplers.
37 *
38 * Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
39 * defined in dumb.h. We may investigate later what code MSVC generates, but
40 * if it seems too slow then we suggest you use a good compiler.
41 *
42 * FIXME: these comments are somewhat out of date now.
43 */
44
45
46
47long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta)
48{
49 int dt, inv_dt;
50 int VOLUME_VARIABLES;
51 long done;
52 long todo;
53 LONG_LONG todo64;
54 int quality;
55
56 if (!resampler || resampler->dir == 0) return 0;
57 ASSERT(resampler->dir == -1 || resampler->dir == 1);
58
59 done = 0;
60 dt = (int)(delta * 65536.0 + 0.5);
61 if (dt == 0 || dt == (int)-0x80000000) return 0;
62 inv_dt = (int)(1.0 / delta * 65536.0 + 0.5);
63 SET_VOLUME_VARIABLES;
64
65 if (VOLUMES_ARE_ZERO) dst = NULL;
66
67 _dumb_init_cubic();
68
69 quality = resampler->quality;
70
71 while (done < dst_size) {
72 if (process_pickup(resampler)) {
73 RETURN_VOLUME_VARIABLES;
74 return done;
75 }
76
77 if ((resampler->dir ^ dt) < 0)
78 dt = -dt;
79
80 if (resampler->dir < 0)
81 todo64 = ((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt);
82 else
83 todo64 = ((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt);
84
85 if (todo64 < 0)
86 todo = 0;
87 else if (todo64 > dst_size - done)
88 todo = dst_size - done;
89 else
90 todo = (long) todo64;
91
92 done += todo;
93
94 {
95 SRCTYPE *src = resampler->src;
96 long pos = resampler->pos;
97 int subpos = resampler->subpos;
98 long diff = pos;
99 long overshot;
100 if (resampler->dir < 0) {
101 if (!dst) {
102 /* Silence or simulation */
103 LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
104 pos += (long)(new_subpos >> 16);
105 subpos = (long)new_subpos & 65535;
106 } else {
107 /* FIR resampling, backwards */
108 SRCTYPE *x;
109 if ( resampler->fir_resampler_ratio != delta ) {
110 resampler_set_rate( resampler->fir_resampler[0], delta );
111 resampler_set_rate( resampler->fir_resampler[1], delta );
112 resampler->fir_resampler_ratio = delta;
113 }
114 x = &src[pos*SRC_CHANNELS];
115 while ( todo ) {
116 while ( ( resampler_get_free_count( resampler->fir_resampler[0] ) ||
117 (!resampler_get_sample_count( resampler->fir_resampler[0] )
118#if SRC_CHANNELS == 2
119 && !resampler_get_sample_count( resampler->fir_resampler[1] )
120#endif
121 ) ) && pos >= resampler->start )
122 {
123 POKE_FIR(0);
124 pos--;
125 x -= SRC_CHANNELS;
126 }
127 if ( !resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
128 MIX_FIR;
129 ADVANCE_FIR;
130 --todo;
131 }
132 done -= todo;
133 }
134 diff = diff - pos;
135 overshot = resampler->start - pos - 1;
136 if (diff >= 3) {
137 COPYSRC2(resampler->X, 0, overshot < 3, src, pos+3);
138 COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
139 COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
140 } else if (diff >= 2) {
141 COPYSRC(resampler->X, 0, resampler->X, 2);
142 COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
143 COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
144 } else if (diff >= 1) {
145 COPYSRC(resampler->X, 0, resampler->X, 1);
146 COPYSRC(resampler->X, 1, resampler->X, 2);
147 COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
148 }
149 } else {
150 if (!dst) {
151 /* Silence or simulation */
152 LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
153 pos += (long)(new_subpos >> 16);
154 subpos = (long)new_subpos & 65535;
155 } else {
156 /* FIR resampling, forwards */
157 SRCTYPE *x;
158 if ( resampler->fir_resampler_ratio != delta ) {
159 resampler_set_rate( resampler->fir_resampler[0], delta );
160 resampler_set_rate( resampler->fir_resampler[1], delta );
161 resampler->fir_resampler_ratio = delta;
162 }
163 x = &src[pos*SRC_CHANNELS];
164 while ( todo ) {
165 while ( ( resampler_get_free_count( resampler->fir_resampler[0] ) ||
166 (!resampler_get_sample_count( resampler->fir_resampler[0] )
167#if SRC_CHANNELS == 2
168 && !resampler_get_sample_count( resampler->fir_resampler[1] )
169#endif
170 ) ) && pos < resampler->end )
171 {
172 POKE_FIR(0);
173 pos++;
174 x += SRC_CHANNELS;
175 }
176 if ( !resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
177 MIX_FIR;
178 ADVANCE_FIR;
179 --todo;
180 }
181 done -= todo;
182 }
183 diff = pos - diff;
184 overshot = pos - resampler->end;
185 if (diff >= 3) {
186 COPYSRC2(resampler->X, 0, overshot < 3, src, pos-3);
187 COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
188 COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
189 } else if (diff >= 2) {
190 COPYSRC(resampler->X, 0, resampler->X, 2);
191 COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
192 COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
193 } else if (diff >= 1) {
194 COPYSRC(resampler->X, 0, resampler->X, 1);
195 COPYSRC(resampler->X, 1, resampler->X, 2);
196 COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
197 }
198 }
199 resampler->pos = pos;
200 resampler->subpos = subpos;
201 }
202 }
203
204 RETURN_VOLUME_VARIABLES;
205 return done;
206}
207
208
209
210void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst)
211{
212 int VOLUME_VARIABLES;
213 SRCTYPE *src;
214 long pos;
215 int subpos;
216 int quality;
217 SRCTYPE *x;
218
219 if (!resampler || resampler->dir == 0) { MIX_ZEROS(=); return; }
220 ASSERT(resampler->dir == -1 || resampler->dir == 1);
221
222 if (process_pickup(resampler)) { MIX_ZEROS(=); return; }
223
224 SET_VOLUME_VARIABLES;
225
226 if (VOLUMES_ARE_ZERO) { MIX_ZEROS(=); return; }
227
228 _dumb_init_cubic();
229
230 quality = resampler->quality;
231
232 src = resampler->src;
233 pos = resampler->pos;
234 subpos = resampler->subpos;
235 x = resampler->X;
236
237 if (resampler->dir < 0) {
238 HEAVYASSERT(pos >= resampler->start);
239 /* FIR resampling, backwards */
240 PEEK_FIR;
241 } else {
242 HEAVYASSERT(pos < resampler->end);
243 /* FIR resampling, forwards */
244 PEEK_FIR;
245 }
246}
247
248
249
250#undef MIX_ZEROS
251#undef MIX_FIR
252#undef PEEK_FIR
253#undef VOLUMES_ARE_ZERO
254#undef SET_VOLUME_VARIABLES
255#undef RETURN_VOLUME_VARIABLES
256#undef VOLUME_VARIABLES
257#undef VOLUME_PARAMETERS
258#undef SUFFIX3
dumb/src/helpers/resample.c+0−330
@@ -1,330 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * resample.c - Resampling helpers. / / \ \
12 * | < / \_
13 * By Bob and entheh. | \/ /\ /
14 * \_ / > /
15 * In order to find a good trade-off between | \ / /
16 * speed and accuracy in this code, some tests | ' /
17 * were carried out regarding the behaviour of \__/
18 * long long ints with gcc. The following code
19 * was tested:
20 *
21 * int a, b, c;
22 * c = ((long long)a * b) >> 16;
23 *
24 * DJGPP GCC Version 3.0.3 generated the following assembly language code for
25 * the multiplication and scaling, leaving the 32-bit result in EAX.
26 *
27 * movl -8(%ebp), %eax ; read one int into EAX
28 * imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
29 * shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
30 *
31 * Note that a 32*32->64 multiplication is performed, allowing for high
32 * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
33 * so it is a minor concern when four multiplications are being performed
34 * (the cubic resampler). On the Pentium MMX and earlier, it takes four or
35 * more cycles, so this method is unsuitable for use in the low-quality
36 * resamplers.
37 *
38 * Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
39 * defined in dumb.h. We may investigate later what code MSVC generates, but
40 * if it seems too slow then we suggest you use a good compiler.
41 *
42 * FIXME: these comments are somewhat out of date now.
43 */
44
45#include <math.h>
46#include "dumb.h"
47
48#include "internal/resampler.h"
49
50
51
52/* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is
53 * called when it should be. There will be a considerable performance hit,
54 * since at least one condition has to be tested for every sample generated.
55 */
56#ifdef HEAVYDEBUG
57#define HEAVYASSERT(cond) ASSERT(cond)
58#else
59#define HEAVYASSERT(cond)
60#endif
61
62
63
64/* Make MSVC shut the hell up about if ( upd ) UPDATE_VOLUME() conditions being constant */
65#ifdef _MSC_VER
66#pragma warning(disable:4127 4701)
67#endif
68
69
70
71/* A global variable for controlling resampling quality wherever a local
72 * specification doesn't override it. The following values are valid:
73 *
74 * 0 - DUMB_RQ_ALIASING - fastest
75 * 1 - DUMB_RQ_BLEP - nicer than aliasing, but slower
76 * 2 - DUMB_RQ_LINEAR
77 * 3 - DUMB_RQ_BLAM - band-limited linear interpolation, nice but slower
78 * 4 - DUMB_RQ_CUBIC
79 * 5 - DUMB_RQ_FIR - nicest
80 *
81 * Values outside the range 0-4 will behave the same as the nearest
82 * value within the range.
83 */
84int dumb_resampling_quality = DUMB_RQ_CUBIC;
85
86
87
88//#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16))
89//#define MULSC(a, b) ((a) * ((b) >> 2) >> 14)
90#define MULSCV(a, b) ((int)((LONG_LONG)(a) * (b) >> 32))
91#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
92#define MULSC16(a, b) ((int)((LONG_LONG)((a) << 12) * ((b) << 12) >> 32))
93
94
95
96/* Executes the content 'iterator' times.
97 * Clobbers the 'iterator' variable.
98 * The loop is unrolled by four.
99 */
100#if 0
101#define LOOP4(iterator, CONTENT) \
102{ \
103 if ((iterator) & 2) { \
104 CONTENT; \
105 CONTENT; \
106 } \
107 if ((iterator) & 1) { \
108 CONTENT; \
109 } \
110 (iterator) >>= 2; \
111 while (iterator) { \
112 CONTENT; \
113 CONTENT; \
114 CONTENT; \
115 CONTENT; \
116 (iterator)--; \
117 } \
118}
119#else
120#define LOOP4(iterator, CONTENT) \
121{ \
122 while ( (iterator)-- ) \
123 { \
124 CONTENT; \
125 } \
126}
127#endif
128
129#define PASTERAW(a, b) a ## b /* This does not expand macros in b ... */
130#define PASTE(a, b) PASTERAW(a, b) /* ... but b is expanded during this substitution. */
131
132#define X PASTE(x.x, SRCBITS)
133
134
135
136void _dumb_init_cubic(void)
137{
138 static int done = 0;
139 if (done) return;
140
141 resampler_init();
142
143 done = 1;
144}
145
146
147
148/* Create resamplers for 24-in-32-bit source samples. */
149
150/* #define SUFFIX
151 * MSVC warns if we try to paste a null SUFFIX, so instead we define
152 * special macros for the function names that don't bother doing the
153 * corresponding paste. The more generic definitions are further down.
154 */
155#define process_pickup PASTE(process_pickup, SUFFIX2)
156#define dumb_resample PASTE(PASTE(dumb_resample, SUFFIX2), SUFFIX3)
157#define dumb_resample_get_current_sample PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX2), SUFFIX3)
158
159#define SRCTYPE sample_t
160#define SRCBITS 24
161#define FIR(x) (x >> 8)
162#include "resample.inc"
163
164/* Undefine the simplified macros. */
165#undef dumb_resample_get_current_sample
166#undef dumb_resample
167#undef process_pickup
168
169
170/* Now define the proper ones that use SUFFIX. */
171#define dumb_reset_resampler PASTE(dumb_reset_resampler, SUFFIX)
172#define dumb_start_resampler PASTE(dumb_start_resampler, SUFFIX)
173#define process_pickup PASTE(PASTE(process_pickup, SUFFIX), SUFFIX2)
174#define dumb_resample PASTE(PASTE(PASTE(dumb_resample, SUFFIX), SUFFIX2), SUFFIX3)
175#define dumb_resample_get_current_sample PASTE(PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX), SUFFIX2), SUFFIX3)
176#define dumb_end_resampler PASTE(dumb_end_resampler, SUFFIX)
177
178/* Create resamplers for 16-bit source samples. */
179#define SUFFIX _16
180#define SRCTYPE short
181#define SRCBITS 16
182#define FIR(x) (x)
183#include "resample.inc"
184
185/* Create resamplers for 8-bit source samples. */
186#define SUFFIX _8
187#define SRCTYPE signed char
188#define SRCBITS 8
189#define FIR(x) (x << 8)
190#include "resample.inc"
191
192
193#undef dumb_reset_resampler
194#undef dumb_start_resampler
195#undef process_pickup
196#undef dumb_resample
197#undef dumb_resample_get_current_sample
198#undef dumb_end_resampler
199
200
201
202void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, long pos, long start, long end, int quality)
203{
204 if (n == 8)
205 dumb_reset_resampler_8(resampler, src, src_channels, pos, start, end, quality);
206 else if (n == 16)
207 dumb_reset_resampler_16(resampler, src, src_channels, pos, start, end, quality);
208 else
209 dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
210}
211
212
213
214DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, long pos, long start, long end, int quality)
215{
216 if (n == 8)
217 return dumb_start_resampler_8(src, src_channels, pos, start, end, quality);
218 else if (n == 16)
219 return dumb_start_resampler_16(src, src_channels, pos, start, end, quality);
220 else
221 return dumb_start_resampler(src, src_channels, pos, start, end, quality);
222}
223
224
225
226long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta)
227{
228 if (n == 8)
229 return dumb_resample_8_1_1(resampler, dst, dst_size, volume, delta);
230 else if (n == 16)
231 return dumb_resample_16_1_1(resampler, dst, dst_size, volume, delta);
232 else
233 return dumb_resample_1_1(resampler, dst, dst_size, volume, delta);
234}
235
236
237
238long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta)
239{
240 if (n == 8)
241 return dumb_resample_8_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
242 else if (n == 16)
243 return dumb_resample_16_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
244 else
245 return dumb_resample_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
246}
247
248
249
250long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta)
251{
252 if (n == 8)
253 return dumb_resample_8_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
254 else if (n == 16)
255 return dumb_resample_16_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
256 else
257 return dumb_resample_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
258}
259
260
261
262long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta)
263{
264 if (n == 8)
265 return dumb_resample_8_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
266 else if (n == 16)
267 return dumb_resample_16_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
268 else
269 return dumb_resample_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
270}
271
272
273
274void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst)
275{
276 if (n == 8)
277 dumb_resample_get_current_sample_8_1_1(resampler, volume, dst);
278 else if (n == 16)
279 dumb_resample_get_current_sample_16_1_1(resampler, volume, dst);
280 else
281 dumb_resample_get_current_sample_1_1(resampler, volume, dst);
282}
283
284
285
286void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
287{
288 if (n == 8)
289 dumb_resample_get_current_sample_8_1_2(resampler, volume_left, volume_right, dst);
290 else if (n == 16)
291 dumb_resample_get_current_sample_16_1_2(resampler, volume_left, volume_right, dst);
292 else
293 dumb_resample_get_current_sample_1_2(resampler, volume_left, volume_right, dst);
294}
295
296
297
298void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
299{
300 if (n == 8)
301 dumb_resample_get_current_sample_8_2_1(resampler, volume_left, volume_right, dst);
302 else if (n == 16)
303 dumb_resample_get_current_sample_16_2_1(resampler, volume_left, volume_right, dst);
304 else
305 dumb_resample_get_current_sample_2_1(resampler, volume_left, volume_right, dst);
306}
307
308
309
310void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
311{
312 if (n == 8)
313 dumb_resample_get_current_sample_8_2_2(resampler, volume_left, volume_right, dst);
314 else if (n == 16)
315 dumb_resample_get_current_sample_16_2_2(resampler, volume_left, volume_right, dst);
316 else
317 dumb_resample_get_current_sample_2_2(resampler, volume_left, volume_right, dst);
318}
319
320
321
322void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler)
323{
324 if (n == 8)
325 dumb_end_resampler_8(resampler);
326 else if (n == 16)
327 dumb_end_resampler_16(resampler);
328 else
329 dumb_end_resampler(resampler);
330}
dumb/src/helpers/resample.inc+0−256
@@ -1,256 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * resample.inc - Resampling helper template. / / \ \
12 * | < / \_
13 * By Bob and entheh. | \/ /\ /
14 * \_ / > /
15 * In order to find a good trade-off between | \ / /
16 * speed and accuracy in this code, some tests | ' /
17 * were carried out regarding the behaviour of \__/
18 * long long ints with gcc. The following code
19 * was tested:
20 *
21 * int a, b, c;
22 * c = ((long long)a * b) >> 16;
23 *
24 * DJGPP GCC Version 3.0.3 generated the following assembly language code for
25 * the multiplication and scaling, leaving the 32-bit result in EAX.
26 *
27 * movl -8(%ebp), %eax ; read one int into EAX
28 * imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
29 * shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
30 *
31 * Note that a 32*32->64 multiplication is performed, allowing for high
32 * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
33 * so it is a minor concern when four multiplications are being performed
34 * (the cubic resampler). On the Pentium MMX and earlier, it takes four or
35 * more cycles, so this method is unsuitable for use in the low-quality
36 * resamplers.
37 *
38 * Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
39 * defined in dumb.h. We may investigate later what code MSVC generates, but
40 * if it seems too slow then we suggest you use a good compiler.
41 *
42 * FIXME: these comments are somewhat out of date now.
43 */
44
45
46
47void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_channels, long pos, long start, long end, int quality)
48{
49 int i;
50 resampler->src = src;
51 resampler->pos = pos;
52 resampler->subpos = 0;
53 resampler->start = start;
54 resampler->end = end;
55 resampler->dir = 1;
56 resampler->pickup = NULL;
57 resampler->pickup_data = NULL;
58 if (quality < 0)
59 {
60 resampler->quality = 0;
61 }
62 else if (quality > DUMB_RQ_N_LEVELS - 1)
63 {
64 resampler->quality = DUMB_RQ_N_LEVELS - 1;
65 }
66 else
67 {
68 resampler->quality = quality;
69 }
70 for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
71 resampler->overshot = -1;
72 resampler->fir_resampler_ratio = 0;
73 resampler_clear(resampler->fir_resampler[0]);
74 resampler_clear(resampler->fir_resampler[1]);
75 resampler_set_quality(resampler->fir_resampler[0], resampler->quality);
76 resampler_set_quality(resampler->fir_resampler[1], resampler->quality);
77}
78
79
80
81DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, long start, long end, int quality)
82{
83 DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
84 if (!resampler) return NULL;
85 dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
86 return resampler;
87}
88
89
90
91#define UPDATE_VOLUME( pvol, vol ) { \
92 if (pvol) { \
93 vol##r += vol##d; \
94 if ((vol##d < 0 && vol##r <= vol##t) || \
95 (vol##d > 0 && vol##r >= vol##t)) { \
96 pvol->volume = pvol->target; \
97 if ( pvol->declick_stage == 0 || \
98 pvol->declick_stage >= 3) \
99 pvol->declick_stage++; \
100 pvol = NULL; \
101 vol = MULSCV( vol##t, vol##m ); \
102 } else { \
103 vol = MULSCV( vol##r, vol##m ); \
104 } \
105 } \
106}
107
108
109
110/* Create mono source resampler. */
111#define SUFFIX2 _1
112#define SRC_CHANNELS 1
113#define DIVIDE_BY_SRC_CHANNELS(x) (x)
114#define COPYSRC(dstarray, dstindex, srcarray, srcindex) (dstarray)[dstindex] = (srcarray)[srcindex]
115#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) (dstarray)[dstindex] = condition ? (srcarray)[srcindex] : 0
116#define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume
117#define MONO_DEST_VOLUME_VARIABLES vol, volr, vold, volt, volm
118#define MONO_DEST_VOLUME_ZEROS 0
119#define SET_MONO_DEST_VOLUME_VARIABLES { \
120 if ( volume ) { \
121 volr = (int)(volume->volume * 16777216.0); \
122 vold = (int)(volume->delta * 16777216.0); \
123 volt = (int)(volume->target * 16777216.0); \
124 volm = (int)(volume->mix * 16777216.0); \
125 vol = MULSCV( volr, volm ); \
126 if ( volr == volt ) volume = NULL; \
127 } else { \
128 vol = 0; \
129 vold = 0; \
130 volt = 0; \
131 volm = 0; \
132 } \
133}
134#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f
135#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
136#define POKE_FIR(offset) { \
137 resampler_write_sample( resampler->fir_resampler[0], FIR(x[offset]) ); \
138}
139#define MONO_DEST_PEEK_FIR *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol )
140#define MONO_DEST_MIX_FIR { \
141 *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
142 UPDATE_VOLUME( volume, vol ); \
143}
144#define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0], 1 )
145#define STEREO_DEST_PEEK_FIR { \
146 int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
147 *dst++ = MULSC( sample, lvol ); \
148 *dst++ = MULSC( sample, rvol ); \
149}
150#define STEREO_DEST_MIX_FIR { \
151 int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
152 *dst++ += MULSC( sample, lvol ); \
153 *dst++ += MULSC( sample, rvol ); \
154 UPDATE_VOLUME( volume_left, lvol ); \
155 UPDATE_VOLUME( volume_right, rvol ); \
156}
157#include "resamp2.inc"
158
159/* Create stereo source resampler. */
160#define SUFFIX2 _2
161#define SRC_CHANNELS 2
162#define DIVIDE_BY_SRC_CHANNELS(x) ((x) >> 1)
163#define COPYSRC(dstarray, dstindex, srcarray, srcindex) { \
164 (dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
165 (dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \
166}
167#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) { \
168 if (condition) { \
169 (dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
170 (dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \
171 } else { \
172 (dstarray)[(dstindex)*2] = 0; \
173 (dstarray)[(dstindex)*2+1] = 0; \
174 } \
175}
176
177#define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right
178#define MONO_DEST_VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm
179#define MONO_DEST_VOLUME_ZEROS 0, 0
180#define SET_MONO_DEST_VOLUME_VARIABLES { \
181 if ( volume_left ) { \
182 lvolr = (int)(volume_left->volume * 16777216.0); \
183 lvold = (int)(volume_left->delta * 16777216.0); \
184 lvolt = (int)(volume_left->target * 16777216.0); \
185 lvolm = (int)(volume_left->mix * 16777216.0); \
186 lvol = MULSCV( lvolr, lvolm ); \
187 if ( lvolr == lvolt ) volume_left = NULL; \
188 } else { \
189 lvol = 0; \
190 lvold = 0; \
191 lvolt = 0; \
192 lvolm = 0; \
193 } \
194 if ( volume_right ) { \
195 rvolr = (int)(volume_right->volume * 16777216.0); \
196 rvold = (int)(volume_right->delta * 16777216.0); \
197 rvolt = (int)(volume_right->target * 16777216.0); \
198 rvolm = (int)(volume_right->mix * 16777216.0); \
199 rvol = MULSCV( rvolr, rvolm ); \
200 if ( rvolr == rvolt ) volume_right = NULL; \
201 } else { \
202 rvol = 0; \
203 rvold = 0; \
204 rvolt = 0; \
205 rvolm = 0; \
206 } \
207}
208#define RETURN_MONO_DEST_VOLUME_VARIABLES { \
209 if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \
210 if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
211}
212#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
213#define POKE_FIR(offset) { \
214 resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
215 resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
216}
217#define MONO_DEST_PEEK_FIR { \
218 *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
219 MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
220}
221#define MONO_DEST_MIX_FIR { \
222 *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
223 MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
224 UPDATE_VOLUME( volume_left, lvol ); \
225 UPDATE_VOLUME( volume_right, rvol ); \
226}
227#define ADVANCE_FIR { \
228 resampler_remove_sample( resampler->fir_resampler[0], 1 ); \
229 resampler_remove_sample( resampler->fir_resampler[1], 1 ); \
230}
231#define STEREO_DEST_PEEK_FIR { \
232 *dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
233 *dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
234}
235#define STEREO_DEST_MIX_FIR { \
236 *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
237 *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
238 UPDATE_VOLUME( volume_left, lvol ); \
239 UPDATE_VOLUME( volume_right, rvol ); \
240}
241#include "resamp2.inc"
242
243
244
245void dumb_end_resampler(DUMB_RESAMPLER *resampler)
246{
247 if (resampler)
248 free(resampler);
249}
250
251
252
253#undef FIR
254#undef SRCBITS
255#undef SRCTYPE
256#undef SUFFIX
dumb/src/helpers/riff.c+0−85
@@ -1,85 +0,0 @@
1#include "dumb.h"
2#include "internal/riff.h"
3
4#include <stdlib.h>
5
6struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper )
7{
8 unsigned stream_size;
9 struct riff * stream;
10
11 if ( size < 8 ) return 0;
12
13 if ( dumbfile_seek(f, offset, DFS_SEEK_SET) ) return 0;
14 if ( dumbfile_mgetl(f) != DUMB_ID('R','I','F','F') ) return 0;
15
16 stream_size = dumbfile_igetl(f);
17 if ( stream_size + 8 > size ) return 0;
18 if ( stream_size < 4 ) return 0;
19
20 stream = (struct riff *) malloc( sizeof( struct riff ) );
21 if ( ! stream ) return 0;
22
23 stream->type = dumbfile_mgetl(f);
24 stream->chunk_count = 0;
25 stream->chunks = 0;
26
27 stream_size -= 4;
28
29 while ( stream_size && !dumbfile_error(f) )
30 {
31 struct riff_chunk * chunk;
32 if ( stream_size < 8 ) break;
33 stream->chunks = ( struct riff_chunk * ) realloc( stream->chunks, ( stream->chunk_count + 1 ) * sizeof( struct riff_chunk ) );
34 if ( ! stream->chunks ) break;
35 chunk = stream->chunks + stream->chunk_count;
36 chunk->type = dumbfile_mgetl(f);
37 chunk->size = dumbfile_igetl(f);
38 chunk->offset = dumbfile_pos(f);
39 stream_size -= 8;
40 if ( stream_size < chunk->size ) break;
41 if ( chunk->type == DUMB_ID('R','I','F','F') )
42 {
43 chunk->nested = riff_parse( f, chunk->offset - 8, chunk->size + 8, proper );
44 if ( ! chunk->nested ) break;
45 }
46 else
47 {
48 chunk->nested = 0;
49 }
50 dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET);
51 stream_size -= chunk->size;
52 if ( proper && ( chunk->size & 1 ) )
53 {
54 dumbfile_skip(f, 1);
55 -- stream_size;
56 }
57 ++stream->chunk_count;
58 }
59
60 if ( stream_size )
61 {
62 riff_free( stream );
63 stream = 0;
64 }
65
66 return stream;
67}
68
69void riff_free( struct riff * stream )
70{
71 if ( stream )
72 {
73 if ( stream->chunks )
74 {
75 unsigned i;
76 for ( i = 0; i < stream->chunk_count; ++i )
77 {
78 struct riff_chunk * chunk = stream->chunks + i;
79 if ( chunk->nested ) riff_free( chunk->nested );
80 }
81 free( stream->chunks );
82 }
83 free( stream );
84 }
85}
dumb/src/helpers/stdfile.c+0−146
@@ -1,146 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * stdfile.c - stdio file input module. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdio.h>
21
22#include "dumb.h"
23
24
25
26typedef struct dumb_stdfile
27{
28 FILE * file;
29 long size;
30} dumb_stdfile;
31
32
33
34static void *dumb_stdfile_open(const char *filename)
35{
36 dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
37 if ( !file ) return 0;
38 file->file = fopen(filename, "rb");
39 fseek(file->file, 0, SEEK_END);
40 file->size = ftell(file->file);
41 fseek(file->file, 0, SEEK_SET);
42 return file;
43}
44
45
46
47static int dumb_stdfile_skip(void *f, long n)
48{
49 dumb_stdfile * file = ( dumb_stdfile * ) f;
50 return fseek(file->file, n, SEEK_CUR);
51}
52
53
54
55static int dumb_stdfile_getc(void *f)
56{
57 dumb_stdfile * file = ( dumb_stdfile * ) f;
58 return fgetc(file->file);
59}
60
61
62
63static long dumb_stdfile_getnc(char *ptr, long n, void *f)
64{
65 dumb_stdfile * file = ( dumb_stdfile * ) f;
66 return fread(ptr, 1, n, file->file);
67}
68
69
70
71static void dumb_stdfile_close(void *f)
72{
73 dumb_stdfile * file = ( dumb_stdfile * ) f;
74 fclose(file->file);
75 free(f);
76}
77
78
79
80static void dumb_stdfile_noclose(void *f)
81{
82 free(f);
83}
84
85
86
87static int dumb_stdfile_seek(void *f, long n)
88{
89 dumb_stdfile * file = ( dumb_stdfile * ) f;
90 return fseek(file->file, n, SEEK_SET);
91}
92
93
94
95static long dumb_stdfile_get_size(void *f)
96{
97 dumb_stdfile * file = ( dumb_stdfile * ) f;
98 return file->size;
99}
100
101
102
103static const DUMBFILE_SYSTEM stdfile_dfs = {
104 &dumb_stdfile_open,
105 &dumb_stdfile_skip,
106 &dumb_stdfile_getc,
107 &dumb_stdfile_getnc,
108 &dumb_stdfile_close,
109 &dumb_stdfile_seek,
110 &dumb_stdfile_get_size
111};
112
113
114
115void dumb_register_stdfiles(void)
116{
117 register_dumbfile_system(&stdfile_dfs);
118}
119
120
121
122static const DUMBFILE_SYSTEM stdfile_dfs_leave_open = {
123 NULL,
124 &dumb_stdfile_skip,
125 &dumb_stdfile_getc,
126 &dumb_stdfile_getnc,
127 &dumb_stdfile_noclose,
128 &dumb_stdfile_seek,
129 &dumb_stdfile_get_size
130};
131
132
133
134DUMBFILE *dumbfile_open_stdfile(FILE *p)
135{
136 dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
137 DUMBFILE *d;
138 if ( !file ) return 0;
139 file->file = p;
140 fseek(p, 0, SEEK_END);
141 file->size = ftell(p);
142 fseek(p, 0, SEEK_SET);
143 d = dumbfile_open_ex(file, &stdfile_dfs_leave_open);
144
145 return d;
146}
dumb/src/helpers/tarray.c+0−175
@@ -1,175 +0,0 @@
1#include "internal/tarray.h"
2
3#include <string.h>
4
5 /*
6 Structures which contain the play times of each pattern and row combination in the song,
7 not guaranteed to be valid for the whole song until the loop status is no longer zero.
8 The initial count and restart count will both be zero on song start, then both will be
9 incremented until the song loops. Restart count will be reset to zero on loop for all
10 rows which have a time equal to or greater than the loop start point, so time keeping
11 functions will know which timestamp the song is currently located at.
12
13 Timestamp lists are guaranteed to be allocated in blocks of 16 timestamps at a time.
14 */
15
16 /*
17 We don't need full timekeeping because the player loop only wants the first play time
18 of the loop start order/row. We also don't really want full timekeeping because it
19 involves a lot of memory allocations, which is also slow.
20 */
21
22#undef FULL_TIMEKEEPING
23
24typedef struct DUMB_IT_ROW_TIME
25{
26 unsigned int count, restart_count;
27#ifndef FULL_TIMEKEEPING
28 LONG_LONG first_time;
29#else
30 LONG_LONG * times;
31#endif
32} DUMB_IT_ROW_TIME;
33
34void * timekeeping_array_create(size_t size)
35{
36 size_t * _size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * size );
37 if ( _size ) {
38 *_size = size;
39 }
40 return _size;
41}
42
43void timekeeping_array_destroy(void * array)
44{
45#ifdef FULL_TIMEKEEPING
46 size_t i;
47 size_t * size = (size_t *) array;
48 DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
49
50 for (i = 0; i < *size; i++) {
51 if (s[i].times) free(s[i].times);
52 }
53#endif
54
55 free(array);
56}
57
58void * timekeeping_array_dup(void * array)
59{
60 size_t i;
61 size_t * size = (size_t *) array;
62 DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
63 size_t * new_size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * *size );
64 if ( new_size ) {
65 DUMB_IT_ROW_TIME * new_s = (DUMB_IT_ROW_TIME *)(new_size + 1);
66
67 *new_size = *size;
68
69 for (i = 0; i < *size; i++) {
70 new_s[i].count = s[i].count;
71 new_s[i].restart_count = s[i].restart_count;
72
73#ifndef FULL_TIMEKEEPING
74 new_s[i].first_time = s[i].first_time;
75#else
76 if ( s[i].times ) {
77 size_t time_count = ( s[i].count + 15 ) & ~15;
78 new_s[i].times = (LONG_LONG *) malloc( sizeof(LONG_LONG) * time_count );
79 if ( new_s[i].times == (void *)0 ) {
80 timekeeping_array_destroy( new_size );
81 return (void *) 0;
82 }
83 memcpy( new_s[i].times, s[i].times, sizeof(LONG_LONG) * s[i].count );
84 }
85#endif
86 }
87 }
88
89 return new_size;
90}
91
92void timekeeping_array_reset(void * array, size_t loop_start)
93{
94 size_t i;
95 size_t * size = (size_t *) array;
96 DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
97
98 DUMB_IT_ROW_TIME * s_loop_start = s + loop_start;
99 LONG_LONG loop_start_time;
100
101 if ( loop_start >= *size || s_loop_start->count < 1 ) return;
102
103#ifndef FULL_TIMEKEEPING
104 loop_start_time = s_loop_start->first_time;
105#else
106 loop_start_time = s_loop_start->times[0];
107#endif
108
109 for ( i = 0; i < *size; i++ ) {
110#ifndef FULL_TIMEKEEPING
111 if ( s[i].count && s[i].first_time >= loop_start_time ) {
112#else
113 if ( s[i].count && s[i].times[0] >= loop_start_time ) {
114#endif
115 s[i].restart_count = 0;
116 }
117 }
118}
119
120void timekeeping_array_push(void * array, size_t index, LONG_LONG time)
121{
122#ifdef FULL_TIMEKEEPING
123 size_t i;
124 size_t time_count;
125#endif
126 size_t * size = (size_t *) array;
127 DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
128
129 if (index >= *size) return;
130
131#ifndef FULL_TIMEKEEPING
132 if ( !s[index].count++ )
133 s[index].first_time = time;
134#else
135 time_count = ( s[index].count + 16 ) & ~15;
136
137 s[index].times = (LONG_LONG *) realloc( s[index].times, sizeof(LONG_LONG) * time_count );
138
139 s[index].times[s[index].count++] = time;
140#endif
141}
142
143void timekeeping_array_bump(void * array, size_t index)
144{
145 size_t * size = (size_t *) array;
146 DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
147
148 if (index >= *size) return;
149
150 s[index].restart_count++;
151}
152
153unsigned int timekeeping_array_get_count(void * array, size_t index)
154{
155 size_t * size = (size_t *) array;
156 DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
157
158 if (index >= *size) return 0;
159
160 return s[index].count;
161}
162
163LONG_LONG timekeeping_array_get_item(void * array, size_t index)
164{
165 size_t * size = (size_t *) array;
166 DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
167
168 if (index >= *size || s[index].restart_count >= s[index].count) return 0;
169
170#ifndef FULL_TIMEKEEPING
171 return s[index].first_time;
172#else
173 return s[index].times[s[index].restart_count];
174#endif
175}
dumb/src/it/itmisc.c+0−249
@@ -1,249 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itmisc.c - Miscellaneous functions relating / / \ \
12 * to module files. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include "dumb.h"
21#include "internal/it.h"
22
23
24int dumb_it_default_panning_separation = 25;
25
26
27DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh)
28{
29 return duh_get_raw_sigdata(duh, -1, SIGTYPE_IT);
30}
31
32
33
34const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd)
35{
36 return sd ? sd->song_message : NULL;
37}
38
39
40
41int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd)
42{
43 return sd ? sd->n_orders : 0;
44}
45
46
47
48int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd)
49{
50 return sd ? sd->n_samples : 0;
51}
52
53
54
55int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd)
56{
57 return sd ? sd->n_instruments : 0;
58}
59
60
61
62const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i)
63{
64 ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
65 return sd->sample[i].name;
66}
67
68
69
70const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i)
71{
72 ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
73 return sd->sample[i].filename;
74}
75
76
77
78const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i)
79{
80 ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
81 return sd->instrument[i].name;
82}
83
84
85
86const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd, int i)
87{
88 ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
89 return sd->instrument[i].filename;
90}
91
92
93
94int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd)
95{
96 return sd ? sd->global_volume : 0;
97}
98
99
100
101void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv)
102{
103 if (sd) sd->global_volume = gv;
104}
105
106
107
108int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd)
109{
110 return sd ? sd->mixing_volume : 0;
111}
112
113
114
115void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv)
116{
117 if (sd) sd->mixing_volume = mv;
118}
119
120
121
122int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd)
123{
124 return sd ? sd->speed : 0;
125}
126
127
128
129void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed)
130{
131 if (sd) sd->speed = speed;
132}
133
134
135
136int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd)
137{
138 return sd ? sd->tempo : 0;
139}
140
141
142
143void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo)
144{
145 if (sd) sd->tempo = tempo;
146}
147
148
149
150int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel)
151{
152 ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
153 return sd ? sd->channel_volume[channel] : 0;
154}
155
156void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume)
157{
158 ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
159 if (sd) sd->channel_volume[channel] = volume;
160}
161
162
163
164int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr)
165{
166 return sr ? sr->order : -1;
167}
168
169
170
171int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr)
172{
173 return sr ? sr->row : -1;
174}
175
176
177
178int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr)
179{
180 return sr ? sr->globalvolume : 0;
181}
182
183
184
185void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv)
186{
187 if (sr) sr->globalvolume = gv;
188}
189
190
191
192int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr)
193{
194 return sr ? sr->tempo : 0;
195}
196
197
198
199void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo)
200{
201 if (sr) sr->tempo = tempo;
202}
203
204
205
206int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr)
207{
208 return sr ? sr->speed : 0;
209}
210
211
212
213void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed)
214{
215 if (sr) sr->speed = speed;
216}
217
218
219
220int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel)
221{
222 return sr ? sr->channel[channel].channelvolume : 0;
223}
224
225
226
227void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume)
228{
229 if (sr) sr->channel[channel].channelvolume = volume;
230}
231
232
233
234void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted)
235{
236 if (sr) {
237 if (muted)
238 sr->channel[channel].flags |= IT_CHANNEL_MUTED;
239 else
240 sr->channel[channel].flags &= ~IT_CHANNEL_MUTED;
241 }
242}
243
244
245
246int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel)
247{
248 return sr ? (sr->channel[channel].flags & IT_CHANNEL_MUTED) != 0 : 0;
249}
dumb/src/it/itread.c+0−1416
@@ -1,1416 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itread.c - Code to read an Impulse Tracker / / \ \
12 * module from an open file. | < / \_
13 * | \/ /\ /
14 * Based on the loader from an IT player by Bob. \_ / > /
15 * Adapted for DUMB by entheh. | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>//might not be necessary later; required for memset
22
23#include "dumb.h"
24#include "internal/it.h"
25
26#ifndef min
27#define min(a, b) (((a) < (b)) ? (a) : (b))
28#endif
29
30
31#define INVESTIGATE_OLD_INSTRUMENTS
32
33
34
35typedef unsigned char byte;
36typedef unsigned short word;
37typedef unsigned long dword;
38
39typedef struct readblock_crap readblock_crap;
40
41struct readblock_crap {
42 unsigned char *sourcebuf;
43 unsigned char *sourcepos;
44 unsigned char *sourceend;
45 int rembits;
46};
47
48
49static int readblock(DUMBFILE *f, readblock_crap * crap)
50{
51 long size;
52 int c;
53
54 size = dumbfile_igetw(f);
55 if (size < 0)
56 return (int)size;
57
58 crap->sourcebuf = malloc(size);
59 if (!crap->sourcebuf)
60 return -1;
61
62 c = (int)dumbfile_getnc((char *)crap->sourcebuf, size, f);
63 if (c < size) {
64 free(crap->sourcebuf);
65 crap->sourcebuf = NULL;
66 return -1;
67 }
68
69 crap->sourcepos = crap->sourcebuf;
70 crap->sourceend = crap->sourcebuf + size;
71 crap->rembits = 8;
72 return 0;
73}
74
75
76
77static void freeblock(readblock_crap * crap)
78{
79 free(crap->sourcebuf);
80 crap->sourcebuf = NULL;
81}
82
83
84
85static int readbits(int bitwidth, readblock_crap * crap)
86{
87 int val = 0;
88 int b = 0;
89
90 if (crap->sourcepos >= crap->sourceend) return val;
91
92 while (bitwidth > crap->rembits) {
93 val |= *crap->sourcepos++ << b;
94 if (crap->sourcepos >= crap->sourceend) return val;
95 b += crap->rembits;
96 bitwidth -= crap->rembits;
97 crap->rembits = 8;
98 }
99
100 val |= (*crap->sourcepos & ((1 << bitwidth) - 1)) << b;
101 *crap->sourcepos >>= bitwidth;
102 crap->rembits -= bitwidth;
103
104 return val;
105}
106
107
108
109/** WARNING - do we even need to pass `right`? */
110/** WARNING - why bother memsetting at all? The whole array is written... */
111// if we do memset, dumb_silence() would be neater...
112static int decompress8(DUMBFILE *f, signed char *data, int len, int it215, int stereo)
113{
114 int blocklen, blockpos;
115 byte bitwidth;
116 word val;
117 signed char d1, d2;
118 readblock_crap crap;
119
120 memset(&crap, 0, sizeof(crap));
121
122 for (blocklen = 0, blockpos = 0; blocklen < len; blocklen++, blockpos += 1 + stereo)
123 data[ blockpos ] = 0;
124
125 while (len > 0) {
126 //Read a block of compressed data:
127 if (readblock(f, &crap))
128 return -1;
129 //Set up a few variables
130 blocklen = (len < 0x8000) ? len : 0x8000; //Max block length is 0x8000 bytes
131 blockpos = 0;
132 bitwidth = 9;
133 d1 = d2 = 0;
134 //Start the decompression:
135 while (blockpos < blocklen) {
136 //Read a value:
137 val = (word)readbits(bitwidth, &crap);
138 //Check for bit width change:
139
140 if (bitwidth < 7) { //Method 1:
141 if (val == (1 << (bitwidth - 1))) {
142 val = (word)readbits(3, &crap) + 1;
143 bitwidth = (val < bitwidth) ? val : val + 1;
144 continue;
145 }
146 }
147 else if (bitwidth < 9) { //Method 2
148 byte border = (0xFF >> (9 - bitwidth)) - 4;
149
150 if (val > border && val <= (border + 8)) {
151 val -= border;
152 bitwidth = (val < bitwidth) ? val : val + 1;
153 continue;
154 }
155 }
156 else if (bitwidth == 9) { //Method 3
157 if (val & 0x100) {
158 bitwidth = (val + 1) & 0xFF;
159 continue;
160 }
161 }
162 else { //Illegal width, abort ?
163 freeblock(&crap);
164 return -1;
165 }
166
167 //Expand the value to signed byte:
168 {
169 signed char v; //The sample value:
170 if (bitwidth < 8) {
171 byte shift = 8 - bitwidth;
172 v = (val << shift);
173 v >>= shift;
174 }
175 else
176 v = (signed char)val;
177
178 //And integrate the sample value
179 //(It always has to end with integration doesn't it ? ;-)
180 d1 += v;
181 d2 += d1;
182 }
183
184 //Store !
185 /* Version 2.15 was an unofficial version with hacked compression
186 * code. Yay, better compression :D
187 */
188 *data++ = it215 ? d2 : d1;
189 data += stereo;
190 len--;
191 blockpos++;
192 }
193 freeblock(&crap);
194 }
195 return 0;
196}
197
198
199
200static int decompress16(DUMBFILE *f, short *data, int len, int it215, int stereo)
201{
202 int blocklen, blockpos;
203 byte bitwidth;
204 long val;
205 signed short d1, d2;
206 readblock_crap crap;
207
208 memset(&crap, 0, sizeof(crap));
209
210 for ( blocklen = 0, blockpos = 0; blocklen < len; blocklen++, blockpos += 1 + stereo )
211 data[ blockpos ] = 0;
212
213 while (len > 0) {
214 //Read a block of compressed data:
215 if (readblock(f, &crap))
216 return -1;
217 //Set up a few variables
218 blocklen = (len < 0x4000) ? len : 0x4000; // Max block length is 0x4000 bytes
219 blockpos = 0;
220 bitwidth = 17;
221 d1 = d2 = 0;
222 //Start the decompression:
223 while (blockpos < blocklen) {
224 val = readbits(bitwidth, &crap);
225 //Check for bit width change:
226
227 if (bitwidth < 7) { //Method 1:
228 if (val == (1 << (bitwidth - 1))) {
229 val = readbits(4, &crap) + 1;
230 bitwidth = (val < bitwidth) ? val : val + 1;
231 continue;
232 }
233 }
234 else if (bitwidth < 17) { //Method 2
235 word border = (0xFFFF >> (17 - bitwidth)) - 8;
236
237 if (val > border && val <= (border + 16)) {
238 val -= border;
239 bitwidth = val < bitwidth ? val : val + 1;
240 continue;
241 }
242 }
243 else if (bitwidth == 17) { //Method 3
244 if (val & 0x10000) {
245 bitwidth = (val + 1) & 0xFF;
246 continue;
247 }
248 }
249 else { //Illegal width, abort ?
250 freeblock(&crap);
251 return -1;
252 }
253
254 //Expand the value to signed byte:
255 {
256 short v; //The sample value:
257 if (bitwidth < 16) {
258 byte shift = 16 - bitwidth;
259 v = (short)(val << shift);
260 v >>= shift;
261 }
262 else
263 v = (short)val;
264
265 //And integrate the sample value
266 //(It always has to end with integration doesn't it ? ;-)
267 d1 += v;
268 d2 += d1;
269 }
270
271 //Store !
272 /* Version 2.15 was an unofficial version with hacked compression
273 * code. Yay, better compression :D
274 */
275 *data++ = it215 ? d2 : d1;
276 data += stereo;
277 len--;
278 blockpos++;
279 }
280 freeblock(&crap);
281 }
282 return 0;
283}
284
285
286
287static int it_read_envelope(IT_ENVELOPE *envelope, DUMBFILE *f)
288{
289 int n;
290
291 envelope->flags = dumbfile_getc(f);
292 envelope->n_nodes = dumbfile_getc(f);
293 if(envelope->n_nodes > 25) {
294 TRACE("IT error: wrong number of envelope nodes (%d)\n", envelope->n_nodes);
295 envelope->n_nodes = 0;
296 return -1;
297 }
298 envelope->loop_start = dumbfile_getc(f);
299 envelope->loop_end = dumbfile_getc(f);
300 envelope->sus_loop_start = dumbfile_getc(f);
301 envelope->sus_loop_end = dumbfile_getc(f);
302 for (n = 0; n < envelope->n_nodes; n++) {
303 envelope->node_y[n] = dumbfile_getc(f);
304 envelope->node_t[n] = dumbfile_igetw(f);
305 }
306 dumbfile_skip(f, 75 - envelope->n_nodes * 3 + 1);
307
308 if (envelope->n_nodes <= 0)
309 envelope->flags &= ~IT_ENVELOPE_ON;
310 else {
311 if (envelope->loop_end >= envelope->n_nodes || envelope->loop_start > envelope->loop_end) envelope->flags &= ~IT_ENVELOPE_LOOP_ON;
312 if (envelope->sus_loop_end >= envelope->n_nodes || envelope->sus_loop_start > envelope->sus_loop_end) envelope->flags &= ~IT_ENVELOPE_SUSTAIN_LOOP;
313 }
314
315 return dumbfile_error(f);
316}
317
318
319
320static int it_read_old_instrument(IT_INSTRUMENT *instrument, DUMBFILE *f)
321{
322 int n;
323
324 /*if (dumbfile_mgetl(f) != IT_INSTRUMENT_SIGNATURE)
325 return -1;*/
326 // XXX
327 dumbfile_skip(f, 4);
328
329 dumbfile_getnc((char *)instrument->filename, 13, f);
330 instrument->filename[13] = 0;
331
332 instrument->volume_envelope.flags = dumbfile_getc(f);
333 instrument->volume_envelope.loop_start = dumbfile_getc(f);
334 instrument->volume_envelope.loop_end = dumbfile_getc(f);
335 instrument->volume_envelope.sus_loop_start = dumbfile_getc(f);
336 instrument->volume_envelope.sus_loop_end = dumbfile_getc(f);
337
338 /* Skip two unused bytes. */
339 dumbfile_skip(f, 2);
340
341 /* In the old instrument format, fadeout ranges from 0 to 64, and is
342 * subtracted at intervals from a value starting at 512. In the new
343 * format, all these values are doubled. Therefore we double when loading
344 * from the old instrument format - that way we don't have to think about
345 * it later.
346 */
347 instrument->fadeout = dumbfile_igetw(f) << 1;
348 instrument->new_note_action = dumbfile_getc(f);
349 instrument->dup_check_type = dumbfile_getc(f);
350 instrument->dup_check_action = DCA_NOTE_CUT; // This might be wrong!
351 /** WARNING - what is the duplicate check action for old-style instruments? */
352
353 /* Skip Tracker Version and Number of Samples. These are only used in
354 * separate instrument files. Also skip unused byte.
355 */
356 dumbfile_skip(f, 4);
357
358 dumbfile_getnc((char *)instrument->name, 26, f);
359 instrument->name[26] = 0;
360
361 /* Skip unused bytes following the Instrument Name. */
362 dumbfile_skip(f, 6);
363
364 instrument->pp_separation = 0;
365 instrument->pp_centre = 60;
366 instrument->global_volume = 128;
367 /** WARNING - should global_volume be 64 or something? */
368 instrument->default_pan = 32;
369 /** WARNING - should default_pan be 128, meaning don`t use? */
370 instrument->random_volume = 0;
371 instrument->random_pan = 0;
372
373 for (n = 0; n < 120; n++) {
374 instrument->map_note[n] = dumbfile_getc(f);
375 instrument->map_sample[n] = dumbfile_getc(f);
376 }
377
378 /* Skip "Volume envelope (200 bytes)". */
379 // - need to know better what this is for though.
380 dumbfile_skip(f, 200);
381
382#ifdef INVESTIGATE_OLD_INSTRUMENTS
383 fprintf(stderr, "Inst %02d Env:", n);
384#endif
385
386 for (n = 0; n < 25; n++)
387 {
388 instrument->volume_envelope.node_t[n] = dumbfile_getc(f);
389 instrument->volume_envelope.node_y[n] = dumbfile_getc(f);
390
391#ifdef INVESTIGATE_OLD_INSTRUMENTS
392 fprintf(stderr, " %d,%d",
393 instrument->volume_envelope.node_t[n],
394 instrument->volume_envelope.node_y[n]);
395#endif
396
397 // This loop is unfinished, as we can probably escape from it before
398 // the end if we want to. Hence the otherwise useless dumbfile_skip()
399 // call below.
400 }
401 dumbfile_skip(f, 50 - (n << 1));
402 instrument->volume_envelope.n_nodes = n;
403
404#ifdef INVESTIGATE_OLD_INSTRUMENTS
405 fprintf(stderr, "\n");
406#endif
407
408 if (dumbfile_error(f))
409 return -1;
410
411 {
412 IT_ENVELOPE *envelope = &instrument->volume_envelope;
413 if (envelope->n_nodes <= 0)
414 envelope->flags &= ~IT_ENVELOPE_ON;
415 else {
416 if (envelope->loop_end >= envelope->n_nodes || envelope->loop_start > envelope->loop_end) envelope->flags &= ~IT_ENVELOPE_LOOP_ON;
417 if (envelope->sus_loop_end >= envelope->n_nodes || envelope->sus_loop_start > envelope->sus_loop_end) envelope->flags &= ~IT_ENVELOPE_SUSTAIN_LOOP;
418 }
419 }
420
421 instrument->filter_cutoff = 127;
422 instrument->filter_resonance = 0;
423
424 instrument->pan_envelope.flags = 0;
425 instrument->pitch_envelope.flags = 0;
426
427 return 0;
428}
429
430
431
432static int it_read_instrument(IT_INSTRUMENT *instrument, DUMBFILE *f, int maxlen)
433{
434 int n;
435 long len;
436
437 /*if (dumbfile_mgetl(f) != IT_INSTRUMENT_SIGNATURE)
438 return -1;*/
439 // XXX
440
441 if (maxlen) len = dumbfile_pos(f);
442 else len = 0;
443
444 dumbfile_skip(f, 4);
445
446 dumbfile_getnc((char *)instrument->filename, 13, f);
447 instrument->filename[13] = 0;
448
449 instrument->new_note_action = dumbfile_getc(f);
450 instrument->dup_check_type = dumbfile_getc(f);
451 instrument->dup_check_action = dumbfile_getc(f);
452 instrument->fadeout = dumbfile_igetw(f);
453 instrument->pp_separation = dumbfile_getc(f);
454 instrument->pp_centre = dumbfile_getc(f);
455 instrument->global_volume = dumbfile_getc(f);
456 instrument->default_pan = dumbfile_getc(f);
457 instrument->random_volume = dumbfile_getc(f);
458 instrument->random_pan = dumbfile_getc(f);
459
460 /* Skip Tracker Version and Number of Samples. These are only used in
461 * separate instrument files. Also skip unused byte.
462 */
463 dumbfile_skip(f, 4);
464
465 dumbfile_getnc((char *)instrument->name, 26, f);
466 instrument->name[26] = 0;
467
468 instrument->filter_cutoff = dumbfile_getc(f);
469 instrument->filter_resonance = dumbfile_getc(f);
470
471 /* Skip MIDI Channel, Program and Bank. */
472 //dumbfile_skip(f, 4);
473 /*instrument->output = dumbfile_getc(f);
474 if ( instrument->output > 16 ) {
475 instrument->output -= 128;
476 } else {
477 instrument->output = 0;
478 }
479 dumbfile_skip(f, 3);*/
480 dumbfile_skip(f, 4);
481
482 for (n = 0; n < 120; n++) {
483 instrument->map_note[n] = dumbfile_getc(f);
484 instrument->map_sample[n] = dumbfile_getc(f);
485 }
486
487 if (dumbfile_error(f))
488 return -1;
489
490 if (it_read_envelope(&instrument->volume_envelope, f)) return -1;
491 if (it_read_envelope(&instrument->pan_envelope, f)) return -1;
492 if (it_read_envelope(&instrument->pitch_envelope, f)) return -1;
493
494 if (maxlen) {
495 len = dumbfile_pos(f) - len;
496 if ( maxlen - len < 124 ) return 0;
497 }
498
499 if ( dumbfile_mgetl(f) == IT_MPTX_SIGNATURE ) {
500 for ( n = 0; n < 120; n++ ) {
501 instrument->map_sample[ n ] += dumbfile_getc( f ) << 8;
502 }
503
504 if (dumbfile_error(f))
505 return -1;
506 }
507
508 /*if ( dumbfile_mgetl(f) == IT_INSM_SIGNATURE ) {
509 long end = dumbfile_igetl(f);
510 end += dumbfile_pos(f);
511 while ( dumbfile_pos(f) < end ) {
512 int chunkid = dumbfile_igetl(f);
513 switch ( chunkid ) {
514 case DUMB_ID('P','L','U','G'):
515 instrument->output = dumbfile_getc(f);
516 break;
517 default:
518 chunkid = chunkid / 0x100 + dumbfile_getc(f) * 0x1000000;
519 break;
520 }
521 }
522
523 if (dumbfile_error(f))
524 return -1;
525 }*/
526
527 return 0;
528}
529
530
531
532static int it_read_sample_header(IT_SAMPLE *sample, unsigned char *convert, long *offset, DUMBFILE *f)
533{
534 /* XXX
535 if (dumbfile_mgetl(f) != IT_SAMPLE_SIGNATURE)
536 return -1;*/
537 int hax = 0;
538 long s = dumbfile_mgetl(f);
539 if (s != IT_SAMPLE_SIGNATURE) {
540 if ( s == ( IT_SAMPLE_SIGNATURE >> 16 ) ) {
541 s <<= 16;
542 s |= dumbfile_mgetw(f);
543 if ( s != IT_SAMPLE_SIGNATURE )
544 return -1;
545 hax = 1;
546 }
547 }
548
549 dumbfile_getnc((char *)sample->filename, 13, f);
550 sample->filename[13] = 0;
551
552 sample->global_volume = dumbfile_getc(f);
553 sample->flags = dumbfile_getc(f);
554 sample->default_volume = dumbfile_getc(f);
555
556 dumbfile_getnc((char *)sample->name, 26, f);
557 sample->name[26] = 0;
558
559 *convert = dumbfile_getc(f);
560 sample->default_pan = dumbfile_getc(f);
561 sample->length = dumbfile_igetl(f);
562 sample->loop_start = dumbfile_igetl(f);
563 sample->loop_end = dumbfile_igetl(f);
564 sample->C5_speed = dumbfile_igetl(f);
565 sample->sus_loop_start = dumbfile_igetl(f);
566 sample->sus_loop_end = dumbfile_igetl(f);
567
568#ifdef STEREO_SAMPLES_COUNT_AS_TWO
569 if (sample->flags & IT_SAMPLE_STEREO) {
570 sample->length >>= 1;
571 sample->loop_start >>= 1;
572 sample->loop_end >>= 1;
573 sample->C5_speed >>= 1;
574 sample->sus_loop_start >>= 1;
575 sample->sus_loop_end >>= 1;
576 }
577#endif
578
579 if (sample->flags & IT_SAMPLE_EXISTS) {
580 if (sample->length <= 0)
581 sample->flags &= ~IT_SAMPLE_EXISTS;
582 else {
583 if ((unsigned int)sample->loop_end > (unsigned int)sample->length)
584 sample->flags &= ~IT_SAMPLE_LOOP;
585 else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end)
586 sample->flags &= ~IT_SAMPLE_LOOP;
587
588 if ((unsigned int)sample->sus_loop_end > (unsigned int)sample->length)
589 sample->flags &= ~IT_SAMPLE_SUS_LOOP;
590 else if ((unsigned int)sample->sus_loop_start >= (unsigned int)sample->sus_loop_end)
591 sample->flags &= ~IT_SAMPLE_SUS_LOOP;
592
593 /* We may be able to truncate the sample to save memory. */
594 if (sample->flags & IT_SAMPLE_LOOP &&
595 *convert != 0xFF) { /* not truncating compressed samples, for now... */
596 if ((sample->flags & IT_SAMPLE_SUS_LOOP) && sample->sus_loop_end >= sample->loop_end)
597 sample->length = sample->sus_loop_end;
598 else
599 sample->length = sample->loop_end;
600 }
601 }
602 }
603
604 *offset = dumbfile_igetl(f);
605
606 sample->vibrato_speed = dumbfile_getc(f);
607 sample->vibrato_depth = dumbfile_getc(f);
608 if ( ! hax ) {
609 sample->vibrato_rate = dumbfile_getc(f);
610 sample->vibrato_waveform = dumbfile_getc(f);
611 } else {
612 sample->vibrato_rate = 0;
613 sample->vibrato_waveform = 0;
614 }
615 sample->finetune = 0;
616 sample->max_resampling_quality = -1;
617
618 return dumbfile_error(f);
619}
620
621long _dumb_it_read_sample_data_adpcm4(IT_SAMPLE *sample, DUMBFILE *f)
622{
623 long n, len, delta;
624 signed char * ptr, * end;
625 signed char compression_table[16];
626 if (dumbfile_getnc((char *)compression_table, 16, f) != 16)
627 return -1;
628 ptr = (signed char *) sample->data;
629 delta = 0;
630
631 end = ptr + sample->length;
632 len = (sample->length + 1) / 2;
633 for (n = 0; n < len; n++) {
634 int b = dumbfile_getc(f);
635 if (b < 0) return -1;
636 delta += compression_table[b & 0x0F];
637 *ptr++ = delta;
638 if (ptr >= end) break;
639 delta += compression_table[b >> 4];
640 *ptr++ = delta;
641 }
642
643 return 0;
644}
645
646
647static long it_read_sample_data(IT_SAMPLE *sample, unsigned char convert, DUMBFILE *f)
648{
649 long n;
650
651 long datasize = sample->length;
652 if (sample->flags & IT_SAMPLE_STEREO) datasize <<= 1;
653
654 sample->data = malloc(datasize * (sample->flags & IT_SAMPLE_16BIT ? 2 : 1));
655 if (!sample->data)
656 return -1;
657
658 if (!(sample->flags & IT_SAMPLE_16BIT) && (convert == 0xFF)) {
659 if (_dumb_it_read_sample_data_adpcm4(sample, f) < 0)
660 return -1;
661 } else if (sample->flags & 8) {
662 /* If the sample is packed, then we must unpack it. */
663
664 /* Behavior as defined by greasemonkey's munch.py and observed by XMPlay and OpenMPT */
665
666 if (sample->flags & IT_SAMPLE_STEREO) {
667 if (sample->flags & IT_SAMPLE_16BIT) {
668 decompress16(f, (short *) sample->data, (int)(datasize >> 1), convert & 4, 1);
669 decompress16(f, (short *) sample->data + 1, (int)(datasize >> 1), convert & 4, 1);
670 } else {
671 decompress8(f, (signed char *) sample->data, (int)(datasize >> 1), convert & 4, 1);
672 decompress8(f, (signed char *) sample->data + 1, (int)(datasize >> 1), convert & 4, 1);
673 }
674 } else {
675 if (sample->flags & IT_SAMPLE_16BIT)
676 decompress16(f, (short *) sample->data, (int)datasize, convert & 4, 0);
677 else
678 decompress8(f, (signed char *) sample->data, (int)datasize, convert & 4, 0);
679 }
680 } else if (sample->flags & IT_SAMPLE_16BIT) {
681 if (sample->flags & IT_SAMPLE_STEREO) {
682 if (convert & 2) {
683 for (n = 0; n < datasize; n += 2)
684 ((short *)sample->data)[n] = dumbfile_mgetw(f);
685 for (n = 1; n < datasize; n += 2)
686 ((short *)sample->data)[n] = dumbfile_mgetw(f);
687 } else {
688 for (n = 0; n < datasize; n += 2)
689 ((short *)sample->data)[n] = dumbfile_igetw(f);
690 for (n = 1; n < datasize; n += 2)
691 ((short *)sample->data)[n] = dumbfile_igetw(f);
692 }
693 } else {
694 if (convert & 2)
695 for (n = 0; n < datasize; n++)
696 ((short *)sample->data)[n] = dumbfile_mgetw(f);
697 else
698 for (n = 0; n < datasize; n++)
699 ((short *)sample->data)[n] = dumbfile_igetw(f);
700 }
701 } else {
702 if (sample->flags & IT_SAMPLE_STEREO) {
703 for (n = 0; n < datasize; n += 2)
704 ((signed char *)sample->data)[n] = dumbfile_getc(f);
705 for (n = 1; n < datasize; n += 2)
706 ((signed char *)sample->data)[n] = dumbfile_getc(f);
707 } else
708 for (n = 0; n < datasize; n++)
709 ((signed char *)sample->data)[n] = dumbfile_getc(f);
710 }
711
712 if (dumbfile_error(f))
713 return -1;
714
715 if (!(convert & 1)) {
716 /* Convert to signed. */
717 if (sample->flags & IT_SAMPLE_16BIT)
718 for (n = 0; n < datasize; n++)
719 ((short *)sample->data)[n] ^= 0x8000;
720 else
721 for (n = 0; n < datasize; n++)
722 ((signed char *)sample->data)[n] ^= 0x80;
723 }
724
725 /* NOT SUPPORTED:
726 *
727 * convert & 4 - Samples stored as delta values
728 * convert & 16 - Samples stored as TX-Wave 12-bit values
729 * convert & 32 - Left/Right/All Stereo prompt
730 */
731
732 return 0;
733}
734
735
736
737//#define DETECT_DUPLICATE_CHANNELS
738#ifdef DETECT_DUPLICATE_CHANNELS
739#include <stdio.h>
740#endif
741static int it_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer)
742{
743 unsigned char cmask[DUMB_IT_N_CHANNELS];
744 unsigned char cnote[DUMB_IT_N_CHANNELS];
745 unsigned char cinstrument[DUMB_IT_N_CHANNELS];
746 unsigned char cvolpan[DUMB_IT_N_CHANNELS];
747 unsigned char ceffect[DUMB_IT_N_CHANNELS];
748 unsigned char ceffectvalue[DUMB_IT_N_CHANNELS];
749#ifdef DETECT_DUPLICATE_CHANNELS
750 IT_ENTRY *dupentry[DUMB_IT_N_CHANNELS];
751#endif
752
753 int n_entries = 0;
754 int buflen;
755 int bufpos = 0;
756
757 IT_ENTRY *entry;
758
759 unsigned char channel;
760 unsigned char mask;
761
762 memset(cmask, 0, sizeof(cmask));
763 memset(cnote, 0, sizeof(cnote));
764 memset(cinstrument, 0, sizeof(cinstrument));
765 memset(cvolpan, 0, sizeof(cvolpan));
766 memset(ceffect, 0, sizeof(ceffect));
767 memset(ceffectvalue, 0, sizeof(ceffectvalue));
768#ifdef DETECT_DUPLICATE_CHANNELS
769 {
770 int i;
771 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) dupentry[i] = NULL;
772 }
773#endif
774
775 buflen = dumbfile_igetw(f);
776 pattern->n_rows = dumbfile_igetw(f);
777
778 /* Skip four unused bytes. */
779 dumbfile_skip(f, 4);
780
781 if (dumbfile_error(f))
782 return -1;
783
784 /* Read in the pattern data. */
785 dumbfile_getnc((char *)buffer, buflen, f);
786
787 if (dumbfile_error(f))
788 return -1;
789
790 /* Scan the pattern data, and work out how many entries we need room for. */
791 while (bufpos < buflen) {
792 unsigned char b = buffer[bufpos++];
793
794 if (b == 0) {
795 /* End of row */
796 n_entries++;
797 continue;
798 }
799
800 channel = (b - 1) & 63;
801
802 if (b & 128)
803 cmask[channel] = mask = buffer[bufpos++];
804 else
805 mask = cmask[channel];
806
807 {
808 static const unsigned char used[16] = {0, 1, 1, 2, 1, 2, 2, 3, 2, 3, 3, 4, 3, 4, 4, 5};
809 n_entries += (mask != 0);
810 bufpos += used[mask & 15];
811 }
812 }
813
814 pattern->n_entries = n_entries;
815
816 pattern->entry = malloc(n_entries * sizeof(*pattern->entry));
817
818 if (!pattern->entry)
819 return -1;
820
821 bufpos = 0;
822 memset(cmask, 0, sizeof(cmask));
823
824 entry = pattern->entry;
825
826 while (bufpos < buflen) {
827 unsigned char b = buffer[bufpos++];
828
829 if (b == 0) {
830 /* End of row */
831 IT_SET_END_ROW(entry);
832 entry++;
833#ifdef DETECT_DUPLICATE_CHANNELS
834 {
835 int i;
836 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) dupentry[i] = NULL;
837 }
838#endif
839 continue;
840 }
841
842 channel = (b - 1) & 63;
843
844 if (b & 128)
845 cmask[channel] = mask = buffer[bufpos++];
846 else
847 mask = cmask[channel];
848
849 if (mask) {
850 entry->mask = (mask & 15) | (mask >> 4);
851 entry->channel = channel;
852
853 if (mask & IT_ENTRY_NOTE)
854 cnote[channel] = entry->note = buffer[bufpos++];
855 else if (mask & (IT_ENTRY_NOTE << 4))
856 entry->note = cnote[channel];
857
858 if (mask & IT_ENTRY_INSTRUMENT)
859 cinstrument[channel] = entry->instrument = buffer[bufpos++];
860 else if (mask & (IT_ENTRY_INSTRUMENT << 4))
861 entry->instrument = cinstrument[channel];
862
863 if (mask & IT_ENTRY_VOLPAN)
864 cvolpan[channel] = entry->volpan = buffer[bufpos++];
865 else if (mask & (IT_ENTRY_VOLPAN << 4))
866 entry->volpan = cvolpan[channel];
867
868 if (mask & IT_ENTRY_EFFECT) {
869 ceffect[channel] = entry->effect = buffer[bufpos++];
870 ceffectvalue[channel] = entry->effectvalue = buffer[bufpos++];
871 } else {
872 entry->effect = ceffect[channel];
873 entry->effectvalue = ceffectvalue[channel];
874 }
875
876#ifdef DETECT_DUPLICATE_CHANNELS
877 if (dupentry[channel]) {
878 FILE *f = fopen("dupentry.txt", "a");
879 if (!f) abort();
880 fprintf(f, "Two events on channel %d:", channel);
881 fprintf(f, " Event #1:");
882 if (dupentry[channel]->mask & IT_ENTRY_NOTE ) fprintf(f, " %03d", dupentry[channel]->note ); else fprintf(f, " ...");
883 if (dupentry[channel]->mask & IT_ENTRY_INSTRUMENT) fprintf(f, " %03d", dupentry[channel]->instrument); else fprintf(f, " ...");
884 if (dupentry[channel]->mask & IT_ENTRY_VOLPAN ) fprintf(f, " %03d", dupentry[channel]->volpan ); else fprintf(f, " ...");
885 if (dupentry[channel]->mask & IT_ENTRY_EFFECT) fprintf(f, " %c%02X\n", 'A' - 1 + dupentry[channel]->effect, dupentry[channel]->effectvalue); else fprintf(f, " ...\n");
886 fprintf(f, " Event #2:");
887 if (entry->mask & IT_ENTRY_NOTE ) fprintf(f, " %03d", entry->note ); else fprintf(f, " ...");
888 if (entry->mask & IT_ENTRY_INSTRUMENT) fprintf(f, " %03d", entry->instrument); else fprintf(f, " ...");
889 if (entry->mask & IT_ENTRY_VOLPAN ) fprintf(f, " %03d", entry->volpan ); else fprintf(f, " ...");
890 if (entry->mask & IT_ENTRY_EFFECT) fprintf(f, " %c%02X\n", 'A' - 1 + entry->effect, entry->effectvalue); else fprintf(f, " ...\n");
891 fclose(f);
892 }
893 dupentry[channel] = entry;
894#endif
895
896 entry++;
897 }
898 }
899
900 ASSERT(entry == pattern->entry + n_entries);
901
902 return 0;
903}
904
905
906
907/* Currently we assume the sample data are stored after the sample headers in
908 * module files. This assumption may be unjustified; let me know if you have
909 * trouble.
910 */
911
912#define IT_COMPONENT_SONG_MESSAGE 1
913#define IT_COMPONENT_INSTRUMENT 2
914#define IT_COMPONENT_PATTERN 3
915#define IT_COMPONENT_SAMPLE 4
916
917typedef struct IT_COMPONENT
918{
919 unsigned char type;
920 unsigned short n;
921 long offset;
922 short sampfirst; /* component[sampfirst] = first sample data after this */
923 short sampnext; /* sampnext is used to create linked lists of sample data */
924}
925IT_COMPONENT;
926
927
928
929static int it_component_compare(const void *e1, const void *e2)
930{
931 return (int)(((const IT_COMPONENT *)e1)->offset -
932 ((const IT_COMPONENT *)e2)->offset);
933}
934
935
936
937static sigdata_t *it_load_sigdata(DUMBFILE *f)
938{
939 DUMB_IT_SIGDATA *sigdata;
940
941 int cwt, cmwt;
942 int special;
943 int message_length, message_offset;
944
945 IT_COMPONENT *component;
946 int n_components = 0;
947
948 unsigned char sample_convert[4096];
949
950 int n;
951
952 unsigned char *buffer;
953
954 if (dumbfile_mgetl(f) != IT_SIGNATURE)
955 {
956 return NULL;
957 }
958
959 sigdata = malloc(sizeof(*sigdata));
960
961 if (!sigdata)
962 {
963 return NULL;
964 }
965
966 sigdata->song_message = NULL;
967 sigdata->order = NULL;
968 sigdata->instrument = NULL;
969 sigdata->sample = NULL;
970 sigdata->pattern = NULL;
971 sigdata->midi = NULL;
972 sigdata->checkpoint = NULL;
973
974 dumbfile_getnc((char *)sigdata->name, 26, f);
975 sigdata->name[26] = 0;
976
977 /* Skip pattern row highlight info. */
978 dumbfile_skip(f, 2);
979
980 sigdata->n_orders = dumbfile_igetw(f);
981 sigdata->n_instruments = dumbfile_igetw(f);
982 sigdata->n_samples = dumbfile_igetw(f);
983 sigdata->n_patterns = dumbfile_igetw(f);
984
985 cwt = dumbfile_igetw(f);
986 cmwt = dumbfile_igetw(f);
987
988 sigdata->flags = dumbfile_igetw(f);
989 special = dumbfile_igetw(f);
990
991 sigdata->global_volume = dumbfile_getc(f);
992 sigdata->mixing_volume = dumbfile_getc(f);
993 sigdata->speed = dumbfile_getc(f);
994 if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo?
995 sigdata->tempo = dumbfile_getc(f);
996 sigdata->pan_separation = dumbfile_getc(f); /** WARNING: use this */
997
998 /* Skip Pitch Wheel Depth */
999 dumbfile_skip(f, 1);
1000
1001 message_length = dumbfile_igetw(f);
1002 message_offset = (int)dumbfile_igetl(f);
1003
1004 /* Skip Reserved. */
1005 dumbfile_skip(f, 4);
1006
1007 dumbfile_getnc((char *)sigdata->channel_pan, DUMB_IT_N_CHANNELS, f);
1008 dumbfile_getnc((char *)sigdata->channel_volume, DUMB_IT_N_CHANNELS, f);
1009
1010 // XXX sample count
1011 if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_instruments > 256 || sigdata->n_samples > 4000 || sigdata->n_patterns > 256) {
1012 _dumb_it_unload_sigdata(sigdata);
1013 return NULL;
1014 }
1015
1016 sigdata->order = malloc(sigdata->n_orders);
1017 if (!sigdata->order) {
1018 _dumb_it_unload_sigdata(sigdata);
1019 return NULL;
1020 }
1021
1022 if (sigdata->n_instruments) {
1023 sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
1024 if (!sigdata->instrument) {
1025 _dumb_it_unload_sigdata(sigdata);
1026 return NULL;
1027 }
1028 }
1029
1030 if (sigdata->n_samples) {
1031 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
1032 if (!sigdata->sample) {
1033 _dumb_it_unload_sigdata(sigdata);
1034 return NULL;
1035 }
1036 for (n = 0; n < sigdata->n_samples; n++)
1037 sigdata->sample[n].data = NULL;
1038 }
1039
1040 if (sigdata->n_patterns) {
1041 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
1042 if (!sigdata->pattern) {
1043 _dumb_it_unload_sigdata(sigdata);
1044 return NULL;
1045 }
1046 for (n = 0; n < sigdata->n_patterns; n++)
1047 sigdata->pattern[n].entry = NULL;
1048 }
1049
1050 dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f);
1051 sigdata->restart_position = 0;
1052
1053 component = malloc(769 * sizeof(*component));
1054 if (!component) {
1055 _dumb_it_unload_sigdata(sigdata);
1056 return NULL;
1057 }
1058
1059 if (special & 1) {
1060 component[n_components].type = IT_COMPONENT_SONG_MESSAGE;
1061 component[n_components].offset = message_offset;
1062 component[n_components].sampfirst = -1;
1063 n_components++;
1064 }
1065
1066 for (n = 0; n < sigdata->n_instruments; n++) {
1067 component[n_components].type = IT_COMPONENT_INSTRUMENT;
1068 component[n_components].n = n;
1069 component[n_components].offset = dumbfile_igetl(f);
1070 component[n_components].sampfirst = -1;
1071 n_components++;
1072 }
1073
1074 for (n = 0; n < sigdata->n_samples; n++) {
1075 component[n_components].type = IT_COMPONENT_SAMPLE;
1076 component[n_components].n = n;
1077 component[n_components].offset = dumbfile_igetl(f);
1078 component[n_components].sampfirst = -1;
1079 n_components++;
1080 }
1081
1082 for (n = 0; n < sigdata->n_patterns; n++) {
1083 long offset = dumbfile_igetl(f);
1084 if (offset) {
1085 component[n_components].type = IT_COMPONENT_PATTERN;
1086 component[n_components].n = n;
1087 component[n_components].offset = offset;
1088 component[n_components].sampfirst = -1;
1089 n_components++;
1090 } else {
1091 /* Empty 64-row pattern */
1092 sigdata->pattern[n].n_rows = 64;
1093 sigdata->pattern[n].n_entries = 0;
1094 }
1095 }
1096
1097 if (dumbfile_error(f)) {
1098 free(component);
1099 _dumb_it_unload_sigdata(sigdata);
1100 return NULL;
1101 }
1102
1103 /*
1104 if (!(sigdata->flags & 128) != !(special & 8)) {
1105 fprintf(stderr, "Flags Bit 7 (\"Request embedded MIDI configuration\"): %s\n", sigdata->flags & 128 ? "=SET=" : "clear");
1106 fprintf(stderr, "Special Bit 3 (\"MIDI configuration embedded\") : %s\n", special & 8 ? "=SET=" : "clear");
1107 fprintf(stderr, "entheh would like to investigate this IT file.\n");
1108 fprintf(stderr, "Please contact him! entheh@users.sf.net\n");
1109 }
1110 */
1111
1112 if (special & 8) {
1113 /* MIDI configuration is embedded. */
1114 unsigned char mididata[32];
1115 int i;
1116 sigdata->midi = malloc(sizeof(*sigdata->midi));
1117 if (!sigdata->midi) {
1118 free(component);
1119 _dumb_it_unload_sigdata(sigdata);
1120 return NULL;
1121 // Should we be happy with this outcome in some situations?
1122 }
1123 // What are we skipping?
1124 i = dumbfile_igetw(f);
1125 if (dumbfile_error(f) || dumbfile_skip(f, 8*i)) {
1126 free(component);
1127 _dumb_it_unload_sigdata(sigdata);
1128 return NULL;
1129 }
1130 /* Read embedded MIDI configuration */
1131 // What are the first 9 commands for?
1132 if (dumbfile_skip(f, 32*9)) {
1133 free(component);
1134 _dumb_it_unload_sigdata(sigdata);
1135 return NULL;
1136 }
1137 for (i = 0; i < 16; i++) {
1138 unsigned char len = 0;
1139 int j, leftdigit = -1;
1140 if (dumbfile_getnc((char *)mididata, 32, f) < 32) {
1141 free(component);
1142 _dumb_it_unload_sigdata(sigdata);
1143 return NULL;
1144 }
1145 sigdata->midi->SFmacroz[i] = 0;
1146 for (j = 0; j < 32; j++) {
1147 if (leftdigit >= 0) {
1148 if (mididata[j] == 0) {
1149 sigdata->midi->SFmacro[i][len++] = leftdigit;
1150 break;
1151 } else if (mididata[j] == ' ')
1152 sigdata->midi->SFmacro[i][len++] = leftdigit;
1153 else if (mididata[j] >= '0' && mididata[j] <= '9')
1154 sigdata->midi->SFmacro[i][len++] = (leftdigit << 4) | (mididata[j] - '0');
1155 else if (mididata[j] >= 'A' && mididata[j] <= 'F')
1156 sigdata->midi->SFmacro[i][len++] = (leftdigit << 4) | (mididata[j] - 'A' + 0xA);
1157 leftdigit = -1;
1158 } else if (mididata[j] == 0)
1159 break;
1160 else if (mididata[j] == 'z')
1161 sigdata->midi->SFmacroz[i] |= 1 << len++;
1162 else if (mididata[j] >= '0' && mididata[j] <= '9')
1163 leftdigit = mididata[j] - '0';
1164 else if (mididata[j] >= 'A' && mididata[j] <= 'F')
1165 leftdigit = mididata[j] - 'A' + 0xA;
1166 }
1167 sigdata->midi->SFmacrolen[i] = len;
1168 }
1169 for (i = 0; i < 128; i++) {
1170 unsigned char len = 0;
1171 int j, leftdigit = -1;
1172 dumbfile_getnc((char *)mididata, 32, f);
1173 for (j = 0; j < 32; j++) {
1174 if (leftdigit >= 0) {
1175 if (mididata[j] == 0) {
1176 sigdata->midi->Zmacro[i][len++] = leftdigit;
1177 break;
1178 } else if (mididata[j] == ' ')
1179 sigdata->midi->Zmacro[i][len++] = leftdigit;
1180 else if (mididata[j] >= '0' && mididata[j] <= '9')
1181 sigdata->midi->Zmacro[i][len++] = (leftdigit << 4) | (mididata[j] - '0');
1182 else if (mididata[j] >= 'A' && mididata[j] <= 'F')
1183 sigdata->midi->Zmacro[i][len++] = (leftdigit << 4) | (mididata[j] - 'A' + 0xA);
1184 leftdigit = -1;
1185 } else if (mididata[j] == 0)
1186 break;
1187 else if (mididata[j] >= '0' && mididata[j] <= '9')
1188 leftdigit = mididata[j] - '0';
1189 else if (mididata[j] >= 'A' && mididata[j] <= 'F')
1190 leftdigit = mididata[j] - 'A' + 0xA;
1191 }
1192 sigdata->midi->Zmacrolen[i] = len;
1193 }
1194 }
1195
1196 sigdata->flags &= IT_REAL_FLAGS;
1197
1198 qsort(component, n_components, sizeof(IT_COMPONENT), &it_component_compare);
1199
1200 buffer = malloc(65536);
1201 if (!buffer) {
1202 free(component);
1203 _dumb_it_unload_sigdata(sigdata);
1204 return NULL;
1205 }
1206
1207 for (n = 0; n < n_components; n++) {
1208 long offset;
1209 int m;
1210
1211 /* XXX */
1212 if ( component[n].offset == 0 ) {
1213 switch (component[n].type) {
1214 case IT_COMPONENT_INSTRUMENT:
1215 memset( &sigdata->instrument[component[n].n], 0, sizeof(IT_INSTRUMENT) );
1216 break;
1217 case IT_COMPONENT_SAMPLE:
1218 memset( &sigdata->sample[component[n].n], 0, sizeof(IT_SAMPLE) );
1219 break;
1220 case IT_COMPONENT_PATTERN:
1221 {
1222 IT_PATTERN * p = &sigdata->pattern[component[n].n];
1223 p->entry = 0;
1224 p->n_rows = 64;
1225 p->n_entries = 0;
1226 }
1227 break;
1228 }
1229 continue;
1230 }
1231
1232 if (dumbfile_seek(f, component[n].offset, DFS_SEEK_SET)) {
1233 free(buffer);
1234 free(component);
1235 _dumb_it_unload_sigdata(sigdata);
1236 return NULL;
1237 }
1238
1239 switch (component[n].type) {
1240
1241 case IT_COMPONENT_SONG_MESSAGE:
1242 if ( n < n_components ) {
1243 message_length = min( message_length, (int)(component[n+1].offset - component[n].offset) );
1244 }
1245 sigdata->song_message = malloc(message_length + 1);
1246 if (sigdata->song_message) {
1247 if (dumbfile_getnc((char *)sigdata->song_message, message_length, f) < message_length) {
1248 free(buffer);
1249 free(component);
1250 _dumb_it_unload_sigdata(sigdata);
1251 return NULL;
1252 }
1253 sigdata->song_message[message_length] = 0;
1254 }
1255 break;
1256
1257 case IT_COMPONENT_INSTRUMENT:
1258 if (cmwt < 0x200)
1259 m = it_read_old_instrument(&sigdata->instrument[component[n].n], f);
1260 else
1261 m = it_read_instrument(&sigdata->instrument[component[n].n], f, (n + 1 < n_components) ? (int)(component[n+1].offset - component[n].offset) : 0);
1262
1263 if (m) {
1264 free(buffer);
1265 free(component);
1266 _dumb_it_unload_sigdata(sigdata);
1267 return NULL;
1268 }
1269 break;
1270
1271 case IT_COMPONENT_PATTERN:
1272 if (it_read_pattern(&sigdata->pattern[component[n].n], f, buffer)) {
1273 free(buffer);
1274 free(component);
1275 _dumb_it_unload_sigdata(sigdata);
1276 return NULL;
1277 }
1278 break;
1279
1280 case IT_COMPONENT_SAMPLE:
1281 if (it_read_sample_header(&sigdata->sample[component[n].n], &sample_convert[component[n].n], &offset, f)) {
1282 free(buffer);
1283 free(component);
1284 _dumb_it_unload_sigdata(sigdata);
1285 return NULL;
1286 }
1287
1288 if (sigdata->sample[component[n].n].flags & IT_SAMPLE_EXISTS) {
1289 short *sample;
1290
1291 for (m = n + 1; m < n_components; m++)
1292 if (component[m].offset > offset)
1293 break;
1294 m--;
1295
1296 sample = &component[m].sampfirst;
1297
1298 while (*sample >= 0 && component[*sample].offset <= offset)
1299 sample = &component[*sample].sampnext;
1300
1301 component[n].sampnext = *sample;
1302 *sample = n;
1303
1304 component[n].offset = offset;
1305 }
1306 }
1307
1308 m = component[n].sampfirst;
1309
1310 while (m >= 0) {
1311 if (dumbfile_seek(f, component[m].offset, DFS_SEEK_SET)) {
1312 free(buffer);
1313 free(component);
1314 _dumb_it_unload_sigdata(sigdata);
1315 return NULL;
1316 }
1317
1318 if (it_read_sample_data(&sigdata->sample[component[m].n], sample_convert[component[m].n], f)) {
1319 free(buffer);
1320 free(component);
1321 _dumb_it_unload_sigdata(sigdata);
1322 return NULL;
1323 }
1324
1325 m = component[m].sampnext;
1326 }
1327 }
1328
1329 for ( n = 0; n < 10; n++ )
1330 {
1331 if ( dumbfile_getc( f ) == 'X' )
1332 {
1333 if ( dumbfile_getc( f ) == 'T' )
1334 {
1335 if ( dumbfile_getc( f ) == 'P' )
1336 {
1337 if ( dumbfile_getc( f ) == 'M' )
1338 {
1339 break;
1340 }
1341 }
1342 }
1343 }
1344 }
1345
1346 if ( !dumbfile_error( f ) && n < 10 )
1347 {
1348 unsigned int mptx_id = (unsigned int)dumbfile_igetl( f );
1349 while ( !dumbfile_error( f ) && mptx_id != DUMB_ID('M','P','T','S') )
1350 {
1351 unsigned int size = dumbfile_igetw( f );
1352 switch (mptx_id)
1353 {
1354 /* TODO: Add instrument extension readers */
1355
1356 default:
1357 dumbfile_skip(f, size * sigdata->n_instruments);
1358 break;
1359 }
1360
1361 mptx_id = (unsigned int)dumbfile_igetl( f );
1362 }
1363
1364 mptx_id = (unsigned int)dumbfile_igetl( f );
1365 while ( !dumbfile_error(f) && dumbfile_pos(f) < dumbfile_get_size(f) )
1366 {
1367 unsigned int size = dumbfile_igetw( f );
1368 switch (mptx_id)
1369 {
1370 /* TODO: Add more song extension readers */
1371
1372 case DUMB_ID('D','T','.','.'):
1373 if ( size == 2 )
1374 sigdata->tempo = dumbfile_igetw( f );
1375 else if ( size == 4 )
1376 sigdata->tempo = (int)dumbfile_igetl( f );
1377 break;
1378
1379 default:
1380 dumbfile_skip(f, size);
1381 break;
1382 }
1383 mptx_id = (unsigned int)dumbfile_igetl( f );
1384 }
1385 }
1386
1387 free(buffer);
1388 free(component);
1389
1390 _dumb_it_fix_invalid_orders(sigdata);
1391
1392 return sigdata;
1393}
1394
1395
1396
1397DUH *dumb_read_it_quick(DUMBFILE *f)
1398{
1399 sigdata_t *sigdata;
1400
1401 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
1402
1403 sigdata = it_load_sigdata(f);
1404
1405 if (!sigdata)
1406 return NULL;
1407
1408 {
1409 const char *tag[2][2];
1410 tag[0][0] = "TITLE";
1411 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
1412 tag[1][0] = "FORMAT";
1413 tag[1][1] = "IT";
1414 return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
1415 }
1416}
dumb/src/it/itrender.c+0−6102
@@ -1,6102 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itrender.c - Code to render an Impulse Tracker / / \ \
12 * module. | < / \_
13 * | \/ /\ /
14 * Written - painstakingly - by entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <math.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "dumb.h"
25#include "internal/dumb.h"
26#include "internal/it.h"
27#include "internal/lpc.h"
28
29#include "internal/resampler.h"
30
31// Keep this disabled, as it's actually slower than the original C/integer version
32//
33//#ifdef __APPLE__
34//#include <TargetConditionals.h>
35//#if TARGET_CPU_ARM || TARGET_CPU_ARM64
36//#include <arm_neon.h>
37//#define FILTER_NEON
38//#endif
39//#endif
40
41// #define BIT_ARRAY_BULLSHIT
42
43static IT_PLAYING *new_playing()
44{
45 IT_PLAYING * r = (IT_PLAYING*) malloc(sizeof(*r));
46 if (r)
47 {
48 r->resampler.fir_resampler_ratio = 0.0;
49 r->resampler.fir_resampler[0] = resampler_create();
50 if ( !r->resampler.fir_resampler[0] ) {
51 free( r );
52 return NULL;
53 }
54 r->resampler.fir_resampler[1] = resampler_create();
55 if ( !r->resampler.fir_resampler[1] ) {
56 resampler_delete( r->resampler.fir_resampler[0] );
57 free( r );
58 return NULL;
59 }
60 }
61 return r;
62}
63
64static void free_playing(IT_PLAYING * r)
65{
66 resampler_delete( r->resampler.fir_resampler[1] );
67 resampler_delete( r->resampler.fir_resampler[0] );
68 free( r );
69}
70
71static IT_PLAYING *dup_playing(IT_PLAYING *src, IT_CHANNEL *dstchannel, IT_CHANNEL *srcchannel)
72{
73 IT_PLAYING *dst;
74
75 if (!src) return NULL;
76
77 dst = malloc(sizeof(*dst));
78 if (!dst) return NULL;
79
80 dst->flags = src->flags;
81 dst->resampling_quality = src->resampling_quality;
82
83 ASSERT(src->channel);
84 dst->channel = &dstchannel[src->channel - srcchannel];
85 dst->sample = src->sample;
86 dst->instrument = src->instrument;
87 dst->env_instrument = src->env_instrument;
88
89 dst->sampnum = src->sampnum;
90 dst->instnum = src->instnum;
91
92 dst->declick_stage = src->declick_stage;
93
94 dst->float_volume[0] = src->float_volume[0];
95 dst->float_volume[1] = src->float_volume[1];
96
97 dst->ramp_volume[0] = src->ramp_volume[0];
98 dst->ramp_volume[1] = src->ramp_volume[1];
99
100 dst->ramp_delta[0] = src->ramp_delta[0];
101 dst->ramp_delta[1] = src->ramp_delta[1];
102
103 dst->channel_volume = src->channel_volume;
104
105 dst->volume = src->volume;
106 dst->pan = src->pan;
107
108 dst->volume_offset = src->volume_offset;
109 dst->panning_offset = src->panning_offset;
110
111 dst->note = src->note;
112
113 dst->enabled_envelopes = src->enabled_envelopes;
114
115 dst->filter_cutoff = src->filter_cutoff;
116 dst->filter_resonance = src->filter_resonance;
117
118 dst->true_filter_cutoff = src->true_filter_cutoff;
119 dst->true_filter_resonance = src->true_filter_resonance;
120
121 dst->vibrato_speed = src->vibrato_speed;
122 dst->vibrato_depth = src->vibrato_depth;
123 dst->vibrato_n = src->vibrato_n;
124 dst->vibrato_time = src->vibrato_time;
125 dst->vibrato_waveform = src->vibrato_waveform;
126
127 dst->tremolo_speed = src->tremolo_speed;
128 dst->tremolo_depth = src->tremolo_depth;
129 dst->tremolo_time = src->tremolo_time;
130 dst->tremolo_waveform = src->tremolo_waveform;
131
132 dst->panbrello_speed = src->panbrello_speed;
133 dst->panbrello_depth = src->panbrello_depth;
134 dst->panbrello_time = src->panbrello_time;
135 dst->panbrello_waveform = src->panbrello_waveform;
136 dst->panbrello_random = src->panbrello_random;
137
138 dst->sample_vibrato_time = src->sample_vibrato_time;
139 dst->sample_vibrato_waveform = src->sample_vibrato_waveform;
140 dst->sample_vibrato_depth = src->sample_vibrato_depth;
141
142 dst->slide = src->slide;
143 dst->delta = src->delta;
144 dst->finetune = src->finetune;
145
146 dst->volume_envelope = src->volume_envelope;
147 dst->pan_envelope = src->pan_envelope;
148 dst->pitch_envelope = src->pitch_envelope;
149
150 dst->fadeoutcount = src->fadeoutcount;
151
152 dst->filter_state[0] = src->filter_state[0];
153 dst->filter_state[1] = src->filter_state[1];
154
155 dst->resampler = src->resampler;
156 dst->resampler.pickup_data = dst;
157 dst->resampler.fir_resampler_ratio = src->resampler.fir_resampler_ratio;
158 dst->resampler.fir_resampler[0] = resampler_dup( src->resampler.fir_resampler[0] );
159 if ( !dst->resampler.fir_resampler[0] ) {
160 free( dst );
161 return NULL;
162 }
163 dst->resampler.fir_resampler[1] = resampler_dup( src->resampler.fir_resampler[1] );
164 if ( !dst->resampler.fir_resampler[1] ) {
165 resampler_delete( dst->resampler.fir_resampler[0] );
166 free( dst );
167 return NULL;
168 }
169 dst->time_lost = src->time_lost;
170
171 //dst->output = src->output;
172
173 return dst;
174}
175
176
177
178static void dup_channel(IT_CHANNEL *dst, IT_CHANNEL *src)
179{
180 dst->flags = src->flags;
181
182 dst->volume = src->volume;
183 dst->volslide = src->volslide;
184 dst->xm_volslide = src->xm_volslide;
185 dst->panslide = src->panslide;
186
187 dst->pan = src->pan;
188 dst->truepan = src->truepan;
189
190 dst->channelvolume = src->channelvolume;
191 dst->channelvolslide = src->channelvolslide;
192
193 dst->instrument = src->instrument;
194 dst->note = src->note;
195
196 dst->SFmacro = src->SFmacro;
197
198 dst->filter_cutoff = src->filter_cutoff;
199 dst->filter_resonance = src->filter_resonance;
200
201 dst->key_off_count = src->key_off_count;
202 dst->note_cut_count = src->note_cut_count;
203 dst->note_delay_count = src->note_delay_count;
204 dst->note_delay_entry = src->note_delay_entry;
205
206 dst->new_note_action = src->new_note_action;
207
208 dst->arpeggio_table = src->arpeggio_table;
209 memcpy(dst->arpeggio_offsets, src->arpeggio_offsets, sizeof(dst->arpeggio_offsets));
210 dst->retrig = src->retrig;
211 dst->xm_retrig = src->xm_retrig;
212 dst->retrig_tick = src->retrig_tick;
213
214 dst->tremor_time = src->tremor_time;
215
216 dst->vibrato_waveform = src->vibrato_waveform;
217 dst->tremolo_waveform = src->tremolo_waveform;
218 dst->panbrello_waveform = src->panbrello_waveform;
219
220 dst->portamento = src->portamento;
221 dst->toneporta = src->toneporta;
222 dst->toneslide = src->toneslide;
223 dst->toneslide_tick = src->toneslide_tick;
224 dst->last_toneslide_tick = src->last_toneslide_tick;
225 dst->ptm_toneslide = src->ptm_toneslide;
226 dst->ptm_last_toneslide = src->ptm_last_toneslide;
227 dst->okt_toneslide = src->okt_toneslide;
228 dst->destnote = src->destnote;
229
230 dst->glissando = src->glissando;
231
232 dst->sample = src->sample;
233 dst->truenote = src->truenote;
234
235 dst->midi_state = src->midi_state;
236
237 dst->lastvolslide = src->lastvolslide;
238 dst->lastDKL = src->lastDKL;
239 dst->lastEF = src->lastEF;
240 dst->lastG = src->lastG;
241 dst->lastHspeed = src->lastHspeed;
242 dst->lastHdepth = src->lastHdepth;
243 dst->lastRspeed = src->lastRspeed;
244 dst->lastRdepth = src->lastRdepth;
245 dst->lastYspeed = src->lastYspeed;
246 dst->lastYdepth = src->lastYdepth;
247 dst->lastI = src->lastI;
248 dst->lastJ = src->lastJ;
249 dst->lastN = src->lastN;
250 dst->lastO = src->lastO;
251 dst->high_offset = src->high_offset;
252 dst->lastP = src->lastP;
253 dst->lastQ = src->lastQ;
254 dst->lastS = src->lastS;
255 dst->pat_loop_row = src->pat_loop_row;
256 dst->pat_loop_count = src->pat_loop_count;
257 dst->pat_loop_end_row = src->pat_loop_end_row;
258 dst->lastW = src->lastW;
259
260 dst->xm_lastE1 = src->xm_lastE1;
261 dst->xm_lastE2 = src->xm_lastE2;
262 dst->xm_lastEA = src->xm_lastEA;
263 dst->xm_lastEB = src->xm_lastEB;
264 dst->xm_lastX1 = src->xm_lastX1;
265 dst->xm_lastX2 = src->xm_lastX2;
266
267 dst->inv_loop_delay = src->inv_loop_delay;
268 dst->inv_loop_speed = src->inv_loop_speed;
269 dst->inv_loop_offset = src->inv_loop_offset;
270
271 dst->playing = dup_playing(src->playing, dst, src);
272
273#ifdef BIT_ARRAY_BULLSHIT
274 dst->played_patjump = bit_array_dup(src->played_patjump);
275 dst->played_patjump_order = src->played_patjump_order;
276#endif
277
278 //dst->output = src->output;
279}
280
281
282
283/* Allocate the new callbacks first, then pass them to this function!
284 * It will free them on failure.
285 */
286static DUMB_IT_SIGRENDERER *dup_sigrenderer(DUMB_IT_SIGRENDERER *src, int n_channels, IT_CALLBACKS *callbacks)
287{
288 DUMB_IT_SIGRENDERER *dst;
289 int i;
290
291 if (!src) {
292 if (callbacks) free(callbacks);
293 return NULL;
294 }
295
296 dst = malloc(sizeof(*dst));
297 if (!dst) {
298 if (callbacks) free(callbacks);
299 return NULL;
300 }
301
302 dst->sigdata = src->sigdata;
303
304 dst->n_channels = n_channels;
305
306 dst->resampling_quality = src->resampling_quality;
307
308 dst->globalvolume = src->globalvolume;
309 dst->globalvolslide = src->globalvolslide;
310
311 dst->tempo = src->tempo;
312 dst->temposlide = src->temposlide;
313
314 for (i = 0; i < DUMB_IT_N_CHANNELS; i++)
315 dup_channel(&dst->channel[i], &src->channel[i]);
316
317 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
318 dst->playing[i] = dup_playing(src->playing[i], dst->channel, src->channel);
319
320 dst->tick = src->tick;
321 dst->speed = src->speed;
322 dst->rowcount = src->rowcount;
323
324 dst->order = src->order;
325 dst->row = src->row;
326 dst->processorder = src->processorder;
327 dst->processrow = src->processrow;
328 dst->breakrow = src->breakrow;
329
330 dst->restart_position = src->restart_position;
331
332 dst->n_rows = src->n_rows;
333
334 dst->entry_start = src->entry_start;
335 dst->entry = src->entry;
336 dst->entry_end = src->entry_end;
337
338 dst->time_left = src->time_left;
339 dst->sub_time_left = src->sub_time_left;
340
341 dst->ramp_style = src->ramp_style;
342
343 dst->click_remover = NULL;
344
345 dst->callbacks = callbacks;
346
347#ifdef BIT_ARRAY_BULLSHIT
348 dst->played = bit_array_dup(src->played);
349
350 dst->looped = src->looped;
351 dst->time_played = src->time_played;
352 dst->row_timekeeper = timekeeping_array_dup(src->row_timekeeper);
353#endif
354
355 dst->gvz_time = src->gvz_time;
356 dst->gvz_sub_time = src->gvz_sub_time;
357
358 //dst->max_output = src->max_output;
359
360 return dst;
361}
362
363
364
365static const IT_MIDI default_midi = {
366 /* unsigned char SFmacro[16][16]; */
367 {
368 {0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
369 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
370 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
371 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
372 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
373 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
374 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
375 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
376 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
377 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
378 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
379 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
380 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
381 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
382 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
383 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
384 },
385 /* unsigned char SFmacrolen[16]; */
386 {4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
387 /* unsigned short SFmacroz[16]; */
388 /* Bitfield; bit 0 set = z in first position */
389 {
390 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
391 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
392 },
393 /* unsigned char Zmacro[128][16]; */
394 {
395 {0xF0, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
396 {0xF0, 0xF0, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
397 {0xF0, 0xF0, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
398 {0xF0, 0xF0, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
399 {0xF0, 0xF0, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
400 {0xF0, 0xF0, 0x01, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
401 {0xF0, 0xF0, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
402 {0xF0, 0xF0, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
403 {0xF0, 0xF0, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
404 {0xF0, 0xF0, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
405 {0xF0, 0xF0, 0x01, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
406 {0xF0, 0xF0, 0x01, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
407 {0xF0, 0xF0, 0x01, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
408 {0xF0, 0xF0, 0x01, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
409 {0xF0, 0xF0, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
410 {0xF0, 0xF0, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
411
412 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
413 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
414 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
415 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
416 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
417 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
418 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
419 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
420 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
421 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
422 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
423 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
424 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
425 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
426 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
427 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
428
429 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
430 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
431 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
432 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
433 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
434 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
435 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
436 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
437 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
438 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
439 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
440 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
441 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
442 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
443 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
444 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
445
446 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
447 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
448 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
449 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
450 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
451 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
452 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
453 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
454 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
455 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
456 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
457 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
458 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
459 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
460 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
461 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
462
463 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
464 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
465 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
466 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
467 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
468 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
469 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
470 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
471 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
472 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
473 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
474 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
475 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
476 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
477 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
478 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
479
480 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
481 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
482 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
483 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
484 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
485 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
486 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
487 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
488 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
489 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
490 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
491 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
492 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
493 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
494 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
495 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
496
497 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
498 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
499 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
500 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
501 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
502 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
503 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
504 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
505 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
506 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
507 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
508 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
509 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
510 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
511 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
512 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
513
514 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
515 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
516 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
517 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
518 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
519 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
520 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
521 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
522 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
523 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
524 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
525 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
526 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
527 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
528 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
529 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
530 },
531 /* unsigned char Zmacrolen[128]; */
532 {
533 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
534 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
535 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
536 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
537 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
538 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
539 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
540 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
541 }
542};
543
544
545
546static void it_reset_filter_state(IT_FILTER_STATE *state)
547{
548 state->currsample = 0;
549 state->prevsample = 0;
550}
551
552
553
554#define LOG10 2.30258509299
555
556/* IMPORTANT: This function expects one extra sample in 'src' so it can apply
557 * click removal. It reads size samples, starting from src[0], and writes its
558 * output starting at dst[pos]. The pos parameter is required for getting
559 * click removal right.
560 */
561
562static void it_filter_int(DUMB_CLICK_REMOVER *cr, IT_FILTER_STATE *state, sample_t *dst, long pos, sample_t *src, long size, int step, int sampfreq, int cutoff, int resonance)
563{
564 sample_t currsample = state->currsample;
565 sample_t prevsample = state->prevsample;
566
567 float a, b, c;
568
569 long datasize;
570
571 {
572 float inv_angle = (float)(sampfreq * pow(0.5, 0.25 + cutoff*(1.0/(24<<IT_ENVELOPE_SHIFT))) * (1.0/(2*3.14159265358979323846*110.0)));
573 float loss = (float)exp(resonance*(-LOG10*1.2/128.0));
574 float d, e;
575#if 0
576 loss *= 2; // This is the mistake most players seem to make!
577#endif
578
579#if 1
580 d = (1.0f - loss) / inv_angle;
581 if (d > 2.0f) d = 2.0f;
582 d = (loss - d) * inv_angle;
583 e = inv_angle * inv_angle;
584 a = 1.0f / (1.0f + d + e);
585 c = -e * a;
586 b = 1.0f - a - c;
587#else
588 a = 1.0f / (inv_angle*inv_angle + inv_angle*loss + loss);
589 c = -(inv_angle*inv_angle) * a;
590 b = 1.0f - a - c;
591#endif
592 }
593
594 dst += pos * step;
595 datasize = size * step;
596
597#define INT_FILTERS
598#ifdef INT_FILTERS
599#define MULSCA(a, b) ((int)((LONG_LONG)((a) << 4) * (b) >> 32))
600#define SCALEB 12
601 {
602 int ai = (int)(a * (1 << (16+SCALEB)));
603 int bi = (int)(b * (1 << (16+SCALEB)));
604 int ci = (int)(c * (1 << (16+SCALEB)));
605 int i;
606
607 if (cr) {
608 sample_t startstep = MULSCA(src[0], ai) + MULSCA(currsample, bi) + MULSCA(prevsample, ci);
609 dumb_record_click(cr, pos, startstep);
610 }
611
612 for (i = 0; i < datasize; i += step) {
613 {
614 sample_t newsample = MULSCA(src[i], ai) + MULSCA(currsample, bi) + MULSCA(prevsample, ci);
615 prevsample = currsample;
616 currsample = newsample;
617 }
618 dst[i] += currsample;
619 }
620
621 if (cr) {
622 sample_t endstep = MULSCA(src[datasize], ai) + MULSCA(currsample, bi) + MULSCA(prevsample, ci);
623 dumb_record_click(cr, pos + size, -endstep);
624 }
625 }
626#else
627#error This version is broken - it does not use step, and state should contain floats for it
628 if (cr) {
629 float startstep = src[0]*a + currsample*b + prevsample*c;
630 dumb_record_click(cr, pos, (sample_t)startstep);
631 }
632
633 {
634 int i = size % 3;
635 while (i > 0) {
636 {
637 float newsample = *src++*a + currsample*b + prevsample*c;
638 prevsample = currsample;
639 currsample = newsample;
640 }
641 *dst++ += (sample_t)currsample;
642 i--;
643 }
644 i = size / 3;
645 while (i > 0) {
646 float newsample;
647 /* Gotta love unrolled loops! */
648 *dst++ += (sample_t)(newsample = *src++*a + currsample*b + prevsample*c);
649 *dst++ += (sample_t)(prevsample = *src++*a + newsample*b + currsample*c);
650 *dst++ += (sample_t)(currsample = *src++*a + prevsample*b + newsample*c);
651 i--;
652 }
653 }
654
655 if (cr) {
656 float endstep = src[datasize]*a + currsample*b + prevsample*c;
657 dumb_record_click(cr, pos + size, -(sample_t)endstep);
658 }
659#endif
660
661 state->currsample = currsample;
662 state->prevsample = prevsample;
663}
664
665#if defined(_USE_SSE) && (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__))
666#include <xmmintrin.h>
667
668static void it_filter_sse(DUMB_CLICK_REMOVER *cr, IT_FILTER_STATE *state, sample_t *dst, long pos, sample_t *src, long size, int step, int sampfreq, int cutoff, int resonance)
669{
670 __m128 data, impulse;
671 __m128 temp1, temp2;
672
673 sample_t currsample = state->currsample;
674 sample_t prevsample = state->prevsample;
675
676 float imp[4];
677
678 //profiler( filter_sse ); On ClawHammer Athlon64 3200+, ~12000 cycles, ~500 for that x87 setup code (as opposed to ~25500 for the original integer code)
679
680 long datasize;
681
682 {
683 float inv_angle = (float)(sampfreq * pow(0.5, 0.25 + cutoff*(1.0/(24<<IT_ENVELOPE_SHIFT))) * (1.0/(2*3.14159265358979323846*110.0)));
684 float loss = (float)exp(resonance*(-LOG10*1.2/128.0));
685 float d, e;
686#if 0
687 loss *= 2; // This is the mistake most players seem to make!
688#endif
689
690#if 1
691 d = (1.0f - loss) / inv_angle;
692 if (d > 2.0f) d = 2.0f;
693 d = (loss - d) * inv_angle;
694 e = inv_angle * inv_angle;
695 imp[0] = 1.0f / (1.0f + d + e);
696 imp[2] = -e * imp[0];
697 imp[1] = 1.0f - imp[0] - imp[2];
698#else
699 imp[0] = 1.0f / (inv_angle*inv_angle + inv_angle*loss + loss);
700 imp[2] = -(inv_angle*inv_angle) * imp[0];
701 imp[1] = 1.0f - imp[0] - imp[2];
702#endif
703 imp[3] = 0.0f;
704 }
705
706 dst += pos * step;
707 datasize = size * step;
708
709 {
710 int ai, bi, ci, i;
711
712 if (cr) {
713 sample_t startstep;
714 ai = (int)(imp[0] * (1 << (16+SCALEB)));
715 bi = (int)(imp[1] * (1 << (16+SCALEB)));
716 ci = (int)(imp[2] * (1 << (16+SCALEB)));
717 startstep = MULSCA(src[0], ai) + MULSCA(currsample, bi) + MULSCA(prevsample, ci);
718 dumb_record_click(cr, pos, startstep);
719 }
720
721 temp1 = _mm_setzero_ps();
722 data = _mm_cvtsi32_ss( temp1, currsample );
723 temp2 = _mm_cvtsi32_ss( temp1, prevsample );
724 impulse = _mm_loadu_ps( (const float *) &imp );
725 data = _mm_shuffle_ps( data, temp2, _MM_SHUFFLE(1, 0, 0, 1) );
726
727 for (i = 0; i < datasize; i += step) {
728 temp1 = _mm_cvtsi32_ss( data, src [i] );
729 temp1 = _mm_mul_ps( temp1, impulse );
730 temp2 = _mm_movehl_ps( temp2, temp1 );
731 temp1 = _mm_add_ps( temp1, temp2 );
732 temp2 = temp1;
733 temp2 = _mm_shuffle_ps( temp2, temp1, _MM_SHUFFLE(0, 0, 0, 1) );
734 temp1 = _mm_add_ps( temp1, temp2 );
735 temp1 = _mm_shuffle_ps( temp1, data, _MM_SHUFFLE(2, 1, 0, 0) );
736 data = temp1;
737 dst [i] += _mm_cvtss_si32( temp1 );
738 }
739
740 currsample = _mm_cvtss_si32( temp1 );
741 temp1 = _mm_shuffle_ps( temp1, data, _MM_SHUFFLE(0, 0, 0, 2) );
742 prevsample = _mm_cvtss_si32( temp1 );
743
744 if (cr) {
745 sample_t endstep = MULSCA(src[datasize], ai) + MULSCA(currsample, bi) + MULSCA(prevsample, ci);
746 dumb_record_click(cr, pos + size, -endstep);
747 }
748 }
749
750 state->currsample = currsample;
751 state->prevsample = prevsample;
752}
753#endif
754
755#ifdef FILTER_NEON
756static void it_filter_neon(DUMB_CLICK_REMOVER *cr, IT_FILTER_STATE *state, sample_t *dst, long pos, sample_t *src, long size, int step, int sampfreq, int cutoff, int resonance)
757{
758 float32x4_t data, impulse;
759 float32x4_t temp1;
760 float32x2_t temp2;
761 float32_t temp3;
762
763 sample_t currsample = state->currsample;
764 sample_t prevsample = state->prevsample;
765
766 float imp[4];
767
768 //profiler( filter_sse ); On ClawHammer Athlon64 3200+, ~12000 cycles, ~500 for that x87 setup code (as opposed to ~25500 for the original integer code)
769
770 long datasize;
771
772 {
773 float inv_angle = (float)(sampfreq * pow(0.5, 0.25 + cutoff*(1.0/(24<<IT_ENVELOPE_SHIFT))) * (1.0/(2*3.14159265358979323846*110.0)));
774 float loss = (float)exp(resonance*(-LOG10*1.2/128.0));
775 float d, e;
776#if 0
777 loss *= 2; // This is the mistake most players seem to make!
778#endif
779
780#if 1
781 d = (1.0f - loss) / inv_angle;
782 if (d > 2.0f) d = 2.0f;
783 d = (loss - d) * inv_angle;
784 e = inv_angle * inv_angle;
785 imp[0] = 1.0f / (1.0f + d + e);
786 imp[2] = -e * imp[0];
787 imp[1] = 1.0f - imp[0] - imp[2];
788#else
789 imp[0] = 1.0f / (inv_angle*inv_angle + inv_angle*loss + loss);
790 imp[2] = -(inv_angle*inv_angle) * imp[0];
791 imp[1] = 1.0f - imp[0] - imp[2];
792#endif
793 imp[3] = 0.0f;
794 }
795
796 dst += pos * step;
797 datasize = size * step;
798
799 {
800 int ai, bi, ci, i;
801
802 if (cr) {
803 sample_t startstep;
804 ai = (int)(imp[0] * (1 << (16+SCALEB)));
805 bi = (int)(imp[1] * (1 << (16+SCALEB)));
806 ci = (int)(imp[2] * (1 << (16+SCALEB)));
807 startstep = MULSCA(src[0], ai) + MULSCA(currsample, bi) + MULSCA(prevsample, ci);
808 dumb_record_click(cr, pos, startstep);
809 }
810
811 data = vdupq_n_f32(0.0f);
812 data = vsetq_lane_f32( currsample, data, 1 );
813 data = vsetq_lane_f32( prevsample, data, 2 );
814 impulse = vld1q_f32( (const float32_t *) &imp );
815
816 for (i = 0; i < datasize; i += step) {
817 data = vsetq_lane_f32( src [i], data, 0 );
818 temp1 = vmulq_f32(data, impulse);
819 temp2 = vadd_f32(vget_high_f32(temp1), vget_low_f32(temp1));
820 temp3 = vget_lane_f32(vpadd_f32(temp2, temp2), 0);
821 data = vextq_f32(data, data, 3);
822 data = vsetq_lane_f32(temp3, data, 1);
823 dst [i] += temp3;
824 }
825
826 currsample = temp3;
827 prevsample = vgetq_lane_f32(data, 2);
828
829 if (cr) {
830 sample_t endstep = MULSCA(src[datasize], ai) + MULSCA(currsample, bi) + MULSCA(prevsample, ci);
831 dumb_record_click(cr, pos + size, -endstep);
832 }
833 }
834
835 state->currsample = currsample;
836 state->prevsample = prevsample;
837}
838#endif
839
840#undef LOG10
841
842#ifdef _USE_SSE
843#if defined(_M_IX86) || defined(__i386__)
844
845#ifdef _MSC_VER
846#include <intrin.h>
847#elif defined(__clang__) || defined(__GNUC__)
848static inline void
849__cpuid(int *data, int selector)
850{
851#if defined(__PIC__) && defined(__i386__)
852 asm("xchgl %%ebx, %%esi; cpuid; xchgl %%ebx, %%esi"
853 : "=a" (data[0]),
854 "=S" (data[1]),
855 "=c" (data[2]),
856 "=d" (data[3])
857 : "0" (selector));
858#elif defined(__PIC__) && defined(__amd64__)
859 asm("xchg{q} {%%}rbx, %q1; cpuid; xchg{q} {%%}rbx, %q1"
860 : "=a" (data[0]),
861 "=&r" (data[1]),
862 "=c" (data[2]),
863 "=d" (data[3])
864 : "0" (selector));
865#else
866 asm("cpuid"
867 : "=a" (data[0]),
868 "=b" (data[1]),
869 "=c" (data[2]),
870 "=d" (data[3])
871 : "a"(selector));
872#endif
873}
874#else
875#define __cpuid(a,b) memset((a), 0, sizeof(int) * 4)
876#endif
877
878static int query_cpu_feature_sse() {
879 int buffer[4];
880 __cpuid(buffer,1);
881 if ((buffer[3]&(1<<25)) == 0) return 0;
882 return 1;
883}
884
885static int _dumb_it_use_sse = 0;
886
887void _dumb_init_sse()
888{
889 static int initialized = 0;
890 if (!initialized)
891 {
892 _dumb_it_use_sse = query_cpu_feature_sse();
893 initialized = 1;
894 }
895}
896
897#elif defined(_M_X64) || defined(__amd64__)
898
899static const int _dumb_it_use_sse = 1;
900
901void _dumb_init_sse() { }
902
903#else
904
905static const int _dumb_it_use_sse = 0;
906
907void _dumb_init_sse() { }
908
909#endif
910#endif
911
912static void it_filter(DUMB_CLICK_REMOVER *cr, IT_FILTER_STATE *state, sample_t *dst, long pos, sample_t *src, long size, int step, int sampfreq, int cutoff, int resonance)
913{
914#if defined(_USE_SSE) && (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__))
915 _dumb_init_sse();
916 if ( _dumb_it_use_sse ) it_filter_sse( cr, state, dst, pos, src, size, step, sampfreq, cutoff, resonance );
917 else
918#endif
919#ifdef FILTER_NEON
920 it_filter_neon( cr, state, dst, pos, src, size, step, sampfreq, cutoff, resonance );
921#else
922 it_filter_int( cr, state, dst, pos, src, size, step, sampfreq, cutoff, resonance );
923#endif
924}
925
926
927
928static const signed char it_sine[256] = {
929 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
930 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
931 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
932 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64,
933 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60,
934 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
935 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26,
936 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2,
937 0, -2, -3, -5, -6, -8, -9,-11,-12,-14,-16,-17,-19,-20,-22,-23,
938 -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44,
939 -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59,
940 -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64,
941 -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60,
942 -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,
943 -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,
944 -24,-23,-22,-20,-19,-17,-16,-14,-12,-11, -9, -8, -6, -5, -3, -2
945};
946
947
948
949#if 1
950/** WARNING: use these! */
951/** JULIEN: Plus for XM compatibility it could be interesting to rename
952 * it_sawtooth[] to it_rampdown[], and add an it_rampup[].
953 * Also, still for XM compat', twood be good if it was possible to tell the
954 * the player not to retrig' the waveform on a new instrument.
955 * Both of these are only for completness though, as I don't think it would
956 * be very noticeable ;)
957 */
958/** ENTHEH: IT also has the 'don't retrig' thingy :) */
959static const signed char it_sawtooth[256] = {
960 64, 63, 63, 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56,
961 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48,
962 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40,
963 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32,
964 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24,
965 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16,
966 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8,
967 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0,
968 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8,
969 -8, -9, -9,-10,-10,-11,-11,-12,-12,-13,-13,-14,-14,-15,-15,-16,
970 -16,-17,-17,-18,-18,-19,-19,-20,-20,-21,-21,-22,-22,-23,-23,-24,
971 -24,-25,-25,-26,-26,-27,-27,-28,-28,-29,-29,-30,-30,-31,-31,-32,
972 -32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40,
973 -40,-41,-41,-42,-42,-43,-43,-44,-44,-45,-45,-46,-46,-47,-47,-48,
974 -48,-49,-49,-50,-50,-51,-51,-52,-52,-53,-53,-54,-54,-55,-55,-56,
975 -56,-57,-57,-58,-58,-59,-59,-60,-60,-61,-61,-62,-62,-63,-63,-64
976};
977
978static const signed char it_squarewave[256] = {
979 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
980 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
981 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
982 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
983 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
984 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
985 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
986 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
987 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
988 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
989 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
990 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
991 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
992 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
993 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
994 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
995};
996
997static const signed char it_xm_ramp[256] = {
998 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8,
999 -8, -9, -9,-10,-10,-11,-11,-12,-12,-13,-13,-14,-14,-15,-15,-16,
1000 -16,-17,-17,-18,-18,-19,-19,-20,-20,-21,-21,-22,-22,-23,-23,-24,
1001 -24,-25,-25,-26,-26,-27,-27,-28,-28,-29,-29,-30,-30,-31,-31,-32,
1002 -32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40,
1003 -40,-41,-41,-42,-42,-43,-43,-44,-44,-45,-45,-46,-46,-47,-47,-48,
1004 -48,-49,-49,-50,-50,-51,-51,-52,-52,-53,-53,-54,-54,-55,-55,-56,
1005 -56,-57,-57,-58,-58,-59,-59,-60,-60,-61,-61,-62,-62,-63,-63,-64,
1006 64, 63, 63, 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56,
1007 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48,
1008 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40,
1009 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32,
1010 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24,
1011 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16,
1012 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8,
1013 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0
1014};
1015
1016static const signed char it_xm_squarewave[256] = {
1017 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1018 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1019 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1020 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1021 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1022 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1023 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1024 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1025 -64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,
1026 -64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,
1027 -64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,
1028 -64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,
1029 -64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,
1030 -64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,
1031 -64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,
1032 -64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64
1033};
1034
1035#endif
1036
1037
1038
1039static void reset_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer)
1040{
1041 int i;
1042
1043 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
1044 IT_CHANNEL *channel = &sigrenderer->channel[i];
1045 channel->key_off_count = 0;
1046 channel->note_cut_count = 0;
1047 channel->note_delay_count = 0;
1048 }
1049}
1050
1051
1052
1053static const unsigned char arpeggio_mod[32] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1};
1054static const unsigned char arpeggio_xm[32] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
1055static const unsigned char arpeggio_okt_3[32] = {1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0};
1056static const unsigned char arpeggio_okt_4[32] = {0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1};
1057static const unsigned char arpeggio_okt_5[32] = {2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2};
1058
1059
1060
1061static void reset_channel_effects(IT_CHANNEL *channel)
1062{
1063 channel->volslide = 0;
1064 channel->xm_volslide = 0;
1065 channel->panslide = 0;
1066 channel->channelvolslide = 0;
1067 channel->arpeggio_table = (const unsigned char *) &arpeggio_mod;
1068 memset(channel->arpeggio_offsets, 0, sizeof(channel->arpeggio_offsets));
1069 channel->retrig = 0;
1070 if (channel->xm_retrig) {
1071 channel->xm_retrig = 0;
1072 channel->retrig_tick = 0;
1073 }
1074 channel->tremor_time &= 127;
1075 channel->portamento = 0;
1076 channel->toneporta = 0;
1077 if (channel->ptm_toneslide) {
1078 channel->ptm_last_toneslide = channel->ptm_toneslide;
1079 channel->last_toneslide_tick = channel->toneslide_tick;
1080 } else
1081 channel->ptm_last_toneslide = 0;
1082 channel->ptm_toneslide = 0;
1083 channel->toneslide_tick = 0;
1084 channel->okt_toneslide = 0;
1085 if (channel->playing) {
1086 channel->playing->vibrato_n = 0;
1087 channel->playing->tremolo_speed = 0;
1088 channel->playing->tremolo_depth = 0;
1089 channel->playing->panbrello_speed = 0;
1090 }
1091}
1092
1093static void reset_effects(DUMB_IT_SIGRENDERER *sigrenderer)
1094{
1095 int i;
1096
1097 sigrenderer->globalvolslide = 0;
1098 sigrenderer->temposlide = 0;
1099
1100 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
1101 reset_channel_effects(&sigrenderer->channel[i]);
1102 }
1103}
1104
1105
1106
1107static void update_tremor(IT_CHANNEL *channel)
1108{
1109 if ((channel->tremor_time & 128) && channel->playing) {
1110 if (channel->tremor_time == 128)
1111 channel->tremor_time = (channel->lastI >> 4) | 192;
1112 else if (channel->tremor_time == 192)
1113 channel->tremor_time = (channel->lastI & 15) | 128;
1114 else
1115 channel->tremor_time--;
1116 }
1117}
1118
1119
1120
1121static void it_pickup_loop(DUMB_RESAMPLER *resampler, void *data)
1122{
1123 resampler->pos -= resampler->end - resampler->start;
1124 ((IT_PLAYING *)data)->time_lost += resampler->end - resampler->start;
1125}
1126
1127
1128
1129static void it_pickup_pingpong_loop(DUMB_RESAMPLER *resampler, void *data)
1130{
1131 if (resampler->dir < 0) {
1132 resampler->pos = (resampler->start << 1) - 1 - resampler->pos;
1133 resampler->subpos ^= 65535;
1134 resampler->dir = 1;
1135 ((IT_PLAYING *)data)->time_lost += (resampler->end - resampler->start) << 1;
1136 } else {
1137 resampler->pos = (resampler->end << 1) - 1 - resampler->pos;
1138 resampler->subpos ^= 65535;
1139 resampler->dir = -1;
1140 }
1141}
1142
1143
1144
1145static void it_pickup_stop_at_end(DUMB_RESAMPLER *resampler, void *data)
1146{
1147 (void)data;
1148
1149 if (resampler->dir < 0) {
1150 resampler->pos = (resampler->start << 1) - 1 - resampler->pos;
1151 resampler->subpos ^= 65535;
1152 /* By rights, time_lost would be updated here. However, there is no
1153 * need at this point; it will not be used.
1154 *
1155 * ((IT_PLAYING *)data)->time_lost += (resampler->src_end - resampler->src_start) << 1;
1156 */
1157 resampler->dir = 1;
1158 } else
1159 resampler->dir = 0;
1160}
1161
1162
1163
1164static void it_pickup_stop_after_reverse(DUMB_RESAMPLER *resampler, void *data)
1165{
1166 (void)data;
1167
1168 resampler->dir = 0;
1169}
1170
1171
1172
1173static void it_playing_update_resamplers(IT_PLAYING *playing)
1174{
1175 if ((playing->sample->flags & IT_SAMPLE_SUS_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF)) {
1176 playing->resampler.start = playing->sample->sus_loop_start;
1177 playing->resampler.end = playing->sample->sus_loop_end;
1178 if (playing->resampler.start == playing->resampler.end)
1179 playing->resampler.pickup = &it_pickup_stop_at_end;
1180 else if (playing->sample->flags & IT_SAMPLE_PINGPONG_SUS_LOOP)
1181 playing->resampler.pickup = &it_pickup_pingpong_loop;
1182 else
1183 playing->resampler.pickup = &it_pickup_loop;
1184 } else if (playing->sample->flags & IT_SAMPLE_LOOP) {
1185 playing->resampler.start = playing->sample->loop_start;
1186 playing->resampler.end = playing->sample->loop_end;
1187 if (playing->resampler.start == playing->resampler.end)
1188 playing->resampler.pickup = &it_pickup_stop_at_end;
1189 else if (playing->sample->flags & IT_SAMPLE_PINGPONG_LOOP)
1190 playing->resampler.pickup = &it_pickup_pingpong_loop;
1191 else
1192 playing->resampler.pickup = &it_pickup_loop;
1193 } else if (playing->flags & IT_PLAYING_REVERSE) {
1194 playing->resampler.start = 0;
1195 playing->resampler.end = playing->sample->length;
1196 playing->resampler.dir = -1;
1197 playing->resampler.pickup = &it_pickup_stop_after_reverse;
1198 } else {
1199 if (playing->sample->flags & IT_SAMPLE_SUS_LOOP)
1200 playing->resampler.start = playing->sample->sus_loop_start;
1201 else
1202 playing->resampler.start = 0;
1203 playing->resampler.end = playing->sample->length;
1204 playing->resampler.pickup = &it_pickup_stop_at_end;
1205 }
1206 ASSERT(playing->resampler.pickup_data == playing);
1207}
1208
1209
1210
1211/* This should be called whenever the sample or sample position changes. */
1212static void it_playing_reset_resamplers(IT_PLAYING *playing, long pos)
1213{
1214 int bits = playing->sample->flags & IT_SAMPLE_16BIT ? 16 : 8;
1215 int quality = playing->resampling_quality;
1216 int channels = playing->sample->flags & IT_SAMPLE_STEREO ? 2 : 1;
1217 if (playing->sample->max_resampling_quality >= 0 && quality > playing->sample->max_resampling_quality)
1218 quality = playing->sample->max_resampling_quality;
1219 dumb_reset_resampler_n(bits, &playing->resampler, playing->sample->data, channels, pos, 0, 0, quality);
1220 playing->resampler.pickup_data = playing;
1221 playing->time_lost = 0;
1222 playing->flags &= ~IT_PLAYING_DEAD;
1223 it_playing_update_resamplers(playing);
1224}
1225
1226static void it_retrigger_note(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel);
1227
1228/* Should we only be retriggering short samples on XM? */
1229
1230static void update_retrig(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel)
1231{
1232 if (channel->xm_retrig) {
1233 channel->retrig_tick--;
1234 if (channel->retrig_tick <= 0) {
1235 if (channel->playing) {
1236 it_playing_reset_resamplers(channel->playing, 0);
1237 channel->playing->declick_stage = 0;
1238 } else if (sigrenderer->sigdata->flags & IT_WAS_AN_XM) it_retrigger_note(sigrenderer, channel);
1239 channel->retrig_tick = channel->xm_retrig;
1240 }
1241 } else if (channel->retrig & 0x0F) {
1242 channel->retrig_tick--;
1243 if (channel->retrig_tick <= 0) {
1244 if (channel->retrig < 0x10) {
1245 } else if (channel->retrig < 0x20) {
1246 channel->volume--;
1247 if (channel->volume > 64) channel->volume = 0;
1248 } else if (channel->retrig < 0x30) {
1249 channel->volume -= 2;
1250 if (channel->volume > 64) channel->volume = 0;
1251 } else if (channel->retrig < 0x40) {
1252 channel->volume -= 4;
1253 if (channel->volume > 64) channel->volume = 0;
1254 } else if (channel->retrig < 0x50) {
1255 channel->volume -= 8;
1256 if (channel->volume > 64) channel->volume = 0;
1257 } else if (channel->retrig < 0x60) {
1258 channel->volume -= 16;
1259 if (channel->volume > 64) channel->volume = 0;
1260 } else if (channel->retrig < 0x70) {
1261 channel->volume <<= 1;
1262 channel->volume /= 3;
1263 } else if (channel->retrig < 0x80) {
1264 channel->volume >>= 1;
1265 } else if (channel->retrig < 0x90) {
1266 } else if (channel->retrig < 0xA0) {
1267 channel->volume++;
1268 if (channel->volume > 64) channel->volume = 64;
1269 } else if (channel->retrig < 0xB0) {
1270 channel->volume += 2;
1271 if (channel->volume > 64) channel->volume = 64;
1272 } else if (channel->retrig < 0xC0) {
1273 channel->volume += 4;
1274 if (channel->volume > 64) channel->volume = 64;
1275 } else if (channel->retrig < 0xD0) {
1276 channel->volume += 8;
1277 if (channel->volume > 64) channel->volume = 64;
1278 } else if (channel->retrig < 0xE0) {
1279 channel->volume += 16;
1280 if (channel->volume > 64) channel->volume = 64;
1281 } else if (channel->retrig < 0xF0) {
1282 channel->volume *= 3;
1283 channel->volume >>= 1;
1284 if (channel->volume > 64) channel->volume = 64;
1285 } else {
1286 channel->volume <<= 1;
1287 if (channel->volume > 64) channel->volume = 64;
1288 }
1289 if (channel->playing) {
1290 it_playing_reset_resamplers(channel->playing, 0);
1291 channel->playing->declick_stage = 0;
1292 } else if (sigrenderer->sigdata->flags & IT_WAS_AN_XM) it_retrigger_note(sigrenderer, channel);
1293 channel->retrig_tick = channel->retrig & 0x0F;
1294 }
1295 }
1296}
1297
1298
1299static void update_smooth_effects_playing(IT_PLAYING *playing)
1300{
1301 playing->vibrato_time += playing->vibrato_n *
1302 (playing->vibrato_speed << 2);
1303 playing->tremolo_time += playing->tremolo_speed << 2;
1304 playing->panbrello_time += playing->panbrello_speed;
1305 if (playing->panbrello_waveform == 3)
1306 playing->panbrello_random = (rand() % 129) - 64;
1307}
1308
1309static void update_smooth_effects(DUMB_IT_SIGRENDERER *sigrenderer)
1310{
1311 int i;
1312
1313 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
1314 IT_CHANNEL *channel = &sigrenderer->channel[i];
1315 IT_PLAYING *playing = channel->playing;
1316
1317 if (playing) {
1318 update_smooth_effects_playing(playing);
1319 }
1320 }
1321
1322 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
1323 IT_PLAYING *playing = sigrenderer->playing[i];
1324
1325 if (playing) {
1326 update_smooth_effects_playing(playing);
1327 }
1328 }
1329}
1330
1331
1332static const unsigned char pt_tab_invloop[16] =
1333{
1334 0x00, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0D,
1335 0x0F, 0x13, 0x16, 0x1A, 0x20, 0x2B, 0x40, 0x80
1336};
1337
1338static void update_invert_loop(IT_CHANNEL *channel, IT_SAMPLE *sample)
1339{
1340 channel->inv_loop_delay += pt_tab_invloop[channel->inv_loop_speed];
1341 if (channel->inv_loop_delay >= 0x80)
1342 {
1343 channel->inv_loop_delay = 0;
1344
1345 if (sample && ((sample->flags & (IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP)) == (IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP)) && !(sample->flags & (IT_SAMPLE_STEREO | IT_SAMPLE_16BIT)))
1346 {
1347 if (sample->loop_end - sample->loop_start >= 4)
1348 {
1349 channel->inv_loop_offset++;
1350 if (channel->inv_loop_offset >= (sample->loop_end - sample->loop_start)) channel->inv_loop_offset = 0;
1351
1352 ((char *)sample->data)[sample->loop_start + channel->inv_loop_offset] ^= 0xFF;
1353 }
1354 }
1355 }
1356}
1357
1358
1359static void update_playing_effects(IT_PLAYING *playing)
1360{
1361 IT_CHANNEL *channel = playing->channel;
1362
1363 if (channel->channelvolslide) {
1364 playing->channel_volume = channel->channelvolume;
1365 }
1366
1367 if (channel->okt_toneslide) {
1368 if (channel->okt_toneslide--) {
1369 playing->note += channel->toneslide;
1370 if (playing->note >= 120) {
1371 if (channel->toneslide < 0) playing->note = 0;
1372 else playing->note = 119;
1373 }
1374 }
1375 } else if (channel->ptm_toneslide) {
1376 if (--channel->toneslide_tick == 0) {
1377 channel->toneslide_tick = channel->ptm_toneslide;
1378 if (playing) {
1379 playing->note += channel->toneslide;
1380 if (playing->note >= 120) {
1381 if (channel->toneslide < 0) playing->note = 0;
1382 else playing->note = 119;
1383 }
1384 if (channel->playing == playing) {
1385 channel->note = channel->truenote = playing->note;
1386 }
1387 if (channel->toneslide_retrig) {
1388 it_playing_reset_resamplers(playing, 0);
1389 playing->declick_stage = 0;
1390 }
1391 }
1392 }
1393 }
1394}
1395
1396
1397static void update_effects(DUMB_IT_SIGRENDERER *sigrenderer)
1398{
1399 int i;
1400
1401 if (sigrenderer->globalvolslide) {
1402 sigrenderer->globalvolume += sigrenderer->globalvolslide;
1403 if (sigrenderer->globalvolume > 128) {
1404 if (sigrenderer->globalvolslide >= 0)
1405 sigrenderer->globalvolume = 128;
1406 else
1407 sigrenderer->globalvolume = 0;
1408 }
1409 }
1410
1411 if (sigrenderer->temposlide) {
1412 sigrenderer->tempo += sigrenderer->temposlide;
1413 if (sigrenderer->tempo < 32) {
1414 if (sigrenderer->temposlide >= 0)
1415 sigrenderer->tempo = 255;
1416 else
1417 sigrenderer->tempo = 32;
1418 }
1419 }
1420
1421 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
1422 IT_CHANNEL *channel = &sigrenderer->channel[i];
1423 IT_PLAYING *playing = channel->playing;
1424
1425 if (channel->xm_volslide) {
1426 channel->volume += channel->xm_volslide;
1427 if (channel->volume > 64) {
1428 if (channel->xm_volslide >= 0)
1429 channel->volume = 64;
1430 else
1431 channel->volume = 0;
1432 }
1433 }
1434
1435 if (channel->volslide) {
1436 int clip = (sigrenderer->sigdata->flags & IT_WAS_AN_S3M) ? 63 : 64;
1437 channel->volume += channel->volslide;
1438 if (channel->volume > clip) {
1439 if (channel->volslide >= 0)
1440 channel->volume = clip;
1441 else
1442 channel->volume = 0;
1443 }
1444 }
1445
1446 if (channel->panslide) {
1447 if (sigrenderer->sigdata->flags & IT_WAS_AN_XM) {
1448 if (IT_IS_SURROUND(channel->pan))
1449 {
1450 channel->pan = 32;
1451 channel->truepan = 32 + 128 * 64;
1452 }
1453 if (channel->panslide == -128)
1454 channel->truepan = 32;
1455 else
1456 channel->truepan = MID(32, channel->truepan + channel->panslide*64, 32+255*64);
1457 } else {
1458 if (IT_IS_SURROUND(channel->pan))
1459 {
1460 channel->pan = 32;
1461 }
1462 channel->pan += channel->panslide;
1463 if (channel->pan > 64) {
1464 if (channel->panslide >= 0)
1465 channel->pan = 64;
1466 else
1467 channel->pan = 0;
1468 }
1469 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
1470 }
1471 }
1472
1473 if (channel->channelvolslide) {
1474 channel->channelvolume += channel->channelvolslide;
1475 if (channel->channelvolume > 64) {
1476 if (channel->channelvolslide >= 0)
1477 channel->channelvolume = 64;
1478 else
1479 channel->channelvolume = 0;
1480 }
1481 }
1482
1483 update_tremor(channel);
1484
1485 update_retrig(sigrenderer, channel);
1486
1487 if (channel->inv_loop_speed) update_invert_loop(channel, playing ? playing->sample : NULL);
1488
1489 if (playing) {
1490 playing->slide += channel->portamento;
1491
1492 if (sigrenderer->sigdata->flags & IT_LINEAR_SLIDES) {
1493 if (channel->toneporta && channel->destnote < 120) {
1494 int currpitch = ((playing->note - 60) << 8) + playing->slide;
1495 int destpitch = (channel->destnote - 60) << 8;
1496 if (currpitch > destpitch) {
1497 currpitch -= channel->toneporta;
1498 if (currpitch < destpitch) {
1499 currpitch = destpitch;
1500 channel->destnote = IT_NOTE_OFF;
1501 }
1502 } else if (currpitch < destpitch) {
1503 currpitch += channel->toneporta;
1504 if (currpitch > destpitch) {
1505 currpitch = destpitch;
1506 channel->destnote = IT_NOTE_OFF;
1507 }
1508 }
1509 playing->slide = currpitch - ((playing->note - 60) << 8);
1510 }
1511 } else {
1512 if (channel->toneporta && channel->destnote < 120) {
1513 float amiga_multiplier = playing->sample->C5_speed * (1.0f / AMIGA_DIVISOR);
1514
1515 float deltanote = (float)pow(DUMB_SEMITONE_BASE, 60 - playing->note);
1516 /* deltanote is 1.0 for C-5, 0.5 for C-6, etc. */
1517
1518 float deltaslid = deltanote - playing->slide * amiga_multiplier;
1519
1520 float destdelta = (float)pow(DUMB_SEMITONE_BASE, 60 - channel->destnote);
1521 if (deltaslid < destdelta) {
1522 playing->slide -= channel->toneporta;
1523 deltaslid = deltanote - playing->slide * amiga_multiplier;
1524 if (deltaslid > destdelta) {
1525 playing->note = channel->destnote;
1526 playing->slide = 0;
1527 channel->destnote = IT_NOTE_OFF;
1528 }
1529 } else {
1530 playing->slide += channel->toneporta;
1531 deltaslid = deltanote - playing->slide * amiga_multiplier;
1532 if (deltaslid < destdelta) {
1533 playing->note = channel->destnote;
1534 playing->slide = 0;
1535 channel->destnote = IT_NOTE_OFF;
1536 }
1537 }
1538 }
1539 }
1540
1541 update_playing_effects(playing);
1542 }
1543 }
1544
1545 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
1546 IT_PLAYING *playing = sigrenderer->playing[i];
1547 if (playing) update_playing_effects(playing);
1548 }
1549
1550 update_smooth_effects(sigrenderer);
1551}
1552
1553
1554static void it_note_off(IT_PLAYING *playing);
1555
1556// This function should be renamed; it doesn't do the 'Update Pattern Variables' operation ittech.txt describes
1557/* Returns 1 if a pattern loop is happening. */
1558static int update_pattern_variables(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
1559{
1560 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
1561
1562 if (entry->mask & IT_ENTRY_EFFECT) {
1563 switch (entry->effect) {
1564 case IT_JUMP_TO_ORDER:
1565 /* XXX jump and break in same row */
1566 if ( ( ( sigrenderer->processrow | 0xC00 ) == 0xFFFE ) &&
1567 ! ( sigrenderer->processrow & 0x800 ) ) {
1568 sigrenderer->processrow = 0xFFFE & ~0xC00;
1569 } else {
1570 sigrenderer->breakrow = 0;
1571 sigrenderer->processrow = 0xFFFE & ~0x400;
1572 }
1573 sigrenderer->processorder = entry->effectvalue - 1;
1574 break;
1575
1576 case IT_S:
1577 {
1578 unsigned char effectvalue = entry->effectvalue;
1579 if (sigrenderer->sigdata->flags & IT_WAS_AN_S3M) {
1580 if (effectvalue == 0)
1581 effectvalue = channel->lastDKL;
1582 channel->lastDKL = effectvalue;
1583 } else {
1584 if (effectvalue == 0)
1585 effectvalue = channel->lastS;
1586 }
1587 channel->lastS = effectvalue;
1588 switch (effectvalue >> 4) {
1589 case IT_S_PATTERN_LOOP:
1590 {
1591 unsigned char v = effectvalue & 15;
1592 if (v == 0) {
1593#ifdef BIT_ARRAY_BULLSHIT
1594 if (!channel->played_patjump)
1595 channel->played_patjump = bit_array_create(256);
1596 else {
1597 if ( channel->played_patjump_order != 0xFFFE && channel->played_patjump_order != sigrenderer->order )
1598 bit_array_merge(sigrenderer->played, channel->played_patjump, channel->played_patjump_order * 256);
1599 //if (channel->played_patjump_order != sigrenderer->order)
1600 bit_array_reset(channel->played_patjump);
1601 }
1602 channel->played_patjump_order = sigrenderer->order;
1603#endif
1604 channel->pat_loop_row = sigrenderer->processrow;
1605 } else {
1606 if (channel->pat_loop_count == 0) {
1607#ifdef BIT_ARRAY_BULLSHIT
1608 /* wft, uninitialized and no start marker yet... */
1609 if (channel->played_patjump_order == 0xFFFE) {
1610 int n;
1611 bit_array_destroy(channel->played_patjump);
1612 channel->played_patjump = bit_array_create(256);
1613 for (n = channel->pat_loop_row; n <= sigrenderer->row; n++)
1614 bit_array_clear(sigrenderer->played, sigrenderer->order * 256 + n);
1615 channel->played_patjump_order = sigrenderer->order;
1616 } else if (channel->played_patjump_order == sigrenderer->order) {
1617 bit_array_set(channel->played_patjump, sigrenderer->row);
1618 bit_array_mask(sigrenderer->played, channel->played_patjump, channel->played_patjump_order * 256);
1619 //bit_array_reset(channel->played_patjump);
1620 }
1621#endif
1622 channel->pat_loop_count = v;
1623 sigrenderer->breakrow = channel->pat_loop_row;
1624 if ((sigrenderer->sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM) {
1625 /* For XM files, if a loop occurs by itself, keep breakrow set for when the pattern ends - fun bug in FT2! */
1626 if ((sigrenderer->processrow|0xC00) < 0xFFFE) {
1627 /* Infinite pattern loops are possible, so we check whether the pattern loop we're hitting now is earlier than the last one we hit. */
1628 if (sigrenderer->processrow < channel->pat_loop_end_row)
1629 sigrenderer->processorder = 0xFFFE; /* suspect infinite loop, so trigger loop callback */
1630 else
1631 sigrenderer->processorder = 0xFFFF; /* don't trigger loop callback */
1632 channel->pat_loop_end_row = sigrenderer->processrow;
1633 sigrenderer->processrow = 0xFFFF; /* special case: don't reset breakrow or pat_loop_end_row */
1634 }
1635 } else {
1636 /* IT files do this regardless of other flow control effects seen here. */
1637 sigrenderer->processorder = 0xFFFF; /* special case: don't trigger loop callback */
1638 sigrenderer->processrow = 0xFFFE;
1639 }
1640 return 1;
1641 } else if (--channel->pat_loop_count) {
1642#ifdef BIT_ARRAY_BULLSHIT
1643 if (channel->played_patjump_order == sigrenderer->order) {
1644 bit_array_set(channel->played_patjump, sigrenderer->row);
1645 bit_array_mask(sigrenderer->played, channel->played_patjump, channel->played_patjump_order * 256);
1646 //bit_array_reset(channel->played_patjump);
1647 }
1648#endif
1649 sigrenderer->breakrow = channel->pat_loop_row;
1650 if ((sigrenderer->sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM) {
1651 /* For XM files, if a loop occurs by itself, keep breakrow set for when the pattern ends - fun bug in FT2! */
1652 if ((sigrenderer->processrow|0xC00) < 0xFFFE) {
1653 /* Infinite pattern loops are possible, so we check whether the pattern loop we're hitting now is earlier than the last one we hit. */
1654 if (sigrenderer->processrow < channel->pat_loop_end_row)
1655 sigrenderer->processorder = 0xFFFE; /* suspect infinite loop, so trigger loop callback */
1656 else
1657 sigrenderer->processorder = 0xFFFF; /* don't trigger loop callback */
1658 channel->pat_loop_end_row = sigrenderer->processrow;
1659 sigrenderer->processrow = 0xFFFF; /* special case: don't reset breakrow or pat_loop_end_row */
1660 }
1661 } else {
1662 /* IT files do this regardless of other flow control effects seen here. */
1663 sigrenderer->processorder = 0xFFFF; /* special case: don't trigger loop callback */
1664 sigrenderer->processrow = 0xFFFE;
1665 }
1666 return 1;
1667 } else if ((sigrenderer->sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM) {
1668 channel->pat_loop_end_row = 0;
1669 // TODO
1670 /* Findings:
1671 - If a pattern loop completes successfully, and then the pattern terminates, then the next pattern will start on the row corresponding to the E60.
1672 - If a pattern loop doesn't do any loops, and then the pattern terminates, then the next pattern will start on the first row.
1673 - If a break appears to the left of the pattern loop, it jumps into the relevant position in the next pattern, and that's it.
1674 - If a break appears to the right of the pattern loop, it jumps to the start of the next pattern, and that's it.
1675 - If we jump, then effect a loop using an old E60, and then the pattern ends, the next pattern starts on the row corresponding to the E60.
1676 - Theory: breakrow is not cleared when it's a pattern loop effect!
1677 */
1678 if ((sigrenderer->processrow | 0xC00) < 0xFFFE) // I have no idea if this is correct or not - FT2 is so weird :(
1679 sigrenderer->breakrow = channel->pat_loop_row; /* emulate bug in FT2 */
1680 } else
1681 channel->pat_loop_row = sigrenderer->processrow + 1;
1682#ifdef BIT_ARRAY_BULLSHIT
1683 /*channel->played_patjump_order |= 0x8000;*/
1684 if (channel->played_patjump_order == sigrenderer->order) {
1685 bit_array_destroy(channel->played_patjump);
1686 channel->played_patjump = 0;
1687 channel->played_patjump_order = 0xFFFE;
1688 }
1689 bit_array_clear(sigrenderer->played, sigrenderer->order * 256 + sigrenderer->row);
1690#endif
1691 }
1692 }
1693 break;
1694 case IT_S_PATTERN_DELAY:
1695 sigrenderer->rowcount = 1 + (effectvalue & 15);
1696 break;
1697 }
1698 }
1699 }
1700 }
1701
1702 return 0;
1703}
1704
1705
1706
1707/* This function guarantees that channel->sample will always be valid if it
1708 * is nonzero. In other words, to check if it is valid, simply check if it is
1709 * nonzero.
1710 */
1711static void instrument_to_sample(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
1712{
1713 if (sigdata->flags & IT_USE_INSTRUMENTS) {
1714 if (channel->instrument >= 1 && channel->instrument <= sigdata->n_instruments) {
1715 if (channel->note < 120) {
1716 channel->sample = sigdata->instrument[channel->instrument-1].map_sample[channel->note];
1717 channel->truenote = sigdata->instrument[channel->instrument-1].map_note[channel->note];
1718 } else
1719 channel->sample = 0;
1720 } else
1721 channel->sample = 0;
1722 } else {
1723 channel->sample = channel->instrument;
1724 channel->truenote = channel->note;
1725 }
1726 if (!(channel->sample >= 1 && channel->sample <= sigdata->n_samples && (sigdata->sample[channel->sample-1].flags & IT_SAMPLE_EXISTS) && sigdata->sample[channel->sample-1].C5_speed))
1727 channel->sample = 0;
1728}
1729
1730
1731
1732static void fix_sample_looping(IT_PLAYING *playing)
1733{
1734 if ((playing->sample->flags & (IT_SAMPLE_LOOP | IT_SAMPLE_SUS_LOOP)) ==
1735 (IT_SAMPLE_LOOP | IT_SAMPLE_SUS_LOOP)) {
1736 if (playing->resampler.dir < 0) {
1737 playing->resampler.pos = (playing->sample->sus_loop_end << 1) - 1 - playing->resampler.pos;
1738 playing->resampler.subpos ^= 65535;
1739 playing->resampler.dir = 1;
1740 }
1741
1742 playing->resampler.pos += playing->time_lost;
1743 // XXX what
1744 playing->time_lost = 0;
1745 }
1746}
1747
1748
1749
1750static void it_compatible_gxx_retrigger(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
1751{
1752 int flags = 0;
1753 if (channel->sample) {
1754 if (sigdata->flags & IT_USE_INSTRUMENTS) {
1755 if (!(channel->playing->flags & IT_PLAYING_SUSTAINOFF)) {
1756 if (channel->playing->env_instrument->volume_envelope.flags & IT_ENVELOPE_CARRY)
1757 flags |= 1;
1758 if (channel->playing->env_instrument->pan_envelope.flags & IT_ENVELOPE_CARRY)
1759 flags |= 2;
1760 if (channel->playing->env_instrument->pitch_envelope.flags & IT_ENVELOPE_CARRY)
1761 flags |= 4;
1762 }
1763 }
1764 }
1765 if (!(flags & 1)) {
1766 channel->playing->volume_envelope.next_node = 0;
1767 channel->playing->volume_envelope.tick = 0;
1768 }
1769 if (!(flags & 2)) {
1770 channel->playing->pan_envelope.next_node = 0;
1771 channel->playing->pan_envelope.tick = 0;
1772 }
1773 if (!(flags & 4)) {
1774 channel->playing->pitch_envelope.next_node = 0;
1775 channel->playing->pitch_envelope.tick = 0;
1776 }
1777 channel->playing->fadeoutcount = 1024;
1778 // Should we remove IT_PLAYING_BACKGROUND? Test with sample with sustain loop...
1779 channel->playing->flags &= ~(IT_PLAYING_BACKGROUND | IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING | IT_PLAYING_DEAD);
1780 it_playing_update_resamplers(channel->playing);
1781
1782 if (!flags && channel->sample)
1783 if (sigdata->flags & IT_USE_INSTRUMENTS)
1784 channel->playing->env_instrument = &sigdata->instrument[channel->instrument-1];
1785}
1786
1787
1788
1789static void it_note_off(IT_PLAYING *playing)
1790{
1791 if (playing) {
1792 playing->enabled_envelopes |= IT_ENV_VOLUME;
1793 playing->flags |= IT_PLAYING_BACKGROUND | IT_PLAYING_SUSTAINOFF;
1794 fix_sample_looping(playing);
1795 it_playing_update_resamplers(playing);
1796 if (playing->instrument)
1797 if ((playing->instrument->volume_envelope.flags & (IT_ENVELOPE_ON | IT_ENVELOPE_LOOP_ON)) != IT_ENVELOPE_ON)
1798 playing->flags |= IT_PLAYING_FADING;
1799 }
1800}
1801
1802
1803
1804static void xm_note_off(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
1805{
1806 if (channel->playing) {
1807 if (!channel->instrument || channel->instrument > sigdata->n_instruments ||
1808 !(sigdata->instrument[channel->instrument-1].volume_envelope.flags & IT_ENVELOPE_ON))
1809 //if (!(entry->mask & IT_ENTRY_INSTRUMENT))
1810 // dunno what that was there for ...
1811 channel->volume = 0;
1812 channel->playing->flags |= IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING;
1813 it_playing_update_resamplers(channel->playing);
1814 }
1815}
1816
1817
1818static void recalculate_it_envelope_node(IT_PLAYING_ENVELOPE *pe, IT_ENVELOPE *e)
1819{
1820 int envpos = pe->tick;
1821 unsigned int pt = e->n_nodes - 1;
1822 unsigned int i;
1823 for (i = 0; i < (unsigned int)(e->n_nodes - 1); ++i)
1824 {
1825 if (envpos <= e->node_t[i])
1826 {
1827 pt = i;
1828 break;
1829 }
1830 }
1831 pe->next_node = pt;
1832}
1833
1834
1835static void recalculate_it_envelope_nodes(IT_PLAYING *playing)
1836{
1837 recalculate_it_envelope_node(&playing->volume_envelope, &playing->env_instrument->volume_envelope);
1838 recalculate_it_envelope_node(&playing->pan_envelope, &playing->env_instrument->pitch_envelope);
1839 recalculate_it_envelope_node(&playing->pitch_envelope, &playing->env_instrument->pitch_envelope);
1840}
1841
1842
1843static void it_retrigger_note(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel)
1844{
1845 int vol_env_tick = 0;
1846 int pan_env_tick = 0;
1847 int pitch_env_tick = 0;
1848
1849 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
1850 unsigned char nna = ~0;
1851 int i, envelopes_copied = 0;
1852
1853 if (channel->playing) {
1854 if (channel->note == IT_NOTE_CUT)
1855 nna = NNA_NOTE_CUT;
1856 else if (channel->note == IT_NOTE_OFF)
1857 nna = NNA_NOTE_OFF;
1858 else if (channel->note > 120)
1859 nna = NNA_NOTE_FADE;
1860 else if (!channel->playing->instrument || (channel->playing->flags & IT_PLAYING_DEAD))
1861 nna = NNA_NOTE_CUT;
1862 else if (channel->new_note_action != 0xFF)
1863 {
1864 nna = channel->new_note_action;
1865 }
1866 else
1867 nna = channel->playing->instrument->new_note_action;
1868
1869 if (!(channel->playing->flags & IT_PLAYING_SUSTAINOFF))
1870 {
1871 if (nna != NNA_NOTE_CUT)
1872 vol_env_tick = channel->playing->volume_envelope.tick;
1873 pan_env_tick = channel->playing->pan_envelope.tick;
1874 pitch_env_tick = channel->playing->pitch_envelope.tick;
1875 envelopes_copied = 1;
1876 }
1877
1878 switch (nna) {
1879 case NNA_NOTE_CUT:
1880 channel->playing->declick_stage = 3;
1881 break;
1882 case NNA_NOTE_OFF:
1883 it_note_off(channel->playing);
1884 break;
1885 case NNA_NOTE_FADE:
1886 channel->playing->flags |= IT_PLAYING_BACKGROUND | IT_PLAYING_FADING;
1887 break;
1888 }
1889 }
1890
1891 channel->new_note_action = 0xFF;
1892
1893 if (channel->sample == 0 || channel->note > 120)
1894 return;
1895
1896 channel->destnote = IT_NOTE_OFF;
1897
1898 if (channel->playing) {
1899 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
1900 if (!sigrenderer->playing[i]) {
1901 sigrenderer->playing[i] = channel->playing;
1902 channel->playing = NULL;
1903 break;
1904 }
1905 }
1906
1907 if (sigrenderer->sigdata->flags & IT_USE_INSTRUMENTS)
1908 {
1909 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
1910 IT_PLAYING * playing = sigrenderer->playing[i];
1911 if (playing && playing->channel == channel && playing->instrument->dup_check_type) {
1912 int match = 1;
1913 switch (playing->instrument->dup_check_type)
1914 {
1915 case DCT_NOTE:
1916 match = (channel->truenote == playing->note);
1917 case DCT_SAMPLE:
1918 match = match && (channel->sample == playing->sampnum);
1919 case DCT_INSTRUMENT:
1920 match = match && (channel->instrument == playing->instnum);
1921 break;
1922 }
1923
1924 if (match)
1925 {
1926 switch (playing->instrument->dup_check_action)
1927 {
1928 case DCA_NOTE_CUT:
1929 playing->declick_stage = 3;
1930 if (channel->playing == playing) channel->playing = NULL;
1931 break;
1932 case DCA_NOTE_OFF:
1933 if (!(playing->flags & IT_PLAYING_SUSTAINOFF))
1934 it_note_off(playing);
1935 break;
1936 case DCA_NOTE_FADE:
1937 playing->flags |= IT_PLAYING_BACKGROUND | IT_PLAYING_FADING;
1938 break;
1939 }
1940 }
1941 }
1942 }
1943 }
1944
1945/** WARNING - come up with some more heuristics for replacing old notes */
1946#if 0
1947 if (channel->playing) {
1948 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
1949 if (sigrenderer->playing[i]->flags & IT_PLAYING_BACKGROUND) {
1950 write_seqtime();
1951 sequence_c(SEQUENCE_STOP_SIGNAL);
1952 sequence_c(i);
1953 channel->VChannel = &module->VChannel[i];
1954 break;
1955 }
1956 }
1957 }
1958#endif
1959 }
1960
1961 if (channel->playing)
1962 free_playing(channel->playing);
1963
1964 channel->playing = new_playing();
1965
1966 if (!channel->playing)
1967 return;
1968
1969 if (!envelopes_copied && sigdata->flags & IT_USE_INSTRUMENTS) {
1970 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
1971 IT_PLAYING * playing = sigrenderer->playing[i];
1972 if (!playing || playing->channel != channel) continue;
1973 if (playing->flags & IT_PLAYING_SUSTAINOFF) continue;
1974 if (nna != NNA_NOTE_CUT)
1975 vol_env_tick = playing->volume_envelope.tick;
1976 pan_env_tick = playing->pan_envelope.tick;
1977 pitch_env_tick = playing->pitch_envelope.tick;
1978 envelopes_copied = 1;
1979 break;
1980 }
1981 }
1982
1983 channel->playing->flags = 0;
1984 channel->playing->resampling_quality = sigrenderer->resampling_quality;
1985 channel->playing->channel = channel;
1986 channel->playing->sample = &sigdata->sample[channel->sample-1];
1987 if (sigdata->flags & IT_USE_INSTRUMENTS)
1988 channel->playing->instrument = &sigdata->instrument[channel->instrument-1];
1989 else
1990 channel->playing->instrument = NULL;
1991 channel->playing->env_instrument = channel->playing->instrument;
1992 channel->playing->sampnum = channel->sample;
1993 channel->playing->instnum = channel->instrument;
1994 channel->playing->declick_stage = 0;
1995 channel->playing->channel_volume = channel->channelvolume;
1996 channel->playing->note = channel->truenote;
1997 channel->playing->enabled_envelopes = 0;
1998 channel->playing->volume_offset = 0;
1999 channel->playing->panning_offset = 0;
2000 //channel->playing->output = channel->output;
2001 if (sigdata->flags & IT_USE_INSTRUMENTS) {
2002 IT_PLAYING * playing = channel->playing;
2003 IT_INSTRUMENT * instrument = playing->instrument;
2004 if (instrument->volume_envelope.flags & IT_ENVELOPE_ON) playing->enabled_envelopes |= IT_ENV_VOLUME;
2005 if (instrument->pan_envelope.flags & IT_ENVELOPE_ON) playing->enabled_envelopes |= IT_ENV_PANNING;
2006 if (instrument->pitch_envelope.flags & IT_ENVELOPE_ON) playing->enabled_envelopes |= IT_ENV_PITCH;
2007 if (instrument->random_volume) playing->volume_offset = (rand() % (instrument->random_volume * 2 + 1)) - instrument->random_volume;
2008 if (instrument->random_pan) playing->panning_offset = (rand() % (instrument->random_pan * 2 + 1)) - instrument->random_pan;
2009 //if (instrument->output) playing->output = instrument->output;
2010 }
2011 channel->playing->filter_cutoff = 127;
2012 channel->playing->filter_resonance = 0;
2013 channel->playing->true_filter_cutoff = 127 << 8;
2014 channel->playing->true_filter_resonance = 0;
2015 channel->playing->vibrato_speed = 0;
2016 channel->playing->vibrato_depth = 0;
2017 channel->playing->vibrato_n = 0;
2018 channel->playing->vibrato_time = 0;
2019 channel->playing->vibrato_waveform = channel->vibrato_waveform;
2020 channel->playing->tremolo_speed = 0;
2021 channel->playing->tremolo_depth = 0;
2022 channel->playing->tremolo_time = 0;
2023 channel->playing->tremolo_waveform = channel->tremolo_waveform;
2024 channel->playing->panbrello_speed = 0;
2025 channel->playing->panbrello_depth = 0;
2026 channel->playing->panbrello_time = 0;
2027 channel->playing->panbrello_waveform = channel->panbrello_waveform;
2028 channel->playing->panbrello_random = 0;
2029 channel->playing->sample_vibrato_time = 0;
2030 channel->playing->sample_vibrato_waveform = channel->playing->sample->vibrato_waveform;
2031 channel->playing->sample_vibrato_depth = 0;
2032 channel->playing->slide = 0;
2033 channel->playing->finetune = channel->playing->sample->finetune;
2034
2035 if (sigdata->flags & IT_USE_INSTRUMENTS)
2036 {
2037 if (envelopes_copied && channel->playing->env_instrument->volume_envelope.flags & IT_ENVELOPE_CARRY) {
2038 channel->playing->volume_envelope.tick = vol_env_tick;
2039 } else {
2040 channel->playing->volume_envelope.tick = 0;
2041 }
2042 if (envelopes_copied && channel->playing->env_instrument->pan_envelope.flags & IT_ENVELOPE_CARRY) {
2043 channel->playing->pan_envelope.tick = pan_env_tick;
2044 } else {
2045 channel->playing->pan_envelope.tick = 0;
2046 }
2047 if (envelopes_copied && channel->playing->env_instrument->pitch_envelope.flags & IT_ENVELOPE_CARRY) {
2048 channel->playing->pitch_envelope.tick = pitch_env_tick;
2049 } else {
2050 channel->playing->pitch_envelope.tick = 0;
2051 }
2052 recalculate_it_envelope_nodes(channel->playing);
2053 }
2054 channel->playing->fadeoutcount = 1024;
2055 it_reset_filter_state(&channel->playing->filter_state[0]);
2056 it_reset_filter_state(&channel->playing->filter_state[1]);
2057 it_playing_reset_resamplers(channel->playing, 0);
2058
2059 /** WARNING - is everything initialised? */
2060}
2061
2062
2063
2064static void get_default_volpan(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
2065{
2066 if (channel->sample == 0)
2067 return;
2068
2069 channel->volume = sigdata->sample[channel->sample-1].default_volume;
2070
2071 if (sigdata->flags & IT_WAS_AN_XM) {
2072 if (!(sigdata->flags & IT_WAS_A_MOD))
2073 channel->truepan = 32 + sigdata->sample[channel->sample-1].default_pan*64;
2074 return;
2075 }
2076
2077 {
2078 int pan = sigdata->sample[channel->sample-1].default_pan;
2079 if (pan >= 128 && pan <= 192) {
2080 channel->pan = pan - 128;
2081 return;
2082 }
2083 }
2084
2085 if (sigdata->flags & IT_USE_INSTRUMENTS) {
2086 IT_INSTRUMENT *instrument = &sigdata->instrument[channel->instrument-1];
2087 if (instrument->default_pan <= 64)
2088 channel->pan = instrument->default_pan;
2089 if (instrument->filter_cutoff >= 128)
2090 channel->filter_cutoff = instrument->filter_cutoff - 128;
2091 if (instrument->filter_resonance >= 128)
2092 channel->filter_resonance = instrument->filter_resonance - 128;
2093 }
2094}
2095
2096
2097
2098static void get_true_pan(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
2099{
2100 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
2101
2102 if (channel->sample && !IT_IS_SURROUND_SHIFTED(channel->truepan) && (sigdata->flags & IT_USE_INSTRUMENTS)) {
2103 IT_INSTRUMENT *instrument = &sigdata->instrument[channel->instrument-1];
2104 int truepan = channel->truepan;
2105 truepan += (channel->note - instrument->pp_centre) * instrument->pp_separation << (IT_ENVELOPE_SHIFT - 3);
2106 channel->truepan = (unsigned short)MID(0, truepan, 64 << IT_ENVELOPE_SHIFT);
2107 }
2108}
2109
2110
2111
2112static void post_process_it_volpan(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
2113{
2114 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
2115
2116 if (entry->mask & IT_ENTRY_VOLPAN) {
2117 if (entry->volpan <= 84) {
2118 /* Volume */
2119 /* Fine volume slide up */
2120 /* Fine volume slide down */
2121 } else if (entry->volpan <= 94) {
2122 /* Volume slide up */
2123 unsigned char v = entry->volpan - 85;
2124 if (v == 0)
2125 v = channel->lastvolslide;
2126 channel->lastvolslide = v;
2127 /* = effect Dx0 where x == entry->volpan - 85 */
2128 channel->volslide += v;
2129 } else if (entry->volpan <= 104) {
2130 /* Volume slide down */
2131 unsigned char v = entry->volpan - 95;
2132 if (v == 0)
2133 v = channel->lastvolslide;
2134 channel->lastvolslide = v;
2135 /* = effect D0x where x == entry->volpan - 95 */
2136 channel->volslide -= v;
2137 } else if (entry->volpan <= 114) {
2138 /* Portamento down */
2139 unsigned char v = (entry->volpan - 105) << 2;
2140 if (v == 0)
2141 v = channel->lastEF;
2142 channel->lastEF = v;
2143 channel->portamento -= v << 4;
2144 } else if (entry->volpan <= 124) {
2145 /* Portamento up */
2146 unsigned char v = (entry->volpan - 115) << 2;
2147 if (v == 0)
2148 v = channel->lastEF;
2149 channel->lastEF = v;
2150 channel->portamento += v << 4;
2151 } else if (entry->volpan <= 202) {
2152 /* Pan */
2153 /* Tone Portamento */
2154 } else if (entry->volpan <= 212) {
2155 /* Vibrato */
2156 /* This is unaffected by IT_OLD_EFFECTS. However, if v == 0, then any doubling of depth that happened before (with Hxy in the effect column) will be preserved. */
2157 unsigned char v = entry->volpan - 203;
2158 if (v == 0)
2159 v = channel->lastHdepth;
2160 else {
2161 v <<= 2;
2162 channel->lastHdepth = v;
2163 }
2164 if (channel->playing) {
2165 channel->playing->vibrato_speed = channel->lastHspeed;
2166 channel->playing->vibrato_depth = v;
2167 channel->playing->vibrato_n++;
2168 }
2169 }
2170 }
2171}
2172
2173
2174
2175static void it_send_midi(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel, unsigned char midi_byte)
2176{
2177 if (sigrenderer->callbacks->midi)
2178 if ((*sigrenderer->callbacks->midi)(sigrenderer->callbacks->midi_data, (int)(channel - sigrenderer->channel), midi_byte))
2179 return;
2180
2181 switch (channel->midi_state) {
2182 case 4: /* Ready to receive resonance parameter */
2183 if (midi_byte < 0x80) channel->filter_resonance = midi_byte;
2184 channel->midi_state = 0;
2185 break;
2186 case 3: /* Ready to receive cutoff parameter */
2187 if (midi_byte < 0x80) channel->filter_cutoff = midi_byte;
2188 channel->midi_state = 0;
2189 break;
2190 case 2: /* Ready for byte specifying which parameter will follow */
2191 if (midi_byte == 0) /* Cutoff */
2192 channel->midi_state = 3;
2193 else if (midi_byte == 1) /* Resonance */
2194 channel->midi_state = 4;
2195 else
2196 channel->midi_state = 0;
2197 break;
2198 default: /* Counting initial F0 bytes */
2199 switch (midi_byte) {
2200 case 0xF0:
2201 channel->midi_state++;
2202 break;
2203 case 0xFA:
2204 case 0xFC:
2205 case 0xFF:
2206 /* Reset filter parameters for all channels */
2207 {
2208 int i;
2209 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
2210 sigrenderer->channel[i].filter_cutoff = 127;
2211 sigrenderer->channel[i].filter_resonance = 0;
2212 //// should we be resetting channel[i].playing->filter_* here?
2213 }
2214 }
2215 /* Fall through */
2216 default:
2217 channel->midi_state = 0;
2218 break;
2219 }
2220 }
2221}
2222
2223
2224
2225static void xm_envelope_calculate_value(IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
2226{
2227 if (pe->next_node <= 0)
2228 pe->value = envelope->node_y[0] << IT_ENVELOPE_SHIFT;
2229 else if (pe->next_node >= envelope->n_nodes)
2230 pe->value = envelope->node_y[envelope->n_nodes-1] << IT_ENVELOPE_SHIFT;
2231 else {
2232 int ys = envelope->node_y[pe->next_node-1] << IT_ENVELOPE_SHIFT;
2233 int ts = envelope->node_t[pe->next_node-1];
2234 int te = envelope->node_t[pe->next_node];
2235
2236 if (ts == te)
2237 pe->value = ys;
2238 else {
2239 int ye = envelope->node_y[pe->next_node] << IT_ENVELOPE_SHIFT;
2240 int t = pe->tick;
2241
2242 pe->value = ys + (ye - ys) * (t - ts) / (te - ts);
2243 }
2244 }
2245}
2246
2247
2248
2249extern const char xm_convert_vibrato[];
2250
2251const char mod_convert_vibrato[] = {
2252 IT_VIBRATO_SINE,
2253 IT_VIBRATO_RAMP_UP, /* this will be inverted by IT_OLD_EFFECTS */
2254 IT_VIBRATO_XM_SQUARE,
2255 IT_VIBRATO_XM_SQUARE
2256};
2257
2258/* Returns 1 if a callback caused termination of playback. */
2259static int process_effects(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry, int ignore_cxx)
2260{
2261 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
2262 IT_PLAYING *playing;
2263 int i;
2264
2265 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
2266
2267 if (entry->mask & IT_ENTRY_EFFECT) {
2268 switch (entry->effect) {
2269/*
2270Notes about effects (as compared to other module formats)
2271
2272C This is now in *HEX*. (Used to be in decimal in ST3)
2273E/F/G/H/U You need to check whether the song uses Amiga/Linear slides.
2274H/U Vibrato in Impulse Tracker is two times finer than in
2275 any other tracker and is updated EVERY tick.
2276 If "Old Effects" is *ON*, then the vibrato is played in the
2277 normal manner (every non-row tick and normal depth)
2278E/F/G These commands ALL share the same memory.
2279Oxx Offsets to samples are to the 'xx00th' SAMPLE. (ie. for
2280 16 bit samples, the offset is xx00h*2)
2281 Oxx past the sample end will be ignored, unless "Old Effects"
2282 is ON, in which case the Oxx will play from the end of the
2283 sample.
2284Yxy This uses a table 4 times larger (hence 4 times slower) than
2285 vibrato or tremelo. If the waveform is set to random, then
2286 the 'speed' part of the command is interpreted as a delay.
2287*/
2288 case IT_SET_SPEED:
2289 if (entry->effectvalue)
2290 {
2291 /*if (entry->effectvalue == 255)
2292 if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data))
2293 return 1;*/
2294 if (sigdata->flags & IT_WAS_AN_STM) {
2295 int n = entry->effectvalue;
2296 if (n >= 32) {
2297 sigrenderer->tick = sigrenderer->speed = n;
2298 }
2299 } else {
2300 sigrenderer->tick = sigrenderer->speed = entry->effectvalue;
2301 }
2302 }
2303 else if ((sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM) {
2304#ifdef BIT_ARRAY_BULLSHIT
2305 bit_array_set(sigrenderer->played, sigrenderer->order * 256 + sigrenderer->row);
2306#endif
2307 sigrenderer->speed = 0;
2308#ifdef BIT_ARRAY_BULLSHIT
2309 sigrenderer->looped = 1;
2310#endif
2311 if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data))
2312 return 1;
2313 }
2314 break;
2315
2316 case IT_BREAK_TO_ROW:
2317 if (ignore_cxx) break;
2318 sigrenderer->breakrow = entry->effectvalue;
2319 /* XXX jump and break on the same row */
2320 if ( ( ( sigrenderer->processrow | 0xC00 ) == 0xFFFE ) &&
2321 ! ( sigrenderer->processrow & 0x400 ) ) {
2322 sigrenderer->processrow = 0xFFFE & ~0xC00;
2323 } else {
2324 sigrenderer->processorder = sigrenderer->order;
2325 sigrenderer->processrow = 0xFFFE & ~0x800;
2326 }
2327 break;
2328
2329 case IT_VOLSLIDE_VIBRATO:
2330 for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
2331 if (i < 0) playing = channel->playing;
2332 else {
2333 playing = sigrenderer->playing[i];
2334 if (!playing || playing->channel != channel) continue;
2335 }
2336 if (playing) {
2337 playing->vibrato_speed = channel->lastHspeed;
2338 playing->vibrato_depth = channel->lastHdepth;
2339 playing->vibrato_n++;
2340 }
2341 }
2342 /* Fall through and process volume slide. */
2343 case IT_VOLUME_SLIDE:
2344 case IT_VOLSLIDE_TONEPORTA:
2345 /* The tone portamento component is handled elsewhere. */
2346 {
2347 unsigned char v = entry->effectvalue;
2348 if (!(sigdata->flags & IT_WAS_A_MOD)) {
2349 if (v == 0)
2350 v = channel->lastDKL;
2351 channel->lastDKL = v;
2352 }
2353 if (!(sigdata->flags & IT_WAS_AN_XM)) {
2354 int clip = (sigdata->flags & IT_WAS_AN_S3M) ? 63 : 64;
2355 if ((v & 0x0F) == 0x0F) {
2356 if (!(v & 0xF0)) {
2357 channel->volslide = -15;
2358 channel->volume -= 15;
2359 if (channel->volume > clip) channel->volume = 0;
2360 } else {
2361 channel->volume += v >> 4;
2362 if (channel->volume > clip) channel->volume = clip;
2363 }
2364 } else if ((v & 0xF0) == 0xF0) {
2365 if (!(v & 0x0F)) {
2366 channel->volslide = 15;
2367 channel->volume += 15;
2368 if (channel->volume > clip) channel->volume = clip;
2369 } else {
2370 channel->volume -= v & 15;
2371 if (channel->volume > clip) channel->volume = 0;
2372 }
2373 } else if (!(v & 0x0F)) {
2374 channel->volslide = v >> 4;
2375 } else {
2376 channel->volslide = -(v & 15);
2377 }
2378 } else {
2379 if ((v & 0x0F) == 0) { /* Dx0 */
2380 channel->volslide = v >> 4;
2381 } else if ((v & 0xF0) == 0) { /* D0x */
2382 channel->volslide = -v;
2383 } else if ((v & 0x0F) == 0x0F) { /* DxF */
2384 channel->volume += v >> 4;
2385 if (channel->volume > 64) channel->volume = 64;
2386 } else if ((v & 0xF0) == 0xF0) { /* DFx */
2387 channel->volume -= v & 15;
2388 if (channel->volume > 64) channel->volume = 0;
2389 }
2390 }
2391 }
2392 break;
2393 case IT_XM_FINE_VOLSLIDE_DOWN:
2394 {
2395 unsigned char v = entry->effectvalue;
2396 if (v == 0)
2397 v = channel->xm_lastEB;
2398 channel->xm_lastEB = v;
2399 channel->volume -= v;
2400 if (channel->volume > 64) channel->volume = 0;
2401 }
2402 break;
2403 case IT_XM_FINE_VOLSLIDE_UP:
2404 {
2405 unsigned char v = entry->effectvalue;
2406 if (v == 0)
2407 v = channel->xm_lastEA;
2408 channel->xm_lastEA = v;
2409 channel->volume += v;
2410 if (channel->volume > 64) channel->volume = 64;
2411 }
2412 break;
2413 case IT_PORTAMENTO_DOWN:
2414 {
2415 unsigned char v = entry->effectvalue;
2416 if (sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_669)) {
2417 if (!(sigdata->flags & IT_WAS_A_MOD)) {
2418 if (v == 0xF0)
2419 v |= channel->xm_lastE2;
2420 else if (v >= 0xF0)
2421 channel->xm_lastE2 = v & 15;
2422 else if (v == 0xE0)
2423 v |= channel->xm_lastX2;
2424 else
2425 channel->xm_lastX2 = v & 15;
2426 }
2427 } else if (sigdata->flags & IT_WAS_AN_S3M) {
2428 if (v == 0)
2429 v = channel->lastDKL;
2430 channel->lastDKL = v;
2431 } else {
2432 if (v == 0)
2433 v = channel->lastEF;
2434 channel->lastEF = v;
2435 }
2436 for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
2437 if (i < 0) playing = channel->playing;
2438 else {
2439 playing = sigrenderer->playing[i];
2440 if (!playing || playing->channel != channel) continue;
2441 }
2442 if (playing) {
2443 if ((v & 0xF0) == 0xF0)
2444 playing->slide -= (v & 15) << 4;
2445 else if ((v & 0xF0) == 0xE0)
2446 playing->slide -= (v & 15) << 2;
2447 else if (i < 0 && sigdata->flags & IT_WAS_A_669)
2448 channel->portamento -= v << 3;
2449 else if (i < 0)
2450 channel->portamento -= v << 4;
2451 }
2452 }
2453 }
2454 break;
2455 case IT_PORTAMENTO_UP:
2456 {
2457 unsigned char v = entry->effectvalue;
2458 if (sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_669)) {
2459 if (!(sigdata->flags & IT_WAS_A_MOD)) {
2460 if (v == 0xF0)
2461 v |= channel->xm_lastE1;
2462 else if (v >= 0xF0)
2463 channel->xm_lastE1 = v & 15;
2464 else if (v == 0xE0)
2465 v |= channel->xm_lastX1;
2466 else
2467 channel->xm_lastX1 = v & 15;
2468 }
2469 } else if (sigdata->flags & IT_WAS_AN_S3M) {
2470 if (v == 0)
2471 v = channel->lastDKL;
2472 channel->lastDKL = v;
2473 } else {
2474 if (v == 0)
2475 v = channel->lastEF;
2476 channel->lastEF = v;
2477 }
2478 for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
2479 if (i < 0) playing = channel->playing;
2480 else {
2481 playing = sigrenderer->playing[i];
2482 if (!playing || playing->channel != channel) continue;
2483 }
2484 if (playing) {
2485 if ((v & 0xF0) == 0xF0)
2486 playing->slide += (v & 15) << 4;
2487 else if ((v & 0xF0) == 0xE0)
2488 playing->slide += (v & 15) << 2;
2489 else if (i < 0 && sigdata->flags & IT_WAS_A_669)
2490 channel->portamento += v << 3;
2491 else if (i < 0)
2492 channel->portamento += v << 4;
2493 }
2494 }
2495 }
2496 break;
2497 case IT_XM_PORTAMENTO_DOWN:
2498 {
2499 unsigned char v = entry->effectvalue;
2500 if (!(sigdata->flags & IT_WAS_A_MOD)) {
2501 if (v == 0)
2502 v = channel->lastJ;
2503 channel->lastJ = v;
2504 }
2505 if (channel->playing)
2506 channel->portamento -= v << 4;
2507 }
2508 break;
2509 case IT_XM_PORTAMENTO_UP:
2510 {
2511 unsigned char v = entry->effectvalue;
2512 if (!(sigdata->flags & IT_WAS_A_MOD)) {
2513 if (v == 0)
2514 v = channel->lastEF;
2515 channel->lastEF = v;
2516 }
2517 if (channel->playing)
2518 channel->portamento += v << 4;
2519 }
2520 break;
2521 case IT_XM_KEY_OFF:
2522 channel->key_off_count = entry->effectvalue;
2523 if (!channel->key_off_count) xm_note_off(sigdata, channel);
2524 break;
2525 case IT_VIBRATO:
2526 {
2527 if (entry->effectvalue || !(sigdata->flags & IT_WAS_A_669)) {
2528 unsigned char speed = entry->effectvalue >> 4;
2529 unsigned char depth = entry->effectvalue & 15;
2530 if (speed == 0)
2531 speed = channel->lastHspeed;
2532 channel->lastHspeed = speed;
2533 if (depth == 0)
2534 depth = channel->lastHdepth;
2535 else {
2536 if (sigdata->flags & IT_OLD_EFFECTS && !(sigdata->flags & IT_WAS_A_MOD))
2537 depth <<= 3;
2538 else
2539 depth <<= 2;
2540 channel->lastHdepth = depth;
2541 }
2542 for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
2543 if (i < 0) playing = channel->playing;
2544 else {
2545 playing = sigrenderer->playing[i];
2546 if (!playing || playing->channel != channel) continue;
2547 }
2548 if (playing) {
2549 playing->vibrato_speed = speed;
2550 playing->vibrato_depth = depth;
2551 playing->vibrato_n++;
2552 }
2553 }
2554 }
2555 }
2556 break;
2557 case IT_TREMOR:
2558 {
2559 unsigned char v = entry->effectvalue;
2560 if (v == 0) {
2561 if (sigdata->flags & IT_WAS_AN_S3M)
2562 v = channel->lastDKL;
2563 else
2564 v = channel->lastI;
2565 }
2566 else if (!(sigdata->flags & IT_OLD_EFFECTS)) {
2567 if (v & 0xF0) v -= 0x10;
2568 if (v & 0x0F) v -= 0x01;
2569 }
2570 if (sigdata->flags & IT_WAS_AN_S3M)
2571 channel->lastDKL = v;
2572 else
2573 channel->lastI = v;
2574 channel->tremor_time |= 128;
2575 }
2576 update_tremor(channel);
2577 break;
2578 case IT_ARPEGGIO:
2579 {
2580 unsigned char v = entry->effectvalue;
2581 /* XM files have no memory for arpeggio (000 = no effect)
2582 * and we use lastJ for portamento down instead.
2583 */
2584 if (!(sigdata->flags & IT_WAS_AN_XM)) {
2585 if (sigdata->flags & IT_WAS_AN_S3M) {
2586 if (v == 0)
2587 v = channel->lastDKL;
2588 channel->lastDKL = v;
2589 } else {
2590 if (v == 0)
2591 v = channel->lastJ;
2592 channel->lastJ = v;
2593 }
2594 }
2595 channel->arpeggio_offsets[0] = 0;
2596 channel->arpeggio_offsets[1] = (v & 0xF0) >> 4;
2597 channel->arpeggio_offsets[2] = (v & 0x0F);
2598 channel->arpeggio_table = (const unsigned char *)(((sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD))==IT_WAS_AN_XM) ? &arpeggio_xm : &arpeggio_mod);
2599 }
2600 break;
2601 case IT_SET_CHANNEL_VOLUME:
2602 if (sigdata->flags & IT_WAS_AN_XM)
2603 channel->volume = MIN(entry->effectvalue, 64);
2604 else if (entry->effectvalue <= 64)
2605 channel->channelvolume = entry->effectvalue;
2606#ifdef VOLUME_OUT_OF_RANGE_SETS_MAXIMUM
2607 else
2608 channel->channelvolume = 64;
2609#endif
2610 if (channel->playing)
2611 channel->playing->channel_volume = channel->channelvolume;
2612 break;
2613 case IT_CHANNEL_VOLUME_SLIDE:
2614 {
2615 unsigned char v = entry->effectvalue;
2616 if (v == 0)
2617 v = channel->lastN;
2618 channel->lastN = v;
2619 if ((v & 0x0F) == 0) { /* Nx0 */
2620 channel->channelvolslide = v >> 4;
2621 } else if ((v & 0xF0) == 0) { /* N0x */
2622 channel->channelvolslide = -v;
2623 } else {
2624 if ((v & 0x0F) == 0x0F) { /* NxF */
2625 channel->channelvolume += v >> 4;
2626 if (channel->channelvolume > 64) channel->channelvolume = 64;
2627 } else if ((v & 0xF0) == 0xF0) { /* NFx */
2628 channel->channelvolume -= v & 15;
2629 if (channel->channelvolume > 64) channel->channelvolume = 0;
2630 } else
2631 break;
2632 if (channel->playing)
2633 channel->playing->channel_volume = channel->channelvolume;
2634 }
2635 }
2636 break;
2637 case IT_SET_SAMPLE_OFFSET:
2638 {
2639 unsigned char v = entry->effectvalue;
2640 /*if (sigdata->flags & IT_WAS_A_MOD) {
2641 if (v == 0) break;
2642 } else*/ {
2643 if (v == 0)
2644 v = channel->lastO;
2645 channel->lastO = v;
2646 }
2647 /* Note: we set the offset even if tone portamento is
2648 * specified. Impulse Tracker does the same.
2649 */
2650 if (entry->mask & IT_ENTRY_NOTE) {
2651 if (channel->playing) {
2652 int offset = ((int)channel->high_offset << 16) | ((int)v << 8);
2653 IT_PLAYING *playing = channel->playing;
2654 IT_SAMPLE *sample = playing->sample;
2655 int end;
2656 if ((sample->flags & IT_SAMPLE_SUS_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF))
2657 end = (int)sample->sus_loop_end;
2658 else if (sample->flags & IT_SAMPLE_LOOP)
2659 end = (int)sample->loop_end;
2660 else {
2661 end = (int)sample->length;
2662 if ( sigdata->flags & IT_WAS_PROCESSED && end > 64 ) // XXX bah damn LPC and edge case modules
2663 end -= 64;
2664 }
2665 if ((sigdata->flags & IT_WAS_A_PTM) && (sample->flags & IT_SAMPLE_16BIT))
2666 offset >>= 1;
2667 if (offset < end) {
2668 it_playing_reset_resamplers(playing, offset);
2669 playing->declick_stage = 0;
2670 } else if (sigdata->flags & IT_OLD_EFFECTS) {
2671 it_playing_reset_resamplers(playing, end);
2672 playing->declick_stage = 0;
2673 }
2674 }
2675 }
2676 }
2677 break;
2678 case IT_PANNING_SLIDE:
2679 /** JULIEN: guess what? the docs are wrong! (how unusual ;)
2680 * Pxy seems to memorize its previous value... and there
2681 * might be other mistakes like that... (sigh!)
2682 */
2683 /** ENTHEH: umm... but... the docs say that Pxy memorises its
2684 * value... don't they? :o
2685 */
2686 {
2687 unsigned char v = entry->effectvalue;
2688 int p = channel->truepan;
2689 if (sigdata->flags & IT_WAS_AN_XM)
2690 {
2691 if (IT_IS_SURROUND(channel->pan))
2692 {
2693 channel->pan = 32;
2694 p = 32 + 128 * 64;
2695 }
2696 p >>= 6;
2697 }
2698 else {
2699 if (IT_IS_SURROUND(channel->pan)) p = 32 << 8;
2700 p = (p + 128) >> 8;
2701 channel->pan = p;
2702 }
2703 if (v == 0)
2704 v = channel->lastP;
2705 channel->lastP = v;
2706 if ((v & 0x0F) == 0) { /* Px0 */
2707 channel->panslide = -(v >> 4);
2708 } else if ((v & 0xF0) == 0) { /* P0x */
2709 channel->panslide = v;
2710 } else if ((v & 0x0F) == 0x0F) { /* PxF */
2711 p -= v >> 4;
2712 } else if ((v & 0xF0) == 0xF0) { /* PFx */
2713 p += v & 15;
2714 }
2715 if (sigdata->flags & IT_WAS_AN_XM)
2716 channel->truepan = 32 + MID(0, p, 255) * 64;
2717 else {
2718 if (p < 0) p = 0;
2719 else if (p > 64) p = 64;
2720 channel->pan = p;
2721 channel->truepan = p << 8;
2722 }
2723 }
2724 break;
2725 case IT_RETRIGGER_NOTE:
2726 {
2727 unsigned char v = entry->effectvalue;
2728 if (sigdata->flags & IT_WAS_AN_XM) {
2729 if ((v & 0x0F) == 0) v |= channel->lastQ & 0x0F;
2730 if ((v & 0xF0) == 0) v |= channel->lastQ & 0xF0;
2731 channel->lastQ = v;
2732 } else if (sigdata->flags & IT_WAS_AN_S3M) {
2733 if (v == 0)
2734 v = channel->lastDKL;
2735 channel->lastDKL = v;
2736 } else {
2737 if (v == 0)
2738 v = channel->lastQ;
2739 channel->lastQ = v;
2740 }
2741 if ((v & 0x0F) == 0) v |= 0x01;
2742 channel->retrig = v;
2743 if (entry->mask & IT_ENTRY_NOTE) {
2744 channel->retrig_tick = v & 0x0F;
2745 /* Emulate a bug */
2746 if (sigdata->flags & IT_WAS_AN_XM)
2747 update_retrig(sigrenderer, channel);
2748 } else
2749 update_retrig(sigrenderer, channel);
2750 }
2751 break;
2752 case IT_XM_RETRIGGER_NOTE:
2753 channel->retrig_tick = channel->xm_retrig = entry->effectvalue;
2754 if (entry->effectvalue == 0)
2755 if (channel->playing) {
2756 it_playing_reset_resamplers(channel->playing, 0);
2757 channel->playing->declick_stage = 0;
2758 }
2759 break;
2760 case IT_TREMOLO:
2761 {
2762 unsigned char speed, depth;
2763 if (sigdata->flags & IT_WAS_AN_S3M) {
2764 unsigned char v = entry->effectvalue;
2765 if (v == 0)
2766 v = channel->lastDKL;
2767 channel->lastDKL = v;
2768 speed = v >> 4;
2769 depth = v & 15;
2770 } else {
2771 speed = entry->effectvalue >> 4;
2772 depth = entry->effectvalue & 15;
2773 if (speed == 0)
2774 speed = channel->lastRspeed;
2775 channel->lastRspeed = speed;
2776 if (depth == 0)
2777 depth = channel->lastRdepth;
2778 channel->lastRdepth = depth;
2779 }
2780 for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
2781 if (i < 0) playing = channel->playing;
2782 else {
2783 playing = sigrenderer->playing[i];
2784 if (!playing || playing->channel != channel) continue;
2785 }
2786 if (playing) {
2787 playing->tremolo_speed = speed;
2788 playing->tremolo_depth = depth;
2789 }
2790 }
2791 }
2792 break;
2793 case IT_S:
2794 {
2795 /* channel->lastS was set in update_pattern_variables(). */
2796 unsigned char effectvalue = channel->lastS;
2797 switch (effectvalue >> 4) {
2798 //case IT_S_SET_FILTER:
2799 /* Waveforms for commands S3x, S4x and S5x:
2800 * 0: Sine wave
2801 * 1: Ramp down
2802 * 2: Square wave
2803 * 3: Random wave
2804 */
2805 case IT_S_SET_GLISSANDO_CONTROL:
2806 channel->glissando = effectvalue & 15;
2807 break;
2808
2809 case IT_S_FINETUNE:
2810 if (channel->playing) {
2811 channel->playing->finetune = ((int)(effectvalue & 15) - 8) << 5;
2812 }
2813 break;
2814
2815 case IT_S_SET_VIBRATO_WAVEFORM:
2816 {
2817 int waveform = effectvalue & 3;
2818 if (sigdata->flags & IT_WAS_A_MOD) waveform = mod_convert_vibrato[waveform];
2819 else if (sigdata->flags & IT_WAS_AN_XM) waveform = xm_convert_vibrato[waveform];
2820 channel->vibrato_waveform = waveform;
2821 if (channel->playing) {
2822 channel->playing->vibrato_waveform = waveform;
2823 if (!(effectvalue & 4))
2824 channel->playing->vibrato_time = 0;
2825 }
2826 }
2827 break;
2828 case IT_S_SET_TREMOLO_WAVEFORM:
2829 {
2830 int waveform = effectvalue & 3;
2831 if (sigdata->flags & IT_WAS_A_MOD) waveform = mod_convert_vibrato[waveform];
2832 else if (sigdata->flags & IT_WAS_AN_XM) waveform = xm_convert_vibrato[waveform];
2833 channel->tremolo_waveform = waveform;
2834 if (channel->playing) {
2835 channel->playing->tremolo_waveform = waveform;
2836 if (!(effectvalue & 4))
2837 channel->playing->tremolo_time = 0;
2838 }
2839 }
2840 break;
2841 case IT_S_SET_PANBRELLO_WAVEFORM:
2842 channel->panbrello_waveform = effectvalue & 3;
2843 if (channel->playing) {
2844 channel->playing->panbrello_waveform = effectvalue & 3;
2845 if (!(effectvalue & 4))
2846 channel->playing->panbrello_time = 0;
2847 }
2848 break;
2849
2850 case IT_S_FINE_PATTERN_DELAY:
2851 sigrenderer->tick += effectvalue & 15;
2852 break;
2853#if 1
2854 case IT_S7:
2855 {
2856 if (sigrenderer->sigdata->flags & IT_USE_INSTRUMENTS)
2857 {
2858 int i;
2859 switch (effectvalue & 15)
2860 {
2861 case 0: /* cut background notes */
2862 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
2863 {
2864 IT_PLAYING * playing = sigrenderer->playing[i];
2865 if (playing && channel == playing->channel)
2866 {
2867 playing->declick_stage = 3;
2868 if (channel->playing == playing) channel->playing = NULL;
2869 }
2870 }
2871 break;
2872 case 1: /* release background notes */
2873 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
2874 {
2875 IT_PLAYING * playing = sigrenderer->playing[i];
2876 if (playing && channel == playing->channel && !(playing->flags & IT_PLAYING_SUSTAINOFF))
2877 {
2878 it_note_off(playing);
2879 }
2880 }
2881 break;
2882 case 2: /* fade background notes */
2883 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
2884 {
2885 IT_PLAYING * playing = sigrenderer->playing[i];
2886 if (playing && channel == playing->channel)
2887 {
2888 //playing->flags &= IT_PLAYING_SUSTAINOFF;
2889 playing->flags |= IT_PLAYING_FADING;
2890 }
2891 }
2892 break;
2893 case 3:
2894 channel->new_note_action = NNA_NOTE_CUT;
2895 break;
2896 case 4:
2897 channel->new_note_action = NNA_NOTE_CONTINUE;
2898 break;
2899 case 5:
2900 channel->new_note_action = NNA_NOTE_OFF;
2901 break;
2902 case 6:
2903 channel->new_note_action = NNA_NOTE_FADE;
2904 break;
2905
2906 case 7:
2907 if (channel->playing)
2908 channel->playing->enabled_envelopes &= ~IT_ENV_VOLUME;
2909 break;
2910 case 8:
2911 if (channel->playing)
2912 channel->playing->enabled_envelopes |= IT_ENV_VOLUME;
2913 break;
2914
2915 case 9:
2916 if (channel->playing)
2917 channel->playing->enabled_envelopes &= ~IT_ENV_PANNING;
2918 break;
2919 case 10:
2920 if (channel->playing)
2921 channel->playing->enabled_envelopes |= IT_ENV_PANNING;
2922 break;
2923
2924 case 11:
2925 if (channel->playing)
2926 channel->playing->enabled_envelopes &= ~IT_ENV_PITCH;
2927 break;
2928 case 12:
2929 if (channel->playing)
2930 channel->playing->enabled_envelopes |= IT_ENV_PITCH;
2931 break;
2932 }
2933 }
2934 }
2935 break;
2936#endif
2937 case IT_S_SET_PAN:
2938 //ASSERT(!(sigdata->flags & IT_WAS_AN_XM));
2939 channel->pan =
2940 ((effectvalue & 15) << 2) |
2941 ((effectvalue & 15) >> 2);
2942 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
2943
2944 if (channel->playing)
2945 channel->playing->panbrello_depth = 0;
2946 break;
2947 case IT_S_SET_SURROUND_SOUND:
2948 if ((effectvalue & 15) == 15) {
2949 if (channel->playing && channel->playing->sample &&
2950 !(channel->playing->sample->flags & (IT_SAMPLE_LOOP | IT_SAMPLE_SUS_LOOP))) {
2951 channel->playing->flags |= IT_PLAYING_REVERSE;
2952 it_playing_reset_resamplers( channel->playing, channel->playing->sample->length - 1 );
2953 }
2954 } else if ((effectvalue & 15) == 1) {
2955 channel->pan = IT_SURROUND;
2956 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
2957 }
2958 if (channel->playing)
2959 channel->playing->panbrello_depth = 0;
2960 break;
2961 case IT_S_SET_HIGH_OFFSET:
2962 channel->high_offset = effectvalue & 15;
2963 break;
2964 //case IT_S_PATTERN_LOOP:
2965 case IT_S_DELAYED_NOTE_CUT:
2966 channel->note_cut_count = effectvalue & 15;
2967 if (!channel->note_cut_count) {
2968 if (sigdata->flags & (IT_WAS_AN_XM | IT_WAS_A_PTM))
2969 channel->volume = 0;
2970 else
2971 channel->note_cut_count = 1;
2972 }
2973 break;
2974 case IT_S_SET_MIDI_MACRO:
2975 if ((sigdata->flags & (IT_WAS_AN_XM | IT_WAS_A_MOD)) == (IT_WAS_AN_XM | IT_WAS_A_MOD)) {
2976 channel->inv_loop_speed = effectvalue & 15;
2977 update_invert_loop(channel, channel->playing ? channel->playing->sample : NULL);
2978 } else channel->SFmacro = effectvalue & 15;
2979 break;
2980 }
2981 }
2982 break;
2983 case IT_SET_SONG_TEMPO:
2984 {
2985 unsigned char v = entry->effectvalue;
2986 if (v == 0)
2987 v = channel->lastW;
2988 channel->lastW = v;
2989 if (v < 0x10)
2990 sigrenderer->temposlide = -v;
2991 else if (v < 0x20)
2992 sigrenderer->temposlide = v & 15;
2993 else
2994 sigrenderer->tempo = v;
2995 }
2996 break;
2997 case IT_FINE_VIBRATO:
2998 {
2999 unsigned char speed = entry->effectvalue >> 4;
3000 unsigned char depth = entry->effectvalue & 15;
3001 if (speed == 0)
3002 speed = channel->lastHspeed;
3003 channel->lastHspeed = speed;
3004 if (depth == 0)
3005 depth = channel->lastHdepth;
3006 else {
3007 if (sigdata->flags & IT_OLD_EFFECTS)
3008 depth <<= 1;
3009 channel->lastHdepth = depth;
3010 }
3011 for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
3012 if (i < 0) playing = channel->playing;
3013 else {
3014 playing = sigrenderer->playing[i];
3015 if (!playing || playing->channel != channel) continue;
3016 }
3017 if (playing) {
3018 playing->vibrato_speed = speed;
3019 playing->vibrato_depth = depth;
3020 playing->vibrato_n++;
3021 }
3022 }
3023 }
3024 break;
3025 case IT_SET_GLOBAL_VOLUME:
3026 if ((sigdata->flags & IT_WAS_AN_S3M) && (entry->effectvalue > 64))
3027 break;
3028 if (entry->effectvalue <= 128)
3029 sigrenderer->globalvolume = entry->effectvalue;
3030#ifdef VOLUME_OUT_OF_RANGE_SETS_MAXIMUM
3031 else
3032 sigrenderer->globalvolume = 128;
3033#endif
3034 break;
3035 case IT_GLOBAL_VOLUME_SLIDE:
3036 {
3037 unsigned char v = entry->effectvalue;
3038 if (v == 0)
3039 v = channel->lastW;
3040 channel->lastW = v;
3041 if ((v & 0x0F) == 0) { /* Wx0 */
3042 sigrenderer->globalvolslide =
3043 (sigdata->flags & IT_WAS_AN_XM) ? (v >> 4)*2 : (v >> 4);
3044 } else if ((v & 0xF0) == 0) { /* W0x */
3045 sigrenderer->globalvolslide =
3046 (sigdata->flags & IT_WAS_AN_XM) ? (-v)*2 : (-v);
3047 } else if ((v & 0x0F) == 0x0F) { /* WxF */
3048 sigrenderer->globalvolume += v >> 4;
3049 if (sigrenderer->globalvolume > 128) sigrenderer->globalvolume = 128;
3050 } else if ((v & 0xF0) == 0xF0) { /* WFx */
3051 sigrenderer->globalvolume -= v & 15;
3052 if (sigrenderer->globalvolume > 128) sigrenderer->globalvolume = 0;
3053 }
3054 }
3055 break;
3056 case IT_SET_PANNING:
3057 if (sigdata->flags & IT_WAS_AN_XM) {
3058 channel->truepan = 32 + entry->effectvalue*64;
3059 } else {
3060 if (sigdata->flags & IT_WAS_AN_S3M)
3061 channel->pan = (entry->effectvalue + 1) >> 1;
3062 else
3063 channel->pan = (entry->effectvalue + 2) >> 2;
3064 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
3065 }
3066 if (channel->playing)
3067 channel->playing->panbrello_depth = 0;
3068 break;
3069 case IT_PANBRELLO:
3070 {
3071 unsigned char speed = entry->effectvalue >> 4;
3072 unsigned char depth = entry->effectvalue & 15;
3073 if (speed == 0)
3074 speed = channel->lastYspeed;
3075 channel->lastYspeed = speed;
3076 if (depth == 0)
3077 depth = channel->lastYdepth;
3078 channel->lastYdepth = depth;
3079 if (channel->playing) {
3080 channel->playing->panbrello_speed = speed;
3081 channel->playing->panbrello_depth = depth;
3082 }
3083 }
3084 break;
3085 case IT_MIDI_MACRO:
3086 {
3087 const IT_MIDI *midi = sigdata->midi ? sigdata->midi : &default_midi;
3088 if (entry->effectvalue >= 0x80) {
3089 int n = midi->Zmacrolen[entry->effectvalue-0x80];
3090 int i;
3091 for (i = 0; i < n; i++)
3092 it_send_midi(sigrenderer, channel, midi->Zmacro[entry->effectvalue-0x80][i]);
3093 } else {
3094 int n = midi->SFmacrolen[channel->SFmacro];
3095 int i, j;
3096 for (i = 0, j = 1; i < n; i++, j <<= 1)
3097 it_send_midi(sigrenderer, channel,
3098 (unsigned char)(midi->SFmacroz[channel->SFmacro] & j ?
3099 entry->effectvalue : midi->SFmacro[channel->SFmacro][i]));
3100 }
3101 }
3102 break;
3103 case IT_XM_SET_ENVELOPE_POSITION:
3104 if (channel->playing && channel->playing->env_instrument) {
3105 IT_ENVELOPE *envelope = &channel->playing->env_instrument->volume_envelope;
3106 if (envelope->flags & IT_ENVELOPE_ON) {
3107 IT_PLAYING_ENVELOPE *pe = &channel->playing->volume_envelope;
3108 pe->tick = entry->effectvalue;
3109 if (pe->tick >= envelope->node_t[envelope->n_nodes-1])
3110 pe->tick = envelope->node_t[envelope->n_nodes-1];
3111 pe->next_node = 0;
3112 while (pe->tick > envelope->node_t[pe->next_node]) pe->next_node++;
3113 xm_envelope_calculate_value(envelope, pe);
3114 }
3115 }
3116 break;
3117
3118 /* uggly plain portamento for now */
3119 case IT_PTM_NOTE_SLIDE_DOWN:
3120 case IT_PTM_NOTE_SLIDE_DOWN_RETRIG:
3121 {
3122 channel->toneslide_retrig = (entry->effect == IT_PTM_NOTE_SLIDE_DOWN_RETRIG);
3123
3124 if (channel->ptm_last_toneslide) {
3125 channel->toneslide_tick = channel->last_toneslide_tick;
3126
3127 if (--channel->toneslide_tick == 0) {
3128 channel->truenote += channel->toneslide;
3129 if (channel->truenote >= 120) {
3130 if (channel->toneslide < 0) channel->truenote = 0;
3131 else channel->truenote = 119;
3132 }
3133 channel->note += channel->toneslide;
3134 if (channel->note >= 120) {
3135 if (channel->toneslide < 0) channel->note = 0;
3136 else channel->note = 119;
3137 }
3138
3139 if (channel->playing) {
3140 if (channel->sample) channel->playing->note = channel->truenote;
3141 else channel->playing->note = channel->note;
3142 it_playing_reset_resamplers(channel->playing, 0);
3143 channel->playing->declick_stage = 0;
3144 }
3145 }
3146 }
3147
3148 channel->ptm_last_toneslide = 0;
3149
3150 channel->toneslide = -(entry->effectvalue & 15);
3151 channel->ptm_toneslide = (entry->effectvalue & 0xF0) >> 4;
3152 channel->toneslide_tick += channel->ptm_toneslide;
3153 }
3154 break;
3155 case IT_PTM_NOTE_SLIDE_UP:
3156 case IT_PTM_NOTE_SLIDE_UP_RETRIG:
3157 {
3158 channel->toneslide_retrig = (entry->effect == IT_PTM_NOTE_SLIDE_UP_RETRIG);
3159
3160 if (channel->ptm_last_toneslide) {
3161 channel->toneslide_tick = channel->last_toneslide_tick;
3162
3163 if (--channel->toneslide_tick == 0) {
3164 channel->truenote += channel->toneslide;
3165 if (channel->truenote >= 120) {
3166 if (channel->toneslide < 0) channel->truenote = 0;
3167 else channel->truenote = 119;
3168 }
3169 channel->note += channel->toneslide;
3170 if (channel->note >= 120) {
3171 if (channel->toneslide < 0) channel->note = 0;
3172 else channel->note = 119;
3173 }
3174
3175 if (channel->playing) {
3176 if (channel->sample) channel->playing->note = channel->truenote;
3177 else channel->playing->note = channel->note;
3178 it_playing_reset_resamplers(channel->playing, 0);
3179 channel->playing->declick_stage = 0;
3180 }
3181 }
3182 }
3183
3184 channel->ptm_last_toneslide = 0;
3185
3186 channel->toneslide = -(entry->effectvalue & 15);
3187 channel->ptm_toneslide = (entry->effectvalue & 0xF0) >> 4;
3188 channel->toneslide_tick += channel->ptm_toneslide;
3189 }
3190 break;
3191
3192 case IT_OKT_NOTE_SLIDE_DOWN:
3193 case IT_OKT_NOTE_SLIDE_DOWN_ROW:
3194 channel->toneslide = -entry->effectvalue;
3195 channel->okt_toneslide = (entry->effect == IT_OKT_NOTE_SLIDE_DOWN) ? 255 : 1;
3196 break;
3197
3198 case IT_OKT_NOTE_SLIDE_UP:
3199 case IT_OKT_NOTE_SLIDE_UP_ROW:
3200 channel->toneslide = entry->effectvalue;
3201 channel->okt_toneslide = (entry->effect == IT_OKT_NOTE_SLIDE_UP) ? 255 : 1;
3202 break;
3203
3204 case IT_OKT_ARPEGGIO_3:
3205 case IT_OKT_ARPEGGIO_4:
3206 case IT_OKT_ARPEGGIO_5:
3207 {
3208 channel->arpeggio_offsets[0] = 0;
3209 channel->arpeggio_offsets[1] = -(entry->effectvalue >> 4);
3210 channel->arpeggio_offsets[2] = entry->effectvalue & 0x0F;
3211
3212 switch (entry->effect)
3213 {
3214 case IT_OKT_ARPEGGIO_3:
3215 channel->arpeggio_table = (const unsigned char *)&arpeggio_okt_3;
3216 break;
3217
3218 case IT_OKT_ARPEGGIO_4:
3219 channel->arpeggio_table = (const unsigned char *)&arpeggio_okt_4;
3220 break;
3221
3222 case IT_OKT_ARPEGGIO_5:
3223 channel->arpeggio_table = (const unsigned char *)&arpeggio_okt_5;
3224 break;
3225 }
3226 }
3227 break;
3228
3229 case IT_OKT_VOLUME_SLIDE_DOWN:
3230 if ( entry->effectvalue <= 16 ) channel->volslide = -entry->effectvalue;
3231 else
3232 {
3233 channel->volume -= entry->effectvalue - 16;
3234 if (channel->volume > 64) channel->volume = 0;
3235 }
3236 break;
3237
3238 case IT_OKT_VOLUME_SLIDE_UP:
3239 if ( entry->effectvalue <= 16 ) channel->volslide = entry->effectvalue;
3240 else
3241 {
3242 channel->volume += entry->effectvalue - 16;
3243 if (channel->volume > 64) channel->volume = 64;
3244 }
3245 break;
3246 }
3247 }
3248
3249 if (!(sigdata->flags & IT_WAS_AN_XM))
3250 post_process_it_volpan(sigrenderer, entry);
3251
3252 return 0;
3253}
3254
3255
3256
3257static int process_it_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
3258{
3259 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
3260 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
3261
3262 // When tone portamento and instrument are specified:
3263 // If Gxx is off:
3264 // - same sample, do nothing but portamento
3265 // - diff sample, retrigger all but keep current note+slide + do porta
3266 // - if instrument is invalid, nothing; if sample is invalid, cut
3267 // If Gxx is on:
3268 // - same sample or new sample invalid, retrigger envelopes and initialise note value for portamento to 'seek' to
3269 // - diff sample/inst, start using new envelopes
3270 // When tone portamento is specified alone, sample won't change.
3271 // TODO: consider what happens with instrument alone after all this...
3272
3273 if (entry->mask & (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) {
3274 if (entry->mask & IT_ENTRY_INSTRUMENT)
3275 channel->instrument = entry->instrument;
3276 instrument_to_sample(sigdata, channel);
3277 if (channel->note <= 120) {
3278 if ((sigdata->flags & IT_USE_INSTRUMENTS) && channel->sample == 0)
3279 it_retrigger_note(sigrenderer, channel); /* Stop the note */ /*return 1;*/
3280 if (entry->mask & IT_ENTRY_INSTRUMENT)
3281 get_default_volpan(sigdata, channel);
3282 } else
3283 it_retrigger_note(sigrenderer, channel); /* Stop the note */
3284 }
3285
3286 /** WARNING: This is not ideal, since channel->playing might not get allocated owing to lack of memory... */
3287 if (((entry->mask & IT_ENTRY_VOLPAN) && entry->volpan >= 193 && entry->volpan <= 202) ||
3288 ((entry->mask & IT_ENTRY_EFFECT) && (entry->effect == IT_TONE_PORTAMENTO || entry->effect == IT_VOLSLIDE_TONEPORTA)))
3289 {
3290 if (channel->playing && (entry->mask & IT_ENTRY_INSTRUMENT)) {
3291 if (sigdata->flags & IT_COMPATIBLE_GXX)
3292 it_compatible_gxx_retrigger(sigdata, channel);
3293 else if ((!(sigdata->flags & IT_USE_INSTRUMENTS) ||
3294 (channel->instrument >= 1 && channel->instrument <= sigdata->n_instruments)) &&
3295 channel->sample != channel->playing->sampnum)
3296 {
3297 unsigned char note = channel->playing->note;
3298 int slide = channel->playing->slide;
3299 it_retrigger_note(sigrenderer, channel);
3300 if (channel->playing) {
3301 channel->playing->note = note;
3302 channel->playing->slide = slide;
3303 // Should we be preserving sample_vibrato_time? depth?
3304 }
3305 }
3306 }
3307
3308 channel->toneporta = 0;
3309
3310 if ((entry->mask & IT_ENTRY_VOLPAN) && entry->volpan >= 193 && entry->volpan <= 202) {
3311 /* Tone Portamento in the volume column */
3312 static const unsigned char slidetable[] = {0, 1, 4, 8, 16, 32, 64, 96, 128, 255};
3313 unsigned char v = slidetable[entry->volpan - 193];
3314 if (sigdata->flags & IT_COMPATIBLE_GXX) {
3315 if (v == 0)
3316 v = channel->lastG;
3317 channel->lastG = v;
3318 } else {
3319 if (v == 0)
3320 v = channel->lastEF;
3321 channel->lastEF = v;
3322 }
3323 channel->toneporta += v << 4;
3324 }
3325
3326 if ((entry->mask & IT_ENTRY_EFFECT) && (entry->effect == IT_TONE_PORTAMENTO || entry->effect == IT_VOLSLIDE_TONEPORTA)) {
3327 /* Tone Portamento in the effect column */
3328 unsigned char v;
3329 if (entry->effect == IT_TONE_PORTAMENTO)
3330 v = entry->effectvalue;
3331 else
3332 v = 0;
3333 if (sigdata->flags & IT_COMPATIBLE_GXX) {
3334 if (v == 0)
3335 v = channel->lastG;
3336 channel->lastG = v;
3337 } else {
3338 if (v == 0 && !(sigdata->flags & IT_WAS_A_669))
3339 v = channel->lastEF;
3340 channel->lastEF = v;
3341 }
3342 channel->toneporta += v << 4;
3343 }
3344
3345 if ((entry->mask & IT_ENTRY_NOTE) || ((sigdata->flags & IT_COMPATIBLE_GXX) && (entry->mask & IT_ENTRY_INSTRUMENT))) {
3346 if (channel->note <= 120) {
3347 if (channel->sample)
3348 channel->destnote = channel->truenote;
3349 else
3350 channel->destnote = channel->note;
3351 }
3352 }
3353
3354 if (channel->playing) goto skip_start_note;
3355 }
3356
3357 if ((entry->mask & IT_ENTRY_NOTE) ||
3358 ((entry->mask & IT_ENTRY_INSTRUMENT) && (!channel->playing || entry->instrument != channel->playing->instnum)))
3359 {
3360 if (channel->note <= 120) {
3361 get_true_pan(sigdata, channel);
3362 if ((entry->mask & IT_ENTRY_NOTE) || !(sigdata->flags & (IT_WAS_AN_S3M|IT_WAS_A_PTM)))
3363 it_retrigger_note(sigrenderer, channel);
3364 }
3365 }
3366
3367 skip_start_note:
3368
3369 if (entry->mask & IT_ENTRY_VOLPAN) {
3370 if (entry->volpan <= 64) {
3371 /* Volume */
3372 channel->volume = entry->volpan;
3373 } else if (entry->volpan <= 74) {
3374 /* Fine volume slide up */
3375 unsigned char v = entry->volpan - 65;
3376 if (v == 0)
3377 v = channel->lastvolslide;
3378 channel->lastvolslide = v;
3379 /* = effect DxF where x == entry->volpan - 65 */
3380 channel->volume += v;
3381 if (channel->volume > 64) channel->volume = 64;
3382 } else if (entry->volpan <= 84) {
3383 /* Fine volume slide down */
3384 unsigned char v = entry->volpan - 75;
3385 if (v == 0)
3386 v = channel->lastvolslide;
3387 channel->lastvolslide = v;
3388 /* = effect DFx where x == entry->volpan - 75 */
3389 channel->volume -= v;
3390 if (channel->volume > 64) channel->volume = 0;
3391 } else if (entry->volpan < 128) {
3392 /* Volume slide up */
3393 /* Volume slide down */
3394 /* Portamento down */
3395 /* Portamento up */
3396 } else if (entry->volpan <= 192) {
3397 /* Pan */
3398 channel->pan = entry->volpan - 128;
3399 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
3400 }
3401 /* else */
3402 /* Tone Portamento */
3403 /* Vibrato */
3404 }
3405 return 0;
3406}
3407
3408
3409
3410static void retrigger_xm_envelopes(IT_PLAYING *playing)
3411{
3412 playing->volume_envelope.next_node = 0;
3413 playing->volume_envelope.tick = -1;
3414 playing->pan_envelope.next_node = 0;
3415 playing->pan_envelope.tick = -1;
3416 playing->fadeoutcount = 1024;
3417}
3418
3419
3420
3421static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
3422{
3423 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
3424 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
3425 IT_PLAYING * playing = NULL;
3426
3427 if (entry->mask & IT_ENTRY_INSTRUMENT) {
3428 int oldsample = channel->sample;
3429 channel->inv_loop_offset = 0;
3430 channel->instrument = entry->instrument;
3431 instrument_to_sample(sigdata, channel);
3432 if (channel->playing &&
3433 !((entry->mask & IT_ENTRY_NOTE) && entry->note >= 120) &&
3434 !((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_XM_KEY_OFF && entry->effectvalue == 0)) {
3435 playing = dup_playing(channel->playing, channel, channel);
3436 if (!playing) return;
3437 if (!(sigdata->flags & IT_WAS_A_MOD)) {
3438 /* Retrigger vol/pan envelopes if enabled, and cancel fadeout.
3439 * Also reset vol/pan to that of _original_ instrument.
3440 */
3441 channel->playing->flags &= ~(IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING);
3442 it_playing_update_resamplers(channel->playing);
3443
3444 channel->volume = channel->playing->sample->default_volume;
3445 channel->truepan = 32 + channel->playing->sample->default_pan*64;
3446
3447 retrigger_xm_envelopes(channel->playing);
3448 } else {
3449 /* Switch if sample changed */
3450 if (oldsample != channel->sample) {
3451 int i;
3452 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
3453 if (!sigrenderer->playing[i]) {
3454 channel->playing->declick_stage = 3;
3455 sigrenderer->playing[i] = channel->playing;
3456 channel->playing = NULL;
3457 break;
3458 }
3459 }
3460
3461 if (!channel->sample) {
3462 if (channel->playing)
3463 {
3464 free_playing(channel->playing);
3465 channel->playing = NULL;
3466 }
3467 } else {
3468 if (channel->playing) {
3469 free_playing(channel->playing);
3470 }
3471 channel->playing = playing;
3472 playing = NULL;
3473 channel->playing->declick_stage = 0;
3474 channel->playing->sampnum = channel->sample;
3475 channel->playing->sample = &sigdata->sample[channel->sample-1];
3476 it_playing_reset_resamplers(channel->playing, 0);
3477 }
3478 }
3479 get_default_volpan(sigdata, channel);
3480 }
3481 }
3482 }
3483
3484 if (!((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_XM_KEY_OFF && entry->effectvalue == 0) &&
3485 (entry->mask & IT_ENTRY_NOTE))
3486 {
3487 if (!(entry->mask & IT_ENTRY_INSTRUMENT))
3488 instrument_to_sample(sigdata, channel);
3489
3490 if (channel->note >= 120)
3491 xm_note_off(sigdata, channel);
3492 else if (channel->sample == 0) {
3493 /** If we get here, one of the following is the case:
3494 ** 1. The instrument has never been specified on this channel.
3495 ** 2. The specified instrument is invalid.
3496 ** 3. The instrument has no sample mapped to the selected note.
3497 ** What should happen?
3498 **
3499 ** Experimentation shows that any existing note stops and cannot
3500 ** be brought back. A subsequent instrument change fixes that.
3501 **/
3502 if (channel->playing) {
3503 int i;
3504 if (playing) {
3505 free_playing(channel->playing);
3506 channel->playing = playing;
3507 playing = NULL;
3508 }
3509 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
3510 if (!sigrenderer->playing[i]) {
3511 channel->playing->declick_stage = 3;
3512 sigrenderer->playing[i] = channel->playing;
3513 channel->playing = NULL;
3514 break;
3515 }
3516 }
3517 if (channel->playing) {
3518 free_playing(channel->playing);
3519 channel->playing = NULL;
3520 }
3521 }
3522 if (playing) free_playing(playing);
3523 return;
3524 } else if (channel->playing && (entry->mask & IT_ENTRY_VOLPAN) && ((entry->volpan>>4) == 0xF)) {
3525 /* Don't retrigger note; portamento in the volume column. */
3526 } else if (channel->playing &&
3527 (entry->mask & IT_ENTRY_EFFECT) &&
3528 (entry->effect == IT_TONE_PORTAMENTO ||
3529 entry->effect == IT_VOLSLIDE_TONEPORTA)) {
3530 /* Don't retrigger note; portamento in the effects column. */
3531 } else {
3532 channel->destnote = IT_NOTE_OFF;
3533
3534 if (!channel->playing) {
3535 channel->playing = new_playing();
3536 if (!channel->playing) {
3537 if (playing) free_playing(playing);
3538 return;
3539 }
3540 // Adding the following seems to do the trick for the case where a piece starts with an instrument alone and then some notes alone.
3541 retrigger_xm_envelopes(channel->playing);
3542 }
3543 else if (playing) {
3544 /* volume rampy stuff! move note to NNA */
3545 int i;
3546 IT_PLAYING * ptemp;
3547 if (playing->sample) ptemp = playing;
3548 else ptemp = channel->playing;
3549 if (!ptemp) {
3550 if (playing) free_playing(playing);
3551 return;
3552 }
3553 playing = NULL;
3554 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
3555 if (!sigrenderer->playing[i]) {
3556 ptemp->declick_stage = 3;
3557 ptemp->flags |= IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING;
3558 sigrenderer->playing[i] = ptemp;
3559 ptemp = NULL;
3560 break;
3561 }
3562 }
3563 if (ptemp) free_playing(ptemp);
3564 }
3565
3566 channel->playing->flags = 0;
3567 channel->playing->resampling_quality = sigrenderer->resampling_quality;
3568 channel->playing->channel = channel;
3569 channel->playing->sample = &sigdata->sample[channel->sample-1];
3570 if (sigdata->flags & IT_USE_INSTRUMENTS)
3571 channel->playing->instrument = &sigdata->instrument[channel->instrument-1];
3572 else
3573 channel->playing->instrument = NULL;
3574 channel->playing->env_instrument = channel->playing->instrument;
3575 channel->playing->sampnum = channel->sample;
3576 channel->playing->instnum = channel->instrument;
3577 channel->playing->declick_stage = 0;
3578 channel->playing->channel_volume = channel->channelvolume;
3579 channel->playing->note = channel->truenote;
3580 channel->playing->enabled_envelopes = 0;
3581 channel->playing->volume_offset = 0;
3582 channel->playing->panning_offset = 0;
3583 //channel->playing->output = channel->output;
3584 if (sigdata->flags & IT_USE_INSTRUMENTS) {
3585 IT_PLAYING * playing = channel->playing;
3586 IT_INSTRUMENT * instrument = playing->instrument;
3587 if (instrument->volume_envelope.flags & IT_ENVELOPE_ON) playing->enabled_envelopes |= IT_ENV_VOLUME;
3588 if (instrument->pan_envelope.flags & IT_ENVELOPE_ON) playing->enabled_envelopes |= IT_ENV_PANNING;
3589 //if (instrument->output) playing->output = instrument->output;
3590 }
3591 channel->playing->filter_cutoff = 127;
3592 channel->playing->filter_resonance = 0;
3593 channel->playing->true_filter_cutoff = 127 << 8;
3594 channel->playing->true_filter_resonance = 0;
3595 channel->playing->vibrato_speed = 0;
3596 channel->playing->vibrato_depth = 0;
3597 channel->playing->vibrato_n = 0;
3598 channel->playing->vibrato_time = 0;
3599 channel->playing->vibrato_waveform = 0;
3600 channel->playing->tremolo_speed = 0;
3601 channel->playing->tremolo_depth = 0;
3602 channel->playing->tremolo_time = 0;
3603 channel->playing->tremolo_waveform = 0;
3604 channel->playing->panbrello_speed = 0;
3605 channel->playing->panbrello_depth = 0;
3606 channel->playing->panbrello_time = 0;
3607 channel->playing->panbrello_waveform = 0;
3608 channel->playing->panbrello_random = 0;
3609 channel->playing->sample_vibrato_time = 0;
3610 channel->playing->sample_vibrato_waveform = channel->playing->sample->vibrato_waveform;
3611 channel->playing->sample_vibrato_depth = 0;
3612 channel->playing->slide = 0;
3613 channel->playing->finetune = channel->playing->sample->finetune;
3614 it_reset_filter_state(&channel->playing->filter_state[0]); // Are these
3615 it_reset_filter_state(&channel->playing->filter_state[1]); // necessary?
3616 it_playing_reset_resamplers(channel->playing, 0);
3617
3618 /** WARNING - is everything initialised? */
3619 }
3620 }
3621
3622 if (!((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_XM_KEY_OFF && entry->effectvalue == 0) &&
3623 !((entry->mask & IT_ENTRY_NOTE) && entry->note >= 120) &&
3624 (entry->mask & (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) == (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT))
3625 {
3626 if (channel->playing) retrigger_xm_envelopes(channel->playing);
3627 get_default_volpan(sigdata, channel);
3628 }
3629
3630 if ((entry->mask & IT_ENTRY_VOLPAN) && ((entry->volpan>>4) == 0xF)) {
3631 /* Tone Portamento */
3632 unsigned char v = (entry->volpan & 15) << 4;
3633 if (v == 0)
3634 v = channel->lastG;
3635 channel->lastG = v;
3636 if (entry->mask & IT_ENTRY_NOTE)
3637 if (channel->sample && channel->note < 120)
3638 channel->destnote = channel->truenote;
3639 channel->toneporta = v << 4;
3640 } else if ((entry->mask & IT_ENTRY_EFFECT) &&
3641 (entry->effect == IT_TONE_PORTAMENTO ||
3642 entry->effect == IT_VOLSLIDE_TONEPORTA)) {
3643 unsigned char v;
3644 if (entry->effect == IT_TONE_PORTAMENTO)
3645 v = entry->effectvalue;
3646 else
3647 v = 0;
3648 if (v == 0)
3649 v = channel->lastG;
3650 channel->lastG = v;
3651 if (entry->mask & IT_ENTRY_NOTE)
3652 if (channel->sample && channel->note < 120)
3653 channel->destnote = channel->truenote;
3654 channel->toneporta = v << 4;
3655 }
3656
3657 if (entry->mask & IT_ENTRY_VOLPAN) {
3658 int effect = entry->volpan >> 4;
3659 int value = entry->volpan & 15;
3660 switch (effect) {
3661 case 0x6: /* Volume slide down */
3662 channel->xm_volslide = -value;
3663 break;
3664 case 0x7: /* Volume slide up */
3665 channel->xm_volslide = value;
3666 break;
3667 case 0x8: /* Fine volume slide down */
3668 channel->volume -= value;
3669 if (channel->volume > 64) channel->volume = 0;
3670 break;
3671 case 0x9: /* Fine volume slide up */
3672 channel->volume += value;
3673 if (channel->volume > 64) channel->volume = 64;
3674 break;
3675 case 0xA: /* Set vibrato speed */
3676 if (value)
3677 channel->lastHspeed = value;
3678 if (channel->playing)
3679 channel->playing->vibrato_speed = channel->lastHspeed;
3680 break;
3681 case 0xB: /* Vibrato */
3682 if (value)
3683 channel->lastHdepth = value << 2; /** WARNING: correct ? */
3684 if (channel->playing) {
3685 channel->playing->vibrato_depth = channel->lastHdepth;
3686 channel->playing->vibrato_speed = channel->lastHspeed;
3687 channel->playing->vibrato_n++;
3688 }
3689 break;
3690 case 0xC: /* Set panning */
3691 channel->truepan = 32 + value*(17*64);
3692 break;
3693 case 0xD: /* Pan slide left */
3694 /* -128 is a special case for emulating a 'feature' in FT2.
3695 * As soon as effects are processed, it goes hard left.
3696 */
3697 channel->panslide = value ? -value : -128;
3698 break;
3699 case 0xE: /* Pan slide Right */
3700 channel->panslide = value;
3701 break;
3702 case 0xF: /* Tone porta */
3703 break;
3704 default: /* Volume */
3705 channel->volume = entry->volpan - 0x10;
3706 break;
3707 }
3708 }
3709
3710 if (playing) free_playing(playing);
3711}
3712
3713
3714
3715/* This function assumes !IT_IS_END_ROW(entry). */
3716static int process_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry, int ignore_cxx)
3717{
3718 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
3719
3720 if (sigdata->flags & IT_WAS_AN_XM)
3721 process_xm_note_data(sigrenderer, entry);
3722 else
3723 if (process_it_note_data(sigrenderer, entry)) return 0;
3724
3725 return process_effects(sigrenderer, entry, ignore_cxx);
3726}
3727
3728
3729
3730static int process_entry(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry, int ignore_cxx)
3731{
3732 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
3733
3734 if (entry->mask & IT_ENTRY_NOTE)
3735 channel->note = entry->note;
3736
3737 if ((entry->mask & (IT_ENTRY_NOTE|IT_ENTRY_EFFECT)) && (sigrenderer->sigdata->flags & IT_WAS_A_669)) {
3738 reset_channel_effects(channel);
3739 // XXX unknown
3740 if (channel->playing) channel->playing->finetune = 0;
3741 }
3742
3743 if ((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_S) {
3744 /* channel->lastS was set in update_pattern_variables(). */
3745 unsigned char effectvalue = channel->lastS;
3746 if (effectvalue >> 4 == IT_S_NOTE_DELAY) {
3747 channel->note_delay_count = effectvalue & 15;
3748 if (channel->note_delay_count == 0)
3749 channel->note_delay_count = 1;
3750 channel->note_delay_entry = entry;
3751 return 0;
3752 }
3753 }
3754
3755 return process_note_data(sigrenderer, entry, ignore_cxx);
3756}
3757
3758
3759
3760static void update_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer)
3761{
3762 int i;
3763
3764 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
3765 IT_CHANNEL *channel = &sigrenderer->channel[i];
3766
3767 if (channel->key_off_count) {
3768 channel->key_off_count--;
3769 if (channel->key_off_count == 0)
3770 xm_note_off(sigrenderer->sigdata, channel);
3771 } else if (channel->note_cut_count) {
3772 channel->note_cut_count--;
3773 if (channel->note_cut_count == 0) {
3774 if (sigrenderer->sigdata->flags & (IT_WAS_AN_XM | IT_WAS_A_PTM))
3775 channel->volume = 0;
3776 else if (channel->playing) {
3777 int i;
3778 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
3779 if (!sigrenderer->playing[i]) {
3780 channel->playing->declick_stage = 3;
3781 sigrenderer->playing[i] = channel->playing;
3782 channel->playing = NULL;
3783 break;
3784 }
3785 }
3786 if (channel->playing) {
3787 free_playing(channel->playing);
3788 channel->playing = NULL;
3789 }
3790 }
3791 }
3792 } else if (channel->note_delay_count) {
3793 channel->note_delay_count--;
3794 if (channel->note_delay_count == 0)
3795 process_note_data(sigrenderer, channel->note_delay_entry, 0);
3796 /* Don't bother checking the return value; if the note
3797 * was delayed, there can't have been a speed=0.
3798 */
3799 }
3800 }
3801}
3802
3803
3804
3805static int envelope_get_y(IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
3806{
3807#if 1
3808 (void)envelope; //TODO: remove the parameter
3809 return pe->value;
3810#else
3811 int ys, ye;
3812 int ts, te;
3813 int t;
3814
3815 if (pe->next_node <= 0)
3816 return envelope->node_y[0] << IT_ENVELOPE_SHIFT;
3817
3818 if (pe->next_node >= envelope->n_nodes)
3819 return envelope->node_y[envelope->n_nodes-1] << IT_ENVELOPE_SHIFT;
3820
3821 ys = envelope->node_y[pe->next_node-1] << IT_ENVELOPE_SHIFT;
3822 ts = envelope->node_t[pe->next_node-1];
3823 te = envelope->node_t[pe->next_node];
3824
3825 if (ts == te)
3826 return ys;
3827
3828 ye = envelope->node_y[pe->next_node] << IT_ENVELOPE_SHIFT;
3829
3830 t = pe->tick;
3831
3832 return ys + (ye - ys) * (t - ts) / (te - ts);
3833#endif
3834}
3835
3836
3837
3838#if 0
3839static int it_envelope_end(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
3840{
3841 if (pe->next_node >= envelope->n_nodes)
3842 return 1;
3843
3844 if (pe->tick < envelope->node_t[pe->next_node]) return 0;
3845
3846 if ((envelope->flags & IT_ENVELOPE_LOOP_ON) &&
3847 envelope->loop_end >= pe->next_node &&
3848 envelope->node_t[envelope->loop_end] <= pe->tick) return 0;
3849
3850 if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) &&
3851 !(playing->flags & IT_PLAYING_SUSTAINOFF) &&
3852 envelope->sus_loop_end >= pe->next_node &&
3853 envelope->node_t[envelope->sus_loop_end] <= pe->tick) return 0;
3854
3855 if (envelope->node_t[envelope->n_nodes-1] <= pe->tick) return 1;
3856
3857 return 0;
3858}
3859#endif
3860
3861
3862
3863/* Returns 1 when fading should be initiated for a volume envelope. */
3864static int update_it_envelope(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe, int flags)
3865{
3866 if (!(playing->enabled_envelopes & flags) || !envelope->n_nodes)
3867 return 0;
3868
3869 ASSERT(envelope->n_nodes > 0);
3870
3871 if (pe->tick <= 0)
3872 pe->value = envelope->node_y[0] << IT_ENVELOPE_SHIFT;
3873 else if (pe->tick >= envelope->node_t[envelope->n_nodes-1]) {
3874 pe->value = envelope->node_y[envelope->n_nodes-1] << IT_ENVELOPE_SHIFT;
3875 } else {
3876 int ys = envelope->node_y[pe->next_node-1] << IT_ENVELOPE_SHIFT;
3877 int ts = envelope->node_t[pe->next_node-1];
3878 int te = envelope->node_t[pe->next_node];
3879
3880 if (ts == te)
3881 pe->value = ys;
3882 else {
3883 int ye = envelope->node_y[pe->next_node] << IT_ENVELOPE_SHIFT;
3884 int t = pe->tick;
3885
3886 pe->value = ys + (ye - ys) * (t - ts) / (te - ts);
3887 }
3888 }
3889
3890 pe->tick++;
3891
3892 recalculate_it_envelope_node(pe, envelope);
3893
3894 if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF)) {
3895 if (pe->tick > envelope->node_t[envelope->sus_loop_end]) {
3896 pe->next_node = envelope->sus_loop_start + 1;
3897 ASSERT(pe->next_node <= envelope->n_nodes);
3898 pe->tick = envelope->node_t[envelope->sus_loop_start];
3899 return 0;
3900 }
3901 } else if (envelope->flags & IT_ENVELOPE_LOOP_ON) {
3902 if (pe->tick > envelope->node_t[envelope->loop_end]) {
3903 pe->next_node = envelope->loop_start + 1;
3904 ASSERT(pe->next_node <= envelope->n_nodes);
3905 pe->tick = envelope->node_t[envelope->loop_start];
3906 return 0;
3907 }
3908 }
3909 else if (pe->tick > envelope->node_t[envelope->n_nodes - 1])
3910 return 1;
3911
3912 return 0;
3913}
3914
3915
3916
3917static void update_it_envelopes(IT_PLAYING *playing)
3918{
3919 IT_ENVELOPE *envelope = &playing->env_instrument->volume_envelope;
3920 IT_PLAYING_ENVELOPE *pe = &playing->volume_envelope;
3921
3922 if (update_it_envelope(playing, envelope, pe, IT_ENV_VOLUME)) {
3923 playing->flags |= IT_PLAYING_FADING;
3924 if (pe->value == 0)
3925 playing->flags |= IT_PLAYING_DEAD;
3926 }
3927
3928 update_it_envelope(playing, &playing->env_instrument->pan_envelope, &playing->pan_envelope, IT_ENV_PANNING);
3929 update_it_envelope(playing, &playing->env_instrument->pitch_envelope, &playing->pitch_envelope, IT_ENV_PITCH);
3930}
3931
3932
3933
3934static int xm_envelope_is_sustaining(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
3935{
3936 if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF))
3937 if (envelope->sus_loop_start < envelope->n_nodes)
3938 if (pe->tick == envelope->node_t[envelope->sus_loop_start])
3939 return 1;
3940 return 0;
3941}
3942
3943
3944
3945static void update_xm_envelope(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
3946{
3947 if (!(envelope->flags & IT_ENVELOPE_ON))
3948 return;
3949
3950 if (xm_envelope_is_sustaining(playing, envelope, pe))
3951 return;
3952
3953 if (pe->tick >= envelope->node_t[envelope->n_nodes-1])
3954 return;
3955
3956 pe->tick++;
3957
3958 /* pe->next_node must be kept up to date for envelope_get_y(). */
3959 while (pe->tick > envelope->node_t[pe->next_node])
3960 pe->next_node++;
3961
3962 if ((envelope->flags & IT_ENVELOPE_LOOP_ON) && envelope->loop_end < envelope->n_nodes) {
3963 if (pe->tick == envelope->node_t[envelope->loop_end]) {
3964 pe->next_node = MID(0, envelope->loop_start, envelope->n_nodes - 1);
3965 pe->tick = envelope->node_t[pe->next_node];
3966 }
3967 }
3968
3969 xm_envelope_calculate_value(envelope, pe);
3970}
3971
3972
3973
3974static void update_xm_envelopes(IT_PLAYING *playing)
3975{
3976 update_xm_envelope(playing, &playing->env_instrument->volume_envelope, &playing->volume_envelope);
3977 update_xm_envelope(playing, &playing->env_instrument->pan_envelope, &playing->pan_envelope);
3978}
3979
3980
3981
3982static void update_fadeout(DUMB_IT_SIGDATA *sigdata, IT_PLAYING *playing)
3983{
3984 if (playing->flags & IT_PLAYING_FADING) {
3985 playing->fadeoutcount -= playing->env_instrument->fadeout;
3986 if (playing->fadeoutcount <= 0) {
3987 playing->fadeoutcount = 0;
3988 if (!(sigdata->flags & IT_WAS_AN_XM))
3989 playing->flags |= IT_PLAYING_DEAD;
3990 }
3991 }
3992}
3993
3994static int apply_pan_envelope(IT_PLAYING *playing);
3995static float calculate_volume(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume);
3996
3997static void playing_volume_setup(DUMB_IT_SIGRENDERER * sigrenderer, IT_PLAYING * playing, float invt2g)
3998{
3999 DUMB_IT_SIGDATA * sigdata = sigrenderer->sigdata;
4000 int pan;
4001 float vol, span;
4002 float rampScale;
4003 int ramp_style = sigrenderer->ramp_style;
4004
4005 pan = apply_pan_envelope(playing);
4006
4007 if ((sigrenderer->n_channels >= 2) && (sigdata->flags & IT_STEREO) && (sigrenderer->n_channels != 3 || !IT_IS_SURROUND_SHIFTED(pan))) {
4008 if (!IT_IS_SURROUND_SHIFTED(pan)) {
4009 span = (pan - (32<<8)) * sigdata->pan_separation * (1.0f / ((32<<8) * 128));
4010 vol = 0.5f * (1.0f - span);
4011 playing->float_volume[0] = vol;
4012 playing->float_volume[1] = 1.0f - vol;
4013 } else {
4014 playing->float_volume[0] = -0.5f;
4015 playing->float_volume[1] = 0.5f;
4016 }
4017 } else {
4018 playing->float_volume[0] = 1.0f;
4019 playing->float_volume[1] = 1.0f;
4020 }
4021
4022 vol = calculate_volume(sigrenderer, playing, 1.0f);
4023 playing->float_volume[0] *= vol;
4024 playing->float_volume[1] *= vol;
4025
4026 rampScale = 4;
4027
4028 if (ramp_style > 0 && playing->declick_stage == 2) {
4029 if ((playing->ramp_volume[0] == 0 && playing->ramp_volume[1] == 0) || vol == 0)
4030 rampScale = 48;
4031 }
4032
4033 if (ramp_style == 0 || (ramp_style < 2 && playing->declick_stage == 2)) {
4034 if (playing->declick_stage <= 2) {
4035 playing->ramp_volume[0] = playing->float_volume[0];
4036 playing->ramp_volume[1] = playing->float_volume[1];
4037 playing->declick_stage = 2;
4038 } else {
4039 playing->float_volume[0] = 0;
4040 playing->float_volume[1] = 0;
4041 playing->ramp_volume[0] = 0;
4042 playing->ramp_volume[1] = 0;
4043 playing->declick_stage = 5;
4044 }
4045 playing->ramp_delta[0] = 0;
4046 playing->ramp_delta[1] = 0;
4047 } else {
4048 if (playing->declick_stage == 0) {
4049 playing->ramp_volume[0] = 0;
4050 playing->ramp_volume[1] = 0;
4051 rampScale = 48;
4052 playing->declick_stage++;
4053 } else if (playing->declick_stage == 1) {
4054 rampScale = 48;
4055 } else if (playing->declick_stage >= 3) {
4056 playing->float_volume[0] = 0;
4057 playing->float_volume[1] = 0;
4058 if (playing->declick_stage == 3)
4059 playing->declick_stage++;
4060 rampScale = 48;
4061 }
4062 playing->ramp_delta[0] = rampScale * invt2g * (playing->float_volume[0] - playing->ramp_volume[0]);
4063 playing->ramp_delta[1] = rampScale * invt2g * (playing->float_volume[1] - playing->ramp_volume[1]);
4064 }
4065}
4066
4067static void process_playing(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float invt2g)
4068{
4069 DUMB_IT_SIGDATA * sigdata = sigrenderer->sigdata;
4070
4071 if (playing->instrument) {
4072 if (sigdata->flags & IT_WAS_AN_XM)
4073 update_xm_envelopes(playing);
4074 else
4075 update_it_envelopes(playing);
4076 update_fadeout(sigdata, playing);
4077 }
4078
4079 playing_volume_setup(sigrenderer, playing, invt2g);
4080
4081 if (sigdata->flags & IT_WAS_AN_XM) {
4082 /* 'depth' is used to store the tick number for XM files. */
4083 if (playing->sample_vibrato_depth < playing->sample->vibrato_rate)
4084 playing->sample_vibrato_depth++;
4085 } else {
4086 playing->sample_vibrato_depth += playing->sample->vibrato_rate;
4087 if (playing->sample_vibrato_depth > playing->sample->vibrato_depth << 8)
4088 playing->sample_vibrato_depth = playing->sample->vibrato_depth << 8;
4089 }
4090
4091 playing->sample_vibrato_time += playing->sample->vibrato_speed;
4092}
4093
4094static int delta_to_note(float delta, int base)
4095{
4096#define DUMB_LOG2(x) ((float)log((x))/(float)log(2.0f))
4097
4098 float note;
4099 note = DUMB_LOG2(delta * 65536.f / (float)base)*12.0f+60.5f;
4100 if (note > 119) note = 119;
4101 else if (note < 0) note = 0;
4102 return (int)note;
4103
4104#undef DUMB_LOG2
4105}
4106
4107// Period table for Protracker octaves 0-5:
4108#if 0
4109static const unsigned short ProTrackerPeriodTable[6*12] =
4110{
4111 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907,
4112 856,808,762,720,678,640,604,570,538,508,480,453,
4113 428,404,381,360,339,320,302,285,269,254,240,226,
4114 214,202,190,180,170,160,151,143,135,127,120,113,
4115 107,101,95,90,85,80,75,71,67,63,60,56,
4116 53,50,47,45,42,40,37,35,33,31,30,28
4117};
4118
4119
4120static const unsigned short ProTrackerTunedPeriods[16*12] =
4121{
4122 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907,
4123 1700,1604,1514,1430,1348,1274,1202,1134,1070,1010,954,900,
4124 1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948,894,
4125 1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940,888,
4126 1664,1570,1482,1398,1320,1246,1176,1110,1048,990,934,882,
4127 1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926,874,
4128 1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,868,
4129 1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914,862,
4130 1814,1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,
4131 1800,1700,1604,1514,1430,1350,1272,1202,1134,1070,1010,954,
4132 1788,1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948,
4133 1774,1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940,
4134 1762,1664,1570,1482,1398,1320,1246,1176,1110,1048,988,934,
4135 1750,1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926,
4136 1736,1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,
4137 1724,1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914
4138};
4139#endif
4140
4141static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer)
4142{
4143 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
4144 int i;
4145
4146 float invt2g = 1.0f / ((float)TICK_TIME_DIVIDEND / (float)sigrenderer->tempo / 256.0f);
4147
4148 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
4149 IT_CHANNEL *channel = &sigrenderer->channel[i];
4150 IT_PLAYING *playing = channel->playing;
4151
4152 if (playing) {
4153 int vibrato_shift;
4154 switch (playing->vibrato_waveform)
4155 {
4156 default:
4157 vibrato_shift = it_sine[playing->vibrato_time];
4158 break;
4159 case 1:
4160 vibrato_shift = it_sawtooth[playing->vibrato_time];
4161 break;
4162 case 2:
4163 vibrato_shift = it_squarewave[playing->vibrato_time];
4164 break;
4165 case 3:
4166 vibrato_shift = (rand() % 129) - 64;
4167 break;
4168 case 4:
4169 vibrato_shift = it_xm_squarewave[playing->vibrato_time];
4170 break;
4171 case 5:
4172 vibrato_shift = it_xm_ramp[playing->vibrato_time];
4173 break;
4174 case 6:
4175 vibrato_shift = it_xm_ramp[255-playing->vibrato_time];
4176 break;
4177 }
4178 vibrato_shift *= playing->vibrato_n;
4179 vibrato_shift *= playing->vibrato_depth;
4180 vibrato_shift >>= 4;
4181
4182 if (sigdata->flags & IT_OLD_EFFECTS)
4183 vibrato_shift = -vibrato_shift;
4184
4185 playing->volume = channel->volume;
4186 playing->pan = channel->truepan;
4187
4188 if (playing->volume_offset) {
4189 playing->volume += (playing->volume_offset * playing->volume) >> 7;
4190 if (playing->volume > 64) {
4191 if (playing->volume_offset < 0) playing->volume = 0;
4192 else playing->volume = 64;
4193 }
4194 }
4195
4196 if (playing->panning_offset && !IT_IS_SURROUND_SHIFTED(playing->pan)) {
4197 playing->pan += playing->panning_offset << IT_ENVELOPE_SHIFT;
4198 if (playing->pan > 64 << IT_ENVELOPE_SHIFT) {
4199 if (playing->panning_offset < 0) playing->pan = 0;
4200 else playing->pan = 64 << IT_ENVELOPE_SHIFT;
4201 }
4202 }
4203
4204 if (sigdata->flags & IT_LINEAR_SLIDES) {
4205 int currpitch = ((playing->note - 60) << 8) + playing->slide
4206 + vibrato_shift
4207 + playing->finetune;
4208
4209 /* We add a feature here, which is that of keeping the pitch
4210 * within range. Otherwise it crashes. Trust me. It happened.
4211 * The limit 32768 gives almost 11 octaves either way.
4212 */
4213 if (currpitch < -32768)
4214 currpitch = -32768;
4215 else if (currpitch > 32767)
4216 currpitch = 32767;
4217
4218 playing->delta = (float)pow(DUMB_PITCH_BASE, currpitch);
4219 playing->delta *= playing->sample->C5_speed * (1.f / 65536.0f);
4220 } else {
4221 int slide = playing->slide + vibrato_shift;
4222
4223 playing->delta = (float)pow(DUMB_PITCH_BASE, ((60 - playing->note) << 8) - playing->finetune );
4224 /* playing->delta is 1.0 for C-5, 0.5 for C-6, etc. */
4225
4226 playing->delta *= 1.0f / playing->sample->C5_speed;
4227
4228 playing->delta -= slide / AMIGA_DIVISOR;
4229
4230 if (playing->delta < (1.0f / 65536.0f) / 32768.0f) {
4231 // Should XM notes die if Amiga slides go out of range?
4232 playing->flags |= IT_PLAYING_DEAD;
4233 playing->delta = 1. / 32768.;
4234 continue;
4235 }
4236
4237 playing->delta = (1.0f / 65536.0f) / playing->delta;
4238 }
4239
4240 if (playing->channel->glissando && playing->channel->toneporta && playing->channel->destnote < 120) {
4241 playing->delta = (float)pow(DUMB_SEMITONE_BASE, delta_to_note(playing->delta, (int)playing->sample->C5_speed) - 60)
4242 * playing->sample->C5_speed * (1.f / 65536.f);
4243 }
4244
4245 /*
4246 if ( channel->arpeggio ) { // another FT2 bug...
4247 if ((sigdata->flags & (IT_LINEAR_SLIDES|IT_WAS_AN_XM|IT_WAS_A_MOD)) == (IT_WAS_AN_XM|IT_LINEAR_SLIDES) &&
4248 playing->flags & IT_PLAYING_SUSTAINOFF)
4249 {
4250 if ( channel->arpeggio > 0xFF )
4251 playing->delta = playing->sample->C5_speed * (1.f / 65536.f);
4252 }
4253 else*/
4254 {
4255 int tick = sigrenderer->tick - 1;
4256 if ((sigrenderer->sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD))!=IT_WAS_AN_XM)
4257 tick = sigrenderer->speed - tick - 1;
4258 else if (tick == sigrenderer->speed - 1)
4259 tick = 0;
4260 else
4261 ++tick;
4262 playing->delta *= (float)pow(DUMB_SEMITONE_BASE, channel->arpeggio_offsets[channel->arpeggio_table[tick&31]]);
4263 }
4264 /*
4265 }*/
4266
4267 playing->filter_cutoff = channel->filter_cutoff;
4268 playing->filter_resonance = channel->filter_resonance;
4269 }
4270 }
4271
4272 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
4273 if (sigrenderer->channel[i].playing) {
4274 process_playing(sigrenderer, sigrenderer->channel[i].playing, invt2g);
4275 if (!(sigdata->flags & IT_WAS_AN_XM)) {
4276 //if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) {
4277 // This change was made so Gxx would work correctly when a note faded out or whatever. Let's hope nothing else was broken by it.
4278 if (sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD) {
4279 free_playing(sigrenderer->channel[i].playing);
4280 sigrenderer->channel[i].playing = NULL;
4281 }
4282 }
4283 }
4284 }
4285
4286 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
4287 if (sigrenderer->playing[i]) {
4288 process_playing(sigrenderer, sigrenderer->playing[i], invt2g);
4289 if (sigrenderer->playing[i]->flags & IT_PLAYING_DEAD) {
4290 free_playing(sigrenderer->playing[i]);
4291 sigrenderer->playing[i] = NULL;
4292 }
4293 }
4294 }
4295}
4296
4297
4298
4299static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
4300{
4301 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
4302
4303 // Set note vol/freq to vol/freq set for each channel
4304
4305 if (sigrenderer->speed && --sigrenderer->tick == 0) {
4306 reset_tick_counts(sigrenderer);
4307 sigrenderer->tick = sigrenderer->speed;
4308 sigrenderer->rowcount--;
4309 if (sigrenderer->rowcount == 0) {
4310 sigrenderer->rowcount = 1;
4311
4312#ifdef BIT_ARRAY_BULLSHIT
4313 if (sigrenderer->n_rows)
4314 {
4315#if 1
4316 /*
4317 if (bit_array_test(sigrenderer->played, sigrenderer->order * 256 + sigrenderer->row))
4318 {
4319 if (sigrenderer->callbacks->loop) {
4320 if ((*sigrenderer->callbacks->loop)(sigrenderer->callbacks->loop_data))
4321 return 1;
4322 bit_array_reset(sigrenderer->played);
4323 if (sigrenderer->speed == 0)
4324 goto speed0; I love goto
4325 }
4326 }
4327 */
4328#endif
4329 bit_array_set(sigrenderer->played, sigrenderer->order * 256 + sigrenderer->row);
4330 {
4331 int n;
4332 for (n = 0; n < DUMB_IT_N_CHANNELS; n++)
4333 {
4334 IT_CHANNEL * channel = &sigrenderer->channel[n];
4335 if (channel->played_patjump)
4336 {
4337 if (channel->played_patjump_order == sigrenderer->order)
4338 {
4339 bit_array_set(channel->played_patjump, sigrenderer->row);
4340 }
4341 /*
4342 else if ((channel->played_patjump_order & 0x7FFF) == sigrenderer->order)
4343 {
4344 channel->played_patjump_order |= 0x4000;
4345 }
4346 else if ((channel->played_patjump_order & 0x3FFF) == sigrenderer->order)
4347 {
4348 if ((sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM)
4349 {
4350 joy, was XM, pattern loop bug triggered break to row in same order
4351 bit_array_mask(sigrenderer->played, channel->played_patjump, sigrenderer->order * 256);
4352 }
4353 bit_array_destroy(channel->played_patjump);
4354 channel->played_patjump = 0;
4355 channel->played_patjump_order = 0xFFFE;
4356 }
4357 */
4358 else
4359 {
4360 bit_array_destroy(channel->played_patjump);
4361 channel->played_patjump = 0;
4362 channel->played_patjump_order = 0xFFFE;
4363 }
4364 }
4365 }
4366 }
4367 }
4368#endif
4369
4370 sigrenderer->processrow++;
4371
4372 if (sigrenderer->processrow >= sigrenderer->n_rows) {
4373 IT_PATTERN *pattern;
4374 int n;
4375 int processorder = sigrenderer->processorder;
4376
4377 if ((sigrenderer->processrow|0xC00) == 0xFFFE + 1) { /* It was incremented above! */
4378 sigrenderer->processrow = sigrenderer->breakrow;
4379 sigrenderer->breakrow = 0;
4380 for (n = 0; n < DUMB_IT_N_CHANNELS; n++) sigrenderer->channel[n].pat_loop_end_row = 0;
4381 } else {
4382 sigrenderer->processrow = sigrenderer->breakrow;
4383 sigrenderer->breakrow = 0; // XXX lolwut
4384 }
4385
4386 if (sigrenderer->processorder == 0xFFFF)
4387 sigrenderer->processorder = sigrenderer->order - 1;
4388
4389 for (;;) {
4390 sigrenderer->processorder++;
4391
4392 if (sigrenderer->processorder >= sigdata->n_orders) {
4393 sigrenderer->processorder = sigrenderer->restart_position;
4394 if (sigrenderer->processorder >= sigdata->n_orders) {
4395 /* Restarting beyond end. We'll loop for now. */
4396 sigrenderer->processorder = -1;
4397 continue;
4398 }
4399 if (sigdata->flags & IT_WAS_AN_OKT) {
4400 /* Reset some things */
4401 sigrenderer->speed = sigdata->speed;
4402 sigrenderer->tempo = sigdata->tempo;
4403 for (n = 0; n < DUMB_IT_N_CHANNELS; n++) {
4404 xm_note_off(sigdata, &sigrenderer->channel[n]);
4405 }
4406 }
4407 }
4408
4409 n = sigdata->order[sigrenderer->processorder];
4410
4411 if (n < sigdata->n_patterns)
4412 break;
4413
4414#ifdef INVALID_ORDERS_END_SONG
4415 if (n != IT_ORDER_SKIP)
4416#else
4417 if (n == IT_ORDER_END)
4418#endif
4419 {
4420 sigrenderer->processorder = sigrenderer->restart_position - 1;
4421 }
4422
4423#ifdef BIT_ARRAY_BULLSHIT
4424 /* Fix play tracking and timekeeping for orders containing skip commands */
4425 for (n = 0; n < 256; n++) {
4426 bit_array_set(sigrenderer->played, sigrenderer->processorder * 256 + n);
4427 timekeeping_array_push(sigrenderer->row_timekeeper, sigrenderer->processorder * 256 + n, sigrenderer->time_played);
4428 timekeeping_array_bump(sigrenderer->row_timekeeper, sigrenderer->processorder * 256 + n);
4429 }
4430#endif
4431 }
4432
4433 pattern = &sigdata->pattern[n];
4434
4435 n = sigrenderer->n_rows;
4436 sigrenderer->n_rows = pattern->n_rows;
4437
4438 if (sigrenderer->processrow >= sigrenderer->n_rows)
4439 sigrenderer->processrow = 0;
4440
4441/** WARNING - everything pertaining to a new pattern initialised? */
4442
4443 sigrenderer->entry = sigrenderer->entry_start = pattern->entry;
4444 sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries;
4445
4446 /* If n_rows was 0, we're only just starting. Don't do anything weird here. */
4447 /* added: process row check, for break to row spooniness */
4448 if (n && (processorder == 0xFFFF ? sigrenderer->order > sigrenderer->processorder : sigrenderer->order >= sigrenderer->processorder)
4449#ifdef BIT_ARRAY_BULLSHIT
4450 && bit_array_test(sigrenderer->played, sigrenderer->processorder * 256 + sigrenderer->processrow)
4451#endif
4452 ) {
4453#ifdef BIT_ARRAY_BULLSHIT
4454 sigrenderer->looped = 1;
4455#endif
4456 if (sigrenderer->callbacks->loop) {
4457 if ((*sigrenderer->callbacks->loop)(sigrenderer->callbacks->loop_data))
4458 return 1;
4459#ifdef BIT_ARRAY_BULLSHIT
4460 bit_array_reset(sigrenderer->played);
4461#endif
4462 if (sigrenderer->speed == 0)
4463 goto speed0; /* I love goto */
4464 }
4465 }
4466 sigrenderer->order = sigrenderer->processorder;
4467
4468 n = sigrenderer->processrow;
4469 while (n) {
4470 while (sigrenderer->entry < sigrenderer->entry_end) {
4471 if (IT_IS_END_ROW(sigrenderer->entry)) {
4472 sigrenderer->entry++;
4473 break;
4474 }
4475 sigrenderer->entry++;
4476 }
4477 n--;
4478 }
4479 sigrenderer->row = sigrenderer->processrow;
4480 } else {
4481 if (sigrenderer->entry) {
4482 while (sigrenderer->entry < sigrenderer->entry_end) {
4483 if (IT_IS_END_ROW(sigrenderer->entry)) {
4484 sigrenderer->entry++;
4485 break;
4486 }
4487 sigrenderer->entry++;
4488 }
4489 sigrenderer->row++;
4490 } else {
4491#ifdef BIT_ARRAY_BULLSHIT
4492 bit_array_clear(sigrenderer->played, sigrenderer->order * 256);
4493#endif
4494 sigrenderer->entry = sigrenderer->entry_start;
4495 sigrenderer->row = 0;
4496 }
4497 }
4498
4499#ifdef BIT_ARRAY_BULLSHIT
4500 if (sigrenderer->looped == 0) {
4501 timekeeping_array_push(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row, sigrenderer->time_played);
4502 }
4503 timekeeping_array_bump(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row);
4504#endif
4505
4506 if (!(sigdata->flags & IT_WAS_A_669))
4507 reset_effects(sigrenderer);
4508
4509 {
4510 IT_ENTRY *entry = sigrenderer->entry;
4511 int ignore_cxx = 0;
4512
4513 while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry))
4514 ignore_cxx |= update_pattern_variables(sigrenderer, entry++);
4515
4516 entry = sigrenderer->entry;
4517
4518 while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry))
4519 if (process_entry(sigrenderer, entry++, sigdata->flags & IT_WAS_AN_XM ? 0 : ignore_cxx))
4520 return 1;
4521 }
4522
4523 if (sigdata->flags & IT_WAS_AN_OKT)
4524 update_effects(sigrenderer);
4525 else if (!(sigdata->flags & IT_OLD_EFFECTS))
4526 update_smooth_effects(sigrenderer);
4527 } else {
4528 {
4529 IT_ENTRY *entry = sigrenderer->entry;
4530
4531 while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry)) {
4532 if (entry->mask & IT_ENTRY_EFFECT && entry->effect != IT_SET_SAMPLE_OFFSET)
4533 process_effects(sigrenderer, entry, 0);
4534 /* Don't bother checking the return value; if there
4535 * was a pattern delay, there can't be a speed=0.
4536 */
4537 entry++;
4538 }
4539 }
4540
4541 update_effects(sigrenderer);
4542 }
4543 } else {
4544 if ( !(sigdata->flags & IT_WAS_AN_STM) || !(sigrenderer->tick & 15)) {
4545 speed0:
4546 update_effects(sigrenderer);
4547 update_tick_counts(sigrenderer);
4548 }
4549 }
4550
4551 if (sigrenderer->globalvolume == 0) {
4552 if (sigrenderer->callbacks->global_volume_zero) {
4553 LONG_LONG t = sigrenderer->gvz_sub_time + ((TICK_TIME_DIVIDEND / (sigrenderer->tempo << 8)) << 16);
4554 sigrenderer->gvz_time += (int)(t >> 16);
4555 sigrenderer->gvz_sub_time = (int)t & 65535;
4556 if (sigrenderer->gvz_time >= 65536 * 12) {
4557#ifdef BIT_ARRAY_BULLSHIT
4558 sigrenderer->looped = 1;
4559#endif
4560 if ((*sigrenderer->callbacks->global_volume_zero)(sigrenderer->callbacks->global_volume_zero_data))
4561 return 1;
4562 }
4563 }
4564 } else {
4565 if (sigrenderer->callbacks->global_volume_zero) {
4566 sigrenderer->gvz_time = 0;
4567 sigrenderer->gvz_sub_time = 0;
4568 }
4569 }
4570
4571 process_all_playing(sigrenderer);
4572
4573 {
4574 LONG_LONG t = (TICK_TIME_DIVIDEND / (sigrenderer->tempo << 8)) << 16;
4575 if ( sigrenderer->sigdata->flags & IT_WAS_AN_STM ) {
4576 t /= 16;
4577 }
4578 t += sigrenderer->sub_time_left;
4579 sigrenderer->time_left += (int)(t >> 16);
4580 sigrenderer->sub_time_left = (int)t & 65535;
4581 }
4582
4583 return 0;
4584}
4585
4586
4587
4588int dumb_it_max_to_mix = 64;
4589
4590#if 0
4591static const int aiMODVol[] =
4592{
4593 0,
4594 16, 24, 32, 48, 64, 80, 96, 112,
4595 128, 144, 160, 176, 192, 208, 224, 240,
4596 256, 272, 288, 304, 320, 336, 352, 368,
4597 384, 400, 416, 432, 448, 464, 480, 496,
4598 529, 545, 561, 577, 593, 609, 625, 641,
4599 657, 673, 689, 705, 721, 737, 753, 769,
4600 785, 801, 817, 833, 849, 865, 881, 897,
4601 913, 929, 945, 961, 977, 993, 1009, 1024
4602};
4603#endif
4604
4605static const int aiPTMVolScaled[] =
4606{
4607 0,
4608 31, 54, 73, 96, 111, 130, 153, 172,
4609 191, 206, 222, 237, 252, 275, 298, 317,
4610 336, 351, 370, 386, 401, 416, 428, 443,
4611 454, 466, 477, 489, 512, 531, 553, 573,
4612 592, 611, 626, 645, 660, 679, 695, 710,
4613 725, 740, 756, 767, 782, 798, 809, 820,
4614 836, 847, 859, 870, 881, 897, 908, 916,
4615 927, 939, 950, 962, 969, 983, 1005, 1024
4616};
4617
4618static float calculate_volume(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume)
4619{
4620 if (volume != 0) {
4621 int vol;
4622
4623 if (playing->channel->flags & IT_CHANNEL_MUTED)
4624 return 0;
4625
4626 if ((playing->channel->tremor_time & 192) == 128)
4627 return 0;
4628
4629 switch (playing->tremolo_waveform)
4630 {
4631 default:
4632 vol = it_sine[playing->tremolo_time];
4633 break;
4634 case 1:
4635 vol = it_sawtooth[playing->tremolo_time];
4636 break;
4637 case 2:
4638 vol = it_squarewave[playing->tremolo_time];
4639 break;
4640 case 3:
4641 vol = (rand() % 129) - 64;
4642 break;
4643 case 4:
4644 vol = it_xm_squarewave[playing->tremolo_time];
4645 break;
4646 case 5:
4647 vol = it_xm_ramp[playing->tremolo_time];
4648 break;
4649 case 6:
4650 vol = it_xm_ramp[255-((sigrenderer->sigdata->flags & IT_WAS_A_MOD)?playing->vibrato_time:playing->tremolo_time)];
4651 break;
4652 }
4653 vol *= playing->tremolo_depth;
4654
4655 vol = (playing->volume << 5) + vol;
4656
4657 if (vol <= 0)
4658 return 0;
4659
4660 if (vol > 64 << 5)
4661 vol = 64 << 5;
4662
4663 if ( sigrenderer->sigdata->flags & IT_WAS_A_PTM )
4664 {
4665 int v = aiPTMVolScaled[ vol >> 5 ];
4666 if ( vol < 64 << 5 )
4667 {
4668 int f = vol & ( ( 1 << 5 ) - 1 );
4669 int f2 = ( 1 << 5 ) - f;
4670 int v2 = aiPTMVolScaled[ ( vol >> 5 ) + 1 ];
4671 v = ( v * f2 + v2 * f ) >> 5;
4672 }
4673 vol = v << 1;
4674 }
4675
4676 volume *= vol; /* 64 << 5 */
4677 volume *= playing->sample->global_volume; /* 64 */
4678 volume *= playing->channel_volume; /* 64 */
4679 volume *= sigrenderer->globalvolume; /* 128 */
4680 volume *= sigrenderer->sigdata->mixing_volume; /* 128 */
4681 volume *= 1.0f / ((64 << 5) * 64.0f * 64.0f * 128.0f * 128.0f);
4682
4683 if (volume && playing->instrument) {
4684 if (playing->enabled_envelopes & IT_ENV_VOLUME && playing->env_instrument->volume_envelope.n_nodes) {
4685 volume *= envelope_get_y(&playing->env_instrument->volume_envelope, &playing->volume_envelope);
4686 volume *= 1.0f / (64 << IT_ENVELOPE_SHIFT);
4687 }
4688 volume *= playing->instrument->global_volume; /* 128 */
4689 volume *= playing->fadeoutcount; /* 1024 */
4690 volume *= 1.0f / (128.0f * 1024.0f);
4691 }
4692 }
4693
4694 return volume;
4695}
4696
4697
4698
4699static int apply_pan_envelope(IT_PLAYING *playing)
4700{
4701 if (playing->pan <= 64 << IT_ENVELOPE_SHIFT) {
4702 int pan;
4703 if (playing->panbrello_depth) {
4704 switch (playing->panbrello_waveform) {
4705 default:
4706 pan = it_sine[playing->panbrello_time];
4707 break;
4708 case 1:
4709 pan = it_sawtooth[playing->panbrello_time];
4710 break;
4711 case 2:
4712 pan = it_squarewave[playing->panbrello_time];
4713 break;
4714 case 3:
4715 pan = playing->panbrello_random;
4716 break;
4717 }
4718 pan *= playing->panbrello_depth << 3;
4719
4720 pan += playing->pan;
4721 if (pan < 0) pan = 0;
4722 else if (pan > 64 << IT_ENVELOPE_SHIFT) pan = 64 << IT_ENVELOPE_SHIFT;
4723 } else {
4724 pan = playing->pan;
4725 }
4726
4727 if (playing->env_instrument && (playing->enabled_envelopes & IT_ENV_PANNING)) {
4728 int p = envelope_get_y(&playing->env_instrument->pan_envelope, &playing->pan_envelope);
4729 if (pan > 32 << IT_ENVELOPE_SHIFT)
4730 p *= (64 << IT_ENVELOPE_SHIFT) - pan;
4731 else
4732 p *= pan;
4733 pan += p >> (5 + IT_ENVELOPE_SHIFT);
4734 }
4735 return pan;
4736 }
4737 return playing->pan;
4738}
4739
4740
4741
4742/* Note: if a click remover is provided, and store_end_sample is set, then
4743 * the end point will be computed twice. This situation should not arise.
4744 */
4745static long render_playing(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume, float main_delta, float delta, long pos, long size, sample_t **samples, int store_end_sample, int *left_to_mix)
4746{
4747 int bits;
4748
4749 long size_rendered;
4750
4751 DUMB_VOLUME_RAMP_INFO lvol, rvol;
4752
4753 if (playing->flags & IT_PLAYING_DEAD)
4754 return 0;
4755
4756 if (*left_to_mix <= 0)
4757 volume = 0;
4758
4759 {
4760 int quality = sigrenderer->resampling_quality;
4761 if (playing->sample->max_resampling_quality >= 0 && quality > playing->sample->max_resampling_quality)
4762 quality = playing->sample->max_resampling_quality;
4763 playing->resampler.quality = quality;
4764 resampler_set_quality(playing->resampler.fir_resampler[0], quality);
4765 resampler_set_quality(playing->resampler.fir_resampler[1], quality);
4766 }
4767
4768 bits = playing->sample->flags & IT_SAMPLE_16BIT ? 16 : 8;
4769
4770 if (volume == 0) {
4771 if (playing->sample->flags & IT_SAMPLE_STEREO)
4772 size_rendered = dumb_resample_n_2_1(bits, &playing->resampler, NULL, size, 0, 0, delta);
4773 else
4774 size_rendered = dumb_resample_n_1_1(bits, &playing->resampler, NULL, size, 0, delta);
4775 } else {
4776 lvol.volume = playing->ramp_volume [0];
4777 rvol.volume = playing->ramp_volume [1];
4778 lvol.delta = playing->ramp_delta [0] * main_delta;
4779 rvol.delta = playing->ramp_delta [1] * main_delta;
4780 lvol.target = playing->float_volume [0];
4781 rvol.target = playing->float_volume [1];
4782 rvol.mix = lvol.mix = volume;
4783 lvol.declick_stage = rvol.declick_stage = playing->declick_stage;
4784 if (sigrenderer->n_channels >= 2) {
4785 if (playing->sample->flags & IT_SAMPLE_STEREO) {
4786 if (sigrenderer->click_remover) {
4787 sample_t click[2];
4788 dumb_resample_get_current_sample_n_2_2(bits, &playing->resampler, &lvol, &rvol, click);
4789 dumb_record_click(sigrenderer->click_remover[0], pos, click[0]);
4790 dumb_record_click(sigrenderer->click_remover[1], pos, click[1]);
4791 }
4792 size_rendered = dumb_resample_n_2_2(bits, &playing->resampler, samples[0] + pos*2, size, &lvol, &rvol, delta);
4793 if (store_end_sample) {
4794 sample_t click[2];
4795 dumb_resample_get_current_sample_n_2_2(bits, &playing->resampler, &lvol, &rvol, click);
4796 samples[0][(pos + size_rendered) * 2] = click[0];
4797 samples[0][(pos + size_rendered) * 2 + 1] = click[1];
4798 }
4799 if (sigrenderer->click_remover) {
4800 sample_t click[2];
4801 dumb_resample_get_current_sample_n_2_2(bits, &playing->resampler, &lvol, &rvol, click);
4802 dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -click[0]);
4803 dumb_record_click(sigrenderer->click_remover[1], pos + size_rendered, -click[1]);
4804 }
4805 } else {
4806 if (sigrenderer->click_remover) {
4807 sample_t click[2];
4808 dumb_resample_get_current_sample_n_1_2(bits, &playing->resampler, &lvol, &rvol, click);
4809 dumb_record_click(sigrenderer->click_remover[0], pos, click[0]);
4810 dumb_record_click(sigrenderer->click_remover[1], pos, click[1]);
4811 }
4812 size_rendered = dumb_resample_n_1_2(bits, &playing->resampler, samples[0] + pos*2, size, &lvol, &rvol, delta);
4813 if (store_end_sample) {
4814 sample_t click[2];
4815 dumb_resample_get_current_sample_n_1_2(bits, &playing->resampler, &lvol, &rvol, click);
4816 samples[0][(pos + size_rendered) * 2] = click[0];
4817 samples[0][(pos + size_rendered) * 2 + 1] = click[1];
4818 }
4819 if (sigrenderer->click_remover) {
4820 sample_t click[2];
4821 dumb_resample_get_current_sample_n_1_2(bits, &playing->resampler, &lvol, &rvol, click);
4822 dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -click[0]);
4823 dumb_record_click(sigrenderer->click_remover[1], pos + size_rendered, -click[1]);
4824 }
4825 }
4826 } else {
4827 if (playing->sample->flags & IT_SAMPLE_STEREO) {
4828 if (sigrenderer->click_remover) {
4829 sample_t click;
4830 dumb_resample_get_current_sample_n_2_1(bits, &playing->resampler, &lvol, &rvol, &click);
4831 dumb_record_click(sigrenderer->click_remover[0], pos, click);
4832 }
4833 size_rendered = dumb_resample_n_2_1(bits, &playing->resampler, samples[0] + pos, size, &lvol, &rvol, delta);
4834 if (store_end_sample)
4835 dumb_resample_get_current_sample_n_2_1(bits, &playing->resampler, &lvol, &rvol, &samples[0][pos + size_rendered]);
4836 if (sigrenderer->click_remover) {
4837 sample_t click;
4838 dumb_resample_get_current_sample_n_2_1(bits, &playing->resampler, &lvol, &rvol, &click);
4839 dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -click);
4840 }
4841 } else {
4842 if (sigrenderer->click_remover) {
4843 sample_t click;
4844 dumb_resample_get_current_sample_n_1_1(bits, &playing->resampler, &lvol, &click);
4845 dumb_record_click(sigrenderer->click_remover[0], pos, click);
4846 }
4847 size_rendered = dumb_resample_n_1_1(bits, &playing->resampler, samples[0] + pos, size, &lvol, delta);
4848 if (store_end_sample)
4849 dumb_resample_get_current_sample_n_1_1(bits, &playing->resampler, &lvol, &samples[0][pos + size_rendered]);
4850 if (sigrenderer->click_remover) {
4851 sample_t click;
4852 dumb_resample_get_current_sample_n_1_1(bits, &playing->resampler, &lvol, &click);
4853 dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -click);
4854 }
4855 }
4856 }
4857 playing->ramp_volume [0] = lvol.volume;
4858 playing->ramp_volume [1] = rvol.volume;
4859 playing->declick_stage = (lvol.declick_stage > rvol.declick_stage) ? lvol.declick_stage : rvol.declick_stage;
4860 if (playing->declick_stage >= 4)
4861 playing->flags |= IT_PLAYING_DEAD;
4862 (*left_to_mix)--;
4863 }
4864
4865 if (playing->resampler.dir == 0)
4866 playing->flags |= IT_PLAYING_DEAD;
4867
4868 return size_rendered;
4869}
4870
4871typedef struct IT_TO_MIX
4872{
4873 IT_PLAYING *playing;
4874 float volume;
4875}
4876IT_TO_MIX;
4877
4878
4879
4880static int it_to_mix_compare(const void *e1, const void *e2)
4881{
4882 if (((const IT_TO_MIX *)e1)->volume > ((const IT_TO_MIX *)e2)->volume)
4883 return -1;
4884
4885 if (((const IT_TO_MIX *)e1)->volume < ((const IT_TO_MIX *)e2)->volume)
4886 return 1;
4887
4888 return 0;
4889}
4890
4891
4892
4893static void apply_pitch_modifications(DUMB_IT_SIGDATA *sigdata, IT_PLAYING *playing, float *delta, int *cutoff)
4894{
4895 {
4896 int sample_vibrato_shift;
4897 switch (playing->sample_vibrato_waveform)
4898 {
4899 default:
4900 sample_vibrato_shift = it_sine[playing->sample_vibrato_time];
4901 break;
4902 case 1:
4903 sample_vibrato_shift = it_sawtooth[playing->sample_vibrato_time];
4904 break;
4905 case 2:
4906 sample_vibrato_shift = it_squarewave[playing->sample_vibrato_time];
4907 break;
4908 case 3:
4909 sample_vibrato_shift = (rand() % 129) - 64;
4910 break;
4911 case 4:
4912 sample_vibrato_shift = it_xm_squarewave[playing->sample_vibrato_time];
4913 break;
4914 case 5:
4915 sample_vibrato_shift = it_xm_ramp[playing->sample_vibrato_time];
4916 break;
4917 case 6:
4918 sample_vibrato_shift = it_xm_ramp[255-playing->sample_vibrato_time];
4919 break;
4920 }
4921
4922 if (sigdata->flags & IT_WAS_AN_XM) {
4923 int depth = playing->sample->vibrato_depth; /* True depth */
4924 if (playing->sample->vibrato_rate) {
4925 depth *= playing->sample_vibrato_depth; /* Tick number */
4926 depth /= playing->sample->vibrato_rate; /* XM sweep */
4927 }
4928 sample_vibrato_shift *= depth;
4929 } else
4930 sample_vibrato_shift *= playing->sample_vibrato_depth >> 8;
4931
4932 sample_vibrato_shift >>= 4;
4933
4934 if (sample_vibrato_shift) {
4935 if ((sigdata->flags & IT_LINEAR_SLIDES) || !(sigdata->flags & IT_WAS_AN_XM))
4936 *delta *= (float)pow(DUMB_PITCH_BASE, sample_vibrato_shift);
4937 else {
4938 /* complicated! */
4939 float scale = *delta / playing->delta;
4940
4941 *delta = (1.0f / 65536.0f) / playing->delta;
4942
4943 *delta -= sample_vibrato_shift / AMIGA_DIVISOR;
4944
4945 if (*delta < (1.0f / 65536.0f) / 32767.0f) {
4946 *delta = (1.0f / 65536.0f) / 32767.0f;
4947 }
4948
4949 *delta = (1.0f / 65536.0f) / *delta * scale;
4950 }
4951 }
4952 }
4953
4954 if (playing->env_instrument &&
4955 (playing->enabled_envelopes & IT_ENV_PITCH))
4956 {
4957 int p = envelope_get_y(&playing->env_instrument->pitch_envelope, &playing->pitch_envelope);
4958 if (playing->env_instrument->pitch_envelope.flags & IT_ENVELOPE_PITCH_IS_FILTER)
4959 *cutoff = (*cutoff * (p+(32<<IT_ENVELOPE_SHIFT))) >> (6 + IT_ENVELOPE_SHIFT);
4960 else
4961 *delta *= (float)pow(DUMB_PITCH_BASE, p >> (IT_ENVELOPE_SHIFT - 7));
4962 }
4963}
4964
4965
4966
4967static void render_normal(DUMB_IT_SIGRENDERER *sigrenderer, float volume, float delta, long pos, long size, sample_t **samples)
4968{
4969 int i;
4970
4971 int n_to_mix = 0;
4972 IT_TO_MIX to_mix[DUMB_IT_TOTAL_CHANNELS];
4973 int left_to_mix = dumb_it_max_to_mix;
4974
4975 sample_t **samples_to_filter = NULL;
4976
4977 //int max_output = sigrenderer->max_output;
4978
4979 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
4980 if (sigrenderer->channel[i].playing && !(sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) {
4981 to_mix[n_to_mix].playing = sigrenderer->channel[i].playing;
4982 to_mix[n_to_mix].volume = volume == 0 ? 0 : calculate_volume(sigrenderer, sigrenderer->channel[i].playing, volume);
4983 n_to_mix++;
4984 }
4985 }
4986
4987 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
4988 if (sigrenderer->playing[i]) { /* Won't be dead; it would have been freed. */
4989 to_mix[n_to_mix].playing = sigrenderer->playing[i];
4990 to_mix[n_to_mix].volume = volume == 0 ? 0 : calculate_volume(sigrenderer, sigrenderer->playing[i], volume);
4991 n_to_mix++;
4992 }
4993 }
4994
4995 if (volume != 0)
4996 qsort(to_mix, n_to_mix, sizeof(IT_TO_MIX), &it_to_mix_compare);
4997
4998 for (i = 0; i < n_to_mix; i++) {
4999 IT_PLAYING *playing = to_mix[i].playing;

1103 more lines aren’t shown here.

dumb/src/it/itunload.c+0−72
@@ -1,72 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itunload.c - Code to free an Impulse Tracker / / \ \
12 * module from memory. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/it.h"
24
25
26
27void _dumb_it_unload_sigdata(sigdata_t *vsigdata)
28{
29 if (vsigdata) {
30 DUMB_IT_SIGDATA *sigdata = vsigdata;
31 int n;
32
33 if (sigdata->song_message)
34 free(sigdata->song_message);
35
36 if (sigdata->order)
37 free(sigdata->order);
38
39 if (sigdata->instrument)
40 free(sigdata->instrument);
41
42 if (sigdata->sample) {
43 for (n = 0; n < sigdata->n_samples; n++)
44 if (sigdata->sample[n].data)
45 free(sigdata->sample[n].data);
46
47 free(sigdata->sample);
48 }
49
50 if (sigdata->pattern) {
51 for (n = 0; n < sigdata->n_patterns; n++)
52 if (sigdata->pattern[n].entry)
53 free(sigdata->pattern[n].entry);
54 free(sigdata->pattern);
55 }
56
57 if (sigdata->midi)
58 free(sigdata->midi);
59
60 {
61 IT_CHECKPOINT *checkpoint = sigdata->checkpoint;
62 while (checkpoint) {
63 IT_CHECKPOINT *next = checkpoint->next;
64 _dumb_it_end_sigrenderer(checkpoint->sigrenderer);
65 free(checkpoint);
66 checkpoint = next;
67 }
68 }
69
70 free(vsigdata);
71 }
72}
dumb/src/it/ptmeffect.c+0−125
@@ -1,125 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * ptmeffect.c - Code for converting PTM / / \ \
12 * effects to IT effects. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. Based on xmeffect.c \_ / > /
15 * by Julien Cugniere. | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21
22#include <stdlib.h>
23#include <string.h>
24
25#include "dumb.h"
26#include "internal/it.h"
27
28void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry)
29{
30 if (effect >= PTM_N_EFFECTS)
31 return;
32
33 /* Linearisation of the effect number... */
34 if (effect == PTM_E) {
35 effect = PTM_EBASE + HIGH(value);
36 value = LOW(value);
37 }
38
39 /* convert effect */
40 entry->mask |= IT_ENTRY_EFFECT;
41 switch (effect) {
42
43 case PTM_APPREGIO: effect = IT_ARPEGGIO; break;
44 case PTM_PORTAMENTO_UP: effect = IT_PORTAMENTO_UP; break;
45 case PTM_PORTAMENTO_DOWN: effect = IT_PORTAMENTO_DOWN; break;
46 case PTM_TONE_PORTAMENTO: effect = IT_TONE_PORTAMENTO; break;
47 case PTM_VIBRATO: effect = IT_VIBRATO; break;
48 case PTM_VOLSLIDE_TONEPORTA: effect = IT_VOLSLIDE_TONEPORTA; break;
49 case PTM_VOLSLIDE_VIBRATO: effect = IT_VOLSLIDE_VIBRATO; break;
50 case PTM_TREMOLO: effect = IT_TREMOLO; break;
51 case PTM_SAMPLE_OFFSET: effect = IT_SET_SAMPLE_OFFSET; break;
52 case PTM_VOLUME_SLIDE: effect = IT_VOLUME_SLIDE; break;
53 case PTM_POSITION_JUMP: effect = IT_JUMP_TO_ORDER; break;
54 case PTM_SET_CHANNEL_VOLUME: effect = IT_SET_CHANNEL_VOLUME; break;
55 case PTM_PATTERN_BREAK: effect = IT_BREAK_TO_ROW; break;
56 case PTM_SET_GLOBAL_VOLUME: effect = IT_SET_GLOBAL_VOLUME; break;
57 case PTM_RETRIGGER: effect = IT_RETRIGGER_NOTE; break;
58 case PTM_FINE_VIBRATO: effect = IT_FINE_VIBRATO; break;
59
60 /* TODO properly */
61 case PTM_NOTE_SLIDE_UP: effect = IT_PTM_NOTE_SLIDE_UP; break;
62 case PTM_NOTE_SLIDE_DOWN: effect = IT_PTM_NOTE_SLIDE_DOWN; break;
63 case PTM_NOTE_SLIDE_UP_RETRIG: effect = IT_PTM_NOTE_SLIDE_UP_RETRIG; break;
64 case PTM_NOTE_SLIDE_DOWN_RETRIG: effect = IT_PTM_NOTE_SLIDE_DOWN_RETRIG; break;
65
66 case PTM_SET_TEMPO_BPM:
67 effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO);
68 break;
69
70 case PTM_EBASE+PTM_E_SET_FINETUNE: effect = SBASE+IT_S_FINETUNE; break; /** TODO */
71 case PTM_EBASE+PTM_E_SET_LOOP: effect = SBASE+IT_S_PATTERN_LOOP; break;
72 case PTM_EBASE+PTM_E_NOTE_CUT: effect = SBASE+IT_S_DELAYED_NOTE_CUT; break;
73 case PTM_EBASE+PTM_E_NOTE_DELAY: effect = SBASE+IT_S_NOTE_DELAY; break;
74 case PTM_EBASE+PTM_E_PATTERN_DELAY: effect = SBASE+IT_S_PATTERN_DELAY; break;
75 case PTM_EBASE+PTM_E_SET_PANNING: effect = SBASE+IT_S_SET_PAN; break;
76
77 case PTM_EBASE+PTM_E_FINE_VOLSLIDE_UP:
78 effect = IT_VOLUME_SLIDE;
79 value = EFFECT_VALUE(value, 0xF);
80 break;
81
82 case PTM_EBASE + PTM_E_FINE_VOLSLIDE_DOWN:
83 effect = IT_VOLUME_SLIDE;
84 value = EFFECT_VALUE(0xF, value);
85 break;
86
87 case PTM_EBASE + PTM_E_FINE_PORTA_UP:
88 effect = IT_PORTAMENTO_UP;
89 value = EFFECT_VALUE(0xF, value);
90 break;
91
92 case PTM_EBASE + PTM_E_FINE_PORTA_DOWN:
93 effect = IT_PORTAMENTO_DOWN;
94 value = EFFECT_VALUE(0xF, value);
95 break;
96
97 case PTM_EBASE + PTM_E_RETRIG_NOTE:
98 effect = IT_XM_RETRIGGER_NOTE;
99 value = EFFECT_VALUE(0, value);
100 break;
101
102 case PTM_EBASE + PTM_E_SET_VIBRATO_CONTROL:
103 effect = SBASE+IT_S_SET_VIBRATO_WAVEFORM;
104 value &= ~4; /** TODO: value&4 -> don't retrig wave */
105 break;
106
107 case PTM_EBASE + PTM_E_SET_TREMOLO_CONTROL:
108 effect = SBASE+IT_S_SET_TREMOLO_WAVEFORM;
109 value &= ~4; /** TODO: value&4 -> don't retrig wave */
110 break;
111
112 default:
113 /* user effect (often used in demos for synchronisation) */
114 entry->mask &= ~IT_ENTRY_EFFECT;
115 }
116
117 /* Inverse linearisation... */
118 if (effect >= SBASE && effect < SBASE+16) {
119 value = EFFECT_VALUE(effect-SBASE, value);
120 effect = IT_S;
121 }
122
123 entry->effect = effect;
124 entry->effectvalue = value;
125}
dumb/src/it/read669.c+0−448
@@ -1,448 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * read669.c - Code to read a 669 Composer module / / \ \
12 * from an open file. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo, int breakpoint, unsigned char *buffer, int * used_channels)
30{
31 int pos;
32 int channel;
33 int row;
34 IT_ENTRY *entry;
35
36 pattern->n_rows = 64;
37
38 if (dumbfile_getnc((char *)buffer, 64 * 3 * 8, f) < 64 * 3 * 8)
39 return -1;
40
41 /* compute number of entries */
42 pattern->n_entries = 64 + 1; /* Account for the row end markers, speed command */
43 if (breakpoint < 63) pattern->n_entries++; /* and break to row 0 */
44
45 pos = 0;
46 for (row = 0; row < 64; row++) {
47 for (channel = 0; channel < 8; channel++) {
48 if (buffer[pos+0] != 0xFF || buffer[pos+2] != 0xFF)
49 pattern->n_entries++;
50 pos += 3;
51 }
52 }
53
54 pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
55 if (!pattern->entry)
56 return -1;
57
58 if (breakpoint == 63) breakpoint++;
59
60 entry = pattern->entry;
61
62 entry->channel = 8;
63 entry->mask = IT_ENTRY_EFFECT;
64 entry->effect = IT_SET_SPEED;
65 entry->effectvalue = tempo;
66 entry++;
67
68 pos = 0;
69 for (row = 0; row < 64; row++) {
70
71 if (row == breakpoint) {
72 entry->channel = 8;
73 entry->mask = IT_ENTRY_EFFECT;
74 entry->effect = IT_BREAK_TO_ROW;
75 entry->effectvalue = 0;
76 entry++;
77 }
78
79 for (channel = 0; channel < 8; channel++) {
80 if (buffer[pos+0] != 0xFF || buffer[pos+2] != 0xFF) {
81 entry->channel = channel;
82 entry->mask = 0;
83
84 if (buffer[pos+0] < 0xFE) {
85 entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT;
86 entry->note = (buffer[pos+0] >> 2) + 36;
87 entry->instrument = (((buffer[pos+0] << 4) | (buffer[pos+1] >> 4)) & 0x3F) + 1;
88 }
89 if (buffer[pos+0] <= 0xFE) {
90 entry->mask |= IT_ENTRY_VOLPAN;
91 entry->volpan = ((buffer[pos+1] & 15) << 6) / 15;
92 if (*used_channels < channel + 1) *used_channels = channel + 1;
93 }
94 if (buffer[pos+2] != 0xFF) {
95 entry->mask |= IT_ENTRY_EFFECT;
96 entry->effectvalue = buffer[pos+2] & 15;
97 switch (buffer[pos+2] >> 4) {
98 case 0:
99 entry->effect = IT_PORTAMENTO_UP;
100 break;
101 case 1:
102 entry->effect = IT_PORTAMENTO_DOWN;
103 break;
104 case 2:
105 entry->effect = IT_TONE_PORTAMENTO;
106 break;
107 case 3:
108 entry->effect = IT_S;
109 entry->effectvalue += IT_S_FINETUNE * 16 + 8;
110 break;
111 case 4:
112 entry->effect = IT_VIBRATO;
113 // XXX speed unknown
114 entry->effectvalue |= 0x10;
115 break;
116 case 5:
117 if (entry->effectvalue) {
118 entry->effect = IT_SET_SPEED;
119 } else {
120 entry->mask &= ~IT_ENTRY_EFFECT;
121 }
122 break;
123#if 0
124 /* dunno about this, really... */
125 case 6:
126 if (entry->effectvalue == 0) {
127 entry->effect = IT_PANNING_SLIDE;
128 entry->effectvalue = 0xFE;
129 } else if (entry->effectvalue == 1) {
130 entry->effect = IT_PANNING_SLIDE;
131 entry->effectvalue = 0xEF;
132 } else {
133 entry->mask &= ~IT_ENTRY_EFFECT;
134 }
135 break;
136#endif
137 default:
138 entry->mask &= ~IT_ENTRY_EFFECT;
139 break;
140 }
141 if (*used_channels < channel + 1) *used_channels = channel + 1;
142 }
143
144 entry++;
145 }
146 pos += 3;
147 }
148 IT_SET_END_ROW(entry);
149 entry++;
150 }
151
152 return 0;
153}
154
155
156
157static int it_669_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
158{
159 dumbfile_getnc((char *)sample->name, 13, f);
160 sample->name[13] = 0;
161
162 sample->filename[0] = 0;
163
164 sample->length = dumbfile_igetl(f);
165 sample->loop_start = dumbfile_igetl(f);
166 sample->loop_end = dumbfile_igetl(f);
167
168 if (dumbfile_error(f))
169 return -1;
170
171 if (sample->length <= 0) {
172 sample->flags = 0;
173 return 0;
174 }
175
176 sample->flags = IT_SAMPLE_EXISTS;
177
178 sample->global_volume = 64;
179 sample->default_volume = 64;
180
181 sample->default_pan = 0;
182 sample->C5_speed = 8363;
183 // the above line might be wrong
184
185 if ((sample->loop_end > sample->length) && !(sample->loop_start))
186 sample->loop_end = 0;
187
188 if (sample->loop_end > sample->length)
189 sample->loop_end = sample->length;
190
191 if (sample->loop_end - sample->loop_start > 2)
192 sample->flags |= IT_SAMPLE_LOOP;
193
194 sample->vibrato_speed = 0;
195 sample->vibrato_depth = 0;
196 sample->vibrato_rate = 0;
197 sample->vibrato_waveform = 0; // do we have to set _all_ these?
198 sample->finetune = 0;
199 sample->max_resampling_quality = -1;
200
201 return 0;
202}
203
204
205
206static int it_669_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
207{
208 long i;
209 long truncated_size;
210
211 /* let's get rid of the sample data coming after the end of the loop */
212 if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
213 truncated_size = sample->length - sample->loop_end;
214 sample->length = sample->loop_end;
215 } else {
216 truncated_size = 0;
217 }
218
219 sample->data = malloc(sample->length);
220
221 if (!sample->data)
222 return -1;
223
224 if (sample->length)
225 {
226 i = dumbfile_getnc(sample->data, sample->length, f);
227
228 if (i < sample->length) {
229 //return -1;
230 // ficking truncated files
231 if (i <= 0) {
232 sample->flags = 0;
233 return 0;
234 }
235 sample->length = i;
236 if (sample->loop_end > i) sample->loop_end = i;
237 } else {
238 /* skip truncated data */
239 dumbfile_skip(f, truncated_size);
240 // Should we be truncating it?
241 if (dumbfile_error(f))
242 return -1;
243 }
244
245 for (i = 0; i < sample->length; i++)
246 ((signed char *)sample->data)[i] ^= 0x80;
247 }
248
249 return 0;
250}
251
252
253static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
254{
255 DUMB_IT_SIGDATA *sigdata;
256 int n_channels;
257 int i;
258 unsigned char tempolist[128];
259 unsigned char breaklist[128];
260
261 i = dumbfile_igetw(f);
262 if (i != 0x6669 && i != 0x4E4A) return NULL;
263
264 *ext = (i == 0x4E4A);
265
266 sigdata = malloc(sizeof(*sigdata));
267 if (!sigdata) {
268 return NULL;
269 }
270
271 if (dumbfile_getnc((char *)sigdata->name, 36, f) < 36) {
272 free(sigdata);
273 return NULL;
274 }
275 sigdata->name[36] = 0;
276
277 sigdata->order = NULL;
278 sigdata->instrument = NULL;
279 sigdata->pattern = NULL;
280 sigdata->midi = NULL;
281 sigdata->checkpoint = NULL;
282 sigdata->sample = NULL;
283
284 sigdata->n_instruments = 0;
285
286 sigdata->song_message = malloc(72 + 2 + 1);
287 if (!sigdata->song_message) {
288 free(sigdata);
289 return NULL;
290 }
291 if (dumbfile_getnc((char *)sigdata->song_message, 36, f) < 36) {
292 _dumb_it_unload_sigdata(sigdata);
293 return NULL;
294 }
295 sigdata->song_message[36] = 13;
296 sigdata->song_message[36 + 1] = 10;
297 if (dumbfile_getnc((char *)sigdata->song_message + 38, 36, f) < 36) {
298 _dumb_it_unload_sigdata(sigdata);
299 return NULL;
300 }
301 sigdata->song_message[38 + 36] = 0;
302
303 sigdata->n_samples = dumbfile_getc(f);
304 sigdata->n_patterns = dumbfile_getc(f);
305 sigdata->restart_position = dumbfile_getc(f);
306
307 if ((sigdata->n_samples) > 64 || (sigdata->n_patterns > 128)) {
308 _dumb_it_unload_sigdata(sigdata);
309 return NULL;
310 }
311
312 sigdata->order = malloc(128); /* We may need to scan the extra ones! */
313 if (!sigdata->order) {
314 _dumb_it_unload_sigdata(sigdata);
315 return NULL;
316 }
317 if (dumbfile_getnc((char *)sigdata->order, 128, f) < 128) {
318 _dumb_it_unload_sigdata(sigdata);
319 return NULL;
320 }
321
322 for (i = 0; i < 128; i++) {
323 if (sigdata->order[i] == 255) break;
324 if (sigdata->order[i] >= sigdata->n_patterns) {
325 _dumb_it_unload_sigdata(sigdata);
326 return NULL;
327 }
328 }
329 if (!i) {
330 _dumb_it_unload_sigdata(sigdata);
331 return NULL;
332 }
333 sigdata->n_orders = i;
334
335 if (dumbfile_getnc((char *)tempolist, 128, f) < 128) {
336 _dumb_it_unload_sigdata(sigdata);
337 return NULL;
338 }
339
340 if (dumbfile_getnc((char *)breaklist, 128, f) < 128) {
341 _dumb_it_unload_sigdata(sigdata);
342 return NULL;
343 }
344
345 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
346 if (!sigdata->sample) {
347 _dumb_it_unload_sigdata(sigdata);
348 return NULL;
349 }
350
351 for (i = 0; i < sigdata->n_samples; i++)
352 sigdata->sample[i].data = NULL;
353
354 for (i = 0; i < sigdata->n_samples; i++) {
355 if (it_669_read_sample_header(&sigdata->sample[i], f)) {
356 _dumb_it_unload_sigdata(sigdata);
357 return NULL;
358 }
359 }
360
361 /* May as well try to save a tiny bit of memory. */
362 if (sigdata->n_orders < 128) {
363 unsigned char *order = realloc(sigdata->order, sigdata->n_orders);
364 if (order) sigdata->order = order;
365 }
366
367 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
368 if (!sigdata->pattern) {
369 _dumb_it_unload_sigdata(sigdata);
370 return NULL;
371 }
372 for (i = 0; i < sigdata->n_patterns; i++)
373 sigdata->pattern[i].entry = NULL;
374
375 n_channels = 0;
376
377 /* Read in the patterns */
378 {
379 unsigned char *buffer = malloc(64 * 3 * 8); /* 64 rows * 3 bytes * 8 channels */
380 if (!buffer) {
381 _dumb_it_unload_sigdata(sigdata);
382 return NULL;
383 }
384 for (i = 0; i < sigdata->n_patterns; i++) {
385 if (it_669_read_pattern(&sigdata->pattern[i], f, tempolist[i], breaklist[i], buffer, &n_channels) != 0) {
386 free(buffer);
387 _dumb_it_unload_sigdata(sigdata);
388 return NULL;
389 }
390 }
391 free(buffer);
392 }
393
394 sigdata->n_pchannels = n_channels;
395
396 /* And finally, the sample data */
397 for (i = 0; i < sigdata->n_samples; i++) {
398 if (it_669_read_sample_data(&sigdata->sample[i], f)) {
399 _dumb_it_unload_sigdata(sigdata);
400 return NULL;
401 }
402 }
403
404 /* Now let's initialise the remaining variables, and we're done! */
405 sigdata->flags = IT_OLD_EFFECTS | IT_LINEAR_SLIDES | IT_STEREO | IT_WAS_A_669;
406
407 sigdata->global_volume = 128;
408 sigdata->mixing_volume = 48;
409 sigdata->speed = 4;
410 sigdata->tempo = 78;
411 sigdata->pan_separation = 128;
412
413 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
414
415 for (i = 0; i < DUMB_IT_N_CHANNELS; i += 2) {
416 int sep = 32 * dumb_it_default_panning_separation / 100;
417 sigdata->channel_pan[i+0] = 32 + sep;
418 sigdata->channel_pan[i+1] = 32 - sep;
419 }
420
421 _dumb_it_fix_invalid_orders(sigdata);
422
423 return sigdata;
424}
425
426
427
428DUH *dumb_read_669_quick(DUMBFILE *f)
429{
430 sigdata_t *sigdata;
431 int ext;
432
433 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
434
435 sigdata = it_669_load_sigdata(f, &ext);
436
437 if (!sigdata)
438 return NULL;
439
440 {
441 const char *tag[2][2];
442 tag[0][0] = "TITLE";
443 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
444 tag[1][0] = "FORMAT";
445 tag[1][1] = ext ? "669 Extended" : "669";
446 return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
447 }
448}
dumb/src/it/readam.c+0−789
@@ -1,789 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readam.c - Code to read a RIFF AM module / / \ \
12 * from a parsed RIFF structure. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22
23#include "dumb.h"
24#include "internal/it.h"
25#include "internal/riff.h"
26
27static int it_riff_am_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int len, int ver )
28{
29 int header_length;
30 int default_pan;
31 int default_volume;
32 int flags;
33 int length;
34 int length_bytes;
35 int loop_start;
36 int loop_end;
37 int sample_rate;
38
39 long start = dumbfile_pos( f );
40
41 if ( ver == 0 )
42 {
43 if ( len < 0x38 )
44 return -1;
45
46 header_length = 0x38;
47
48 dumbfile_getnc( (char *) sample->name, 28, f );
49 sample->name[ 28 ] = 0;
50
51 default_pan = dumbfile_getc( f );
52 default_volume = dumbfile_getc( f );
53 flags = dumbfile_igetw( f );
54 length = dumbfile_igetl( f );
55 loop_start = dumbfile_igetl( f );
56 loop_end = dumbfile_igetl( f );
57 sample_rate = dumbfile_igetl( f );
58 }
59 else
60 {
61 if (len < 4) return -1;
62
63 header_length = dumbfile_igetl( f );
64 if ( header_length < 0x40 )
65 return -1;
66 if ( header_length + 4 > len )
67 return -1;
68
69 start += 4;
70 len -= 4;
71
72 dumbfile_getnc( (char *) sample->name, 32, f );
73
74 default_pan = dumbfile_igetw( f );
75 default_volume = dumbfile_igetw( f );
76 flags = dumbfile_igetw( f );
77 dumbfile_skip( f, 2 );
78 length = dumbfile_igetl( f );
79 loop_start = dumbfile_igetl( f );
80 loop_end = dumbfile_igetl( f );
81 sample_rate = dumbfile_igetl( f );
82
83 if ( default_pan > 0x7FFF || default_volume > 0x7FFF )
84 return -1;
85
86 default_pan = default_pan * 64 / 32767;
87 default_volume = default_volume * 64 / 32767;
88 }
89
90 if ( ! length ) {
91 sample->flags &= ~IT_SAMPLE_EXISTS;
92 return 0;
93 }
94
95 if ( flags & ~( 0x8000 | 0x80 | 0x20 | 0x10 | 0x08 | 0x04 ) )
96 return -1;
97
98 length_bytes = length << ( ( flags & 0x04 ) >> 2 );
99
100 if ( length_bytes + header_length > len )
101 return -1;
102
103 sample->flags = 0;
104
105 if ( flags & 0x80 ) sample->flags |= IT_SAMPLE_EXISTS;
106 if ( flags & 0x04 ) sample->flags |= IT_SAMPLE_16BIT;
107
108 sample->length = length;
109 sample->loop_start = loop_start;
110 sample->loop_end = loop_end;
111 sample->C5_speed = sample_rate;
112 sample->default_volume = default_volume;
113 sample->default_pan = default_pan | ( ( flags & 0x20 ) << 2 );
114 sample->filename[0] = 0;
115 sample->global_volume = 64;
116 sample->vibrato_speed = 0;
117 sample->vibrato_depth = 0;
118 sample->vibrato_rate = 0;
119 sample->vibrato_waveform = IT_VIBRATO_SINE;
120 sample->finetune = 0;
121 sample->max_resampling_quality = -1;
122
123 if ( flags & 0x08 )
124 {
125 if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) &&
126 ((unsigned int)sample->loop_start < (unsigned int)sample->loop_end))
127 {
128 sample->length = sample->loop_end;
129 sample->flags |= IT_SAMPLE_LOOP;
130 if ( flags & 0x10 ) sample->flags |= IT_SAMPLE_PINGPONG_LOOP;
131 }
132 }
133
134 length_bytes = sample->length << ( ( flags & 0x04 ) >> 2 );
135
136 sample->data = malloc( length_bytes );
137 if ( ! sample->data )
138 return -1;
139
140 if ( dumbfile_seek( f, start + header_length, DFS_SEEK_SET ) )
141 return -1;
142
143 dumbfile_getnc( sample->data, length_bytes, f );
144
145 return 0;
146}
147
148static int it_riff_am_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len, int ver )
149{
150 int nrows, row;
151 long start, end;
152 unsigned flags;
153 int p, q, r;
154 IT_ENTRY * entry;
155
156 nrows = dumbfile_getc( f ) + 1;
157
158 pattern->n_rows = nrows;
159
160 len -= 1;
161
162 pattern->n_entries = 0;
163
164 row = 0;
165
166 start = dumbfile_pos( f );
167 end = start + len;
168
169 while ( (row < nrows) && !dumbfile_error( f ) && (dumbfile_pos( f ) < end) ) {
170 p = dumbfile_getc( f );
171 if ( ! p ) {
172 ++ row;
173 continue;
174 }
175
176 flags = p & 0xE0;
177
178 if (flags) {
179 ++ pattern->n_entries;
180 if (flags & 0x80) dumbfile_skip( f, 2 );
181 if (flags & 0x40) dumbfile_skip( f, 2 );
182 if (flags & 0x20) dumbfile_skip( f, 1 );
183 }
184 }
185
186 if ( ! pattern->n_entries ) return 0;
187
188 pattern->n_entries += nrows;
189
190 pattern->entry = malloc( pattern->n_entries * sizeof( * pattern->entry ) );
191 if ( ! pattern->entry ) return -1;
192
193 entry = pattern->entry;
194
195 row = 0;
196
197 dumbfile_seek( f, start, DFS_SEEK_SET );
198
199 while ( ( row < nrows ) && !dumbfile_error( f ) && ( dumbfile_pos( f ) < end ) )
200 {
201 p = dumbfile_getc( f );
202
203 if ( ! p )
204 {
205 IT_SET_END_ROW( entry );
206 ++ entry;
207 ++ row;
208 continue;
209 }
210
211 flags = p;
212 entry->channel = flags & 0x1F;
213 entry->mask = 0;
214
215 if (flags & 0xE0)
216 {
217 if ( flags & 0x80 )
218 {
219 q = dumbfile_getc( f );
220 r = dumbfile_getc( f );
221 _dumb_it_xm_convert_effect( r, q, entry, 0 );
222 }
223
224 if ( flags & 0x40 )
225 {
226 q = dumbfile_getc( f );
227 r = dumbfile_getc( f );
228 if ( q )
229 {
230 entry->mask |= IT_ENTRY_INSTRUMENT;
231 entry->instrument = q;
232 }
233 if ( r )
234 {
235 entry->mask |= IT_ENTRY_NOTE;
236 entry->note = r - 1;
237 }
238 }
239
240 if ( flags & 0x20 )
241 {
242 q = dumbfile_getc( f );
243 entry->mask |= IT_ENTRY_VOLPAN;
244 if ( ver == 0 ) entry->volpan = q;
245 else entry->volpan = q * 64 / 127;
246 }
247
248 if (entry->mask) entry++;
249 }
250 }
251
252 while ( row < nrows )
253 {
254 IT_SET_END_ROW( entry );
255 ++ entry;
256 ++ row;
257 }
258
259 pattern->n_entries = entry - pattern->entry;
260 if ( ! pattern->n_entries ) return -1;
261
262 return 0;
263}
264
265static DUMB_IT_SIGDATA *it_riff_amff_load_sigdata( DUMBFILE * f, struct riff * stream )
266{
267 DUMB_IT_SIGDATA *sigdata;
268
269 int n, o, p, found;
270
271 if ( ! stream ) goto error;
272
273 if ( stream->type != DUMB_ID( 'A', 'M', 'F', 'F' ) ) goto error;
274
275 sigdata = malloc( sizeof( *sigdata ) );
276 if ( ! sigdata ) goto error;
277
278 sigdata->n_patterns = 0;
279 sigdata->n_samples = 0;
280 sigdata->name[0] = 0;
281
282 found = 0;
283
284 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
285 {
286 struct riff_chunk * c = stream->chunks + n;
287 switch( c->type )
288 {
289 case DUMB_ID( 'M', 'A', 'I', 'N' ):
290 /* initialization data */
291 if ( ( found & 1 ) || ( c->size < 0x48 ) ) goto error_sd;
292 found |= 1;
293 break;
294
295 case DUMB_ID( 'O', 'R', 'D', 'R' ):
296 if ( ( found & 2 ) || ( c->size < 1 ) ) goto error_sd;
297 found |= 2;
298 break;
299
300 case DUMB_ID( 'P', 'A', 'T', 'T' ):
301 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_sd;
302 o = dumbfile_getc( f );
303 if ( o >= sigdata->n_patterns ) sigdata->n_patterns = o + 1;
304 o = dumbfile_igetl( f );
305 if ( (unsigned)o + 5 > c->size ) goto error_sd;
306 break;
307
308 case DUMB_ID( 'I', 'N', 'S', 'T' ):
309 {
310 if ( c->size < 0xE1 ) goto error_sd;
311 if ( dumbfile_seek( f, c->offset + 1, DFS_SEEK_SET ) ) goto error_sd;
312 o = dumbfile_getc( f );
313 if ( o >= sigdata->n_samples ) sigdata->n_samples = o + 1;
314 if ( c->size >= 0x121 )
315 {
316 if ( dumbfile_seek( f, c->offset + 0xE1, DFS_SEEK_SET ) ) goto error_sd;
317 if ( dumbfile_mgetl( f ) == DUMB_ID('S','A','M','P') )
318 {
319 unsigned size = dumbfile_igetl( f );
320 if ( size + 0xE1 + 8 > c->size ) goto error_sd;
321 }
322 }
323 }
324 break;
325 }
326 }
327
328 if ( found != 3 || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd;
329
330 if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd;
331
332 sigdata->song_message = NULL;
333 sigdata->order = NULL;
334 sigdata->instrument = NULL;
335 sigdata->sample = NULL;
336 sigdata->pattern = NULL;
337 sigdata->midi = NULL;
338 sigdata->checkpoint = NULL;
339
340 sigdata->mixing_volume = 48;
341 sigdata->pan_separation = 128;
342
343 sigdata->n_instruments = 0;
344 sigdata->n_orders = 0;
345 sigdata->restart_position = 0;
346
347 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
348
349 for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
350 int sep = 32 * dumb_it_default_panning_separation / 100;
351 sigdata->channel_pan[n ] = 32 - sep;
352 sigdata->channel_pan[n+1] = 32 + sep;
353 sigdata->channel_pan[n+2] = 32 + sep;
354 sigdata->channel_pan[n+3] = 32 - sep;
355 }
356
357 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
358 {
359 struct riff_chunk * c = stream->chunks + n;
360 switch ( c->type )
361 {
362 case DUMB_ID( 'M', 'A', 'I', 'N' ):
363 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
364 dumbfile_getnc( (char *) sigdata->name, 64, f );
365 sigdata->name[ 64 ] = 0;
366 sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M;
367 o = dumbfile_getc( f );
368 if ( ! ( o & 1 ) ) sigdata->flags |= IT_LINEAR_SLIDES;
369 if ( ( o & ~3 ) || ! ( o & 2 ) ) goto error_usd; // unknown flags
370 sigdata->n_pchannels = dumbfile_getc( f );
371 sigdata->speed = dumbfile_getc( f );
372 sigdata->tempo = dumbfile_getc( f );
373
374 dumbfile_skip( f, 4 );
375
376 sigdata->global_volume = dumbfile_getc( f );
377
378 if ( c->size < 0x48 + (unsigned)sigdata->n_pchannels ) goto error_usd;
379
380 for ( o = 0; o < sigdata->n_pchannels; ++o )
381 {
382 p = dumbfile_getc( f );
383 sigdata->channel_pan[ o ] = p;
384 if ( p >= 128 )
385 {
386 sigdata->channel_volume[ o ] = 0;
387 }
388 }
389 break;
390 }
391 }
392
393 sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
394 if ( ! sigdata->pattern ) goto error_usd;
395 for ( n = 0; n < sigdata->n_patterns; ++n )
396 sigdata->pattern[ n ].entry = NULL;
397
398 sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
399 if ( ! sigdata->sample ) goto error_usd;
400 for ( n = 0; n < sigdata->n_samples; ++n )
401 {
402 IT_SAMPLE * sample = sigdata->sample + n;
403 sample->data = NULL;
404 sample->flags = 0;
405 sample->name[ 0 ] = 0;
406 }
407
408 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
409 {
410 struct riff_chunk * c = stream->chunks + n;
411 switch ( c->type )
412 {
413 case DUMB_ID( 'O', 'R', 'D', 'R' ):
414 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
415 sigdata->n_orders = dumbfile_getc( f ) + 1;
416 if ( (unsigned)sigdata->n_orders + 1 > c->size ) goto error_usd;
417 sigdata->order = malloc( sigdata->n_orders );
418 if ( ! sigdata->order ) goto error_usd;
419 dumbfile_getnc( (char *) sigdata->order, sigdata->n_orders, f );
420 break;
421
422 case DUMB_ID( 'P', 'A', 'T', 'T' ):
423 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
424 o = dumbfile_getc( f );
425 p = dumbfile_igetl( f );
426 if ( it_riff_am_process_pattern( sigdata->pattern + o, f, p, 0 ) ) goto error_usd;
427 break;
428
429 case DUMB_ID( 'I', 'N', 'S', 'T' ):
430 {
431 IT_SAMPLE * sample;
432 if ( dumbfile_seek( f, c->offset + 1, DFS_SEEK_SET ) ) goto error_usd;
433 sample = sigdata->sample + dumbfile_getc( f );
434 if ( c->size >= 0x121 )
435 {
436 if ( dumbfile_seek( f, c->offset + 0xE1, DFS_SEEK_SET ) ) goto error_usd;
437 if ( dumbfile_mgetl( f ) == DUMB_ID('S','A','M','P') )
438 {
439 unsigned size = dumbfile_igetl( f );
440 if ( it_riff_am_process_sample( sample, f, size, 0 ) ) goto error_usd;
441 break;
442 }
443 }
444 dumbfile_seek( f, c->offset + 2, DFS_SEEK_SET );
445 dumbfile_getnc( (char *) sample->name, 28, f );
446 sample->name[ 28 ] = 0;
447 }
448 break;
449 }
450 }
451
452 _dumb_it_fix_invalid_orders( sigdata );
453
454 return sigdata;
455
456error_usd:
457 _dumb_it_unload_sigdata( sigdata );
458 goto error;
459error_sd:
460 free( sigdata );
461error:
462 return NULL;
463}
464
465static DUMB_IT_SIGDATA *it_riff_am_load_sigdata( DUMBFILE * f, struct riff * stream )
466{
467 DUMB_IT_SIGDATA *sigdata;
468
469 int n, o, p, found;
470
471 if ( ! f || ! stream ) goto error;
472
473 if ( stream->type != DUMB_ID( 'A', 'M', ' ', ' ' ) ) goto error;
474
475 sigdata = malloc(sizeof(*sigdata));
476 if ( ! sigdata ) goto error;
477
478 sigdata->n_patterns = 0;
479 sigdata->n_samples = 0;
480 sigdata->name[0] = 0;
481
482 found = 0;
483
484 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
485 {
486 struct riff_chunk * c = stream->chunks + n;
487 switch( c->type )
488 {
489 case DUMB_ID( 'I' ,'N' ,'I' ,'T' ):
490 /* initialization data */
491 if ( ( found & 1 ) || ( c->size < 0x48 ) ) goto error_sd;
492 found |= 1;
493 break;
494
495 case DUMB_ID( 'O', 'R', 'D', 'R' ):
496 if ( ( found & 2 ) || ( c->size < 1 ) ) goto error_sd;
497 found |= 2;
498 break;
499
500 case DUMB_ID( 'P', 'A', 'T', 'T' ):
501 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_sd;
502 o = dumbfile_getc( f );
503 if ( o >= sigdata->n_patterns ) sigdata->n_patterns = o + 1;
504 o = dumbfile_igetl( f );
505 if ( (unsigned)o + 5 > c->size ) goto error_sd;
506 break;
507
508 case DUMB_ID( 'R', 'I', 'F', 'F' ):
509 {
510 struct riff * str = c->nested;
511 switch ( str->type )
512 {
513 case DUMB_ID( 'A', 'I', ' ', ' ' ):
514 for ( o = 0; (unsigned)o < str->chunk_count; ++o )
515 {
516 struct riff_chunk * chk = str->chunks + o;
517 switch( chk->type )
518 {
519 case DUMB_ID( 'I', 'N', 'S', 'T' ):
520 {
521 struct riff * temp;
522 unsigned size;
523 unsigned sample_found;
524 if ( dumbfile_seek( f, chk->offset, DFS_SEEK_SET ) ) goto error_sd;
525 size = dumbfile_igetl( f );
526 if ( size < 0x142 ) goto error_sd;
527 sample_found = 0;
528 dumbfile_skip( f, 1 );
529 p = dumbfile_getc( f );
530 if ( p >= sigdata->n_samples ) sigdata->n_samples = p + 1;
531 temp = riff_parse( f, chk->offset + 4 + size, chk->size - size - 4, 1 );
532 if ( temp )
533 {
534 if ( temp->type == DUMB_ID( 'A', 'S', ' ', ' ' ) )
535 {
536 for ( p = 0; (unsigned)p < temp->chunk_count; ++p )
537 {
538 if ( temp->chunks[ p ].type == DUMB_ID( 'S', 'A', 'M', 'P' ) )
539 {
540 if ( sample_found )
541 {
542 riff_free( temp );
543 goto error_sd;
544 }
545 sample_found = 1;
546 }
547 }
548 }
549 riff_free( temp );
550 }
551 }
552 }
553 }
554 }
555 }
556 break;
557 }
558 }
559
560 if ( found != 3 || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd;
561
562 if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd;
563
564 sigdata->song_message = NULL;
565 sigdata->order = NULL;
566 sigdata->instrument = NULL;
567 sigdata->sample = NULL;
568 sigdata->pattern = NULL;
569 sigdata->midi = NULL;
570 sigdata->checkpoint = NULL;
571
572 sigdata->mixing_volume = 48;
573 sigdata->pan_separation = 128;
574
575 sigdata->n_instruments = 0;
576 sigdata->n_orders = 0;
577 sigdata->restart_position = 0;
578
579 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
580
581 for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
582 int sep = 32 * dumb_it_default_panning_separation / 100;
583 sigdata->channel_pan[n ] = 32 - sep;
584 sigdata->channel_pan[n+1] = 32 + sep;
585 sigdata->channel_pan[n+2] = 32 + sep;
586 sigdata->channel_pan[n+3] = 32 - sep;
587 }
588
589 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
590 {
591 struct riff_chunk * c = stream->chunks + n;
592 switch ( c->type )
593 {
594 case DUMB_ID( 'I', 'N', 'I', 'T' ):
595 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
596 dumbfile_getnc( (char *) sigdata->name, 64, f );
597 sigdata->name[ 64 ] = 0;
598 sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M;
599 o = dumbfile_getc( f );
600 if ( ! ( o & 1 ) ) sigdata->flags |= IT_LINEAR_SLIDES;
601 if ( ( o & ~3 ) || ! ( o & 2 ) ) goto error_usd; // unknown flags
602 sigdata->n_pchannels = dumbfile_getc( f );
603 sigdata->speed = dumbfile_getc( f );
604 sigdata->tempo = dumbfile_getc( f );
605
606 dumbfile_skip( f, 4 );
607
608 sigdata->global_volume = dumbfile_getc( f );
609
610 if ( c->size < 0x48 + (unsigned)sigdata->n_pchannels ) goto error_usd;
611
612 for ( o = 0; o < sigdata->n_pchannels; ++o )
613 {
614 p = dumbfile_getc( f );
615 if ( p <= 128 )
616 {
617 sigdata->channel_pan[ o ] = p / 2;
618 }
619 else
620 {
621 sigdata->channel_volume[ o ] = 0;
622 }
623 }
624 break;
625 }
626 }
627
628 sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
629 if ( ! sigdata->pattern ) goto error_usd;
630 for ( n = 0; n < sigdata->n_patterns; ++n )
631 sigdata->pattern[ n ].entry = NULL;
632
633 sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
634 if ( ! sigdata->sample ) goto error_usd;
635 for ( n = 0; n < sigdata->n_samples; ++n )
636 {
637 IT_SAMPLE * sample = sigdata->sample + n;
638 sample->data = NULL;
639 sample->flags = 0;
640 sample->name[ 0 ] = 0;
641 }
642
643 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
644 {
645 struct riff_chunk * c = stream->chunks + n;
646 switch ( c->type )
647 {
648 case DUMB_ID( 'O', 'R', 'D', 'R' ):
649 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
650 sigdata->n_orders = dumbfile_getc( f ) + 1;
651 if ( (unsigned)sigdata->n_orders + 1 > c->size ) goto error_usd;
652 sigdata->order = malloc( sigdata->n_orders );
653 if ( ! sigdata->order ) goto error_usd;
654 dumbfile_getnc( (char *) sigdata->order, sigdata->n_orders, f );
655 break;
656
657 case DUMB_ID( 'P', 'A', 'T', 'T' ):
658 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
659 o = dumbfile_getc( f );
660 p = dumbfile_igetl( f );
661 if ( it_riff_am_process_pattern( sigdata->pattern + o, f, p, 1 ) ) goto error_usd;
662 break;
663
664 case DUMB_ID( 'R', 'I', 'F', 'F' ):
665 {
666 struct riff * str = c->nested;
667 switch ( str->type )
668 {
669 case DUMB_ID('A', 'I', ' ', ' '):
670 for ( o = 0; (unsigned)o < str->chunk_count; ++o )
671 {
672 struct riff_chunk * chk = str->chunks + o;
673 switch( chk->type )
674 {
675 case DUMB_ID( 'I', 'N', 'S', 'T' ):
676 {
677 struct riff * temp;
678 unsigned size;
679 unsigned sample_found;
680 IT_SAMPLE * sample;
681 if ( dumbfile_seek( f, chk->offset, DFS_SEEK_SET ) ) goto error_usd;
682 size = dumbfile_igetl( f );
683 dumbfile_skip( f, 1 );
684 p = dumbfile_getc( f );
685 temp = riff_parse( f, chk->offset + 4 + size, chk->size - size - 4, 1 );
686 sample_found = 0;
687 sample = sigdata->sample + p;
688 if ( temp )
689 {
690 if ( temp->type == DUMB_ID( 'A', 'S', ' ', ' ' ) )
691 {
692 for ( p = 0; (unsigned)p < temp->chunk_count; ++p )
693 {
694 struct riff_chunk * c = temp->chunks + p;
695 if ( c->type == DUMB_ID( 'S', 'A', 'M', 'P' ) )
696 {
697 if ( sample_found )
698 {
699 riff_free( temp );
700 goto error_usd;
701 }
702 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) )
703 {
704 riff_free( temp );
705 goto error_usd;
706 }
707 if ( it_riff_am_process_sample( sample, f, c->size, 1 ) )
708 {
709 riff_free( temp );
710 goto error_usd;
711 }
712 sample_found = 1;
713 }
714 }
715 }
716 riff_free( temp );
717 }
718 if ( ! sample_found )
719 {
720 dumbfile_seek( f, chk->offset + 6, DFS_SEEK_SET );
721 dumbfile_getnc( (char *) sample->name, 32, f );
722 sample->name[ 32 ] = 0;
723 }
724 }
725 }
726 }
727 }
728 }
729 break;
730 }
731 }
732
733 _dumb_it_fix_invalid_orders( sigdata );
734
735 return sigdata;
736
737error_usd:
738 _dumb_it_unload_sigdata( sigdata );
739 goto error;
740error_sd:
741 free( sigdata );
742error:
743 return NULL;
744}
745
746DUH *dumb_read_riff_amff( DUMBFILE * f, struct riff * stream )
747{
748 sigdata_t *sigdata;
749 long length;
750
751 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
752
753 sigdata = it_riff_amff_load_sigdata( f, stream );
754
755 if (!sigdata)
756 return NULL;
757
758 length = 0;/*_dumb_it_build_checkpoints(sigdata, 0);*/
759
760 {
761 const char *tag[2][2];
762 tag[0][0] = "TITLE";
763 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
764 tag[1][0] = "FORMAT";
765 tag[1][1] = "RIFF AMFF";
766 return make_duh( length, 2, ( const char * const (*) [ 2 ] ) tag, 1, & descptr, & sigdata );
767 }
768}
769
770DUH *dumb_read_riff_am( DUMBFILE * f, struct riff * stream )
771{
772 sigdata_t *sigdata;
773
774 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
775
776 sigdata = it_riff_am_load_sigdata( f, stream );
777
778 if (!sigdata)
779 return NULL;
780
781 {
782 const char *tag[2][2];
783 tag[0][0] = "TITLE";
784 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
785 tag[1][0] = "FORMAT";
786 tag[1][1] = "RIFF AM";
787 return make_duh( -1, 2, ( const char * const (*) [ 2 ] ) tag, 1, & descptr, & sigdata );
788 }
789}
dumb/src/it/readamf.c+0−559
@@ -1,559 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readamf.c - Code to read a DSMI AMF module from / / \ \
12 * an open file. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29static void it_amf_process_track( IT_ENTRY *entry_table, unsigned char *track, int rows, int channels )
30{
31 int last_instrument = 0;
32 int tracksize = track[ 0 ] + ( track[ 1 ] << 8 ) + ( track[ 2 ] << 16 );
33 track += 3;
34 while ( tracksize-- ) {
35 unsigned int row = track[ 0 ];
36 unsigned int command = track[ 1 ];
37 unsigned int argument = track[ 2 ];
38 IT_ENTRY * entry = entry_table + row * channels;
39 if ( row >= ( unsigned int ) rows ) break;
40 if ( command < 0x7F ) {
41 entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT | IT_ENTRY_VOLPAN;
42 entry->note = command;
43 if ( ! entry->instrument ) entry->instrument = last_instrument;
44 entry->volpan = argument;
45 }
46 else if ( command == 0x7F ) {
47 signed char row_delta = ( signed char ) argument;
48 int row_source = ( int ) row + ( int ) row_delta;
49 if ( row_source >= 0 && row_source < ( int ) rows ) {
50 *entry = entry_table[ row_source * channels ];
51 }
52 }
53 else if ( command == 0x80 ) {
54 entry->mask |= IT_ENTRY_INSTRUMENT;
55 last_instrument = argument + 1;
56 entry->instrument = last_instrument;
57 }
58 else if ( command == 0x83 ) {
59 entry->mask |= IT_ENTRY_VOLPAN;
60 entry->volpan = argument;
61 }
62 else {
63 unsigned int effect = command & 0x7F;
64 unsigned int effectvalue = argument;
65 switch (effect) {
66 case 0x01: effect = IT_SET_SPEED; break;
67
68 case 0x02: effect = IT_VOLUME_SLIDE;
69 case 0x0A: if ( effect == 0x0A ) effect = IT_VOLSLIDE_TONEPORTA;
70 case 0x0B: if ( effect == 0x0B ) effect = IT_VOLSLIDE_VIBRATO;
71 if ( effectvalue & 0x80 ) effectvalue = ( -( signed char ) effectvalue ) & 0x0F;
72 else effectvalue = ( effectvalue & 0x0F ) << 4;
73 break;
74
75 case 0x04:
76 if ( effectvalue & 0x80 ) {
77 effect = IT_PORTAMENTO_UP;
78 effectvalue = ( -( signed char ) effectvalue ) & 0x7F;
79 }
80 else {
81 effect = IT_PORTAMENTO_DOWN;
82 }
83 break;
84
85 case 0x06: effect = IT_TONE_PORTAMENTO; break;
86
87 case 0x07: effect = IT_TREMOR; break;
88
89 case 0x08: effect = IT_ARPEGGIO; break;
90
91 case 0x09: effect = IT_VIBRATO; break;
92
93 case 0x0C: effect = IT_BREAK_TO_ROW; break;
94
95 case 0x0D: effect = IT_JUMP_TO_ORDER; break;
96
97 case 0x0F: effect = IT_RETRIGGER_NOTE; break;
98
99 case 0x10: effect = IT_SET_SAMPLE_OFFSET; break;
100
101 case 0x11:
102 if ( effectvalue ) {
103 effect = IT_VOLUME_SLIDE;
104 if ( effectvalue & 0x80 )
105 effectvalue = 0xF0 | ( ( -( signed char ) effectvalue ) & 0x0F );
106 else
107 effectvalue = 0x0F | ( ( effectvalue & 0x0F ) << 4 );
108 }
109 else
110 effect = 0;
111 break;
112
113 case 0x12:
114 case 0x16:
115 if ( effectvalue ) {
116 int mask = ( effect == 0x16 ) ? 0xE0 : 0xF0;
117 effect = ( effectvalue & 0x80 ) ? IT_PORTAMENTO_UP : IT_PORTAMENTO_DOWN;
118 if ( effectvalue & 0x80 )
119 effectvalue = mask | ( ( -( signed char ) effectvalue ) & 0x0F );
120 else
121 effectvalue = mask | ( effectvalue & 0x0F );
122 }
123 else
124 effect = 0;
125 break;
126
127 case 0x13:
128 effect = IT_S;
129 effectvalue = EFFECT_VALUE( IT_S_NOTE_DELAY, effectvalue & 0x0F );
130 break;
131
132 case 0x14:
133 effect = IT_S;
134 effectvalue = EFFECT_VALUE( IT_S_DELAYED_NOTE_CUT, effectvalue & 0x0F );
135 break;
136
137 case 0x15: effect = IT_SET_SONG_TEMPO; break;
138
139 case 0x17:
140 effectvalue = ( effectvalue + 64 ) & 0x7F;
141 if ( entry->mask & IT_ENTRY_EFFECT ) {
142 if ( !( entry->mask & IT_ENTRY_VOLPAN ) ) {
143 entry->mask |= IT_ENTRY_VOLPAN;
144 entry->volpan = ( effectvalue / 2 ) + 128;
145 }
146 effect = 0;
147 }
148 else {
149 effect = IT_SET_PANNING;
150 }
151 break;
152
153 default: effect = effectvalue = 0;
154 }
155 if ( effect ) {
156 entry->mask |= IT_ENTRY_EFFECT;
157 entry->effect = effect;
158 entry->effectvalue = effectvalue;
159 }
160 }
161 track += 3;
162 }
163}
164
165static int it_amf_process_pattern( IT_PATTERN *pattern, IT_ENTRY *entry_table, int rows, int channels )
166{
167 int i, j;
168 int n_entries = rows;
169 IT_ENTRY * entry;
170
171 pattern->n_rows = rows;
172
173 for ( i = 0, j = channels * rows; i < j; i++ ) {
174 if ( entry_table[ i ].mask ) {
175 n_entries++;
176 }
177 }
178
179 pattern->n_entries = n_entries;
180
181 pattern->entry = entry = malloc( n_entries * sizeof( IT_ENTRY ) );
182 if ( !entry ) {
183 return -1;
184 }
185
186 for ( i = 0; i < rows; i++ ) {
187 for ( j = 0; j < channels; j++ ) {
188 if ( entry_table[ i * channels + j ].mask ) {
189 *entry = entry_table[ i * channels + j ];
190 entry->channel = j;
191 entry++;
192 }
193 }
194 IT_SET_END_ROW( entry );
195 entry++;
196 }
197
198 return 0;
199}
200
201static int it_amf_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, int * offset, int ver )
202{
203 int exists;
204
205 exists = dumbfile_getc( f );
206
207 dumbfile_getnc( (char *) sample->name, 32, f );
208 sample->name[32] = 0;
209
210 dumbfile_getnc( (char *) sample->filename, 13, f );
211 sample->filename[13] = 0;
212
213 *offset = (int)dumbfile_igetl( f );
214 sample->length = dumbfile_igetl( f );
215 sample->C5_speed = dumbfile_igetw( f );
216 sample->default_volume = dumbfile_getc( f );
217 sample->global_volume = 64;
218 if ( sample->default_volume > 64 ) sample->default_volume = 64;
219
220 if ( ver >= 11 ) {
221 sample->loop_start = dumbfile_igetl( f );
222 sample->loop_end = dumbfile_igetl( f );
223 } else {
224 sample->loop_start = dumbfile_igetw( f );
225 sample->loop_end = sample->length;
226 }
227
228 if ( sample->length <= 0 ) {
229 sample->flags = 0;
230 return 0;
231 }
232
233 sample->flags = exists == 1 ? IT_SAMPLE_EXISTS : 0;
234
235 sample->default_pan = 0;
236 sample->finetune = 0;
237
238 if ( sample->loop_end > sample->loop_start + 2 && sample->loop_end <= sample->length )
239 sample->flags |= IT_SAMPLE_LOOP;
240
241 sample->vibrato_speed = 0;
242 sample->vibrato_depth = 0;
243 sample->vibrato_rate = 0;
244 sample->vibrato_waveform = 0; // do we have to set _all_ these?
245 sample->max_resampling_quality = -1;
246
247 return dumbfile_error(f);
248}
249
250
251
252static int it_amf_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
253{
254 int i, read_length = 0;
255
256 sample->data = malloc( sample->length );
257
258 if ( !sample->data )
259 return -1;
260
261 if ( sample->length )
262 read_length = (int)dumbfile_getnc( sample->data, sample->length, f );
263
264 for ( i = 0; i < read_length; i++ ) {
265 ( ( signed char * ) sample->data )[ i ] ^= 0x80;
266 }
267
268 for ( i = read_length; i < sample->length; i++ ) {
269 ( ( signed char * ) sample->data )[ i ] = 0;
270 }
271
272 return 0; /* Sometimes the last sample is truncated :( */
273}
274
275static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
276{
277 DUMB_IT_SIGDATA *sigdata;
278 int i, j, ver, ntracks, realntracks, nchannels;
279
280 int maxsampleseekpos = 0;
281 int sampleseekpos[256];
282
283 unsigned short *orderstotracks;
284 unsigned short *trackmap;
285 unsigned int tracksize[256];
286
287 unsigned char **track;
288
289 static const char sig[] = "AMF";
290
291 char signature [3];
292
293 if ( dumbfile_getnc( signature, 3, f ) != 3 ||
294 memcmp( signature, sig, 3 ) ) {
295 return NULL;
296 }
297
298 *version = ver = dumbfile_getc( f );
299 if ( ver < 10 || ver > 14) {
300 return NULL;
301 }
302
303 sigdata = malloc(sizeof(*sigdata));
304 if (!sigdata) {
305 return NULL;
306 }
307
308 dumbfile_getnc( (char *) sigdata->name, 32, f );
309 sigdata->name[ 32 ] = 0;
310 sigdata->n_samples = dumbfile_getc( f );
311 sigdata->n_orders = dumbfile_getc( f );
312 ntracks = dumbfile_igetw( f );
313 nchannels = dumbfile_getc( f );
314
315 if ( dumbfile_error( f ) ||
316 sigdata->n_samples < 1 || sigdata->n_samples > 255 ||
317 sigdata->n_orders < 1 || sigdata->n_orders > 255 ||
318 ! ntracks ||
319 nchannels < 1 || nchannels > 32 ) {
320 free( sigdata );
321 return NULL;
322 }
323
324 sigdata->n_pchannels = nchannels;
325
326 memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );
327
328 if ( ver >= 11 ) {
329 int nchannels = ( ver >= 13 ) ? 32 : 16;
330 for ( i = 0; i < nchannels; i++ ) {
331 signed char panpos = dumbfile_getc( f );
332 int pan = ( panpos + 64 ) / 2;
333 if ( pan < 0 ) pan = 0;
334 else if ( pan > 64 ) pan = IT_SURROUND;
335 sigdata->channel_pan[ i ] = pan;
336 }
337 }
338 else {
339 int sep = 32 * dumb_it_default_panning_separation / 100;
340 for ( i = 0; i < 16; i++ ) {
341 sigdata->channel_pan[ i ] = ( dumbfile_getc( f ) & 1 ) ? 32 - sep : 32 + sep;
342 }
343 }
344
345 sigdata->tempo = 125;
346 sigdata->speed = 6;
347 if ( ver >= 13 ) {
348 i = dumbfile_getc( f );
349 if ( i >= 32 ) sigdata->tempo = i;
350 i = dumbfile_getc( f );
351 if ( i <= 32 ) sigdata->speed = i;
352 }
353
354 sigdata->order = malloc( sigdata->n_orders );
355 if ( !sigdata->order ) {
356 free( sigdata );
357 return NULL;
358 }
359
360 orderstotracks = malloc( sigdata->n_orders * nchannels * sizeof( unsigned short ) );
361 if ( !orderstotracks ) {
362 free( sigdata->order );
363 free( sigdata );
364 return NULL;
365 }
366
367 for ( i = 0; i < sigdata->n_orders; i++ ) {
368 sigdata->order[ i ] = i;
369 tracksize[ i ] = 64;
370 if ( ver >= 14 ) {
371 tracksize[ i ] = dumbfile_igetw( f );
372 }
373 for ( j = 0; j < nchannels; j++ ) {
374 orderstotracks[ i * nchannels + j ] = dumbfile_igetw( f );
375 }
376 }
377
378 if ( dumbfile_error( f ) ) {
379 free( orderstotracks );
380 free( sigdata->order );
381 free( sigdata );
382 return NULL;
383 }
384
385 sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
386 if ( !sigdata->sample ) {
387 free( orderstotracks );
388 free( sigdata->order );
389 free( sigdata );
390 return NULL;
391 }
392
393 sigdata->restart_position = 0;
394
395 sigdata->song_message = NULL;
396 sigdata->instrument = NULL;
397 sigdata->pattern = NULL;
398 sigdata->midi = NULL;
399 sigdata->checkpoint = NULL;
400
401 sigdata->n_instruments = 0;
402
403 for ( i = 0; i < sigdata->n_samples; ++i )
404 sigdata->sample[i].data = NULL;
405
406 for ( i = 0; i < sigdata->n_samples; ++i ) {
407 int offset;
408 if ( it_amf_read_sample_header( &sigdata->sample[i], f, &offset, ver ) ) {
409 goto error_ott;
410 }
411 sampleseekpos[ i ] = offset;
412 if ( offset > maxsampleseekpos ) maxsampleseekpos = offset;
413 }
414
415 sigdata->n_patterns = sigdata->n_orders;
416
417 sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
418 if ( !sigdata->pattern ) {
419 goto error_ott;
420 }
421 for (i = 0; i < sigdata->n_patterns; ++i)
422 sigdata->pattern[i].entry = NULL;
423
424 trackmap = malloc( ntracks * sizeof( unsigned short ) );
425 if ( !trackmap ) {
426 goto error_ott;
427 }
428
429 if ( dumbfile_getnc( ( char * ) trackmap, ntracks * sizeof( unsigned short ), f ) != (long)(ntracks * sizeof( unsigned short )) ) {
430 goto error_tm;
431 }
432
433 realntracks = 0;
434
435 for ( i = 0; i < ntracks; i++ ) {
436 if ( trackmap[ i ] > realntracks ) realntracks = trackmap[ i ];
437 }
438
439 track = calloc( realntracks, sizeof( unsigned char * ) );
440 if ( !track ) {
441 goto error_tm;
442 }
443
444 for ( i = 0; i < realntracks; i++ ) {
445 int tracksize = dumbfile_igetw( f );
446 tracksize += dumbfile_getc( f ) << 16;
447 track[ i ] = malloc( tracksize * 3 + 3 );
448 if ( !track[ i ] ) {
449 goto error_all;
450 }
451 track[ i ][ 0 ] = tracksize & 255;
452 track[ i ][ 1 ] = ( tracksize >> 8 ) & 255;
453 track[ i ][ 2 ] = ( tracksize >> 16 ) & 255;
454 if ( dumbfile_getnc( (char *) track[ i ] + 3, tracksize * 3, f ) != tracksize * 3 ) {
455 goto error_all;
456 }
457 }
458
459 for ( i = 1; i <= maxsampleseekpos; i++ ) {
460 for ( j = 0; j < sigdata->n_samples; j++ ) {
461 if ( sampleseekpos[ j ] == i ) {
462 if ( it_amf_read_sample_data( &sigdata->sample[ j ], f ) ) {
463 goto error_all;
464 }
465 break;
466 }
467 }
468 }
469
470 /* Process tracks into patterns */
471 for ( i = 0; i < sigdata->n_patterns; i++ ) {
472 IT_ENTRY * entry_table = calloc( tracksize[ i ] * nchannels, sizeof( IT_ENTRY ) );
473 if ( !entry_table ) {
474 goto error_all;
475 }
476 for ( j = 0; j < nchannels; j++ ) {
477 int ntrack = orderstotracks[ i * nchannels + j ];
478 if ( ntrack && ntrack <= ntracks ) {
479 int realtrack = trackmap[ ntrack - 1 ];
480 if ( realtrack ) {
481 realtrack--;
482 if ( realtrack < realntracks && track[ realtrack ] ) {
483 it_amf_process_track( entry_table + j, track[ realtrack ], tracksize[ i ], nchannels );
484 }
485 }
486 }
487 }
488 if ( it_amf_process_pattern( &sigdata->pattern[ i ], entry_table, tracksize[ i ], nchannels ) ) {
489 free( entry_table );
490 goto error_all;
491 }
492 free( entry_table );
493 }
494
495 /* Now let's initialise the remaining variables, and we're done! */
496 sigdata->flags = IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO | IT_WAS_AN_S3M;
497
498 sigdata->global_volume = 128;
499 sigdata->mixing_volume = 48;
500 sigdata->pan_separation = 128;
501
502 _dumb_it_fix_invalid_orders(sigdata);
503
504 for ( i = 0; i < realntracks; i++ ) {
505 if ( track[ i ] ) {
506 free( track[ i ] );
507 }
508 }
509 free( track );
510 free( trackmap );
511 free( orderstotracks );
512
513 return sigdata;
514
515error_all:
516 for ( i = 0; i < realntracks; i++ ) {
517 if ( track[ i ] ) {
518 free( track[ i ] );
519 }
520 }
521 free( track );
522error_tm:
523 free( trackmap );
524error_ott:
525 free( orderstotracks );
526 _dumb_it_unload_sigdata( sigdata );
527 return NULL;
528}
529
530
531
532DUH *dumb_read_amf_quick(DUMBFILE *f)
533{
534 sigdata_t *sigdata;
535
536 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
537
538 int version;
539
540 sigdata = it_amf_load_sigdata(f, &version);
541
542 if (!sigdata)
543 return NULL;
544
545 {
546 const char *tag[2][2];
547 char ver_string[14];
548 tag[0][0] = "TITLE";
549 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
550 tag[1][0] = "FORMAT";
551 memcpy( ver_string, "DSMI AMF v", 10 );
552 ver_string[10] = '0' + version / 10;
553 ver_string[11] = '.';
554 ver_string[12] = '0' + version % 10;
555 ver_string[13] = 0;
556 tag[1][1] = ver_string;
557 return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
558 }
559}
dumb/src/it/readany.c+0−132
@@ -1,132 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readany.c - Code to detect and read any of the / / \ \
12 * module formats supported by DUMB. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22
23#include "dumb.h"
24
25#ifdef _MSC_VER
26 #define strnicmp _strnicmp
27#else
28 #if defined(unix) || defined(__unix__) || defined(__unix)
29 #include <strings.h>
30 #endif
31 #define strnicmp strncasecmp
32#endif
33
34enum { maximum_signature_size = 0x30 };
35
36DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong)
37{
38 unsigned char signature[ maximum_signature_size ];
39 unsigned long signature_size;
40 DUH * duh = NULL;
41
42 /* signature_size = dumbfile_get_size(f); */
43
44 signature_size = dumbfile_getnc( (char *)signature, maximum_signature_size, f );
45 dumbfile_seek( f, 0, DFS_SEEK_SET );
46
47 if (signature_size >= 4 &&
48 signature[0] == 'I' && signature[1] == 'M' &&
49 signature[2] == 'P' && signature[3] == 'M')
50 {
51 duh = dumb_read_it_quick( f );
52 }
53 else if (signature_size >= 17 && !memcmp(signature, "Extended Module: ", 17))
54 {
55 duh = dumb_read_xm_quick( f );
56 }
57 else if (signature_size >= 0x30 &&
58 signature[0x2C] == 'S' && signature[0x2D] == 'C' &&
59 signature[0x2E] == 'R' && signature[0x2F] == 'M')
60 {
61 duh = dumb_read_s3m_quick( f );
62 }
63 else if (signature_size >= 30 &&
64 /*signature[28] == 0x1A &&*/ signature[29] == 2 &&
65 ( ! strnicmp( ( const char * ) signature + 20, "!Scream!", 8 ) ||
66 ! strnicmp( ( const char * ) signature + 20, "BMOD2STM", 8 ) ||
67 ! strnicmp( ( const char * ) signature + 20, "WUZAMOD!", 8 ) ) )
68 {
69 duh = dumb_read_stm_quick( f );
70 }
71 else if (signature_size >= 2 &&
72 ((signature[0] == 0x69 && signature[1] == 0x66) ||
73 (signature[0] == 0x4A && signature[1] == 0x4E)))
74 {
75 duh = dumb_read_669_quick( f );
76 }
77 else if (signature_size >= 0x30 &&
78 signature[0x2C] == 'P' && signature[0x2D] == 'T' &&
79 signature[0x2E] == 'M' && signature[0x2F] == 'F')
80 {
81 duh = dumb_read_ptm_quick( f );
82 }
83 else if (signature_size >= 4 &&
84 signature[0] == 'P' && signature[1] == 'S' &&
85 signature[2] == 'M' && signature[3] == ' ')
86 {
87 duh = dumb_read_psm_quick( f, subsong );
88 }
89 else if (signature_size >= 4 &&
90 signature[0] == 'P' && signature[1] == 'S' &&
91 signature[2] == 'M' && signature[3] == 254)
92 {
93 duh = dumb_read_old_psm_quick( f );
94 }
95 else if (signature_size >= 3 &&
96 signature[0] == 'M' && signature[1] == 'T' &&
97 signature[2] == 'M')
98 {
99 duh = dumb_read_mtm_quick( f );
100 }
101 else if ( signature_size >= 4 &&
102 signature[0] == 'R' && signature[1] == 'I' &&
103 signature[2] == 'F' && signature[3] == 'F')
104 {
105 duh = dumb_read_riff_quick( f );
106 }
107 else if ( signature_size >= 24 &&
108 !memcmp( signature, "ASYLUM Music Format", 19 ) &&
109 !memcmp( signature + 19, " V1.0", 5 ) )
110 {
111 duh = dumb_read_asy_quick( f );
112 }
113 else if ( signature_size >= 3 &&
114 signature[0] == 'A' && signature[1] == 'M' &&
115 signature[2] == 'F')
116 {
117 duh = dumb_read_amf_quick( f );
118 }
119 else if ( signature_size >= 8 &&
120 !memcmp( signature, "OKTASONG", 8 ) )
121 {
122 duh = dumb_read_okt_quick( f );
123 }
124
125 if ( !duh )
126 {
127 dumbfile_seek( f, 0, DFS_SEEK_SET );
128 duh = dumb_read_mod_quick( f, restrict_ );
129 }
130
131 return duh;
132}
dumb/src/it/readasy.c+0−339
@@ -1,339 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readasy.c - Code to read an ASYLUM Music Format / / \ \
12 * module from an open file. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer )
30{
31 int pos;
32 int channel;
33 int row;
34 IT_ENTRY *entry;
35
36 pattern->n_rows = 64;
37
38 if ( dumbfile_getnc( (char *) buffer, 64 * 8 * 4, f ) != 64 * 8 * 4 )
39 return -1;
40
41 /* compute number of entries */
42 pattern->n_entries = 64; /* Account for the row end markers */
43 pos = 0;
44 for ( row = 0; row < 64; ++row ) {
45 for ( channel = 0; channel < 8; ++channel ) {
46 if ( buffer[ pos + 0 ] | buffer[ pos + 1 ] | buffer[ pos + 2 ] | buffer[ pos + 3 ] )
47 ++pattern->n_entries;
48 pos += 4;
49 }
50 }
51
52 pattern->entry = malloc( pattern->n_entries * sizeof( *pattern->entry ) );
53 if ( !pattern->entry )
54 return -1;
55
56 entry = pattern->entry;
57 pos = 0;
58 for ( row = 0; row < 64; ++row ) {
59 for ( channel = 0; channel < 8; ++channel ) {
60 if ( buffer[ pos + 0 ] | buffer[ pos + 1 ] | buffer[ pos + 2 ] | buffer[ pos + 3 ] ) {
61 entry->channel = channel;
62 entry->mask = 0;
63
64 if ( buffer[ pos + 0 ] && buffer[ pos + 0 ] < 96 ) {
65 entry->note = buffer[ pos + 0 ];
66 entry->mask |= IT_ENTRY_NOTE;
67 }
68
69 if ( buffer[ pos + 1 ] && buffer[ pos + 1 ] <= 64 ) {
70 entry->instrument = buffer[ pos + 1 ];
71 entry->mask |= IT_ENTRY_INSTRUMENT;
72 }
73
74 _dumb_it_xm_convert_effect( buffer[ pos + 2 ], buffer[ pos + 3 ], entry, 1 );
75
76 // fixup
77 switch ( entry->effect ) {
78 case IT_SET_PANNING:
79 entry->effectvalue <<= 1;
80 break;
81 }
82
83 if ( entry->mask ) ++entry;
84 }
85 pos += 4;
86 }
87 IT_SET_END_ROW( entry );
88 ++entry;
89 }
90
91 pattern->n_entries = entry - pattern->entry;
92
93 return 0;
94}
95
96
97
98static int it_asy_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f )
99{
100 int finetune, key_offset;
101
102/**
103 21 22 Chars Sample 1 name. If the name is not a full
104 22 chars in length, it will be null
105 terminated.
106
107If
108the sample name begins with a '#' character (ASCII $23 (35)) then this is
109assumed not to be an instrument name, and is probably a message.
110*/
111 dumbfile_getnc( (char *) sample->name, 22, f );
112 sample->name[22] = 0;
113
114 sample->filename[0] = 0;
115
116/** Each finetune step changes the note 1/8th of a semitone. */
117 finetune = ( signed char ) ( dumbfile_getc( f ) << 4 ) >> 4; /* signed nibble */
118 sample->default_volume = dumbfile_getc( f ); // Should we be setting global_volume to this instead?
119 sample->global_volume = 64;
120 if ( sample->default_volume > 64 ) sample->default_volume = 64;
121 key_offset = ( signed char ) dumbfile_getc( f ); /* base key offset */
122 sample->length = dumbfile_igetl( f );
123 sample->loop_start = dumbfile_igetl( f );
124 sample->loop_end = sample->loop_start + dumbfile_igetl( f );
125
126 if ( sample->length <= 0 ) {
127 sample->flags = 0;
128 return 0;
129 }
130
131 sample->flags = IT_SAMPLE_EXISTS;
132
133 sample->default_pan = 0;
134 sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 * pow( DUMB_SEMITONE_BASE, key_offset ) );//( long )( 16726.0 * pow( DUMB_PITCH_BASE, finetune * 32 ) );
135 sample->finetune = finetune * 32;
136 // the above line might be wrong
137
138 if ( ( sample->loop_end - sample->loop_start > 2 ) && ( sample->loop_end <= sample->length ) )
139 sample->flags |= IT_SAMPLE_LOOP;
140
141 sample->vibrato_speed = 0;
142 sample->vibrato_depth = 0;
143 sample->vibrato_rate = 0;
144 sample->vibrato_waveform = 0; // do we have to set _all_ these?
145 sample->max_resampling_quality = -1;
146
147 return dumbfile_error(f);
148}
149
150
151
152static int it_asy_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
153{
154 long truncated_size;
155
156 /* let's get rid of the sample data coming after the end of the loop */
157 if ( ( sample->flags & IT_SAMPLE_LOOP ) && sample->loop_end < sample->length ) {
158 truncated_size = sample->length - sample->loop_end;
159 sample->length = sample->loop_end;
160 } else {
161 truncated_size = 0;
162 }
163
164 sample->data = malloc( sample->length );
165
166 if ( !sample->data )
167 return -1;
168
169 if ( sample->length )
170 dumbfile_getnc( sample->data, sample->length, f );
171
172 dumbfile_skip( f, truncated_size );
173
174 return dumbfile_error( f );
175}
176
177
178
179static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
180{
181 DUMB_IT_SIGDATA *sigdata;
182 int i;
183
184 static const char sig_part[] = "ASYLUM Music Format";
185 static const char sig_rest[] = " V1.0"; /* whee, string space optimization with format type below */
186
187 char signature [32];
188
189 if ( dumbfile_getnc( signature, 32, f ) != 32 ||
190 memcmp( signature, sig_part, 19 ) ||
191 memcmp( signature + 19, sig_rest, 5 ) ) {
192 return NULL;
193 }
194
195 sigdata = malloc(sizeof(*sigdata));
196 if (!sigdata) {
197 return NULL;
198 }
199
200 sigdata->speed = dumbfile_getc( f ); /* XXX seems to fit the files I have */
201 sigdata->tempo = dumbfile_getc( f ); /* ditto */
202 sigdata->n_samples = dumbfile_getc( f ); /* ditto */
203 sigdata->n_patterns = dumbfile_getc( f );
204 sigdata->n_orders = dumbfile_getc( f );
205 sigdata->restart_position = dumbfile_getc( f );
206
207 if ( dumbfile_error( f ) || !sigdata->n_samples || sigdata->n_samples > 64 || !sigdata->n_patterns ||
208 !sigdata->n_orders ) {
209 free( sigdata );
210 return NULL;
211 }
212
213 if ( sigdata->restart_position > sigdata->n_orders ) /* XXX */
214 sigdata->restart_position = 0;
215
216 sigdata->order = malloc( sigdata->n_orders );
217 if ( !sigdata->order ) {
218 free( sigdata );
219 return NULL;
220 }
221
222 if ( dumbfile_getnc( (char *) sigdata->order, sigdata->n_orders, f ) != sigdata->n_orders ||
223 dumbfile_skip( f, 256 - sigdata->n_orders ) ) {
224 free( sigdata->order );
225 free( sigdata );
226 return NULL;
227 }
228
229 sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
230 if ( !sigdata->sample ) {
231 free( sigdata->order );
232 free( sigdata );
233 return NULL;
234 }
235
236 sigdata->song_message = NULL;
237 sigdata->instrument = NULL;
238 sigdata->pattern = NULL;
239 sigdata->midi = NULL;
240 sigdata->checkpoint = NULL;
241
242 sigdata->n_instruments = 0;
243
244 for ( i = 0; i < sigdata->n_samples; ++i )
245 sigdata->sample[i].data = NULL;
246
247 for ( i = 0; i < sigdata->n_samples; ++i ) {
248 if ( it_asy_read_sample_header( &sigdata->sample[i], f ) ) {
249 _dumb_it_unload_sigdata( sigdata );
250 return NULL;
251 }
252 }
253
254 if ( dumbfile_skip( f, 37 * ( 64 - sigdata->n_samples ) ) ) {
255 _dumb_it_unload_sigdata( sigdata );
256 return NULL;
257 }
258
259 sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
260 if ( !sigdata->pattern ) {
261 _dumb_it_unload_sigdata( sigdata );
262 return NULL;
263 }
264 for (i = 0; i < sigdata->n_patterns; ++i)
265 sigdata->pattern[i].entry = NULL;
266
267 /* Read in the patterns */
268 {
269 unsigned char *buffer = malloc( 64 * 8 * 4 ); /* 64 rows * 8 channels * 4 bytes */
270 if ( !buffer ) {
271 _dumb_it_unload_sigdata( sigdata );
272 return NULL;
273 }
274 for ( i = 0; i < sigdata->n_patterns; ++i ) {
275 if ( it_asy_read_pattern( &sigdata->pattern[i], f, buffer ) != 0 ) {
276 free( buffer );
277 _dumb_it_unload_sigdata( sigdata );
278 return NULL;
279 }
280 }
281 free( buffer );
282 }
283
284 /* And finally, the sample data */
285 for ( i = 0; i < sigdata->n_samples; ++i ) {
286 if ( it_asy_read_sample_data( &sigdata->sample[i], f ) ) {
287 _dumb_it_unload_sigdata( sigdata );
288 return NULL;
289 }
290 }
291
292 /* Now let's initialise the remaining variables, and we're done! */
293 sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
294
295 sigdata->global_volume = 128;
296 sigdata->mixing_volume = 48;
297 sigdata->pan_separation = 128;
298
299 sigdata->n_pchannels = 8;
300
301 sigdata->name[0] = 0;
302
303 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
304
305 for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) {
306 int sep = 32 * dumb_it_default_panning_separation / 100;
307 sigdata->channel_pan[i+0] = 32 - sep;
308 sigdata->channel_pan[i+1] = 32 + sep;
309 sigdata->channel_pan[i+2] = 32 + sep;
310 sigdata->channel_pan[i+3] = 32 - sep;
311 }
312
313 _dumb_it_fix_invalid_orders(sigdata);
314
315 return sigdata;
316}
317
318
319
320DUH *dumb_read_asy_quick(DUMBFILE *f)
321{
322 sigdata_t *sigdata;
323
324 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
325
326 sigdata = it_asy_load_sigdata(f);
327
328 if (!sigdata)
329 return NULL;
330
331 {
332 const char *tag[2][2];
333 tag[0][0] = "TITLE";
334 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
335 tag[1][0] = "FORMAT";
336 tag[1][1] = "ASYLUM Music Format";
337 return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
338 }
339}
dumb/src/it/readdsmf.c+0−383
@@ -1,383 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readam.c - Code to read a RIFF DSMF module / / \ \
12 * from a parsed RIFF structure. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22
23#include "dumb.h"
24#include "internal/it.h"
25#include "internal/riff.h"
26
27static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int len )
28{
29 int flags;
30
31 dumbfile_getnc( (char *) sample->filename, 13, f );
32 sample->filename[ 14 ] = 0;
33
34 flags = dumbfile_igetw( f );
35 sample->default_volume = dumbfile_getc( f );
36 sample->length = dumbfile_igetl( f );
37 sample->loop_start = dumbfile_igetl( f );
38 sample->loop_end = dumbfile_igetl( f );
39 dumbfile_skip( f, 32 - 28 );
40 sample->C5_speed = dumbfile_igetw( f ) * 2;
41 dumbfile_skip( f, 36 - 34 );
42 dumbfile_getnc( (char *) sample->name, 28, f );
43 sample->name[ 28 ] = 0;
44
45 /*if ( data[ 0x38 ] || data[ 0x39 ] || data[ 0x3A ] || data[ 0x3B ] )
46 return -1;*/
47
48 if ( ! sample->length ) {
49 sample->flags &= ~IT_SAMPLE_EXISTS;
50 return 0;
51 }
52
53 /*if ( flags & ~( 2 | 1 ) )
54 return -1;*/
55
56 if ( sample->length + 64 > len )
57 return -1;
58
59 sample->flags = IT_SAMPLE_EXISTS;
60
61 sample->default_pan = 0;
62 sample->global_volume = 64;
63 sample->vibrato_speed = 0;
64 sample->vibrato_depth = 0;
65 sample->vibrato_rate = 0;
66 sample->vibrato_waveform = IT_VIBRATO_SINE;
67 sample->finetune = 0;
68 sample->max_resampling_quality = -1;
69
70 if ( flags & 1 )
71 {
72 if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) &&
73 ((unsigned int)sample->loop_start < (unsigned int)sample->loop_end))
74 {
75 sample->length = sample->loop_end;
76 sample->flags |= IT_SAMPLE_LOOP;
77 if ( flags & 0x10 ) sample->flags |= IT_SAMPLE_PINGPONG_LOOP;
78 }
79 }
80
81 sample->data = malloc( sample->length );
82 if ( ! sample->data )
83 return -1;
84
85 dumbfile_getnc( sample->data, sample->length, f );
86
87 if ( ! ( flags & 2 ) )
88 {
89 for ( flags = 0; flags < sample->length; ++flags )
90 ( ( signed char * ) sample->data ) [ flags ] ^= 0x80;
91 }
92
93 return 0;
94}
95
96static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len )
97{
98 int length, row;
99 unsigned flags;
100 long start, end;
101 int p, q, r;
102 IT_ENTRY * entry;
103
104 length = dumbfile_igetw( f );
105 if ( length > len ) return -1;
106
107 len = length - 2;
108
109 pattern->n_rows = 64;
110 pattern->n_entries = 64;
111
112 row = 0;
113
114 start = dumbfile_pos( f );
115 end = start + len;
116
117 while ( (row < 64) && !dumbfile_error( f ) && (dumbfile_pos( f ) < end) ) {
118 p = dumbfile_getc( f );
119 if ( ! p ) {
120 ++ row;
121 continue;
122 }
123
124 flags = p & 0xF0;
125
126 if (flags) {
127 ++ pattern->n_entries;
128 if (flags & 0x80) dumbfile_skip( f, 1 );
129 if (flags & 0x40) dumbfile_skip( f, 1 );
130 if (flags & 0x20) dumbfile_skip( f, 1 );
131 if (flags & 0x10) dumbfile_skip( f, 2 );
132 }
133 }
134
135 if ( pattern->n_entries == 64 ) return 0;
136
137 pattern->entry = malloc( pattern->n_entries * sizeof( * pattern->entry ) );
138 if ( ! pattern->entry ) return -1;
139
140 entry = pattern->entry;
141
142 row = 0;
143
144 if ( dumbfile_seek( f, start, DFS_SEEK_SET ) ) return -1;
145
146 while ( ( row < 64 ) && !dumbfile_error( f ) && ( dumbfile_pos( f ) < end ) )
147 {
148 p = dumbfile_getc( f );
149 if ( ! p )
150 {
151 IT_SET_END_ROW( entry );
152 ++ entry;
153 ++ row;
154 continue;
155 }
156
157 flags = p;
158 entry->channel = flags & 0x0F;
159 entry->mask = 0;
160
161 if ( flags & 0xF0 )
162 {
163 if ( flags & 0x80 )
164 {
165 q = dumbfile_getc( f );
166 if ( q )
167 {
168 entry->mask |= IT_ENTRY_NOTE;
169 entry->note = q - 1;
170 }
171 }
172
173 if ( flags & 0x40 )
174 {
175 q = dumbfile_getc( f );
176 if ( q )
177 {
178 entry->mask |= IT_ENTRY_INSTRUMENT;
179 entry->instrument = q;
180 }
181 }
182
183 if ( flags & 0x20 )
184 {
185 entry->mask |= IT_ENTRY_VOLPAN;
186 entry->volpan = dumbfile_getc( f );
187 }
188
189 if ( flags & 0x10 )
190 {
191 q = dumbfile_getc( f );
192 r = dumbfile_getc( f );
193 _dumb_it_xm_convert_effect( q, r, entry, 0 );
194 }
195
196 if (entry->mask) entry++;
197 }
198 }
199
200 while ( row < 64 )
201 {
202 IT_SET_END_ROW( entry );
203 ++ entry;
204 ++ row;
205 }
206
207 pattern->n_entries = entry - pattern->entry;
208 if ( ! pattern->n_entries ) return -1;
209
210 return 0;
211}
212
213static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * stream )
214{
215 DUMB_IT_SIGDATA *sigdata;
216
217 int n, o, found;
218
219 if ( ! stream ) goto error;
220
221 if ( stream->type != DUMB_ID( 'D', 'S', 'M', 'F' ) ) goto error;
222
223 sigdata = malloc(sizeof(*sigdata));
224 if ( ! sigdata ) goto error;
225
226 sigdata->n_patterns = 0;
227 sigdata->n_samples = 0;
228 sigdata->name[0] = 0;
229
230 found = 0;
231
232 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
233 {
234 struct riff_chunk * c = stream->chunks + n;
235 switch( c->type )
236 {
237 case DUMB_ID( 'S' ,'O' ,'N' ,'G' ):
238 /* initialization data */
239 if ( ( found ) || ( c->size < 192 ) ) goto error_sd;
240 found = 1;
241 break;
242
243 case DUMB_ID( 'P', 'A', 'T', 'T' ):
244 ++ sigdata->n_patterns;
245 break;
246
247 case DUMB_ID( 'I', 'N', 'S', 'T' ):
248 ++ sigdata->n_samples;
249 break;
250 }
251 }
252
253 if ( !found || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd;
254
255 if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd;
256
257 sigdata->song_message = NULL;
258 sigdata->order = NULL;
259 sigdata->instrument = NULL;
260 sigdata->sample = NULL;
261 sigdata->pattern = NULL;
262 sigdata->midi = NULL;
263 sigdata->checkpoint = NULL;
264
265 sigdata->mixing_volume = 48;
266 sigdata->pan_separation = 128;
267
268 sigdata->n_instruments = 0;
269 sigdata->n_orders = 0;
270 sigdata->restart_position = 0;
271
272 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
273
274 for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
275 int sep = 32 * dumb_it_default_panning_separation / 100;
276 sigdata->channel_pan[n ] = 32 - sep;
277 sigdata->channel_pan[n+1] = 32 + sep;
278 sigdata->channel_pan[n+2] = 32 + sep;
279 sigdata->channel_pan[n+3] = 32 - sep;
280 }
281
282 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
283 {
284 struct riff_chunk * c = stream->chunks + n;
285 switch ( c->type )
286 {
287 case DUMB_ID( 'S', 'O', 'N', 'G' ):
288 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
289 dumbfile_getnc( (char *) sigdata->name, 28, f );
290 sigdata->name[ 28 ] = 0;
291 sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
292 dumbfile_skip( f, 36 - 28 );
293 sigdata->n_orders = dumbfile_igetw( f );
294 //sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever
295 //sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 );
296 dumbfile_skip( f, 42 - 38 );
297 sigdata->n_pchannels = dumbfile_igetw( f );
298 sigdata->global_volume = dumbfile_getc( f );
299 sigdata->mixing_volume = dumbfile_getc( f );
300 sigdata->speed = dumbfile_getc( f );
301 sigdata->tempo = dumbfile_getc( f );
302
303 for ( o = 0; o < 16; ++o )
304 {
305 sigdata->channel_pan[ o ] = dumbfile_getc( f ) / 2;
306 }
307
308 sigdata->order = malloc( 128 );
309 if ( ! sigdata->order ) goto error_usd;
310 dumbfile_getnc( (char *) sigdata->order, 128, f );
311
312 break;
313 }
314 }
315
316 sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
317 if ( ! sigdata->pattern ) goto error_usd;
318 for ( n = 0; n < sigdata->n_patterns; ++n )
319 sigdata->pattern[ n ].entry = NULL;
320
321 sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
322 if ( ! sigdata->sample ) goto error_usd;
323 for ( n = 0; n < sigdata->n_samples; ++n )
324 {
325 IT_SAMPLE * sample = sigdata->sample + n;
326 sample->data = NULL;
327 }
328
329 sigdata->n_samples = 0;
330 sigdata->n_patterns = 0;
331
332 for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
333 {
334 struct riff_chunk * c = stream->chunks + n;
335 switch ( c->type )
336 {
337 case DUMB_ID( 'P', 'A', 'T', 'T' ):
338 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
339 if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, f, c->size ) ) goto error_usd;
340 ++ sigdata->n_patterns;
341 break;
342
343 case DUMB_ID( 'I', 'N', 'S', 'T' ):
344 if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
345 if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, f, c->size ) ) goto error_usd;
346 ++ sigdata->n_samples;
347 break;
348 }
349 }
350
351 _dumb_it_fix_invalid_orders( sigdata );
352
353 return sigdata;
354
355error_usd:
356 _dumb_it_unload_sigdata( sigdata );
357 goto error;
358error_sd:
359 free( sigdata );
360error:
361 return NULL;
362}
363
364DUH *dumb_read_riff_dsmf( DUMBFILE * f, struct riff * stream )
365{
366 sigdata_t *sigdata;
367
368 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
369
370 sigdata = it_riff_dsmf_load_sigdata( f, stream );
371
372 if (!sigdata)
373 return NULL;
374
375 {
376 const char *tag[2][2];
377 tag[0][0] = "TITLE";
378 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
379 tag[1][0] = "FORMAT";
380 tag[1][1] = "RIFF DSMF";
381 return make_duh( -1, 2, ( const char * const (*) [ 2 ] ) tag, 1, & descptr, & sigdata );
382 }
383}
dumb/src/it/readmod.c+0−637
@@ -1,637 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readmod.c - Code to read a good old-fashioned / / \ \
12 * Amiga module from an open file. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char *buffer)
30{
31 int pos;
32 int channel;
33 int row;
34 IT_ENTRY *entry;
35
36 pattern->n_rows = 64;
37
38 if (n_channels == 0) {
39 /* Read the first four channels, leaving gaps for the rest. */
40 for (pos = 0; pos < 64*8*4; pos += 8*4)
41 dumbfile_getnc((char *)buffer + pos, 4*4, f);
42 /* Read the other channels into the gaps we left. */
43 for (pos = 4*4; pos < 64*8*4; pos += 8*4)
44 dumbfile_getnc((char *)buffer + pos, 4*4, f);
45
46 n_channels = 8;
47 } else
48 dumbfile_getnc((char *)buffer, 64 * n_channels * 4, f);
49
50 if (dumbfile_error(f))
51 return -1;
52
53 /* compute number of entries */
54 pattern->n_entries = 64; /* Account for the row end markers */
55 pos = 0;
56 for (row = 0; row < 64; row++) {
57 for (channel = 0; channel < n_channels; channel++) {
58 if (buffer[pos+0] | buffer[pos+1] | buffer[pos+2] | buffer[pos+3])
59 pattern->n_entries++;
60 pos += 4;
61 }
62 }
63
64 pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
65 if (!pattern->entry)
66 return -1;
67
68 entry = pattern->entry;
69 pos = 0;
70 for (row = 0; row < 64; row++) {
71 for (channel = 0; channel < n_channels; channel++) {
72 if (buffer[pos+0] | buffer[pos+1] | buffer[pos+2] | buffer[pos+3]) {
73 unsigned char sample = (buffer[pos+0] & 0xF0) | (buffer[pos+2] >> 4);
74 int period = ((int)(buffer[pos+0] & 0x0F) << 8) | buffer[pos+1];
75
76 entry->channel = channel;
77 entry->mask = 0;
78
79 if (period) {
80 int note;
81 entry->mask |= IT_ENTRY_NOTE;
82
83 /* frequency = (AMIGA_DIVISOR / 8) / (period * 2)
84 * C-1: period = 214 -> frequency = 16726
85 * so, set C5_speed to 16726
86 * and period = 214 should translate to C5 aka 60
87 * halve the period, go up an octive
88 *
89 * period = 214 / pow(DUMB_SEMITONE_BASE, note - 60)
90 * pow(DUMB_SEMITONE_BASE, note - 60) = 214 / period
91 * note - 60 = log(214/period) / log(DUMB_SEMITONE_BASE)
92 */
93 note = (int)floor(log(214.0/period) / log(DUMB_SEMITONE_BASE) + 60.5);
94 entry->note = MID(0, note, 119);
95 // or should we preserve the period?
96 //entry->note = buffer[pos+0] & 0x0F; /* High nibble */
97 //entry->volpan = buffer[pos+1]; /* Low byte */
98 // and what about finetune?
99 }
100
101 if (sample) {
102 entry->mask |= IT_ENTRY_INSTRUMENT;
103 entry->instrument = sample;
104 }
105
106 _dumb_it_xm_convert_effect(buffer[pos+2] & 0x0F, buffer[pos+3], entry, 1);
107
108 entry++;
109 }
110 pos += 4;
111 }
112 IT_SET_END_ROW(entry);
113 entry++;
114 }
115
116 return 0;
117}
118
119
120
121static int it_mod_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, unsigned long fft, int stk)
122{
123 int finetune, loop_start, loop_length;
124
125/**
126 21 22 Chars Sample 1 name. If the name is not a full
127 22 chars in length, it will be null
128 terminated.
129
130If
131the sample name begins with a '#' character (ASCII $23 (35)) then this is
132assumed not to be an instrument name, and is probably a message.
133*/
134 dumbfile_getnc((char *)sample->name, 22, f);
135 sample->name[22] = 0;
136
137 sample->filename[0] = 0;
138
139 sample->length = dumbfile_mgetw(f) << 1;
140 if (fft == DUMB_ID('F','E','S','T'))
141 finetune = (signed char)((-dumbfile_getc(f) & 0x1F) << 3) >> 3;
142 else
143 finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
144/** Each finetune step changes the note 1/8th of a semitone. */
145 sample->global_volume = 64;
146 sample->default_volume = dumbfile_getc(f); // Should we be setting global_volume to this instead?
147 loop_start = dumbfile_mgetw(f);
148 if ( !stk ) loop_start <<= 1;
149 loop_length = dumbfile_mgetw(f) << 1;
150 if ( loop_length > 2 && loop_start + loop_length > sample->length && loop_start / 2 + loop_length <= sample->length )
151 loop_start /= 2;
152 sample->loop_start = loop_start;
153 sample->loop_end = loop_start + loop_length;
154/**
155Once this sample has been played completely from beginning
156to end, if the repeat length (next field) is greater than two bytes it
157will loop back to this position in the sample and continue playing. Once
158it has played for the repeat length, it continues to loop back to the
159repeat start offset. This means the sample continues playing until it is
160told to stop.
161*/
162
163 if (sample->length <= 0) {
164 sample->flags = 0;
165 return 0;
166 }
167
168 sample->flags = IT_SAMPLE_EXISTS;
169
170 sample->default_pan = 0;
171 sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
172 sample->finetune = finetune * ((fft == DUMB_ID('F','E','S','T')) ? 16 : 32);
173 // the above line might be wrong
174
175 if (sample->loop_end > sample->length)
176 sample->loop_end = sample->length;
177
178 if (sample->loop_end - sample->loop_start > 2)
179 sample->flags |= IT_SAMPLE_LOOP;
180
181 sample->vibrato_speed = 0;
182 sample->vibrato_depth = 0;
183 sample->vibrato_rate = 0;
184 sample->vibrato_waveform = 0; // do we have to set _all_ these?
185 sample->max_resampling_quality = -1;
186
187 return dumbfile_error(f);
188}
189
190
191
192static int it_mod_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f, unsigned long fft)
193{
194 long i;
195 long truncated_size;
196
197 /* let's get rid of the sample data coming after the end of the loop */
198 if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
199 truncated_size = sample->length - sample->loop_end;
200 sample->length = sample->loop_end;
201 } else {
202 truncated_size = 0;
203 }
204
205 if (sample->length) {
206 sample->data = malloc(sample->length);
207
208 if (!sample->data)
209 return -1;
210
211 /* Sample data are stored in "8-bit two's compliment format" (sic). */
212 /*
213 for (i = 0; i < sample->length; i++)
214 ((signed char *)sample->left)[i] = dumbfile_getc(f);
215 */
216 /* F U Olivier Lapicque */
217 if (sample->length >= 5)
218 {
219 i = dumbfile_getnc(sample->data, 5, f);
220 if (i == 5)
221 {
222 if (!memcmp(sample->data, "ADPCM", 5))
223 {
224 if (_dumb_it_read_sample_data_adpcm4(sample, f) < 0)
225 return -1;
226
227 return 0;
228 }
229 else
230 {
231 i += dumbfile_getnc(((char *)sample->data) + 5, sample->length - 5, f);
232 }
233 }
234 }
235 else
236 {
237 i = dumbfile_getnc(sample->data, sample->length, f);
238 }
239 if (i < sample->length)
240 {
241 if (i <= 0)
242 {
243 sample->flags = 0;
244 return 0;
245 }
246 sample->length = i;
247 if (sample->loop_end > i) sample->loop_end = i;
248 // holy crap!
249 if (sample->loop_start > i) sample->flags &= ~IT_SAMPLE_LOOP;
250 }
251 else
252 {
253 /* skip truncated data */
254 int feh = dumbfile_error(f);
255
256 if (truncated_size) dumbfile_skip(f, truncated_size);
257 // Should we be truncating it?
258
259 if (feh)
260 return -1;
261 }
262
263 if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) {
264 int delta = 0;
265 for (i = 0; i < sample->length; i++) {
266 delta += ((signed char *)sample->data)[i];
267 ((signed char *)sample->data)[i] = delta;
268 }
269 }
270 }
271
272 return 0;
273}
274
275
276
277#define MOD_FFT_OFFSET (20 + 31*(22+2+1+1+2+2) + 1 + 1 + 128)
278
279static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
280{
281 DUMB_IT_SIGDATA *sigdata;
282 int n_channels;
283 int i;
284 unsigned long fft;
285
286 if ( dumbfile_seek(f, MOD_FFT_OFFSET, DFS_SEEK_SET) )
287 return NULL;
288
289 fft = dumbfile_mgetl(f);
290 if (dumbfile_error(f))
291 return NULL;
292
293 if ( dumbfile_seek(f, 0, DFS_SEEK_SET) )
294 return NULL;
295
296 sigdata = malloc(sizeof(*sigdata));
297 if (!sigdata) {
298 return NULL;
299 }
300
301 /**
302 1 20 Chars Title of the song. If the title is not a
303 full 20 chars in length, it will be null-
304 terminated.
305 */
306 if (dumbfile_getnc((char *)sigdata->name, 20, f) < 20) {
307 free(sigdata);
308 return NULL;
309 }
310 sigdata->name[20] = 0;
311
312 sigdata->n_samples = 31;
313
314 switch (fft) {
315 case DUMB_ID('M','.','K','.'):
316 case DUMB_ID('M','!','K','!'):
317 case DUMB_ID('M','&','K','!'):
318 case DUMB_ID('N','.','T','.'):
319 case DUMB_ID('N','S','M','S'):
320 case DUMB_ID('F','L','T','4'):
321 case DUMB_ID('M',0,0,0):
322 case DUMB_ID('8',0,0,0):
323 case DUMB_ID('F','E','S','T'):
324 n_channels = 4;
325 break;
326 case DUMB_ID('F','L','T','8'):
327 n_channels = 0;
328 /* 0 indicates a special case; two four-channel patterns must be
329 * combined into one eight-channel pattern. Pattern indexes must
330 * be halved. Why oh why do they obfuscate so?
331 */
332 /*for (i = 0; i < 128; i++)
333 sigdata->order[i] >>= 1;*/
334 break;
335 case DUMB_ID('C','D','8','1'):
336 case DUMB_ID('O','C','T','A'):
337 case DUMB_ID('O','K','T','A'):
338 n_channels = 8;
339 break;
340 case DUMB_ID('1','6','C','N'):
341 n_channels = 16;
342 break;
343 case DUMB_ID('3','2','C','N'):
344 n_channels = 32;
345 break;
346 default:
347 /* If we get an illegal tag, assume 4 channels 15 samples. */
348 if ((fft & 0x0000FFFFL) == DUMB_ID(0,0,'C','H')) {
349 if (fft >= '1' << 24 && fft < '4' << 24) {
350 n_channels = ((fft & 0x00FF0000L) >> 16) - '0';
351 if ((unsigned int)n_channels >= 10) {
352 /* Rightmost character wasn't a digit. */
353 n_channels = 4;
354 sigdata->n_samples = 15;
355 } else {
356 n_channels += (((fft & 0xFF000000L) >> 24) - '0') * 10;
357 /* MODs should really only go up to 32 channels, but we're lenient. */
358 if ((unsigned int)(n_channels - 1) >= DUMB_IT_N_CHANNELS - 1) {
359 /* No channels or too many? Can't be right... */
360 n_channels = 4;
361 sigdata->n_samples = 15;
362 }
363 }
364 } else {
365 n_channels = 4;
366 sigdata->n_samples = 15;
367 }
368 } else if ((fft & 0x00FFFFFFL) == DUMB_ID(0,'C','H','N')) {
369 n_channels = (fft >> 24) - '0';
370 if ((unsigned int)(n_channels - 1) >= 9) {
371 /* Character was '0' or it wasn't a digit */
372 n_channels = 4;
373 sigdata->n_samples = 15;
374 }
375 } else if ((fft & 0xFFFFFF00L) == DUMB_ID('T','D','Z',0)) {
376 n_channels = (fft & 0x000000FFL) - '0';
377 if ((unsigned int)(n_channels - 1) >= 9) {
378 /* We've been very lenient, given that it should have
379 * been 1, 2 or 3, but this MOD has been very naughty and
380 * must be punished.
381 */
382 n_channels = 4;
383 sigdata->n_samples = 15;
384 }
385 } else {
386 n_channels = 4;
387 sigdata->n_samples = 15;
388 fft = 0;
389 }
390 }
391
392 // moo
393 if ( ( restrict_ & 1 ) && sigdata->n_samples == 15 )
394 {
395 free(sigdata);
396 return NULL;
397 }
398
399 sigdata->n_pchannels = n_channels ? n_channels : 8; /* special case for 0, see above */
400
401 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
402 if (!sigdata->sample) {
403 free(sigdata);
404 return NULL;
405 }
406
407 sigdata->song_message = NULL;
408 sigdata->order = NULL;
409 sigdata->instrument = NULL;
410 sigdata->pattern = NULL;
411 sigdata->midi = NULL;
412 sigdata->checkpoint = NULL;
413
414 sigdata->n_instruments = 0;
415
416 for (i = 0; i < sigdata->n_samples; i++)
417 sigdata->sample[i].data = NULL;
418
419 for (i = 0; i < sigdata->n_samples; i++) {
420 if (it_mod_read_sample_header(&sigdata->sample[i], f, fft, sigdata->n_samples == 15)) {
421 _dumb_it_unload_sigdata(sigdata);
422 return NULL;
423 }
424 }
425
426 sigdata->n_orders = dumbfile_getc(f);
427 sigdata->restart_position = dumbfile_getc(f);
428 // what if this is >= 127? what about with Fast Tracker II?
429
430/* if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right?
431 _dumb_it_unload_sigdata(sigdata);
432 return NULL;
433 }*/
434
435 //if (sigdata->restart_position >= sigdata->n_orders)
436 //sigdata->restart_position = 0;
437
438 sigdata->order = malloc(128); /* We may need to scan the extra ones! */
439 if (!sigdata->order) {
440 _dumb_it_unload_sigdata(sigdata);
441 return NULL;
442 }
443 if (dumbfile_getnc((char *)sigdata->order, 128, f) < 128) {
444 _dumb_it_unload_sigdata(sigdata);
445 return NULL;
446 }
447
448 if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right?
449 sigdata->n_orders = 128;
450 //while (sigdata->n_orders > 1 && !sigdata->order[sigdata->n_orders - 1]) sigdata->n_orders--;
451 }
452
453 if ( ! n_channels )
454 for (i = 0; i < 128; i++)
455 sigdata->order[i] >>= 1;
456
457 /* "The old NST format contains only 15 samples (instead of 31). Further
458 * it doesn't contain a file format tag (id). So Pattern data offset is
459 * at 20+15*30+1+1+128."
460 * - Then I shall assume the File Format Tag never exists if there are
461 * only 15 samples. I hope this isn't a faulty assumption...
462 */
463 if (sigdata->n_samples == 31)
464 dumbfile_skip(f, 4);
465
466 sigdata->n_patterns = -1;
467
468 if ( ( restrict_ & 2 ) )
469 {
470 unsigned char buffer[5];
471 long sample_number;
472 long total_sample_size;
473 long offset = dumbfile_pos(f);
474 long remain = dumbfile_get_size(f) - offset;
475 if ( dumbfile_error( f ) ||
476 dumbfile_seek( f, 0, SEEK_END ) ) {
477 _dumb_it_unload_sigdata(sigdata);
478 return NULL;
479 }
480 sample_number = sigdata->n_samples - 1;
481 total_sample_size = 0;
482 while (dumbfile_pos(f) > offset && sample_number >= 0) {
483 if (sigdata->sample[sample_number].flags & IT_SAMPLE_EXISTS) {
484 if ( dumbfile_seek(f, -((sigdata->sample[sample_number].length + 1) / 2 + 5 + 16), DFS_SEEK_CUR) ||
485 dumbfile_getnc((char *)buffer, 5, f) < 5 ) {
486 _dumb_it_unload_sigdata(sigdata);
487 return NULL;
488 }
489 if ( !memcmp( buffer, "ADPCM", 5 ) ) { /* BAH */
490 total_sample_size += (sigdata->sample[sample_number].length + 1) / 2 + 5 + 16;
491 if ( dumbfile_seek(f, -5, DFS_SEEK_CUR) ) {
492 _dumb_it_unload_sigdata(sigdata);
493 return NULL;
494 }
495 } else {
496 total_sample_size += sigdata->sample[sample_number].length;
497 if ( dumbfile_seek(f, -(sigdata->sample[sample_number].length - ((sigdata->sample[sample_number].length + 1) / 2 + 5 + 16) + 5), DFS_SEEK_CUR) ) {
498 _dumb_it_unload_sigdata(sigdata);
499 return NULL;
500 }
501 }
502 }
503 --sample_number;
504 }
505
506 if (remain > total_sample_size) {
507 sigdata->n_patterns = ( remain - total_sample_size + 4 ) / ( 256 * sigdata->n_pchannels );
508 if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) {
509 remain -= sigdata->n_patterns * 256 * sigdata->n_pchannels;
510 if (dumbfile_skip(f, remain - total_sample_size)) {
511 _dumb_it_unload_sigdata(sigdata);
512 return NULL;
513 }
514 }
515 }
516 }
517 else
518 {
519 for (i = 0; i < 128; i++)
520 {
521 if (sigdata->order[i] > sigdata->n_patterns)
522 sigdata->n_patterns = sigdata->order[i];
523 }
524 sigdata->n_patterns++;
525 }
526
527 if ( sigdata->n_patterns <= 0 ) {
528 _dumb_it_unload_sigdata(sigdata);
529 return NULL;
530 }
531
532 /* May as well try to save a tiny bit of memory. */
533 if (sigdata->n_orders < 128) {
534 unsigned char *order = realloc(sigdata->order, sigdata->n_orders);
535 if (order) sigdata->order = order;
536 }
537
538 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
539 if (!sigdata->pattern) {
540 _dumb_it_unload_sigdata(sigdata);
541 return NULL;
542 }
543 for (i = 0; i < sigdata->n_patterns; i++)
544 sigdata->pattern[i].entry = NULL;
545
546 /* Read in the patterns */
547 {
548 unsigned char *buffer = malloc(256 * sigdata->n_pchannels); /* 64 rows * 4 bytes */
549 if (!buffer) {
550 _dumb_it_unload_sigdata(sigdata);
551 return NULL;
552 }
553 for (i = 0; i < sigdata->n_patterns; i++) {
554 if (it_mod_read_pattern(&sigdata->pattern[i], f, n_channels, buffer) != 0) {
555 free(buffer);
556 _dumb_it_unload_sigdata(sigdata);
557 return NULL;
558 }
559 }
560 free(buffer);
561 }
562
563 /* And finally, the sample data */
564 for (i = 0; i < sigdata->n_samples; i++) {
565 if (it_mod_read_sample_data(&sigdata->sample[i], f, fft)) {
566 _dumb_it_unload_sigdata(sigdata);
567 return NULL;
568 }
569 }
570
571 /* w00t! */
572 /*if ( n_channels == 4 &&
573 ( sigdata->n_samples == 15 ||
574 ( ( fft & 240 ) != DUMB_ID( 0, 0, 'C', 0 ) &&
575 ( fft & 240 ) != DUMB_ID( 0, 0, 'H', 0 ) &&
576 ( fft & 240 ) != 0 ) ) ) {
577 for ( i = 0; i < sigdata->n_samples; ++i ) {
578 IT_SAMPLE * sample = &sigdata->sample [i];
579 if ( sample && ( sample->flags & IT_SAMPLE_EXISTS ) ) {
580 int n, o;
581 o = sample->length;
582 if ( o > 4 ) o = 4;
583 for ( n = 0; n < o; ++n )
584 ( ( char * ) sample->data ) [n] = 0;
585 }
586 }
587 }*/
588
589 /* Now let's initialise the remaining variables, and we're done! */
590 sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
591
592 sigdata->global_volume = 128;
593 sigdata->mixing_volume = 48;
594 /* We want 50 ticks per second; 50/6 row advances per second;
595 * 50*10=500 row advances per minute; 500/4=125 beats per minute.
596 */
597 sigdata->speed = 6;
598 sigdata->tempo = 125;
599 sigdata->pan_separation = 128;
600
601 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
602
603 for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) {
604 int sep = 32 * dumb_it_default_panning_separation / 100;
605 sigdata->channel_pan[i+0] = 32 - sep;
606 sigdata->channel_pan[i+1] = 32 + sep;
607 sigdata->channel_pan[i+2] = 32 + sep;
608 sigdata->channel_pan[i+3] = 32 - sep;
609 }
610
611 _dumb_it_fix_invalid_orders(sigdata);
612
613 return sigdata;
614}
615
616
617
618DUH *dumb_read_mod_quick(DUMBFILE *f, int restrict_)
619{
620 sigdata_t *sigdata;
621
622 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
623
624 sigdata = it_mod_load_sigdata(f, restrict_);
625
626 if (!sigdata)
627 return NULL;
628
629 {
630 const char *tag[2][2];
631 tag[0][0] = "TITLE";
632 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
633 tag[1][0] = "FORMAT";
634 tag[1][1] = "MOD";
635 return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
636 }
637}
dumb/src/it/readmtm.c+0−413
@@ -1,413 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readmtm.c - Code to read a MultiTracker Module / / \ \
12 * from an open file. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27size_t strlen_max(const char * ptr, size_t max)
28{
29 const char * end, * start;
30 if (ptr==0) return 0;
31 start = ptr;
32 end = ptr + max;
33 while(*ptr && ptr < end) ptr++;
34 return ptr - start;
35}
36
37static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * track, const unsigned short * sequence, int n_rows)
38{
39 int n, o, note, sample;
40 const unsigned char * t;
41 IT_ENTRY * entry;
42
43 pattern->n_rows = n_rows;
44 pattern->n_entries = n_rows;
45
46 for (n = 0; n < 32; n++) {
47 if (sequence[n]) {
48 t = &track[192 * (sequence[n] - 1)];
49 for (o = 0; o < n_rows; o++) {
50 if (t[0] || t[1] || t[2]) pattern->n_entries++;
51 t += 3;
52 }
53 }
54 }
55
56 entry = malloc(pattern->n_entries * sizeof(*entry));
57 if (!entry) return -1;
58 pattern->entry = entry;
59
60 for (n = 0; n < n_rows; n++) {
61 for (o = 0; o < 32; o++) {
62 if (sequence[o]) {
63 t = &track[192 * (sequence[o] - 1) + (n * 3)];
64 if (t[0] || t[1] || t[2]) {
65 entry->channel = o;
66 entry->mask = 0;
67 note = t[0] >> 2;
68 sample = ((t[0] << 4) | (t[1] >> 4)) & 0x3F;
69
70 if (note) {
71 entry->mask |= IT_ENTRY_NOTE;
72 entry->note = note + 24;
73 }
74
75 if (sample) {
76 entry->mask |= IT_ENTRY_INSTRUMENT;
77 entry->instrument = sample;
78 }
79
80 _dumb_it_xm_convert_effect(t[1] & 0xF, t[2], entry, 1);
81
82 if (entry->mask) entry++;
83 }
84 }
85 }
86 IT_SET_END_ROW(entry);
87 entry++;
88 }
89
90 pattern->n_entries = entry - pattern->entry;
91
92 return 0;
93}
94
95static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
96{
97 int finetune, flags;
98
99 dumbfile_getnc((char *)sample->name, 22, f);
100 sample->name[22] = 0;
101
102 sample->filename[0] = 0;
103
104 sample->length = dumbfile_igetl(f);
105 sample->loop_start = dumbfile_igetl(f);
106 sample->loop_end = dumbfile_igetl(f);
107 finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
108 sample->global_volume = 64;
109 sample->default_volume = dumbfile_getc(f);
110
111 flags = dumbfile_getc(f);
112
113 if (sample->length <= 0) {
114 sample->flags = 0;
115 return 0;
116 }
117
118 sample->flags = IT_SAMPLE_EXISTS;
119
120 if (flags & 1) {
121 sample->flags |= IT_SAMPLE_16BIT;
122 sample->length >>= 1;
123 sample->loop_start >>= 1;
124 sample->loop_end >>= 1;
125 }
126
127 sample->default_pan = 0;
128 sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 );//(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
129 sample->finetune = finetune * 32;
130 // the above line might be wrong
131
132 if (sample->loop_end > sample->length)
133 sample->loop_end = sample->length;
134
135 if (sample->loop_end - sample->loop_start > 2)
136 sample->flags |= IT_SAMPLE_LOOP;
137
138 sample->vibrato_speed = 0;
139 sample->vibrato_depth = 0;
140 sample->vibrato_rate = 0;
141 sample->vibrato_waveform = 0; // do we have to set _all_ these?
142 sample->max_resampling_quality = -1;
143
144 return dumbfile_error(f);
145}
146
147static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
148{
149 long i;
150 long truncated_size;
151
152 /* let's get rid of the sample data coming after the end of the loop */
153 if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
154 truncated_size = sample->length - sample->loop_end;
155 sample->length = sample->loop_end;
156 } else {
157 truncated_size = 0;
158 }
159
160 sample->data = malloc(sample->length);
161
162 if (!sample->data)
163 return -1;
164
165 dumbfile_getnc((char *)sample->data, sample->length, f);
166 dumbfile_skip(f, truncated_size);
167
168 if (dumbfile_error(f))
169 return -1;
170
171 for (i = 0; i < sample->length; i++)
172 ((signed char *)sample->data)[i] ^= 0x80;
173
174 return 0;
175}
176
177static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
178{
179 DUMB_IT_SIGDATA *sigdata;
180
181 int n, o, n_tracks, l_comment, n_rows, n_channels;
182
183 unsigned char * track;
184
185 unsigned short * sequence;
186
187 char * comment;
188
189 if (dumbfile_getc(f) != 'M' ||
190 dumbfile_getc(f) != 'T' ||
191 dumbfile_getc(f) != 'M') goto error;
192
193 *version = dumbfile_getc(f);
194
195 sigdata = malloc(sizeof(*sigdata));
196 if (!sigdata) goto error;
197
198 dumbfile_getnc((char *)sigdata->name, 20, f);
199 sigdata->name[20] = 0;
200
201 n_tracks = dumbfile_igetw(f);
202 sigdata->n_patterns = dumbfile_getc(f) + 1;
203 sigdata->n_orders = dumbfile_getc(f) + 1;
204 l_comment = dumbfile_igetw(f);
205 sigdata->n_samples = dumbfile_getc(f);
206 //if (dumbfile_getc(f)) goto error_sd;
207 dumbfile_getc(f);
208 n_rows = dumbfile_getc(f);
209 n_channels = dumbfile_getc(f);
210
211 if (dumbfile_error(f) ||
212 (n_tracks <= 0) ||
213 (sigdata->n_samples <= 0) ||
214 (n_rows <= 0 || n_rows > 64) ||
215 (n_channels <= 0 || n_channels > 32)) goto error_sd;
216
217 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
218
219 if (dumbfile_getnc((char *)sigdata->channel_pan, 32, f) < 32) goto error_sd;
220
221 for (n = 0; n < 32; n++) {
222 if (sigdata->channel_pan[n] <= 15) {
223 sigdata->channel_pan[n] -= (sigdata->channel_pan[n] & 8) >> 3;
224 sigdata->channel_pan[n] = (sigdata->channel_pan[n] * 32) / 7;
225 } else {
226 sigdata->channel_volume[n] = 0;
227 sigdata->channel_pan[n] = 7;
228 }
229 }
230
231 for (n = 32; n < DUMB_IT_N_CHANNELS; n += 4) {
232 int sep = 32 * dumb_it_default_panning_separation / 100;
233 sigdata->channel_pan[n ] = 32 - sep;
234 sigdata->channel_pan[n+1] = 32 + sep;
235 sigdata->channel_pan[n+2] = 32 + sep;
236 sigdata->channel_pan[n+3] = 32 - sep;
237 }
238
239 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
240 if (!sigdata->sample) goto error_sd;
241
242 sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
243
244 sigdata->global_volume = 128;
245 sigdata->mixing_volume = 48;
246 sigdata->speed = 6;
247 sigdata->tempo = 125;
248 sigdata->pan_separation = 128;
249
250 sigdata->song_message = NULL;
251 sigdata->order = NULL;
252 sigdata->instrument = NULL;
253 sigdata->pattern = NULL;
254 sigdata->midi = NULL;
255 sigdata->checkpoint = NULL;
256
257 sigdata->n_instruments = 0;
258
259 sigdata->restart_position = 0;
260 sigdata->n_pchannels = n_channels;
261
262 for (n = 0; n < sigdata->n_samples; n++)
263 sigdata->sample[n].data = NULL;
264
265 for (n = 0; n < sigdata->n_samples; n++) {
266 if (it_mtm_read_sample_header(&sigdata->sample[n], f)) goto error_usd;
267 }
268
269 sigdata->order = malloc(sigdata->n_orders);
270 if (!sigdata->order) goto error_usd;
271
272 if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_usd;
273 if (sigdata->n_orders < 128)
274 if (dumbfile_skip(f, 128 - sigdata->n_orders)) goto error_usd;
275
276 track = malloc(192 * n_tracks);
277 if (!track) goto error_usd;
278
279 if (dumbfile_getnc((char *)track, 192 * n_tracks, f) < 192 * n_tracks) goto error_ft;
280
281 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
282 if (!sigdata->pattern) goto error_ft;
283 for (n = 0; n < sigdata->n_patterns; n++)
284 sigdata->pattern[n].entry = NULL;
285
286 sequence = malloc(sigdata->n_patterns * 32 * sizeof(*sequence));
287 if (!sequence) goto error_ft;
288
289 for (n = 0; n < sigdata->n_patterns; n++) {
290 for (o = 0; o < 32; o++) {
291 sequence[(n * 32) + o] = dumbfile_igetw(f);
292 if (sequence[(n * 32) + o] > n_tracks)
293 {
294 //goto error_fs;
295 // illegal track number, silence instead of rejecting the file
296 sequence[(n * 32) + o] = 0;
297 }
298 }
299 }
300
301 for (n = 0; n < sigdata->n_patterns; n++) {
302 if (it_mtm_assemble_pattern(&sigdata->pattern[n], track, &sequence[n * 32], n_rows)) goto error_fs;
303 }
304
305 if (l_comment) {
306 comment = malloc(l_comment);
307 if (!comment) goto error_fs;
308 if (dumbfile_getnc(comment, l_comment, f) < l_comment) goto error_fc;
309
310 /* Time for annoying "logic", yes. We want each line which has text,
311 * and each blank line in between all the valid lines.
312 */
313
314 /* Find last actual line. */
315 for (o = -1, n = 0; n < l_comment; n += 40) {
316 if (comment[n]) o = n;
317 }
318
319 if (o >= 0) {
320
321 int l, m;
322
323 for (l = 0, n = 0; n <= o; n += 40) {
324 l += strlen_max(&comment[n], 40) + 2;
325 }
326
327 l -= 1;
328
329 sigdata->song_message = malloc(l);
330 if (!sigdata->song_message) goto error_fc;
331
332 for (m = 0, n = 0; n <= o; n += 40) {
333 int p = strlen_max(&comment[n], 40);
334 if (p) {
335 memcpy(sigdata->song_message + m, &comment[n], p);
336 m += p;
337 }
338 if (l - m > 1) {
339 sigdata->song_message[m++] = 13;
340 sigdata->song_message[m++] = 10;
341 }
342 }
343
344 sigdata->song_message[m] = 0;
345 }
346
347 free(comment);
348 }
349
350 for (n = 0; n < sigdata->n_samples; n++) {
351 if (it_mtm_read_sample_data(&sigdata->sample[n], f)) goto error_fs;
352 }
353
354 _dumb_it_fix_invalid_orders(sigdata);
355
356 free(sequence);
357 free(track);
358
359 return sigdata;
360
361error_fc:
362 free(comment);
363error_fs:
364 free(sequence);
365error_ft:
366 free(track);
367error_usd:
368 _dumb_it_unload_sigdata(sigdata);
369 return NULL;
370
371error_sd:
372 free(sigdata);
373error:
374 return NULL;
375}
376
377static char hexdigit(int in)
378{
379 if (in < 10) return in + '0';
380 else return in + 'A' - 10;
381}
382
383DUH *dumb_read_mtm_quick(DUMBFILE *f)
384{
385 sigdata_t *sigdata;
386 int ver;
387
388 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
389
390 sigdata = it_mtm_load_sigdata(f, &ver);
391
392 if (!sigdata)
393 return NULL;
394
395 {
396 char version[16];
397 const char *tag[2][2];
398 tag[0][0] = "TITLE";
399 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
400 tag[1][0] = "FORMAT";
401 version[0] = 'M';
402 version[1] = 'T';
403 version[2] = 'M';
404 version[3] = ' ';
405 version[4] = 'v';
406 version[5] = hexdigit(ver >> 4);
407 version[6] = '.';
408 version[7] = hexdigit(ver & 15);
409 version[8] = 0;
410 tag[1][1] = (const char *) &version;
411 return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
412 }
413}
dumb/src/it/readokt.c+0−558
@@ -1,558 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readokt.c - Code to read an Oktalyzer module / / \ \
12 * from an open file. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data, int length, int n_channels)
30{
31 int pos;
32 int channel;
33 int row;
34 int n_rows;
35 IT_ENTRY *entry;
36
37 if (length < 2) return -1;
38
39 n_rows = (data[0] << 8) | data[1];
40 if (!n_rows) n_rows = 64;
41
42 if (length < 2 + (n_rows * n_channels * 4)) return -1;
43
44 pattern->n_rows = n_rows;
45
46 /* compute number of entries */
47 pattern->n_entries = n_rows; /* Account for the row end markers */
48 pos = 2;
49 for (row = 0; row < pattern->n_rows; row++) {
50 for (channel = 0; channel < n_channels; channel++) {
51 if (data[pos+0] | data[pos+2])
52 pattern->n_entries++;
53 pos += 4;
54 }
55 }
56
57 pattern->entry = (IT_ENTRY *) malloc(pattern->n_entries * sizeof(*pattern->entry));
58 if (!pattern->entry)
59 return -1;
60
61 entry = pattern->entry;
62 pos = 2;
63 for (row = 0; row < n_rows; row++) {
64 for (channel = 0; channel < n_channels; channel++) {
65 if (data[pos+0] | data[pos+2]) {
66 entry->channel = channel;
67 entry->mask = 0;
68
69 if (data[pos+0] > 0 && data[pos+0] <= 36) {
70 entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT;
71
72 entry->note = data[pos+0] + 35;
73 entry->instrument = data[pos+1] + 1;
74 }
75
76 entry->effect = 0;
77 entry->effectvalue = data[pos+3];
78
79 switch (data[pos+2]) {
80 case 2: if (data[pos+3]) entry->effect = IT_PORTAMENTO_DOWN; break; // XXX code calls this rs_portu, but it's adding to the period, which decreases the pitch
81 case 13: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN; break;
82 case 21: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN_ROW; break;
83
84 case 1: if (data[pos+3]) entry->effect = IT_PORTAMENTO_UP; break; // XXX same deal here, increasing the pitch
85 case 17: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP; break;
86 case 30: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP_ROW; break;
87
88 case 10: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_3; break;
89 case 11: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_4; break;
90 case 12: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_5; break;
91
92 case 15: entry->effect = IT_S; entry->effectvalue = EFFECT_VALUE(IT_S_SET_FILTER, data[pos+3] & 0x0F); break;
93
94 case 25: entry->effect = IT_JUMP_TO_ORDER; break;
95
96 case 27: entry->note = IT_NOTE_OFF; entry->mask |= IT_ENTRY_NOTE; break;
97
98 case 28: entry->effect = IT_SET_SPEED; break;
99
100 case 31:
101 if ( data[pos+3] <= 0x40 ) entry->effect = IT_SET_CHANNEL_VOLUME;
102 else if ( data[pos+3] <= 0x50 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x40; }
103 else if ( data[pos+3] <= 0x60 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP; entry->effectvalue = data[pos+3] - 0x50; }
104 else if ( data[pos+3] <= 0x70 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x50; }
105 else if ( data[pos+3] <= 0x80 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP; entry->effectvalue = data[pos+3] - 0x60; }
106 break;
107 }
108
109 if ( entry->effect ) entry->mask |= IT_ENTRY_EFFECT;
110
111 entry++;
112 }
113 pos += 4;
114 }
115 IT_SET_END_ROW(entry);
116 entry++;
117 }
118
119 return 0;
120}
121
122
123
124static void it_okt_read_sample_header(IT_SAMPLE *sample, const unsigned char * data)
125{
126 int loop_start, loop_length;
127
128 memcpy(sample->name, data, 20);
129 sample->name[20] = 0;
130
131 sample->filename[0] = 0;
132
133 sample->length = (data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23];
134 sample->global_volume = 64;
135 sample->default_volume = data[29];
136 loop_start = ((data[24] << 8) | data[25]) << 1;
137 loop_length = ((data[26] << 8) | data[27]) << 1;
138 sample->sus_loop_start = loop_start;
139 sample->sus_loop_end = loop_start + loop_length;
140
141 if (sample->length <= 0) {
142 sample->flags = 0;
143 return;
144 }
145
146 sample->flags = IT_SAMPLE_EXISTS;
147
148 sample->default_pan = 0;
149 sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
150 sample->finetune = 0;
151
152 if (sample->sus_loop_end > sample->length)
153 sample->sus_loop_end = sample->length;
154
155 if (loop_length > 2)
156 sample->flags |= IT_SAMPLE_SUS_LOOP;
157
158 sample->vibrato_speed = 0;
159 sample->vibrato_depth = 0;
160 sample->vibrato_rate = 0;
161 sample->vibrato_waveform = 0; // do we have to set _all_ these?
162 sample->max_resampling_quality = -1;
163}
164
165
166
167static int it_okt_read_sample_data(IT_SAMPLE *sample, const char * data, int length)
168{
169 if (length && sample->length) {
170 if (length < sample->length) {
171 sample->length = length;
172 if (length < sample->sus_loop_end) sample->sus_loop_end = length;
173 }
174
175 sample->data = malloc(length);
176
177 if (!sample->data)
178 return -1;
179
180 memcpy(sample->data, data, length);
181 }
182
183 return 0;
184}
185
186
187
188typedef struct IFF_CHUNK IFF_CHUNK;
189typedef struct IFF_CHUNKED IFF_CHUNKED;
190
191struct IFF_CHUNK
192{
193 unsigned type;
194 unsigned char * data;
195 unsigned size;
196};
197
198struct IFF_CHUNKED
199{
200 unsigned chunk_count;
201 IFF_CHUNK * chunks;
202};
203
204
205
206static IFF_CHUNKED *dumbfile_read_okt(DUMBFILE *f)
207{
208 IFF_CHUNKED *mod = (IFF_CHUNKED *) malloc(sizeof(*mod));
209 if (!mod) return NULL;
210
211 mod->chunk_count = 0;
212 mod->chunks = 0;
213
214 for (;;)
215 {
216 long bytes_read;
217 IFF_CHUNK * chunk = ( IFF_CHUNK * ) realloc( mod->chunks, ( mod->chunk_count + 1 ) * sizeof( IFF_CHUNK ) );
218 if ( !chunk )
219 {
220 if ( mod->chunks ) free( mod->chunks );
221 free( mod );
222 return NULL;
223 }
224 mod->chunks = chunk;
225 chunk += mod->chunk_count;
226
227 bytes_read = dumbfile_mgetl( f );
228 if ( bytes_read < 0 ) break;
229
230 chunk->type = bytes_read;
231 chunk->size = dumbfile_mgetl( f );
232
233 if ( dumbfile_error( f ) ) break;
234
235 chunk->data = (unsigned char *) malloc( chunk->size );
236 if ( !chunk->data )
237 {
238 free( mod->chunks );
239 free( mod );
240 return NULL;
241 }
242
243 bytes_read = dumbfile_getnc( ( char * ) chunk->data, chunk->size, f );
244 if ( bytes_read < chunk->size )
245 {
246 if ( bytes_read <= 0 ) {
247 free( chunk->data );
248 break;
249 } else {
250 chunk->size = bytes_read;
251 mod->chunk_count++;
252 break;
253 }
254 }
255
256 mod->chunk_count++;
257 }
258
259 if ( !mod->chunk_count ) {
260 if ( mod->chunks ) free(mod->chunks);
261 free(mod);
262 mod = NULL;
263 }
264
265 return mod;
266}
267
268void free_okt(IFF_CHUNKED * mod)
269{
270 unsigned i;
271 if (mod)
272 {
273 if (mod->chunks)
274 {
275 for (i = 0; i < mod->chunk_count; i++)
276 {
277 if (mod->chunks[i].data) free(mod->chunks[i].data);
278 }
279 free(mod->chunks);
280 }
281 free(mod);
282 }
283}
284
285const IFF_CHUNK * get_chunk_by_type(IFF_CHUNKED * mod, unsigned type, unsigned offset)
286{
287 unsigned i;
288 if (mod)
289 {
290 if (mod->chunks)
291 {
292 for (i = 0; i < mod->chunk_count; i++)
293 {
294 if (mod->chunks[i].type == type)
295 {
296 if (!offset) return &mod->chunks[i];
297 else offset--;
298 }
299 }
300 }
301 }
302 return NULL;
303}
304
305unsigned get_chunk_count(IFF_CHUNKED *mod, unsigned type)
306{
307 unsigned i, count = 0;
308 if (mod)
309 {
310 if (mod->chunks)
311 {
312 for (i = 0; i < mod->chunk_count; i++)
313 {
314 if (mod->chunks[i].type == type) count++;
315 }
316 }
317 }
318 return count;
319}
320
321
322static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
323{
324 DUMB_IT_SIGDATA *sigdata;
325 int n_channels;
326 int i, j, k, l;
327 IFF_CHUNKED *mod;
328 const IFF_CHUNK *chunk;
329
330 char signature[8];
331
332 if (dumbfile_getnc(signature, 8, f) < 8 ||
333 memcmp(signature, "OKTASONG", 8)) {
334 return NULL;
335 }
336
337 mod = dumbfile_read_okt(f);
338 if (!mod)
339 return NULL;
340
341 sigdata = (DUMB_IT_SIGDATA *) malloc(sizeof(*sigdata));
342 if (!sigdata) {
343 free_okt(mod);
344 return NULL;
345 }
346
347 sigdata->name[0] = 0;
348
349 chunk = get_chunk_by_type(mod, DUMB_ID('S','P','E','E'), 0);
350 if (!chunk || chunk->size < 2) {
351 free(sigdata);
352 free_okt(mod);
353 return NULL;
354 }
355
356 sigdata->speed = (chunk->data[0] << 8) | chunk->data[1];
357
358 chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0);
359 if (!chunk || chunk->size < 32) {
360 free(sigdata);
361 free_okt(mod);
362 return NULL;
363 }
364
365 sigdata->n_samples = chunk->size / 32;
366
367 chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0);
368 if (!chunk || chunk->size < 8) {
369 free(sigdata);
370 free_okt(mod);
371 return NULL;
372 }
373
374 n_channels = 0;
375
376 for (i = 0; i < 4; i++) {
377 j = (chunk->data[i * 2] << 8) | chunk->data[i * 2 + 1];
378 if (!j) n_channels++;
379 else if (j == 1) n_channels += 2;
380 }
381
382 if (!n_channels) {
383 free(sigdata);
384 free_okt(mod);
385 return NULL;
386 }
387
388 sigdata->n_pchannels = n_channels;
389
390 sigdata->sample = (IT_SAMPLE *) malloc(sigdata->n_samples * sizeof(*sigdata->sample));
391 if (!sigdata->sample) {
392 free(sigdata);
393 free_okt(mod);
394 return NULL;
395 }
396
397 sigdata->song_message = NULL;
398 sigdata->order = NULL;
399 sigdata->instrument = NULL;
400 sigdata->pattern = NULL;
401 sigdata->midi = NULL;
402 sigdata->checkpoint = NULL;
403
404 sigdata->n_instruments = 0;
405
406 for (i = 0; i < sigdata->n_samples; i++)
407 sigdata->sample[i].data = NULL;
408
409 chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0);
410
411 for (i = 0; i < sigdata->n_samples; i++) {
412 it_okt_read_sample_header(&sigdata->sample[i], chunk->data + 32 * i);
413 }
414
415 sigdata->restart_position = 0;
416
417 chunk = get_chunk_by_type(mod, DUMB_ID('P','L','E','N'), 0);
418 if (!chunk || chunk->size < 2) {
419 _dumb_it_unload_sigdata(sigdata);
420 free_okt(mod);
421 return NULL;
422 }
423
424 sigdata->n_orders = (chunk->data[0] << 8) | chunk->data[1];
425 // what if this is > 128?
426
427 if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) {
428 _dumb_it_unload_sigdata(sigdata);
429 free_okt(mod);
430 return NULL;
431 }
432
433 chunk = get_chunk_by_type(mod, DUMB_ID('P','A','T','T'), 0);
434 if (!chunk || chunk->size < (unsigned)sigdata->n_orders) {
435 _dumb_it_unload_sigdata(sigdata);
436 free_okt(mod);
437 return NULL;
438 }
439
440 sigdata->order = (unsigned char *) malloc(sigdata->n_orders);
441 if (!sigdata->order) {
442 _dumb_it_unload_sigdata(sigdata);
443 free_okt(mod);
444 return NULL;
445 }
446
447 memcpy(sigdata->order, chunk->data, sigdata->n_orders);
448
449 /* Work out how many patterns there are. */
450 chunk = get_chunk_by_type(mod, DUMB_ID('S','L','E','N'), 0);
451 if (!chunk || chunk->size < 2) {
452 _dumb_it_unload_sigdata(sigdata);
453 free_okt(mod);
454 return NULL;
455 }
456
457 sigdata->n_patterns = (chunk->data[0] << 8) | chunk->data[1];
458
459 j = get_chunk_count(mod, DUMB_ID('P','B','O','D'));
460 if (sigdata->n_patterns > j) sigdata->n_patterns = j;
461
462 if (!sigdata->n_patterns) {
463 _dumb_it_unload_sigdata(sigdata);
464 free_okt(mod);
465 return NULL;
466 }
467
468 sigdata->pattern = (IT_PATTERN *) malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
469 if (!sigdata->pattern) {
470 _dumb_it_unload_sigdata(sigdata);
471 free_okt(mod);
472 return NULL;
473 }
474 for (i = 0; i < sigdata->n_patterns; i++)
475 sigdata->pattern[i].entry = NULL;
476
477 /* Read in the patterns */
478 for (i = 0; i < sigdata->n_patterns; i++) {
479 chunk = get_chunk_by_type(mod, DUMB_ID('P','B','O','D'), i);
480 if (it_okt_read_pattern(&sigdata->pattern[i], chunk->data, chunk->size, n_channels) != 0) {
481 _dumb_it_unload_sigdata(sigdata);
482 free_okt(mod);
483 return NULL;
484 }
485 }
486
487 /* And finally, the sample data */
488 k = get_chunk_count(mod, DUMB_ID('S','B','O','D'));
489 for (i = 0, j = 0; i < sigdata->n_samples && j < k; i++) {
490 if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) {
491 chunk = get_chunk_by_type(mod, DUMB_ID('S','B','O','D'), j);
492 if (it_okt_read_sample_data(&sigdata->sample[i], (const char *)chunk->data, chunk->size)) {
493 _dumb_it_unload_sigdata(sigdata);
494 free_okt(mod);
495 return NULL;
496 }
497 j++;
498 }
499 }
500 for (; i < sigdata->n_samples; i++) {
501 sigdata->sample[i].flags = 0;
502 }
503
504 chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0);
505
506 for (i = 0, j = 0; i < n_channels && j < 4; j++) {
507 k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1];
508 l = (j == 1 || j == 2) ? 48 : 16;
509 if (k == 0) {
510 sigdata->channel_pan[i++] = l;
511 }
512 else if (k == 1) {
513 sigdata->channel_pan[i++] = l;
514 sigdata->channel_pan[i++] = l;
515 }
516 }
517
518 free_okt(mod);
519
520 /* Now let's initialise the remaining variables, and we're done! */
521 sigdata->flags = IT_WAS_AN_OKT | IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
522
523 sigdata->global_volume = 128;
524 sigdata->mixing_volume = 48;
525 /* We want 50 ticks per second; 50/6 row advances per second;
526 * 50*10=500 row advances per minute; 500/4=125 beats per minute.
527 */
528 sigdata->tempo = 125;
529 sigdata->pan_separation = 128;
530
531 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
532 memset(sigdata->channel_pan + n_channels, 32, DUMB_IT_N_CHANNELS - n_channels);
533
534 _dumb_it_fix_invalid_orders(sigdata);
535
536 return sigdata;
537}
538
539
540
541DUH *dumb_read_okt_quick(DUMBFILE *f)
542{
543 sigdata_t *sigdata;
544
545 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
546
547 sigdata = it_okt_load_sigdata(f);
548
549 if (!sigdata)
550 return NULL;
551
552 {
553 const char *tag[1][2];
554 tag[0][0] = "FORMAT";
555 tag[0][1] = "Oktalyzer";
556 return make_duh(-1, 1, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
557 }
558}
dumb/src/it/readoldpsm.c+0−689
@@ -1,689 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readpsm.c - Code to read an old Protracker / / \ \
12 * Studio module from an open file. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27static int psm_sample_compare(const void *e1, const void *e2)
28{
29 const unsigned char * pa = e1;
30 const unsigned char * pb = e2;
31 int a = pa[37] | (pa[38] << 8) | (pa[39] << 16) | (pa[40] << 24);
32 int b = pb[37] | (pb[38] << 8) | (pb[39] << 16) | (pb[40] << 24);
33 return a - b;
34}
35
36static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
37{
38 int n, o, count = *num, true_num, snum, offset, flags, finetune, delta;
39
40 unsigned char * buffer;
41 const unsigned char * sdata;
42 long sample_bytes;
43
44 buffer = malloc(count * 64);
45 if (!buffer) goto error;
46
47 if (dumbfile_getnc((char *)buffer, count * 64, f) < count * 64) goto error_fb;
48
49 true_num = 0;
50
51 for (n = 0; n < count; n++) {
52 snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
53 if ((snum < 1) || (snum > 255)) goto error_fb;
54 if (true_num < snum) true_num = snum;
55 }
56
57 if (true_num > count) {
58 IT_SAMPLE * meh = realloc(*sample, true_num * sizeof(*meh));
59 if (!meh) goto error_fb;
60 for (n = count; n < true_num; n++) {
61 meh[n].data = NULL;
62 }
63 *sample = meh;
64 *num = true_num;
65 }
66
67 qsort(buffer, count, 64, &psm_sample_compare);
68
69 for (n = 0; n < true_num; n++) {
70 (*sample)[n].flags = 0;
71 }
72
73 for (n = 0; n < count; n++) {
74 IT_SAMPLE * s;
75 snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
76 s = &((*sample)[snum - 1]);
77 memcpy(s->filename, buffer + (n * 64), 13);
78 s->filename[13] = 0;
79 memcpy(s->name, buffer + (n * 64) + 13, 24);
80 s->name[24] = 0;
81 offset = buffer[(n * 64) + 37] | (buffer[(n * 64) + 38] << 8) |
82 (buffer[(n * 64) + 39] << 16) | (buffer[(n * 64) + 40] << 24);
83 flags = buffer[(n * 64) + 47];
84 s->length = buffer[(n * 64) + 48] | (buffer[(n * 64) + 49] << 8) |
85 (buffer[(n * 64) + 50] << 16) | (buffer[(n * 64) + 51] << 24);
86 s->loop_start = buffer[(n * 64) + 52] | (buffer[(n * 64) + 53] << 8) |
87 (buffer[(n * 64) + 54] << 16) | (buffer[(n * 64) + 55] << 24);
88 s->loop_end = buffer[(n * 64) + 56] | (buffer[(n * 64) + 57] << 8) |
89 (buffer[(n * 64) + 58] << 16) | (buffer[(n * 64) + 59] << 24);
90
91 if (s->length <= 0) continue;
92
93 finetune = buffer[(n * 64) + 60];
94 s->default_volume = buffer[(n * 64) + 61];
95 s->C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8);
96 if (finetune & 15) {
97 finetune &= 15;
98 if (finetune >= 8) finetune -= 16;
99 //s->C5_speed = (long)((double)s->C5_speed * pow(DUMB_PITCH_BASE, finetune*32));
100 s->finetune = finetune * 32;
101 }
102 else s->finetune = 0;
103
104 s->flags |= IT_SAMPLE_EXISTS;
105 if (flags & 0x41) {
106 s->flags &= ~IT_SAMPLE_EXISTS;
107 continue;
108 }
109 if (flags & 0x20) s->flags |= IT_SAMPLE_PINGPONG_LOOP;
110 if (flags & 4) s->flags |= IT_SAMPLE_16BIT;
111
112 if (flags & 0x80) {
113 s->flags |= IT_SAMPLE_LOOP;
114 if ((unsigned int)s->loop_end > (unsigned int)s->length)
115 s->loop_end = s->length;
116 else if ((unsigned int)s->loop_start >= (unsigned int)s->loop_end)
117 s->flags &= ~IT_SAMPLE_LOOP;
118 else
119 s->length = s->loop_end;
120 }
121
122 s->global_volume = 64;
123
124 s->vibrato_speed = 0;
125 s->vibrato_depth = 0;
126 s->vibrato_rate = 0;
127 s->vibrato_waveform = IT_VIBRATO_SINE;
128 s->max_resampling_quality = -1;
129
130 sample_bytes = s->length * ((flags & 4) ? 2 : 1);
131 s->data = malloc(sample_bytes);
132 if (!s->data) goto error_fb;
133
134 if (dumbfile_seek(f, offset, DFS_SEEK_SET) || dumbfile_getnc(s->data, sample_bytes, f) < sample_bytes) goto error_fb;
135 sdata = ( const unsigned char * ) s->data;
136
137 if (flags & 0x10) {
138 if (flags & 8) {
139 if (flags & 4) {
140 for (o = 0; o < s->length; o++)
141 ((short *)s->data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000;
142 } else {
143 for (o = 0; o < s->length; o++)
144 ((signed char *)s->data)[o] = sdata[o] ^ 0x80;
145 }
146 } else {
147 if (flags & 4) {
148 for (o = 0; o < s->length; o++)
149 ((short *)s->data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8);
150 } else {
151 memcpy(s->data, sdata, s->length);
152 }
153 }
154 } else {
155 delta = 0;
156 if (flags & 8) {
157 /* unsigned delta? mehhh, does anything even use this? */
158 if (flags & 4) {
159 for (o = 0; o < s->length; o++) {
160 delta += (short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
161 ((short *)s->data)[o] = delta ^ 0x8000;
162 }
163 } else {
164 for (o = 0; o < s->length; o++) {
165 delta += (signed char)sdata[o];
166 ((signed char *)s->data)[o] = delta ^ 0x80;
167 }
168 }
169 } else {
170 if (flags & 4) {
171 for (o = 0; o < s->length; o++) {
172 delta += (signed short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
173 ((signed short *)s->data)[o] = delta;
174 }
175 } else {
176 for (o = 0; o < s->length; o++) {
177 delta += (signed char)sdata[o];
178 ((signed char *)s->data)[o] = delta;
179 }
180 }
181 }
182 }
183 }
184
185 free(buffer);
186
187 return 0;
188
189error_fb:
190 free(buffer);
191error:
192 return -1;
193}
194
195static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num, int size, int pchans)
196{
197 int n, offset, psize, rows, chans, row, flags, channel;
198
199 unsigned char * buffer, * ptr, * end;
200
201 IT_ENTRY * entry;
202
203 buffer = malloc(size);
204 if (!buffer) goto error;
205
206 if (dumbfile_getnc((char *)buffer, size, f) < size) goto error_fb;
207
208 offset = 0;
209
210 for (n = 0; n < num; n++) {
211 IT_PATTERN * p = &pattern[n];
212
213 if (offset >= size) goto error_fb;
214
215 ptr = buffer + offset;
216 psize = ptr[0] | (ptr[1] << 8);
217 rows = ptr[2];
218 chans = ptr[3];
219
220 if (!rows || !chans) {
221 p->n_rows = 1;
222 p->n_entries = 0;
223 continue;
224 }
225
226 psize = (psize + 15) & ~15;
227
228 end = ptr + psize;
229 ptr += 4;
230
231 p->n_rows = rows;
232 p->n_entries = rows;
233 row = 0;
234
235 while ((row < rows) && (ptr < end)) {
236 flags = *ptr++;
237 if (!flags) {
238 row++;
239 continue;
240 }
241 if (flags & 0xE0) {
242 p->n_entries++;
243 if (flags & 0x80) ptr += 2;
244 if (flags & 0x40) ptr++;
245 if (flags & 0x20) {
246 ptr++;
247 if (*ptr == 40) ptr += 3;
248 else ptr++;
249 }
250 }
251 }
252
253 entry = malloc(p->n_entries * sizeof(*p->entry));
254 if (!entry) goto error_fb;
255
256 p->entry = entry;
257
258 ptr = buffer + offset + 4;
259 row = 0;
260
261 while ((row < rows) && (ptr < end)) {
262 flags = *ptr++;
263 if (!flags) {
264 IT_SET_END_ROW(entry);
265 entry++;
266 row++;
267 continue;
268 }
269 if (flags & 0xE0) {
270 entry->mask = 0;
271 entry->channel = channel = flags & 0x1F;
272 if (channel >= chans)
273 {
274 //channel = 0;
275 //goto error_fb;
276 }
277 if (flags & 0x80) {
278 if ((*ptr < 60) && (channel < pchans)) {
279 entry->mask |= IT_ENTRY_NOTE;
280 entry->note = *ptr + 35;
281 }
282 ptr++;
283 if (*ptr) {
284 entry->mask |= IT_ENTRY_INSTRUMENT;
285 entry->instrument = *ptr;
286 }
287 ptr++;
288 }
289 if (flags & 0x40) {
290 if (*ptr <= 64) {
291 entry->mask |= IT_ENTRY_VOLPAN;
292 entry->volpan = *ptr;
293 }
294 ptr++;
295 }
296 if (flags & 0x20) {
297 entry->mask |= IT_ENTRY_EFFECT;
298
299 switch (*ptr) {
300 case 1:
301 entry->effect = IT_XM_FINE_VOLSLIDE_UP;
302 entry->effectvalue = ptr[1];
303 break;
304
305 case 2:
306 entry->effect = IT_VOLUME_SLIDE;
307 entry->effectvalue = (ptr[1] << 4) & 0xF0;
308 break;
309
310 case 3:
311 entry->effect = IT_XM_FINE_VOLSLIDE_DOWN;
312 entry->effectvalue = ptr[1];
313 break;
314
315 case 4:
316 entry->effect = IT_VOLUME_SLIDE;
317 entry->effectvalue = ptr[1] & 0xF;
318 break;
319
320 case 10:
321 entry->effect = IT_PORTAMENTO_UP;
322 entry->effectvalue = EFFECT_VALUE(0xF, ptr[1]);
323 break;
324
325 case 11:
326 entry->effect = IT_PORTAMENTO_UP;
327 entry->effectvalue = ptr[1];
328 break;
329
330 case 12:
331 entry->effect = IT_PORTAMENTO_DOWN;
332 entry->effectvalue = EFFECT_VALUE(ptr[1], 0xF);
333 break;
334
335 case 13:
336 entry->effect = IT_PORTAMENTO_DOWN;
337 entry->effectvalue = ptr[1];
338 break;
339
340 case 14:
341 entry->effect = IT_TONE_PORTAMENTO;
342 entry->effectvalue = ptr[1];
343 break;
344
345 case 15:
346 entry->effect = IT_S;
347 entry->effectvalue = EFFECT_VALUE(IT_S_SET_GLISSANDO_CONTROL, ptr[1] & 15);
348 break;
349
350 case 16:
351 entry->effect = IT_VOLSLIDE_TONEPORTA;
352 entry->effectvalue = ptr[1] << 4;
353 break;
354
355 case 17:
356 entry->effect = IT_VOLSLIDE_TONEPORTA;
357 entry->effectvalue = ptr[1] & 0xF;
358 break;
359
360 case 20:
361 entry->effect = IT_VIBRATO;
362 entry->effectvalue = ptr[1];
363 break;
364
365 case 21:
366 entry->effect = IT_S;
367 entry->effectvalue = EFFECT_VALUE(IT_S_SET_VIBRATO_WAVEFORM, ptr[1] & 11);
368 break;
369
370 case 22:
371 entry->effect = IT_VOLSLIDE_VIBRATO;
372 entry->effectvalue = ptr[1] << 4;
373 break;
374
375 case 23:
376 entry->effect = IT_VOLSLIDE_VIBRATO;
377 entry->effectvalue = ptr[1] & 0xF;
378 break;
379
380 case 30:
381 entry->effect = IT_TREMOLO;
382 entry->effectvalue = ptr[1];
383 break;
384
385 case 31:
386 entry->effect = IT_S;
387 entry->effectvalue = EFFECT_VALUE(IT_S_SET_TREMOLO_WAVEFORM, ptr[1] & 11);
388 break;
389
390 case 40:
391 entry->effect = IT_SET_SAMPLE_OFFSET;
392 entry->effectvalue = ptr[2];
393 ptr += 2;
394 break;
395
396 case 41:
397 entry->effect = IT_XM_RETRIGGER_NOTE;
398 entry->effectvalue = ptr[1];
399 break;
400
401 case 42:
402 entry->effect = IT_S;
403 entry->effectvalue = EFFECT_VALUE(IT_S_DELAYED_NOTE_CUT, ptr[1] & 0xF);
404 break;
405
406 case 43:
407 entry->effect = IT_S;
408 entry->effectvalue = EFFECT_VALUE(IT_S_NOTE_DELAY, ptr[1] & 0xF);
409 break;
410
411 case 50:
412 entry->effect = IT_JUMP_TO_ORDER;
413 entry->effectvalue = ptr[1];
414 break;
415
416 case 51:
417 entry->effect = IT_BREAK_TO_ROW;
418 entry->effectvalue = ptr[1];
419 break;
420
421 case 52:
422 entry->effect = IT_S;
423 entry->effectvalue = EFFECT_VALUE(IT_S_PATTERN_LOOP, ptr[1] & 0xF);
424 break;
425
426 case 53:
427 entry->effect = IT_S;
428 entry->effectvalue = EFFECT_VALUE(IT_S_PATTERN_DELAY, ptr[1] & 0xF);
429 break;
430
431 case 60:
432 entry->effect = IT_SET_SPEED;
433 entry->effectvalue = ptr[1];
434 break;
435
436 case 61:
437 entry->effect = IT_SET_SONG_TEMPO;
438 entry->effectvalue = ptr[1];
439 break;
440
441 case 70:
442 entry->effect = IT_ARPEGGIO;
443 entry->effectvalue = ptr[1];
444 break;
445
446 case 71:
447 entry->effect = IT_S;
448 entry->effectvalue = EFFECT_VALUE(IT_S_FINETUNE, ptr[1] & 0xF);
449 break;
450
451 case 72:
452 /* "balance" ... panning? */
453 entry->effect = IT_SET_PANNING;
454 entry->effectvalue = ((ptr[1] - ((ptr[1] & 8) >> 3)) << 5) / 7;
455 break;
456
457 default:
458 entry->mask &= ~IT_ENTRY_EFFECT;
459 }
460
461 ptr += 2;
462 }
463 if (entry->mask) entry++;
464 }
465 }
466
467 p->n_entries = (int)(entry - p->entry);
468 offset += psize;
469 }
470
471 free(buffer);
472
473 return 0;
474
475error_fb:
476 free(buffer);
477error:
478 return -1;
479}
480
481#define PSM_COMPONENT_ORDERS 0
482#define PSM_COMPONENT_PANPOS 1
483#define PSM_COMPONENT_PATTERNS 2
484#define PSM_COMPONENT_SAMPLE_HEADERS 3
485#define PSM_COMPONENT_COMMENTS 4
486
487typedef struct PSM_COMPONENT
488{
489 unsigned char type;
490 long offset;
491}
492PSM_COMPONENT;
493
494static int psm_component_compare(const void *e1, const void *e2)
495{
496 return (int)(((const PSM_COMPONENT *)e1)->offset -
497 ((const PSM_COMPONENT *)e2)->offset);
498}
499
500static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f)
501{
502 DUMB_IT_SIGDATA *sigdata;
503
504 PSM_COMPONENT *component;
505 int n_components = 0;
506
507 int n, flags, version, pver, n_orders, n_channels, total_pattern_size;
508
509 if (dumbfile_mgetl(f) != DUMB_ID('P','S','M',254)) goto error;
510
511 sigdata = malloc(sizeof(*sigdata));
512 if (!sigdata) goto error;
513
514 if (dumbfile_getnc((char *)sigdata->name, 60, f) < 60 ||
515 sigdata->name[59] != 0x1A) goto error_sd;
516 sigdata->name[59] = 0;
517
518 flags = dumbfile_getc(f);
519 version = dumbfile_getc(f);
520 pver = dumbfile_getc(f);
521 sigdata->speed = dumbfile_getc(f);
522 sigdata->tempo = dumbfile_getc(f);
523 sigdata->mixing_volume = dumbfile_getc(f);
524 sigdata->n_orders = dumbfile_igetw(f);
525 n_orders = dumbfile_igetw(f);
526 sigdata->n_patterns = dumbfile_igetw(f);
527 sigdata->n_samples = dumbfile_igetw(f);
528 sigdata->n_pchannels = dumbfile_igetw(f);
529 n_channels = dumbfile_igetw(f);
530
531 if (dumbfile_error(f) ||
532 (flags & 1) ||
533 (version != 1 && version != 0x10) ||
534 (pver) ||
535 (sigdata->n_orders <= 0) ||
536 (sigdata->n_orders > 255) ||
537 (n_orders > 255) ||
538 (n_orders < sigdata->n_orders) ||
539 (sigdata->n_patterns > 255) ||
540 (sigdata->n_samples > 255) ||
541 (sigdata->n_pchannels > DUMB_IT_N_CHANNELS) ||
542 (sigdata->n_pchannels > n_channels) ||
543 (n_channels > DUMB_IT_N_CHANNELS))
544 goto error_sd;
545
546 sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
547
548 sigdata->global_volume = 128;
549 sigdata->pan_separation = 128;
550
551 sigdata->song_message = NULL;
552 sigdata->order = NULL;
553 sigdata->instrument = NULL;
554 sigdata->sample = NULL;
555 sigdata->pattern = NULL;
556 sigdata->midi = NULL;
557 sigdata->checkpoint = NULL;
558
559 sigdata->n_instruments = 0;
560
561 sigdata->restart_position = 0;
562
563 sigdata->order = malloc(sigdata->n_orders);
564 if (!sigdata->order) goto error_usd;
565
566 if (sigdata->n_samples) {
567 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
568 if (!sigdata->sample) goto error_usd;
569 for (n = 0; n < sigdata->n_samples; n++)
570 sigdata->sample[n].data = NULL;
571 }
572
573 if (sigdata->n_patterns) {
574 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
575 if (!sigdata->pattern) goto error_usd;
576 for (n = 0; n < sigdata->n_patterns; n++)
577 sigdata->pattern[n].entry = NULL;
578 }
579
580 component = malloc(5 * sizeof(*component));
581 if (!component) goto error_usd;
582
583 for (n = 0; n < 5; n++) {
584 component[n_components].offset = dumbfile_igetl(f);
585 if (component[n_components].offset) {
586 component[n_components].type = n;
587 n_components++;
588 }
589 }
590
591 if (!n_components) goto error_fc;
592
593 total_pattern_size = (int)dumbfile_igetl(f);
594 if (!total_pattern_size) goto error_fc;
595
596 qsort(component, n_components, sizeof(PSM_COMPONENT), &psm_component_compare);
597
598 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
599
600 for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
601 int sep = 32 * dumb_it_default_panning_separation / 100;
602 sigdata->channel_pan[n ] = 32 - sep;
603 sigdata->channel_pan[n+1] = 32 + sep;
604 sigdata->channel_pan[n+2] = 32 + sep;
605 sigdata->channel_pan[n+3] = 32 - sep;
606 }
607
608 for (n = 0; n < n_components; n++)
609 {
610 int o;
611
612 if ( dumbfile_seek(f, component[n].offset, DFS_SEEK_SET) ) goto error_fc;
613
614 switch (component[n].type) {
615
616 case PSM_COMPONENT_ORDERS:
617 if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_fc;
618 if (n_orders > sigdata->n_orders)
619 if (dumbfile_skip(f, n_orders - sigdata->n_orders))
620 goto error_fc;
621 if (dumbfile_igetw(f)) goto error_fc;
622 break;
623
624 case PSM_COMPONENT_PANPOS:
625 if (dumbfile_getnc((char *)sigdata->channel_pan, sigdata->n_pchannels, f) < sigdata->n_pchannels) goto error_fc;
626 for (o = 0; o < sigdata->n_pchannels; o++) {
627 sigdata->channel_pan[o] -= (sigdata->channel_pan[o] & 8) >> 3;
628 sigdata->channel_pan[o] = ((int)sigdata->channel_pan[o] << 5) / 7;
629 }
630 break;
631
632 case PSM_COMPONENT_PATTERNS:
633 if (it_old_psm_read_patterns(sigdata->pattern, f, sigdata->n_patterns, total_pattern_size, sigdata->n_pchannels)) goto error_fc;
634 break;
635
636 case PSM_COMPONENT_SAMPLE_HEADERS:
637 if (it_old_psm_read_samples(&sigdata->sample, f, &sigdata->n_samples)) goto error_fc;
638 break;
639
640 case PSM_COMPONENT_COMMENTS:
641 if (dumbfile_mgetl(f) == DUMB_ID('T','E','X','T')) {
642 o = dumbfile_igetw(f);
643 if (o > 0) {
644 sigdata->song_message = malloc(o + 1);
645 if (dumbfile_getnc((char *)sigdata->song_message, o, f) < o) goto error_fc;
646 sigdata->song_message[o] = 0;
647 }
648 }
649 break;
650 }
651 }
652
653 _dumb_it_fix_invalid_orders(sigdata);
654
655 free(component);
656
657 return sigdata;
658
659error_fc:
660 free(component);
661error_usd:
662 _dumb_it_unload_sigdata(sigdata);
663 return NULL;
664error_sd:
665 free(sigdata);
666error:
667 return NULL;
668}
669
670DUH *dumb_read_old_psm_quick(DUMBFILE *f)
671{
672 sigdata_t *sigdata;
673
674 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
675
676 sigdata = it_old_psm_load_sigdata(f);
677
678 if (!sigdata)
679 return NULL;
680
681 {
682 const char *tag[2][2];
683 tag[0][0] = "TITLE";
684 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
685 tag[1][0] = "FORMAT";
686 tag[1][1] = "PSM (old)";
687 return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
688 }
689}
dumb/src/it/readpsm.c+0−1289
@@ -1,1289 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readpsm.c - Code to read a Protracker Studio / / \ \
12 * module from an open file. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22
23#include "dumb.h"
24#include "internal/it.h"
25
26#ifndef min
27#define min(a, b) (((a) < (b)) ? (a) : (b))
28#endif
29
30#ifdef _MSC_VER
31#define snprintf sprintf_s
32#endif
33
34#define PSMV_OLD 940730
35#define PSMV_NEW 940902
36
37typedef struct _PSMCHUNK
38{
39 int id;
40 int len;
41 unsigned char * data;
42} PSMCHUNK;
43
44typedef struct _PSMEVENT
45{
46 int type;
47 unsigned char data[8];
48} PSMEVENT;
49
50#define PSM_EVENT_END 0
51#define PSM_EVENT_PLAY_PATTERN 1
52#define PSM_EVENT_JUMP_TO_LINE 4
53#define PSM_EVENT_SET_SPEED 7
54#define PSM_EVENT_SET_BPM 8
55#define PSM_EVENT_SAMPLE_MAP_TABLE 12
56#define PSM_EVENT_CHANGE_PAN 13
57#define PSM_EVENT_CHANGE_VOL 14
58
59static int it_psm_process_sample(IT_SAMPLE * sample, const unsigned char * data, int len, int id, int version) {
60 int flags;
61 int insno;
62 int length;
63 int loopstart;
64 int loopend;
65 int panpos;
66 int defvol;
67 int samplerate;
68
69 if (len < 0x60) return -1;
70
71 flags = data[0];
72
73 if (version == PSMV_OLD) {
74 memcpy(sample->name, data + 0x0D, 34);
75 sample->name[34] = 0;
76
77 insno = data[0x34] | (data[0x35] << 8);
78 length = data[0x36] | (data[0x37] << 8) | (data[0x38] << 16) | (data[0x39] << 24);
79 loopstart = data[0x3A] | (data[0x3B] << 8) | (data[0x3C] << 16) | (data[0x3D] << 24);
80 loopend = data[0x3E] | (data[0x3F] << 8) | (data[0x40] << 16) | (data[0x41] << 24);
81 panpos = data[0x43];
82 defvol = data[0x44];
83 samplerate = data[0x49] | (data[0x4A] << 8) | (data[0x4B] << 16) | (data[0x4C] << 24);
84 } else /*if (version == PSMV_NEW)*/ {
85 memcpy(sample->name, data + 0x11, 34);
86 sample->name[34] = 0;
87
88 insno = data[0x38] | (data[0x39] << 8);
89 length = data[0x3A] | (data[0x3B] << 8) | (data[0x3C] << 16) | (data[0x3D] << 24);
90 loopstart = data[0x3E] | (data[0x3F] << 8) | (data[0x40] << 16) | (data[0x41] << 24);
91 loopend = data[0x42] | (data[0x43] << 8) | (data[0x44] << 16) | (data[0x45] << 24);
92 panpos = data[0x48];
93 defvol = data[0x49];
94 samplerate = data[0x4E] | (data[0x4F] << 8) | (data[0x50] << 16) | (data[0x51] << 24);
95 }
96
97 if (insno != id) return -1;
98
99 if (!length) {
100 sample->flags &= ~IT_SAMPLE_EXISTS;
101 return 0;
102 }
103
104 if ((length > len - 0x60) || ((flags & 0x7F) != 0)) return -1;
105
106 sample->flags = IT_SAMPLE_EXISTS;
107 sample->length = length;
108 sample->loop_start = loopstart;
109 sample->loop_end = loopend;
110 sample->C5_speed = samplerate;
111 sample->default_volume = defvol >> 1;
112 sample->default_pan = 0;
113 sample->filename[0] = 0;
114 sample->global_volume = 64;
115 sample->vibrato_speed = 0;
116 sample->vibrato_depth = 0;
117 sample->vibrato_rate = 0;
118 sample->vibrato_waveform = IT_VIBRATO_SINE;
119 sample->finetune = 0;
120 sample->max_resampling_quality = -1;
121
122 if (flags & 0x80) {
123 if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) &&
124 ((unsigned int)sample->loop_start < (unsigned int)sample->loop_end)) {
125 sample->length = sample->loop_end;
126 sample->flags |= IT_SAMPLE_LOOP;
127 }
128 }
129
130 sample->data = malloc(sample->length);
131 if (!sample->data)
132 return -1;
133
134 flags = 0;
135 data += 0x60;
136
137 for (insno = 0; insno < sample->length; insno++) {
138 flags += (signed char)(*data++);
139 ((signed char *)sample->data)[insno] = flags;
140 }
141
142 return 0;
143}
144
145static int it_psm_process_pattern(IT_PATTERN * pattern, const unsigned char * data, int len, int speed, int bpm, const unsigned char * pan, const int * vol, int version) {
146 int length, nrows, row, rowlen, pos;
147 unsigned flags, chan;
148 IT_ENTRY * entry;
149
150 length = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
151 if (len > length) len = length;
152
153 if (version == PSMV_OLD) {
154 if (len < 10) return -1;
155 data += 8;
156 len -= 8;
157 } else /*if (version == PSMV_NEW)*/ {
158 if (len < 14) return -1;
159 data += 12;
160 len -= 12;
161 }
162
163 nrows = data[0] | (data[1] << 8);
164
165 if (!nrows) return 0;
166
167 pattern->n_rows = nrows;
168
169 data += 2;
170 len -= 2;
171
172 pattern->n_entries = 0;
173
174 row = 0;
175 pos = 2;
176 rowlen = data[0] | (data[1] << 8);
177
178 while ((row < nrows) && (pos < len)) {
179 if (pos >= rowlen) {
180 row++;
181 rowlen += data[pos] | (data[pos+1] << 8);
182 pos += 2;
183 continue;
184 }
185
186 flags = data[pos++];
187 chan = data[pos++];
188
189 if (chan > 63) return -1;
190
191 if (flags & 0xF0) {
192 pattern->n_entries++;
193 if (flags & 0x80) pos++;
194 if (flags & 0x40) pos++;
195 if (flags & 0x20) pos++;
196 if (flags & 0x10) {
197 switch (data[pos]) {
198 case 0x29:
199 pos++;
200 case 0x33:
201 pos++;
202 default:
203 pos += 2;
204 }
205 }
206 }
207 }
208
209 if (!pattern->n_entries) return 0;
210
211 pattern->n_entries += nrows;
212 if (speed) pattern->n_entries++;
213 if (bpm >= 0x20) pattern->n_entries++;
214
215 for (pos = 0; pos < 32; pos++) {
216 if (!(pan[pos*2+1] & 0xF9)) pattern->n_entries++;
217 if (vol[pos] != -1) pattern->n_entries++;
218 }
219
220 pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
221 if (!pattern->entry) return -1;
222
223 entry = pattern->entry;
224
225 if (speed) {
226 entry->channel = 0;
227 entry->mask = IT_ENTRY_EFFECT;
228 entry->effect = IT_SET_SPEED;
229 entry->effectvalue = speed;
230 entry++;
231 }
232
233 if (bpm >= 0x20) {
234 entry->channel = 0;
235 entry->mask = IT_ENTRY_EFFECT;
236 entry->effect = IT_SET_SONG_TEMPO;
237 entry->effectvalue = bpm;
238 entry++;
239 }
240
241 for (pos = 0; pos < 32; pos++) {
242 if (!(pan[pos*2+1] & 0xF9)) {
243 entry->channel = pos;
244 entry->mask = IT_ENTRY_EFFECT;
245 switch (pan[pos*2+1]) {
246 case 0:
247 entry->effect = IT_SET_PANNING;
248 entry->effectvalue = pan[pos*2] ^ 128;
249 break;
250 case 2:
251 entry->effect = IT_S;
252 entry->effectvalue = EFFECT_VALUE(IT_S_SET_SURROUND_SOUND,1);
253 break;
254 case 4:
255 entry->effect = IT_SET_PANNING;
256 entry->effectvalue = 128;
257 break;
258 }
259 entry++;
260 }
261 if (vol[pos] != -1) {
262 entry->channel = pos;
263 entry->mask = IT_ENTRY_EFFECT;
264 entry->effect = IT_SET_CHANNEL_VOLUME;
265 entry->effectvalue = (vol[pos] + 2) >> 2;
266 entry++;
267 }
268 }
269
270 row = 0;
271 pos = 2;
272 rowlen = data[0] | (data[1] << 8);
273
274 while ((row < nrows) && (pos < len)) {
275 if (pos >= rowlen) {
276 IT_SET_END_ROW(entry);
277 entry++;
278 row++;
279 rowlen += data[pos] | (data[pos+1] << 8);
280 pos += 2;
281 continue;
282 }
283
284 flags = data[pos++];
285 entry->channel = data[pos++];
286 entry->mask = 0;
287
288 if (flags & 0xF0) {
289 if (flags & 0x80) {
290 entry->mask |= IT_ENTRY_NOTE;
291 if (version == PSMV_OLD) {
292 if ((data[pos] < 0x80)) entry->note = (data[pos]>>4)*12+(data[pos]&0x0f)+12;
293 else entry->mask &= ~IT_ENTRY_NOTE;
294 } else /*if (version == PSMV_NEW)*/ {
295 if ((data[pos]) && (data[pos] < 84)) entry->note = data[pos] + 35;
296 else entry->mask &= ~IT_ENTRY_NOTE;
297 }
298 pos++;
299 }
300
301 if (flags & 0x40) {
302 entry->mask |= IT_ENTRY_INSTRUMENT;
303 entry->instrument = data[pos++] + 1;
304 }
305
306 if (flags & 0x20) {
307 entry->mask |= IT_ENTRY_VOLPAN;
308 entry->volpan = (data[pos++] + 1) >> 1;
309 }
310
311 if (flags & 0x10) {
312 entry->mask |= IT_ENTRY_EFFECT;
313 length = data[pos+1];
314 switch (data[pos]) {
315 case 1:
316 entry->effect = IT_VOLUME_SLIDE;
317 if (version == PSMV_OLD) entry->effectvalue = ((length&0x1e)<<3) | 0xF;
318 else /*if (version == PSMV_NEW)*/ entry->effectvalue = (length<<4) | 0xF;
319 break;
320
321 case 2:
322 entry->effect = IT_VOLUME_SLIDE;
323 if (version == PSMV_OLD) entry->effectvalue = (length << 3) & 0xF0;
324 else /*if (version == PSMV_NEW)*/ entry->effectvalue = (length << 4) & 0xF0;
325 break;
326
327 case 3:
328 entry->effect = IT_VOLUME_SLIDE;
329 if (version == PSMV_OLD) entry->effectvalue = (length >> 1) | 0xF0;
330 else /*if (version == PSMV_NEW)*/ entry->effectvalue = length | 0xF0;
331 break;
332
333 case 4:
334 entry->effect = IT_VOLUME_SLIDE;
335 if (version == PSMV_OLD) entry->effectvalue = (length >> 1) & 0xF;
336 else /*if (version == PSMV_NEW)*/ entry->effectvalue = length & 0xF;
337 break;
338
339 case 12:
340 entry->effect = IT_PORTAMENTO_UP;
341 if (version == PSMV_OLD) {
342 if (length < 4) entry->effectvalue = length | 0xF0;
343 else entry->effectvalue = length >> 2;
344 } else /*if (version == PSMV_NEW)*/ {
345 entry->effectvalue = length;
346 }
347 break;
348
349 case 14:
350 entry->effect = IT_PORTAMENTO_DOWN;
351 if (version == PSMV_OLD) {
352 if (length < 4) entry->effectvalue = length | 0xF0;
353 else entry->effectvalue = length >> 2;
354 } else /*if (version == PSMV_NEW)*/ {
355 entry->effectvalue = length;
356 }
357 break;
358
359 case 15:
360 entry->effect = IT_TONE_PORTAMENTO;
361 if (version == PSMV_OLD) entry->effectvalue = length >> 2;
362 else /*if (version == PSMV_NEW)*/ entry->effectvalue = length;
363 break;
364
365 case 0x15:
366 entry->effect = IT_VIBRATO;
367 entry->effectvalue = length;
368 break;
369
370 case 0x18:
371 entry->effect = IT_VOLSLIDE_VIBRATO;
372 entry->effectvalue = length;
373 break;
374
375 case 0x29:
376 entry->effect = IT_SET_SAMPLE_OFFSET;
377 entry->effectvalue = data[pos+2];
378 pos += 2;
379 break;
380
381 case 0x2A:
382 entry->effect = IT_RETRIGGER_NOTE;
383 entry->effectvalue = length;
384 break;
385
386 case 0x33:
387#if 0
388 entry->effect = IT_POSITION_JUMP;
389 entry->effectvalue = data[pos+2];
390#else
391 entry->mask &= ~IT_ENTRY_EFFECT;
392#endif
393 pos++;
394 break;
395
396 case 0x34:
397 entry->effect = IT_BREAK_TO_ROW;
398 entry->effectvalue = length;
399 break;
400
401 case 0x3D:
402 entry->effect = IT_SET_SPEED;
403 entry->effectvalue = length;
404 break;
405
406 case 0x3E:
407 if (length >= 0x20) {
408 entry->effect = IT_SET_SONG_TEMPO;
409 entry->effectvalue = length;
410 } else {
411 entry->mask &= ~IT_ENTRY_EFFECT;
412 }
413 break;
414
415 case 0x47:
416 entry->effect = IT_ARPEGGIO;
417 entry->effectvalue = length;
418 break;
419
420 default:
421 return -1;
422 }
423 pos += 2;
424 }
425 if (entry->mask) entry++;
426 }
427 }
428
429 while (row < nrows) {
430 IT_SET_END_ROW(entry);
431 entry++;
432 row++;
433 }
434
435 pattern->n_entries = entry - pattern->entry;
436 if (!pattern->n_entries) return -1;
437
438 return 0;
439}
440
441
442static void free_chunks(PSMCHUNK * chunk, int count) {
443 int n;
444
445 for (n = 0; n < count; n++) {
446 if (chunk[n].data)
447 free(chunk[n].data);
448 }
449
450 free(chunk);
451}
452
453static void dumb_it_optimize_orders(DUMB_IT_SIGDATA * sigdata);
454
455static int pattcmp( const unsigned char *, const unsigned char *, size_t );
456
457static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong)
458{
459 DUMB_IT_SIGDATA *sigdata;
460
461 PSMCHUNK *chunk;
462 int n_chunks = 0;
463
464 PSMCHUNK *songchunk;
465 int n_song_chunks = 0;
466
467 PSMEVENT *event = 0;
468 int n_events = 0;
469
470 unsigned char * ptr;
471
472 int n, length, o;
473
474 int found;
475
476 int n_patterns = 0;
477
478 int first_pattern_line = -1;
479 int first_pattern;
480
481 int speed, bpm;
482 unsigned char pan[64];
483 int vol[32];
484
485 if (dumbfile_mgetl(f) != DUMB_ID('P','S','M',' ')) goto error;
486
487 length = dumbfile_igetl(f);
488
489 if (dumbfile_mgetl(f) != DUMB_ID('F','I','L','E')) goto error;
490
491 chunk = calloc(768, sizeof(*chunk));
492
493 while (length >= 8) {
494 chunk[n_chunks].id = dumbfile_mgetl(f);
495 n = dumbfile_igetl(f);
496 length -= 8;
497 if (n < 0 || n > length)
498 goto error_fc;
499 chunk[n_chunks].len = n;
500 if (n) {
501 ptr = malloc(n);
502 if (!ptr) goto error_fc;
503 if (dumbfile_getnc((char *)ptr, n, f) < n)
504 {
505 free(ptr);
506 goto error_fc;
507 }
508 chunk[n_chunks].data = ptr;
509 }
510 n_chunks++;
511 length -= n;
512 }
513
514 if (!n_chunks) goto error_fc;
515
516 sigdata = malloc(sizeof(*sigdata));
517 if (!sigdata) goto error_fc;
518
519 sigdata->n_patterns = 0;
520 sigdata->n_samples = 0;
521 sigdata->name[0] = 0;
522
523 found = 0;
524
525 for (n = 0; n < n_chunks; n++) {
526 PSMCHUNK * c = &chunk[n];
527 switch(c->id) {
528 case DUMB_ID('S','D','F','T'):
529 /* song data format? */
530 if ((found & 1) || (c->len != 8) || memcmp(c->data, "MAINSONG", 8)) goto error_sd;
531 found |= 1;
532 break;
533
534 case DUMB_ID('S','O','N','G'):
535 if (/*(found & 2) ||*/ (c->len < 11) /*|| memcmp(c->data, "MAINSONG", 8)*/) goto error_sd;
536 found |= 2;
537 break;
538
539 case DUMB_ID('D','S','M','P'):
540 sigdata->n_samples++;
541 break;
542
543 case DUMB_ID('T','I','T','L'):
544 length = min(sizeof(sigdata->name) - 1, (unsigned)c->len);
545 memcpy(sigdata->name, c->data, length);
546 sigdata->name[length] = 0;
547 }
548 }
549
550 if (found != 3 || !sigdata->n_samples) goto error_sd;
551
552 sigdata->song_message = NULL;
553 sigdata->order = NULL;
554 sigdata->instrument = NULL;
555 sigdata->sample = NULL;
556 sigdata->pattern = NULL;
557 sigdata->midi = NULL;
558 sigdata->checkpoint = NULL;
559
560 sigdata->n_instruments = 0;
561 sigdata->n_orders = 0;
562
563 for (n = 0; n < n_chunks; n++) {
564 PSMCHUNK * c = &chunk[n];
565 if (c->id == DUMB_ID('S','O','N','G')) {
566 if (subsong == 0) break;
567 subsong--;
568 }
569 }
570
571 if (n == n_chunks) return NULL;
572 subsong = n;
573
574 /*for (n = 0; n < n_chunks; n++) {
575 PSMCHUNK * c = &chunk[n];
576 if (c->id == DUMB_ID('S','O','N','G')) {*/
577 {
578 PSMCHUNK * c = &chunk[subsong];
579 {
580 ptr = c->data;
581 if (ptr[10] > 32) goto error_usd;
582 sigdata->n_pchannels = ptr[10];
583 length = c->len - 11;
584 ptr += 11;
585 songchunk = 0;
586 if (length >= 8) {
587 songchunk = malloc(128 * sizeof(*songchunk));
588 if (!songchunk) goto error_usd;
589 while (length >= 8) {
590 songchunk[n_song_chunks].id = DUMB_ID(ptr[0], ptr[1], ptr[2], ptr[3]);
591 n = ptr[4] | (ptr[5] << 8) | (ptr[6] << 16) | (ptr[7] << 24);
592 length -= 8;

697 more lines aren’t shown here.

dumb/src/it/readptm.c+0−554

This diff is large: its 555 lines aren’t shown here.

dumb/src/it/reads3m.c+0−766

This diff is large: its 767 lines aren’t shown here.

dumb/src/it/readstm.c+0−397

This diff is large: its 398 lines aren’t shown here.

dumb/src/it/readxm.c+0−1428

This diff is large: its 1429 lines aren’t shown here.

dumb/src/it/xmeffect.c+0−245

This diff is large: its 246 lines aren’t shown here.

examples/README.md+19−0

This diff is large: its 20 lines aren’t shown here.

examples/dumbout.crenamed from dumb/examples/dumbout.c+110−79

This diff is large: its 341 lines aren’t shown here.

examples/dumbplay.crenamed from dumb/examples/dumbplay.c+88−57

This diff is large: its 300 lines aren’t shown here.

include/aldumb.h+83−0

This diff is large: its 84 lines aren’t shown here.

include/dumb.h+819−0

This diff is large: its 820 lines aren’t shown here.

include/internal/aldumb.hrenamed from dumb/include/internal/aldumb.h+0−2

This diff is large: its 9 lines aren’t shown here.

include/internal/barray.h+43−0

This diff is large: its 44 lines aren’t shown here.

include/internal/dumb.hrenamed from dumb/include/internal/dumb.h+35−21

This diff is large: its 72 lines aren’t shown here.

include/internal/dumbfile.hrenamed from dumb/include/internal/dumbfile.h+1−2

This diff is large: its 10 lines aren’t shown here.

include/internal/it.h+874−0

This diff is large: its 875 lines aren’t shown here.

include/internal/lpc.hrenamed from dumb/include/internal/lpc.h+1−1

This diff is large: its 8 lines aren’t shown here.

include/internal/resampler.h+70−0

This diff is large: its 71 lines aren’t shown here.

include/internal/riff.h+22−0

This diff is large: its 23 lines aren’t shown here.

include/internal/stack_alloc.hrenamed from dumb/include/internal/stack_alloc.h+17−12

This diff is large: its 59 lines aren’t shown here.

include/internal/tarray.h+20−0

This diff is large: its 21 lines aren’t shown here.

pkg-config.pc.in+12−0

This diff is large: its 13 lines aren’t shown here.

src/allegro/alplay.c+217−0

This diff is large: its 218 lines aren’t shown here.

src/allegro/datduh.c+50−0

This diff is large: its 51 lines aren’t shown here.

src/allegro/datit.c+51−0

This diff is large: its 52 lines aren’t shown here.

src/allegro/datitq.c+54−0

This diff is large: its 55 lines aren’t shown here.

src/allegro/datmod.c+51−0

This diff is large: its 52 lines aren’t shown here.

src/allegro/datmodq.c+54−0

This diff is large: its 55 lines aren’t shown here.

src/allegro/dats3m.c+51−0

This diff is large: its 52 lines aren’t shown here.

src/allegro/dats3mq.c+54−0

This diff is large: its 55 lines aren’t shown here.

src/allegro/datunld.c+25−0

This diff is large: its 26 lines aren’t shown here.

src/allegro/datxm.c+51−0

This diff is large: its 52 lines aren’t shown here.

src/allegro/datxmq.c+54−0

This diff is large: its 55 lines aren’t shown here.

src/allegro/packfile.c+119−0

This diff is large: its 120 lines aren’t shown here.

src/core/atexit.crenamed from dumb/src/core/atexit.c+25−36

This diff is large: its 76 lines aren’t shown here.

src/core/duhlen.crenamed from dumb/src/core/duhlen.c+4−12

This diff is large: its 22 lines aren’t shown here.

src/core/duhtag.crenamed from dumb/src/core/duhtag.c+20−25

This diff is large: its 58 lines aren’t shown here.

src/core/dumbfile.c+373−0

This diff is large: its 374 lines aren’t shown here.

src/core/loadduh.crenamed from dumb/src/core/loadduh.c+8−11

This diff is large: its 32 lines aren’t shown here.

src/core/makeduh.c+146−0

This diff is large: its 147 lines aren’t shown here.

src/core/rawsig.crenamed from dumb/src/core/rawsig.c+25−30

This diff is large: its 63 lines aren’t shown here.

src/core/readduh.c+101−0

This diff is large: its 102 lines aren’t shown here.

src/core/register.crenamed from dumb/src/core/register.c+45−53

This diff is large: its 127 lines aren’t shown here.

src/core/rendduh.c+261−0

This diff is large: its 262 lines aren’t shown here.

src/core/rendsig.c+242−0

This diff is large: its 243 lines aren’t shown here.

src/core/unload.crenamed from dumb/src/core/unload.c+24−30

This diff is large: its 68 lines aren’t shown here.

src/helpers/barray.c+155−0

This diff is large: its 156 lines aren’t shown here.

src/helpers/clickrem.c+257−0

This diff is large: its 258 lines aren’t shown here.

src/helpers/lpc.c+340−0

This diff is large: its 341 lines aren’t shown here.

src/helpers/memfile.c+94−0

This diff is large: its 95 lines aren’t shown here.

src/helpers/resamp2.inc+178−0

This diff is large: its 179 lines aren’t shown here.

src/helpers/resamp3.inc+278−0

This diff is large: its 279 lines aren’t shown here.

src/helpers/resample.c+332−0

This diff is large: its 333 lines aren’t shown here.

src/helpers/resample.inc+288−0

This diff is large: its 289 lines aren’t shown here.

src/helpers/resampler.crenamed from dumb/src/helpers/resampler.c+606−669

This diff is large: its 2046 lines aren’t shown here.

src/helpers/riff.c+88−0

This diff is large: its 89 lines aren’t shown here.

src/helpers/sampbuf.crenamed from dumb/src/helpers/sampbuf.c+18−39

This diff is large: its 64 lines aren’t shown here.

src/helpers/silence.crenamed from dumb/src/helpers/silence.c+2−6

This diff is large: its 13 lines aren’t shown here.

src/helpers/stdfile.c+113−0

This diff is large: its 114 lines aren’t shown here.

src/helpers/tarray.c+180−0

This diff is large: its 181 lines aren’t shown here.

src/it/itload.crenamed from dumb/src/it/itload.c+8−12

This diff is large: its 33 lines aren’t shown here.

src/it/itload2.crenamed from dumb/src/it/itload2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/itmisc.c+169−0

This diff is large: its 170 lines aren’t shown here.

src/it/itorder.crenamed from dumb/src/it/itorder.c+34−32

This diff is large: its 82 lines aren’t shown here.

src/it/itread.c+1468−0

This diff is large: its 1469 lines aren’t shown here.

src/it/itread2.crenamed from dumb/src/it/itread2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/itrender.c+6595−0

This diff is large: its 6596 lines aren’t shown here.

src/it/itunload.c+69−0

This diff is large: its 70 lines aren’t shown here.

src/it/load669.crenamed from dumb/src/it/load669.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/load6692.crenamed from dumb/src/it/load6692.c+5−8

This diff is large: its 29 lines aren’t shown here.

src/it/loadamf.crenamed from dumb/src/it/loadamf.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/loadamf2.crenamed from dumb/src/it/loadamf2.c+5−8

This diff is large: its 28 lines aren’t shown here.

src/it/loadany.crenamed from dumb/src/it/loadany.c+8−11

This diff is large: its 36 lines aren’t shown here.

src/it/loadany2.crenamed from dumb/src/it/loadany2.c+4−7

This diff is large: its 22 lines aren’t shown here.

src/it/loadasy.crenamed from dumb/src/it/loadasy.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/loadasy2.crenamed from dumb/src/it/loadasy2.c+5−8

This diff is large: its 28 lines aren’t shown here.

src/it/loadmod.crenamed from dumb/src/it/loadmod.c+8−11

This diff is large: its 32 lines aren’t shown here.

src/it/loadmod2.crenamed from dumb/src/it/loadmod2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/loadmtm.crenamed from dumb/src/it/loadmtm.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/loadmtm2.crenamed from dumb/src/it/loadmtm2.c+5−8

This diff is large: its 29 lines aren’t shown here.

src/it/loadokt.crenamed from dumb/src/it/loadokt.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/loadokt2.crenamed from dumb/src/it/loadokt2.c+5−8

This diff is large: its 23 lines aren’t shown here.

src/it/loadoldpsm.crenamed from dumb/src/it/loadoldpsm.c+9−12

This diff is large: its 42 lines aren’t shown here.

src/it/loadoldpsm2.crenamed from dumb/src/it/loadoldpsm2.c+5−8

This diff is large: its 28 lines aren’t shown here.

src/it/loadpsm.crenamed from dumb/src/it/loadpsm.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/loadpsm2.crenamed from dumb/src/it/loadpsm2.c+5−8

This diff is large: its 29 lines aren’t shown here.

src/it/loadptm.crenamed from dumb/src/it/loadptm.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/loadptm2.crenamed from dumb/src/it/loadptm2.c+5−8

This diff is large: its 29 lines aren’t shown here.

src/it/loadriff.crenamed from dumb/src/it/loadriff.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/loadriff2.crenamed from dumb/src/it/loadriff2.c+5−8

This diff is large: its 24 lines aren’t shown here.

src/it/loads3m.crenamed from dumb/src/it/loads3m.c+8−11

This diff is large: its 32 lines aren’t shown here.

src/it/loads3m2.crenamed from dumb/src/it/loads3m2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/loadstm.crenamed from dumb/src/it/loadstm.c+9−12

This diff is large: its 41 lines aren’t shown here.

src/it/loadstm2.crenamed from dumb/src/it/loadstm2.c+5−8

This diff is large: its 24 lines aren’t shown here.

src/it/loadxm.crenamed from dumb/src/it/loadxm.c+8−11

This diff is large: its 32 lines aren’t shown here.

src/it/loadxm2.crenamed from dumb/src/it/loadxm2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/ptmeffect.c+174−0

This diff is large: its 175 lines aren’t shown here.

src/it/read669.c+454−0

This diff is large: its 455 lines aren’t shown here.

src/it/read6692.crenamed from dumb/src/it/read6692.c+2−5

This diff is large: its 21 lines aren’t shown here.

src/it/readam.c+805−0

This diff is large: its 806 lines aren’t shown here.

src/it/readamf.c+597−0

This diff is large: its 598 lines aren’t shown here.

src/it/readamf2.crenamed from dumb/src/it/readamf2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/readany.c+103−0

This diff is large: its 104 lines aren’t shown here.

src/it/readany2.crenamed from dumb/src/it/readany2.c+4−7

This diff is large: its 22 lines aren’t shown here.

src/it/readasy.c+344−0

This diff is large: its 345 lines aren’t shown here.

src/it/readdsmf.c+395−0

This diff is large: its 396 lines aren’t shown here.

src/it/readmod.c+651−0

This diff is large: its 652 lines aren’t shown here.

src/it/readmod2.crenamed from dumb/src/it/readmod2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/readmtm.c+458−0

This diff is large: its 459 lines aren’t shown here.

src/it/readokt.c+605−0

This diff is large: its 606 lines aren’t shown here.

src/it/readokt2.crenamed from dumb/src/it/readokt2.c+5−8

This diff is large: its 23 lines aren’t shown here.

src/it/readoldpsm.c+745−0

This diff is large: its 746 lines aren’t shown here.

src/it/readpsm.c+1418−0

This diff is large: its 1419 lines aren’t shown here.

src/it/readptm.c+565−0

This diff is large: its 566 lines aren’t shown here.

src/it/readriff.crenamed from dumb/src/it/readriff.c+22−21

This diff is large: its 68 lines aren’t shown here.

src/it/reads3m.c+780−0

This diff is large: its 781 lines aren’t shown here.

src/it/reads3m2.crenamed from dumb/src/it/reads3m2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/readstm.c+404−0

This diff is large: its 405 lines aren’t shown here.

src/it/readstm2.crenamed from dumb/src/it/readstm2.c+5−8

This diff is large: its 24 lines aren’t shown here.

src/it/readxm.c+1431−0

This diff is large: its 1432 lines aren’t shown here.

src/it/readxm2.crenamed from dumb/src/it/readxm2.c+4−7

This diff is large: its 16 lines aren’t shown here.

src/it/xmeffect.c+305−0

This diff is large: its 306 lines aren’t shown here.

vc6/.gitignorerenamed from dumb/vc6/dumb/.gitignore+0−0

File renamed without changes.

vc6/dumb/dumb.vcprojrenamed from dumb/vc6/dumb/dumb.vcproj+2−2

This diff is large: its 18 lines aren’t shown here.

vc6/dumb/dumb.vcxprojrenamed from dumb/vc6/dumb/dumb.vcxproj+42−9

This diff is large: its 115 lines aren’t shown here.

vc6/dumb/dumb.vcxproj.filtersrenamed from dumb/vc6/dumb/dumb.vcxproj.filters+0−0

File renamed without changes.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t