gosu 0.15.2 → 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (234) hide show
  1. checksums.yaml +4 -4
  2. data/dependencies/SDL/include/SDL.h +138 -0
  3. data/dependencies/SDL/include/SDL_assert.h +293 -0
  4. data/dependencies/SDL/include/SDL_atomic.h +295 -0
  5. data/dependencies/SDL/include/SDL_audio.h +859 -0
  6. data/dependencies/SDL/include/SDL_bits.h +121 -0
  7. data/dependencies/SDL/include/SDL_blendmode.h +123 -0
  8. data/dependencies/SDL/include/SDL_clipboard.h +71 -0
  9. data/dependencies/SDL/include/SDL_config.h +55 -0
  10. data/dependencies/SDL/include/SDL_config_android.h +182 -0
  11. data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
  12. data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
  13. data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
  14. data/dependencies/SDL/include/SDL_config_os2.h +188 -0
  15. data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
  16. data/dependencies/SDL/include/SDL_config_psp.h +165 -0
  17. data/dependencies/SDL/include/SDL_config_windows.h +288 -0
  18. data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
  19. data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
  20. data/dependencies/SDL/include/SDL_copying.h +20 -0
  21. data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
  22. data/dependencies/SDL/include/SDL_egl.h +1676 -0
  23. data/dependencies/SDL/include/SDL_endian.h +263 -0
  24. data/dependencies/SDL/include/SDL_error.h +112 -0
  25. data/dependencies/SDL/include/SDL_events.h +827 -0
  26. data/dependencies/SDL/include/SDL_filesystem.h +136 -0
  27. data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
  28. data/dependencies/SDL/include/SDL_gesture.h +87 -0
  29. data/dependencies/SDL/include/SDL_haptic.h +1247 -0
  30. data/dependencies/SDL/include/SDL_hints.h +1578 -0
  31. data/dependencies/SDL/include/SDL_joystick.h +499 -0
  32. data/dependencies/SDL/include/SDL_keyboard.h +217 -0
  33. data/dependencies/SDL/include/SDL_keycode.h +351 -0
  34. data/dependencies/SDL/include/SDL_loadso.h +81 -0
  35. data/dependencies/SDL/include/SDL_locale.h +101 -0
  36. data/dependencies/SDL/include/SDL_log.h +211 -0
  37. data/dependencies/SDL/include/SDL_main.h +180 -0
  38. data/dependencies/SDL/include/SDL_messagebox.h +146 -0
  39. data/dependencies/SDL/include/SDL_metal.h +117 -0
  40. data/dependencies/SDL/include/SDL_misc.h +75 -0
  41. data/dependencies/SDL/include/SDL_mouse.h +302 -0
  42. data/dependencies/SDL/include/SDL_mutex.h +251 -0
  43. data/dependencies/SDL/include/SDL_name.h +33 -0
  44. data/dependencies/SDL/include/SDL_opengl.h +2183 -0
  45. data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
  46. data/dependencies/SDL/include/SDL_opengles.h +39 -0
  47. data/dependencies/SDL/include/SDL_opengles2.h +52 -0
  48. data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
  49. data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
  50. data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
  51. data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
  52. data/dependencies/SDL/include/SDL_pixels.h +479 -0
  53. data/dependencies/SDL/include/SDL_platform.h +198 -0
  54. data/dependencies/SDL/include/SDL_power.h +75 -0
  55. data/dependencies/SDL/include/SDL_quit.h +58 -0
  56. data/dependencies/SDL/include/SDL_rect.h +174 -0
  57. data/dependencies/SDL/include/SDL_render.h +1158 -0
  58. data/dependencies/SDL/include/SDL_revision.h +2 -0
  59. data/dependencies/SDL/include/SDL_rwops.h +283 -0
  60. data/dependencies/SDL/include/SDL_scancode.h +413 -0
  61. data/dependencies/SDL/include/SDL_sensor.h +267 -0
  62. data/dependencies/SDL/include/SDL_shape.h +144 -0
  63. data/dependencies/SDL/include/SDL_stdinc.h +647 -0
  64. data/dependencies/SDL/include/SDL_surface.h +563 -0
  65. data/dependencies/SDL/include/SDL_system.h +325 -0
  66. data/dependencies/SDL/include/SDL_syswm.h +354 -0
  67. data/dependencies/SDL/include/SDL_test.h +69 -0
  68. data/dependencies/SDL/include/SDL_test_assert.h +105 -0
  69. data/dependencies/SDL/include/SDL_test_common.h +218 -0
  70. data/dependencies/SDL/include/SDL_test_compare.h +69 -0
  71. data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
  72. data/dependencies/SDL/include/SDL_test_font.h +81 -0
  73. data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
  74. data/dependencies/SDL/include/SDL_test_harness.h +134 -0
  75. data/dependencies/SDL/include/SDL_test_images.h +78 -0
  76. data/dependencies/SDL/include/SDL_test_log.h +67 -0
  77. data/dependencies/SDL/include/SDL_test_md5.h +129 -0
  78. data/dependencies/SDL/include/SDL_test_memory.h +63 -0
  79. data/dependencies/SDL/include/SDL_test_random.h +115 -0
  80. data/dependencies/SDL/include/SDL_thread.h +366 -0
  81. data/dependencies/SDL/include/SDL_timer.h +115 -0
  82. data/dependencies/SDL/include/SDL_touch.h +102 -0
  83. data/dependencies/SDL/include/SDL_types.h +29 -0
  84. data/dependencies/SDL/include/SDL_version.h +162 -0
  85. data/dependencies/SDL/include/SDL_video.h +1282 -0
  86. data/dependencies/SDL/include/SDL_vulkan.h +276 -0
  87. data/dependencies/SDL/include/begin_code.h +166 -0
  88. data/dependencies/SDL/include/close_code.h +40 -0
  89. data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
  90. data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
  91. data/dependencies/SDL_sound/SDL_sound.c +795 -0
  92. data/dependencies/SDL_sound/SDL_sound.h +725 -0
  93. data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
  94. data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
  95. data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
  96. data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
  97. data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
  98. data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
  99. data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
  100. data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
  101. data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
  102. data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
  103. data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
  104. data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
  105. data/dependencies/SDL_sound/dr_flac.h +5906 -0
  106. data/dependencies/SDL_sound/dr_mp3.h +2832 -0
  107. data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
  108. data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
  109. data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
  110. data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
  111. data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
  112. data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
  113. data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
  114. data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
  115. data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
  116. data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
  117. data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
  118. data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
  119. data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
  120. data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
  121. data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
  122. data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
  123. data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
  124. data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
  125. data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
  126. data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
  127. data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
  128. data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
  129. data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
  130. data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
  131. data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
  132. data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
  133. data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
  134. data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
  135. data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
  136. data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
  137. data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
  138. data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
  139. data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
  140. data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
  141. data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
  142. data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
  143. data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
  144. data/dependencies/al_soft/AL/al.h +655 -0
  145. data/dependencies/al_soft/AL/alc.h +270 -0
  146. data/dependencies/al_soft/AL/alext.h +585 -0
  147. data/dependencies/al_soft/AL/efx-creative.h +3 -0
  148. data/dependencies/al_soft/AL/efx-presets.h +402 -0
  149. data/dependencies/al_soft/AL/efx.h +762 -0
  150. data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
  151. data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
  152. data/{src → dependencies/stb}/stb_image.h +330 -127
  153. data/{src → dependencies/stb}/stb_image_write.h +156 -85
  154. data/{src → dependencies/stb}/stb_truetype.h +192 -69
  155. data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
  156. data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
  157. data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
  158. data/ext/gosu/extconf.rb +56 -22
  159. data/{Gosu → include/Gosu}/Audio.hpp +6 -8
  160. data/{Gosu → include/Gosu}/AutoLink.hpp +0 -0
  161. data/include/Gosu/Bitmap.hpp +100 -0
  162. data/{Gosu → include/Gosu}/Buttons.hpp +94 -35
  163. data/{Gosu → include/Gosu}/Channel.h +0 -0
  164. data/{Gosu → include/Gosu}/Color.h +0 -0
  165. data/{Gosu → include/Gosu}/Color.hpp +0 -0
  166. data/{Gosu → include/Gosu}/Directories.hpp +0 -0
  167. data/{Gosu → include/Gosu}/Font.h +0 -0
  168. data/{Gosu → include/Gosu}/Font.hpp +0 -0
  169. data/{Gosu → include/Gosu}/Fwd.hpp +0 -0
  170. data/{Gosu → include/Gosu}/Gosu.h +3 -0
  171. data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
  172. data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
  173. data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
  174. data/{Gosu → include/Gosu}/IO.hpp +0 -0
  175. data/{Gosu → include/Gosu}/Image.h +0 -0
  176. data/{Gosu → include/Gosu}/Image.hpp +7 -6
  177. data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
  178. data/{Gosu → include/Gosu}/Input.hpp +30 -15
  179. data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
  180. data/{Gosu → include/Gosu}/Math.hpp +0 -0
  181. data/{Gosu → include/Gosu}/Platform.hpp +0 -0
  182. data/{Gosu → include/Gosu}/Sample.h +0 -0
  183. data/{Gosu → include/Gosu}/Song.h +0 -0
  184. data/{Gosu → include/Gosu}/Text.hpp +0 -0
  185. data/{Gosu → include/Gosu}/TextInput.h +0 -0
  186. data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
  187. data/{Gosu → include/Gosu}/Timing.hpp +0 -0
  188. data/{Gosu → include/Gosu}/Utility.hpp +1 -1
  189. data/{Gosu → include/Gosu}/Version.hpp +0 -0
  190. data/{Gosu → include/Gosu}/Window.h +2 -0
  191. data/{Gosu → include/Gosu}/Window.hpp +21 -13
  192. data/lib/OpenAL32.dll +0 -0
  193. data/lib/SDL2.dll +0 -0
  194. data/lib/gosu.rb +0 -3
  195. data/lib/gosu/patches.rb +0 -9
  196. data/lib/gosu/swig_patches.rb +3 -2
  197. data/lib/libmpg123.dll +0 -0
  198. data/lib/libsndfile.dll +0 -0
  199. data/lib64/OpenAL32.dll +0 -0
  200. data/lib64/SDL2.dll +0 -0
  201. data/lib64/libmpg123.dll +0 -0
  202. data/lib64/libsndfile.dll +0 -0
  203. data/rdoc/gosu.rb +95 -20
  204. data/src/Audio.cpp +50 -224
  205. data/src/AudioFile.hpp +17 -37
  206. data/src/AudioFileAudioToolbox.cpp +237 -0
  207. data/src/AudioFileSDLSound.cpp +147 -0
  208. data/src/AudioImpl.cpp +3 -12
  209. data/src/AudioImpl.hpp +3 -1
  210. data/src/Bitmap.cpp +85 -83
  211. data/src/BitmapIO.cpp +52 -58
  212. data/src/Constants.cpp +80 -33
  213. data/src/Font.cpp +3 -1
  214. data/src/GosuWrapper.cpp +19 -0
  215. data/src/Graphics.cpp +7 -4
  216. data/src/Image.cpp +13 -16
  217. data/src/Input.cpp +408 -159
  218. data/src/LargeImageData.cpp +1 -1
  219. data/src/MarkupParser.cpp +2 -1
  220. data/src/RubyGosu.cxx +349 -83
  221. data/src/RubyGosu.h +4 -2
  222. data/src/TexChunk.cpp +1 -1
  223. data/src/TextBuilder.cpp +3 -1
  224. data/src/Texture.cpp +1 -1
  225. data/src/TrueTypeFont.cpp +1 -1
  226. data/src/Utility.cpp +11 -7
  227. data/src/Window.cpp +30 -39
  228. data/src/WindowWrapper.cpp +28 -0
  229. metadata +207 -52
  230. data/Gosu/Bitmap.hpp +0 -113
  231. data/src/AudioToolboxFile.hpp +0 -210
  232. data/src/OggFile.hpp +0 -92
  233. data/src/SndFile.hpp +0 -174
  234. data/src/WinMain.cpp +0 -64
