summaryrefslogtreecommitdiff
path: root/libs/temporal/temporal/time.h
blob: e527965d99ebedbdb4dd2e81c9ccee811e7aef69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
 * Copyright (C) 2017 Paul Davis <paul@linuxaudiosystems.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef __timecode_time_h__
#define __timecode_time_h__

#include <cmath>
#include <inttypes.h>
#include <ostream>

#include "temporal/visibility.h"

namespace Timecode
{

enum Wrap {
	NONE = 0,
	FRAMES,
	SECONDS,
	MINUTES,
	HOURS
};

enum TimecodeFormat {
	timecode_23976,
	timecode_24,
	timecode_24976,
	timecode_25,
	timecode_2997,
	timecode_2997drop,
	timecode_2997000,
	timecode_2997000drop,
	timecode_30,
	timecode_30drop,
	timecode_5994,
	timecode_60
};

struct LIBTEMPORAL_API Time {
	bool          negative;
	uint32_t      hours;
	uint32_t      minutes;
	uint32_t      seconds;
	uint32_t      frames;       ///< Timecode frames (not audio frames)
	uint32_t      subframes;    ///< Typically unused
	double        rate;         ///< Frame rate of this Time
	static double default_rate; ///< Rate to use for default constructor
	bool          drop;         ///< Whether this Time uses dropframe Timecode

	Time (double a_rate = default_rate)
	{
		negative  = false;
		hours     = 0;
		minutes   = 0;
		seconds   = 0;
		frames    = 0;
		subframes = 0;
		rate      = a_rate;
		drop      = (lrintf (100.f * (float)a_rate) == (long)2997);
	}

	bool operator== (const Time& other) const
	{
		return negative == other.negative && hours == other.hours &&
		       minutes == other.minutes && seconds == other.seconds &&
		       frames == other.frames && subframes == other.subframes &&
		       rate == other.rate && drop == other.drop;
	}

	std::ostream& print (std::ostream& ostr) const
	{
		if (negative) {
			ostr << '-';
		}
		ostr << hours << ':' << minutes << ':' << seconds << ':'
		     << frames << '.' << subframes
		     << " @" << rate << (drop ? " drop" : " nondrop");
		return ostr;
	}
};

Wrap LIBTEMPORAL_API increment (Time& timecode, uint32_t);
Wrap LIBTEMPORAL_API decrement (Time& timecode, uint32_t);
Wrap LIBTEMPORAL_API increment_subframes (Time& timecode, uint32_t);
Wrap LIBTEMPORAL_API decrement_subframes (Time& timecode, uint32_t);
Wrap LIBTEMPORAL_API increment_seconds (Time& timecode, uint32_t);
Wrap LIBTEMPORAL_API increment_minutes (Time& timecode, uint32_t);
Wrap LIBTEMPORAL_API increment_hours (Time& timecode, uint32_t);
void LIBTEMPORAL_API frames_floot (Time& timecode);
void LIBTEMPORAL_API seconds_floor (Time& timecode);
void LIBTEMPORAL_API minutes_floor (Time& timecode);
void LIBTEMPORAL_API hours_floor (Time& timecode);

double LIBTEMPORAL_API timecode_to_frames_per_second (TimecodeFormat const t);
bool LIBTEMPORAL_API timecode_has_drop_frames (TimecodeFormat const t);

std::string LIBTEMPORAL_API timecode_format_name (TimecodeFormat const t);
std::string LIBTEMPORAL_API timecode_format_time (Timecode::Time const timecode);

bool LIBTEMPORAL_API parse_timecode_format (std::string tc, Timecode::Time& TC);

std::string LIBTEMPORAL_API
timecode_format_sampletime (
    int64_t sample,
    double  sample_sample_rate,
    double timecode_frames_per_second, bool timecode_drop_frames);

/** Convert timecode (frames per second) to audio sample time (samples per second)
 *
 * @param timecode Timecode to convert (also includes frame-rate)
 * @param sample returned corresponding audio sample time
 * @param use_offset apply offset as given by \p offset_is_negative and \p offset_samples
 * @param use_subframes use \p subframes_per_frame when converting
 * @param sample_sample_rate target sample-rate, may include pull up/down
 * @param subframes_per_frame sub-frames per frame -- must not be 0 if \p use_subframes \c == \c true
 * @param offset_is_negative true if offset_samples is to be subtracted
 * @param offset_samples sample offset to add or subtract
 */
void LIBTEMPORAL_API
timecode_to_sample (
    Timecode::Time const& timecode, int64_t& sample,
    bool use_offset, bool use_subframes,
    double   sample_sample_rate,
    uint32_t subframes_per_frame,
    bool offset_is_negative, int64_t offset_samples);

/** Convert audio sample time (samples per second) to timecode (frames per second)
 *
 * @param sample audio sample time to convert
 * @param timecode resulting Timecode
 * @param use_offset apply offset as given by \p offset_is_negative and \p offset_samples
 * @param use_subframes use \p subframes_per_frame when converting
 * @param timecode_frames_per_second target framerate
 * @param timecode_drop_frames true if fps uses drop-frame-counting. only valid for \c 29.97 \c = \c 30000/1001 fps
 * @param sample_sample_rate source sample-rate, may include pull up/down
 * @param subframes_per_frame sub-frames per frame -- must not be 0 if \p use_subframes \c == \c true
 * @param offset_is_negative true if offset_samples is to be subtracted
 * @param offset_samples sample offset to add or subtract
 */
void LIBTEMPORAL_API
sample_to_timecode (
    int64_t sample, Timecode::Time& timecode,
    bool use_offset, bool use_subframes,
    double   timecode_frames_per_second,
    bool     timecode_drop_frames,
    double   sample_sample_rate,
    uint32_t subframes_per_frame,
    bool offset_is_negative, int64_t offset_samples);

} // namespace Timecode

extern LIBTEMPORAL_API std::ostream& operator<< (std::ostream& ostr, const Timecode::Time& t);

#endif // __timecode_time_h__