[xiph-cvs] cvs commit: vorbis-tools/oggenc encode.c encode.h oggenc.c
Michael Smith
msmith at xiph.org
Thu Sep 7 08:10:50 PDT 2000
msmith 00/09/07 08:10:49
Modified: oggenc encode.c encode.h oggenc.c
Log:
Restructuring of lots of stuff, to make it better and generally neater.
Couple of minor feature additions (--tracknum, --date, etc.)
Revision Changes Path
1.2 +56 -61 vorbis-tools/oggenc/encode.c
Index: encode.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/oggenc/encode.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- encode.c 2000/09/07 00:57:46 1.1
+++ encode.c 2000/09/07 15:10:49 1.2
@@ -21,7 +21,7 @@
#define READSIZE 1024
-static void update_statistics(char *fn, long total, long done, double time,long counter);
+int oe_write_page(ogg_page *page, FILE *fp);
int oe_encode(oe_enc_opt *opt)
{
@@ -34,11 +34,10 @@
vorbis_block vb;
long samplesdone=0;
- long counter=0,counter2=0;
int eos;
long bytes_written = 0;
- void *timer;
+ TIMER *timer;
/* get start time. */
@@ -87,14 +86,14 @@
{
samplesdone += samples_read;
- if((counter++%16==0) && !opt->quiet)
+ if(!opt->quiet)
{
double time;
time = timer_time(timer);
- update_statistics(opt->filename,
- opt->total_samples_per_channel, samplesdone,time,counter2++);
+ opt->progress_update(opt->filename, opt->total_samples_per_channel,
+ samplesdone, time);
}
/* Tell the library how many samples (per channel) we wrote
@@ -121,11 +120,8 @@
int result = ogg_stream_pageout(&os,&og);
if(!result) break;
- fwrite(og.header,1,og.header_len, opt->out);
- fwrite(og.body,1,og.body_len, opt->out);
+ bytes_written += oe_write_page(&og, opt->out);
- bytes_written += og.header_len + og.body_len;
-
if(ogg_page_eos(&og))
eos = 1;
}
@@ -141,27 +137,8 @@
if(!opt->quiet)
{
- double time_elapsed, speed_ratio;
- if(opt->filename)
- fprintf(stderr, "\n\nDone encoding file \"%s\"\n", opt->filename);
- else
- fprintf(stderr, "\n\nDone encoding.\n");
-
- time_elapsed = timer_time(timer);
- speed_ratio = (double)opt->total_samples_per_channel / (double)opt->rate / time_elapsed;
-
-
- fprintf(stderr, "\n\tFile length: %dm %04.1fs\n",
- (int)(opt->total_samples_per_channel/opt->rate/60),
- opt->total_samples_per_channel/opt->rate -
- floor(opt->total_samples_per_channel/opt->rate/60)*60);
- fprintf(stderr, "\tElapsed time: %dm %04.1fs\n",
- (int)(time_elapsed/60),
- time_elapsed - floor(time_elapsed/60)*60);
- fprintf(stderr, "\tRate: %.4f\n", speed_ratio);
- fprintf(stderr, "\tAverage bitrate: %.1f kb/s\n\n",
- 8./1000.*((double)bytes_written/((double)opt->total_samples_per_channel/(double)opt->rate)));
-
+ double time_elapsed = timer_time(timer);
+ opt->end_encode(opt->filename, time_elapsed, opt->rate, samplesdone, bytes_written);
}
timer_clear(timer);
@@ -169,42 +146,60 @@
return 0;
}
-static void update_statistics(char *fn, long total, long done, double time,long counter)
+void update_statistics_full(char *fn, long total, long done, double time)
{
- static char *spinner="|/-\\";
+ static char *spinner="||||////----\\\\\\\\";
+ static int spinpoint = 0;
double remain_time;
int minutes=0,seconds=0;
+
+ remain_time = time/((double)done/(double)total) - time;
+ minutes = ((int)remain_time)/60;
+ seconds = (int)(remain_time - (double)((int)remain_time/60)*60);
+
+ fprintf(stderr, "\rEncoding %s%s%s [%5.1f%%] [%2dm%.2ds remaining] %c",
+ fn?"\"":"", fn?fn:"standard input", fn?"\"":"",
+ done*100.0/total, minutes, seconds, spinner[spinpoint++%16]);
+}
- if(total)
- {
- remain_time = time/((double)done/(double)total) - time;
- minutes = ((int)remain_time)/60;
- seconds = (int)(remain_time - (float)((int)remain_time/60)*60);
- }
+void update_statistics_notime(char *fn, long total, long done, double time)
+{
+ static char *spinner="||||////----\\\\\\\\";
+ static int spinpoint =0;
+
+ fprintf(stderr, "\rEncoding %s%s%s %c",
+ fn?"\"":"", fn?fn:"standard input", fn?"\"":"",
+ spinner[spinpoint++%16]);
+}
- if(fn && total && time > 1.0)
- fprintf(stderr, "\rEncoding \"%s\" [%5.1f%%] [%2dm%.2ds remaining] %c", fn,
- done*100.0/total, minutes, seconds,
- spinner[counter%4]);
- else if(fn && total)
- fprintf(stderr, "\rEncoding \"%s\" [%5.1f%%] %c", fn,
- done*100.0/total,
- spinner[counter%4]);
- else if(fn)
- fprintf(stderr, "\rEncoding \"%s\" [???%%] %c", fn,
- spinner[counter%4]);
- else if(total && time > 1.0)
- fprintf(stderr, "\rEncoding to standard output [%5.1f%%] [%dm%ds remaining] %c",
- done*100.0/total, minutes, seconds,
- spinner[counter%4]);
- else if(total)
- fprintf(stderr, "\rEncoding to standard output [%5.1f%%] %c",
- done*100.0/total,
- spinner[counter%4]);
- else
- fprintf(stderr, "\rEncoding to standard output [???%%] %c",
- spinner[counter%4]);
+int oe_write_page(ogg_page *page, FILE *fp)
+{
+ fwrite(page->header,1,page->header_len, fp);
+ fwrite(page->body,1,page->body_len, fp);
+
+ return page->header_len+page->body_len;
}
+void final_statistics(char *fn, double time, int rate, long samples, long bytes)
+{
+ double speed_ratio;
+ if(fn)
+ fprintf(stderr, "\n\nDone encoding file \"%s\"\n", fn);
+ else
+ fprintf(stderr, "\n\nDone encoding.\n");
+
+ speed_ratio = (double)samples / (double)rate / time;
+
+ fprintf(stderr, "\n\tFile length: %dm %04.1fs\n",
+ (int)(samples/rate/60),
+ samples/rate -
+ floor(samples/rate/60)*60);
+ fprintf(stderr, "\tElapsed time: %dm %04.1fs\n",
+ (int)(time/60),
+ time - floor(time/60)*60);
+ fprintf(stderr, "\tRate: %.4f\n", speed_ratio);
+ fprintf(stderr, "\tAverage bitrate: %.1f kb/s\n\n",
+ 8./1000.*((double)bytes/((double)samples/(double)rate)));
+}
1.2 +30 -6 vorbis-tools/oggenc/encode.h
Index: encode.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/oggenc/encode.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- encode.h 2000/09/07 00:57:46 1.1
+++ encode.h 2000/09/07 15:10:49 1.2
@@ -4,12 +4,32 @@
#include <stdio.h>
#include <vorbis/codec.h>
-typedef long (*audio_read_func)(void *src, float **buffer, int samples);
+
+typedef void TIMER;
+typedef long (*audio_read_func)(void *src, float **buffer, int samples);
+typedef void (*progress_func)(char *fn, long totalsamples,
+ long samples, double time);
+typedef void (*enc_end_func)(char *fn, double time, int rate,
+ long samples, long bytes);
+
+
void *timer_start(void);
double timer_time(void *);
void timer_clear(void *);
+void update_statistics_full(char *fn, long total, long done, double time);
+void update_statistics_notime(char *fn, long total, long done, double time);
+void final_statistics(char *fn, double time, int rate, long total_samples,
+ long bytes);
+
+typedef struct _taglist
+{
+ char *tag;
+ char *contents;
+ struct _taglist *next;
+} taglist;
+
typedef struct
{
char **title;
@@ -20,6 +40,10 @@
int album_count;
char **comments;
int comment_count;
+ char **tracknum;
+ int track_count;
+ char **dates;
+ int date_count;
int quiet;
int rawmode;
@@ -33,21 +57,21 @@
{
vorbis_comment *comments;
vorbis_info *mode;
+ long serialno;
audio_read_func read_samples;
+ progress_func progress_update;
+ enc_end_func end_encode;
+
void *readdata;
+
long total_samples_per_channel;
int channels;
long rate;
FILE *out;
int quiet;
- long serialno;
char *filename;
-
- char *artist;
- char *album;
- char *title;
} oe_enc_opt;
1.2 +76 -33 vorbis-tools/oggenc/oggenc.c
Index: oggenc.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/oggenc/oggenc.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- oggenc.c 2000/09/07 00:57:47 1.1
+++ oggenc.c 2000/09/07 15:10:49 1.2
@@ -21,7 +21,7 @@
#include "encode.h"
#include "audio.h"
-#define VERSION_STRING "OggEnc v0.4\n"
+#define VERSION_STRING "OggEnc v0.5\n"
#define CHUNK 4096 /* We do reads, etc. in multiples of this */
/* Define supported formats here */
@@ -41,18 +41,22 @@
{"output",1,0,'o'},
{"version",0,0,'v'},
{"raw",0,0,'r'},
- {"mode",1,0,'m'}
+ {"mode",1,0,'m'},
+ {"date",1,0,'d'},
+ {"tracknum",1,0,'N'},
+ {NULL,0,0,0}
};
-char *generate_name_string(char *format, char *artist, char *title, char *album);
+char *generate_name_string(char *format, char *artist, char *title, char *album, char *track, char *date);
void parse_options(int argc, char **argv, oe_options *opt);
-void build_comments(vorbis_comment *vc, oe_options *opt, int filenum, oe_enc_opt *eopt);
+void build_comments(vorbis_comment *vc, oe_options *opt, int filenum,
+ char **artist, char **album, char **title, char **tracknum, char **date);
void usage(void);
vorbis_info *choose_mode(int modenum, int channels);
int main(int argc, char **argv)
{
- oe_options opt = {NULL, 0, NULL, 0, NULL, 0, NULL, 0,
+ oe_options opt = {NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
0,0, NULL,NULL,0}; /* Default values */
int i;
@@ -65,7 +69,7 @@
if(optind >= argc)
{
fprintf(stderr, "ERROR: No input files specified. Use -h for help.\n");
- exit(1);
+ return 1;
}
else
{
@@ -105,6 +109,7 @@
int foundformat = 0;
int closeout = 0, closein = 0;
int j=0;
+ char *artist=NULL, *album=NULL, *title=NULL, *track=NULL, *date=NULL;
@@ -112,12 +117,11 @@
enc_opts.serialno = nextserial++;
enc_opts.quiet = opt.quiet;
- enc_opts.artist = NULL;
- enc_opts.title = NULL;
- enc_opts.album = NULL;
+ enc_opts.progress_update = update_statistics_full;
+ enc_opts.end_encode = final_statistics;
/* OK, let's build the vorbis_comments structure */
- build_comments(&vc, &opt, i, &enc_opts);
+ build_comments(&vc, &opt, i, &artist, &album, &title, &track, &date);
if(!strcmp(infiles[i], "-"))
{
@@ -156,25 +160,20 @@
}
else if(opt.namefmt)
{
- out_fn = generate_name_string(opt.namefmt, enc_opts.artist, enc_opts.title, enc_opts.album);
+ out_fn = generate_name_string(opt.namefmt, artist, title, album, track,date);
}
else if(opt.title)
{
- out_fn = malloc(strlen(enc_opts.title) + 5);
- strcpy(out_fn, enc_opts.title);
+ out_fn = malloc(strlen(title) + 5);
+ strcpy(out_fn, title);
strcat(out_fn, ".ogg");
}
else
{
/* Create a filename from existing filename, replacing extension with .ogg */
char *start, *end;
-
- start = rindex(infiles[i], '/');
- if(start)
- start += 1; /* Skip over the / */
- else
- start = infiles[i];
+ start = infiles[i];
end = rindex(infiles[i], '.');
end = end?end:(start + strlen(infiles[i])+1);
@@ -230,6 +229,8 @@
}
enc_opts.mode = choose_mode(opt.modenum, enc_opts.channels);
+ if(!enc_opts.total_samples_per_channel)
+ enc_opts.progress_update = update_statistics_notime;
if(!opt.quiet)
fprintf(stderr, "Encoding using encoder mode %d\n", opt.modenum?opt.modenum:3);
@@ -270,21 +271,26 @@
"\n"
" Naming:\n"
" -o, --output=fn Write file to fn (only valid in single-file mode)\n"
- " -n, --names=string Produce filenames as this string, with %%a, %%t, %%l\n"
- " replaced by artist, title, album respectively (see below\n"
- " for specifying these). Note that this can be given as a \n"
- " single string to specify a particular output filename.\n"
+ " -n, --names=string Produce filenames as this string, with %%a, %%t, %%l,\n"
+ " %%n, %%d replaces by artist, title, album, track number,\n"
+ " and date, respectively (see below for specifying these).\n"
" %%%% gives a literal %%.\n"
" -c, --comment=c Add the given string as an extra comment. This may be\n"
" used multiple times.\n"
+ " -d, --date Date for track (usually date of performance)\n"
+ " -N, --tracknum Track number for this track\n"
" -t, --title Title for this track\n"
" -l, --album Name of album\n"
" -a, --artist Name of artist\n"
" If multiple input files are given, then multiple\n"
- " instances of the previous three arguments will be used,\n"
+ " instances of the previous five arguments will be used,\n"
" in the order they are given. If fewer titles are\n"
" specified than files, OggEnc will print a warning, and\n"
- " reuse the final one for the remaining files.\n"
+ " reuse the final one for the remaining files. If fewer\n"
+ " track numbers are given, the remaining files will be\n"
+ " unnumbered. For the others, the final tag will be reused\n"
+ " for all others without warning (so you can specify a date\n"
+ " once, for example, and have it used for all the files)\n"
"\n"
"INPUT FILES:\n"
" OggEnc input files must currently be 44.1kHz, 16 bit stereo WAV files.\n"
@@ -298,16 +304,17 @@
" OggEnc support multiple different modes. Each of these is a fully VBR mode,\n"
" but they vary in intended (average) bitrate. The following table shows \n"
" approximate average bitrates (note that mode 3 is the default)\n"
- " Mode | Bitrate\n"
+ " Mode | Bitrate (stereo)\n"
" 1 | N/A\n"
" 2 | 128 kbps\n"
- " 3 | 160 kbps\n"
+ " *3 | 160 kbps\n"
" 4 | 192 kbps\n"
" 5 | 256 kbps\n"
" 6 | 350 kbps\n\n");
}
-char *generate_name_string(char *format, char *artist, char *title, char *album)
+char *generate_name_string(char *format,
+ char *artist, char *title, char *album, char *track, char *date)
{
char *buffer;
char *cur;
@@ -333,6 +340,10 @@
strcat(buffer, artist?artist:"(none)");
cur += strlen(artist?artist:"(none)");
break;
+ case 'd':
+ strcat(buffer, date?date:"(none)");
+ cur += strlen(date?date:"(none)");
+ break;
case 't':
strcat(buffer, title?title:"(none)");
cur += strlen(title?title:"(none)");
@@ -341,6 +352,10 @@
strcat(buffer, album?album:"(none)");
cur += strlen(album?album:"(none)");
break;
+ case 'n':
+ strcat(buffer, track?track:"(none)");
+ cur += strlen(track?track:"(none)");
+ break;
default:
fprintf(stderr, "WARNING: Ignoring illegal escape character '%c' in name format\n", *(format - 1));
break;
@@ -358,7 +373,7 @@
int ret;
int option_index = 1;
- while((ret = getopt_long(argc, argv, "a:c:hl:m:n:o:qrt:v",
+ while((ret = getopt_long(argc, argv, "a:c:d:hl:m:n:N:o:qrt:v",
long_options, &option_index)) != -1)
{
switch(ret)
@@ -375,6 +390,10 @@
opt->comments = realloc(opt->comments, (++opt->comment_count)*sizeof(char *));
opt->comments[opt->comment_count - 1] = strdup(optarg);
break;
+ case 'd':
+ opt->dates = realloc(opt->dates, (++opt->date_count)*sizeof(char *));
+ opt->dates[opt->date_count - 1] = strdup(optarg);
+ break;
case 'l':
opt->album = realloc(opt->album, (++opt->album_count)*sizeof(char *));
opt->album[opt->album_count - 1] = strdup(optarg);
@@ -416,6 +435,10 @@
fprintf(stderr, VERSION_STRING);
exit(0);
break;
+ case 'N':
+ opt->tracknum = realloc(opt->tracknum, (++opt->track_count)*sizeof(char *));
+ opt->tracknum[opt->track_count - 1] = strdup(optarg);
+ break;
case '?':
fprintf(stderr, "WARNING: Unknown option specified, ignoring->\n");
break;
@@ -426,7 +449,8 @@
}
}
-void build_comments(vorbis_comment *vc, oe_options *opt, int filenum, oe_enc_opt *eopt)
+void build_comments(vorbis_comment *vc, oe_options *opt, int filenum,
+ char **artist, char **album, char **title, char **tracknum, char **date)
{
int i;
@@ -446,7 +470,7 @@
else
i = filenum;
- eopt->title = opt->title[i];
+ *title = opt->title[i];
vorbis_comment_add_tag(vc, "title", opt->title[i]);
}
@@ -457,9 +481,20 @@
else
i = filenum;
- eopt->artist = opt->artist[i];
+ *artist = opt->artist[i];
vorbis_comment_add_tag(vc, "artist", opt->artist[i]);
}
+
+ if(opt->date_count)
+ {
+ if(filenum >= opt->date_count)
+ i = opt->date_count-1;
+ else
+ i = filenum;
+
+ *date = opt->dates[i];
+ vorbis_comment_add_tag(vc, "date", opt->dates[i]);
+ }
if(opt->album_count)
{
@@ -470,9 +505,16 @@
else
i = filenum;
- eopt->album = opt->album[i];
+ *album = opt->album[i];
vorbis_comment_add_tag(vc, "album", opt->album[i]);
}
+
+ if(filenum < opt->track_count)
+ {
+ i = filenum;
+ *tracknum = opt->tracknum[i];
+ vorbis_comment_add_tag(vc, "tracknumber", opt->tracknum[i]);
+ }
}
vorbis_info *choose_mode(int modenum, int channels)
@@ -515,3 +557,4 @@
mono rather than stereo */
return mode;
}
+
--- >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