aboutsummaryrefslogtreecommitdiff
path: root/miragextract.c
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2020-05-07 04:42:34 -0400
committerB. Watson <yalhcru@gmail.com>2020-05-07 04:42:34 -0400
commitf8a072dfc63065a134268fbc0a75a1eff02294fe (patch)
tree3f8b613fc3f44620a4f9352c7d6c909aedca3e34 /miragextract.c
parent1aba77a39dea8fe7372ca6406eb870e61e27941a (diff)
downloadmiragextract-f8a072dfc63065a134268fbc0a75a1eff02294fe.tar.gz
add a bunch of options, make sndfile work
Diffstat (limited to 'miragextract.c')
-rw-r--r--miragextract.c187
1 files changed, 153 insertions, 34 deletions
diff --git a/miragextract.c b/miragextract.c
index 2c16132..9d63476 100644
--- a/miragextract.c
+++ b/miragextract.c
@@ -1,27 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
#include <sndfile.h>
#include <mirage/mirage.h>
+#define VERSION "0.0.1"
+
const char *self;
static MirageContext *mirage = NULL;
static MirageDisc *disc = NULL;
static MirageSession *session = NULL;
static int output_track_number = 0;
-// static int tracks;
+int total_bytes = 0;
+
+char *imagefile = NULL;
+char *outfilebase = "track";
+char *outfmt = "wav";
+int want_track = 0; /* -1 = no tracks, 0 = all, 1-99 = just that one */
+double quality = 0.7l;
+int swap_bytes = 0;
void die(char *msg) {
fprintf(stderr, "%s: %s\n", self, msg);
exit(1);
}
-void extract_audio(MirageTrack *track) {
+const guint8 *apply_s_opt(const guint8 *buf, gint len) {
+ int i;
+ static guint8 newbuf[4096];
+
+ if(!swap_bytes) return buf;
+
+ for(i = 0; i < len; i += 2) {
+ newbuf[i] = buf[i + 1];
+ newbuf[i + 1] = buf[i];
+ }
+
+ return (const guint8 *)newbuf;
}
-void extract_track(int t) {
+void extract_track(int t, int extract) {
MirageTrack *track;
MirageSector *sector;
int sector_type, sec = 0;
@@ -29,12 +50,12 @@ void extract_track(int t) {
const guint8 *buf;
char *ext;
char outfile[4096];
- FILE *out;
- SNDFILE *sfout;
+ FILE *out = NULL;
+ SNDFILE *sfout = NULL;
struct SF_INFO sfi;
- double quality = 0.7l;
+ int bytes = 0;
- output_track_number++;
+ printf(" Track %d (%d): ", t + 1, output_track_number);
if(!(track = mirage_session_get_track_by_index(session, t, NULL)))
die("can't read track");
@@ -45,14 +66,17 @@ void extract_track(int t) {
case MIRAGE_SECTOR_MODE1:
case MIRAGE_SECTOR_MODE2_FORM1:
// printf("Track %d is data, extracting\n", output_track_number);
+ printf("data, ");
ext = "iso";
break;
case MIRAGE_SECTOR_AUDIO:
// printf("Track %d is audio, extracting\n", output_track_number);
- ext = "ogg";
+ printf("audio, ");
+ ext = outfmt;
break;
default:
// printf("Track %d is unsupported type, dumping raw\n", output_track_number);
+ printf("<unknown>, ");
ext = "raw";
break;
}
@@ -64,56 +88,142 @@ void extract_track(int t) {
printf("got %d bytes per sector\n", len);
*/
- sprintf(outfile, "track%02d.%s", output_track_number, ext);
-
- if(sector_type == MIRAGE_SECTOR_AUDIO) {
- sfi.samplerate = 44100;
- sfi.channels = 2;
- sfi.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
- if(!(sfout = sf_open(outfile, SFM_WRITE, &sfi)))
- die("can't open output audio file");
- sf_command(sfout, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof(double));
- } else {
- if(!(out = fopen(outfile, "wb"))) {
- die("can't open output file");
+ sprintf(outfile, "%s%02d.%s", outfilebase, output_track_number, ext);
+
+ if(extract) {
+ if((sector_type == MIRAGE_SECTOR_AUDIO) && (outfmt[0] != 'c')) {
+ sfi.samplerate = 44100;
+ sfi.channels = 2;
+
+ switch(outfmt[0]) {
+ case 'o':
+ sfi.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
+ break;
+ case 'f':
+ sfi.format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
+ break;
+ case 'w':
+ sfi.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+ break;
+ }
+
+ if(!(sfout = sf_open(outfile, SFM_WRITE, &sfi)))
+ die("can't open output audio file");
+ sf_command(sfout, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof(double));
+
+ } else {
+ if(!(out = fopen(outfile, "wb"))) {
+ die("can't open output file");
+ }
}
}
sec = mirage_track_get_track_start(track);
while((sector = mirage_track_get_sector(track, sec++, 0, NULL))) {
mirage_sector_get_data(sector, &buf, &len, NULL);
- if(sector_type == MIRAGE_SECTOR_AUDIO) {
- /* TODO: find out what happens on big-endian platform! */
- sf_write_short(sfout, (const short *)buf, len / 2);
- } else {
- fwrite(buf, len, 1, out);
+ bytes += len;
+ if(extract) {
+ if(sfout) {
+ sf_write_short(sfout, (const short *)apply_s_opt(buf, len), len / 2);
+ } else {
+ fwrite(buf, len, 1, out);
+ }
}
g_object_unref(sector);
}
- if(sector_type == MIRAGE_SECTOR_AUDIO) {
- sf_close(sfout);
- } else {
- fclose(out);
- }
+ if(sfout) sf_close(sfout);
+ if(out) fclose(out);
- printf("read %d sectors\n", sec);
+ printf("%d bytes (%d sectors)\n", bytes, sec);
+ if(extract) printf(" Extracted to %s\n", outfile);
+ total_bytes += bytes;
return;
}
+void usage(int exit_code) {
+ fprintf(exit_code ? stderr : stdout,
+ "miragextract v" VERSION " by B. Watson, WTFPL\n"
+ "Usage: %s [-l] [-s] [-t track] [-b base] [-f fmt ] [-q quality ] image-file\n"
+ "See man page for details\n", self);
+ exit(exit_code);
+}
+
+void parse_args(int argc, char **argv) {
+ if(argc == 1) usage(0);
+ if(argc > 1 && strcmp(argv[1], "--help") == 0) usage(0);
+
+ while(++argv, --argc) {
+ if(argv[0][0] == '-') {
+ char *nextarg = argv[1];
+ switch(argv[0][1]) {
+ case 'l':
+ want_track = -1;
+ break;
+ case 's':
+ swap_bytes = 1;
+ break;
+ case 't':
+ if(nextarg) {
+ argv++, argc--;
+ want_track = atoi(nextarg);
+ if(want_track < 1 || want_track > 99)
+ die("invalid track number for -t (must be 1-99)");
+ } else
+ die("-t option requires track argument");
+ break;
+ case 'b':
+ if(nextarg) {
+ argv++, argc--;
+ outfilebase = nextarg;
+ } else
+ die("-b option requires base filename argument");
+ break;
+ case 'f':
+ if(nextarg) {
+ argv++, argc--;
+ outfmt = nextarg;
+ } else
+ die("-f option requires format argument");
+ break;
+ case 'q':
+ if(nextarg) {
+ argv++, argc--;
+ quality = (double)atoi(nextarg) / 10.0l;
+ if(quality < 0.0l || quality > 1.0l)
+ die("invalid quality for -q (must be 1-10)");
+ } else
+ die("-t option requires track argument");
+ break;
+ default:
+ die("unrecognized option");
+ break;
+ }
+ } else if(imagefile) {
+ die("too many arguments on command line");
+ } else {
+ imagefile = *argv;
+ }
+ }
+
+ if(!imagefile) die("missing image file argument");
+}
+
int main(int argc, char **argv) {
self = argv[0];
gchar *fn[2];
int s, t;
+ parse_args(argc, argv);
+
if(!((mirage = g_object_new(MIRAGE_TYPE_CONTEXT, NULL))))
die("couldn't get mirage context");
if(!mirage_initialize(NULL))
die("couldn't initialize libmirage");
- fn[0] = "test.cue";
+ fn[0] = imagefile;
fn[1] = NULL;
if(!(disc = mirage_context_load_image(mirage, fn, NULL)))
@@ -123,12 +233,21 @@ int main(int argc, char **argv) {
if(!(session = mirage_disc_get_session_by_index(disc, s, NULL)))
die("couldn't read session");
+ printf("Session %d\n", s + 1);
+
for(t = 0; t < mirage_session_get_number_of_tracks(session); t++) {
- printf("session %d, track %d\n", s, t);
- extract_track(t);
+ int extract = 0;
+ output_track_number++;
+
+ // printf("session %d, track %d\n", s + 1, t + 1);
+ if(want_track == 0 || want_track == output_track_number)
+ extract = 1;
+
+ extract_track(t, extract);
}
}
mirage_shutdown(NULL);
+ printf("Total size: %d bytes\n", total_bytes);
return 0;
}