141 return AL_TRUE; |
141 return AL_TRUE; |
142 } |
142 } |
143 |
143 |
144 |
144 |
145 int load_oggvorbis (const char *filename, ALenum *format, char **data, ALsizei *bitsize, ALsizei *freq) { |
145 int load_oggvorbis (const char *filename, ALenum *format, char **data, ALsizei *bitsize, ALsizei *freq) { |
146 /*implementation inspired from http://www.devmaster.net/forums/showthread.php?t=1153 */ |
146 /*implementation inspired from http://www.devmaster.net/forums/showthread.php?t=1153 */ |
147 OggVorbis_File oggStream; /*stream handle*/ |
147 OggVorbis_File oggStream; /*stream handle*/ |
148 vorbis_info *vorbisInfo; /*some formatting data*/ |
148 vorbis_info *vorbisInfo; /*some formatting data*/ |
149 int64_t pcm_length; /*length of the decoded data*/ |
149 int64_t pcm_length; /*length of the decoded data*/ |
150 int section, result, size = 0; |
150 int section, result, size, endianness; |
151 #ifdef DEBUG |
151 #ifdef DEBUG |
152 int i; |
152 int i; |
153 vorbis_comment *vorbisComment; /*other less useful data*/ |
153 vorbis_comment *vorbisComment; /*other less useful data*/ |
154 #endif |
154 #endif |
155 |
155 |
156 result = ov_fopen((char*) filename, &oggStream); |
156 result = ov_fopen((char*) filename, &oggStream); |
157 if (result < 0) { |
157 if (result < 0) { |
158 fprintf (stderr, "ERROR 'load_oggvorbis()': ov_fopen failed with %X", result); |
158 fprintf (stderr, "ERROR 'load_oggvorbis()': ov_fopen failed with %X", result); |
159 ov_clear(&oggStream); |
159 ov_clear(&oggStream); |
160 return -1; |
160 return -1; |
161 } |
161 } |
162 |
162 |
|
163 /*load OGG header and determine the decoded data size*/ |
163 vorbisInfo = ov_info(&oggStream, -1); |
164 vorbisInfo = ov_info(&oggStream, -1); |
164 pcm_length = ov_pcm_total(&oggStream, -1) << vorbisInfo->channels; |
165 pcm_length = ov_pcm_total(&oggStream, -1) << vorbisInfo->channels; |
165 |
166 |
166 #ifdef DEBUG |
167 #ifdef DEBUG |
167 vorbisComment = ov_comment(&oggStream, -1); |
168 vorbisComment = ov_comment(&oggStream, -1); |
177 fprintf(stderr, "# comment: %d\n", vorbisComment->comments); |
178 fprintf(stderr, "# comment: %d\n", vorbisComment->comments); |
178 for (i = 0; i < vorbisComment->comments; i++) |
179 for (i = 0; i < vorbisComment->comments; i++) |
179 fprintf(stderr, "\tComment %d: %s\n", i, vorbisComment->user_comments[i]); |
180 fprintf(stderr, "\tComment %d: %s\n", i, vorbisComment->user_comments[i]); |
180 #endif |
181 #endif |
181 |
182 |
182 /*allocates enough room for the decoded data*/ |
183 /*allocates enough room for the decoded data*/ |
183 *data = (char*) Malloc (sizeof(char) * pcm_length); |
184 *data = (char*) Malloc (sizeof(char) * pcm_length); |
184 |
185 |
185 /*there *should* not be ogg at 8 bits*/ |
186 /*there *should* not be ogg at 8 bits*/ |
186 if (vorbisInfo->channels == 1) |
187 if (vorbisInfo->channels == 1) |
187 *format = AL_FORMAT_MONO16; |
188 *format = AL_FORMAT_MONO16; |
188 else { |
|
189 if (vorbisInfo->channels == 2) |
|
190 *format = AL_FORMAT_STEREO16; |
|
191 else { |
189 else { |
192 fprintf(stderr, "ERROR 'load_oggvorbis()': wrong OGG header - channel value (%d)\n", vorbisInfo->channels); |
190 if (vorbisInfo->channels == 2) |
193 ov_clear(&oggStream); |
191 *format = AL_FORMAT_STEREO16; |
194 return AL_FALSE; |
192 else { |
|
193 fprintf(stderr, "ERROR 'load_oggvorbis()': wrong OGG header - channel value (%d)\n", vorbisInfo->channels); |
|
194 ov_clear(&oggStream); |
|
195 return AL_FALSE; |
|
196 } |
195 } |
197 } |
196 } |
198 |
197 |
199 size = 0; |
|
200 #ifdef __LITTLE_ENDIAN__ |
|
201 endianness = 0; |
|
202 #elif __BIG_ENDIAN__ |
|
203 endianness = 1; |
|
204 #endif |
198 while (size < pcm_length) { |
205 while (size < pcm_length) { |
199 /*ov_read decodes the ogg stream and storse the pcm in data*/ |
206 /*ov_read decodes the ogg stream and storse the pcm in data*/ |
200 result = ov_read (&oggStream, *data + size, pcm_length - size, 0, 2, 1, §ion); |
207 result = ov_read (&oggStream, *data + size, pcm_length - size, endianness, 2, 1, §ion); |
201 if (result > 0) { |
208 if (result > 0) { |
202 size += result; |
209 size += result; |
203 } else { |
210 } else { |
204 if (result == 0) |
211 if (result == 0) |
205 break; |
212 break; |