added IT support
This commit is contained in:
parent
1ea433512e
commit
d426b678d2
8
Makefile
8
Makefile
|
@ -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"
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
Loading…
Reference in New Issue