added MOD support

This commit is contained in:
Mathias Panzenböck 2012-12-29 01:07:41 +01:00
parent ed3e8de46f
commit 5de2ff6e6b
5 changed files with 176 additions and 9 deletions

View File

@ -1,6 +1,13 @@
PREFIX=/usr/local
BUILDDIR=build
OBJ=$(BUILDDIR)/audioextract.o $(BUILDDIR)/wave.o $(BUILDDIR)/ogg.o $(BUILDDIR)/mpeg.o $(BUILDDIR)/id3.o $(BUILDDIR)/midi.o
OBJ=\
$(BUILDDIR)/audioextract.o \
$(BUILDDIR)/wave.o \
$(BUILDDIR)/ogg.o \
$(BUILDDIR)/mpeg.o \
$(BUILDDIR)/id3.o \
$(BUILDDIR)/midi.o \
$(BUILDDIR)/mod.o
CC=gcc
CFLAGS=-Wall -std=gnu99 -O2 -fmessage-length=0 -g
BIN=$(BUILDDIR)/audioextract
@ -12,7 +19,7 @@ all: $(BIN)
$(BIN): $(OBJ)
$(CC) $(CFLAGS) $(OBJ) -o $@
$(BUILDDIR)/audioextract.o: audioextract.c audioextract.h ogg.h wave.h mpeg.h id3.h midi.h
$(BUILDDIR)/audioextract.o: audioextract.c audioextract.h ogg.h wave.h mpeg.h id3.h midi.h mod.h
$(CC) $(CFLAGS) $< -o $@ -c
$(BUILDDIR)/wave.o: wave.c audioextract.h wave.h
@ -30,6 +37,9 @@ $(BUILDDIR)/id3.o: id3.c audioextract.h id3.h
$(BUILDDIR)/midi.o: midi.c audioextract.h midi.h
$(CC) $(CFLAGS) $< -o $@ -c
$(BUILDDIR)/mod.o: mod.c audioextract.h mod.h
$(CC) $(CFLAGS) $< -o $@ -c
install: all
install -s -D $(BIN) "$(PREFIX)/bin/audioextract"

View File

@ -35,10 +35,11 @@ using the `--min-size` one can hopefully extract only real MPEG files.
-f, --formats=FORMATS Comma separated list of formats (file magics) to extract.
Supported formats:
all all supported formats
default the default set of formats (AIFF, ID3v2, Ogg, RIFF, MIDI)
default the default set of formats (AIFF, ID3v2, Ogg, RIFF, MIDI, MOD)
aiff big-endian (Apple) wave files
id3v2 MPEG files with ID3v2 tags at the start
midi MIDI files
mod MOD files
mpeg any MPEG files (e.g. MP3)
ogg Ogg files (Vorbis, FLAC, Opus, Theora, etc.)
riff little-endian (Windows) wave files
@ -56,7 +57,7 @@ using the `--min-size` one can hopefully extract only real MPEG files.
removed from the set of formats to extract. E.g. extract
everything except wave files:
audioextract --formats=all,-wave data.bin
./build/audioextract --formats=all,-wave data.bin
-o, --output=DIR Directory where extracted files should be written. (default: ".")
-m, --min-size=SIZE Minumum size of extracted files (skip smaller). (default: 0)

View File

