gosu 0.15.1 → 1.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/COPYING +1 -1
  4. data/dependencies/SDL/include/SDL.h +138 -0
  5. data/dependencies/SDL/include/SDL_assert.h +293 -0
  6. data/dependencies/SDL/include/SDL_atomic.h +295 -0
  7. data/dependencies/SDL/include/SDL_audio.h +859 -0
  8. data/dependencies/SDL/include/SDL_bits.h +121 -0
  9. data/dependencies/SDL/include/SDL_blendmode.h +123 -0
  10. data/dependencies/SDL/include/SDL_clipboard.h +71 -0
  11. data/dependencies/SDL/include/SDL_config.h +55 -0
  12. data/dependencies/SDL/include/SDL_config_android.h +182 -0
  13. data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
  14. data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
  15. data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
  16. data/dependencies/SDL/include/SDL_config_os2.h +188 -0
  17. data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
  18. data/dependencies/SDL/include/SDL_config_psp.h +165 -0
  19. data/dependencies/SDL/include/SDL_config_windows.h +288 -0
  20. data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
  21. data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
  22. data/dependencies/SDL/include/SDL_copying.h +20 -0
  23. data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
  24. data/dependencies/SDL/include/SDL_egl.h +1676 -0
  25. data/dependencies/SDL/include/SDL_endian.h +263 -0
  26. data/dependencies/SDL/include/SDL_error.h +112 -0
  27. data/dependencies/SDL/include/SDL_events.h +827 -0
  28. data/dependencies/SDL/include/SDL_filesystem.h +136 -0
  29. data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
  30. data/dependencies/SDL/include/SDL_gesture.h +87 -0
  31. data/dependencies/SDL/include/SDL_haptic.h +1247 -0
  32. data/dependencies/SDL/include/SDL_hints.h +1578 -0
  33. data/dependencies/SDL/include/SDL_joystick.h +499 -0
  34. data/dependencies/SDL/include/SDL_keyboard.h +217 -0
  35. data/dependencies/SDL/include/SDL_keycode.h +351 -0
  36. data/dependencies/SDL/include/SDL_loadso.h +81 -0
  37. data/dependencies/SDL/include/SDL_locale.h +101 -0
  38. data/dependencies/SDL/include/SDL_log.h +211 -0
  39. data/dependencies/SDL/include/SDL_main.h +180 -0
  40. data/dependencies/SDL/include/SDL_messagebox.h +146 -0
  41. data/dependencies/SDL/include/SDL_metal.h +117 -0
  42. data/dependencies/SDL/include/SDL_misc.h +75 -0
  43. data/dependencies/SDL/include/SDL_mouse.h +302 -0
  44. data/dependencies/SDL/include/SDL_mutex.h +251 -0
  45. data/dependencies/SDL/include/SDL_name.h +33 -0
  46. data/dependencies/SDL/include/SDL_opengl.h +2183 -0
  47. data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
  48. data/dependencies/SDL/include/SDL_opengles.h +39 -0
  49. data/dependencies/SDL/include/SDL_opengles2.h +52 -0
  50. data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
  51. data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
  52. data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
  53. data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
  54. data/dependencies/SDL/include/SDL_pixels.h +479 -0
  55. data/dependencies/SDL/include/SDL_platform.h +198 -0
  56. data/dependencies/SDL/include/SDL_power.h +75 -0
  57. data/dependencies/SDL/include/SDL_quit.h +58 -0
  58. data/dependencies/SDL/include/SDL_rect.h +174 -0
  59. data/dependencies/SDL/include/SDL_render.h +1158 -0
  60. data/dependencies/SDL/include/SDL_revision.h +2 -0
  61. data/dependencies/SDL/include/SDL_rwops.h +283 -0
  62. data/dependencies/SDL/include/SDL_scancode.h +413 -0
  63. data/dependencies/SDL/include/SDL_sensor.h +267 -0
  64. data/dependencies/SDL/include/SDL_shape.h +144 -0
  65. data/dependencies/SDL/include/SDL_stdinc.h +647 -0
  66. data/dependencies/SDL/include/SDL_surface.h +563 -0
  67. data/dependencies/SDL/include/SDL_system.h +325 -0
  68. data/dependencies/SDL/include/SDL_syswm.h +354 -0
  69. data/dependencies/SDL/include/SDL_test.h +69 -0
  70. data/dependencies/SDL/include/SDL_test_assert.h +105 -0
  71. data/dependencies/SDL/include/SDL_test_common.h +218 -0
  72. data/dependencies/SDL/include/SDL_test_compare.h +69 -0
  73. data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
  74. data/dependencies/SDL/include/SDL_test_font.h +81 -0
  75. data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
  76. data/dependencies/SDL/include/SDL_test_harness.h +134 -0
  77. data/dependencies/SDL/include/SDL_test_images.h +78 -0
  78. data/dependencies/SDL/include/SDL_test_log.h +67 -0
  79. data/dependencies/SDL/include/SDL_test_md5.h +129 -0
  80. data/dependencies/SDL/include/SDL_test_memory.h +63 -0
  81. data/dependencies/SDL/include/SDL_test_random.h +115 -0
  82. data/dependencies/SDL/include/SDL_thread.h +366 -0
  83. data/dependencies/SDL/include/SDL_timer.h +115 -0
  84. data/dependencies/SDL/include/SDL_touch.h +102 -0
  85. data/dependencies/SDL/include/SDL_types.h +29 -0
  86. data/dependencies/SDL/include/SDL_version.h +162 -0
  87. data/dependencies/SDL/include/SDL_video.h +1282 -0
  88. data/dependencies/SDL/include/SDL_vulkan.h +276 -0
  89. data/dependencies/SDL/include/begin_code.h +166 -0
  90. data/dependencies/SDL/include/close_code.h +40 -0
  91. data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
  92. data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
  93. data/dependencies/SDL_sound/SDL_sound.c +795 -0
  94. data/dependencies/SDL_sound/SDL_sound.h +725 -0
  95. data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
  96. data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
  97. data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
  98. data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
  99. data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
  100. data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
  101. data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
  102. data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
  103. data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
  104. data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
  105. data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
  106. data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
  107. data/dependencies/SDL_sound/dr_flac.h +5906 -0
  108. data/dependencies/SDL_sound/dr_mp3.h +2832 -0
  109. data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
  110. data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
  111. data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
  112. data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
  113. data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
  114. data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
  115. data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
  116. data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
  117. data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
  118. data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
  119. data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
  120. data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
  121. data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
  122. data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
  123. data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
  124. data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
  125. data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
  126. data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
  127. data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
  128. data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
  129. data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
  130. data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
  131. data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
  132. data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
  133. data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
  134. data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
  135. data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
  136. data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
  137. data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
  138. data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
  139. data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
  140. data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
  141. data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
  142. data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
  143. data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
  144. data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
  145. data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
  146. data/dependencies/al_soft/AL/al.h +655 -0
  147. data/dependencies/al_soft/AL/alc.h +270 -0
  148. data/dependencies/al_soft/AL/alext.h +585 -0
  149. data/dependencies/al_soft/AL/efx-creative.h +3 -0
  150. data/dependencies/al_soft/AL/efx-presets.h +402 -0
  151. data/dependencies/al_soft/AL/efx.h +762 -0
  152. data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
  153. data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
  154. data/{src → dependencies/stb}/stb_image.h +330 -127
  155. data/{src → dependencies/stb}/stb_image_write.h +156 -85
  156. data/{src → dependencies/stb}/stb_truetype.h +192 -69
  157. data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
  158. data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
  159. data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
  160. data/ext/gosu/extconf.rb +53 -39
  161. data/{Gosu → include/Gosu}/Audio.hpp +6 -8
  162. data/include/Gosu/Bitmap.hpp +100 -0
  163. data/{Gosu → include/Gosu}/Buttons.hpp +104 -44
  164. data/{Gosu → include/Gosu}/Color.hpp +0 -0
  165. data/{Gosu → include/Gosu}/Directories.hpp +0 -0
  166. data/{Gosu → include/Gosu}/Font.hpp +1 -1
  167. data/{Gosu → include/Gosu}/Fwd.hpp +0 -5
  168. data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
  169. data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
  170. data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
  171. data/{Gosu → include/Gosu}/IO.hpp +0 -0
  172. data/{Gosu → include/Gosu}/Image.hpp +7 -6
  173. data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
  174. data/{Gosu → include/Gosu}/Input.hpp +39 -51
  175. data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
  176. data/{Gosu → include/Gosu}/Math.hpp +0 -0
  177. data/{Gosu → include/Gosu}/Platform.hpp +0 -0
  178. data/{Gosu → include/Gosu}/Text.hpp +0 -0
  179. data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
  180. data/{Gosu → include/Gosu}/Timing.hpp +0 -0
  181. data/{Gosu → include/Gosu}/Utility.hpp +15 -4
  182. data/{Gosu → include/Gosu}/Version.hpp +3 -3
  183. data/{Gosu → include/Gosu}/Window.hpp +46 -34
  184. data/lib/OpenAL32.dll +0 -0
  185. data/lib/SDL2.dll +0 -0
  186. data/lib/gosu.rb +0 -3
  187. data/lib/gosu/patches.rb +0 -23
  188. data/lib/gosu/preview.rb +1 -3
  189. data/lib/gosu/swig_patches.rb +6 -8
  190. data/lib64/OpenAL32.dll +0 -0
  191. data/lib64/SDL2.dll +0 -0
  192. data/rdoc/gosu.rb +112 -23
  193. data/src/Audio.cpp +50 -224
  194. data/src/AudioFile.hpp +20 -37
  195. data/src/AudioFileAudioToolbox.cpp +237 -0
  196. data/src/AudioFileSDLSound.cpp +147 -0
  197. data/src/AudioImpl.cpp +3 -12
  198. data/src/AudioImpl.hpp +3 -1
  199. data/src/Bitmap.cpp +85 -83
  200. data/src/BitmapIO.cpp +52 -58
  201. data/src/Font.cpp +4 -1
  202. data/src/Graphics.cpp +7 -4
  203. data/src/Image.cpp +13 -16
  204. data/src/Input.cpp +412 -164
  205. data/src/LargeImageData.cpp +2 -1
  206. data/src/MarkupParser.cpp +2 -1
  207. data/src/Resolution.cpp +8 -8
  208. data/src/RubyGosu.cxx +1184 -352
  209. data/src/RubyGosu.h +3 -2
  210. data/src/TexChunk.cpp +1 -1
  211. data/src/Text.cpp +1 -0
  212. data/src/TextBuilder.cpp +3 -1
  213. data/src/Texture.cpp +1 -1
  214. data/src/TrueTypeFont.cpp +2 -1
  215. data/src/TrueTypeFontWin.cpp +3 -3
  216. data/src/Utility.cpp +11 -7
  217. data/src/Window.cpp +90 -62
  218. data/src/WindowUIKit.cpp +21 -9
  219. metadata +195 -46
  220. data/Gosu/AutoLink.hpp +0 -14
  221. data/Gosu/Bitmap.hpp +0 -113
  222. data/lib/gosu/zen.rb +0 -89
  223. data/src/AudioToolboxFile.hpp +0 -210
  224. data/src/MPEGFile.hpp +0 -90
  225. data/src/OggFile.hpp +0 -92
  226. data/src/SndFile.hpp +0 -174
  227. data/src/WinMain.cpp +0 -64
