Mercurial > SDL_sound_CoreAudio
annotate decoders/shn.c @ 100:6d9fdec2f708
added config.h, added --enable-debug flag, various other changes to the build system
author | fingolfin |
---|---|
date | Wed, 03 Oct 2001 12:25:34 +0000 |
parents | 155ab2a427ca |
children | c08794028df4 |
rev | line source |
---|---|
86 | 1 /* |
2 * SDL_sound -- An abstract sound format decoding API. | |
3 * Copyright (C) 2001 Ryan C. Gordon. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2.1 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 | |
20 /* | |
21 * Shorten decoder for SDL_sound. | |
22 * | |
23 * This driver handles Shorten-compressed waveforms. Despite the fact that | |
24 * SHNs are generally used in online trading communities, they tend to be | |
25 * much bigger than MP3s. If an MP3 crunches the waveform to 10-20 percent | |
26 * of its original size, SHNs only go to about 50-60%. Why do the Phish fans | |
27 * of the world use this format then? Rabid music traders appreciate the | |
28 * sound quality; SHNs, unlike MP3s, do not throw away any part of the | |
29 * waveform. Yes, there are people that notice this, and further more, they | |
30 * demand it...and if they can't get a good transfer of those larger files | |
31 * over the 'net, they haven't underestimated the bandwidth of CDs travelling | |
32 * the world through the postal system. | |
33 * | |
34 * Shorten homepage: http://www.softsound.com/Shorten.html | |
35 * | |
36 * The Shorten format was gleaned from the shorten codebase, by Tony | |
37 * Robinson and SoftSound Limited, but none of their code was used here. | |
38 * | |
39 * Please see the file LICENSE in the source's root directory. | |
40 * | |
41 * This file written by Ryan C. Gordon. (icculus@clutteredmind.org) | |
42 */ | |
43 | |
44 #if (defined SOUND_SUPPORTS_SHN) | |
45 | |
100
6d9fdec2f708
added config.h, added --enable-debug flag, various other changes to the build system
fingolfin
parents:
86
diff
changeset
|
46 #define __SDL_SOUND_INTERNAL__ |
6d9fdec2f708
added config.h, added --enable-debug flag, various other changes to the build system
fingolfin
parents:
86
diff
changeset
|
47 #include "SDL_sound_internal.h" |
6d9fdec2f708
added config.h, added --enable-debug flag, various other changes to the build system
fingolfin
parents:
86
diff
changeset
|
48 |
86 | 49 #include <stdio.h> |
50 #include <stdlib.h> | |
51 #include <string.h> | |
52 #include <assert.h> | |
53 #include "SDL_sound.h" | |
54 | |
55 | |
56 static int SHN_init(void); | |
57 static void SHN_quit(void); | |
58 static int SHN_open(Sound_Sample *sample, const char *ext); | |
59 static void SHN_close(Sound_Sample *sample); | |
60 static Uint32 SHN_read(Sound_Sample *sample); | |
61 | |
62 const Sound_DecoderFunctions __Sound_DecoderFunctions_SHN = | |
63 { | |
64 { | |
65 "SHN", | |
66 "Shorten-compressed audio data", | |
67 "Ryan C. Gordon <icculus@clutteredmind.org>", | |
68 "http://www.icculus.org/SDL_sound/" | |
69 }, | |
70 | |
71 SHN_init, /* init() method */ | |
72 SHN_quit, /* quit() method */ | |
73 SHN_open, /* open() method */ | |
74 SHN_close, /* close() method */ | |
75 SHN_read /* read() method */ | |
76 }; | |
77 | |
78 | |
79 static int SHN_init(void) | |
80 { | |
81 return(1); /* initialization always successful. */ | |
82 } /* SHN_init */ | |
83 | |
84 | |
85 static void SHN_quit(void) | |
86 { | |
87 /* it's a no-op. */ | |
88 } /* SHN_quit */ | |
89 | |
90 | |
91 static Uint32 mask_table[] = | |
92 { | |
93 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, | |
94 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, | |
95 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, | |
96 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, | |
97 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, | |
98 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF | |
99 }; | |
100 | |
101 | |
102 #define MAGIC_NUM 0x676B6A61 /* looks like "ajkg" as chars. */ | |
103 | |
104 /* | |
105 * Look through the whole file for a SHN magic number. This is costly, so | |
106 * it should only be done if the user SWEARS they have a Shorten stream... | |
107 */ | |
108 static inline int extended_shn_magic_search(Sound_Sample *sample) | |
109 { | |
110 SDL_RWops *rw = ((Sound_SampleInternal *) sample->opaque)->rw; | |
111 Uint32 word = 0; | |
112 Uint8 ch; | |
113 | |
114 while (1) | |
115 { | |
116 BAIL_IF_MACRO(SDL_RWread(rw, &ch, sizeof (ch), 1) != 1, NULL, -1); | |
117 word = ((word << 8) & 0xFFFFFF00) | ch; | |
118 if (SDL_SwapLE32(word) == MAGIC_NUM) | |
119 { | |
120 BAIL_IF_MACRO(SDL_RWread(rw, &ch, sizeof (ch), 1) != 1, NULL, -1); | |
121 return((int) ch); | |
122 } /* if */ | |
123 } /* while */ | |
124 | |
125 return((int) ch); | |
126 } /* extended_shn_magic_search */ | |
127 | |
128 | |
129 /* look for the magic number in the RWops and see what kind of file this is. */ | |
130 static inline int determine_shn_version(Sound_Sample *sample) | |
131 { | |
132 SDL_RWops *rw = ((Sound_SampleInternal *) sample->opaque)->rw; | |
133 Uint32 magic; | |
134 Uint8 ch; | |
135 | |
136 /* | |
137 * Apparently the magic number can start at any byte offset in the file, | |
138 * and we should just discard prior data, but I'm going to restrict it | |
139 * to offset zero for now, so we don't chug down every file that might | |
140 * happen to pass through here. If the extension is explicitly "SHN", we | |
141 * check the whole stream, though. | |
142 */ | |
143 | |
144 if (__Sound_strcasecmp(ext, "shn") == 0) | |
145 return(extended_shn_magic_search(sample); | |
146 | |
147 BAIL_IF_MACRO(SDL_RWread(rw, &magic, sizeof (magic), 1) != 1, NULL, -1); | |
148 BAIL_IF_MACRO(SDL_SwapLE32(magic) != MAGIC_NUM, "SHN: Not a SHN file", -1); | |
149 BAIL_IF_MACRO(SDL_RWread(rw, &ch, sizeof (ch), 1) != 1, NULL, -1); | |
150 BAIL_IF_MACRO(ch > 3, "SHN: Unsupported file version", -1); | |
151 | |
152 return((int) ch); | |
153 } /* determine_shn_version */ | |
154 | |
155 | |
156 static int SHN_open(Sound_Sample *sample, const char *ext) | |
157 { | |
158 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
159 SDL_RWops *rw = internal->rw; | |
160 int shn_version = determine_shn_version(sample, ext); | |
161 int mean = MEAN_VERSION2; | |
162 | |
163 BAIL_IF_MACRO(shn_version == -1, NULL, 0); | |
164 if (shn_version < 2) /* downgrade? */ | |
165 mean = MEAN_VERSION0; | |
166 | |
167 | |
168 | |
169 SNDDBG(("SHN: Accepting data stream.\n")); | |
170 set up sample->actual; | |
171 sample->flags = SOUND_SAMPLEFLAG_NONE; | |
172 return(1); /* we'll handle this data. */ | |
173 } /* SHN_open */ | |
174 | |
175 | |
176 static void SHN_close(Sound_Sample *sample) | |
177 { | |
178 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
179 clean up anything you put into internal->decoder_private; | |
180 } /* SHN_close */ | |
181 | |
182 | |
183 static Uint32 SHN_read(Sound_Sample *sample) | |
184 { | |
185 Uint32 retval; | |
186 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
187 | |
188 /* | |
189 * We don't actually do any decoding, so we read the fmt data | |
190 * directly into the internal buffer... | |
191 */ | |
192 retval = SDL_RWread(internal->rw, internal->buffer, | |
193 1, internal->buffer_size); | |
194 | |
195 (or whatever. Do some decoding here...) | |
196 | |
197 /* Make sure the read went smoothly... */ | |
198 if (retval == 0) | |
199 sample->flags |= SOUND_SAMPLEFLAG_EOF; | |
200 | |
201 else if (retval == -1) | |
202 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
203 | |
204 /* (next call this EAGAIN may turn into an EOF or error.) */ | |
205 else if (retval < internal->buffer_size) | |
206 sample->flags |= SOUND_SAMPLEFLAG_EAGAIN; | |
207 | |
208 (or whatever. retval == number of bytes you put in internal->buffer). | |
209 | |
210 return(retval); | |
211 } /* SHN_read */ | |
212 | |
213 #endif /* defined SOUND_SUPPORTS_SHN */ | |
214 | |
215 /* end of shn.c ... */ | |
216 |