summaryrefslogtreecommitdiff
path: root/libs/libltc/encoder.c
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-12-14 16:18:47 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-12-14 16:18:47 +0000
commitc9c94ca1c247adfc1a78fda0eda185a9a7589696 (patch)
tree52d520020e7ff2455b8abf83fbcc69a4ba02b9ca /libs/libltc/encoder.c
parentfd1414f6668712c641da6c7d51f4b3e2bf6fae5a (diff)
merge robin gareus' libltc into ardour source tree for convenience
git-svn-id: svn://localhost/ardour2/branches/3.0@13665 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/libltc/encoder.c')
-rw-r--r--libs/libltc/encoder.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/libs/libltc/encoder.c b/libs/libltc/encoder.c
new file mode 100644
index 0000000000..fce2a0ce51
--- /dev/null
+++ b/libs/libltc/encoder.c
@@ -0,0 +1,106 @@
+/*
+ libltc - en+decode linear timecode
+
+ Copyright (C) 2006-2012 Robin Gareus <robin@gareus.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "ltc/encoder.h"
+
+/**
+ * add values to the output buffer
+ */
+static int addvalues(LTCEncoder *e, int n) {
+ const ltcsnd_sample_t tgtval = e->state ? e->enc_hi : e->enc_lo;
+
+ if (e->offset + n >= e->bufsize) {
+ fprintf(stderr, "libltc: buffer overflow: %d/%lu\n", (int) e->offset, (unsigned long) e->bufsize);
+ return 1;
+ }
+
+ ltcsnd_sample_t * const wave = &(e->buf[e->offset]);
+ const double tcf = e->filter_const;
+ if (tcf > 0) {
+ /* low-pass-filter
+ * LTC signal should have a rise time of 40 us +/- 10 us.
+ *
+ * rise-time means from <10% to >90% of the signal.
+ * in each call to addvalues() we start at 50%, so
+ * here we need half-of it. (0.000020 sec)
+ *
+ * e->cutoff = 1.0 -exp( -1.0 / (sample_rate * .000020 / exp(1.0)) );
+ */
+ int i;
+ ltcsnd_sample_t val = SAMPLE_CENTER;
+ int m = (n+1)>>1;
+ for (i = 0 ; i < m ; i++) {
+ val = val + tcf * (tgtval - val);
+ wave[n-i-1] = wave[i] = val;
+ }
+ } else {
+ /* perfect square wave */
+ memset(wave, tgtval, n);
+ }
+
+ e->offset += n;
+ return 0;
+}
+
+int encode_byte(LTCEncoder *e, int byte, double speed) {
+ 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);
+
+ do
+ {
+ int n;
+ if ((c & b) == 0) {
+ n = (int)(spc + e->sample_remainder);
+ e->sample_remainder = spc + e->sample_remainder - n;
+ e->state = !e->state;
+ err |= addvalues(e, n);
+ } else {
+ n = (int)(sph + e->sample_remainder);
+ e->sample_remainder = sph + e->sample_remainder - n;
+ e->state = !e->state;
+ err |= addvalues(e, n);
+
+ n = (int)(sph + e->sample_remainder);
+ e->sample_remainder = sph + e->sample_remainder - n;
+ e->state = !e->state;
+ err |= addvalues(e, n);
+ }
+ /* this is based on the assumption that with every compiler
+ * ((unsigned char) 128)<<1 == ((unsigned char 1)>>1) == 0
+ */
+ if (speed < 0)
+ b >>= 1;
+ else
+ b <<= 1;
+ } while (b);
+
+ return err;
+}