2 // Copyright (C) 2008 Tim Blechmann
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.
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.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef UTILITIES_TIME_TAG_HPP
20 #define UTILITIES_TIME_TAG_HPP
25 #include "boost/date_time/posix_time/posix_time_types.hpp"
26 #include "boost/date_time/gregorian/gregorian_types.hpp"
30 /** time_tag class, compatible to osc time tags */
33 typedef std::uint32_t uint32
;
34 typedef std::uint64_t uint64
;
42 static const uint32 ntp_offset
= 2208988800UL; /* seconds between 01-01-1900 and 01-01-1970 */
45 static const uint64 fraction_steps
= uint64(1)<<32;
51 time_tag(time_tag
const & rhs
):
55 time_tag(uint64 timetag
):
59 time_tag(uint32 secs
, uint32 fraction
)
62 cu
.unpacked
[1] = secs
;
63 cu
.unpacked
[0] = fraction
;
68 uint32
get_secs(void) const
70 return reinterpret_cast<const cast_union
*>(&data_
)->unpacked
[1];
73 uint32
get_fraction(void) const
75 return reinterpret_cast<const cast_union
*>(&data_
)->unpacked
[0];
78 double get_nanoseconds(void) const
80 return get_fractional_seconds() * 1e9
;
83 double get_fractional_seconds(void) const
85 return get_fraction() / double(fraction_steps
);
88 bool operator<(time_tag
const & rhs
) const
90 return data_
< rhs
.data_
;
93 bool operator<=(time_tag
const & rhs
) const
95 return data_
<= rhs
.data_
;
98 bool operator==(time_tag
const & rhs
) const
100 return data_
== rhs
.data_
;
103 bool operator!=(time_tag
const & rhs
) const
105 return !operator==(rhs
);
108 time_tag
& operator+=(time_tag
const & rhs
)
114 time_tag
operator+(time_tag
const & rhs
) const
116 time_tag
ret (*this);
121 time_tag
& operator-=(time_tag
const & rhs
)
127 time_tag
operator-(time_tag
const & rhs
) const
129 time_tag
ret (*this);
134 template <typename float_t
>
135 static time_tag
from_ns(float_t ns
)
137 const float_t units_per_ns
= float_t(fraction_steps
) / 1e9
;
140 return time_tag(0, ns
* units_per_ns
);
143 float_t secs
= std::floor(ns
/ 1e9
);
144 ns
= std::fmod(ns
, 1e9
);
145 return time_tag(secs
, ns
* units_per_ns
);
149 static time_tag
from_samples_small(unsigned int sample_count
, float samplerate
)
151 assert(sample_count
< samplerate
);
153 const float units_per_sample
= float(fraction_steps
) / samplerate
;
154 return time_tag(0, sample_count
* units_per_sample
);
157 static time_tag
from_samples(unsigned int sample_count
, float samplerate
)
159 const float_t units_per_sample
= float_t(fraction_steps
) / samplerate
;
161 if (sample_count
< samplerate
)
162 return from_samples_small(sample_count
, samplerate
);
165 float_t secs
= std::floor(sample_count
/ samplerate
);
166 float_t samples
= std::fmod(sample_count
, samplerate
);
167 return time_tag(secs
, samples
* units_per_sample
);
171 float to_samples(float samplerate
)
173 float seconds
= get_fractional_seconds();
174 uint32_t secs
= get_secs();
177 seconds
+= (float)secs
;
178 return seconds
* samplerate
;
181 static time_tag
from_ptime(boost::posix_time::ptime
const & pt
)
183 using namespace boost::gregorian
;
184 using namespace boost::posix_time
;
186 const date
base(1970, Jan
, 1);
188 time_duration diff
= pt
- ptime(base
);
190 uint32 secs
= diff
.total_seconds() + ntp_offset
;
192 double fraction
= double(diff
.fractional_seconds());
194 if (diff
.resolution() == boost::date_time::nano
)
195 fraction
/= 1000000000;
196 else if (diff
.resolution() == boost::date_time::micro
)
198 else if (diff
.resolution() == boost::date_time::milli
)
203 assert (fraction
< 1.0 && fraction
>= 0);
205 uint32 fraction_units
= std::floor(fraction
* double(std::numeric_limits
<uint32
>::max()));
206 return time_tag(secs
, fraction_units
);
209 boost::posix_time::ptime
to_ptime(void) const
211 using namespace boost::gregorian
;
212 using namespace boost::posix_time
;
214 const date
base(1970, Jan
, 1);
215 #ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
216 time_duration offset
= seconds(get_secs() - ntp_offset
) + nanoseconds(get_nanoseconds());
218 time_duration offset
= seconds(get_secs() - ntp_offset
) + microseconds(get_nanoseconds()/1000);
220 return ptime(base
, offset
);
227 } /* namespace nova */
229 #endif /* UTILITIES_TIME_TAG_HPP */