1 /*
2 Copyright (C) 2013 Robin Gareus <robin@gareus.org>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21
22 #include "timecode.h"
23
24 #define TCtoDbl(r) ( (double)((r)->num) / (double)((r)->den) )
25
timecode_rate_to_double(TimecodeRate const * const r)26 double timecode_rate_to_double(TimecodeRate const * const r) {
27 return TCtoDbl(r);
28 }
29
timecode_sample_to_time(TimecodeTime * const t,TimecodeRate const * const r,const double samplerate,const int64_t sample)30 static void timecode_sample_to_time (TimecodeTime * const t, TimecodeRate const * const r, const double samplerate, const int64_t sample) {
31 const double fps_d = TCtoDbl(r);
32 const int64_t fps_i = ceil(fps_d);
33
34 if (r->drop) {
35 int64_t frameNumber = floor((double)sample * fps_d / samplerate);
36
37 /* there are 17982 frames in 10 min @ 29.97df */
38 const int64_t D = frameNumber / 17982;
39 const int64_t M = frameNumber % 17982;
40
41 t->subframe = rint(r->subframes * ((double)sample * fps_d / samplerate - (double)frameNumber));
42
43 if (t->subframe == r->subframes && r->subframes != 0) {
44 t->subframe = 0;
45 frameNumber++;
46 }
47
48 frameNumber += 18*D + 2*((M - 2) / 1798);
49
50 t->frame = frameNumber % 30;
51 t->second = (frameNumber / 30) % 60;
52 t->minute = ((frameNumber / 30) / 60) % 60;
53 t->hour = (((frameNumber / 30) / 60) / 60);
54
55 } else {
56 double timecode_frames_left_exact;
57 double timecode_frames_fraction;
58 int64_t timecode_frames_left;
59 const double frames_per_timecode_frame = samplerate / fps_d;
60 const int64_t frames_per_hour = (int64_t)(3600 * fps_i * frames_per_timecode_frame);
61
62 t->hour = sample / frames_per_hour;
63 double sample_d = sample % frames_per_hour;
64
65 timecode_frames_left_exact = sample_d / frames_per_timecode_frame;
66 timecode_frames_fraction = timecode_frames_left_exact - floor(timecode_frames_left_exact);
67
68 t->subframe = (int32_t) rint(timecode_frames_fraction * r->subframes);
69
70 timecode_frames_left = (int64_t) floor (timecode_frames_left_exact);
71
72 if (t->subframe == r->subframes && r->subframes != 0) {
73 t->subframe = 0;
74 timecode_frames_left++;
75 }
76
77 t->minute = timecode_frames_left / (fps_i * 60);
78 timecode_frames_left = timecode_frames_left % (fps_i * 60);
79 t->second = timecode_frames_left / fps_i;
80 t->frame = timecode_frames_left % fps_i;
81 }
82 }
83
timecode_framenumber_to_time(TimecodeTime * const t,TimecodeRate const * const r,const int64_t frameno)84 void timecode_framenumber_to_time (TimecodeTime * const t, TimecodeRate const * const r, const int64_t frameno) {
85 timecode_sample_to_time(t, r, TCtoDbl(r), frameno);
86 }
87
timecode_time_to_string(char * smptestring,TimecodeTime const * const t)88 void timecode_time_to_string (char *smptestring, TimecodeTime const * const t) {
89 snprintf(smptestring, 12, "%02d:%02d:%02d:%02d",
90 t->hour, t->minute, t->second, t->frame);
91 }
92
timecode_framenumber_to_string(char * smptestring,TimecodeRate const * const r,const int64_t frameno)93 void timecode_framenumber_to_string (char *smptestring, TimecodeRate const * const r, const int64_t frameno) {
94 TimecodeTime t;
95 timecode_framenumber_to_time(&t, r, frameno);
96 timecode_time_to_string(smptestring, &t);
97 }
98
99 // vim:sw=2 sts=2 ts=8 et:
100