~ubuntu-branches/ubuntu/gutsy/vorbis-tools/gutsy

« back to all changes in this revision

Viewing changes to oggdec/oggdec.c

  • Committer: Bazaar Package Importer
  • Author(s): Jesus Climent
  • Date: 2005-04-10 09:22:24 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050410092224-xtukpa3qghghhjje
Tags: 1.0.1-1.3
* Authorized NMU.
* Modified alsa to mention alsa09 (although the device might be nowadays
  alsa, back, since alsa1.0 has been already released). (Closes: #258286)
* Modified the manpage/help message for vorbiscomment to make it a bit more
  userfiendly: Closes: #252531.
* Added oggdec to the long description field, so that it triggers apt-cache
  searches: Closes: #274894.
* Typos in manpages: Closes: #302150.
* Escaped dashes in manpage: Closes: #264365.
* Quiet option is actually with -Q, not -q (Closes: #211289) Reported
  upstream but patched for Debian.
* Change input.wav with inputfile, since we accept flac-formated files:
  Closes: #262509.
* Translation bits:
  * Updated translation hu.po: Closes: #272037.
  * French translation correction: Encodage -> Codage (Closes: #248431).
  * debian/rules: remove .gmo's to avoid clash with uploaded tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* OggDec
 
2
 *
 
3
 * This program is distributed under the GNU General Public License, version 2.
 
4
 * A copy of this license is included with this source.
 
5
 *
 
6
 * Copyright 2002, Michael Smith <msmith@xiph.org>
 
7
 *
 
8
 */
 
9
 
 
10
#include <stdlib.h>
 
11
#include <stdio.h>
 
12
#include <getopt.h>
 
13
#include <errno.h>
 
14
#include <string.h>
 
15
 
 
16
#if defined(_WIN32) || defined(__EMX__) || defined(__WATCOMC__)
 
17
#include <fcntl.h>
 
18
#include <io.h>
 
19
#endif
 
20
 
 
21
#include <vorbis/vorbisfile.h>
 
22
 
 
23
struct option long_options[] = {
 
24
    {"quiet", 0,0,'Q'},
 
25
    {"help",0,0,'h'},
 
26
    {"version", 0, 0, 'v'},
 
27
    {"bits", 1, 0, 'b'},
 
28
    {"endianness", 1, 0, 'e'},
 
29
    {"raw", 0, 0, 'R'},
 
30
    {"sign", 1, 0, 's'},
 
31
    {"output", 1, 0, 'o'},
 
32
    {NULL,0,0,0}
 
33
};
 
34
 
 
35
#define VERSIONSTRING "OggDec 1.0.1\n"
 
36
 
 
37
static int quiet = 0;
 
38
static int bits = 16;
 
39
static int endian = 0;
 
40
static int raw = 0;
 
41
static int sign = 1;
 
42
unsigned char headbuf[44]; /* The whole buffer */
 
43
char *outfilename = NULL;
 
44
 
 
45
static void usage(void) {
 
46
    fprintf(stderr, "Usage: oggdec [flags] file1.ogg [file2.ogg ... fileN.ogg]\n"
 
47
                    "\n"
 
48
                    "Supported flags:\n"
 
49
                    " --quiet, -Q      Quiet mode. No console output.\n"
 
50
                    " --help,  -h      Produce this help message.\n"
 
51
                    " --version, -v    Print out version number.\n"
 
52
                    " --bits, -b       Bit depth for output (8 and 16 supported)\n"
 
53
                    " --endianness, -e Output endianness for 16 bit output. 0 for\n"
 
54
                    "                  little endian (default), 1 for big endian\n"
 
55
                    " --sign, -s       Sign for output PCM, 0 for unsigned, 1 for\n"
 
56
                    "                  signed (default 1)\n"
 
57
                    " --raw, -R        Raw (headerless) output.\n"
 
58
                    " --output, -o     Output to given filename. May only be used\n"
 
59
                    "                  if there is only one input file\n"
 
60
 
 
61
            );
 
62
 
 
63
}
 
64
 
 
65
 
 
66
static void parse_options(int argc, char **argv)
 
67
{
 
68
    int option_index = 1;
 
69
    int ret;
 
70
 
 
71
    while((ret = getopt_long(argc, argv, "Qhvb:e:Rs:o:", 
 
72
                    long_options, &option_index)) != -1)
 
73
    {
 
74
        switch(ret)
 
75
        {
 
76
            case 'Q':
 
77
                quiet = 1;
 
78
                break;
 
79
            case 'h':
 
80
                usage();
 
81
                exit(0);
 
82
                break;
 
83
            case 'v':
 
84
                fprintf(stderr, VERSIONSTRING);
 
85
                exit(0);
 
86
                break;
 
87
            case 's':
 
88
                sign = atoi(optarg);
 
89
                break;
 
90
            case 'b':
 
91
                bits = atoi(optarg);
 
92
                if(bits <= 8)
 
93
                    bits = 8;
 
94
                else
 
95
                    bits = 16;
 
96
                break;
 
97
            case 'e':
 
98
                endian = atoi(optarg);
 
99
                break;
 
100
            case 'o':
 
101
                outfilename = strdup(optarg);
 
102
                break;
 
103
            case 'R':
 
104
                raw = 1;
 
105
                break;
 
106
            default:
 
107
                fprintf(stderr, "Internal error: Unrecognised argument\n");
 
108
                break;
 
109
        }
 
110
    }
 
111
}
 
112
 
 
113
#define WRITE_U32(buf, x) *(buf)     = (unsigned char)((x)&0xff);\
 
114
                          *((buf)+1) = (unsigned char)(((x)>>8)&0xff);\
 
115
                          *((buf)+2) = (unsigned char)(((x)>>16)&0xff);\
 
116
                          *((buf)+3) = (unsigned char)(((x)>>24)&0xff);
 
117
 
 
118
#define WRITE_U16(buf, x) *(buf)     = (unsigned char)((x)&0xff);\
 
119
                          *((buf)+1) = (unsigned char)(((x)>>8)&0xff);
 
120
 
 
121
/* Some of this based on ao/src/ao_wav.c */
 
122
int write_prelim_header(OggVorbis_File *vf, FILE *out, ogg_int64_t knownlength) {
 
123
    unsigned int size = 0x7fffffff;
 
124
    int channels = ov_info(vf,0)->channels;
 
125
    int samplerate = ov_info(vf,0)->rate;
 
126
    int bytespersec = channels*samplerate*bits/8;
 
127
    int align = channels*bits/8;
 
128
    int samplesize = bits;
 
129
 
 
130
    if(knownlength && knownlength*bits/8*channels < size)
 
131
        size = (unsigned int)(knownlength*bits/8*channels+44) ;
 
132
 
 
133
    memcpy(headbuf, "RIFF", 4);
 
134
    WRITE_U32(headbuf+4, size-8);
 
135
    memcpy(headbuf+8, "WAVE", 4);
 
136
    memcpy(headbuf+12, "fmt ", 4);
 
137
    WRITE_U32(headbuf+16, 16);
 
138
    WRITE_U16(headbuf+20, 1); /* format */
 
139
    WRITE_U16(headbuf+22, channels);
 
140
    WRITE_U32(headbuf+24, samplerate);
 
141
    WRITE_U32(headbuf+28, bytespersec);
 
142
    WRITE_U16(headbuf+32, align);
 
143
    WRITE_U16(headbuf+34, samplesize);
 
144
    memcpy(headbuf+36, "data", 4);
 
145
    WRITE_U32(headbuf+40, size - 44);
 
146
 
 
147
    if(fwrite(headbuf, 1, 44, out) != 44) {
 
148
        fprintf(stderr, "ERROR: Failed to write wav header: %s\n", strerror(errno));
 
149
        return 1;
 
150
    }
 
151
 
 
152
    return 0;
 
153
}
 
154
 
 
155
int rewrite_header(FILE *out, unsigned int written) 
 
156
{
 
157
    unsigned int length = written;
 
158
 
 
159
    length += 44;
 
160
 
 
161
    WRITE_U32(headbuf+4, length-8);
 
162
    WRITE_U32(headbuf+40, length-44);
 
163
    if(fseek(out, 0, SEEK_SET) != 0)
 
164
        return 1;
 
165
 
 
166
    if(fwrite(headbuf, 1, 44, out) != 44) {
 
167
        fprintf(stderr, "ERROR: Failed to write wav header: %s\n", strerror(errno));
 
168
        return 1;
 
169
    }
 
170
    return 0;
 
171
}
 
172
 
 
173
static int decode_file(char *infile, char *outfile)
 
174
{
 
175
    FILE *in, *out=NULL;
 
176
    OggVorbis_File vf;
 
177
    int bs = 0;
 
178
    char buf[8192];
 
179
    int buflen = 8192;
 
180
    unsigned int written = 0;
 
181
    int ret;
 
182
    ogg_int64_t length = 0;
 
183
    ogg_int64_t done = 0;
 
184
    int size;
 
185
    int seekable = 0;
 
186
    int percent = 0;
 
187
 
 
188
    if(!infile) {
 
189
#ifdef __BORLANDC__
 
190
        setmode(fileno(stdin), O_BINARY);
 
191
#elif _WIN32
 
192
        _setmode(_fileno(stdin), _O_BINARY);
 
193
#endif
 
194
        in = stdin;
 
195
    }
 
196
    else {
 
197
        in = fopen(infile, "rb");
 
198
        if(!in) {
 
199
            fprintf(stderr, "ERROR: Failed to open input file: %s\n", strerror(errno));
 
200
            return 1;
 
201
        }
 
202
    }
 
203
 
 
204
    if(!outfile) {
 
205
#ifdef __BORLANDC__
 
206
        setmode(fileno(stdout), O_BINARY);
 
207
#elif _WIN32
 
208
        _setmode(_fileno(stdout), _O_BINARY);
 
209
#endif
 
210
        out = stdout;
 
211
    }
 
212
    else {
 
213
        out = fopen(outfile, "wb");
 
214
        if(!out) {
 
215
            fprintf(stderr, "ERROR: Failed to open output file: %s\n", strerror(errno));
 
216
            return 1;
 
217
        }
 
218
    }
 
219
 
 
220
    if(ov_open(in, &vf, NULL, 0) < 0) {
 
221
        fprintf(stderr, "ERROR: Failed to open input as vorbis\n");
 
222
        fclose(in);
 
223
        fclose(out);
 
224
        return 1;
 
225
    }
 
226
 
 
227
    if(ov_seekable(&vf)) {
 
228
        seekable = 1;
 
229
        length = ov_pcm_total(&vf, 0);
 
230
        size = bits/8 * ov_info(&vf, 0)->channels;
 
231
        if(!quiet)
 
232
            fprintf(stderr, "Decoding \"%s\" to \"%s\"\n", 
 
233
                    infile?infile:"standard input", 
 
234
                    outfile?outfile:"standard output");
 
235
    }
 
236
 
 
237
    if(!raw) {
 
238
        if(write_prelim_header(&vf, out, length)) {
 
239
            ov_clear(&vf);
 
240
            fclose(out);
 
241
            return 1;
 
242
        }
 
243
    }
 
244
 
 
245
    while((ret = ov_read(&vf, buf, buflen, endian, bits/8, sign, &bs)) != 0) {
 
246
        if(bs != 0) {
 
247
            fprintf(stderr, "Only one logical bitstream currently supported\n");
 
248
            break;
 
249
        }
 
250
 
 
251
        if(ret < 0 && !quiet) {
 
252
            fprintf(stderr, "Warning: hole in data\n");
 
253
            continue;
 
254
        }
 
255
 
 
256
        if(fwrite(buf, 1, ret, out) != ret) {
 
257
            fprintf(stderr, "Error writing to file: %s\n", strerror(errno));
 
258
            ov_clear(&vf);
 
259
            fclose(out);
 
260
            return 1;
 
261
        }
 
262
 
 
263
        written += ret;
 
264
        if(!quiet && seekable) {
 
265
            done += ret/size;
 
266
            if((double)done/(double)length * 200. > (double)percent) {
 
267
                percent = (double)done/(double)length *200;
 
268
                fprintf(stderr, "\r\t[%5.1f%%]", (double)percent/2.);
 
269
            }
 
270
        }
 
271
    }
 
272
 
 
273
    if(seekable && !quiet)
 
274
        fprintf(stderr, "\n");
 
275
 
 
276
    if(!raw)
 
277
        rewrite_header(out, written); /* We don't care if it fails, too late */
 
278
 
 
279
    ov_clear(&vf);
 
280
 
 
281
    fclose(out);
 
282
    return 0;
 
283
}
 
284
 
 
285
int main(int argc, char **argv)
 
286
{
 
287
    int i;
 
288
 
 
289
    if(argc == 1) {
 
290
        fprintf(stderr, VERSIONSTRING);
 
291
        usage();
 
292
        return 1;
 
293
    }
 
294
 
 
295
    parse_options(argc,argv);
 
296
 
 
297
    if(!quiet)
 
298
        fprintf(stderr, VERSIONSTRING);
 
299
 
 
300
    if(optind >= argc) {
 
301
        fprintf(stderr, "ERROR: No input files specified. Use -h for help\n");
 
302
        return 1;
 
303
    }
 
304
 
 
305
    if(argc - optind > 1 && outfilename) {
 
306
        fprintf(stderr, "ERROR: Can only specify one input file if output filename is specified\n");
 
307
        return 1;
 
308
    }
 
309
    
 
310
    for(i=optind; i < argc; i++) {
 
311
        char *in, *out;
 
312
        if(!strcmp(argv[i], "-"))
 
313
            in = NULL;
 
314
        else
 
315
            in = argv[i];
 
316
 
 
317
        if(outfilename) {
 
318
            if(!strcmp(outfilename, "-"))
 
319
                out = NULL;
 
320
            else
 
321
                out = outfilename;
 
322
        }
 
323
        else {
 
324
            char *end = strrchr(argv[i], '.');
 
325
            end = end?end:(argv[i] + strlen(argv[i]) + 1);
 
326
 
 
327
            out = malloc(strlen(argv[i]) + 10);
 
328
            strncpy(out, argv[i], end-argv[i]);
 
329
            out[end-argv[i]] = 0;
 
330
            if(raw)
 
331
                strcat(out, ".raw");
 
332
            else
 
333
                strcat(out, ".wav");
 
334
        }
 
335
 
 
336
        if(decode_file(in,out))
 
337
            return 1;
 
338
    }
 
339
 
 
340
    if(outfilename)
 
341
        free(outfilename);
 
342
 
 
343
    return 0;
 
344
}
 
345
    
 
346