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.
- checksums.yaml +4 -4
- data/dependencies/SDL/include/SDL.h +138 -0
- data/dependencies/SDL/include/SDL_assert.h +293 -0
- data/dependencies/SDL/include/SDL_atomic.h +295 -0
- data/dependencies/SDL/include/SDL_audio.h +859 -0
- data/dependencies/SDL/include/SDL_bits.h +121 -0
- data/dependencies/SDL/include/SDL_blendmode.h +123 -0
- data/dependencies/SDL/include/SDL_clipboard.h +71 -0
- data/dependencies/SDL/include/SDL_config.h +55 -0
- data/dependencies/SDL/include/SDL_config_android.h +182 -0
- data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
- data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
- data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
- data/dependencies/SDL/include/SDL_config_os2.h +188 -0
- data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
- data/dependencies/SDL/include/SDL_config_psp.h +165 -0
- data/dependencies/SDL/include/SDL_config_windows.h +288 -0
- data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
- data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
- data/dependencies/SDL/include/SDL_copying.h +20 -0
- data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
- data/dependencies/SDL/include/SDL_egl.h +1676 -0
- data/dependencies/SDL/include/SDL_endian.h +263 -0
- data/dependencies/SDL/include/SDL_error.h +112 -0
- data/dependencies/SDL/include/SDL_events.h +827 -0
- data/dependencies/SDL/include/SDL_filesystem.h +136 -0
- data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
- data/dependencies/SDL/include/SDL_gesture.h +87 -0
- data/dependencies/SDL/include/SDL_haptic.h +1247 -0
- data/dependencies/SDL/include/SDL_hints.h +1578 -0
- data/dependencies/SDL/include/SDL_joystick.h +499 -0
- data/dependencies/SDL/include/SDL_keyboard.h +217 -0
- data/dependencies/SDL/include/SDL_keycode.h +351 -0
- data/dependencies/SDL/include/SDL_loadso.h +81 -0
- data/dependencies/SDL/include/SDL_locale.h +101 -0
- data/dependencies/SDL/include/SDL_log.h +211 -0
- data/dependencies/SDL/include/SDL_main.h +180 -0
- data/dependencies/SDL/include/SDL_messagebox.h +146 -0
- data/dependencies/SDL/include/SDL_metal.h +117 -0
- data/dependencies/SDL/include/SDL_misc.h +75 -0
- data/dependencies/SDL/include/SDL_mouse.h +302 -0
- data/dependencies/SDL/include/SDL_mutex.h +251 -0
- data/dependencies/SDL/include/SDL_name.h +33 -0
- data/dependencies/SDL/include/SDL_opengl.h +2183 -0
- data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
- data/dependencies/SDL/include/SDL_opengles.h +39 -0
- data/dependencies/SDL/include/SDL_opengles2.h +52 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
- data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
- data/dependencies/SDL/include/SDL_pixels.h +479 -0
- data/dependencies/SDL/include/SDL_platform.h +198 -0
- data/dependencies/SDL/include/SDL_power.h +75 -0
- data/dependencies/SDL/include/SDL_quit.h +58 -0
- data/dependencies/SDL/include/SDL_rect.h +174 -0
- data/dependencies/SDL/include/SDL_render.h +1158 -0
- data/dependencies/SDL/include/SDL_revision.h +2 -0
- data/dependencies/SDL/include/SDL_rwops.h +283 -0
- data/dependencies/SDL/include/SDL_scancode.h +413 -0
- data/dependencies/SDL/include/SDL_sensor.h +267 -0
- data/dependencies/SDL/include/SDL_shape.h +144 -0
- data/dependencies/SDL/include/SDL_stdinc.h +647 -0
- data/dependencies/SDL/include/SDL_surface.h +563 -0
- data/dependencies/SDL/include/SDL_system.h +325 -0
- data/dependencies/SDL/include/SDL_syswm.h +354 -0
- data/dependencies/SDL/include/SDL_test.h +69 -0
- data/dependencies/SDL/include/SDL_test_assert.h +105 -0
- data/dependencies/SDL/include/SDL_test_common.h +218 -0
- data/dependencies/SDL/include/SDL_test_compare.h +69 -0
- data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
- data/dependencies/SDL/include/SDL_test_font.h +81 -0
- data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
- data/dependencies/SDL/include/SDL_test_harness.h +134 -0
- data/dependencies/SDL/include/SDL_test_images.h +78 -0
- data/dependencies/SDL/include/SDL_test_log.h +67 -0
- data/dependencies/SDL/include/SDL_test_md5.h +129 -0
- data/dependencies/SDL/include/SDL_test_memory.h +63 -0
- data/dependencies/SDL/include/SDL_test_random.h +115 -0
- data/dependencies/SDL/include/SDL_thread.h +366 -0
- data/dependencies/SDL/include/SDL_timer.h +115 -0
- data/dependencies/SDL/include/SDL_touch.h +102 -0
- data/dependencies/SDL/include/SDL_types.h +29 -0
- data/dependencies/SDL/include/SDL_version.h +162 -0
- data/dependencies/SDL/include/SDL_video.h +1282 -0
- data/dependencies/SDL/include/SDL_vulkan.h +276 -0
- data/dependencies/SDL/include/begin_code.h +166 -0
- data/dependencies/SDL/include/close_code.h +40 -0
- data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
- data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
- data/dependencies/SDL_sound/SDL_sound.c +795 -0
- data/dependencies/SDL_sound/SDL_sound.h +725 -0
- data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
- data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
- data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
- data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
- data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
- data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
- data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
- data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
- data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
- data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
- data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
- data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
- data/dependencies/SDL_sound/dr_flac.h +5906 -0
- data/dependencies/SDL_sound/dr_mp3.h +2832 -0
- data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
- data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
- data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
- data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
- data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
- data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
- data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
- data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
- data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
- data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
- data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
- data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
- data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
- data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
- data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
- data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
- data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
- data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
- data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
- data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
- data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
- data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
- data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
- data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
- data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
- data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
- data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
- data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
- data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
- data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
- data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
- data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
- data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
- data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
- data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
- data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
- data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
- data/dependencies/al_soft/AL/al.h +655 -0
- data/dependencies/al_soft/AL/alc.h +270 -0
- data/dependencies/al_soft/AL/alext.h +585 -0
- data/dependencies/al_soft/AL/efx-creative.h +3 -0
- data/dependencies/al_soft/AL/efx-presets.h +402 -0
- data/dependencies/al_soft/AL/efx.h +762 -0
- data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
- data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
- data/{src → dependencies/stb}/stb_image.h +330 -127
- data/{src → dependencies/stb}/stb_image_write.h +156 -85
- data/{src → dependencies/stb}/stb_truetype.h +192 -69
- data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
- data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
- data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
- data/ext/gosu/extconf.rb +56 -22
- data/{Gosu → include/Gosu}/Audio.hpp +6 -8
- data/{Gosu → include/Gosu}/AutoLink.hpp +0 -0
- data/include/Gosu/Bitmap.hpp +100 -0
- data/{Gosu → include/Gosu}/Buttons.hpp +94 -35
- data/{Gosu → include/Gosu}/Channel.h +0 -0
- data/{Gosu → include/Gosu}/Color.h +0 -0
- data/{Gosu → include/Gosu}/Color.hpp +0 -0
- data/{Gosu → include/Gosu}/Directories.hpp +0 -0
- data/{Gosu → include/Gosu}/Font.h +0 -0
- data/{Gosu → include/Gosu}/Font.hpp +0 -0
- data/{Gosu → include/Gosu}/Fwd.hpp +0 -0
- data/{Gosu → include/Gosu}/Gosu.h +3 -0
- data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
- data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
- data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
- data/{Gosu → include/Gosu}/IO.hpp +0 -0
- data/{Gosu → include/Gosu}/Image.h +0 -0
- data/{Gosu → include/Gosu}/Image.hpp +7 -6
- data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
- data/{Gosu → include/Gosu}/Input.hpp +30 -15
- data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
- data/{Gosu → include/Gosu}/Math.hpp +0 -0
- data/{Gosu → include/Gosu}/Platform.hpp +0 -0
- data/{Gosu → include/Gosu}/Sample.h +0 -0
- data/{Gosu → include/Gosu}/Song.h +0 -0
- data/{Gosu → include/Gosu}/Text.hpp +0 -0
- data/{Gosu → include/Gosu}/TextInput.h +0 -0
- data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
- data/{Gosu → include/Gosu}/Timing.hpp +0 -0
- data/{Gosu → include/Gosu}/Utility.hpp +1 -1
- data/{Gosu → include/Gosu}/Version.hpp +0 -0
- data/{Gosu → include/Gosu}/Window.h +2 -0
- data/{Gosu → include/Gosu}/Window.hpp +21 -13
- data/lib/OpenAL32.dll +0 -0
- data/lib/SDL2.dll +0 -0
- data/lib/gosu.rb +0 -3
- data/lib/gosu/patches.rb +0 -9
- data/lib/gosu/swig_patches.rb +3 -2
- data/lib/libmpg123.dll +0 -0
- data/lib/libsndfile.dll +0 -0
- data/lib64/OpenAL32.dll +0 -0
- data/lib64/SDL2.dll +0 -0
- data/lib64/libmpg123.dll +0 -0
- data/lib64/libsndfile.dll +0 -0
- data/rdoc/gosu.rb +95 -20
- data/src/Audio.cpp +50 -224
- data/src/AudioFile.hpp +17 -37
- data/src/AudioFileAudioToolbox.cpp +237 -0
- data/src/AudioFileSDLSound.cpp +147 -0
- data/src/AudioImpl.cpp +3 -12
- data/src/AudioImpl.hpp +3 -1
- data/src/Bitmap.cpp +85 -83
- data/src/BitmapIO.cpp +52 -58
- data/src/Constants.cpp +80 -33
- data/src/Font.cpp +3 -1
- data/src/GosuWrapper.cpp +19 -0
- data/src/Graphics.cpp +7 -4
- data/src/Image.cpp +13 -16
- data/src/Input.cpp +408 -159
- data/src/LargeImageData.cpp +1 -1
- data/src/MarkupParser.cpp +2 -1
- data/src/RubyGosu.cxx +349 -83
- data/src/RubyGosu.h +4 -2
- data/src/TexChunk.cpp +1 -1
- data/src/TextBuilder.cpp +3 -1
- data/src/Texture.cpp +1 -1
- data/src/TrueTypeFont.cpp +1 -1
- data/src/Utility.cpp +11 -7
- data/src/Window.cpp +30 -39
- data/src/WindowWrapper.cpp +28 -0
- metadata +207 -52
- data/Gosu/Bitmap.hpp +0 -113
- data/src/AudioToolboxFile.hpp +0 -210
- data/src/OggFile.hpp +0 -92
- data/src/SndFile.hpp +0 -174
- 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
|
+
|