208
|
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 * Module player for SDL_sound. This driver handles anything that ModPlug does.
|
|
22 *
|
|
23 * Please see the file COPYING in the source's root directory.
|
|
24 *
|
|
25 * This file written by Torbjörn Andersson (d91tan@Update.UU.SE)
|
|
26 */
|
|
27
|
|
28 #if HAVE_CONFIG_H
|
|
29 # include <config.h>
|
|
30 #endif
|
|
31
|
|
32 #ifdef SOUND_SUPPORTS_MODPLUG
|
|
33
|
|
34 #include <stdio.h>
|
|
35 #include <stdlib.h>
|
|
36 #include <string.h>
|
|
37 #include <assert.h>
|
|
38
|
|
39 #include "SDL_sound.h"
|
|
40
|
|
41 #define __SDL_SOUND_INTERNAL__
|
|
42 #include "SDL_sound_internal.h"
|
|
43
|
|
44 #include "modplug.h"
|
|
45
|
|
46
|
|
47 static int MODPLUG_init(void);
|
|
48 static void MODPLUG_quit(void);
|
|
49 static int MODPLUG_open(Sound_Sample *sample, const char *ext);
|
|
50 static void MODPLUG_close(Sound_Sample *sample);
|
|
51 static Uint32 MODPLUG_read(Sound_Sample *sample);
|
|
52
|
|
53 static const char *extensions_modplug[] =
|
|
54 {
|
|
55 /* Plays 22 different mod formats (there are two kinds of AMF), including:
|
|
56 */
|
|
57 "MOD", "S3M", "XM", "IT", "669", "AMF", "AMS", "DMB",
|
|
58 "DMF", "DSM", "FAR", "MDL", "MED", "MHM", "OKT", "PTM",
|
|
59 "STM", "ULT", "UMX", "MT2", "PSM",
|
|
60
|
|
61 /* Plays zip, rar, gzip, and bzip2 compressed mods. The following
|
|
62 * extensions are recognized:
|
|
63 */
|
|
64 "MDZ", "S3Z", "XMZ", "ITZ", /* zip */
|
|
65 "MDR", "S3R", "XMR", "ITR", /* rar */
|
|
66 "MDGZ", "S3GZ", "XMGZ", "ITGZ", /* gzip */
|
|
67
|
|
68 /* You can also load plain old ZIP, RAR, and GZ files. If ModPlug finds
|
|
69 * a mod in them, it will play it.
|
|
70 */
|
|
71 #if 0
|
|
72 "ZIP", "RAR", "GZ",
|
|
73 #endif
|
|
74
|
|
75 NULL
|
|
76 };
|
|
77
|
|
78 const Sound_DecoderFunctions __Sound_DecoderFunctions_MODPLUG =
|
|
79 {
|
|
80 {
|
|
81 extensions_modplug,
|
|
82 "Play modules through ModPlug",
|
|
83 "Torbjörn Andersson <d91tan@Update.UU.SE>",
|
|
84 "http://modplug-xmms.sourceforge.net/"
|
|
85 },
|
|
86
|
|
87 MODPLUG_init, /* init() method */
|
|
88 MODPLUG_quit, /* quit() method */
|
|
89 MODPLUG_open, /* open() method */
|
|
90 MODPLUG_close, /* close() method */
|
|
91 MODPLUG_read /* read() method */
|
|
92 };
|
|
93
|
|
94
|
|
95 static int MODPLUG_init(void)
|
|
96 {
|
|
97 ModPlug_Settings settings;
|
|
98
|
|
99 /* The settings will require some experimenting. I've borrowed some
|
|
100 * of them from the XMMS ModPlug plugin.
|
|
101 */
|
|
102 settings.mFlags =
|
|
103 MODPLUG_ENABLE_OVERSAMPLING
|
|
104 | MODPLUG_ENABLE_NOISE_REDUCTION
|
|
105 | MODPLUG_ENABLE_REVERB
|
|
106 | MODPLUG_ENABLE_MEGABASS
|
|
107 | MODPLUG_ENABLE_SURROUND;
|
|
108 settings.mChannels = 2;
|
|
109 settings.mBits = 16;
|
|
110 settings.mFrequency = 44100;
|
|
111 settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
|
|
112 settings.mReverbDepth = 30;
|
|
113 settings.mReverbDelay = 100;
|
|
114 settings.mBassAmount = 40;
|
|
115 settings.mBassRange = 30;
|
|
116 settings.mSurroundDepth = 20;
|
|
117 settings.mSurroundDelay = 20;
|
|
118 settings.mLoopCount = 0;
|
|
119
|
|
120 ModPlug_SetSettings(&settings);
|
|
121 return(1); /* success. */
|
|
122 } /* MODPLUG_init */
|
|
123
|
|
124
|
|
125 static void MODPLUG_quit(void)
|
|
126 {
|
|
127 } /* MODPLUG_quit */
|
|
128
|
|
129
|
|
130 /* Most MOD files I've seen have tended to be a few hundred KB, even if some
|
|
131 * of them were much smaller than that.
|
|
132 */
|
|
133 #define CHUNK_SIZE 65536
|
|
134
|
|
135 static int MODPLUG_open(Sound_Sample *sample, const char *ext)
|
|
136 {
|
|
137 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
|
138 ModPlugFile *module;
|
|
139 Uint8 *data;
|
|
140 size_t size;
|
|
141 Uint32 retval;
|
|
142
|
|
143 /* ModPlug needs the entire stream in one big chunk. I don't like it,
|
|
144 * but I don't think there's any way around it.
|
|
145 */
|
|
146 data = (Uint8 *) malloc(CHUNK_SIZE);
|
|
147 BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
148 size = 0;
|
|
149
|
|
150 do
|
|
151 {
|
|
152 retval = SDL_RWread(internal->rw, &data[size], 1, CHUNK_SIZE);
|
|
153 size += retval;
|
|
154 if (retval == CHUNK_SIZE)
|
|
155 {
|
|
156 data = (Uint8 *) realloc(data, size + CHUNK_SIZE);
|
|
157 BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
158 } /* if */
|
|
159 } while (retval > 0);
|
|
160
|
|
161 /* The buffer may be a bit too large, but that doesn't matter. I think
|
|
162 * it's safe to free it as soon as ModPlug_Load() is finished anyway.
|
|
163 */
|
|
164 module = ModPlug_Load((void *) data, size);
|
|
165 free(data);
|
|
166 BAIL_IF_MACRO(module == NULL, "MODPLUG: Not a module file.", 0);
|
|
167
|
|
168 SNDDBG(("MODPLUG: [%d ms] %s\n",
|
|
169 ModPlug_GetLength(module), ModPlug_GetName(module)));
|
|
170
|
|
171 sample->actual.channels = 2;
|
|
172 sample->actual.rate = 44100;
|
|
173 sample->actual.format = AUDIO_S16SYS;
|
|
174
|
|
175 internal->decoder_private = (void *) module;
|
|
176 sample->flags = SOUND_SAMPLEFLAG_NONE;
|
|
177
|
|
178 SNDDBG(("MODPLUG: Accepting data stream\n"));
|
|
179 return(1); /* we'll handle this data. */
|
|
180 } /* MODPLUG_open */
|
|
181
|
|
182
|
|
183 static void MODPLUG_close(Sound_Sample *sample)
|
|
184 {
|
|
185 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
|
186 ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
|
|
187
|
|
188 ModPlug_Unload(module);
|
|
189 } /* MODPLUG_close */
|
|
190
|
|
191
|
|
192 static Uint32 MODPLUG_read(Sound_Sample *sample)
|
|
193 {
|
|
194 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
|
|
195 ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
|
|
196 int retval;
|
|
197
|
|
198 retval = ModPlug_Read(module, internal->buffer, internal->buffer_size);
|
|
199 if (retval == 0)
|
|
200 sample->flags |= SOUND_SAMPLEFLAG_EOF;
|
|
201 return(retval);
|
|
202 } /* MODPLUG_read */
|
|
203
|
|
204 #endif /* SOUND_SUPPORTS_MODPLUG */
|
|
205
|
|
206
|
|
207 /* end of modplug.c ... */
|