Merge branch 'windows+cc' into cairocanvas
[ardour.git] / libs / libltc / encoder.c
1 /*
2    libltc - en+decode linear timecode
3
4    Copyright (C) 2006-2012 Robin Gareus <robin@gareus.org>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU Lesser General Public License as
8    published by the Free Software Foundation, either version 3 of the
9    License, or (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library.
18    If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
25
26 #include "ltc/encoder.h"
27
28 /**
29  * add values to the output buffer
30  */
31 static int addvalues(LTCEncoder *e, int n) {
32         const ltcsnd_sample_t tgtval = e->state ? e->enc_hi : e->enc_lo;
33
34         if (e->offset + n >= e->bufsize) {
35                 fprintf(stderr, "libltc: buffer overflow: %d/%lu\n", (int) e->offset, (unsigned long) e->bufsize);
36                 return 1;
37         }
38
39         ltcsnd_sample_t * const wave = &(e->buf[e->offset]);
40         const double tcf =  e->filter_const;
41         if (tcf > 0) {
42                 /* low-pass-filter
43                  * LTC signal should have a rise time of 40 us +/- 10 us.
44                  *
45                  * rise-time means from <10% to >90% of the signal.
46                  * in each call to addvalues() we start at 50%, so
47                  * here we need half-of it. (0.000020 sec)
48                  *
49                  * e->cutoff = 1.0 -exp( -1.0 / (sample_rate * .000020 / exp(1.0)) );
50                  */
51                 int i;
52                 ltcsnd_sample_t val = SAMPLE_CENTER;
53                 int m = (n+1)>>1;
54                 for (i = 0 ; i < m ; i++) {
55                         val = val + tcf * (tgtval - val);
56                         wave[n-i-1] = wave[i] = val;
57                 }
58         } else {
59                 /* perfect square wave */
60                 memset(wave, tgtval, n);
61         }
62
63         e->offset += n;
64         return 0;
65 }
66
67 int encode_byte(LTCEncoder *e, int byte, double speed) {
68         if (byte < 0 || byte > 9) return -1;
69         if (speed ==0) return -1;
70
71         int err = 0;
72         const unsigned char c = ((unsigned char*)&e->f)[byte];
73         unsigned char b = (speed < 0)?128:1; // bit
74         const double spc = e->samples_per_clock * fabs(speed);
75         const double sph = e->samples_per_clock_2 * fabs(speed);
76
77         do
78         {
79                 int n;
80                 if ((c & b) == 0) {
81                         n = (int)(spc + e->sample_remainder);
82                         e->sample_remainder = spc + e->sample_remainder - n;
83                         e->state = !e->state;
84                         err |= addvalues(e, n);
85                 } else {
86                         n = (int)(sph + e->sample_remainder);
87                         e->sample_remainder = sph + e->sample_remainder - n;
88                         e->state = !e->state;
89                         err |= addvalues(e, n);
90
91                         n = (int)(sph + e->sample_remainder);
92                         e->sample_remainder = sph + e->sample_remainder - n;
93                         e->state = !e->state;
94                         err |= addvalues(e, n);
95                 }
96                 /* this is based on the assumption that with every compiler
97                  * ((unsigned char) 128)<<1 == ((unsigned char 1)>>1) == 0
98                  */
99                 if (speed < 0)
100                         b >>= 1;
101                 else
102                         b <<= 1;
103         } while (b);
104
105         return err;
106 }