[xiph-cvs] cvs commit: vorbis-tools/oggdec Makefile.am oggdec.c

Michael Smith msmith at xiph.org
Tue Jul 2 06:38:43 PDT 2002



msmith      02/07/02 06:38:43

  Modified:    .        Makefile.am configure.in
  Added:       oggdec   Makefile.am oggdec.c
  Log:
  oggdec. A _simple_, portable (hopefully) command line decoder (to wav and raw
  formats).

Revision  Changes    Path
1.11      +1 -1      vorbis-tools/Makefile.am

Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/Makefile.am,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- Makefile.am	2002/02/17 12:57:13	1.10
+++ Makefile.am	2002/07/02 13:38:41	1.11
@@ -2,7 +2,7 @@
 
 AUTOMAKE_OPTIONS = foreign dist-zip
 
-SUBDIRS = po intl include share oggenc ogg123 vorbiscomment vcut ogginfo debian win32
+SUBDIRS = po intl include share oggenc ogg123 vorbiscomment vcut oggdec ogginfo debian win32 
 
 EXTRA_DIST = README AUTHORS COPYING vorbis-tools.spec acinclude.m4
 

<p><p>1.39      +1 -1      vorbis-tools/configure.in

Index: configure.in
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/configure.in,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- configure.in	2002/05/02 14:19:27	1.38
+++ configure.in	2002/07/02 13:38:42	1.39
@@ -132,4 +132,4 @@
 AC_SUBST(I18N_CFLAGS)
 AC_SUBST(I18N_LIBS)
 
-AC_OUTPUT(Makefile intl/Makefile po/Makefile.in include/Makefile share/Makefile win32/Makefile oggenc/Makefile oggenc/man/Makefile ogg123/Makefile vorbiscomment/Makefile vcut/Makefile ogginfo/Makefile debian/Makefile)
+AC_OUTPUT(Makefile intl/Makefile po/Makefile.in include/Makefile share/Makefile win32/Makefile oggdec/Makefile oggenc/Makefile oggenc/man/Makefile ogg123/Makefile vorbiscomment/Makefile vcut/Makefile ogginfo/Makefile debian/Makefile)

<p><p>1.1                  vorbis-tools/oggdec/Makefile.am

Index: Makefile.am
===================================================================
## Process this file with automake to produce Makefile.in

AUTOMAKE_OPTIONS = foreign

datadir = @datadir@
localedir = $(datadir)/locale
DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@

bin_PROGRAMS = oggdec

INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ @SHARE_CFLAGS@

oggdec_LDADD = @VORBISFILE_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ @LIBICONV@ @SHARE_LIBS@
oggdec_DEPENDENCIES = @SHARE_LIBS@

oggdec_SOURCES = oggdec.c

debug:
        $(MAKE) all CFLAGS="@DEBUG@"

profile:
        $(MAKE) all CFLAGS="@PROFILE@"

<p><p>1.1                  vorbis-tools/oggdec/oggdec.c

Index: oggdec.c
===================================================================
/* OggDec
 *
 * This program is distributed under the GNU General Public License, version 2.
 * A copy of this license is included with this source.
 *
 * Copyright 2002, Michael Smith <msmith at labyrinth.net.au>
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <errno.h>
#include <string.h>

#include <vorbis/vorbisfile.h>

truct option long_options[] = {
    {"quiet", 0,0,'Q'},
    {"help",0,0,'h'},
    {"version", 0, 0, 'v'},
    {"bits", 1, 0, 'b'},
    {"endianness", 1, 0, 'e'},
    {"raw", 1, 0, 'R'},
    {"sign", 1, 0, 's'},
    {NULL,0,0,0}
};

#define VERSIONSTRING "OggDec 1.0\n"

tatic int quiet = 0;
static int bits = 16;
static int endian = 0;
static int raw = 0;
static int sign = 1;
unsigned char headbuf[44]; /* The whole buffer */

