-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error in timetag to time.Time conversion #56
Comments
This implementation seems OK to me: const secondsFrom1900To1970 = 2208988800 // Source: RFC 868
const nanosecondsPerFraction = float64(0.23283064365386962891) // 1e9/(2^32)
func timetagToTime(timetag uint64) time.Time {
if timetag == 1 {
// Means "immediately". It cannot occur otherwise as timetag == 0 gets
// converted to January 1, 1900 while time.Time{} means year 1 in Go.
// Use the IsZero method to detect it.
return time.Time{}
}
return time.Unix(
int64(timetag>>32)-secondsFrom1900To1970,
int64(nanosecondsPerFraction*float64(timetag&(1<<32-1))),
)
}
func timeToTimetag(v time.Time) uint64 {
if v.IsZero() {
return 1
}
seconds := uint64(v.Unix() + secondsFrom1900To1970)
secondFraction := float64(v.Nanosecond()) / nanosecondsPerFraction
return (seconds << 32) + uint64(uint32(secondFraction))
} Here, we handle For the nanosecond part, we pre-calculate the number of nanoseconds per fraction so that its a simple floating point multiplication at runtime. We could round it to the nearest nanosecond rather than flooring it as the format has a precision of 0.233ns. It might not be a good idea to bring something from the past into the future (if we ever had transfers faster than a ns and time measurement precise enough...). Whatever! Something else: edited to fix mistake in the function implementation edited to add the inverse operation |
Cool to see this lib being updated. Are you using it in a project? Music-related? |
Hey :) First, thanks a lot for reporting the issue and your work. You were of course completely right. Happy that you discovered this bug. I used OSC a lot during my work at my former employer. There we used OSC for controlling devices and content in interactive installations, tv shows, etc. |
No problem, I was looking at using OSC for a Go project. Nice! That's the kind of domain I'm looking at as well, having background in stage lighting. |
Extract from the code:
This function is used on bundle reception (
readBundle
called byreadPacket
called by a few functions) to parse received timetags. It takes the lower 32 bits from the timetag and gives them as the second argument oftime.Unix
, that has the following signature and doc:However, the OSC 1.0 spec describes time tags as:
As such, the lower 32 bits should be used as fractions of a second (1 second / 2^32 ~= 0.233 nano second per fraction) rather than whole nanoseconds.
If this analysis is right, this bug affects every bundle received by this library by a big amount: between 0s at the start of the second up to, at the end of a second, 2^32-1 nanoseconds - 1 second, or ~3.295 seconds! I have not run the code, but I assume people using the bundle feature would notice such big delays in dispatch?
The text was updated successfully, but these errors were encountered: