comparison decoders/mp3.c @ 14:41e5e07c5fed

Initial add.
author Ryan C. Gordon <icculus@icculus.org>
date Tue, 18 Sep 2001 11:01:48 +0000
parents
children d9e84e857569
comparison
equal deleted inserted replaced
13:f2af6266775f 14:41e5e07c5fed
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 * MPEG-1 Layer 3, or simply, "MP3", decoder for SDL_sound.
22 *
23 * This driver handles all those highly compressed songs you stole through
24 * Napster. :) It depends on the SMPEG library for decoding, which can
25 * be grabbed from: http://www.lokigames.com/development/smpeg.php3
26 *
27 * Please see the file LICENSE in the source's root directory.
28 *
29 * This file written by Ryan C. Gordon. (icculus@clutteredmind.org)
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36
37 #include "smpeg.h"
38 #include "SDL_sound.h"
39 #include "extra_rwops.h"
40
41 #define __SDL_SOUND_INTERNAL__
42 #include "SDL_sound_internal.h"
43
44 #if (!defined SOUND_SUPPORTS_MP3)
45 #error SOUND_SUPPORTS_MP3 must be defined.
46 #endif
47
48
49 static int MP3_open(Sound_Sample *sample, const char *ext);
50 static void MP3_close(Sound_Sample *sample);
51 static Uint32 MP3_read(Sound_Sample *sample);
52
53 const Sound_DecoderFunctions __Sound_DecoderFunctions_MP3 =
54 {
55 {
56 "MP3",
57 "MPEG-1 Layer 3 audio through SMPEG",
58 "Ryan C. Gordon <icculus@clutteredmind.org>",
59 "http://www.icculus.org/SDL_sound/"
60 },
61
62 MP3_open, /* open() method */
63 MP3_close, /* close() method */
64 MP3_read /* read() method */
65 };
66
67 static __inline__ void output_version(void)
68 {
69 static int first_time = 1;
70
71 if (first_time)
72 {
73 SMPEG_version v;
74 SMPEG_VERSION(&v);
75 _D(("MP3: Compiled against SMPEG v%d.%d.%d.\n",
76 v.major, v.minor, v.patch));
77 first_time = 0;
78 } /* if */
79 } /* output_version */
80
81
82 static int MP3_open(Sound_Sample *sample, const char *ext)
83 {
84 SMPEG *smpeg;
85 SMPEG_Info smpeg_info;
86 SDL_AudioSpec spec;
87 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
88 SDL_RWops *refCounter;
89
90 output_version();
91
92 refCounter = RWops_RWRefCounter_new(internal->rw);
93 if (refCounter == NULL)
94 {
95 _D(("MP3: Failed to create reference counting RWops.\n"));
96 return(0);
97 } /* if */
98
99 /* replace original RWops. This is safe. Honest. :) */
100 internal->rw = refCounter;
101
102 /*
103 * increment the refcount, since SMPEG will nuke the RWops if it can't
104 * accept the contained data...
105 */
106 RWops_RWRefCounter_addRef(refCounter);
107 smpeg = SMPEG_new_rwops(refCounter, &smpeg_info, 0);
108
109 if (SMPEG_error(smpeg))
110 {
111 Sound_SetError(SMPEG_error(smpeg));
112 SMPEG_delete(smpeg);
113 return(0);
114 } /* if */
115
116 if (!smpeg_info.has_audio)
117 {
118 Sound_SetError("MP3: No audio stream found in data.");
119 SMPEG_delete(smpeg);
120 return(0);
121 } /* if */
122
123 _D(("MP3: Accepting data stream.\n"));
124 _D(("MP3: has_audio == %s.\n", smpeg_info.has_audio ? "TRUE" : "FALSE"));
125 _D(("MP3: has_video == %s.\n", smpeg_info.has_video ? "TRUE" : "FALSE"));
126 _D(("MP3: width == %d.\n", smpeg_info.width));
127 _D(("MP3: height == %d.\n", smpeg_info.height));
128 _D(("MP3: current_frame == %d.\n", smpeg_info.current_frame));
129 _D(("MP3: current_fps == %f.\n", smpeg_info.current_fps));
130 _D(("MP3: audio_string == [%s].\n", smpeg_info.audio_string));
131 _D(("MP3: audio_current_frame == %d.\n", smpeg_info.audio_current_frame));
132 _D(("MP3: current_offset == %d.\n", smpeg_info.current_offset));
133 _D(("MP3: total_size == %d.\n", smpeg_info.total_size));
134 _D(("MP3: current_time == %f.\n", smpeg_info.current_time));
135 _D(("MP3: total_time == %f.\n", smpeg_info.total_time));
136
137 SMPEG_enablevideo(smpeg, 0);
138 SMPEG_enableaudio(smpeg, 1);
139 SMPEG_loop(smpeg, 0);
140
141 SMPEG_wantedSpec(smpeg, &spec);
142 sample->actual.format = spec.format;
143 sample->actual.rate = spec.freq;
144 sample->actual.channels = spec.channels;
145 sample->flags = SOUND_SAMPLEFLAG_NONE;
146 internal->decoder_private = smpeg;
147
148 SMPEG_play(smpeg);
149 return(1);
150 } /* MP3_open */
151
152
153 static void MP3_close(Sound_Sample *sample)
154 {
155 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
156 SMPEG_delete((SMPEG *) internal->decoder_private);
157 } /* MP3_close */
158
159
160 static Uint32 MP3_read(Sound_Sample *sample)
161 {
162 Uint32 retval;
163 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
164 SMPEG *smpeg = (SMPEG *) internal->decoder_private;
165
166 retval = SMPEG_playAudio(smpeg, internal->buffer, internal->buffer_size);
167 if (retval < internal->buffer_size)
168 {
169 char *errMsg = SMPEG_error(smpeg);
170 if (errMsg == NULL)
171 sample->flags |= SOUND_SAMPLEFLAG_EOF;
172 else
173 {
174 Sound_SetError(errMsg);
175 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
176 } /* else */
177 } /* if */
178
179 return(retval);
180 } /* MP3_read */
181
182 /* end of mp3.c ... */
183