tatic void usage(void) {
    fprintf(stderr, "Usage: oggdec [flags] file1.ogg [file2.ogg ... fileN.ogg]\n"
                    "\n"
                    "Supported flags:\n"
                    " --quiet, -q      Quiet mode. No console output.\n"
                    " --help,  -h      Produce this help message.\n"
                    " --version, -v    Print out version number.\n"
                    " --bits, -b       Bit depth for output (8 and 16 supported)\n"
                    " --endianness, -e Output endianness for 16 bit output. 0 for\n"
                    "                  little endian (default), 1 for big endian\n"
                    " --sign, -s       Sign for output PCM, 0 for unsigned, 1 for\n"
                    "                  signed (default 1)\n"
                    " --raw, -R        Raw (headerless) output.\n"
            );

}

<p>static void parse_options(int argc, char **argv)
{
    int option_index = 1;
    int ret;

    while((ret = getopt_long(argc, argv, "Qhvb:e:r:s:", 
                    long_options, &option_index)) != -1)
    {
        switch(ret)
        {
            case 'Q':
                quiet = 1;
                break;
            case 'h':
                usage();
                exit(0);
                break;
            case 'v':
                fprintf(stderr, VERSIONSTRING);
                exit(0);
                break;
            case 's':
                sign = atoi(optarg);
                break;
            case 'b':
                bits = atoi(optarg);
                if(bits <= 8)
                    bits = 8;
                else
                    bits = 16;
                break;
            case 'e':
                endian = atoi(optarg);
                break;
            case 'R':
                raw = atoi(optarg);
                break;
            default:
                fprintf(stderr, "Internal error: Unrecognised argument\n");
                break;
        }
    }
}

#define WRITE_U32(buf, x) *(buf)     = (unsigned char)((x)&0xff);\
                          *((buf)+1) = (unsigned char)(((x)>>8)&0xff);\
                          *((buf)+2) = (unsigned char)(((x)>>16)&0xff);\
                          *((buf)+3) = (unsigned char)(((x)>>24)&0xff);

#define WRITE_U16(buf, x) *(buf)     = (unsigned char)((x)&0xff);\
                          *((buf)+1) = (unsigned char)(((x)>>8)&0xff);

/* Some of this based on ao/src/ao_wav.c */
int write_prelim_header(OggVorbis_File *vf, FILE *out, ogg_int64_t knownlength) {
    unsigned int size = 0x7fffffff;
    int channels = ov_info(vf,0)->channels;
    int samplerate = ov_info(vf,0)->rate;
    int bytespersec = channels*samplerate*bits/8;
    int align = channels*bits/8;
    int samplesize = bits;

    if(knownlength)
        size = (unsigned int)knownlength;

    memcpy(headbuf, "RIFF", 4);
    WRITE_U32(headbuf+4, size-8);
    memcpy(headbuf+8, "WAVE", 4);
    memcpy(headbuf+12, "fmt ", 4);
    WRITE_U32(headbuf+16, 16);
    WRITE_U16(headbuf+20, 1); /* format */
    WRITE_U16(headbuf+22, channels);
    WRITE_U32(headbuf+24, samplerate);
    WRITE_U32(headbuf+28, bytespersec);
    WRITE_U16(headbuf+32, align);
    WRITE_U16(headbuf+34, samplesize);
    memcpy(headbuf+36, "data", 4);
    WRITE_U32(headbuf+40, size - 44);

    if(fwrite(headbuf, 1, 44, out) != 44) {
        fprintf(stderr, "ERROR: Failed to write wav header: %s\n", strerror(errno));
        return 1;
    }

    return 0;
}

int rewrite_header(FILE *out, unsigned int written) 
{
    unsigned int length = written;

    length += 44;

    WRITE_U32(headbuf+4, length-8);
    WRITE_U32(headbuf+40, length-44);
    if(fseek(out, 0, SEEK_SET) != 0) {
        fprintf(stderr, "ERROR: Failed to seek on seekable file: %s\n", strerror(errno));
        return 1;
    }

    if(fwrite(headbuf, 1, 44, out) != 44) {
        fprintf(stderr, "ERROR: Failed to write wav header: %s\n", strerror(errno));
        return 1;
    }
    return 0;
}

