Mercurial > SDL_sound_CoreAudio
comparison decoders/shn.c @ 86:155ab2a427ca
Initial add.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Tue, 25 Sep 2001 22:43:09 +0000 |
parents | |
children | 6d9fdec2f708 |
comparison
equal
deleted
inserted
replaced
85:b939258bd177 | 86:155ab2a427ca |
---|---|
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 | |
46 #include <stdio.h> | |
47 #include <stdlib.h> | |
48 #include <string.h> | |
49 #include <assert.h> | |
50 #include "SDL_sound.h" | |
51 | |
52 #define __SDL_SOUND_INTERNAL__ | |
53 #include "SDL_sound_internal.h" | |
54 | |
55 static int SHN_init(void); | |
56 static void SHN_quit(void); | |
57 static int SHN_open(Sound_Sample *sample, const char *ext); | |
58 static void SHN_close(Sound_Sample *sample); | |
59 static Uint32 SHN_read(Sound_Sample *sample); | |
60 | |
61 const Sound_DecoderFunctions __Sound_DecoderFunctions_SHN = | |
62 { | |
63 { | |
64 "SHN", | |
65 "Shorten-compressed audio data", | |
66 "Ryan C. Gordon <icculus@clutteredmind.org>", | |
67 "http://www.icculus.org/SDL_sound/" | |
68 }, | |
69 | |
70 SHN_init, /* init() method */ | |
71 SHN_quit, /* quit() method */ | |
72 SHN_open, /* open() method */ | |
73 SHN_close, /* close() method */ | |
74 SHN_read /* read() method */ | |
75 }; | |
76 | |
77 | |
78 static int SHN_init(void) | |
79 { | |
80 return(1); /* initialization always successful. */ | |
81 } /* SHN_init */ | |
82 | |
83 | |
84 static void SHN_quit(void) | |
85 { | |
86 /* it's a no-op. */ | |
87 } /* SHN_quit */ | |
88 | |
89 | |
90 static Uint32 mask_table[] = | |
91 { | |
92 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, | |
93 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, | |
94 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, | |
95 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, | |
96 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, | |
97 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF | |
98 }; | |
99 | |
100 | |
101 #define MAGIC_NUM 0x676B6A61 /* looks like "ajkg" as chars. */ | |
102 | |
103 /* | |
104 * Look through the whole file for a SHN magic number. This is costly, so | |
105 * it should only be done if the user SWEARS they have a Shorten stream... | |
106 */ | |
107 static inline int extended_shn_magic_search(Sound_Sample *sample) | |
108 { | |
109 SDL_RWops *rw = ((Sound_SampleInternal *) sample->opaque)->rw; | |
110 Uint32 word = 0; | |
111 Uint8 ch; | |
112 | |
113 while (1) | |
114 { | |
115 BAIL_IF_MACRO(SDL_RWread(rw, &ch, sizeof (ch), 1) != 1, NULL, -1); | |
116 word = ((word << 8) & 0xFFFFFF00) | ch; | |
117 if (SDL_SwapLE32(word) == MAGIC_NUM) | |
118 { | |
119 BAIL_IF_MACRO(SDL_RWread(rw, &ch, sizeof (ch), 1) != 1, NULL, -1); | |
120 return((int) ch); | |
121 } /* if */ | |
122 } /* while */ | |
123 | |
124 return((int) ch); | |
125 } /* extended_shn_magic_search */ | |
126 | |
127 | |
128 /* look for the magic number in the RWops and see what kind of file this is. */ | |
129 static inline int determine_shn_version(Sound_Sample *sample) | |
130 { | |
131 SDL_RWops *rw = ((Sound_SampleInternal *) sample->opaque)->rw; | |
132 Uint32 magic; | |
133 Uint8 ch; | |
134 | |
135 /* | |
136 * Apparently the magic number can start at any byte offset in the file, | |
137 * and we should just discard prior data, but I'm going to restrict it | |
138 * to offset zero for now, so we don't chug down every file that might | |
139 * happen to pass through here. If the extension is explicitly "SHN", we | |
140 * check the whole stream, though. | |
141 */ | |
142 | |
143 if (__Sound_strcasecmp(ext, "shn") == 0) | |
144 return(extended_shn_magic_search(sample); | |
145 | |
146 BAIL_IF_MACRO(SDL_RWread(rw, &magic, sizeof (magic), 1) != 1, NULL, -1); | |
147 BAIL_IF_MACRO(SDL_SwapLE32(magic) != MAGIC_NUM, "SHN: Not a SHN file", -1); | |
148 BAIL_IF_MACRO(SDL_RWread(rw, &ch, sizeof (ch), 1) != 1, NULL, -1); | |
149 BAIL_IF_MACRO(ch > 3, "SHN: Unsupported file version", -1); | |
150 | |
151 return((int) ch); | |
152 } /* determine_shn_version */ | |
153 | |
154 | |
155 static int SHN_open(Sound_Sample *sample, const char *ext) | |
156 { | |
157 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
158 SDL_RWops *rw = internal->rw; | |
159 int shn_version = determine_shn_version(sample, ext); | |
160 int mean = MEAN_VERSION2; | |
161 | |
162 BAIL_IF_MACRO(shn_version == -1, NULL, 0); | |
163 if (shn_version < 2) /* downgrade? */ | |
164 mean = MEAN_VERSION0; | |
165 | |
166 | |
167 | |
168 SNDDBG(("SHN: Accepting data stream.\n")); | |
169 set up sample->actual; | |
170 sample->flags = SOUND_SAMPLEFLAG_NONE; | |
171 return(1); /* we'll handle this data. */ | |
172 } /* SHN_open */ | |
173 | |
174 | |
175 static void SHN_close(Sound_Sample *sample) | |
176 { | |
177 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
178 clean up anything you put into internal->decoder_private; | |
179 } /* SHN_close */ | |
180 | |
181 | |
182 static Uint32 SHN_read(Sound_Sample *sample) | |
183 { | |
184 Uint32 retval; | |
185 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
186 | |
187 /* | |
188 * We don't actually do any decoding, so we read the fmt data | |
189 * directly into the internal buffer... | |
190 */ | |
191 retval = SDL_RWread(internal->rw, internal->buffer, | |
192 1, internal->buffer_size); | |
193 | |
194 (or whatever. Do some decoding here...) | |
195 | |
196 /* Make sure the read went smoothly... */ | |
197 if (retval == 0) | |
198 sample->flags |= SOUND_SAMPLEFLAG_EOF; | |
199 | |
200 else if (retval == -1) | |
201 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
202 | |
203 /* (next call this EAGAIN may turn into an EOF or error.) */ | |
204 else if (retval < internal->buffer_size) | |
205 sample->flags |= SOUND_SAMPLEFLAG_EAGAIN; | |
206 | |
207 (or whatever. retval == number of bytes you put in internal->buffer). | |
208 | |
209 return(retval); | |
210 } /* SHN_read */ | |
211 | |
212 #endif /* defined SOUND_SUPPORTS_SHN */ | |
213 | |
214 /* end of shn.c ... */ | |
215 |