@@ -0,0 +1,223 @@
1
+ /**
2
+ * SDL_sound; A sound processing toolkit.
3
+ *
4
+ * Please see the file LICENSE.txt in the source's root directory.
5
+ *
6
+ * This file written by Ryan C. Gordon.
7
+ */
8
+
9
+ /*
10
+ * Ogg Vorbis decoder for SDL_sound.
11
+ *
12
+ * This driver handles .OGG audio files, and uses Sean Barrett's excellent
13
+ * stb_vorbis for the heavy lifting. Since stb_vorbis is a single,
14
+ * public domain C header file, it's just compiled into this source and
15
+ * needs no external dependencies.
16
+ *
17
+ * stb_vorbis homepage: https://nothings.org/stb_vorbis/
18
+ */
19
+
20
+ #define __SDL_SOUND_INTERNAL__
21
+ #include "SDL_sound_internal.h"
22
+
23
+ #if SOUND_SUPPORTS_VORBIS
24
+
25
+ /* Configure and include stb_vorbis for compiling... */
26
+ #define STB_VORBIS_NO_STDIO 1
27
+ #define STB_VORBIS_NO_CRT 1
28
+ #define STB_VORBIS_NO_PUSHDATA_API 1
29
+ #define STB_VORBIS_MAX_CHANNELS 6
30
+ #define STBV_CDECL
31
+ #define STB_FORCEINLINE SDL_FORCE_INLINE
32
+ #if SDL_BYTEORDER == SDL_BIG_ENDIAN
33
+ #define STB_VORBIS_BIG_ENDIAN 1
34
+ #endif
35
+
36
+ #if !defined(__clang_analyzer__)
37
+ #ifdef assert
38
+ #undef assert
39
+ #endif
40
+ #ifdef memset
41
+ #undef memset
42
+ #endif
43
+ #ifdef memcpy
44
+ #undef memcpy
45
+ #endif
46
+ #ifdef alloca
47
+ #undef alloca
48
+ #endif
49
+ #define assert SDL_assert
50
+ #define memset SDL_memset
51
+ #define memcmp SDL_memcmp
52
+ #define memcpy SDL_memcpy
53
+ #define qsort SDL_qsort
54
+ #define pow SDL_pow
55
+ #define floor SDL_floor
56
+ #define malloc SDL_malloc
57
+ #define realloc SDL_realloc
58
+ #define free SDL_free
59
+ #define alloca(x) ((void *) SDL_stack_alloc(Uint8, (x)))
60
+ #define dealloca(x) SDL_stack_free((x))
61
+ #define ldexp(v, e) SDL_scalbn((v), (e))
62
+ #define abs(x) SDL_abs(x)
63
+ #define cos(x) SDL_cos(x)
64
+ #define sin(x) SDL_sin(x)
65
+ #define log(x) SDL_log(x)
66
+ #endif
67
+ #include "stb_vorbis.h"
68
+
69
+ static const char *vorbis_error_string(const int err)
70
+ {
71
+ switch (err)
72
+ {
73
+ case VORBIS__no_error: return NULL;
74
+ case VORBIS_need_more_data: return "VORBIS: need more data";
75
+ case VORBIS_invalid_api_mixing: return "VORBIS: can't mix API modes";
76
+ case VORBIS_outofmem: return "VORBIS: out of memory";
77
+ case VORBIS_feature_not_supported: return "VORBIS: feature not supported";
78
+ case VORBIS_too_many_channels: return "VORBIS: too many channels";
79
+ case VORBIS_seek_without_length: return "VORBIS: can't seek in unknown length stream";
80
+ case VORBIS_unexpected_eof: return "VORBIS: unexpected eof";
81
+ case VORBIS_seek_invalid: return "VORBIS: invalid seek";
82
+ case VORBIS_invalid_setup: return "VORBIS: invalid setup";
83
+ case VORBIS_invalid_stream: return "VORBIS: invalid stream";
84
+ case VORBIS_missing_capture_pattern: return "VORBIS: missing capture pattern";
85
+ case VORBIS_invalid_stream_structure_version: return "VORBIS: invalid stream structure version";
86
+ case VORBIS_continued_packet_flag_invalid: return "VORBIS: continued packet flag invalid";
87
+ case VORBIS_incorrect_stream_serial_number: return "VORBIS: incorrect stream serial number";
88
+ case VORBIS_invalid_first_page: return "VORBIS: invalid first page";
89
+ case VORBIS_bad_packet_type: return "VORBIS: bad packet type";
90
+ case VORBIS_cant_find_last_page: return "VORBIS: can't find last page";
91
+ case VORBIS_seek_failed: return "VORBIS: seek failed";
92
+ default: break;
93
+ } /* switch */
94
+
95
+ return "VORBIS: unknown error";
96
+ } /* vorbis_error_string */
97
+
98
+ static int VORBIS_init(void)
99
+ {
100
+ return 1; /* always succeeds. */
101
+ } /* VORBIS_init */
102
+
103
+ static void VORBIS_quit(void)
104
+ {
105
+ /* it's a no-op. */
106
+ } /* VORBIS_quit */
107
+
108
+ static int VORBIS_open(Sound_Sample *sample, const char *ext)
109
+ {
110
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
111
+ SDL_RWops *rw = internal->rw;
112
+ int err = 0;
113
+ stb_vorbis *stb = stb_vorbis_open_rwops(rw, 0, &err, NULL);
114
+ unsigned int num_frames;
115
+
116
+ BAIL_IF_MACRO(!stb, vorbis_error_string(err), 0);
117
+
118
+ SNDDBG(("VORBIS: Accepting data stream.\n"));
119
+
120
+ internal->decoder_private = stb;
121
+ sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
122
+ sample->actual.format = AUDIO_F32SYS;
123
+ sample->actual.channels = stb->channels;
124
+ sample->actual.rate = stb->sample_rate;
125
+ num_frames = stb_vorbis_stream_length_in_samples(stb);
126
+ if (!num_frames)
127
+ internal->total_time = -1;
128
+ else
129
+ {
130
+ const unsigned int rate = stb->sample_rate;
131
+ internal->total_time = (num_frames / rate) * 1000;
132
+ internal->total_time += (num_frames % rate) * 1000 / rate;
133
+ } /* else */
134
+
135
+ return 1; /* we'll handle this data. */
136
+ } /* VORBIS_open */
137
+
138
+
139
+ static void VORBIS_close(Sound_Sample *sample)
140
+ {
141
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
142
+ stb_vorbis *stb = (stb_vorbis *) internal->decoder_private;
143
+ stb_vorbis_close(stb);
144
+ } /* VORBIS_close */
145
+
146
+
147
+ static Uint32 VORBIS_read(Sound_Sample *sample)
148
+ {
149
+ Uint32 retval;
150
+ int rc;
151
+ int err;
152
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
153
+ stb_vorbis *stb = (stb_vorbis *) internal->decoder_private;
154
+ const int channels = (int) sample->actual.channels;
155
+ const int want_samples = (int) (internal->buffer_size / sizeof (float));
156
+
157
+ stb_vorbis_get_error(stb); /* clear any error state */
158
+ rc = stb_vorbis_get_samples_float_interleaved(stb, channels, (float *) internal->buffer, want_samples);
159
+ retval = (Uint32) (rc * channels * sizeof (float)); /* rc == number of sample frames read */
160
+ err = stb_vorbis_get_error(stb);
161
+
162
+ if (retval == 0)
163
+ {
164
+ if (!err)
165
+ sample->flags |= SOUND_SAMPLEFLAG_EOF;
166
+ else
167
+ {
168
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
169
+ /* !!! FIXME: should I set this? __Sound_SetError(vorbis_error_string(err)); */
170
+ } /* else */
171
+ } /* if */
172
+
173
+ else if (retval < internal->buffer_size)
174
+ sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
175
+
176
+ return retval;
177
+ } /* VORBIS_read */
178
+
179
+
180
+ static int VORBIS_rewind(Sound_Sample *sample)
181
+ {
182
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
183
+ stb_vorbis *stb = (stb_vorbis *) internal->decoder_private;
184
+ BAIL_IF_MACRO(!stb_vorbis_seek_start(stb), vorbis_error_string(stb_vorbis_get_error(stb)), 0);
185
+ return 1;
186
+ } /* VORBIS_rewind */
187
+
188
+
189
+ static int VORBIS_seek(Sound_Sample *sample, Uint32 ms)
190
+ {
191
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
192
+ stb_vorbis *stb = (stb_vorbis *) internal->decoder_private;
193
+ const float frames_per_ms = ((float) sample->actual.rate) / 1000.0f;
194
+ const Uint32 frame_offset = (Uint32) (frames_per_ms * ((float) ms));
195
+ const unsigned int sampnum = (unsigned int) frame_offset;
196
+ BAIL_IF_MACRO(!stb_vorbis_seek(stb, sampnum), vorbis_error_string(stb_vorbis_get_error(stb)), 0);
197
+ return 1;
198
+ } /* VORBIS_seek */
199
+
200
+
201
+ static const char *extensions_vorbis[] = { "OGG", NULL };
202
+ const Sound_DecoderFunctions __Sound_DecoderFunctions_VORBIS =
203
+ {
204
+ {
205
+ extensions_vorbis,
206
+ "Ogg Vorbis audio",
207
+ "Ryan C. Gordon <icculus@icculus.org>",
208
+ "https://icculus.org/SDL_sound/"
209
+ },
210
+
211
+ VORBIS_init, /* init() method */
212
+ VORBIS_quit, /* quit() method */
213
+ VORBIS_open, /* open() method */
214
+ VORBIS_close, /* close() method */
215
+ VORBIS_read, /* read() method */
216
+ VORBIS_rewind, /* rewind() method */
217
+ VORBIS_seek /* seek() method */
218
+ };
219
+
220
+ #endif /* SOUND_SUPPORTS_VORBIS */
221
+
222
+ /* end of SDL_sound_vorbis.c ... */
223
+
@@ -0,0 +1,783 @@
1
+ /**
2
+ * SDL_sound; A sound processing toolkit.
3
+ *
4
+ * Please see the file LICENSE.txt in the source's root directory.
5
+ *
6
+ * This file written by Ryan C. Gordon.
7
+ */
8
+
9
+ /*
10
+ * WAV decoder for SDL_sound.
11
+ *
12
+ * This driver handles Microsoft .WAVs, in as many of the thousands of
13
+ * variations as we can.
14
+ */
15
+
16
+ #define __SDL_SOUND_INTERNAL__
17
+ #include "SDL_sound_internal.h"
18
+
19
+ #if SOUND_SUPPORTS_WAV
20
+
21
+ /* Better than SDL_ReadLE16, since you can detect i/o errors... */
22
+ static SDL_INLINE int read_le16(SDL_RWops *rw, Uint16 *ui16)
23
+ {
24
+ int rc = SDL_RWread(rw, ui16, sizeof (Uint16), 1);
25
+ BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
26
+ *ui16 = SDL_SwapLE16(*ui16);
27
+ return 1;
28
+ } /* read_le16 */
29
+
30
+
31
+ /* Better than SDL_ReadLE32, since you can detect i/o errors... */
32
+ static SDL_INLINE int read_le32(SDL_RWops *rw, Uint32 *ui32)
33
+ {
34
+ int rc = SDL_RWread(rw, ui32, sizeof (Uint32), 1);
35
+ BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
36
+ *ui32 = SDL_SwapLE32(*ui32);
37
+ return 1;
38
+ } /* read_le32 */
39
+
40
+ static SDL_INLINE int read_le16s(SDL_RWops *rw, Sint16 *si16)
41
+ {
42
+ return read_le16(rw, (Uint16 *) si16);
43
+ } /* read_le16s */
44
+
45
+ static SDL_INLINE int read_le32s(SDL_RWops *rw, Sint32 *si32)
46
+ {
47
+ return read_le32(rw, (Uint32 *) si32);
48
+ } /* read_le32s */
49
+
50
+
51
+ /* This is just cleaner on the caller's end... */
52
+ static SDL_INLINE int read_uint8(SDL_RWops *rw, Uint8 *ui8)
53
+ {
54
+ int rc = SDL_RWread(rw, ui8, sizeof (Uint8), 1);
55
+ BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
56
+ return 1;
57
+ } /* read_uint8 */
58
+
59
+
60
+ /* Chunk management code... */
61
+
62
+ #define riffID 0x46464952 /* "RIFF", in ascii. */
63
+ #define waveID 0x45564157 /* "WAVE", in ascii. */
64
+ #define factID 0x74636166 /* "fact", in ascii. */
65
+
66
+
67
+ /*****************************************************************************
68
+ * The FORMAT chunk... *
69
+ *****************************************************************************/
70
+
71
+ #define fmtID 0x20746D66 /* "fmt ", in ascii. */
72
+
73
+ #define FMT_NORMAL 0x0001 /* Uncompressed waveform data. */
74
+ #define FMT_ADPCM 0x0002 /* ADPCM compressed waveform data. */
75
+
76
+ typedef struct
77
+ {
78
+ Sint16 iCoef1;
79
+ Sint16 iCoef2;
80
+ } ADPCMCOEFSET;
81
+
82
+ typedef struct
83
+ {
84
+ Uint8 bPredictor;
85
+ Uint16 iDelta;
86
+ Sint16 iSamp1;
87
+ Sint16 iSamp2;
88
+ } ADPCMBLOCKHEADER;
89
+
90
+ typedef struct S_WAV_FMT_T
91
+ {
92
+ Uint32 chunkID;
93
+ Sint32 chunkSize;
94
+ Sint16 wFormatTag;
95
+ Uint16 wChannels;
96
+ Uint32 dwSamplesPerSec;
97
+ Uint32 dwAvgBytesPerSec;
98
+ Uint16 wBlockAlign;
99
+ Uint16 wBitsPerSample;
100
+
101
+ Uint32 next_chunk_offset;
102
+
103
+ Uint32 sample_frame_size;
104
+ Uint32 data_starting_offset;
105
+ Uint32 total_bytes;
106
+
107
+ void (*free)(struct S_WAV_FMT_T *fmt);
108
+ Uint32 (*read_sample)(Sound_Sample *sample);
109
+ int (*rewind_sample)(Sound_Sample *sample);
110
+ int (*seek_sample)(Sound_Sample *sample, Uint32 ms);
111
+
112
+ union
113
+ {
114
+ struct
115
+ {
116
+ Uint16 cbSize;
117
+ Uint16 wSamplesPerBlock;
118
+ Uint16 wNumCoef;
119
+ ADPCMCOEFSET *aCoef;
120
+ ADPCMBLOCKHEADER *blockheaders;
121
+ Uint32 samples_left_in_block;
122
+ int nibble_state;
123
+ Sint8 nibble;
124
+ } adpcm;
125
+
126
+ /* put other format-specific data here... */
127
+ } fmt;
128
+ } fmt_t;
129
+
130
+
131
+ /*
132
+ * Read in a fmt_t from disk. This makes this process safe regardless of
133
+ * the processor's byte order or how the fmt_t structure is packed.
134
+ * Note that the union "fmt" is not read in here; that is handled as
135
+ * needed in the read_fmt_* functions.
136
+ */
137
+ static int read_fmt_chunk(SDL_RWops *rw, fmt_t *fmt)
138
+ {
139
+ /* skip reading the chunk ID, since it was already read at this point... */
140
+ fmt->chunkID = fmtID;
141
+
142
+ BAIL_IF_MACRO(!read_le32s(rw, &fmt->chunkSize), NULL, 0);
143
+ BAIL_IF_MACRO(fmt->chunkSize < 16, "WAV: Invalid chunk size", 0);
144
+ fmt->next_chunk_offset = SDL_RWtell(rw) + fmt->chunkSize;
145
+
146
+ BAIL_IF_MACRO(!read_le16s(rw, &fmt->wFormatTag), NULL, 0);
147
+ BAIL_IF_MACRO(!read_le16(rw, &fmt->wChannels), NULL, 0);
148
+ BAIL_IF_MACRO(!read_le32(rw, &fmt->dwSamplesPerSec), NULL, 0);
149
+ BAIL_IF_MACRO(!read_le32(rw, &fmt->dwAvgBytesPerSec), NULL, 0);
150
+ BAIL_IF_MACRO(!read_le16(rw, &fmt->wBlockAlign), NULL, 0);
151
+ BAIL_IF_MACRO(!read_le16(rw, &fmt->wBitsPerSample), NULL, 0);
152
+
153
+ return 1;
154
+ } /* read_fmt_chunk */
155
+
156
+
157
+
158
+ /*****************************************************************************
159
+ * The DATA chunk... *
160
+ *****************************************************************************/
161
+
162
+ #define dataID 0x61746164 /* "data", in ascii. */
163
+
164
+ typedef struct
165
+ {
166
+ Uint32 chunkID;
167
+ Sint32 chunkSize;
168
+ /* Then, (chunkSize) bytes of waveform data... */
169
+ } data_t;
170
+
171
+
172
+ /*
173
+ * Read in a data_t from disk. This makes this process safe regardless of
174
+ * the processor's byte order or how the fmt_t structure is packed.
175
+ */
176
+ static int read_data_chunk(SDL_RWops *rw, data_t *data)
177
+ {
178
+ /* skip reading the chunk ID, since it was already read at this point... */
179
+ data->chunkID = dataID;
180
+ BAIL_IF_MACRO(!read_le32s(rw, &data->chunkSize), NULL, 0);
181
+ return 1;
182
+ } /* read_data_chunk */
183
+
184
+
185
+
186
+
187
+ /*****************************************************************************
188
+ * this is what we store in our internal->decoder_private field... *
189
+ *****************************************************************************/
190
+
191
+ typedef struct
192
+ {
193
+ fmt_t *fmt;
194
+ Sint32 bytesLeft;
195
+ } wav_t;
196
+
197
+
198
+
199
+
200
+ /*****************************************************************************
201
+ * Normal, uncompressed waveform handler... *
202
+ *****************************************************************************/
203
+
204
+ /*
205
+ * Sound_Decode() lands here for uncompressed WAVs...
206
+ */
207
+ static Uint32 read_sample_fmt_normal(Sound_Sample *sample)
208
+ {
209
+ Uint32 retval;
210
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
211
+ wav_t *w = (wav_t *) internal->decoder_private;
212
+ Uint32 max = (internal->buffer_size < (Uint32) w->bytesLeft) ?
213
+ internal->buffer_size : (Uint32) w->bytesLeft;
214
+
215
+ SDL_assert(max > 0);
216
+
217
+ /*
218
+ * We don't actually do any decoding, so we read the wav data
219
+ * directly into the internal buffer...
220
+ */
221
+ retval = SDL_RWread(internal->rw, internal->buffer, 1, max);
222
+
223
+ w->bytesLeft -= retval;
224
+
225
+ /* Make sure the read went smoothly... */
226
+ if ((retval == 0) || (w->bytesLeft == 0))
227
+ sample->flags |= SOUND_SAMPLEFLAG_EOF;
228
+
229
+ else if (retval == -1)
230
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
231
+
232
+ /* (next call this EAGAIN may turn into an EOF or error.) */
233
+ else if (retval < internal->buffer_size)
234
+ sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
235
+
236
+ return retval;
237
+ } /* read_sample_fmt_normal */
238
+
239
+
240
+ static int seek_sample_fmt_normal(Sound_Sample *sample, Uint32 ms)
241
+ {
242
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
243
+ wav_t *w = (wav_t *) internal->decoder_private;
244
+ fmt_t *fmt = w->fmt;
245
+ int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
246
+ int pos = (int) (fmt->data_starting_offset + offset);
247
+ int rc = SDL_RWseek(internal->rw, pos, SEEK_SET);
248
+ BAIL_IF_MACRO(rc != pos, ERR_IO_ERROR, 0);
249
+ w->bytesLeft = fmt->total_bytes - offset;
250
+ return 1; /* success. */
251
+ } /* seek_sample_fmt_normal */
252
+
253
+
254
+ static int rewind_sample_fmt_normal(Sound_Sample *sample)
255
+ {
256
+ /* no-op. */
257
+ return 1;
258
+ } /* rewind_sample_fmt_normal */
259
+
260
+
261
+ static int read_fmt_normal(SDL_RWops *rw, fmt_t *fmt)
262
+ {
263
+ /* (don't need to read more from the RWops...) */
264
+ fmt->free = NULL;
265
+ fmt->read_sample = read_sample_fmt_normal;
266
+ fmt->rewind_sample = rewind_sample_fmt_normal;
267
+ fmt->seek_sample = seek_sample_fmt_normal;
268
+ return 1;
269
+ } /* read_fmt_normal */
270
+
271
+
272
+
273
+ /*****************************************************************************
274
+ * ADPCM compression handler... *
275
+ *****************************************************************************/
276
+
277
+ #define FIXED_POINT_COEF_BASE 256
278
+ #define FIXED_POINT_ADAPTION_BASE 256
279
+ #define SMALLEST_ADPCM_DELTA 16
280
+
281
+
282
+ static SDL_INLINE int read_adpcm_block_headers(Sound_Sample *sample)
283
+ {
284
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
285
+ SDL_RWops *rw = internal->rw;
286
+ wav_t *w = (wav_t *) internal->decoder_private;
287
+ fmt_t *fmt = w->fmt;
288
+ ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
289
+ int i;
290
+ int max = fmt->wChannels;
291
+
292
+ if (w->bytesLeft < fmt->wBlockAlign)
293
+ {
294
+ sample->flags |= SOUND_SAMPLEFLAG_EOF;
295
+ return 0;
296
+ } /* if */
297
+
298
+ w->bytesLeft -= fmt->wBlockAlign;
299
+
300
+ for (i = 0; i < max; i++)
301
+ BAIL_IF_MACRO(!read_uint8(rw, &headers[i].bPredictor), NULL, 0);
302
+
303
+ for (i = 0; i < max; i++)
304
+ BAIL_IF_MACRO(!read_le16(rw, &headers[i].iDelta), NULL, 0);
305
+
306
+ for (i = 0; i < max; i++)
307
+ BAIL_IF_MACRO(!read_le16s(rw, &headers[i].iSamp1), NULL, 0);
308
+
309
+ for (i = 0; i < max; i++)
310
+ BAIL_IF_MACRO(!read_le16s(rw, &headers[i].iSamp2), NULL, 0);
311
+
312
+ fmt->fmt.adpcm.samples_left_in_block = fmt->fmt.adpcm.wSamplesPerBlock;
313
+ fmt->fmt.adpcm.nibble_state = 0;
314
+ return 1;
315
+ } /* read_adpcm_block_headers */
316
+
317
+
318
+ static SDL_INLINE void do_adpcm_nibble(Uint8 nib,
319
+ ADPCMBLOCKHEADER *header,
320
+ Sint32 lPredSamp)
321
+ {
322
+ static const Sint32 max_audioval = ((1<<(16-1))-1);
323
+ static const Sint32 min_audioval = -(1<<(16-1));
324
+ static const Sint32 AdaptionTable[] =
325
+ {
326
+ 230, 230, 230, 230, 307, 409, 512, 614,
327
+ 768, 614, 512, 409, 307, 230, 230, 230
328
+ };
329
+
330
+ Sint32 lNewSamp;
331
+ Sint32 delta;
332
+
333
+ if (nib & 0x08)
334
+ lNewSamp = lPredSamp + (header->iDelta * (nib - 0x10));
335
+ else
336
+ lNewSamp = lPredSamp + (header->iDelta * nib);
337
+
338
+ /* clamp value... */
339
+ if (lNewSamp < min_audioval)
340
+ lNewSamp = min_audioval;
341
+ else if (lNewSamp > max_audioval)
342
+ lNewSamp = max_audioval;
343
+
344
+ delta = ((Sint32) header->iDelta * AdaptionTable[nib]) /
345
+ FIXED_POINT_ADAPTION_BASE;
346
+
347
+ if (delta < SMALLEST_ADPCM_DELTA)
348
+ delta = SMALLEST_ADPCM_DELTA;
349
+
350
+ header->iDelta = delta;
351
+ header->iSamp2 = header->iSamp1;
352
+ header->iSamp1 = lNewSamp;
353
+ } /* do_adpcm_nibble */
354
+
355
+
356
+ static SDL_INLINE int decode_adpcm_sample_frame(Sound_Sample *sample)
357
+ {
358
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
359
+ wav_t *w = (wav_t *) internal->decoder_private;
360
+ fmt_t *fmt = w->fmt;
361
+ ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
362
+ SDL_RWops *rw = internal->rw;
363
+ int i;
364
+ int max = fmt->wChannels;
365
+ Sint32 delta;
366
+ Uint8 nib = fmt->fmt.adpcm.nibble;
367
+
368
+ for (i = 0; i < max; i++)
369
+ {
370
+ Uint8 byte;
371
+ Sint16 iCoef1 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef1;
372
+ Sint16 iCoef2 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef2;
373
+ Sint32 lPredSamp = ((headers[i].iSamp1 * iCoef1) +
374
+ (headers[i].iSamp2 * iCoef2)) /
375
+ FIXED_POINT_COEF_BASE;
376
+
377
+ if (fmt->fmt.adpcm.nibble_state == 0)
378
+ {
379
+ BAIL_IF_MACRO(!read_uint8(rw, &nib), NULL, 0);
380
+ fmt->fmt.adpcm.nibble_state = 1;
381
+ do_adpcm_nibble(nib >> 4, &headers[i], lPredSamp);
382
+ } /* if */
383
+ else
384
+ {
385
+ fmt->fmt.adpcm.nibble_state = 0;
386
+ do_adpcm_nibble(nib & 0x0F, &headers[i], lPredSamp);
387
+ } /* else */
388
+ } /* for */
389
+
390
+ fmt->fmt.adpcm.nibble = nib;
391
+ return 1;
392
+ } /* decode_adpcm_sample_frame */
393
+
394
+
395
+ static SDL_INLINE void put_adpcm_sample_frame1(void *_buf, fmt_t *fmt)
396
+ {
397
+ Uint16 *buf = (Uint16 *) _buf;
398
+ ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
399
+ int i;
400
+ for (i = 0; i < fmt->wChannels; i++)
401
+ *(buf++) = headers[i].iSamp1;
402
+ } /* put_adpcm_sample_frame1 */
403
+
404
+
405
+ static SDL_INLINE void put_adpcm_sample_frame2(void *_buf, fmt_t *fmt)
406
+ {
407
+ Uint16 *buf = (Uint16 *) _buf;
408
+ ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
409
+ int i;
410
+ for (i = 0; i < fmt->wChannels; i++)
411
+ *(buf++) = headers[i].iSamp2;
412
+ } /* put_adpcm_sample_frame2 */
413
+
414
+
415
+ /*
416
+ * Sound_Decode() lands here for ADPCM-encoded WAVs...
417
+ */
418
+ static Uint32 read_sample_fmt_adpcm(Sound_Sample *sample)
419
+ {
420
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
421
+ wav_t *w = (wav_t *) internal->decoder_private;
422
+ fmt_t *fmt = w->fmt;
423
+ Uint32 bw = 0;
424
+
425
+ while (bw < internal->buffer_size)
426
+ {
427
+ /* write ongoing sample frame before reading more data... */
428
+ switch (fmt->fmt.adpcm.samples_left_in_block)
429
+ {
430
+ case 0: /* need to read a new block... */
431
+ if (!read_adpcm_block_headers(sample))
432
+ {
433
+ if ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0)
434
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
435
+ return bw;
436
+ } /* if */
437
+
438
+ /* only write first sample frame for now. */
439
+ put_adpcm_sample_frame2((Uint8 *) internal->buffer + bw, fmt);
440
+ fmt->fmt.adpcm.samples_left_in_block--;
441
+ bw += fmt->sample_frame_size;
442
+ break;
443
+
444
+ case 1: /* output last sample frame of block... */
445
+ put_adpcm_sample_frame1((Uint8 *) internal->buffer + bw, fmt);
446
+ fmt->fmt.adpcm.samples_left_in_block--;
447
+ bw += fmt->sample_frame_size;
448
+ break;
449
+
450
+ default: /* output latest sample frame and read a new one... */
451
+ put_adpcm_sample_frame1((Uint8 *) internal->buffer + bw, fmt);
452
+ fmt->fmt.adpcm.samples_left_in_block--;
453
+ bw += fmt->sample_frame_size;
454
+
455
+ if (!decode_adpcm_sample_frame(sample))
456
+ {
457
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
458
+ return bw;
459
+ } /* if */
460
+ } /* switch */
461
+ } /* while */
462
+
463
+ return bw;
464
+ } /* read_sample_fmt_adpcm */
465
+
466
+
467
+ /*
468
+ * Sound_FreeSample() lands here for ADPCM-encoded WAVs...
469
+ */
470
+ static void free_fmt_adpcm(fmt_t *fmt)
471
+ {
472
+ if (fmt->fmt.adpcm.aCoef != NULL)
473
+ SDL_free(fmt->fmt.adpcm.aCoef);
474
+
475
+ if (fmt->fmt.adpcm.blockheaders != NULL)
476
+ SDL_free(fmt->fmt.adpcm.blockheaders);
477
+ } /* free_fmt_adpcm */
478
+
479
+
480
+ static int rewind_sample_fmt_adpcm(Sound_Sample *sample)
481
+ {
482
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
483
+ wav_t *w = (wav_t *) internal->decoder_private;
484
+ w->fmt->fmt.adpcm.samples_left_in_block = 0;
485
+ return 1;
486
+ } /* rewind_sample_fmt_adpcm */
487
+
488
+
489
+ static int seek_sample_fmt_adpcm(Sound_Sample *sample, Uint32 ms)
490
+ {
491
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
492
+ wav_t *w = (wav_t *) internal->decoder_private;
493
+ fmt_t *fmt = w->fmt;
494
+ Uint32 origsampsleft = fmt->fmt.adpcm.samples_left_in_block;
495
+ int origpos = SDL_RWtell(internal->rw);
496
+ int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
497
+ int bpb = (fmt->fmt.adpcm.wSamplesPerBlock * fmt->sample_frame_size);
498
+ int skipsize = (offset / bpb) * fmt->wBlockAlign;
499
+ int pos = skipsize + fmt->data_starting_offset;
500
+ int rc = SDL_RWseek(internal->rw, pos, SEEK_SET);
501
+ BAIL_IF_MACRO(rc != pos, ERR_IO_ERROR, 0);
502
+
503
+ /* The offset we need is in this block, so we need to decode to there. */
504
+ skipsize += (offset % bpb);
505
+ rc = (offset % bpb); /* bytes into this block we need to decode */
506
+ if (!read_adpcm_block_headers(sample))
507
+ {
508
+ SDL_RWseek(internal->rw, origpos, SEEK_SET); /* try to make sane. */
509
+ return 0;
510
+ } /* if */
511
+
512
+ /* first sample frame of block is a freebie. :) */
513
+ fmt->fmt.adpcm.samples_left_in_block--;
514
+ rc -= fmt->sample_frame_size;
515
+ while (rc > 0)
516
+ {
517
+ if (!decode_adpcm_sample_frame(sample))
518
+ {
519
+ SDL_RWseek(internal->rw, origpos, SEEK_SET);
520
+ fmt->fmt.adpcm.samples_left_in_block = origsampsleft;
521
+ return 0;
522
+ } /* if */
523
+
524
+ fmt->fmt.adpcm.samples_left_in_block--;
525
+ rc -= fmt->sample_frame_size;
526
+ } /* while */
527
+
528
+ w->bytesLeft = fmt->total_bytes - skipsize;
529
+ return 1; /* success. */
530
+ } /* seek_sample_fmt_adpcm */
531
+
532
+
533
+ /*
534
+ * Read in the adpcm-specific info from disk. This makes this process
535
+ * safe regardless of the processor's byte order or how the fmt_t
536
+ * structure is packed.
537
+ */
538
+ static int read_fmt_adpcm(SDL_RWops *rw, fmt_t *fmt)
539
+ {
540
+ size_t i;
541
+
542
+ SDL_memset(&fmt->fmt.adpcm, '\0', sizeof (fmt->fmt.adpcm));
543
+ fmt->free = free_fmt_adpcm;
544
+ fmt->read_sample = read_sample_fmt_adpcm;
545
+ fmt->rewind_sample = rewind_sample_fmt_adpcm;
546
+ fmt->seek_sample = seek_sample_fmt_adpcm;
547
+
548
+ BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.cbSize), NULL, 0);
549
+ BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wSamplesPerBlock), NULL, 0);
550
+ BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wNumCoef), NULL, 0);
551
+
552
+ /* fmt->free() is always called, so these malloc()s will be cleaned up. */
553
+
554
+ i = sizeof (ADPCMCOEFSET) * fmt->fmt.adpcm.wNumCoef;
555
+ fmt->fmt.adpcm.aCoef = (ADPCMCOEFSET *) SDL_malloc(i);
556
+ BAIL_IF_MACRO(fmt->fmt.adpcm.aCoef == NULL, ERR_OUT_OF_MEMORY, 0);
557
+
558
+ for (i = 0; i < fmt->fmt.adpcm.wNumCoef; i++)
559
+ {
560
+ BAIL_IF_MACRO(!read_le16s(rw, &fmt->fmt.adpcm.aCoef[i].iCoef1), NULL, 0);
561
+ BAIL_IF_MACRO(!read_le16s(rw, &fmt->fmt.adpcm.aCoef[i].iCoef2), NULL, 0);
562
+ } /* for */
563
+
564
+ i = sizeof (ADPCMBLOCKHEADER) * fmt->wChannels;
565
+ fmt->fmt.adpcm.blockheaders = (ADPCMBLOCKHEADER *) SDL_malloc(i);
566
+ BAIL_IF_MACRO(fmt->fmt.adpcm.blockheaders == NULL, ERR_OUT_OF_MEMORY, 0);
567
+
568
+ return 1;
569
+ } /* read_fmt_adpcm */
570
+
571
+
572
+
573
+ /*****************************************************************************
574
+ * Everything else... *
575
+ *****************************************************************************/
576
+
577
+ static int WAV_init(void)
578
+ {
579
+ return 1; /* always succeeds. */
580
+ } /* WAV_init */
581
+
582
+
583
+ static void WAV_quit(void)
584
+ {
585
+ /* it's a no-op. */
586
+ } /* WAV_quit */
587
+
588
+
589
+ static int read_fmt(SDL_RWops *rw, fmt_t *fmt)
590
+ {
591
+ /* if it's in this switch statement, we support the format. */
592
+ switch (fmt->wFormatTag)
593
+ {
594
+ case FMT_NORMAL:
595
+ SNDDBG(("WAV: Appears to be uncompressed audio.\n"));
596
+ return read_fmt_normal(rw, fmt);
597
+
598
+ case FMT_ADPCM:
599
+ SNDDBG(("WAV: Appears to be ADPCM compressed audio.\n"));
600
+ return read_fmt_adpcm(rw, fmt);
601
+
602
+ /* add other types here. */
603
+
604
+ default:
605
+ SNDDBG(("WAV: Format 0x%X is unknown.\n",
606
+ (unsigned int) fmt->wFormatTag));
607
+ BAIL_MACRO("WAV: Unsupported format", 0);
608
+ } /* switch */
609
+
610
+ SDL_assert(0); /* shouldn't hit this point. */
611
+ return 0;
612
+ } /* read_fmt */
613
+
614
+
615
+ /*
616
+ * Locate a specific chunk in the WAVE file by ID...
617
+ */
618
+ static int find_chunk(SDL_RWops *rw, Uint32 id)
619
+ {
620
+ Sint32 siz = 0;
621
+ Uint32 _id = 0;
622
+ Uint32 pos = SDL_RWtell(rw);
623
+
624
+ while (1)
625
+ {
626
+ BAIL_IF_MACRO(!read_le32(rw, &_id), NULL, 0);
627
+ if (_id == id)
628
+ return 1;
629
+
630
+ /* skip ahead and see what next chunk is... */
631
+ BAIL_IF_MACRO(!read_le32s(rw, &siz), NULL, 0);
632
+ SDL_assert(siz >= 0);
633
+ pos += (sizeof (Uint32) * 2) + siz;
634
+ if (siz > 0)
635
+ BAIL_IF_MACRO(SDL_RWseek(rw, pos, SEEK_SET) != pos, NULL, 0);
636
+ } /* while */
637
+
638
+ return 0; /* shouldn't hit this, but just in case... */
639
+ } /* find_chunk */
640
+
641
+
642
+ static int WAV_open_internal(Sound_Sample *sample, const char *ext, fmt_t *fmt)
643
+ {
644
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
645
+ SDL_RWops *rw = internal->rw;
646
+ data_t d;
647
+ wav_t *w;
648
+ Uint32 pos;
649
+
650
+ BAIL_IF_MACRO(SDL_ReadLE32(rw) != riffID, "WAV: Not a RIFF file.", 0);
651
+ SDL_ReadLE32(rw); /* throw the length away; we get this info later. */
652
+ BAIL_IF_MACRO(SDL_ReadLE32(rw) != waveID, "WAV: Not a WAVE file.", 0);
653
+ BAIL_IF_MACRO(!find_chunk(rw, fmtID), "WAV: No format chunk.", 0);
654
+ BAIL_IF_MACRO(!read_fmt_chunk(rw, fmt), "WAV: Can't read format chunk.", 0);
655
+
656
+ /* !!! FIXME: need float32 format stuff, since it's not just wBitsPerSample. */
657
+
658
+ sample->actual.channels = (Uint8) fmt->wChannels;
659
+ sample->actual.rate = fmt->dwSamplesPerSec;
660
+ if (fmt->wBitsPerSample == 4)
661
+ sample->actual.format = AUDIO_S16SYS;
662
+ else if (fmt->wBitsPerSample == 8)
663
+ sample->actual.format = AUDIO_U8;
664
+ else if (fmt->wBitsPerSample == 16)
665
+ sample->actual.format = AUDIO_S16LSB;
666
+ else if (fmt->wBitsPerSample == 32)
667
+ sample->actual.format = AUDIO_S32LSB;
668
+ else
669
+ {
670
+ SNDDBG(("WAV: %d bits per sample!?\n", (int) fmt->wBitsPerSample));
671
+ BAIL_MACRO("WAV: Unsupported sample size.", 0);
672
+ } /* else */
673
+
674
+ BAIL_IF_MACRO(!read_fmt(rw, fmt), NULL, 0);
675
+ SDL_RWseek(rw, fmt->next_chunk_offset, SEEK_SET);
676
+ BAIL_IF_MACRO(!find_chunk(rw, dataID), "WAV: No data chunk.", 0);
677
+ BAIL_IF_MACRO(!read_data_chunk(rw, &d), "WAV: Can't read data chunk.", 0);
678
+
679
+ w = (wav_t *) SDL_malloc(sizeof(wav_t));
680
+ BAIL_IF_MACRO(w == NULL, ERR_OUT_OF_MEMORY, 0);
681
+ w->fmt = fmt;
682
+ fmt->total_bytes = w->bytesLeft = d.chunkSize;
683
+ fmt->data_starting_offset = SDL_RWtell(rw);
684
+ fmt->sample_frame_size = ( ((sample->actual.format & 0xFF) / 8) *
685
+ sample->actual.channels );
686
+ internal->decoder_private = (void *) w;
687
+
688
+ internal->total_time = (fmt->total_bytes / fmt->dwAvgBytesPerSec) * 1000;
689
+ internal->total_time += (fmt->total_bytes % fmt->dwAvgBytesPerSec)
690
+ * 1000 / fmt->dwAvgBytesPerSec;
691
+
692
+ sample->flags = SOUND_SAMPLEFLAG_NONE;
693
+ if (fmt->seek_sample != NULL)
694
+ sample->flags |= SOUND_SAMPLEFLAG_CANSEEK;
695
+
696
+ SNDDBG(("WAV: Accepting data stream.\n"));
697
+ return 1; /* we'll handle this data. */
698
+ } /* WAV_open_internal */
699
+
700
+
701
+ static int WAV_open(Sound_Sample *sample, const char *ext)
702
+ {
703
+ int rc;
704
+
705
+ fmt_t *fmt = (fmt_t *) SDL_calloc(1, sizeof (fmt_t));
706
+ BAIL_IF_MACRO(fmt == NULL, ERR_OUT_OF_MEMORY, 0);
707
+
708
+ rc = WAV_open_internal(sample, ext, fmt);
709
+ if (!rc)
710
+ {
711
+ if (fmt->free != NULL)
712
+ fmt->free(fmt);
713
+ SDL_free(fmt);
714
+ } /* if */
715
+
716
+ return rc;
717
+ } /* WAV_open */
718
+
719
+
720
+ static void WAV_close(Sound_Sample *sample)
721
+ {
722
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
723
+ wav_t *w = (wav_t *) internal->decoder_private;
724
+
725
+ if (w->fmt->free != NULL)
726
+ w->fmt->free(w->fmt);
727
+
728
+ SDL_free(w->fmt);
729
+ SDL_free(w);
730
+ } /* WAV_close */
731
+
732
+
733
+ static Uint32 WAV_read(Sound_Sample *sample)
734
+ {
735
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
736
+ wav_t *w = (wav_t *) internal->decoder_private;
737
+ return w->fmt->read_sample(sample);
738
+ } /* WAV_read */
739
+
740
+
741
+ static int WAV_rewind(Sound_Sample *sample)
742
+ {
743
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
744
+ wav_t *w = (wav_t *) internal->decoder_private;
745
+ fmt_t *fmt = w->fmt;
746
+ int rc = SDL_RWseek(internal->rw, fmt->data_starting_offset, SEEK_SET);
747
+ BAIL_IF_MACRO(rc != fmt->data_starting_offset, ERR_IO_ERROR, 0);
748
+ w->bytesLeft = fmt->total_bytes;
749
+ return fmt->rewind_sample(sample);
750
+ } /* WAV_rewind */
751
+
752
+
753
+ static int WAV_seek(Sound_Sample *sample, Uint32 ms)
754
+ {
755
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
756
+ wav_t *w = (wav_t *) internal->decoder_private;
757
+ return w->fmt->seek_sample(sample, ms);
758
+ } /* WAV_seek */
759
+
760
+
761
+ static const char *extensions_wav[] = { "WAV", NULL };
762
+ const Sound_DecoderFunctions __Sound_DecoderFunctions_WAV =
763
+ {
764
+ {
765
+ extensions_wav,
766
+ "Microsoft WAVE audio format",
767
+ "Ryan C. Gordon <icculus@icculus.org>",
768
+ "https://icculus.org/SDL_sound/"
769
+ },
770
+
771
+ WAV_init, /* init() method */
772
+ WAV_quit, /* quit() method */
773
+ WAV_open, /* open() method */
774
+ WAV_close, /* close() method */
775
+ WAV_read, /* read() method */
776
+ WAV_rewind, /* rewind() method */
777
+ WAV_seek /* seek() method */
778
+ };
779
+
780
+ #endif /* SOUND_SUPPORTS_WAV */
781
+
782
+ /* end of SDL_sound_wav.c ... */
783
+