@@ -0,0 +1,352 @@
1
+ /**
2
+ * SDL_sound; An abstract sound format decoding API.
3
+ *
4
+ * Please see the file LICENSE.txt in the source's root directory.
5
+ *
6
+ * This file written by Mattias Engdegård.
7
+ */
8
+
9
+ /*
10
+ * Sun/NeXT .au decoder for SDL_sound.
11
+ * Formats supported: 8 and 16 bit linear PCM, 8 bit µ-law.
12
+ * Files without valid header are assumed to be 8 bit µ-law, 8kHz, mono.
13
+ */
14
+
15
+ #define __SDL_SOUND_INTERNAL__
16
+ #include "SDL_sound_internal.h"
17
+
18
+ #if SOUND_SUPPORTS_AU
19
+
20
+ /* no init/deinit needed */
21
+ static int AU_init(void)
22
+ {
23
+ return 1;
24
+ } /* AU_init */
25
+
26
+ static void AU_quit(void)
27
+ {
28
+ /* no-op. */
29
+ } /* AU_quit */
30
+
31
+ struct au_file_hdr
32
+ {
33
+ Uint32 magic;
34
+ Uint32 hdr_size;
35
+ Uint32 data_size;
36
+ Uint32 encoding;
37
+ Uint32 sample_rate;
38
+ Uint32 channels;
39
+ };
40
+
41
+ #define HDR_SIZE 24
42
+
43
+ enum
44
+ {
45
+ AU_ENC_ULAW_8 = 1, /* 8-bit ISDN µ-law */
46
+ AU_ENC_LINEAR_8 = 2, /* 8-bit linear PCM */
47
+ AU_ENC_LINEAR_16 = 3, /* 16-bit linear PCM */
48
+
49
+ /* the rest are unsupported (I have never seen them in the wild) */
50
+ AU_ENC_LINEAR_24 = 4, /* 24-bit linear PCM */
51
+ AU_ENC_LINEAR_32 = 5, /* 32-bit linear PCM */
52
+ AU_ENC_FLOAT = 6, /* 32-bit IEEE floating point */
53
+ AU_ENC_DOUBLE = 7, /* 64-bit IEEE floating point */
54
+ /* more Sun formats, not supported either */
55
+ AU_ENC_ADPCM_G721 = 23,
56
+ AU_ENC_ADPCM_G722 = 24,
57
+ AU_ENC_ADPCM_G723_3 = 25,
58
+ AU_ENC_ADPCM_G723_5 = 26,
59
+ AU_ENC_ALAW_8 = 27
60
+ };
61
+
62
+ struct audec
63
+ {
64
+ Uint32 total;
65
+ Uint32 remaining;
66
+ Uint32 start_offset;
67
+ int encoding;
68
+ };
69
+
70
+
71
+ /*
72
+ * Read in the AU header from disk. This makes this process safe
73
+ * regardless of the processor's byte order or how the au_file_hdr
74
+ * structure is packed.
75
+ */
76
+ static int read_au_header(SDL_RWops *rw, struct au_file_hdr *hdr)
77
+ {
78
+ if (SDL_RWread(rw, &hdr->magic, sizeof (hdr->magic), 1) != 1)
79
+ return 0;
80
+ hdr->magic = SDL_SwapBE32(hdr->magic);
81
+
82
+ if (SDL_RWread(rw, &hdr->hdr_size, sizeof (hdr->hdr_size), 1) != 1)
83
+ return 0;
84
+ hdr->hdr_size = SDL_SwapBE32(hdr->hdr_size);
85
+
86
+ if (SDL_RWread(rw, &hdr->data_size, sizeof (hdr->data_size), 1) != 1)
87
+ return 0;
88
+ hdr->data_size = SDL_SwapBE32(hdr->data_size);
89
+
90
+ if (SDL_RWread(rw, &hdr->encoding, sizeof (hdr->encoding), 1) != 1)
91
+ return 0;
92
+ hdr->encoding = SDL_SwapBE32(hdr->encoding);
93
+
94
+ if (SDL_RWread(rw, &hdr->sample_rate, sizeof (hdr->sample_rate), 1) != 1)
95
+ return 0;
96
+ hdr->sample_rate = SDL_SwapBE32(hdr->sample_rate);
97
+
98
+ if (SDL_RWread(rw, &hdr->channels, sizeof (hdr->channels), 1) != 1)
99
+ return 0;
100
+ hdr->channels = SDL_SwapBE32(hdr->channels);
101
+
102
+ return 1;
103
+ } /* read_au_header */
104
+
105
+
106
+ #define AU_MAGIC 0x2E736E64 /* ".snd", in ASCII (bigendian number) */
107
+
108
+ static int AU_open(Sound_Sample *sample, const char *ext)
109
+ {
110
+ Sound_SampleInternal *internal = sample->opaque;
111
+ SDL_RWops *rw = internal->rw;
112
+ int skip, hsize, i, bytes_per_second;
113
+ struct au_file_hdr hdr;
114
+ struct audec *dec;
115
+ char c;
116
+
117
+ /* read_au_header() will do byte order swapping. */
118
+ BAIL_IF_MACRO(!read_au_header(rw, &hdr), "AU: bad header", 0);
119
+
120
+ dec = SDL_malloc(sizeof *dec);
121
+ BAIL_IF_MACRO(dec == NULL, ERR_OUT_OF_MEMORY, 0);
122
+ internal->decoder_private = dec;
123
+
124
+ if (hdr.magic == AU_MAGIC)
125
+ {
126
+ /* valid magic */
127
+ dec->encoding = hdr.encoding;
128
+ switch(dec->encoding)
129
+ {
130
+ case AU_ENC_ULAW_8:
131
+ /* Convert 8-bit µ-law to 16-bit linear on the fly. This is
132
+ slightly wasteful if the audio driver must convert them
133
+ back, but µ-law only devices are rare (mostly _old_ Suns) */
134
+ sample->actual.format = AUDIO_S16SYS;
135
+ break;
136
+
137
+ case AU_ENC_LINEAR_8:
138
+ sample->actual.format = AUDIO_S8;
139
+ break;
140
+
141
+ case AU_ENC_LINEAR_16:
142
+ sample->actual.format = AUDIO_S16MSB;
143
+ break;
144
+
145
+ default:
146
+ SDL_free(dec);
147
+ BAIL_MACRO("AU: Unsupported .au encoding", 0);
148
+ } /* switch */
149
+
150
+ sample->actual.rate = hdr.sample_rate;
151
+ sample->actual.channels = hdr.channels;
152
+ dec->remaining = hdr.data_size;
153
+ hsize = hdr.hdr_size;
154
+
155
+ /* skip remaining part of header (input may be unseekable) */
156
+ for (i = HDR_SIZE; i < hsize; i++)
157
+ {
158
+ if (SDL_RWread(rw, &c, 1, 1) != 1)
159
+ {
160
+ SDL_free(dec);
161
+ BAIL_MACRO(ERR_IO_ERROR, 0);
162
+ } /* if */
163
+ } /* for */
164
+ } /* if */
165
+
166
+ else if (SDL_strcasecmp(ext, "au") == 0)
167
+ {
168
+ /*
169
+ * A number of files in the wild have the .au extension but no valid
170
+ * header; these are traditionally assumed to be 8kHz µ-law. Handle
171
+ * them here only if the extension is recognized.
172
+ */
173
+
174
+ SNDDBG(("AU: Invalid header, assuming raw 8kHz µ-law.\n"));
175
+ /* if seeking fails, we lose 24 samples. big deal */
176
+ SDL_RWseek(rw, -HDR_SIZE, SEEK_CUR);
177
+ dec->encoding = AU_ENC_ULAW_8;
178
+ dec->remaining = (Uint32)-1; /* no limit */
179
+ sample->actual.format = AUDIO_S16SYS;
180
+ sample->actual.rate = 8000;
181
+ sample->actual.channels = 1;
182
+ } /* else if */
183
+
184
+ else
185
+ {
186
+ SDL_free(dec);
187
+ BAIL_MACRO("AU: Not an .AU stream.", 0);
188
+ } /* else */
189
+
190
+ bytes_per_second = ( ( dec->encoding == AU_ENC_LINEAR_16 ) ? 2 : 1 )
191
+ * sample->actual.rate * sample->actual.channels ;
192
+ internal->total_time = ((dec->remaining == -1) ? (-1) :
193
+ ( ( dec->remaining / bytes_per_second ) * 1000 ) +
194
+ ( ( dec->remaining % bytes_per_second ) * 1000 /
195
+ bytes_per_second ) );
196
+
197
+ sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
198
+ dec->total = dec->remaining;
199
+ dec->start_offset = SDL_RWtell(rw);
200
+
201
+ SNDDBG(("AU: Accepting data stream.\n"));
202
+ return 1;
203
+ } /* AU_open */
204
+
205
+
206
+ static void AU_close(Sound_Sample *sample)
207
+ {
208
+ Sound_SampleInternal *internal = sample->opaque;
209
+ SDL_free(internal->decoder_private);
210
+ } /* AU_close */
211
+
212
+
213
+ /* table to convert from µ-law encoding to signed 16-bit samples,
214
+ generated by a throwaway perl script */
215
+ static Sint16 ulaw_to_linear[256] = {
216
+ -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
217
+ -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
218
+ -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
219
+ -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
220
+ -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
221
+ -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
222
+ -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
223
+ -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
224
+ -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
225
+ -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
226
+ -876, -844, -812, -780, -748, -716, -684, -652,
227
+ -620, -588, -556, -524, -492, -460, -428, -396,
228
+ -372, -356, -340, -324, -308, -292, -276, -260,
229
+ -244, -228, -212, -196, -180, -164, -148, -132,
230
+ -120, -112, -104, -96, -88, -80, -72, -64,
231
+ -56, -48, -40, -32, -24, -16, -8, 0,
232
+ 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
233
+ 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
234
+ 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
235
+ 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
236
+ 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
237
+ 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
238
+ 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
239
+ 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
240
+ 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
241
+ 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
242
+ 876, 844, 812, 780, 748, 716, 684, 652,
243
+ 620, 588, 556, 524, 492, 460, 428, 396,
244
+ 372, 356, 340, 324, 308, 292, 276, 260,
245
+ 244, 228, 212, 196, 180, 164, 148, 132,
246
+ 120, 112, 104, 96, 88, 80, 72, 64,
247
+ 56, 48, 40, 32, 24, 16, 8, 0
248
+ };
249
+
250
+
251
+ static Uint32 AU_read(Sound_Sample *sample)
252
+ {
253
+ int ret;
254
+ Sound_SampleInternal *internal = sample->opaque;
255
+ struct audec *dec = internal->decoder_private;
256
+ int maxlen;
257
+ Uint8 *buf;
258
+
259
+ maxlen = internal->buffer_size;
260
+ buf = internal->buffer;
261
+ if (dec->encoding == AU_ENC_ULAW_8)
262
+ {
263
+ /* We read µ-law samples into the second half of the buffer, so
264
+ we can expand them to 16-bit samples afterwards */
265
+ maxlen >>= 1;
266
+ buf += maxlen;
267
+ } /* if */
268
+
269
+ if (maxlen > dec->remaining)
270
+ maxlen = dec->remaining;
271
+ ret = SDL_RWread(internal->rw, buf, 1, maxlen);
272
+ if (ret == 0)
273
+ sample->flags |= SOUND_SAMPLEFLAG_EOF;
274
+ else if (ret == -1)
275
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
276
+ else
277
+ {
278
+ dec->remaining -= ret;
279
+ if (ret < maxlen)
280
+ sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
281
+
282
+ if (dec->encoding == AU_ENC_ULAW_8)
283
+ {
284
+ int i;
285
+ Sint16 *dst = internal->buffer;
286
+ for (i = 0; i < ret; i++)
287
+ dst[i] = ulaw_to_linear[buf[i]];
288
+ ret <<= 1; /* return twice as much as read */
289
+ } /* if */
290
+ } /* else */
291
+
292
+ return ret;
293
+ } /* AU_read */
294
+
295
+
296
+ static int AU_rewind(Sound_Sample *sample)
297
+ {
298
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
299
+ struct audec *dec = (struct audec *) internal->decoder_private;
300
+ int rc = SDL_RWseek(internal->rw, dec->start_offset, SEEK_SET);
301
+ BAIL_IF_MACRO(rc != dec->start_offset, ERR_IO_ERROR, 0);
302
+ dec->remaining = dec->total;
303
+ return 1;
304
+ } /* AU_rewind */
305
+
306
+
307
+ static int AU_seek(Sound_Sample *sample, Uint32 ms)
308
+ {
309
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
310
+ struct audec *dec = (struct audec *) internal->decoder_private;
311
+ int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
312
+ int rc;
313
+ int pos;
314
+
315
+ if (dec->encoding == AU_ENC_ULAW_8)
316
+ offset >>= 1; /* halve the byte offset for compression. */
317
+
318
+ pos = (int) (dec->start_offset + offset);
319
+ rc = SDL_RWseek(internal->rw, pos, SEEK_SET);
320
+ BAIL_IF_MACRO(rc != pos, ERR_IO_ERROR, 0);
321
+ dec->remaining = dec->total - offset;
322
+ return 1;
323
+ } /* AU_seek */
324
+
325
+ /*
326
+ * Sometimes the extension ".snd" is used for these files (mostly on the NeXT),
327
+ * and the magic number comes from this. However it may clash with other
328
+ * formats and is somewhat of an anachronism, so only .au is used here.
329
+ */
330
+ static const char *extensions_au[] = { "AU", NULL };
331
+ const Sound_DecoderFunctions __Sound_DecoderFunctions_AU =
332
+ {
333
+ {
334
+ extensions_au,
335
+ "Sun/NeXT audio file format",
336
+ "Mattias Engdegård <f91-men@nada.kth.se>",
337
+ "https://icculus.org/SDL_sound/"
338
+ },
339
+
340
+ AU_init, /* init() method */
341
+ AU_quit, /* quit() method */
342
+ AU_open, /* open() method */
343
+ AU_close, /* close() method */
344
+ AU_read, /* read() method */
345
+ AU_rewind, /* rewind() method */
346
+ AU_seek /* seek() method */
347
+ };
348
+
349
+ #endif /* SOUND_SUPPORTS_AU */
350
+
351
+ /* end of SDL_sound_au.c ... */
352
+
@@ -0,0 +1,747 @@
1
+ /**
2
+ * SDL_sound; An abstract sound format decoding API.
3
+ *
4
+ * Please see the file LICENSE.txt in the source's root directory.
5
+ *
6
+ * This file written by Eric Wing.
7
+ */
8
+
9
+ #define __SDL_SOUND_INTERNAL__
10
+ #include "SDL_sound_internal.h"
11
+
12
+ #if SOUND_SUPPORTS_COREAUDIO
13
+
14
+ #include <stddef.h> /* NULL */
15
+ #include <arpa/inet.h> /* htonl */
16
+ #include <AudioToolbox/AudioToolbox.h>
17
+
18
+ typedef struct CoreAudioFileContainer
19
+ {
20
+ AudioFileID* audioFileID;
21
+ ExtAudioFileRef extAudioFileRef;
22
+ AudioStreamBasicDescription* outputFormat;
23
+ } CoreAudioFileContainer;
24
+
25
+
26
+ static int CoreAudio_init(void)
27
+ {
28
+ return 1; /* always succeeds. */
29
+ } /* CoreAudio_init */
30
+
31
+
32
+ static void CoreAudio_quit(void)
33
+ {
34
+ /* it's a no-op. */
35
+ } /* CoreAudio_quit */
36
+
37
+ /*
38
+ https://developer.apple.com/library/ios/#documentation/MusicAudio/Reference/AudioFileConvertRef/Reference/reference.html
39
+ kAudioFileAIFFType = 'AIFF',
40
+ kAudioFileAIFCType = 'AIFC',
41
+ kAudioFileWAVEType = 'WAVE',
42
+ kAudioFileSoundDesigner2Type = 'Sd2f',
43
+ kAudioFileNextType = 'NeXT',
44
+ kAudioFileMP3Type = 'MPG3',
45
+ kAudioFileMP2Type = 'MPG2',
46
+ kAudioFileMP1Type = 'MPG1',
47
+ kAudioFileAC3Type = 'ac-3',
48
+ kAudioFileAAC_ADTSType = 'adts',
49
+ kAudioFileMPEG4Type = 'mp4f',
50
+ kAudioFileM4AType = 'm4af',
51
+ kAudioFileCAFType = 'caff',
52
+ kAudioFile3GPType = '3gpp',
53
+ kAudioFile3GP2Type = '3gp2',
54
+ kAudioFileAMRType = 'amrf'
55
+ */
56
+ static AudioFileTypeID CoreAudio_GetAudioTypeForExtension(const char* file_extension)
57
+ {
58
+ if( (SDL_strcasecmp(file_extension, "aif") == 0)
59
+ || (SDL_strcasecmp(file_extension, "aiff") == 0)
60
+ || (SDL_strcasecmp(file_extension, "aifc") == 0)
61
+ )
62
+ {
63
+ return kAudioFileAIFCType;
64
+ }
65
+ else if( (SDL_strcasecmp(file_extension, "wav") == 0)
66
+ || (SDL_strcasecmp(file_extension, "wave") == 0)
67
+ )
68
+ {
69
+ return kAudioFileWAVEType;
70
+ }
71
+ else if( (SDL_strcasecmp(file_extension, "mp3") == 0)
72
+ )
73
+ {
74
+ return kAudioFileMP3Type;
75
+ }
76
+ else if( (SDL_strcasecmp(file_extension, "mp4") == 0)
77
+ )
78
+ {
79
+ return kAudioFileMPEG4Type;
80
+ }
81
+ else if( (SDL_strcasecmp(file_extension, "m4a") == 0)
82
+ )
83
+ {
84
+ return kAudioFileM4AType;
85
+ }
86
+ else if( (SDL_strcasecmp(file_extension, "aac") == 0)
87
+ )
88
+ {
89
+ return kAudioFileAAC_ADTSType;
90
+ }
91
+ else if( (SDL_strcasecmp(file_extension, "aac") == 0)
92
+ )
93
+ {
94
+ return kAudioFileAAC_ADTSType;
95
+ }
96
+ else if( (SDL_strcasecmp(file_extension, "caf") == 0)
97
+ || (SDL_strcasecmp(file_extension, "caff") == 0)
98
+ )
99
+ {
100
+ return kAudioFileCAFType;
101
+ }
102
+ else if( (SDL_strcasecmp(file_extension, "Sd2f") == 0)
103
+ || (SDL_strcasecmp(file_extension, "sd2") == 0)
104
+ )
105
+ {
106
+ return kAudioFileSoundDesigner2Type;
107
+ }
108
+ else if( (SDL_strcasecmp(file_extension, "au") == 0)
109
+ || (SDL_strcasecmp(file_extension, "next") == 0)
110
+ )
111
+ {
112
+ return kAudioFileNextType;
113
+ }
114
+ else if( (SDL_strcasecmp(file_extension, "mp2") == 0)
115
+ )
116
+ {
117
+ return kAudioFileMP2Type;
118
+ }
119
+ else if( (SDL_strcasecmp(file_extension, "mp1") == 0)
120
+ )
121
+ {
122
+ return kAudioFileMP1Type;
123
+ }
124
+ else if( (SDL_strcasecmp(file_extension, "ac3") == 0)
125
+ )
126
+ {
127
+ return kAudioFileAC3Type;
128
+ }
129
+ else if( (SDL_strcasecmp(file_extension, "3gpp") == 0)
130
+ )
131
+ {
132
+ return kAudioFile3GPType;
133
+ }
134
+ else if( (SDL_strcasecmp(file_extension, "3gp2") == 0)
135
+ )
136
+ {
137
+ return kAudioFile3GP2Type;
138
+ }
139
+ else if( (SDL_strcasecmp(file_extension, "amrf") == 0)
140
+ || (SDL_strcasecmp(file_extension, "amr") == 0)
141
+ )
142
+ {
143
+ return kAudioFileAMRType;
144
+ }
145
+ else if( (SDL_strcasecmp(file_extension, "ima4") == 0)
146
+ || (SDL_strcasecmp(file_extension, "ima") == 0)
147
+ )
148
+ {
149
+ /* not sure about this one */
150
+ return kAudioFileCAFType;
151
+ }
152
+ else
153
+ {
154
+ return 0;
155
+ }
156
+
157
+ }
158
+
159
+ static const char* CoreAudio_FourCCToString(int32_t error_code)
160
+ {
161
+ static char return_string[16];
162
+ uint32_t big_endian_code = htonl(error_code);
163
+ char* big_endian_str = (char*)&big_endian_code;
164
+ // see if it appears to be a 4-char-code
165
+ if(isprint(big_endian_str[0])
166
+ && isprint(big_endian_str[1])
167
+ && isprint(big_endian_str[2])
168
+ && isprint (big_endian_str[3]))
169
+ {
170
+ return_string[0] = '\'';
171
+ return_string[1] = big_endian_str[0];
172
+ return_string[2] = big_endian_str[1];
173
+ return_string[3] = big_endian_str[2];
174
+ return_string[4] = big_endian_str[3];
175
+ return_string[5] = '\'';
176
+ return_string[6] = '\0';
177
+ }
178
+ else if(error_code > -200000 && error_code < 200000)
179
+ {
180
+ // no, format it as an integer
181
+ snprintf(return_string, 16, "%d", error_code);
182
+ }
183
+ else
184
+ {
185
+ // no, format it as an integer but in hex
186
+ snprintf(return_string, 16, "0x%x", error_code);
187
+ }
188
+ return return_string;
189
+ }
190
+
191
+
192
+
193
+ SInt64 CoreAudio_SizeCallback(void* inClientData)
194
+ {
195
+ SDL_RWops* rw_ops = (SDL_RWops*)inClientData;
196
+ SInt64 current_position = SDL_RWtell(rw_ops);
197
+ SInt64 end_position = SDL_RWseek(rw_ops, 0, SEEK_END);
198
+ SDL_RWseek(rw_ops, current_position, SEEK_SET);
199
+ // fprintf(stderr, "CoreAudio_SizeCallback:%d\n", end_position);
200
+
201
+ return end_position;
202
+ }
203
+
204
+ OSStatus CoreAudio_ReadCallback(
205
+ void* inClientData,
206
+ SInt64 inPosition,
207
+ UInt32 requestCount,
208
+ void* data_buffer,
209
+ UInt32* actualCount
210
+ )
211
+ {
212
+ SDL_RWops* rw_ops = (SDL_RWops*)inClientData;
213
+ SDL_RWseek(rw_ops, inPosition, SEEK_SET);
214
+ size_t bytes_actually_read = SDL_RWread(rw_ops, data_buffer, 1, requestCount);
215
+ // Not sure how to test for a read error with SDL_RWops
216
+ // fprintf(stderr, "CoreAudio_ReadCallback:%d, %d\n", requestCount, bytes_actually_read);
217
+
218
+ *actualCount = bytes_actually_read;
219
+ return noErr;
220
+ }
221
+
222
+
223
+ static int CoreAudio_open(Sound_Sample *sample, const char *ext)
224
+ {
225
+ CoreAudioFileContainer* core_audio_file_container;
226
+ AudioFileID* audio_file_id;
227
+ OSStatus error_result;
228
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
229
+ AudioStreamBasicDescription actual_format;
230
+ AudioStreamBasicDescription output_format;
231
+ Float64 estimated_duration;
232
+ UInt32 format_size;
233
+
234
+
235
+ core_audio_file_container = (CoreAudioFileContainer*)SDL_malloc(sizeof(CoreAudioFileContainer));
236
+ BAIL_IF_MACRO(core_audio_file_container == NULL, ERR_OUT_OF_MEMORY, 0);
237
+
238
+
239
+ audio_file_id = (AudioFileID*)SDL_malloc(sizeof(AudioFileID));
240
+ BAIL_IF_MACRO(audio_file_id == NULL, ERR_OUT_OF_MEMORY, 0);
241
+
242
+ error_result = AudioFileOpenWithCallbacks(
243
+ internal->rw,
244
+ CoreAudio_ReadCallback,
245
+ NULL,
246
+ CoreAudio_SizeCallback,
247
+ NULL,
248
+ CoreAudio_GetAudioTypeForExtension(ext),
249
+ audio_file_id
250
+ );
251
+ if (error_result != noErr)
252
+ {
253
+ AudioFileClose(*audio_file_id);
254
+ SDL_free(audio_file_id);
255
+ SDL_free(core_audio_file_container);
256
+ SNDDBG(("Core Audio: can't grok data. reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
257
+ BAIL_MACRO("Core Audio: Not valid audio data.", 0);
258
+ } /* if */
259
+
260
+ format_size = sizeof(actual_format);
261
+ error_result = AudioFileGetProperty(
262
+ *audio_file_id,
263
+ kAudioFilePropertyDataFormat,
264
+ &format_size,
265
+ &actual_format
266
+ );
267
+ if (error_result != noErr)
268
+ {
269
+ AudioFileClose(*audio_file_id);
270
+ SDL_free(audio_file_id);
271
+ SDL_free(core_audio_file_container);
272
+ SNDDBG(("Core Audio: AudioFileGetProperty failed. reason: [%s]", CoreAudio_FourCCToString(error_result)));
273
+ BAIL_MACRO("Core Audio: Not valid audio data.", 0);
274
+ } /* if */
275
+
276
+ format_size = sizeof(estimated_duration);
277
+ error_result = AudioFileGetProperty(
278
+ *audio_file_id,
279
+ kAudioFilePropertyEstimatedDuration,
280
+ &format_size,
281
+ &estimated_duration
282
+ );
283
+ if (error_result != noErr)
284
+ {
285
+ AudioFileClose(*audio_file_id);
286
+ SDL_free(audio_file_id);
287
+ SDL_free(core_audio_file_container);
288
+ SNDDBG(("Core Audio: AudioFileGetProperty failed. reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
289
+ BAIL_MACRO("Core Audio: Not valid audio data.", 0);
290
+ } /* if */
291
+
292
+
293
+ core_audio_file_container->audioFileID = audio_file_id;
294
+
295
+ internal->decoder_private = core_audio_file_container;
296
+
297
+ sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
298
+ sample->actual.rate = (UInt32) actual_format.mSampleRate;
299
+ sample->actual.channels = (UInt8)actual_format.mChannelsPerFrame;
300
+ internal->total_time = (SInt32)(estimated_duration * 1000.0 + 0.5);
301
+
302
+ #if 0
303
+ /* FIXME: Both Core Audio and SDL 1.3 support float and 32-bit formats */
304
+ if(actual_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
305
+ {
306
+ if(16 == actual_format.mBitsPerChannel)
307
+ {
308
+ if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags)
309
+ {
310
+ sample->actual.format = AUDIO_S16MSB;
311
+ }
312
+ else
313
+ {
314
+ sample->actual.format = AUDIO_U16MSB;
315
+ }
316
+ }
317
+ else if(8 == actual_format.mBitsPerChannel)
318
+ {
319
+ if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags)
320
+ {
321
+ sample->actual.format = AUDIO_S8;
322
+ }
323
+ else
324
+ {
325
+ sample->actual.format = AUDIO_U8;
326
+ }
327
+ }
328
+ else // might be 0 for undefined?
329
+ {
330
+ // This case seems to come up a lot for me. Maybe for file types like .m4a?
331
+ sample->actual.format = AUDIO_S16SYS;
332
+ SNDDBG(("Core Audio: Unsupported actual_format.mBitsPerChannel: [%d].\n", actual_format.mBitsPerChannel));
333
+
334
+ }
335
+ }
336
+ else // little endian
337
+ {
338
+ if(16 == actual_format.mBitsPerChannel)
339
+ {
340
+ if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags)
341
+ {
342
+ sample->actual.format = AUDIO_S16LSB;
343
+ }
344
+ else
345
+ {
346
+ sample->actual.format = AUDIO_U16LSB;
347
+ }
348
+ }
349
+ else if(8 == actual_format.mBitsPerChannel)
350
+ {
351
+ if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags)
352
+ {
353
+ sample->actual.format = AUDIO_S8;
354
+ }
355
+ else
356
+ {
357
+ sample->actual.format = AUDIO_U8;
358
+ }
359
+ }
360
+ else // might be 0 for undefined?
361
+ {
362
+ sample->actual.format = AUDIO_S16SYS;
363
+
364
+ SNDDBG(("Core Audio: Unsupported actual_format.mBitsPerChannel: [%d].\n", actual_format.mBitsPerChannel));
365
+ }
366
+
367
+ }
368
+ #else
369
+
370
+
371
+
372
+ /*
373
+ * I want to use Core Audio to do conversion and decoding for performance reasons.
374
+ * This is particularly important on mobile devices like iOS.
375
+ * Taking from the Ogg Vorbis decode, I pretend the "actual" format is the same
376
+ * as the desired format.
377
+ */
378
+ sample->actual.format = (sample->desired.format == 0) ?
379
+ AUDIO_S16SYS : sample->desired.format;
380
+ #endif
381
+
382
+
383
+ SNDDBG(("CoreAudio: channels == (%d).\n", sample->actual.channels));
384
+ SNDDBG(("CoreAudio: sampling rate == (%d).\n",sample->actual.rate));
385
+ SNDDBG(("CoreAudio: total seconds of sample == (%d).\n", internal->total_time));
386
+ SNDDBG(("CoreAudio: sample->actual.format == (%d).\n", sample->actual.format));
387
+
388
+
389
+
390
+ error_result = ExtAudioFileWrapAudioFileID(*audio_file_id,
391
+ false, // set to false for read-only
392
+ &core_audio_file_container->extAudioFileRef
393
+ );
394
+ if(error_result != noErr)
395
+ {
396
+ AudioFileClose(*audio_file_id);
397
+ SDL_free(audio_file_id);
398
+ SDL_free(core_audio_file_container);
399
+ SNDDBG(("Core Audio: can't wrap data. reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
400
+ BAIL_MACRO("Core Audio: Failed to wrap data.", 0);
401
+ } /* if */
402
+
403
+
404
+ /* The output format must be linear PCM because that's the only type OpenAL knows how to deal with.
405
+ * Set the client format to 16 bit signed integer (native-endian) data because that is the most
406
+ * optimal format on iPhone/iPod Touch hardware.
407
+ * Maintain the channel count and sample rate of the original source format.
408
+ */
409
+ output_format.mSampleRate = actual_format.mSampleRate; // preserve the original sample rate
410
+ output_format.mChannelsPerFrame = actual_format.mChannelsPerFrame; // preserve the number of channels
411
+ output_format.mFormatID = kAudioFormatLinearPCM; // We want linear PCM data
412
+ output_format.mFramesPerPacket = 1; // We know for linear PCM, the definition is 1 frame per packet
413
+
414
+ if(sample->desired.format == 0)
415
+ {
416
+ // do AUDIO_S16SYS
417
+ output_format.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; // I seem to read failures problems without kAudioFormatFlagIsPacked. From a mailing list post, this seems to be a Core Audio bug.
418
+ output_format.mBitsPerChannel = 16; // We know we want 16-bit
419
+ }
420
+ else
421
+ {
422
+ output_format.mFormatFlags = 0; // clear flags
423
+ output_format.mFormatFlags |= kAudioFormatFlagIsPacked; // I seem to read failures problems without kAudioFormatFlagIsPacked. From a mailing list post, this seems to be a Core Audio bug.
424
+ // Mask against bitsize
425
+ if(0xFF & sample->desired.format)
426
+ {
427
+ output_format.mBitsPerChannel = 16; /* 16-bit */
428
+ }
429
+ else
430
+ {
431
+ output_format.mBitsPerChannel = 8; /* 8-bit */
432
+ }
433
+
434
+ // Mask for signed/unsigned
435
+ if((1<<15) & sample->desired.format)
436
+ {
437
+ output_format.mFormatFlags = output_format.mFormatFlags | kAudioFormatFlagIsSignedInteger;
438
+
439
+ }
440
+ else
441
+ {
442
+ // no flag set for unsigned
443
+ }
444
+ // Mask for big/little endian
445
+ if((1<<12) & sample->desired.format)
446
+ {
447
+ output_format.mFormatFlags = output_format.mFormatFlags | kAudioFormatFlagIsBigEndian;
448
+ }
449
+ else
450
+ {
451
+ // no flag set for little endian
452
+ }
453
+ }
454
+
455
+ output_format.mBytesPerPacket = output_format.mBitsPerChannel/8 * output_format.mChannelsPerFrame; // e.g. 16-bits/8 * channels => so 2-bytes per channel per frame
456
+ output_format.mBytesPerFrame = output_format.mBitsPerChannel/8 * output_format.mChannelsPerFrame; // For PCM, since 1 frame is 1 packet, it is the same as mBytesPerPacket
457
+
458
+
459
+ /*
460
+ output_format.mSampleRate = actual_format.mSampleRate; // preserve the original sample rate
461
+ output_format.mChannelsPerFrame = actual_format.mChannelsPerFrame; // preserve the number of channels
462
+ output_format.mFormatID = kAudioFormatLinearPCM; // We want linear PCM data
463
+ // output_format.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
464
+ output_format.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger;
465
+ output_format.mFramesPerPacket = 1; // We know for linear PCM, the definition is 1 frame per packet
466
+ output_format.mBitsPerChannel = 16; // We know we want 16-bit
467
+ output_format.mBytesPerPacket = 2 * output_format.mChannelsPerFrame; // We know we are using 16-bit, so 2-bytes per channel per frame
468
+ output_format.mBytesPerFrame = 2 * output_format.mChannelsPerFrame; // For PCM, since 1 frame is 1 packet, it is the same as mBytesPerPacket
469
+ */
470
+ SNDDBG(("output_format: mSampleRate: %lf\n", output_format.mSampleRate));
471
+ SNDDBG(("output_format: mChannelsPerFrame: %d\n", output_format.mChannelsPerFrame));
472
+ SNDDBG(("output_format: mFormatID: %d\n", output_format.mFormatID));
473
+ SNDDBG(("output_format: mFormatFlags: %d\n", output_format.mFormatFlags));
474
+ SNDDBG(("output_format: mFramesPerPacket: %d\n", output_format.mFramesPerPacket));
475
+ SNDDBG(("output_format: mBitsPerChannel: %d\n", output_format.mBitsPerChannel));
476
+ SNDDBG(("output_format: mBytesPerPacket: %d\n", output_format.mBytesPerPacket));
477
+ SNDDBG(("output_format: mBytesPerFrame: %d\n", output_format.mBytesPerFrame));
478
+
479
+
480
+ /* Set the desired client (output) data format */
481
+ error_result = ExtAudioFileSetProperty(core_audio_file_container->extAudioFileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(output_format), &output_format);
482
+ if(noErr != error_result)
483
+ {
484
+ ExtAudioFileDispose(core_audio_file_container->extAudioFileRef);
485
+ AudioFileClose(*audio_file_id);
486
+ SDL_free(audio_file_id);
487
+ SDL_free(core_audio_file_container);
488
+ SNDDBG(("Core Audio: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) failed, reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
489
+ BAIL_MACRO("Core Audio: Not valid audio data.", 0);
490
+ }
491
+
492
+
493
+ core_audio_file_container->outputFormat = (AudioStreamBasicDescription*)SDL_malloc(sizeof(AudioStreamBasicDescription));
494
+ BAIL_IF_MACRO(core_audio_file_container->outputFormat == NULL, ERR_OUT_OF_MEMORY, 0);
495
+
496
+
497
+
498
+ /* Copy the output format to the audio_description that was passed in so the
499
+ * info will be returned to the user.
500
+ */
501
+ SDL_memcpy(core_audio_file_container->outputFormat, &output_format, sizeof(AudioStreamBasicDescription));
502
+
503
+
504
+
505
+ return 1;
506
+ } /* CoreAudio_open */
507
+
508
+
509
+ static void CoreAudio_close(Sound_Sample *sample)
510
+ {
511
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
512
+ CoreAudioFileContainer* core_audio_file_container = (CoreAudioFileContainer *) internal->decoder_private;
513
+
514
+ SDL_free(core_audio_file_container->outputFormat);
515
+ ExtAudioFileDispose(core_audio_file_container->extAudioFileRef);
516
+ AudioFileClose(*core_audio_file_container->audioFileID);
517
+ SDL_free(core_audio_file_container->audioFileID);
518
+ SDL_free(core_audio_file_container);
519
+ } /* CoreAudio_close */
520
+
521
+
522
+ static Uint32 CoreAudio_read(Sound_Sample *sample)
523
+ {
524
+ OSStatus error_result = noErr;
525
+ /* Documentation/example shows SInt64, but is problematic for big endian
526
+ * on 32-bit cast for ExtAudioFileRead() because it takes the upper
527
+ * bits which turn to 0.
528
+ */
529
+ UInt32 buffer_size_in_frames = 0;
530
+ UInt32 buffer_size_in_frames_remaining = 0;
531
+ UInt32 total_frames_read = 0;
532
+ UInt32 data_buffer_size = 0;
533
+ UInt32 bytes_remaining = 0;
534
+ size_t total_bytes_read = 0;
535
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
536
+ CoreAudioFileContainer* core_audio_file_container = (CoreAudioFileContainer *) internal->decoder_private;
537
+ UInt32 max_buffer_size = internal->buffer_size;
538
+
539
+ // printf("internal->buffer_size=%d, internal->buffer=0x%x, sample->buffer_size=%d\n", internal->buffer_size, internal->buffer, sample->buffer_size);
540
+ // printf("internal->max_buffer_size=%d\n", max_buffer_size);
541
+
542
+ /* Compute how many frames will fit into our max buffer size */
543
+ /* Warning: If this is not evenly divisible, the buffer will not be completely filled which violates the SDL_sound assumption. */
544
+ buffer_size_in_frames = max_buffer_size / core_audio_file_container->outputFormat->mBytesPerFrame;
545
+ // printf("buffer_size_in_frames=%ld, internal->buffer_size=%d, internal->buffer=0x%x outputFormat->mBytesPerFrame=%d, sample->buffer_size=%d\n", buffer_size_in_frames, internal->buffer_size, internal->buffer, core_audio_file_container->outputFormat->mBytesPerFrame, sample->buffer_size);
546
+
547
+
548
+ // void* temp_buffer = SDL_malloc(max_buffer_size);
549
+
550
+ AudioBufferList audio_buffer_list;
551
+ audio_buffer_list.mNumberBuffers = 1;
552
+ audio_buffer_list.mBuffers[0].mDataByteSize = max_buffer_size;
553
+ audio_buffer_list.mBuffers[0].mNumberChannels = core_audio_file_container->outputFormat->mChannelsPerFrame;
554
+ audio_buffer_list.mBuffers[0].mData = internal->buffer;
555
+
556
+
557
+ bytes_remaining = max_buffer_size;
558
+ buffer_size_in_frames_remaining = buffer_size_in_frames;
559
+
560
+ // oops. Due to the kAudioFormatFlagIsPacked bug,
561
+ // I was misled to believe that Core Audio
562
+ // was not always filling my entire requested buffer.
563
+ // So this while-loop might be unnecessary.
564
+ // However, I have not exhaustively tested all formats,
565
+ // so maybe it is possible this loop is useful.
566
+ // It might also handle the not-evenly disvisible case above.
567
+ while(buffer_size_in_frames_remaining > 0 && !(sample->flags & SOUND_SAMPLEFLAG_EOF))
568
+ {
569
+
570
+ data_buffer_size = (UInt32)(buffer_size_in_frames * core_audio_file_container->outputFormat->mBytesPerFrame);
571
+ // printf("data_buffer_size=%d\n", data_buffer_size);
572
+
573
+ buffer_size_in_frames = buffer_size_in_frames_remaining;
574
+
575
+ // printf("reading buffer_size_in_frames=%"PRId64"\n", buffer_size_in_frames);
576
+
577
+
578
+ audio_buffer_list.mBuffers[0].mDataByteSize = bytes_remaining;
579
+ audio_buffer_list.mBuffers[0].mData = &(((UInt8*)internal->buffer)[total_bytes_read]);
580
+
581
+
582
+ /* Read the data into an AudioBufferList */
583
+ error_result = ExtAudioFileRead(core_audio_file_container->extAudioFileRef, &buffer_size_in_frames, &audio_buffer_list);
584
+ if(error_result == noErr)
585
+ {
586
+
587
+
588
+ /* Success */
589
+
590
+ total_frames_read += buffer_size_in_frames;
591
+ buffer_size_in_frames_remaining = buffer_size_in_frames_remaining - buffer_size_in_frames;
592
+
593
+ // printf("read buffer_size_in_frames=%"PRId64", buffer_size_in_frames_remaining=%"PRId64"\n", buffer_size_in_frames, buffer_size_in_frames_remaining);
594
+
595
+ /* ExtAudioFileRead returns the number of frames actually read. Need to convert back to bytes. */
596
+ data_buffer_size = (UInt32)(buffer_size_in_frames * core_audio_file_container->outputFormat->mBytesPerFrame);
597
+ // printf("data_buffer_size=%d\n", data_buffer_size);
598
+
599
+ total_bytes_read += data_buffer_size;
600
+ bytes_remaining = bytes_remaining - data_buffer_size;
601
+
602
+ /* Note: 0 == buffer_size_in_frames is a legitimate value meaning we are EOF. */
603
+ if(0 == buffer_size_in_frames)
604
+ {
605
+ sample->flags |= SOUND_SAMPLEFLAG_EOF;
606
+ }
607
+
608
+ }
609
+ else
610
+ {
611
+ SNDDBG(("Core Audio: ExtAudioFileReadfailed, reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
612
+
613
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
614
+ break;
615
+
616
+ }
617
+ }
618
+
619
+ if( (!(sample->flags & SOUND_SAMPLEFLAG_EOF)) && (total_bytes_read < max_buffer_size))
620
+ {
621
+ SNDDBG(("Core Audio: ExtAudioFileReadfailed SOUND_SAMPLEFLAG_EAGAIN, reason: [total_bytes_read < max_buffer_size], %d, %d.\n", total_bytes_read , max_buffer_size));
622
+
623
+ /* Don't know what to do here. */
624
+ sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
625
+ }
626
+ return total_bytes_read;
627
+ } /* CoreAudio_read */
628
+
629
+
630
+ static int CoreAudio_rewind(Sound_Sample *sample)
631
+ {
632
+ OSStatus error_result = noErr;
633
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
634
+ CoreAudioFileContainer* core_audio_file_container = (CoreAudioFileContainer *) internal->decoder_private;
635
+
636
+ error_result = ExtAudioFileSeek(core_audio_file_container->extAudioFileRef, 0);
637
+ if(error_result != noErr)
638
+ {
639
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
640
+ }
641
+ return 1;
642
+ } /* CoreAudio_rewind */
643
+
644
+ /* Note: I found this tech note:
645
+ https://developer.apple.com/library/mac/#qa/qa2009/qa1678.html
646
+ I don't know if this applies to us. So far, I haven't noticed the problem,
647
+ so I haven't applied any of the techniques.
648
+ */
649
+ static int CoreAudio_seek(Sound_Sample *sample, Uint32 ms)
650
+ {
651
+ OSStatus error_result = noErr;
652
+ Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
653
+ CoreAudioFileContainer* core_audio_file_container = (CoreAudioFileContainer *) internal->decoder_private;
654
+ SInt64 frame_offset = 0;
655
+ AudioStreamBasicDescription actual_format;
656
+ UInt32 format_size;
657
+
658
+
659
+ /* I'm confused. The Apple documentation says this:
660
+ "Seek position is specified in the sample rate and frame count of the file’s audio data format
661
+ — not your application’s audio data format."
662
+ My interpretation is that I want to get the "actual format of the file and compute the frame offset.
663
+ But when I try that, seeking goes to the wrong place.
664
+ When I use outputFormat, things seem to work correctly.
665
+ I must be misinterpreting the documentation or doing something wrong.
666
+ */
667
+ #if 0 /* not working */
668
+ format_size = sizeof(AudioStreamBasicDescription);
669
+ error_result = AudioFileGetProperty(
670
+ *core_audio_file_container->audioFileID,
671
+ kAudioFilePropertyDataFormat,
672
+ &format_size,
673
+ &actual_format
674
+ );
675
+ if(error_result != noErr)
676
+ {
677
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
678
+ BAIL_MACRO("Core Audio: Could not GetProperty for kAudioFilePropertyDataFormat.", 0);
679
+ } /* if */
680
+
681
+ // packetIndex = (pos * sampleRate) / framesPerPacket
682
+ // frame_offset = (SInt64)((ms/1000.0 * actual_format.mSampleRate) / actual_format.mFramesPerPacket);
683
+ #else /* seems to work, but I'm confused */
684
+ // packetIndex = (pos * sampleRate) / framesPerPacket
685
+ frame_offset = (SInt64)((ms/1000.0 * core_audio_file_container->outputFormat->mSampleRate) / core_audio_file_container->outputFormat->mFramesPerPacket);
686
+ #endif
687
+
688
+ // computed against actual format and not the client format
689
+ error_result = ExtAudioFileSeek(core_audio_file_container->extAudioFileRef, frame_offset);
690
+ if(error_result != noErr)
691
+ {
692
+ sample->flags |= SOUND_SAMPLEFLAG_ERROR;
693
+ }
694
+
695
+ return 1;
696
+ } /* CoreAudio_seek */
697
+
698
+
699
+ static const char *extensions_coreaudio[] =
700
+ {
701
+ "aif",
702
+ "aiff",
703
+ "aifc",
704
+ "wav",
705
+ "wave",
706
+ "mp3",
707
+ "mp4",
708
+ "m4a",
709
+ "aac",
710
+ "caf",
711
+ "Sd2f",
712
+ "Sd2",
713
+ "au",
714
+ "next",
715
+ "mp2",
716
+ "mp1",
717
+ "ac3",
718
+ "3gpp",
719
+ "3gp2",
720
+ "amrf",
721
+ "amr",
722
+ "ima4",
723
+ "ima",
724
+ NULL
725
+ };
726
+ const Sound_DecoderFunctions __Sound_DecoderFunctions_CoreAudio =
727
+ {
728
+ {
729
+ extensions_coreaudio,
730
+ "Decode audio through Core Audio through",
731
+ "Eric Wing <ewing . public @ playcontrol.net>",
732
+ "https://playcontrol.net"
733
+ },
734
+
735
+ CoreAudio_init, /* init() method */
736
+ CoreAudio_quit, /* quit() method */
737
+ CoreAudio_open, /* open() method */
738
+ CoreAudio_close, /* close() method */
739
+ CoreAudio_read, /* read() method */
740
+ CoreAudio_rewind, /* rewind() method */
741
+ CoreAudio_seek /* seek() method */
742
+ };
743
+
744
+ #endif /* SOUND_SUPPORTS_COREAUDIO */
745
+
746
+ /* end of SDL_sound_coreaudio.c ... */
747
+