added IT support

This commit is contained in:
Mathias Panzenböck 2012-12-29 06:31:30 +01:00
parent 1ea433512e
commit d426b678d2
5 changed files with 148 additions and 8 deletions

View File

@ -8,7 +8,8 @@ OBJ=\
$(BUILDDIR)/id3.o \
$(BUILDDIR)/midi.o \
$(BUILDDIR)/mod.o \
$(BUILDDIR)/s3m.o
$(BUILDDIR)/s3m.o \
$(BUILDDIR)/it.o
CC=gcc
CFLAGS=-Wall -std=gnu99 -O2 -fmessage-length=0 -g
BIN=$(BUILDDIR)/audioextract
@ -20,7 +21,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 mod.h s3m.h
$(BUILDDIR)/audioextract.o: audioextract.c audioextract.h ogg.h wave.h mpeg.h id3.h midi.h mod.h s3m.h it.h
$(CC) $(CFLAGS) $< -o $@ -c
$(BUILDDIR)/wave.o: wave.c audioextract.h wave.h
@ -44,6 +45,9 @@ $(BUILDDIR)/mod.o: mod.c audioextract.h mod.h
$(BUILDDIR)/s3m.o: s3m.c audioextract.h s3m.h
$(CC) $(CFLAGS) $< -o $@ -c
$(BUILDDIR)/it.o: it.c audioextract.h it.h
$(CC) $(CFLAGS) $< -o $@ -c
install: all
install -s -D $(BIN) "$(PREFIX)/bin/audioextract"

View File

@ -38,11 +38,14 @@ using the `--min-size` one can hopefully extract only real MPEG files.
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
it ImpulseTracker files
midi MIDI files
mod MOD files
mod FastTracker files
mpeg any MPEG files (e.g. MP3)
ogg Ogg files (Vorbis, FLAC, Opus, Theora, etc.)
riff little-endian (Windows) wave files
s3m ScreamTracker files
tracker all tracker files (MOD, S3M, IT)
wave both RIFF and AIFF wave files
WARNING: Because MPEG files do not have a nice file magic, using
@ -57,7 +60,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:
./build/audioextract --formats=all,-wave data.bin
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

