1 /* 2 * Copyright (C) 2017 Paul Davis <paul@linuxaudiosystems.com> 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 of the License, or 7 * (at your option) 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 along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 */ 18 19 #ifndef __timecode_time_h__ 20 #define __timecode_time_h__ 21 22 #include <cmath> 23 #include <inttypes.h> 24 #include <ostream> 25 26 #include "temporal/visibility.h" 27 28 namespace Timecode 29 { 30 31 enum Wrap { 32 NONE = 0, 33 FRAMES, 34 SECONDS, 35 MINUTES, 36 HOURS 37 }; 38 39 enum TimecodeFormat { 40 timecode_23976, 41 timecode_24, 42 timecode_24976, 43 timecode_25, 44 timecode_2997, 45 timecode_2997drop, 46 timecode_2997000, 47 timecode_2997000drop, 48 timecode_30, 49 timecode_30drop, 50 timecode_5994, 51 timecode_60 52 }; 53 54 struct LIBTEMPORAL_API Time { 55 bool negative; 56 uint32_t hours; 57 uint32_t minutes; 58 uint32_t seconds; 59 uint32_t frames; ///< Timecode frames (not audio frames) 60 uint32_t subframes; ///< Typically unused 61 double rate; ///< Frame rate of this Time 62 static double default_rate; ///< Rate to use for default constructor 63 bool drop; ///< Whether this Time uses dropframe Timecode 64 65 Time (double a_rate = default_rate) 66 { 67 negative = false; 68 hours = 0; 69 minutes = 0; 70 seconds = 0; 71 frames = 0; 72 subframes = 0; 73 rate = a_rate; 74 drop = (lrintf (100.f * (float)a_rate) == (long)2997); 75 } 76 77 bool operator== (const Time& other) const 78 { 79 return negative == other.negative && hours == other.hours && 80 minutes == other.minutes && seconds == other.seconds && 81 frames == other.frames && subframes == other.subframes && 82 rate == other.rate && drop == other.drop; 83 } 84 printTime85 std::ostream& print (std::ostream& ostr) const 86 { 87 if (negative) { 88 ostr << '-'; 89 } 90 ostr << hours << ':' << minutes << ':' << seconds << ':' 91 << frames << '.' << subframes 92 << " @" << rate << (drop ? " drop" : " nondrop"); 93 return ostr; 94 } 95 }; 96 97 Wrap LIBTEMPORAL_API increment (Time& timecode, uint32_t); 98 Wrap LIBTEMPORAL_API decrement (Time& timecode, uint32_t); 99 Wrap LIBTEMPORAL_API increment_subframes (Time& timecode, uint32_t); 100 Wrap LIBTEMPORAL_API decrement_subframes (Time& timecode, uint32_t); 101 Wrap LIBTEMPORAL_API increment_seconds (Time& timecode, uint32_t); 102 Wrap LIBTEMPORAL_API increment_minutes (Time& timecode, uint32_t); 103 Wrap LIBTEMPORAL_API increment_hours (Time& timecode, uint32_t); 104 void LIBTEMPORAL_API frames_floot (Time& timecode); 105 void LIBTEMPORAL_API seconds_floor (Time& timecode); 106 void LIBTEMPORAL_API minutes_floor (Time& timecode); 107 void LIBTEMPORAL_API hours_floor (Time& timecode); 108 109 double LIBTEMPORAL_API timecode_to_frames_per_second (TimecodeFormat const t); 110 bool LIBTEMPORAL_API timecode_has_drop_frames (TimecodeFormat const t); 111 112 std::string LIBTEMPORAL_API timecode_format_name (TimecodeFormat const t); 113 std::string LIBTEMPORAL_API timecode_format_time (Timecode::Time const timecode); 114 115 bool LIBTEMPORAL_API parse_timecode_format (std::string tc, Timecode::Time& TC); 116 117 std::string LIBTEMPORAL_API 118 timecode_format_sampletime ( 119 int64_t sample, 120 double sample_sample_rate, 121 double timecode_frames_per_second, bool timecode_drop_frames); 122 123 /** Convert timecode (frames per second) to audio sample time (samples per second) 124 * 125 * @param timecode Timecode to convert (also includes frame-rate) 126 * @param sample returned corresponding audio sample time 127 * @param use_offset apply offset as given by \p offset_is_negative and \p offset_samples 128 * @param use_subframes use \p subframes_per_frame when converting 129 * @param sample_sample_rate target sample-rate, may include pull up/down 130 * @param subframes_per_frame sub-frames per frame -- must not be 0 if \p use_subframes \c == \c true 131 * @param offset_is_negative true if offset_samples is to be subtracted 132 * @param offset_samples sample offset to add or subtract 133 */ 134 void LIBTEMPORAL_API 135 timecode_to_sample ( 136 Timecode::Time const& timecode, int64_t& sample, 137 bool use_offset, bool use_subframes, 138 double sample_sample_rate, 139 uint32_t subframes_per_frame, 140 bool offset_is_negative, int64_t offset_samples); 141 142 /** Convert audio sample time (samples per second) to timecode (frames per second) 143 * 144 * @param sample audio sample time to convert 145 * @param timecode resulting Timecode 146 * @param use_offset apply offset as given by \p offset_is_negative and \p offset_samples 147 * @param use_subframes use \p subframes_per_frame when converting 148 * @param timecode_frames_per_second target framerate 149 * @param timecode_drop_frames true if fps uses drop-frame-counting. only valid for \c 29.97 \c = \c 30000/1001 fps 150 * @param sample_sample_rate source sample-rate, may include pull up/down 151 * @param subframes_per_frame sub-frames per frame -- must not be 0 if \p use_subframes \c == \c true 152 * @param offset_is_negative true if offset_samples is to be subtracted 153 * @param offset_samples sample offset to add or subtract 154 */ 155 void LIBTEMPORAL_API 156 sample_to_timecode ( 157 int64_t sample, Timecode::Time& timecode, 158 bool use_offset, bool use_subframes, 159 double timecode_frames_per_second, 160 bool timecode_drop_frames, 161 double sample_sample_rate, 162 uint32_t subframes_per_frame, 163 bool offset_is_negative, int64_t offset_samples); 164 165 } // namespace Timecode 166 167 extern LIBTEMPORAL_API std::ostream& operator<< (std::ostream& ostr, const Timecode::Time& t); 168 169 #endif // __timecode_time_h__ 170