@ -17,6 +17,7 @@
#include "mpeg.h"
#include "id3.h"
#include "midi.h"
#include "mod.h"
enum fileformat {
NONE = 0,
@ -26,13 +27,16 @@ enum fileformat {
MPEG = 8,
ID3v2 = 16,
MIDI = 32,
MOD = 64,
// TODO:
// MOD = 64,
// S3M = 128,
// IT = 256,
// XM = 512,
};
#define ALL_FORMATS (OGG | RIFF | AIFF | MPEG | ID3v2 | MIDI | MOD)
#define DEFAULT_FORMATS (OGG | RIFF | AIFF | ID3v2 | MIDI | MOD)
int usage(int argc, char **argv)
{
const char *progname = argc <= 0 ? "audioextract" : argv[0];
@ -48,10 +52,11 @@ int usage(int argc, char **argv)
" -f, --formats=FORMATS Comma separated list of formats (file magics) to extract.\n"
" Supported formats:\n"
" all all supported formats\n"
" default the default set of formats (AIFF, ID3v2, Ogg, RIFF, MIDI)\n"
" default the default set of formats (AIFF, ID3v2, Ogg, RIFF, MIDI, MOD)\n"
" aiff big-endian (Apple) wave files\n"
" id3v2 MPEG files with ID3v2 tags at the start\n"
" midi MIDI files\n"
" mod MOD files\n"
" mpeg any MPEG files (e.g. MP3)\n"
" ogg Ogg files (Vorbis, FLAC, Opus, Theora, etc.)\n"
" riff little-endian (Windows) wave files\n"
@ -127,6 +132,15 @@ const unsigned char *findmagic(const unsigned char *start, const unsigned char *
*format = MPEG;
return start;
}
else if (formats & MOD && (size_t)(end - start) >= MOD_MAGIC_OFFSET)
{
uint32_t modmagic = MAGIC(start + MOD_MAGIC_OFFSET);
if (IS_MOD_MAGIC(modmagic))
{
*format = MOD;
return start;
}
}
}
return NULL;
@ -345,6 +359,15 @@ int extract(const char *filepath, const char *outdir, size_t minsize, size_t max
else ++ ptr;
break;
case MOD:
if (mod_isfile(ptr, end, &length))
{
WRITE_FILE(ptr, length, "mod");
ptr += length;
}
else ++ ptr;
break;
case NONE:
++ ptr;
break;
@ -421,13 +444,17 @@ int parse_formats(const char *formats)
{
mask = MIDI;
}
else if (strncasecmp("mod", start, len) == 0)
{
mask = MOD;
}
else if (strncasecmp("all", start, len) == 0)
{
mask = OGG | RIFF | AIFF | MPEG | ID3v2 | MIDI;
mask = ALL_FORMATS;
}
else if (strncasecmp("default", start, len) == 0)
{
mask = OGG | RIFF | AIFF | ID3v2 | MIDI;
mask = DEFAULT_FORMATS;
}
else if (len != 0)
{
@ -468,7 +495,7 @@ int main(int argc, char **argv)
size_t numfiles = 0;
size_t minsize = 0;
size_t maxsize = (size_t)-1;
int formats = OGG | RIFF | AIFF | ID3v2 | MIDI;
int formats = DEFAULT_FORMATS;
const char *outdir = ".";
long long tmp = 0;
size_t size = 0;

49
mod.c Normal file
View File

@ -0,0 +1,49 @@
#include "mod.h"
int mod_isfile(const unsigned char *start, const unsigned char *end, size_t *lengthptr)
{
size_t input_len = (size_t)(end - start);
size_t length = MOD_MAGIC_OFFSET + 4;
size_t channels = 0;
size_t patterns = 0;
if (input_len < length)
return 0;
for (const unsigned char *ptr = start + 20, *sample_end = ptr + 31*30;
ptr < sample_end; ptr += 30)
{
length += (size_t)be16toh(*(const uint16_t*)(ptr + 22)) << 1;
}
uint8_t song_length = start[950];
if (song_length > 0x80)
return 0;
for (const unsigned char *ptr = start + 952, *pattern_table_end = ptr + 128;
ptr < pattern_table_end; ++ ptr)
{
if (*ptr > patterns) patterns = *ptr;
}
++ patterns;
uint32_t magic = MAGIC(start + MOD_MAGIC_OFFSET);
if (IS_MOD_4CH_MAGIC(magic)) channels = 4;
else if (IS_MOD_5CH_MAGIC(magic)) channels = 5;
else if (IS_MOD_6CH_MAGIC(magic)) channels = 6;
else if (IS_MOD_7CH_MAGIC(magic)) channels = 7;
else if (IS_MOD_8CH_MAGIC(magic)) channels = 8;
else if (IS_MOD_16CH_MAGIC(magic)) channels = 16;
else if (IS_MOD_32CH_MAGIC(magic)) channels = 32;
else
return 0;
length += patterns * channels * 64 * 4;
if (input_len < length)
return 0;
if (lengthptr) *lengthptr = length;
return 1;
}

80
mod.h Normal file
View File

@ -0,0 +1,80 @@
#ifndef AUDIOEXTRACT_MOD_H__
#define AUDIOEXTRACT_MOD_H__
#include "audioextract.h"
#define MOD_4CH_MAGIC1 MAGIC("M.K.")
#define MOD_4CH_MAGIC2 MAGIC("M!K!")
#define MOD_4CH_MAGIC3 MAGIC("M&K!")
#define MOD_4CH_MAGIC4 MAGIC("N.T.")
#define MOD_4CH_MAGIC5 MAGIC("FLT4")
#define MOD_4CH_MAGIC6 MAGIC("4CHN")
#define MOD_4CH_MAGIC7 MAGIC("TDZ4")
#define MOD_5CH_MAGIC1 MAGIC("TDZ5") /* not sure if this exists */
#define MOD_6CH_MAGIC1 MAGIC("6CHN")
#define MOD_6CH_MAGIC2 MAGIC("TDZ6")
#define MOD_7CH_MAGIC1 MAGIC("TDZ7") /* not sure if this exists */
#define MOD_8CH_MAGIC1 MAGIC("8CHN")
#define MOD_8CH_MAGIC2 MAGIC("TDZ8")
#define MOD_8CH_MAGIC3 MAGIC("FLT8")
#define MOD_8CH_MAGIC4 MAGIC("CD81")
#define MOD_8CH_MAGIC5 MAGIC("OKTA")
#define MOD_16CH_MAGIC1 MAGIC("16CH")
#define MOD_16CH_MAGIC2 MAGIC("16CN")
#define MOD_32CH_MAGIC1 MAGIC("32CH")
#define MOD_32CH_MAGIC2 MAGIC("32CN")
#define IS_MOD_MAGIC(magic) \
(IS_MOD_4CH_MAGIC(magic) || \
IS_MOD_5CH_MAGIC(magic) || \
IS_MOD_6CH_MAGIC(magic) || \
IS_MOD_7CH_MAGIC(magic) || \
IS_MOD_8CH_MAGIC(magic) || \
IS_MOD_16CH_MAGIC(magic) || \
IS_MOD_32CH_MAGIC(magic))
#define IS_MOD_4CH_MAGIC(magic) \
(((magic) == MOD_4CH_MAGIC1) || \
((magic) == MOD_4CH_MAGIC2) || \
((magic) == MOD_4CH_MAGIC3) || \
((magic) == MOD_4CH_MAGIC4) || \
((magic) == MOD_4CH_MAGIC5) || \
((magic) == MOD_4CH_MAGIC6) || \
((magic) == MOD_4CH_MAGIC7))
#define IS_MOD_5CH_MAGIC(magic) \
((magic) == MOD_5CH_MAGIC1)
#define IS_MOD_6CH_MAGIC(magic) \
(((magic) == MOD_6CH_MAGIC1) || \
((magic) == MOD_6CH_MAGIC2))
#define IS_MOD_7CH_MAGIC(magic) \
((magic) == MOD_7CH_MAGIC1)
#define IS_MOD_8CH_MAGIC(magic) \
(((magic) == MOD_8CH_MAGIC1) || \
((magic) == MOD_8CH_MAGIC2) || \
((magic) == MOD_8CH_MAGIC3) || \
((magic) == MOD_8CH_MAGIC4) || \
((magic) == MOD_8CH_MAGIC5))
#define IS_MOD_16CH_MAGIC(magic) \
(((magic) == MOD_16CH_MAGIC1) || \
((magic) == MOD_16CH_MAGIC2))
#define IS_MOD_32CH_MAGIC(magic) \
(((magic) == MOD_32CH_MAGIC1) || \
((magic) == MOD_32CH_MAGIC2))
#define MOD_MAGIC_OFFSET 1080
int mod_isfile(const unsigned char *start, const unsigned char *end, size_t *lengthptr);
#endif /* AUDIOEXTRACT_MOD_H__ */