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
22 #include <boost/cstdint.hpp>
25 #ifdef BOOST_NO_INT64_T
26 #error "boost doesn't support int64 types"
29 #include "boost/date_time/posix_time/posix_time_types.hpp"
30 #include "boost/date_time/gregorian/gregorian_types.hpp"
35 /** time_tag class, compatible to osc time tags */
38 typedef boost::uint32_t uint32
;
39 typedef boost::uint64_t uint64
;
47 static const uint32 ntp_offset
= 2208988800UL; /* seconds between 01-01-1900 and 01-01-1970 */
50 static const uint64 fraction_steps
= uint64(1)<<32;
56 time_tag(time_tag
const & rhs
):
60 time_tag(uint64 timetag
):
64 time_tag(uint32 secs
, uint32 fraction
)
67 cu
.unpacked
[1] = secs
;
68 cu
.unpacked
[0] = fraction
;
73 uint32
get_secs(void) const
75 return reinterpret_cast<const cast_union
*>(&data_
)->unpacked
[1];
78 uint32
get_fraction(void) const
80 return reinterpret_cast<const cast_union
*>(&data_
)->unpacked
[0];
83 double get_nanoseconds(void) const
85 return get_fractional_seconds() * 1e9
;
88 double get_fractional_seconds(void) const
90 return get_fraction() / double(fraction_steps
);
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 data_
== rhs
.data_
;
108 bool operator!=(time_tag
const & rhs
) const
110 return !operator==(rhs
);
113 time_tag
& operator+=(time_tag
const & rhs
)
119 time_tag
operator+(time_tag
const & rhs
) const
121 time_tag
ret (*this);
126 time_tag
& operator-=(time_tag
const & rhs
)
132 time_tag
operator-(time_tag
const & rhs
) const
134 time_tag
ret (*this);
139 template <typename float_t
>
140 static time_tag
from_ns(float_t ns
)
142 const float_t units_per_ns
= float_t(fraction_steps
) / 1e9
;
145 return time_tag(0, ns
* units_per_ns
);
148 float_t secs
= std::floor(ns
/ 1e9
);
149 ns
= std::fmod(ns
, 1e9
);
150 return time_tag(secs
, ns
* units_per_ns
);
154 static time_tag
from_samples_small(unsigned int sample_count
, float samplerate
)
156 assert(sample_count
< samplerate
);
158 const float units_per_sample
= float(fraction_steps
) / samplerate
;
159 return time_tag(0, sample_count
* units_per_sample
);
162 static time_tag
from_samples(unsigned int sample_count
, float samplerate
)
164 const float_t units_per_sample
= float_t(fraction_steps
) / samplerate
;
166 if (sample_count
< samplerate
)
167 return from_samples_small(sample_count
, samplerate
);
170 float_t secs
= std::floor(sample_count
/ samplerate
);
171 float_t samples
= std::fmod(sample_count
, samplerate
);
172 return time_tag(secs
, samples
* units_per_sample
);
176 float to_samples(float samplerate
)
178 float seconds
= get_fractional_seconds();
179 uint32_t secs
= get_secs();
182 seconds
+= (float)secs
;
183 return seconds
* samplerate
;
186 static time_tag
from_ptime(boost::posix_time::ptime
const & pt
)
188 using namespace boost::gregorian
;
189 using namespace boost::posix_time
;
191 const date
base(1970, Jan
, 1);
193 time_duration diff
= pt
- ptime(base
);
195 uint32 secs
= diff
.total_seconds() + ntp_offset
;
197 double fraction
= double(diff
.fractional_seconds());
199 if (diff
.resolution() == boost::date_time::nano
)
200 fraction
/= 1000000000;
201 else if (diff
.resolution() == boost::date_time::micro
)
203 else if (diff
.resolution() == boost::date_time::milli
)
208 assert (fraction
< 1.0 && fraction
>= 0);
210 uint32 fraction_units
= std::floor(fraction
* double(std::numeric_limits
<uint32
>::max()));
211 return time_tag(secs
, fraction_units
);
214 boost::posix_time::ptime
to_ptime(void) const
216 using namespace boost::gregorian
;
217 using namespace boost::posix_time
;
219 const date
base(1970, Jan
, 1);
220 #ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
221 time_duration offset
= seconds(get_secs() - ntp_offset
) + nanoseconds(get_nanoseconds());
223 time_duration offset
= seconds(get_secs() - ntp_offset
) + microseconds(get_nanoseconds()/1000);
225 return ptime(base
, offset
);
232 } /* namespace nova */
234 #endif /* UTILITIES_TIME_TAG_HPP */