tatic int decode_file(char *infile, char *outfile)
{
    FILE *in, *out=NULL;
    OggVorbis_File vf;
    int bs = 0;
    char buf[8192];
    int buflen = 8192;
    unsigned int written = 0;
    int ret;
    ogg_int64_t length = 0;
    ogg_int64_t done = 0;
    int size;
    int seekable = 0;
    int percent = 0;

    if(!infile) {
#ifdef _WIN32
        _setmode(_fileno(stdin), _O_BINARY);
#endif
        in = stdin;
    }
    else {
        in = fopen(infile, "rb");
        if(!in) {
            fprintf(stderr, "ERROR: Failed to open input file: %s\n", strerror(errno));
            return 1;
        }
    }

    if(!outfile) {
#ifdef _WIN32
        _setmode(_fileno(stdout), _O_BINARY);
#endif
        out = stdout;
    }
    else {
        out = fopen(outfile, "wb");
        if(!in) {
            fprintf(stderr, "ERROR: Failed to open output file: %s\n", strerror(errno));
            return 1;
        }
    }

    if(ov_open(in, &vf, NULL, 0) < 0) {
        fprintf(stderr, "ERROR: Failed to open input as vorbis\n");
        fclose(in);
        fclose(out);
        return 1;
    }

    if(ov_seekable(&vf)) {
        seekable = 1;
        length = ov_pcm_total(&vf, 0);
        size = bits/8 * ov_info(&vf, 0)->channels;
        if(!quiet)
            fprintf(stderr, "Decoding \"%s\" to \"%s\"\n", 
                    infile?infile:"standard input", 
                    outfile?outfile:"standard output");
    }

    if(!raw) {
        if(write_prelim_header(&vf, out, length)) {
            ov_clear(&vf);
            fclose(out);
            return 1;
        }
    }

    while((ret = ov_read(&vf, buf, buflen, endian, bits/8, sign, &bs)) != 0) {
        if(bs != 0) {
            fprintf(stderr, "Only one logical bitstream currently supported\n");
            break;
        }

        if(ret < 0 && !quiet) {
            fprintf(stderr, "Warning: hole in data\n");
            continue;
        }

        if(fwrite(buf, 1, ret, out) != ret) {
            fprintf(stderr, "Error writing to file: %s\n", strerror(errno));
            ov_clear(&vf);
            fclose(out);
            return 1;
        }

        written += ret;
        if(!quiet && seekable) {
            done += ret/size;
            if((double)done/(double)length * 200. > (double)percent) {
                percent = (double)done/(double)length *200;
                fprintf(stderr, "\r\t[%5.1f%%]", (double)percent/2.);
            }
        }
    }

    if(seekable && !quiet)
        fprintf(stderr, "\n");

    if(!raw && seekable)
        rewrite_header(out, written); /* We don't care if it fails, too late */

    ov_clear(&vf);

    fclose(out);
    return 0;
}

int main(int argc, char **argv)
{
    int i;

    if(argc == 1) {
        fprintf(stderr, VERSIONSTRING);
        usage();
        return 1;
    }

    parse_options(argc,argv);

    if(!quiet)
        fprintf(stderr, VERSIONSTRING);

    if(optind >= argc) {
        fprintf(stderr, "ERROR: No input files specified. Use -h for help\n");
        return 1;
    }

    if((argc - optind) % 2 != 0) {
        fprintf(stderr, "ERROR: incorrect usage. Usage message follows\n");
        usage();
        return 1;
    }

    for(i=optind; i < argc; i+= 2) {
        char *in, *out;
        if(!strcmp(argv[i], "-"))
            in = NULL;
        else
            in = argv[i];
        if(!strcmp(argv[i+1], "-"))
            out = NULL;
        else
            out = argv[i+1];

        if(decode_file(in,out))
            return 1;
    }

    return 0;
}
    

<p><p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list