Hello all,
I'm exploring my very first external! But I've run into a snag.
I'd like to build an external object which outputs the number of seconds since "epoch" when banged. Epoch is the beginning of time as the digital world understands it: jan 1 1970.
Could somebody look over the following code and tell me why it works only after the FIRST BANG?
Many thanks Regards, Dave S
#include "m_pd.h" #include "time.h"
static t_class *epochtime_class;
typedef struct _epochtime { t_object x_obj; time_t t; } t_epochtime;
void epochtime_bang(t_epochtime *x) { t_float f=x->t; x->t=time( NULL );
outlet_float(x->x_obj.ob_outlet, f); }
void *epochtime_new(t_floatarg f) { t_epochtime *x = (t_epochtime *)pd_new(epochtime_class);
x->t=f; outlet_new(&x->x_obj, &s_float);
return (void *)x; }
void epochtime_setup(void) { epochtime_class = class_new(gensym("epochtime"), (t_newmethod)epochtime_new, 0, sizeof(t_epochtime), CLASS_DEFAULT, 0);
class_addbang(epochtime_class, epochtime_bang); }
How about just this:
void epochtime_bang(t_epochtime *x) { x->t=time( NULL ); outlet_float(x->x_obj.ob_outlet, x->t); }
On Tue, Nov 19, 2002 at 08:09:48PM -0600, David Sabine wrote:
Hello all,
I'm exploring my very first external! But I've run into a snag.
I'd like to build an external object which outputs the number of seconds since "epoch" when banged. Epoch is the beginning of time as the digital world understands it: jan 1 1970.
Could somebody look over the following code and tell me why it works only after the FIRST BANG?
Many thanks Regards, Dave S
#include "m_pd.h" #include "time.h"
static t_class *epochtime_class;
typedef struct _epochtime { t_object x_obj; time_t t; } t_epochtime;
void epochtime_bang(t_epochtime *x) { t_float f=x->t; x->t=time( NULL );
outlet_float(x->x_obj.ob_outlet, f); }
void *epochtime_new(t_floatarg f) { t_epochtime *x = (t_epochtime *)pd_new(epochtime_class);
x->t=f; outlet_new(&x->x_obj, &s_float);
return (void *)x; }
void epochtime_setup(void) { epochtime_class = class_new(gensym("epochtime"), (t_newmethod)epochtime_new, 0, sizeof(t_epochtime), CLASS_DEFAULT, 0);
class_addbang(epochtime_class, epochtime_bang); }
Hello all,
I succeeded actually using a slightly different approach as you can see in the following source code: Instead of storing the number in a variable, I decided to put the time(NULL) function directly into the outgoing argument to the outlet.
In any case, I don't think this object will be of any use to anybody because PD returns the following number: 1.03777e+009 (or something like it) which can't be used very reliably. I mean it works, but I can't see the seconds pass -- i can only observe the passage of time every 64 seconds or so. (What I mean is that the object will output the same number for about 64 seconds, then it outputs another number which is slightly higher.)
Perhaps Miller has an answer to this? I know that the floating point values in PD are limited to a specific range -- is that the cause of this phenomenon.?
I attached the compiled external and a "epochtime_test.pd" if you want to witness this for yourself.
Regards, Dave S
p.s.: What I'm REALLY trying to do is put together a "difftime()" type of routine. But this "epochtime" seemed simpler and a logical place to begin.
#include "m_pd.h" #include "time.h"
static t_class *epochtime_class;
typedef struct _epochtime { t_object x_obj; } t_epochtime;
void *epochtime_new(void) { t_epochtime *x = (t_epochtime *)pd_new(epochtime_class);
outlet_new(&x->x_obj, &s_float);
return (x); }
void epochtime_bang(t_epochtime *x) { outlet_float(x->x_obj.ob_outlet, (t_float) (time( NULL ))); }
void epochtime_setup(void) { epochtime_class = class_new(gensym("epochtime"), (t_newmethod)epochtime_new, 0, sizeof(t_epochtime), CLASS_DEFAULT, 0);
class_addbang(epochtime_class, epochtime_bang); }
In any case, I don't think this object will be of any use to anybody because PD returns the following number: 1.03777e+009 (or something like it) which can't be used very reliably. I mean it works, but I can't see the seconds pass -- i can only observe the passage of time every 64 seconds or so. (What I mean is that the object will output the same number for about 64 seconds, then it outputs another number which is slightly higher.)
Perhaps Miller has an answer to this? I know that the floating point values in PD are limited to a specific range -- is that the cause of this phenomenon.?
Hi David, i'm not Miller but i can answer this: In PD all numeric values are represented by single precision floats having 24 bits of mantissa, which translates to a accuracy of about 7 or 8 decimal digits. Hence, a number of the order 1e+9 cannot be represented with full accuracy.
Depending on what you are using your external for, you can possibly circumvent the problem by storing the value of time(NULL) with full precision either at class or object setup and then, at a bang, output only the difference between the current time(NULL) and this stored value.
best greetings, Thomas
Hi, David Sabine hat gesagt: // David Sabine wrote:
In any case, I don't think this object will be of any use to anybody because PD returns the following number: 1.03777e+009 (or something like it) which can't be used very reliably. I mean it works, but I can't see the seconds pass -- i can only observe the passage of time every 64 seconds or so. (What I mean is that the object will output the same number for about 64 seconds, then it outputs another number which is slightly higher.)
This has to do with the exponential display of large numbers. Depending on what you want you could make an object with outlets for the 'real' time, like outlets for struct tm { int tm_sec; /* Seconds. [0-60] (1 leap second) */ int tm_min; /* Minutes. [0-59] */ int tm_hour; /* Hours. [0-23] */ int tm_mday; /* Day. [1-31] */ int tm_mon; /* Month. [0-11] */ int tm_year; /* Year - 1900. */ int tm_wday; /* Day of week. [0-6] */ int tm_yday; /* Days in year.[0-365] */ int tm_isdst; /* DST. [-1/0/1]*/ ...
I didn't follow your problems with difftime, but I think difftime
should work as well, if you for example would start the 'clock' at
creation time:
typedef struct _epochtime {
t_object x_obj;
time_t t, starttime;
} t_epochtime;
void *epochtime_new(void)
{
t_epochtime *x = (t_epochtime *)pd_new(epochtime_class);
x->starttime=time();
outlet_new(&x->x_obj, &s_float);
return (x);
}
and on a bang you'd take the current time and do a diff:
x->t=time();
outlet_float(x->x_obj.ob_outlet,
(t_float) (difftime(x->starttime, x->t)));
This should work, but I didn't test it. I use a [bang~] and a counter for timing.
Frank Barknecht _ ______footils.org__
Hello Frank,
I've implemented the changes you suggested. Note that I make two corrections -- "time()" produces errors, the argument must be "time( NULL )"
In any case, this isn't quite the behavior I'm looking for. In essense, this object now outputs a number of seconds since the patch was opened. (or since the object was created in the patch). In other words, it produces a number representing "epoch" as the PD patch understand it...but I'd like to produce "epoch" as UNIX understands it: i.e. Jan 1, 1970.
In any case, perhaps this whole project has lead me away from my original goal - which was to create a difftime object. Ultimately, I'd like to send a message to an object (a list representing a date) and compare it to a second date. Perhaps like below:
"2002 11 20 12 24 00" (as in Nov 20, 2002 12:24 P.M.)
"2002 11 19 12 24 00" (as in 'yesterday'!) = 86400 seconds.
This would be the same output as "difftime()" in C or C++.
It was only after some initial research that I realized that the difftime() function actually uses "seconds since epoch" as represented by "time_t time()" to determine the number of seconds between the two compared dates. Hence, when I started writing the new external, I found it easier to START with epoch (as a mental excersize and to familiarize myself with the process of writing/creating externals).
SO, at this point, I've completed a partially useless object called "epochtime" and I'm no closer to understanding how I could really build a "difftime" object. I'm currently stuck trying to understand how I'll take the "list" in through the inlet and parse it so that it corresponds with the "tm" structure.
Many thanks, Dave S
----- Original Message ----- From: "Frank Barknecht" fbar@footils.org To: pd-list@iem.kug.ac.at Sent: Wednesday, November 20, 2002 4:41 AM Subject: Re: [PD] [epochtime] - my first external
Hi, David Sabine hat gesagt: // David Sabine wrote:
In any case, I don't think this object will be of any use to anybody
because
PD returns the following number: 1.03777e+009 (or something like it)
which
can't be used very reliably. I mean it works, but I can't see the
seconds
pass -- i can only observe the passage of time every 64 seconds or so. (What I mean is that the object will output the same number for about 64 seconds, then it outputs another number which is slightly higher.)
This has to do with the exponential display of large numbers. Depending on what you want you could make an object with outlets for the 'real' time, like outlets for struct tm { int tm_sec; /* Seconds. [0-60] (1 leap second) */ int tm_min; /* Minutes. [0-59] */ int tm_hour; /* Hours. [0-23] */ int tm_mday; /* Day. [1-31] */ int tm_mon; /* Month. [0-11] */ int tm_year; /* Year - 1900. */ int tm_wday; /* Day of week. [0-6] */ int tm_yday; /* Days in year.[0-365] */ int tm_isdst; /* DST. [-1/0/1]*/ ...
I didn't follow your problems with difftime, but I think difftime should work as well, if you for example would start the 'clock' at creation time:
typedef struct _epochtime { t_object x_obj; time_t t, starttime; } t_epochtime;
void *epochtime_new(void) { t_epochtime *x = (t_epochtime *)pd_new(epochtime_class); x->starttime=time(); outlet_new(&x->x_obj, &s_float);
return (x); }
and on a bang you'd take the current time and do a diff:
x->t=time(); outlet_float(x->x_obj.ob_outlet, (t_float) (difftime(x->starttime, x->t)));
This should work, but I didn't test it. I use a [bang~] and a counter for timing.
ciao
Frank Barknecht _ ______footils.org__
PD-list mailing list PD-list@iem.kug.ac.at http://iem.kug.ac.at/cgi-bin/mailman/listinfo/pd-list