diff decoders/modplug.c @ 208:32376317eedb

Initial adds.
author Ryan C. Gordon <icculus@icculus.org>
date Thu, 10 Jan 2002 01:16:24 +0000
parents
children b35c04e4691e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoders/modplug.c	Thu Jan 10 01:16:24 2002 +0000
@@ -0,0 +1,207 @@
+/*
+ * SDL_sound -- An abstract sound format decoding API.
+ * Copyright (C) 2001  Ryan C. Gordon.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Module player for SDL_sound. This driver handles anything that ModPlug does.
+ *
+ * Please see the file COPYING in the source's root directory.
+ *
+ *  This file written by Torbjörn Andersson (d91tan@Update.UU.SE)
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#ifdef SOUND_SUPPORTS_MODPLUG
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "SDL_sound.h"
+
+#define __SDL_SOUND_INTERNAL__
+#include "SDL_sound_internal.h"
+
+#include "modplug.h"
+
+
+static int MODPLUG_init(void);
+static void MODPLUG_quit(void);
+static int MODPLUG_open(Sound_Sample *sample, const char *ext);
+static void MODPLUG_close(Sound_Sample *sample);
+static Uint32 MODPLUG_read(Sound_Sample *sample);
+
+static const char *extensions_modplug[] =
+{
+    /* Plays 22 different mod formats (there are two kinds of AMF), including:
+     */
+    "MOD", "S3M", "XM",  "IT",  "669", "AMF", "AMS", "DMB",
+    "DMF", "DSM", "FAR", "MDL", "MED", "MHM", "OKT", "PTM",
+    "STM", "ULT", "UMX", "MT2", "PSM",
+
+    /* Plays zip, rar, gzip, and bzip2 compressed mods. The following
+     * extensions are recognized:
+     */
+    "MDZ", "S3Z", "XMZ", "ITZ",       /* zip  */
+    "MDR", "S3R", "XMR", "ITR",       /* rar  */
+    "MDGZ", "S3GZ", "XMGZ", "ITGZ",   /* gzip */
+
+    /* You can also load plain old ZIP, RAR, and GZ files. If ModPlug finds
+     * a mod in them, it will play it.
+     */
+#if 0
+    "ZIP", "RAR", "GZ",
+#endif
+
+    NULL
+};
+
+const Sound_DecoderFunctions __Sound_DecoderFunctions_MODPLUG =
+{
+    {
+        extensions_modplug,
+        "Play modules through ModPlug",
+        "Torbjörn Andersson <d91tan@Update.UU.SE>",
+        "http://modplug-xmms.sourceforge.net/"
+    },
+
+    MODPLUG_init,       /*  init() method */
+    MODPLUG_quit,       /*  quit() method */
+    MODPLUG_open,       /*  open() method */
+    MODPLUG_close,      /* close() method */
+    MODPLUG_read        /*  read() method */
+};
+
+
+static int MODPLUG_init(void)
+{
+    ModPlug_Settings settings;
+
+        /* The settings will require some experimenting. I've borrowed some
+         * of them from the XMMS ModPlug plugin.
+         */
+    settings.mFlags =
+          MODPLUG_ENABLE_OVERSAMPLING
+        | MODPLUG_ENABLE_NOISE_REDUCTION
+        | MODPLUG_ENABLE_REVERB
+        | MODPLUG_ENABLE_MEGABASS
+        | MODPLUG_ENABLE_SURROUND;
+    settings.mChannels = 2;
+    settings.mBits = 16;
+    settings.mFrequency = 44100;
+    settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
+    settings.mReverbDepth = 30;
+    settings.mReverbDelay = 100;
+    settings.mBassAmount = 40;
+    settings.mBassRange = 30;
+    settings.mSurroundDepth = 20;
+    settings.mSurroundDelay = 20;
+    settings.mLoopCount = 0;
+
+    ModPlug_SetSettings(&settings);
+    return(1);  /* success. */
+} /* MODPLUG_init */
+
+
+static void MODPLUG_quit(void)
+{
+} /* MODPLUG_quit */
+
+
+/* Most MOD files I've seen have tended to be a few hundred KB, even if some
+ * of them were much smaller than that.
+ */
+#define CHUNK_SIZE 65536
+
+static int MODPLUG_open(Sound_Sample *sample, const char *ext)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    ModPlugFile *module;
+    Uint8 *data;
+    size_t size;
+    Uint32 retval;
+
+        /* ModPlug needs the entire stream in one big chunk. I don't like it,
+         * but I don't think there's any way around it.
+         */
+    data = (Uint8 *) malloc(CHUNK_SIZE);
+    BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
+    size = 0;
+
+    do
+    {
+        retval = SDL_RWread(internal->rw, &data[size], 1, CHUNK_SIZE);
+        size += retval;
+        if (retval == CHUNK_SIZE)
+        {
+            data = (Uint8 *) realloc(data, size + CHUNK_SIZE);
+            BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
+        } /* if */
+    } while (retval > 0);
+
+        /* The buffer may be a bit too large, but that doesn't matter. I think
+         * it's safe to free it as soon as ModPlug_Load() is finished anyway.
+         */
+    module = ModPlug_Load((void *) data, size);
+    free(data);
+    BAIL_IF_MACRO(module == NULL, "MODPLUG: Not a module file.", 0);
+
+    SNDDBG(("MODPLUG: [%d ms] %s\n",
+            ModPlug_GetLength(module), ModPlug_GetName(module)));
+
+    sample->actual.channels = 2;
+    sample->actual.rate = 44100;
+    sample->actual.format = AUDIO_S16SYS;
+
+    internal->decoder_private = (void *) module;
+    sample->flags = SOUND_SAMPLEFLAG_NONE;
+
+    SNDDBG(("MODPLUG: Accepting data stream\n"));
+    return(1); /* we'll handle this data. */
+} /* MODPLUG_open */
+
+
+static void MODPLUG_close(Sound_Sample *sample)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
+
+    ModPlug_Unload(module);
+} /* MODPLUG_close */
+
+
+static Uint32 MODPLUG_read(Sound_Sample *sample)
+{
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
+    int retval;
+
+    retval = ModPlug_Read(module, internal->buffer, internal->buffer_size);
+    if (retval == 0)
+        sample->flags |= SOUND_SAMPLEFLAG_EOF;
+    return(retval);
+} /* MODPLUG_read */
+
+#endif /* SOUND_SUPPORTS_MODPLUG */
+
+
+/* end of modplug.c ... */