Commit ac87bfc3 authored by Jeremy Simon's avatar Jeremy Simon

adding modplug

Original commit message from CVS:
adding modplug
parent 3b68b42a
......@@ -164,7 +164,7 @@ GST_PLUGINS_ALL="\
ac3parse adder audioscale auparse avi chart\
cutter deinterlace flx goom intfloat law level\
median mpeg1enc mpeg1sys mpeg1videoparse mpeg2enc mpeg2sub\
mpegaudio mpegaudioparse mpegstream mpegtypes\
mpegaudio mpegaudioparse mpegstream mpegtypes modplug\
passthrough playondemand rtjpeg silence sine\
smooth spectrum speed stereo stereomono\
synaesthesia udp videoscale volenv volume vumeter wavparse y4m"
......@@ -732,6 +732,8 @@ gst/mpegaudio/Makefile
gst/mpegaudioparse/Makefile
gst/mpegstream/Makefile
gst/mpegtypes/Makefile
gst/modplug/Makefile
gst/modplug/libmodplug/Makefile
gst/passthrough/Makefile
gst/playondemand/Makefile
gst/rtjpeg/Makefile
......
plugindir = $(libdir)/gst
plugin_LTLIBRARIES = libgstmodplug.la
libgstmodplug_la_SOURCES = gstmodplug.cc
libgstmodplug_la_CXXFLAGS = $(GST_CFLAGS)
libgstmodplug_la_LIBADD = $(GST_LIBS) libmodplug/libmodplug.la
libgstmodplug_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@
SUBDIRS=libmodplug
noinst_HEADERS = gstmodplug.h
EXTRA_DIST = README
This diff is collapsed.
/* Gnome-Streamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
#ifndef __GST_MODPLUG_H__
#define __GST_MODPLUG_H__
#include <config.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <gst/gst.h>
#define GST_TYPE_MODPLUG \
(gst_modplug_get_type())
#define GST_MODPLUG(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MODPLUG,GstModPlug))
#define GST_MODPLUG_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstModPlug))
#define GST_IS_MODPLUG(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MODPLUG))
#define GST_IS_MODPLUG_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MODPLUG))
struct _GstModPlug {
GstElement element;
GstPad *sinkpad, *srcpad;
GstBuffer *Buffer;
const gchar *songname;
gboolean reverb;
gint reverb_depth;
gint reverb_delay;
gboolean megabass;
gint megabass_amount;
gint megabass_range;
gboolean surround;
gint surround_depth;
gint surround_delay;
gboolean noise_reduction;
gboolean _16bit;
gboolean oversamp;
gint channel;
gint frequency;
guchar *audiobuffer;
gint32 length;
CSoundFile *mSoundFile;
};
struct _GstModPlugClass {
GstElementClass parent_class;
};
typedef struct _GstModPlug GstModPlug;
typedef struct _GstModPlugClass GstModPlugClass;
GstPad *srcpad;
int need_sync;
GType gst_modplug_get_type(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_MODPLUG_H__ */
lib_LTLIBRARIES = libmodplug.la
libmodplug_la_CXXFLAGS = -fno-exceptions -Wall -ffast-math -D_REENTRANT
libmodplug_la_LDFLAGS = -module -avoid-version
libmodplug_la_SOURCES = tables.cpp \
sndmix.cpp \
sndfile.cpp \
snd_fx.cpp \
snd_flt.cpp \
snd_dsp.cpp \
fastmix.cpp \
mmcmp.cpp \
load_xm.cpp \
load_wav.cpp \
load_umx.cpp \
load_ult.cpp \
load_stm.cpp \
load_s3m.cpp \
load_ptm.cpp \
load_okt.cpp \
load_mtm.cpp \
load_mod.cpp \
load_med.cpp \
load_mdl.cpp \
load_it.cpp \
load_far.cpp \
load_dsm.cpp \
load_dmf.cpp \
load_dbm.cpp \
load_ams.cpp \
load_amf.cpp \
load_669.cpp \
load_j2b.cpp \
load_mt2.cpp \
load_psm.cpp \
modplug.cpp
include_HEADERS = modplug.h
noinst_HEADERS = it_defs.h stdafx.h sndfile.h
EXTRA_DIST = changes.txt
libmodplug v0.7 - A library for decoding MOD-like music formats.
Based on the ModPlug sound engine by Olivier Lapicque <olivierl@jps.net>
Ported to Unix by Kenton Varda <temporal@gauge3d.org>
Additional modifications by Markus Fick <marf@gmx.net> and
Adam Goode <adam@evdebs.org>
Placed in the public domain in October, 2001
All the documentation needed can be found in the comments in modplug.h.
This library should be perfectly accessible from C, although it is written
in C++. Just #include <modplug.h> to use it, and link against
libmodplug.so.
This library has been known to compile fine in Windows using MinGW32 (A
GCC-based compiler). Windows is not yet officially supported, however.
(With about half an hour of hacking, any decent programmer should be able
to convince WinAmp to play mods using this library. ;) )
I need a maintainer for this. I have too many other projects I am working
on, and ModPlug has dropped low on the list. If you would like to be the
new maintainer, please e-mail me at <temporal@gauge3d.org> and tell me why
you think you would be the right person for the job. :)
\ No newline at end of file
changes:
date = 09-feb-2001 [Markus Fick]
-> file: fastmix.cpp
where: spline creation, spline macros
what: added unity gain clamp code, added Quantizer_Bits(shift) preprocessor constants
where: fir creation, fir macros
what: - removed x<pi/2 condition in coef creation
- added quantizer_bits(shift) preprocessor constants
- set default quantizer bits to 15 instead 14 (scale now 32768 instead 16384)
there should not occure any overflows during fir response calculation because
of the symmetric form of filter and the position of the negative fir coefs
- changed final volume calculation for 16bit samples (quality enhancement)
date = 08-feb-2001 [Markus Fick]
-> file: sndmix.cpp
where: function ReadNote()
what: modified behaviour of modplug so that interpolation is only deactivated if
a) the user selects "no interpolation"
b) linear interpolation is set and speed incr. > 0xff00
=> if spline or fir is active then we use always interpolation
-> file: fastmix.cpp
where: spline macros
what: changed spline macros to use precalculated tables (way faster)
where: file
what: - implemented spline table precalculator
- changed fir precalculator + macros (for higher quality and clearer source)
- added some comments and documentation
comment:
- preprocessor constant: SPLINE_FRACBITS
) controls quality/memory usage
range is [4..14] inclusive
4 = low quality, low memory usage
14 = highest quality, highest memory usage (1L<<14)*4*2 bytes
- preprocessor constant: WFIR_FRACBITS
) controls quality/memory usage
range is [4..12] inclusive
4 = low quality, low mu
12 = highest quality, highest memory usage ((1L<<(12+1))+1)*8*2 bytes
date = 07-feb-2001 [Markus Fick]
-> file: fastmix.cpp
where: spline macros
what: fixed error in coef calculation
date = 07-feb-2001 [Markus Fick]
-> file: sndfile.h
where: class definition of soundfile
what: removed InitFIR + DoneFIR function prototypes
-> file: sndfile.cpp
function:CSoundFile::CSoundFile()
what: [modify] removed call to CSoundFile::InitFIRMixer( )
function:CSoundFile::~CSoundFile()
what: [modify] removed call to CSoundFile::DoneFIRMixer( )
-> file: fastmix.cpp
where: spline macros
what: changed formula + added some guard bits to calculation
where: fir macros + implementation
what: - moved CSoundfile::FIR funtions to CzFIR (single instance sfir)
- changed fir macros to support CzFIR class
date = 06-feb-2001 [Markus Fick]
-> file: fastmix.cpp
where: macros
what: - removed fir filter with coef interpolation
- add spline interpolation
RM: now modplug->select( SPLINE ) selects spline and
modplug->select( POLYPHASE ) selects 8tap fir filter
date = 05-feb-2001 [Markus Fick]
-> file: fastmix.cpp
where: macros + filter order
what: [modify] changed filter order to 8 instead of 10
-> file: fastmix.cpp
what: new macros+switch for fir-interpolator with coef interpolation
date = 04-feb-2001 [Markus Fick]
-> file: sndfile.h
where: class CSoundFile (bottom)
what: [add] methods for FIR mixer support
1. int InitFIRInterpolator( );
2. int DoneFIRInterpolator( );
-> file: sndfile.cpp
function:CSoundFile::CSoundFile()
what: [modify] add call to CSoundFile::InitFIRMixer( )
function:CSoundFile::~CSoundFile()
what: [modify] add call to CSoundFile::DoneFIRMixer( )
-> file: fastmix.cpp
new include: <math.h>
why: need it for fir-coef calculation
new function: CSoundFile::InitFIRMixer( ) // initializes fir filter lookup (if necessary)
new function: CSoundFile::DoneFIRMixer( ) // decrements ReferenceCounter (for static vars) and deinitializes fir struct (if possible).
new defs:
#define FIRCPWBN 10 // log2 of number of precalculated wings (-(1L<<FIRCPWBN)..(1L<<FIRCPWBN))
#define FIRLOPOSSHIFT (16-(FIRCPWBN+1)) // shift for lopos of sampleposition -> (16 - FIRCPWBN - 1)
#define FIRLEN 9 // number(-1) of multiplications per sample
#define FIRCUT 0.90f // cutoff of filter
#define MIXNDX_FIRMIXERSRC 0x20 // src-type for firfilter
new vars:
static signed short *cFirLut; // lulines
static int bFirInitialized = 0; // initialized?
static int nFirOrder = FIRLEN; // order (modplug has 4smps pre/post extension, so limit this to 9)
static float nFirFC = FIRCUT; // cutoff (normalized to pi/2)
static int nFirCpw = (1L<<FIRCPWBN); // number of precalculted filter lines
static int nFirUsers = 0; // reference counter
new macros:
#define SNDMIX_GETMONOVOL8FIRFILTER
#define SNDMIX_GETMONOVOL16FIRFILTER
#define SNDMIX_GETSTEREOVOL8FIRFILTER
#define SNDMIX_GETSTEREOVOL16FIRFILTER
new mixer interface macros:
BEGIN_MIX_INTERFACE(Mono8BitFirFilterMix)
BEGIN_MIX_INTERFACE(Mono16BitFirFilterMix)
BEGIN_RAMPMIX_INTERFACE(Mono8BitFirFilterRampMix)
BEGIN_RAMPMIX_INTERFACE(Mono16BitFirFilterRampMix)
BEGIN_MIX_INTERFACE(FastMono8BitFirFilterMix)
BEGIN_MIX_INTERFACE(FastMono16BitFirFilterMix)
BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitFirFilterRampMix)
BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitFirFilterRampMix)
BEGIN_MIX_INTERFACE(Stereo8BitFirFilterMix)
BEGIN_MIX_INTERFACE(Stereo16BitFirFilterMix)
BEGIN_RAMPMIX_INTERFACE(Stereo8BitFirFilterRampMix)
BEGIN_RAMPMIX_INTERFACE(Stereo16BitFirFilterRampMix)
BEGIN_MIX_FLT_INTERFACE(FilterMono8BitFirFilterMix)
BEGIN_MIX_FLT_INTERFACE(FilterMono16BitFirFilterMix)
BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitFirFilterRampMix)
BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitFirFilterRampMix)
BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitFirFilterMix)
BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitFirFilterMix)
BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitFirFilterRampMix)
BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitFirFilterRampMix)
modified:
const LPMIXINTERFACE gpMixFunctionTable[2*2*16] // to hold new fir mixer interface
const LPMIXINTERFACE gpFastMixFunctionTable[2*2*16] // to hold new fir mixer interface
functioN: UINT CSoundFile::CreateStereoMix(int count)
new:
if (!(pChannel->dwFlags & CHN_NOIDO))
{
// use hq-fir mixer?
if( ((gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) ||
((gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == (SNDMIX_HQRESAMPLER)) )
nFlags += MIXNDX_FIRMIXERSRC;
else
nFlags += MIXNDX_LINEARSRC; // use
}
was:
if (!(pChannel->dwFlags & CHN_NOIDO))
{
nFlags += MIXNDX_LINEARSRC; // use
}
This diff is collapsed.
#ifndef _ITDEFS_H_
#define _ITDEFS_H_
#pragma pack(1)
typedef struct tagITFILEHEADER
{
DWORD id; // 0x4D504D49
CHAR songname[26];
WORD reserved1; // 0x1004
WORD ordnum;
WORD insnum;
WORD smpnum;
WORD patnum;
WORD cwtv;
WORD cmwt;
WORD flags;
WORD special;
BYTE globalvol;
BYTE mv;
BYTE speed;
BYTE tempo;
BYTE sep;
BYTE zero;
WORD msglength;
DWORD msgoffset;
DWORD reserved2;
BYTE chnpan[64];
BYTE chnvol[64];
} ITFILEHEADER;
typedef struct tagITENVELOPE
{
BYTE flags;
BYTE num;
BYTE lpb;
BYTE lpe;
BYTE slb;
BYTE sle;
BYTE data[25*3];
BYTE reserved;
} ITENVELOPE;
// Old Impulse Instrument Format (cmwt < 0x200)
typedef struct tagITOLDINSTRUMENT
{
DWORD id; // IMPI = 0x49504D49
CHAR filename[12]; // DOS file name
BYTE zero;
BYTE flags;
BYTE vls;
BYTE vle;
BYTE sls;
BYTE sle;
WORD reserved1;
WORD fadeout;
BYTE nna;
BYTE dnc;
WORD trkvers;
BYTE nos;
BYTE reserved2;
CHAR name[26];
WORD reserved3[3];
BYTE keyboard[240];
BYTE volenv[200];
BYTE nodes[50];
} ITOLDINSTRUMENT;
// Impulse Instrument Format
typedef struct tagITINSTRUMENT
{
DWORD id;
CHAR filename[12];
BYTE zero;
BYTE nna;
BYTE dct;
BYTE dca;
WORD fadeout;
signed char pps;
BYTE ppc;
BYTE gbv;
BYTE dfp;
BYTE rv;
BYTE rp;
WORD trkvers;
BYTE nos;
BYTE reserved1;
CHAR name[26];
BYTE ifc;
BYTE ifr;
BYTE mch;
BYTE mpr;
WORD mbank;
BYTE keyboard[240];
ITENVELOPE volenv;
ITENVELOPE panenv;
ITENVELOPE pitchenv;
BYTE dummy[4]; // was 7, but IT v2.17 saves 554 bytes
} ITINSTRUMENT;
// IT Sample Format
typedef struct ITSAMPLESTRUCT
{
DWORD id; // 0x53504D49
CHAR filename[12];
BYTE zero;
BYTE gvl;
BYTE flags;
BYTE vol;
CHAR name[26];
BYTE cvt;
BYTE dfp;
DWORD length;
DWORD loopbegin;
DWORD loopend;
DWORD C5Speed;
DWORD susloopbegin;
DWORD susloopend;
DWORD samplepointer;
BYTE vis;
BYTE vid;
BYTE vir;
BYTE vit;
} ITSAMPLESTRUCT;
#pragma pack()
extern BYTE autovibit2xm[8];
extern BYTE autovibxm2it[8];
#endif
/*
* This source code is public domain.
*
* Authors: Olivier Lapicque <olivierl@jps.net>,
* Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
*/
////////////////////////////////////////////////////////////
// 669 Composer / UNIS 669 module loader
////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "sndfile.h"
//#pragma warning(disable:4244)
typedef struct tagFILEHEADER669
{
WORD sig; // 'if' or 'JN'
signed char songmessage[108]; // Song Message
BYTE samples; // number of samples (1-64)
BYTE patterns; // number of patterns (1-128)
BYTE restartpos;
BYTE orders[128];
BYTE tempolist[128];
BYTE breaks[128];
} FILEHEADER669;
typedef struct tagSAMPLE669
{
BYTE filename[13];
BYTE length[4]; // when will somebody think about DWORD align ???
BYTE loopstart[4];
BYTE loopend[4];
} SAMPLE669;
BOOL CSoundFile::Read669(const BYTE *lpStream, DWORD dwMemLength)
//---------------------------------------------------------------
{
BOOL b669Ext;
const FILEHEADER669 *pfh = (const FILEHEADER669 *)lpStream;
const SAMPLE669 *psmp = (const SAMPLE669 *)(lpStream + 0x1F1);
DWORD dwMemPos = 0;
if ((!lpStream) || (dwMemLength < sizeof(FILEHEADER669))) return FALSE;
if ((bswapLE16(pfh->sig) != 0x6669) && (bswapLE16(pfh->sig) != 0x4E4A)) return FALSE;
b669Ext = (bswapLE16(pfh->sig) == 0x4E4A) ? TRUE : FALSE;
if ((!pfh->samples) || (pfh->samples > 64) || (pfh->restartpos >= 128)
|| (!pfh->patterns) || (pfh->patterns > 128)) return FALSE;
DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600;
if (dontfuckwithme > dwMemLength) return FALSE;
for (UINT ichk=0; ichk<pfh->samples; ichk++)
{
DWORD len = bswapLE32(*((DWORD *)(&psmp[ichk].length)));
dontfuckwithme += len;
}
if (dontfuckwithme > dwMemLength) return FALSE;
// That should be enough checking: this must be a 669 module.
m_nType = MOD_TYPE_669;
m_dwSongFlags |= SONG_LINEARSLIDES;
m_nMinPeriod = 28 << 2;
m_nMaxPeriod = 1712 << 3;
m_nDefaultTempo = 125;
m_nDefaultSpeed = 6;
m_nChannels = 8;
memcpy(m_szNames[0], pfh->songmessage, 16);
m_nSamples = pfh->samples;
for (UINT nins=1; nins<=m_nSamples; nins++, psmp++)
{
DWORD len = bswapLE32(*((DWORD *)(&psmp->length)));
DWORD loopstart = bswapLE32(*((DWORD *)(&psmp->loopstart)));
DWORD loopend = bswapLE32(*((DWORD *)(&psmp->loopend)));
if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH;
if ((loopend > len) && (!loopstart)) loopend = 0;
if (loopend > len) loopend = len;
if (loopstart + 4 >= loopend) loopstart = loopend = 0;
Ins[nins].nLength = len;
Ins[nins].nLoopStart = loopstart;
Ins[nins].nLoopEnd = loopend;
if (loopend) Ins[nins].uFlags |= CHN_LOOP;
memcpy(m_szNames[nins], psmp->filename, 13);
Ins[nins].nVolume = 256;
Ins[nins].nGlobalVol = 64;
Ins[nins].nPan = 128;
}
// Song Message
m_lpszSongComments = new char[109];
memcpy(m_lpszSongComments, pfh->songmessage, 108);
m_lpszSongComments[108] = 0;
// Reading Orders
memcpy(Order, pfh->orders, 128);
m_nRestartPos = pfh->restartpos;
if (Order[m_nRestartPos] >= pfh->patterns) m_nRestartPos = 0;
// Reading Pattern Break Locations
for (UINT npan=0; npan<8; npan++)
{
ChnSettings[npan].nPan = (npan & 1) ? 0x30 : 0xD0;
ChnSettings[npan].nVolume = 64;
}
// Reading Patterns
dwMemPos = 0x1F1 + pfh->samples * 25;
for (UINT npat=0; npat<pfh->patterns; npat++)
{
Patterns[npat] = AllocatePattern(64, m_nChannels);
if (!Patterns[npat]) break;
PatternSize[npat] = 64;
MODCOMMAND *m = Patterns[npat];
const BYTE *p = lpStream + dwMemPos;
for (UINT row=0; row<64; row++)
{
MODCOMMAND *mspeed = m;
if ((row == pfh->breaks[npat]) && (row != 63))
{
for (UINT i=0; i<8; i++)
{
m[i].command = CMD_PATTERNBREAK;
m[i].param = 0;
}
}
for (UINT n=0; n<8; n++, m++, p+=3)
{
UINT note = p[0] >> 2;
UINT instr = ((p[0] & 0x03) << 4) | (p[1] >> 4);
UINT vol = p[1] & 0x0F;
if (p[0] < 0xFE)
{
m->note = note + 37;
m->instr = instr + 1;
}
if (p[0] <= 0xFE)
{
m->volcmd = VOLCMD_VOLUME;
m->vol = (vol << 2) + 2;
}
if (p[2] != 0xFF)
{
UINT command = p[2] >> 4;
UINT param = p[2] & 0x0F;
switch(command)
{
case 0x00: command = CMD_PORTAMENTOUP; break;
case 0x01: command = CMD_PORTAMENTODOWN; break;
case 0x02: command = CMD_TONEPORTAMENTO; break;
case 0x03: command = CMD_MODCMDEX; param |= 0x50; break;
case 0x04: command = CMD_VIBRATO; param |= 0x40; break;
case 0x05: if (param) command = CMD_SPEED; else command = 0; param += 2; break;
case 0x06: if (param == 0) { command = CMD_PANNINGSLIDE; param = 0xFE; } else
if (param == 1) { command = CMD_PANNINGSLIDE; param = 0xEF; } else
command = 0;
break;
default: command = 0;
}
if (command)
{
if (command == CMD_SPEED) mspeed = NULL;
m->command = command;
m->param = param;
}
}
}
if ((!row) && (mspeed))
{
for (UINT i=0; i<8; i++) if (!mspeed[i].command)
{
mspeed[i].command = CMD_SPEED;
mspeed[i].param = pfh->tempolist[npat] + 2;
break;
}
}
}
dwMemPos += 0x600;
}
// Reading Samples
for (UINT n=1; n<=m_nSamples; n++)
{
UINT len = Ins[n].nLength;
if (dwMemPos >= dwMemLength) break;
if (len > 4) ReadSample(&Ins[n], RS_PCM8U, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
dwMemPos += len;
}
return TRUE;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.