From: Niki Roo Date: Sat, 6 Jul 2024 14:21:41 +0000 (+0200) Subject: add timings conversion and rework offsets X-Git-Url: https://git.nikiroo.be/?a=commitdiff_plain;h=HEAD;p=nsub.git add timings conversion and rework offsets --- diff --git a/src/nsub/nsub.c b/src/nsub/nsub.c index bab09de..f23e942 100644 --- a/src/nsub/nsub.c +++ b/src/nsub/nsub.c @@ -158,14 +158,18 @@ song_t *nsub_read(FILE *in, NSUB_FORMAT fmt) { return song; } -int nsub_write(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { +int nsub_write(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset, + int add_offset, double conv) { switch (fmt) { case NSUB_FMT_LRC: - return nsub_write_lrc(out, song, fmt, apply_offset); + return nsub_write_lrc(out, song, fmt, apply_offset, + add_offset, conv); case NSUB_FMT_WEBVTT: - return nsub_write_webvtt(out, song, fmt, apply_offset); + return nsub_write_webvtt(out, song, fmt, apply_offset, + add_offset, conv); case NSUB_FMT_SRT: - return nsub_write_srt(out, song, fmt, apply_offset); + return nsub_write_srt(out, song, fmt, apply_offset, + add_offset, conv); default: fprintf(stderr, "Unsupported write format %d\n", fmt); return 0; @@ -268,3 +272,14 @@ int nsub_is_timing(const char line[], char deci_sym, int max_deci) { return 1; } + +int apply_conv(int time, double conv) { + // Just so we don't require -lm... + double tmp = time * conv; + double diff = tmp - (int)tmp; + + if (diff >= 0.5) + return (int)tmp + 1; + return (int)tmp; +} + diff --git a/src/nsub/nsub.h b/src/nsub/nsub.h index 35bf334..611f667 100644 --- a/src/nsub/nsub.h +++ b/src/nsub/nsub.h @@ -181,6 +181,16 @@ int nsub_to_ms(const char line[], char deci_sym); */ int nsub_is_timing(const char line[], char deci_sym, int max_deci); +/** + * Apply a conversion ratio to the given time. + * + * @param time the initial time to compute from + * @param conv the conversion ratio to apply (i.e., 1 = no conversion) + * + * @return the converted time + */ +int apply_conv(int time, double conv); + song_t *nsub_read(FILE *in, NSUB_FORMAT fmt); int nsub_read_lrc(song_t *song, char *line); int nsub_read_webvtt(song_t *song, char *line); @@ -188,10 +198,14 @@ int nsub_read_srt(song_t *song, char *line); /* Write */ -int nsub_write(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset); -int nsub_write_lrc(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset); +// conv = time conversion ratio +int nsub_write(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset, + int add_offset, double conv); +int nsub_write_lrc(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset, + int add_offset, double conv); int nsub_write_webvtt(FILE *out, song_t *song, NSUB_FORMAT fmt, - int apply_offset); -int nsub_write_srt(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset); + int apply_offset, int add_offset, double conv); +int nsub_write_srt(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset, + int add_offset, double conv); #endif /* NSUB_H */ diff --git a/src/nsub/nsub_main.c b/src/nsub/nsub_main.c index c11e8b6..7878e34 100644 --- a/src/nsub/nsub_main.c +++ b/src/nsub/nsub_main.c @@ -35,6 +35,8 @@ int main(int argc, char **argv) { char *in_file = NULL; char *out_file = NULL; int apply_offset = 0; + int add_offset = 0; + double conv = 1; if (argc <= 1) { help(argv[0]); @@ -49,30 +51,84 @@ int main(int argc, char **argv) { } else if (!strcmp("--from", arg) || !strcmp("-f", arg)) { if (i + 1 >= argc) { fprintf(stderr, - "The parameter --from/-f requires an argument\n"); + "The parameter --from/-f " + "requires an argument\n" + ); return 5; } from = nsub_parse_fmt(argv[++i], 1); if (from == NSUB_FMT_ERROR) { - fprintf(stderr, "Unsupported input format: %s\n", argv[i]); + fprintf(stderr, + "Unsupported input " + "format: %s\n", argv[i] + ); return 8; } } else if (!strcmp("--to", arg) || !strcmp("-t", arg)) { if (i + 1 >= argc) { - fprintf(stderr, "The parameter --to/-t requires an argument\n"); + fprintf(stderr, + "The parameter --to/-t " + "requires an argument\n" + ); return 5; } to = nsub_parse_fmt(argv[++i], 1); if (to == NSUB_FMT_ERROR) { - fprintf(stderr, "Unsupported output format: %s\n", argv[i]); + fprintf(stderr, + "Unsupported output " + "format: %s\n", argv[i] + ); return 9; } - } else if (!strcmp("--apply-offset", arg) || !strcmp("-a", arg)) { + } else if (!strcmp("--apply-offset", arg) + || !strcmp("-a", arg)) { apply_offset = 1; + } else if (!strcmp("--ntsc", arg) + || !strcmp("-n", arg)) { + conv = 25.00 / 29.97; + } else if (!strcmp("--pal", arg) + || !strcmp("-p", arg)) { + conv = 29.97 / 25.00; + } else if (!strcmp("--offset", arg) + || !strcmp("-o", arg)) { + if (i + 1 >= argc) { + fprintf(stderr, + "The parameter --offset/-o requires " + "an argument\n" + ); + return 5; + } + + if (sscanf(argv[++i], "%i", &add_offset) == EOF) { + fprintf(stderr, + "Bad parameter to %s: %s\n", + arg, argv[i-1] + ); + return 5; + } + } else if (!strcmp("--ratio", arg) + || !strcmp("-r", arg)) { + if (i + 1 >= argc) { + fprintf(stderr, + "The parameter --ratio/-r requires " + "an argument\n" + ); + return 5; + } + + if (sscanf(argv[++i], "%lf", &conv) == EOF) { + fprintf(stderr, + "Bad parameter to %s: %s\n", + arg, argv[i-1] + ); + return 5; + } } else if (!strcmp("--output", arg) || !strcmp("-o", arg)) { if (i + 1 >= argc) { fprintf(stderr, - "The parameter --output/-o requires an argument\n"); + "The parameter --output/-o requires " + "an argument\n" + ); return 5; } out_file = argv[++i]; @@ -109,13 +165,17 @@ int main(int argc, char **argv) { if (from == NSUB_FMT_UNKNOWN) { fprintf(stderr, - "Cannot detect input format, please specify it with '--from'\n"); + "Cannot detect input format, " + "please specify it with '--from'\n" + ); return 6; } if (to == NSUB_FMT_UNKNOWN) { fprintf(stderr, - "Cannot detect output format, please specify it with '--to'\n"); + "Cannot detect output format, " + "please specify it with '--to'\n" + ); return 7; } @@ -123,7 +183,9 @@ int main(int argc, char **argv) { if (in_file && !(in_file[0] == '-' && !in_file[1])) { in = fopen(in_file, "r"); if (!in) { - fprintf(stderr, "Cannot open input file: %s\n", in_file); + fprintf(stderr, + "Cannot open input file: %s\n", in_file + ); rep = 2; } } @@ -132,7 +194,9 @@ int main(int argc, char **argv) { if (!rep && out_file && !(out_file[0] == '-' && !out_file[1])) { out = fopen(out_file, "w"); if (!in) { - fprintf(stderr, "Cannot create output file: %s\n", out_file); + fprintf(stderr, + "Cannot create output file: %s\n", out_file + ); rep = 3; } } @@ -142,7 +206,8 @@ int main(int argc, char **argv) { if (!song) rep = 22; - if (!rep && !nsub_write(out, song, to, apply_offset)) + if (!rep && !nsub_write(out, song, to, apply_offset, + add_offset, conv)) rep = 33; free_song(song); @@ -179,25 +244,51 @@ NSUB_FORMAT nsub_parse_fmt(char *type, int required) { void help(char *program) { printf("NSub subtitles conversion program\n"); printf("Syntax:\n"); - printf("\t%s (--from FMT) (--to FMT) (--apply-offset)\n" - "\t\t (--output OUT_FILE) (IN_FILE)\n", program); - printf("\t> --help (or -h): this help message\n"); - printf("\t> --from (or -f) FMT: select the input format FMT\n"); - printf("\t> --to (or -t) FMT: select the output format FMT\n"); + printf("\t%s (--from FMT) (--to FMT) (--apply-offset) (--offset MSEC)\n" + "\t\t (--ntsc) (--pal) (--ratio RATIO)\n" + "\t\t (--output OUT_FILE) (IN_FILE)\n", + program + ); + + printf("\nOptions:\n"); + printf("\t-h/--help : this help message\n"); + printf("\t-f/--from FMT : select the input format FMT\n"); + printf("\t-t/--to FMT : select the output format FMT\n"); + printf("\t-a/--apply-offset : apply the offset tag " + "value to the lyrics\n" + ); + printf("\t-o/--offset MSEC : add a manual offset to all timings\n"); + printf("\t-n/--ntsc : Convert timings from NTSC to PAL\n"); + printf("\t-p/--pal : Convert timings from PAL to NTSC\n"); + printf("\t-r/--ratio RATIO : Convert timings with a " + "custom ratio\n"); + + printf("\nArguments:\n"); printf( - "\t> --apply-offset (or -a): apply the offset tag value to the lyrics\n"); + "\tIN_FILE : the input file or '-' for stdin " + "(which is the default)\n" + ); printf( - "\t> IN_FILE: the input file or '-' for stdin (which is the default)\n"); + "\tOUT_FILE : the output file or '-' for stdout " + "(which is the default)\n" + ); + printf("\tRATIO : the ratio to apply to timings (1 = no change)\n"); printf( - "\t> OUT_FILE: the output file or '-' for stdout (which is the default)\n"); + "\tMSEC : the offset to add to all timings in " + "milliseconds\n" + ); printf("\n"); printf( - "Note: the in/out formats will be guessed from the extension if needed/possible\n"); + "Note: the in/out formats will be guessed from the " + "extension if needed/possible\n" + ); printf( - "Note: to specify a file named dash (-), prefix it with a path (e.g., './-')\n"); + "Note: to specify a file named dash (-), prefix it with a path" + " (e.g., './-')\n" + ); printf("\n"); printf("Supported formats:\n"); - printf("\t> lrc: lyrics files\n"); - printf("\t> srt: SubRip subtitles files\n"); - printf("\t> vtt/webvtt: Web Video Text Tracks\n"); + printf("\tlrc: lyrics files\n"); + printf("\tsrt: SubRip subtitles files\n"); + printf("\tvtt/webvtt: Web Video Text Tracks\n"); } diff --git a/src/nsub/nsub_read_lrc.c b/src/nsub/nsub_read_lrc.c index 7e56a25..9ce858e 100644 --- a/src/nsub/nsub_read_lrc.c +++ b/src/nsub/nsub_read_lrc.c @@ -122,12 +122,14 @@ static int is_lrc_offset(char *line) { if (*offset) return 0; - // skip spaces then ':' + // skip spaces then ':', then spaces while (*line == ' ') line++; if (*line && *line != ':') return 0; line++; + while (*line == ' ') + line++; // allow sign if (*line == '-' || *line == '+') @@ -217,6 +219,7 @@ static int lrc_millisec(char *line) { // skip [offset: while (*line != ':') line++; + line++; while (*line == ' ') line++; @@ -232,8 +235,9 @@ static int lrc_millisec(char *line) { } else { /* should not happen! */ fprintf(stderr, - "Warning: called lrc_millisec with bad input [%s], ignoring...\n", - line); + "Warning: called lrc_millisec with bad input" + " [%s], ignoring...\n", + line); return 0; } diff --git a/src/nsub/nsub_read_srt.c b/src/nsub/nsub_read_srt.c index c19bc9f..894c342 100644 --- a/src/nsub/nsub_read_srt.c +++ b/src/nsub/nsub_read_srt.c @@ -46,8 +46,10 @@ int nsub_read_srt(song_t *song, char *line) { int new_count = atoi(line); if (new_count != count + 1) { fprintf(stderr, - "Warning: line %zu is out of order (it is numbered %i), ignoring order...\n", - count, new_count); + "Warning: line %zu is out of order " + "(it is numbered %i), ignoring order...\n", + count, new_count + ); } song_add_lyric(song, 0, 0, NULL, NULL); @@ -164,8 +166,10 @@ static int get_start(char *line) { if (!is_srt_timing(line)) { /* should not happen! */ fprintf(stderr, - "Warning: called get_start with bad input [%s], ignoring...\n", - line); + "Warning: called get_start with bad input " + "[%s], ignoring...\n", + line + ); return 0; } @@ -190,8 +194,10 @@ static int get_stop(char *line) { if (!is_srt_timing(line)) { /* should not happen! */ fprintf(stderr, - "Warning: called get_stop with bad input [%s], ignoring...\n", - line); + "Warning: called get_stop with bad input " + "[%s], ignoring...\n", + line + ); return 0; } diff --git a/src/nsub/nsub_write_lrc.c b/src/nsub/nsub_write_lrc.c index 1d42815..4575679 100644 --- a/src/nsub/nsub_write_lrc.c +++ b/src/nsub/nsub_write_lrc.c @@ -25,12 +25,13 @@ /* Declarations */ char *nsub_lrc_time_str(int time, int show_sign); -void nsub_write_lrc_lyric(FILE *out, lyric_t *lyric, int offset); +void nsub_write_lrc_lyric(FILE *out, lyric_t *lyric, int offset, double conv); /* Public */ -int nsub_write_lrc(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { - int offset; +int nsub_write_lrc(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset, + int add_offset, double conv) { + int offset = add_offset; // header: none @@ -44,10 +45,9 @@ int nsub_write_lrc(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { { char *offset_str; if (apply_offset) { - offset = song->offset; + offset += song->offset; offset_str = nsub_lrc_time_str(0, 1); } else { - offset = 0; offset_str = nsub_lrc_time_str(song->offset, 1); } fprintf(out, "[offset: %s]\n", offset_str); @@ -64,7 +64,7 @@ int nsub_write_lrc(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { // lyrics array_loop(song->lyrics, lyric, lyric_t) { - nsub_write_lrc_lyric(out, lyric, offset); + nsub_write_lrc_lyric(out, lyric, offset, conv); } return 1; @@ -72,19 +72,11 @@ int nsub_write_lrc(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { /* Private */ -void nsub_write_lrc_lyric(FILE *out, lyric_t *lyric, int offset) { +void nsub_write_lrc_lyric(FILE *out, lyric_t *lyric, int offset, double conv) { static int lrc_last_stop = 0; if (lyric->type == NSUB_EMPTY) { - if (lrc_last_stop) { - char *time = nsub_lrc_time_str(lrc_last_stop, 0); - fprintf(out, "[%s]\n", time); - free(time); - } else { - fprintf(out, "\n"); - } - - lrc_last_stop = 0; + fprintf(out, "\n"); return; } @@ -95,11 +87,20 @@ void nsub_write_lrc_lyric(FILE *out, lyric_t *lyric, int offset) { } fprintf(out, "-- %s\n", tmp->string); - lrc_last_stop = 0; free_cstring(tmp); return; } + + int start_time = apply_conv(lyric->start, conv) + offset; + if (lrc_last_stop && lrc_last_stop != start_time) { + char *time = nsub_lrc_time_str(lrc_last_stop, 0); + fprintf(out, "[%s]\n", time); + fprintf(out, "\n"); + free(time); + lrc_last_stop = 0; + } + if (lyric->name) { cstring_t *tmp = cstring_clone(lyric->name); @@ -111,8 +112,8 @@ void nsub_write_lrc_lyric(FILE *out, lyric_t *lyric, int offset) { free_cstring(tmp); } - - char *time = nsub_lrc_time_str(lyric->start + offset, 0); + + char *time = nsub_lrc_time_str(start_time, 0); cstring_t *tmp = cstring_clone(lyric->text); if (tmp) { cstring_replace(tmp, "\n", "\\n"); @@ -121,7 +122,7 @@ void nsub_write_lrc_lyric(FILE *out, lyric_t *lyric, int offset) { free(time); free_cstring(tmp); - lrc_last_stop = lyric->stop + offset; + lrc_last_stop = apply_conv(lyric->stop, conv) + offset; } char *nsub_lrc_time_str(int time, int show_sign) { diff --git a/src/nsub/nsub_write_srt.c b/src/nsub/nsub_write_srt.c index 2ecaa25..4357f70 100644 --- a/src/nsub/nsub_write_srt.c +++ b/src/nsub/nsub_write_srt.c @@ -25,12 +25,13 @@ /* Declarations */ char *nsub_srt_time_str(int time, int show_sign); -void nsub_write_srt_lyric(FILE *out, lyric_t *lyric, int offset); +void nsub_write_srt_lyric(FILE *out, lyric_t *lyric, int offset, double conv); /* Public */ -int nsub_write_srt(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { - int offset; +int nsub_write_srt(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset, + int add_offset, double conv) { + int offset = add_offset; // header: none @@ -38,7 +39,7 @@ int nsub_write_srt(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { // offset is not supported in SRT (so, always applied) { - offset = song->offset; + offset += song->offset; } // other metas: none @@ -46,7 +47,7 @@ int nsub_write_srt(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { // lyrics array_loop(song->lyrics, lyric, lyric_t) { - nsub_write_srt_lyric(out, lyric, offset); + nsub_write_srt_lyric(out, lyric, offset, conv); } return 1; @@ -54,7 +55,7 @@ int nsub_write_srt(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { /* Private */ -void nsub_write_srt_lyric(FILE *out, lyric_t *lyric, int offset) { +void nsub_write_srt_lyric(FILE *out, lyric_t *lyric, int offset, double conv) { if (lyric->type == NSUB_EMPTY) { // not supported, ignored return; @@ -71,8 +72,12 @@ void nsub_write_srt_lyric(FILE *out, lyric_t *lyric, int offset) { //if (lyric->name) // not supported, ignored - char *start = nsub_srt_time_str(lyric->start + offset, 0); - char *stop = nsub_srt_time_str(lyric->stop + offset, 0); + char *start = nsub_srt_time_str( + apply_conv(lyric->start, conv) + offset, + 0); + char *stop = nsub_srt_time_str( + apply_conv(lyric->stop , conv) + offset, + 0); fprintf(out, "%s --> %s\n%s\n\n", start, stop, lyric->text); free(start); free(stop); diff --git a/src/nsub/nsub_write_webvtt.c b/src/nsub/nsub_write_webvtt.c index 761bc46..370506a 100644 --- a/src/nsub/nsub_write_webvtt.c +++ b/src/nsub/nsub_write_webvtt.c @@ -24,13 +24,14 @@ /* Declarations */ char *nsub_webvtt_time_str(int time, int show_sign); -void nsub_write_webvtt_lyric(FILE *out, lyric_t *lyric, int offset); +void nsub_write_webvtt_lyric(FILE *out, lyric_t *lyric, int offset, + double conv); /* Public */ int nsub_write_webvtt(FILE *out, song_t *song, NSUB_FORMAT fmt, - int apply_offset) { - int offset; + int apply_offset, int add_offset, double conv) { + int offset = add_offset; // header { @@ -49,7 +50,7 @@ int nsub_write_webvtt(FILE *out, song_t *song, NSUB_FORMAT fmt, // offset is not supported in WebVTT (so, always applied) { - offset = song->offset; + offset += song->offset; } // other metas @@ -62,7 +63,7 @@ int nsub_write_webvtt(FILE *out, song_t *song, NSUB_FORMAT fmt, // lyrics array_loop(song->lyrics, lyric, lyric_t) { - nsub_write_webvtt_lyric(out, lyric, offset); + nsub_write_webvtt_lyric(out, lyric, offset, conv); } return 1; @@ -70,7 +71,8 @@ int nsub_write_webvtt(FILE *out, song_t *song, NSUB_FORMAT fmt, /* Private */ -void nsub_write_webvtt_lyric(FILE *out, lyric_t *lyric, int offset) { +void nsub_write_webvtt_lyric(FILE *out, lyric_t *lyric, int offset, + double conv) { if (lyric->type == NSUB_EMPTY) { fprintf(out, "\n\n"); return; @@ -87,9 +89,13 @@ void nsub_write_webvtt_lyric(FILE *out, lyric_t *lyric, int offset) { // Not always supported by clients, so disabled: // if (lyric->name) //fprintf(out, "%s\n", lyric->name); - - char *start = nsub_webvtt_time_str(lyric->start + offset, 0); - char *stop = nsub_webvtt_time_str(lyric->stop + offset, 0); + + char *start = nsub_webvtt_time_str( + apply_conv(lyric->start, conv) + offset, + 0); + char *stop = nsub_webvtt_time_str( + apply_conv(lyric->stop , conv) + offset, + 0); fprintf(out, "%s --> %s\n%s\n\n", start, stop, lyric->text); free(start); free(stop);