added MOD support
This commit is contained in:
parent
ed3e8de46f
commit
5de2ff6e6b
14
Makefile
14
Makefile
|
@ -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"
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
Loading…
Reference in New Issue