diff --git a/src/Makefile.msc b/src/Makefile.msc new file mode 100644 index 0000000..7214bfc --- /dev/null +++ b/src/Makefile.msc @@ -0,0 +1,69 @@ +# Makefile for libltc using Microsoft (Visual) C +# +# Usage: +# nmake -f Makefile.msc (standard build) +# +# run within src folder! + +# The toplevel directory of the source tree. +# +TOP = . + +# optional build flags +LOC = + +# variables +STATICLIB = libltc.lib +SHAREDLIB = libltc.dll +IMPLIB = libltc.lib + +CC = cl +AS = ml +LD = link +AR = lib +RC = rc +CFLAGS = -nologo /MT -W3 -O2 -Oy- -Fd"libltc" $(LOC) /GF -DWIN32 /TC +WFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE +ASFLAGS = -coff -Zi $(LOC) +LDFLAGS = -nologo -incremental:no -opt:ref +ARFLAGS = -nologo +RCFLAGS = /dWIN32 /r + +OBJS = ltc.obj encoder.obj decoder.obj timecode.obj +OBJA = + +# + + +# targets +all: $(STATICLIB) $(SHAREDLIB) + +$(STATICLIB): $(OBJS) $(OBJA) + $(AR) $(ARFLAGS) -out:$@ $(OBJS) $(OBJA) + +$(SHAREDLIB): $(OBJS) $(OBJA) libltc.res + $(LD) $(LDFLAGS) -dll -implib:$(IMPLIB) \ + -out:$@ $(OBJS) $(OBJA) -def:$(TOP)/libltc.def libltc.res + + +libltc.res: $(TOP)/libltc.rc + $(RC) $(RCFLAGS) /fo$@ $(TOP)/libltc.rc + +{$(TOP)}.c.obj: + $(CC) -c $(WFLAGS) $(CFLAGS) $< + + + + +# cleanup +clean: + -del $(STATICLIB) + -del $(SHAREDLIB) + -del $(IMPLIB) + -del *.obj + -del *.res + -del *.exp + -del *.exe + -del *.pdb + -del *.manifest + \ No newline at end of file diff --git a/src/decoder.c b/src/decoder.c index 417aeb2..5173019 100644 --- a/src/decoder.c +++ b/src/decoder.c @@ -106,7 +106,13 @@ #endif #if (!defined INFINITY && defined _MSC_VER) + +#ifdef __cplusplus #define INFINITY std::numeric_limits::infinity() +#else +// #define INFINITY +#endif + #endif #if (!defined INFINITY && defined HUGE_VAL) #define INFINITY HUGE_VAL @@ -125,7 +131,7 @@ static void parse_ltc(LTCDecoder *d, unsigned char bit, ltc_off_t offset, ltc_of memset(&d->ltc_frame, 0, sizeof(LTCFrame)); if (d->frame_start_prev < 0) { - d->frame_start_off = posinfo - d->snd_to_biphase_period; + d->frame_start_off = (ltc_off_t) (posinfo - d->snd_to_biphase_period); } else { d->frame_start_off = d->frame_start_prev; } @@ -153,7 +159,7 @@ static void parse_ltc(LTCDecoder *d, unsigned char bit, ltc_off_t offset, ltc_of ((unsigned char*)&d->ltc_frame)[k] = bo; } - d->frame_start_off += ceil(d->snd_to_biphase_period); + d->frame_start_off += (ltc_off_t) ceil(d->snd_to_biphase_period); d->bit_cnt--; } @@ -243,9 +249,9 @@ static void parse_ltc(LTCDecoder *d, unsigned char bit, ltc_off_t offset, ltc_of d->queue[d->queue_write_off].biphase_tics[bc] = d->biphase_tics[btc]; } - d->queue[d->queue_write_off].off_start = d->frame_start_off - 16 * d->snd_to_biphase_period; - d->queue[d->queue_write_off].off_end = posinfo + (ltc_off_t) offset - 1LL - 16 * d->snd_to_biphase_period; - d->queue[d->queue_write_off].reverse = (LTC_FRAME_BIT_COUNT >> 3) * 8 * d->snd_to_biphase_period; + d->queue[d->queue_write_off].off_start = (ltc_off_t) (d->frame_start_off - 16 * d->snd_to_biphase_period); + d->queue[d->queue_write_off].off_end = (ltc_off_t) (posinfo + (ltc_off_t) offset - 1LL - 16 * d->snd_to_biphase_period); + d->queue[d->queue_write_off].reverse = (int) ((LTC_FRAME_BIT_COUNT >> 3) * 8 * d->snd_to_biphase_period); d->queue[d->queue_write_off].volume = calc_volume_db(d); d->queue[d->queue_write_off].sample_min = d->snd_to_biphase_min; d->queue[d->queue_write_off].sample_max = d->snd_to_biphase_max; @@ -261,10 +267,10 @@ static void parse_ltc(LTCDecoder *d, unsigned char bit, ltc_off_t offset, ltc_of static inline void biphase_decode2(LTCDecoder *d, ltc_off_t offset, ltc_off_t pos) { - d->biphase_tics[d->biphase_tic] = d->snd_to_biphase_period; + d->biphase_tics[d->biphase_tic] = (float) d->snd_to_biphase_period; d->biphase_tic = (d->biphase_tic + 1) % LTC_FRAME_BIT_COUNT; if (d->snd_to_biphase_cnt <= 2 * d->snd_to_biphase_period) { - pos -= (d->snd_to_biphase_period - d->snd_to_biphase_cnt); + pos -= (ltc_off_t) (d->snd_to_biphase_period - d->snd_to_biphase_cnt); } if (d->snd_to_biphase_state == d->biphase_prev) { diff --git a/src/encoder.c b/src/encoder.c index ebc9095..45cd35c 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -29,8 +29,12 @@ * add values to the output buffer */ static int addvalues(LTCEncoder *e, int n) { + + double tcf; + ltcsnd_sample_t * wave; + const ltcsnd_sample_t tgtval = e->state ? e->enc_hi : e->enc_lo; - + if (e->offset + n >= e->bufsize) { #if 0 fprintf(stderr, "libltc: buffer overflow: %d/%lu\n", (int) e->offset, (unsigned long) e->bufsize); @@ -38,8 +42,8 @@ static int addvalues(LTCEncoder *e, int n) { return 1; } - ltcsnd_sample_t * const wave = &(e->buf[e->offset]); - const double tcf = e->filter_const; + wave = &(e->buf[e->offset]); + tcf = e->filter_const; if (tcf > 0) { /* low-pass-filter * LTC signal should have a rise time of 40 us +/- 10 us. @@ -51,10 +55,12 @@ static int addvalues(LTCEncoder *e, int n) { * e->cutoff = 1.0 -exp( -1.0 / (sample_rate * .000020 / exp(1.0)) ); */ int i; + int m; + ltcsnd_sample_t val = SAMPLE_CENTER; - int m = (n+1)>>1; + m = (n+1)>>1; for (i = 0 ; i < m ; i++) { - val = val + tcf * (tgtval - val); + val = (ltcsnd_sample_t) ( val + tcf * (tgtval - val)); wave[n-i-1] = wave[i] = val; } } else { @@ -67,14 +73,20 @@ static int addvalues(LTCEncoder *e, int n) { } int encode_byte(LTCEncoder *e, int byte, double speed) { + + int err = 0; + unsigned char c; + unsigned char b; + double spc; + double sph; + if (byte < 0 || byte > 9) return -1; if (speed ==0) return -1; - int err = 0; - const unsigned char c = ((unsigned char*)&e->f)[byte]; - unsigned char b = (speed < 0)?128:1; // bit - const double spc = e->samples_per_clock * fabs(speed); - const double sph = e->samples_per_clock_2 * fabs(speed); + c = ((unsigned char*)&e->f)[byte]; + b = (speed < 0)?128:1; // bit + spc = e->samples_per_clock * fabs(speed); + sph = e->samples_per_clock_2 * fabs(speed); do { diff --git a/src/libltc.def b/src/libltc.def new file mode 100644 index 0000000..8008e11 --- /dev/null +++ b/src/libltc.def @@ -0,0 +1,39 @@ +; libltc data compression library +EXPORTS + ltc_decoder_create + ltc_decoder_free + ltc_decoder_queue_flush + ltc_decoder_queue_length + ltc_decoder_read + ltc_decoder_write + ltc_decoder_write_float + ltc_decoder_write_s16 + ltc_decoder_write_u16 + ltc_encoder_buffer_flush + ltc_encoder_create + ltc_encoder_dec_timecode + ltc_encoder_encode_byte + ltc_encoder_encode_frame + ltc_encoder_free + ltc_encoder_get_buffer + ltc_encoder_get_buffersize + ltc_encoder_get_bufptr + ltc_encoder_get_frame + ltc_encoder_get_timecode + ltc_encoder_inc_timecode + ltc_encoder_reinit + ltc_encoder_reset + ltc_encoder_set_bufsize + ltc_encoder_set_filter + ltc_encoder_set_frame + ltc_encoder_set_timecode + ltc_encoder_set_user_bits + ltc_encoder_set_volume + ltc_frame_alignment + ltc_frame_decrement + ltc_frame_get_user_bits + ltc_frame_increment + ltc_frame_reset + ltc_frame_set_parity + ltc_frame_to_time + ltc_time_to_frame diff --git a/src/libltc.rc b/src/libltc.rc new file mode 100644 index 0000000..76e2311 --- /dev/null +++ b/src/libltc.rc @@ -0,0 +1,40 @@ +#include +#include "ltc.h" + +#ifdef GCC_WINDRES +VS_VERSION_INFO VERSIONINFO +#else +VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE +#endif + FILEVERSION LIBLTC_VERSION_MAJOR,LIBLTC_VERSION_MINOR,LIBLTC_VERSION_MICRO,0 + PRODUCTVERSION LIBLTC_VERSION_MAJOR,LIBLTC_VERSION_MINOR,LIBLTC_VERSION_MICRO,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS 1 +#else + FILEFLAGS 0 +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + BEGIN + VALUE "FileDescription", "Linear/Logitudinal Time Code (LTC) Library\0" + VALUE "FileVersion", LIBLTC_VERSION "\0" + VALUE "InternalName", "libltc.dll\0" + VALUE "LegalCopyright", "Copyright (C) Robin Gareus and Jan Weiß\0" + VALUE "OriginalFilename", "libltc.dll\0" + VALUE "ProductName", "libltc\0" + VALUE "ProductVersion", LIBLTC_VERSION "\0" + VALUE "Comments", "For more information visit https://x42.github.io/libltc/\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/src/ltc.c b/src/ltc.c index 03afb1d..8a10749 100644 --- a/src/ltc.c +++ b/src/ltc.c @@ -50,7 +50,7 @@ LTCDecoder* ltc_decoder_create(int apv, int queue_len) { } d->biphase_state = 1; d->snd_to_biphase_period = apv / 80; - d->snd_to_biphase_lmt = (d->snd_to_biphase_period * 3) / 4; + d->snd_to_biphase_lmt = (int) (d->snd_to_biphase_period * 3) / 4; d->snd_to_biphase_min = SAMPLE_CENTER; d->snd_to_biphase_max = SAMPLE_CENTER; @@ -90,9 +90,8 @@ void ltc_decoder_write_ ## FN (LTCDecoder *d, FORMAT *buf, size_t size, ltc_off_ } \ } -LTCWRITE_TEMPLATE(double, double, 128 + (buf[copyStart+i] * 127.0)) -LTCWRITE_TEMPLATE(float, float, 128 + (buf[copyStart+i] * 127.f)) -/* this relies on the compiler to use an arithmetic right-shift for signed values */ +LTCWRITE_TEMPLATE(float, float, 128 + (buf[copyStart+i] * 127.0)) +/* this relies on the compiler to use an arithemtic right-shift for signed values */ LTCWRITE_TEMPLATE(s16, short, 128 + (buf[copyStart+i] >> 8)) /* this relies on the compiler to use a logical right-shift for unsigned values */ LTCWRITE_TEMPLATE(u16, unsigned short, (buf[copyStart+i] >> 8)) @@ -128,10 +127,13 @@ int ltc_decoder_queue_length(LTCDecoder* d) { */ LTCEncoder* ltc_encoder_create(double sample_rate, double fps, enum LTC_TV_STANDARD standard, int flags) { + + LTCEncoder* e = NULL; + if (sample_rate < 1) return NULL; - LTCEncoder* e = (LTCEncoder*) calloc(1, sizeof(LTCEncoder)); + e = (LTCEncoder*) calloc(1, sizeof(LTCEncoder)); if (!e) return NULL; @@ -139,7 +141,7 @@ LTCEncoder* ltc_encoder_create(double sample_rate, double fps, enum LTC_TV_STAND e->enc_lo = 38; e->enc_hi = 218; - e->bufsize = 1 + ceil(sample_rate / fps); + e->bufsize = (size_t) (1 + ceil(sample_rate / fps)); e->buf = (ltcsnd_sample_t*) calloc(e->bufsize, sizeof(ltcsnd_sample_t)); if (!e->buf) { free(e); @@ -158,10 +160,13 @@ void ltc_encoder_free(LTCEncoder *e) { } int ltc_encoder_reinit(LTCEncoder *e, double sample_rate, double fps, enum LTC_TV_STANDARD standard, int flags) { + + size_t bufsize; + if (sample_rate < 1) return -1; - size_t bufsize = 1 + ceil(sample_rate / fps); + bufsize = (size_t) (1 + ceil(sample_rate / fps)); if (bufsize > e->bufsize) { return -1; } @@ -212,29 +217,22 @@ void ltc_encoder_reset(LTCEncoder *e) { e->offset = 0; } -double ltc_encoder_get_volume(LTCEncoder *e) { - ltcsnd_sample_t diff = (e->enc_hi - e->enc_lo) / 2; - return 20.0 * log10((double)diff / 127.0); -} - int ltc_encoder_set_volume(LTCEncoder *e, double dBFS) { + + double pp; + ltcsnd_sample_t diff; + if (dBFS > 0) return -1; - double pp = rint(127.0 * pow(10, dBFS/20.0)); + pp = rint(127.0 * pow(10, dBFS/20.0)); if (pp < 1 || pp > 127) return -1; - ltcsnd_sample_t diff = ((ltcsnd_sample_t) pp)&0x7f; + diff = ((ltcsnd_sample_t) pp)&0x7f; e->enc_lo = SAMPLE_CENTER - diff; e->enc_hi = SAMPLE_CENTER + diff; return 0; } -double ltc_encoder_get_filter(LTCEncoder *e) { - const double num = -2000000.0 * exp(1.0); - const double den = e->sample_rate * log(1.0 - e->filter_const); - return num / den; -} - void ltc_encoder_set_filter(LTCEncoder *e, double rise_time) { /* low-pass-filter * LTC signal should have a rise time of 40 us +/- 10 us. @@ -250,10 +248,10 @@ void ltc_encoder_set_filter(LTCEncoder *e, double rise_time) { e->filter_const = 1.0 - exp( -1.0 / (e->sample_rate * rise_time / 2000000.0 / exp(1.0)) ); } -int ltc_encoder_set_buffersize(LTCEncoder *e, double sample_rate, double fps) { +int ltc_encoder_set_bufsize(LTCEncoder *e, double sample_rate, double fps) { free (e->buf); e->offset = 0; - e->bufsize = 1 + ceil(sample_rate / fps); + e->bufsize = (size_t) (1 + ceil(sample_rate / fps)); e->buf = (ltcsnd_sample_t*) calloc(e->bufsize, sizeof(ltcsnd_sample_t)); if (!e->buf) { return -1; @@ -261,10 +259,6 @@ int ltc_encoder_set_buffersize(LTCEncoder *e, double sample_rate, double fps) { return 0; } -int ltc_encoder_set_bufsize(LTCEncoder *e, double sample_rate, double fps) { - return ltc_encoder_set_buffersize(e, sample_rate, fps); -} - int ltc_encoder_encode_byte(LTCEncoder *e, int byte, double speed) { return encode_byte(e, byte, speed); } @@ -276,13 +270,6 @@ void ltc_encoder_encode_frame(LTCEncoder *e) { } } -void ltc_encoder_encode_reversed_frame(LTCEncoder *e) { - int byte; - for (byte = 9 ; byte >= 0 ; --byte) { - encode_byte(e, byte, -1.0); - } -} - void ltc_encoder_get_timecode(LTCEncoder *e, SMPTETimecode *t) { ltc_frame_to_time(t, &e->f, e->flags); } @@ -308,6 +295,7 @@ void ltc_encoder_set_user_bits(LTCEncoder *e, unsigned long data){ f->user7 = data & 0xF; data >>= 4; f->user8 = data & 0xF; + data >>= 4; } unsigned long ltc_frame_get_user_bits(LTCFrame *f){ @@ -339,11 +327,11 @@ void ltc_encoder_set_frame(LTCEncoder *e, LTCFrame *f) { } int ltc_encoder_inc_timecode(LTCEncoder *e) { - return ltc_frame_increment (&e->f, rint(e->fps), e->standard, e->flags); + return ltc_frame_increment (&e->f, (int) rint(e->fps), e->standard, e->flags); } int ltc_encoder_dec_timecode(LTCEncoder *e) { - return ltc_frame_decrement (&e->f, rint(e->fps), e->standard, e->flags); + return ltc_frame_decrement (&e->f, (int) rint(e->fps), e->standard, e->flags); } size_t ltc_encoder_get_buffersize(LTCEncoder *e) { @@ -354,28 +342,17 @@ void ltc_encoder_buffer_flush(LTCEncoder *e) { e->offset = 0; } -int ltc_encoder_get_bufferptr(LTCEncoder *e, ltcsnd_sample_t **buf, int flush) { - const int len = e->offset; - if (buf) *buf = e->buf; - if (flush) e->offset = 0; - return len; -} - ltcsnd_sample_t *ltc_encoder_get_bufptr(LTCEncoder *e, int *size, int flush) { if (size) *size = e->offset; if (flush) e->offset = 0; return e->buf; } -int ltc_encoder_copy_buffer(LTCEncoder *e, ltcsnd_sample_t *buf) { - const int len = e->offset; +int ltc_encoder_get_buffer(LTCEncoder *e, ltcsnd_sample_t *buf) { + const int len = (int) e->offset; memcpy(buf, e->buf, len * sizeof(ltcsnd_sample_t) ); e->offset = 0; - return len; -} - -int ltc_encoder_get_buffer(LTCEncoder *e, ltcsnd_sample_t *buf) { - return ltc_encoder_copy_buffer(e, buf); + return(len); } void ltc_frame_set_parity(LTCFrame *frame, enum LTC_TV_STANDARD standard) { @@ -405,9 +382,9 @@ void ltc_frame_set_parity(LTCFrame *frame, enum LTC_TV_STANDARD standard) { ltc_off_t ltc_frame_alignment(double samples_per_frame, enum LTC_TV_STANDARD standard) { switch (standard) { case LTC_TV_525_60: - return rint(samples_per_frame * 4.0 / 525.0); + return (ltc_off_t) rint(samples_per_frame * 4.0 / 525.0); case LTC_TV_625_50: - return rint(samples_per_frame * 1.0 / 625.0); + return (ltc_off_t) rint(samples_per_frame * 1.0 / 625.0); default: return 0; }