@ -19,6 +19,7 @@
#include "midi.h"
#include "mod.h"
#include "s3m.h"
#include "it.h"
enum fileformat {
NONE = 0,
@ -30,13 +31,14 @@ enum fileformat {
MIDI = 32,
MOD = 64,
S3M = 128,
IT = 256,
// TODO:
// IT = 256,
// XM = 512,
};
#define ALL_FORMATS (OGG | RIFF | AIFF | MPEG | ID3v2 | MIDI | MOD | S3M)
#define DEFAULT_FORMATS (OGG | RIFF | AIFF | ID3v2 | MIDI | MOD | S3M)
#define ALL_FORMATS (OGG | RIFF | AIFF | MPEG | ID3v2 | MIDI | MOD | S3M | IT)
#define DEFAULT_FORMATS (OGG | RIFF | AIFF | ID3v2 | MIDI | MOD | S3M | IT)
#define TRACKER_FORMATS (MOD | S3M | IT)
int usage(int argc, char **argv)
{
@ -56,11 +58,14 @@ int usage(int argc, char **argv)
" 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"
" it ImpulseTracker files\n"
" midi MIDI files\n"
" mod MOD files\n"
" mod FastTracker 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"
" s3m ScreamTracker files\n"
" tracker all tracker files (MOD, S3M, IT)\n"
" wave both RIFF and AIFF wave files\n"
"\n"
" WARNING: Because MPEG files do not have a nice file magic, using\n"
@ -128,6 +133,11 @@ const unsigned char *findmagic(const unsigned char *start, const unsigned char *
*format = ID3v2;
return start;
}
else if (formats & IT && magic == IT_MAGIC)
{
*format = IT;
return start;
}
else if (formats & MPEG && IS_MPEG_MAGIC(start))
{
*format = MPEG;
@ -388,6 +398,15 @@ int extract(const char *filepath, const char *outdir, size_t minsize, size_t max
else ++ ptr;
break;
case IT:
if (it_isfile(ptr, end, &length))
{
WRITE_FILE(ptr, length, "it");
ptr += length;
}
else ++ ptr;
break;
case NONE:
++ ptr;
break;
@ -472,6 +491,14 @@ int parse_formats(const char *formats)
{
mask = S3M;
}
else if (strncasecmp("it", start, len) == 0)
{
mask = IT;
}
else if (strncasecmp("tracker", start, len) == 0)
{
mask = TRACKER_FORMATS;
}
else if (strncasecmp("all", start, len) == 0)
{
mask = ALL_FORMATS;

90
it.c Normal file
View File

@ -0,0 +1,90 @@
#include "it.h"
int it_isfile(const unsigned char *start, const unsigned char *end, size_t *lengthptr)
{
size_t input_len = (size_t)(end - start);
if (input_len < IT_HEADER_SIZE)
return 0;
if (MAGIC(start) != IT_MAGIC)
return 0;
uint16_t orders = le16toh(*(uint16_t *)(start + 0x20));
uint16_t instruments = le16toh(*(uint16_t *)(start + 0x22));
uint16_t samples = le16toh(*(uint16_t *)(start + 0x24));
uint16_t patterns = le16toh(*(uint16_t *)(start + 0x26));
size_t length = IT_HEADER_SIZE + orders + instruments * 4 + samples * 4 + patterns * 4;
if (input_len < length)
return 0;
#define UPDATE_LENGTH(len) \
{ \
size_t _len = (len); \
if (_len > length) \
{ \
length = _len; \
if (input_len < length) \
return 0; \
} \
}
/* scan instruments */
for (const uint32_t *para = (const uint32_t *)(start + IT_HEADER_SIZE + orders),
*para_end = para + instruments;
para < para_end; ++ para)
{
size_t off = (size_t)le32toh(*para);
UPDATE_LENGTH(off + IT_INSTRUMENT_SIZE);
}
/* scan samples */
for (const uint32_t *para = (const uint32_t *)(start + IT_HEADER_SIZE + orders + instruments * 4),
*para_end = para + samples;
para < para_end; ++ para)
{
size_t off = (size_t)le32toh(*para);
const unsigned char *ptr = start + off;
UPDATE_LENGTH(off + IT_SAMPLE_HEADER_SIZE);
if (MAGIC(ptr) != IT_SAMPLE_MAGIC)
continue;
uint32_t sample_length = le32toh(*(uint32_t *)(ptr + 0x30));
uint32_t sample_pointer = le32toh(*(uint32_t *)(ptr + 0x48));
if (sample_length && sample_pointer)
{
size_t sample_end = sample_pointer + sample_length;
// there are some IT files out there with truncated samples:
if (sample_end > input_len) sample_end = input_len;
if (sample_end > length) length = sample_end;
}
}
/* scan patterns */
for (const uint32_t *para = (const uint32_t *)(start + IT_HEADER_SIZE + orders + instruments * 4 + samples * 4),
*para_end = para + patterns;
para < para_end; ++ para)
{
size_t off = (size_t)le32toh(*para);
const unsigned char *ptr = start + off;
UPDATE_LENGTH(off + IT_PATTERN_HEADER_SIZE);
uint16_t pattern_length = le32toh(*(uint16_t *)ptr);
size_t pattern_end = off + IT_PATTERN_HEADER_SIZE + pattern_length;
// there are some IT files out there with truncated patterns:
if (pattern_end > input_len) pattern_end = input_len;
if (pattern_end > length) length = pattern_end;
}
if (lengthptr) *lengthptr = length;
return 1;
}

16
it.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef AUDIOEXTRACT_IT_H__
#define AUDIOEXTRACT_IT_H__
#include "audioextract.h"
#define IT_MAGIC MAGIC("IMPM")
#define IT_INSTRUMENT_MAGIC MAGIC("IMPI")
#define IT_SAMPLE_MAGIC MAGIC("IMPS")
#define IT_HEADER_SIZE 192
#define IT_INSTRUMENT_SIZE 554
#define IT_SAMPLE_HEADER_SIZE 80
#define IT_PATTERN_HEADER_SIZE 4
int it_isfile(const unsigned char *start, const unsigned char *end, size_t *lengthptr);
#endif /* AUDIOEXTRACT_IT_H__ */