Hi, I want to write a small script for ear training with Chuck. Therefore Chuck should produce values that seem to be quite random. But it seems like that the standard functions here are too deterministic. I know that a non-deterministic random function would not be possible, but most programming languages provide functions that create at least new numbers every time I start the same code. However, in chuck something like the following always prints the same numbers when I run it: while(true){ 1::second => now; Math.rand2(50, 1000) => int rndNumber; <<<rndNumber>>>;} Is there an easy way to get something more unpredictable? I don't want to go deep into random generator programming. But the function does not really what you would expect of a random generator, does it? Cheers Jakob _________________________________________________________________ Connect to the next generation of MSN Messenger http://imagine-msn.com/messenger/launch80/default.aspx?locale=en-us&source=wlmailtagline
I guess you need some pseudo-random number to multiply by, such as the
system time in milliseconds... However I'm not sure how one would get
the system time into ChucK.
I suppose that you could run some sort of batch script, or say a
couple lines of Python, that either gets the current system time, or
creates some type of random seed number; then generates a ChucK file
with that seed number as a global variable.
~David
On Nov 19, 2007 12:26 PM, jakob kaiser
Hi, I want to write a small script for ear training with Chuck. Therefore Chuck should produce values that seem to be quite random. But it seems like that the standard functions here are too deterministic. I know that a non-deterministic random function would not be possible, but most programming languages provide functions that create at least new numbers every time I start the same code. However, in chuck something like the following always prints the same numbers when I run it:
while(true){ 1::second => now; Math.rand2(50, 1000) => int rndNumber; <<<rndNumber>>>; }
Is there an easy way to get something more unpredictable? I don't want to go deep into random generator programming. But the function does not really what you would expect of a random generator, does it?
Cheers
Jakob
________________________________ Connect to the next generation of MSN Messenger Get it now!
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Pseudo-random number generator functions are easy to come by, here's
an example from "Xorshift RNGs" (Marsaglia, 2003;
http://www.jstatsoft.org/v08/i14)
2463534242 => int seed;
fun int xor(int y) {
(y << 13) ^=> y;
(y >> 17) => y;
(y << 5) ^=> y;
return y;
}
seed => int y;
while(true)
{
1::second => now;
xor(y) => y;
<<<y>>>;
}
But again, you need a seed to begin with.
michael
On Nov 19, 2007 12:52 PM, David Powers
I guess you need some pseudo-random number to multiply by, such as the system time in milliseconds... However I'm not sure how one would get the system time into ChucK.
I suppose that you could run some sort of batch script, or say a couple lines of Python, that either gets the current system time, or creates some type of random seed number; then generates a ChucK file with that seed number as a global variable.
~David
On Nov 19, 2007 12:26 PM, jakob kaiser
wrote: Hi, I want to write a small script for ear training with Chuck. Therefore Chuck should produce values that seem to be quite random. But it seems like that the standard functions here are too deterministic. I know that a non-deterministic random function would not be possible, but most programming languages provide functions that create at least new numbers every time I start the same code. However, in chuck something like the following always prints the same numbers when I run it:
while(true){ 1::second => now; Math.rand2(50, 1000) => int rndNumber; <<<rndNumber>>>; }
Is there an easy way to get something more unpredictable? I don't want to go deep into random generator programming. But the function does not really what you would expect of a random generator, does it?
Cheers
Jakob
On 19/11/2007, David Powers
I guess you need some pseudo-random number to multiply by, such as the system time in milliseconds... However I'm not sure how one would get the system time into ChucK.
No, I'm nearly 100% sure you can't, in fact I put that on the wish-list last time we were asked for wishes for exactly this reason (and to be able to make a ChucKoo clock, of course!) I suppose that you could run some sort of batch script, or say a
couple lines of Python, that either gets the current system time, or creates some type of random seed number; then generates a ChucK file with that seed number as a global variable.
Perhaps a script could call the .ck with the system time as a parameter? That sounds reasonable enough, I'm no BASH/ batch wizzard but that should be quite possible. It's a interesting problem. Kas.
I suppose that you could run some sort of batch script, or say a couple lines of Python, that either gets the current system time, or creates some type of random seed number; then generates a ChucK file with that seed number as a global variable.
Perhaps a script could call the .ck with the system time as a parameter? That sounds reasonable enough, I'm no BASH/ batch wizzard but that should be quite possible.
The unix command $ date +%N 479891000 792387000 104883000 339255000 620501000 354854000 gives the nanoseconds for the current time (000000000..999999999), that should be a good seed. michael
Hi! Thanks for all your tips. I'll now try it with the sample value of the time between the code is starting and the moment when the user presses the first key. I guess that should be random enough. But, yeah, I agree with Kassen that a function to read the computer time should be included in one of the next releases. It would be much more elegant with that. And of course I am looking forward to the ChucKoo clock... Cheers Jakob _________________________________________________________________ Invite your mail contacts to join your friends list with Windows Live Spaces. It's easy! http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.aspx&mkt=en-us
jakob kaiser wrote:
Hi! Thanks for all your tips. I'll now try it with the sample value of the time between the code is starting and the moment when the user presses the first key. I guess that should be random enough. But, yeah, I agree with Kassen that a function to read the computer time should be included in one of the next releases. It would be much more elegant with that. And of course I am looking forward to the ChucKoo clock...
Uhm, I still don't get it. I tried your example on two platforms yesterday (Mac and Windows -- my Linux machine is 64-bit) and the numbers are random -- with the exception of the first one (which you can get around by just having an extra, unused "Std.rand();" in your code.). Why would you go to all that trouble? Even if you did have the time in there you'd still have the same problem. Std.srand() just calls the C srand() function and it's already called with the system time when ChucK is initializing... -Scott
On 20/11/2007, Scott Wheeler
yesterday (Mac and Windows -- my Linux machine is 64-bit) and the numbers are random -- with the exception of the first one (which you can get around by just having an extra, unused "Std.rand();" in your code.). Why would you go to all that trouble?
I think we are seeing system dependant issues. I just tried the code from the topic-starting mail on my own Linux box (Studio 64 Debian repositories but the 32 bit version) in the Mini and to me the first value looks just as random as the rest. I re-started the VM a few times and re-started the whole Mini a few times as well and I don't think it ever started with the same number twice. Based on that I wouldn't rule out the possibility that Jacob does have a real issue. Additionally, at the risk of sounding sentimental, to me it seems slightly odd to have a "strongly timed" language that can't read the system time. Aside from ChucKoo clocks and getting around non-random randomness I don't yet have a urgent need for it but there's a sort of aching feeling in the back of my mind that it should be there.... :¬) Oh... I just noticed that on some level it's already there; [chuck]:(2:SYSTEM): setting log level to: 2 (SYSTEM)... [chuck]:(2:SYSTEM): -------( Wed Nov 21 00:32:44 2007 )------- [chuck]:(2:SYSTEM): starting chuck virtual machine... Interesting. Yours, Kas.
Kassen wrote:
On 20/11/2007, *Scott Wheeler*
mailto:wheeler@kde.org> wrote: Additionally, at the risk of sounding sentimental, to me it seems slightly odd to have a "strongly timed" language that can't read the system time.
This is another one of those where the devil is in the details. Just having a function to pass through the value to C's time() would be trivial. (About 10 lines of code added to ulib_std.cpp) However, with support for time comes time zones, daylight savings time, conversions between local time and universal time, addition and subtraction of time, etc. And then it's a big pain in the ass. -Scott
On 21/11/2007, Scott Wheeler
This is another one of those where the devil is in the details. Just having a function to pass through the value to C's time() would be trivial. (About 10 lines of code added to ulib_std.cpp) However, with support for time comes time zones, daylight savings time, conversions between local time and universal time, addition and subtraction of time, etc. And then it's a big pain in the ass.
Really? this might sound naive but I feel it's up to the OS to keep track of those. The little clocks at the bottom of the desktop can have the time, why not some arbitrary program? Actually, I just remembered that our auto-rec example uses some sort of trick to time-stamp saved files to quote a filename I just saw; chuck-session(Mon Jun 25 00h42m33 2007).wav This (in a format readable without lots of string management) would be fine with me, if I go across time-zone I have to re-set the system clock anyway. I once tried to exploit the trick ChucK uses there, I remember now, to tell the time but never succeeded, it seems hard-wired into the file saving Ugen. You are right that something like that wouldn't be enough to -say- manage nuclear reactors across continents but it would be enough for cheep&cheerful bleeps & booms for fun & profit and that would be enough for me, for now at least ;¬). Yours, Kas.
Kassen wrote:
Really? this might sound naive but I feel it's up to the OS to keep track of those. The little clocks at the bottom of the desktop can have the time, why not some arbitrary program?
Sure -- you can do that -- as long as you don't actually want to do anything with the time other than print it. ;-) As you said, you don't have any purpose in mind for date / time support, but most of the time people working with dates / times do in fact have something in mind that they want to do. Here are a couple examples of date / time APIs: http://doc.trolltech.com/4.3/time.html http://www.boost.org/doc/html/date_time.html But let's say that you want your ChucKoo clock to let you sleep in on Saturday. Well, then you need your date / time class to be able to report the day of the week. Or if you want to say, "How much time is there between now and tomorrow at noon?" You need to have API support for adding and subtracting time. -Scott
On 21/11/2007, Scott Wheeler
But let's say that you want your ChucKoo clock to let you sleep in on Saturday. Well, then you need your date / time class to be able to report the day of the week. Or if you want to say, "How much time is there between now and tomorrow at noon?" You need to have API support for adding and subtracting time.
I'm sure this is very naive again, but we do have lots of support for adding and subtracting time. We have both "time" and "duration" as datatypes and day, hour, minute,etc, etc, etc as constants ready made. If we'd have even -say- a function that would report the amount of samples that have passed since newyear 2000 in our timezone it would be quite straightforward to discover the amount of time until "tomorow at noon". The hard bits -as I see it- would be that daylight saving time is variable per country and that within countries this changes as well from year to year (for reasons I don't quite understand like much of how government works...). Just now I read that people are debating whether we should even observe leap-seconds at all. To me it seems quite clear that we will never be able to make a function that can predict the whims of politicians in every country ChucK may be used in with regard to how we will look at the clock and calendar in the future. I'm not even sure if computers in Israel (which I assume observes the Jewish calender) or China (which I would guess observes the Chinese year) use the same calender as my European computers do. As I see it right now these are cultural questions which don't need to matter all that much from a ChucKian point of view. If we'd like to establish the time from a ChucKian point of view I think it would do to know the amount of time that has passed since some known point in time (the birth of the universe, ChucK, Unix or one's favourite religious person, etc) and to know how the calender we'd like to observe works. We already have enough ways to deal with time to take it from there on. Admittedly that would be a bit abstract at the expense of ease of use for most people most of the time but I don't think that a API to reason about time as such is the bottle-neck here. Ok, now that I think about it there are some quite amusing questions. For example, if we would have such a built in calender/clock, would we be able to use this?; if (day % 24::hour) //check to see if we need to adjust for daylight savings time today That would be quite funny. :¬) Kas.
Kassen wrote:
I'm sure this is very naive again, but we do have lots of support for adding and subtracting time. We have both "time" and "duration" as datatypes and day, hour, minute,etc, etc, etc as constants ready made.
If we'd have even -say- a function that would report the amount of samples that have passed since newyear 2000 in our timezone it would be quite straightforward to discover the amount of time until "tomorow at noon".
Well, but the trick in that question is, "What if daylight savings time starts tonight?" I should have made that more clear. That may sound like a contrived example, but to put it in context, let's say that you have a multimedia installation that's doing something connected with time. You've got ChucK running and it may sit there running for a week. Every day it's supposed to do something at noon that is synchronized to other parts of the piece. So you compute a duration until noon tomorrow and chuck that to now. But then it doesn't work.
The hard bits -as I see it- would be that daylight saving time is variable per country [...]
There are faculties on the systems to handle those things -- either via system APIs or using something like boost in the background, it's more a question of how much of that would need to be exposed in a time class for ChucK.
Admittedly that would be a bit abstract at the expense of ease of use for most people most of the time but I don't think that a API to reason about time as such is the bottle-neck here.
Well, I suppose the question that I'm really hinting at is, "What problem are you trying to solve?" That's really the question behind API design. For a lot of potential answers to that question the answer results in an API that's a bit of work to implement. "ChucK doesn't support time." isn't really a good starting point. "I'd like to be able to do ..." is better. For the one proposed case so far (seeding the random number generator) that seems to be more of a problem that there's a bug in ChucK's code somewhere and there I feel like the right solution is fixing the bug. :-) -Scott
On 21/11/2007, Scott Wheeler
starts tonight?" I should have made that more clear.
That may sound like a contrived example, but to put it in context, let's say that you have a multimedia installation that's doing something connected with time. You've got ChucK running and it may sit there running for a week. Every day it's supposed to do something at noon that is synchronized to other parts of the piece. So you compute a duration until noon tomorrow and chuck that to now. But then it doesn't work.
Yes, that's a good question. I myself should clearly have been more clear too because I tried to at least point out that I admired that issue. I have no idea how to solve this, we could use a sort of homunculus solution and trust computers are getting their time/date and info on changing opinions about time and date depending on location from a internet server but audio is quite possibly the worst field to apply that to because it's fairly normal to keep dedicated audio computers offline.
There are faculties on the systems to handle those things -- either via system APIs or using something like boost in the background, it's more a question of how much of that would need to be exposed in a time class for ChucK.
Yes, I agree.
Well, I suppose the question that I'm really hinting at is, "What problem are you trying to solve?" That's really the question behind API design. For a lot of potential answers to that question the answer results in an API that's a bit of work to implement. "ChucK doesn't support time." isn't really a good starting point. "I'd like to be able to do ..." is better. For the one proposed case so far (seeding the random number generator) that seems to be more of a problem that there's a bug in ChucK's code somewhere and there I feel like the right solution is fixing the bug. :-)
I agree there too, this seems a bit too serious to blame Windows for it, my bet is that in the Windows version of the random generator something is going wrong and this should be our first priority. Most of the things I would like to do with time would work just fine with a series of calls that would report hours, minutes, seconds and ms since the last midnight in my timezone and according to the system/bios clock. A single call to just report the amount of samples since the last midnight would be fine as well, disregarding daylight savings time is no major issue to me. This would be enough for installations to change the mood of the piece depending on the time of the day or to make sure you stop playing at exactly 11:30 as promised to the stage manager, etc. Clearly it wouldn't be enough on it's own to have a gradual development from noon to noon and not glitch if the clock is put a hour back in the meantime but if we know at what date we start the installation and we know when the clock change will happen it would still be enough to work around that with some exceptions and extra rules/counters. You're right that I don't have any specific clearly defined issues that need solving right now. I'm after this because I found that toying around with ChucK code and sounds tends to become more evocative when it's somehow linked to the "real" world. Adding support for MIDI or HID often makes a program more interesting because it seems linked more directly to "our reality". It's from that perspective that I think some link between "ChucK time" and "real time" might help create things of amusement or artistic value. As of yet I don't believe international banking systems depend on ChucK to make sure the world economy will keep running and to make sure interest rates are adjusted for leap-seconds. At this point it might be interesting to wonder how long a ChucK program has ever been run at all.... Yours, Kas.
say that you have a multimedia installation that's doing something connected with time. You've got ChucK running and it may sit there running for a week. Every day it's supposed to do something at noon that is synchronized to other parts of the piece. So you compute a duration until noon tomorrow and chuck that to now. But then it doesn't work.
What if a part of your installation was a sundial, whose shadow is being watched by a webcam? I'm not kidding, I've been thinking on these same lines the past few days. Also, please see the following two links, even though they may look completely off-topic right now: http://science.slashdot.org/article.pl?sid=07/11/20/0356214 http://swaratala.blogspot.com/2007/04/time-and-season-in-raga-performance.ht... cheers, -- ------- -.- 1/f ))) --. ------- ... http://www.algomantra.com
Scott Wheeler wrote:
Here are a couple examples of date / time APIs:
http://doc.trolltech.com/4.3/time.html http://www.boost.org/doc/html/date_time.html
After looking at the Java API for dates and times I found that it delegates things in a way that I found nice. http://java.sun.com/j2se/1.5.0/docs/api/java/util/Date.html http://java.sun.com/j2se/1.5.0/docs/api/java/util/Calendar.html It has separation between a Date, which is basically a unix-epoch timestamp and a calendar class which manages all conversions done on that date (and a separate formatting class for reading and wring dates). Mostly just to see how much work it actually is to extend ChucK's type system I wrote something similar to the Date class, called Timestamp (Time is already taken). The API is: Timestamp - int secondsSinceEpoch() - void setSecondsSinceEpoch(int seconds) + Timestamp current() [static] So, a simple example: <<< Timestamp.current().secondsSinceEpoch() >>>; 1::second => now; Timestamp t; t.setSecondsSinceEpoch(1); <<< t.secondsSinceEpoch() >>>; Timestamp.current() @=> t; <<< t.secondsSinceEpoch() >>>; Produces: 1195641120 :(int) 1 :(int) 1195641121 :(int) Random other notes: - The CVS server isn't responding at the moment. It connects, but diffs don't work, so this is based on the last release. - ChucK's type system is scattered across quite a few places. On the wishlist-of-things-nobody'll-every-have-time-for would be consolidating (and cleaning it up) a bit. Possibly en route to a 64-bit port since a lot of the type system relies on casts from integers to pointers. (Sidenote there -- would simply using a long long for the t_CKUINT potentially work on 64-bit platforms? May try that later...) - I tried to follow the current coding style despite difference in taste (or some things that are generally not great C++ practice) so that the code would fit with the rest if the authors want to check it in. - This may not work on Windows. Should work on Mac and Linux. There's a universal binary (Mac) here: http://developer.kde.org/~wheeler/files/chuck.gz -Scott diff -wur ../../chuck-1.2.1.0-orig/src/chuck_dl.h ./chuck_dl.h --- ../../chuck-1.2.1.0-orig/src/chuck_dl.h 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_dl.h 2007-11-21 09:17:18.000000000 +0100 @@ -443,6 +443,7 @@ t_CKPOLAR v_polar; Chuck_Object * v_object; Chuck_String * v_string; + Chuck_Timestamp * v_timestamp; Chuck_DL_Return() { v_complex.re = 0.0; v_complex.im = 0.0; } }; diff -wur ../../chuck-1.2.1.0-orig/src/chuck_lang.cpp ./chuck_lang.cpp --- ../../chuck-1.2.1.0-orig/src/chuck_lang.cpp 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_lang.cpp 2007-11-21 11:11:43.000000000 +0100 @@ -1432,6 +1430,46 @@ return FALSE; } +//----------------------------------------------------------------------------- +// name: init_class_Timestamp() +// desc: ... +//----------------------------------------------------------------------------- +t_CKBOOL init_class_Timestamp( Chuck_Env * env, Chuck_Type * type ) +{ + Chuck_DL_Func * func = NULL; + + if( !type_engine_import_class_begin( env, type, env->global(), object_ctor, object_dtor ) ) + return FALSE; + + // add current() + + func = make_new_sfun("Timestamp", "current", Timestamp_current ); + if( !type_engine_import_sfun( env, func ) ) goto error; + + // add secondsSinceEpoch() + + func = make_new_mfun( "int", "secondsSinceEpoch", Timestamp_secondssinceepoch ); + if( !type_engine_import_mfun( env, func ) ) goto error; + + // add setSecondsSinceEpoch() + + func = make_new_mfun( "void", "setSecondsSinceEpoch", Timestamp_setsecondssinceepoch ); + func->add_arg( "int", "seconds" ); + if( !type_engine_import_mfun( env, func ) ) goto error; + + // end the class import + + type_engine_import_class_end( env ); + + return TRUE; + +error: + + // end the class import + type_engine_import_class_end( env ); + + return FALSE; +} // Object ctor CK_DLL_CTOR( object_ctor ) @@ -2824,3 +2896,26 @@ OBJ_MEMBER_TIME(fake_msg, MidiMsg_offset_when) = time; } +//----------------------------------------------------------------------------- +// Timestamp API +//----------------------------------------------------------------------------- + +CK_DLL_SFUN( Timestamp_current ) +{ + Chuck_Timestamp *time = (Chuck_Timestamp *) instantiate_and_initialize_object( &t_timestamp, SHRED ); + time->setToCurrent(); + RETURN->v_timestamp = time; +} + +CK_DLL_MFUN( Timestamp_secondssinceepoch ) +{ + Chuck_Timestamp *time = (Chuck_Timestamp *) SELF; + RETURN->v_int = (t_CKUINT) time->value; +} + +CK_DLL_MFUN( Timestamp_setsecondssinceepoch ) +{ + Chuck_Timestamp *time = (Chuck_Timestamp *) SELF; + t_CKINT seconds = GET_CK_INT( ARGS ); + time->value = (time_t) seconds; +} diff -wur ../../chuck-1.2.1.0-orig/src/chuck_lang.h ./chuck_lang.h --- ../../chuck-1.2.1.0-orig/src/chuck_lang.h 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_lang.h 2007-11-21 10:55:10.000000000 +0100 @@ -60,7 +60,7 @@ t_CKBOOL init_class_Midi( Chuck_Env * env ); t_CKBOOL init_class_MidiRW( Chuck_Env * env ); t_CKBOOL init_class_HID( Chuck_Env * env ); - +t_CKBOOL init_class_Timestamp( Chuck_Env * env, Chuck_Type * type ); @@ -357,7 +357,13 @@ CK_DLL_MFUN( HidOut_printerr ); CK_DLL_MFUN( HidOut_send ); - - +//----------------------------------------------------------------------------- +// Timestamp API +//----------------------------------------------------------------------------- +CK_DLL_CTOR( Timestamp_ctor ); +CK_DLL_DTOR( Timestamp_dtor ); +CK_DLL_SFUN( Timestamp_current ); +CK_DLL_MFUN( Timestamp_secondssinceepoch ); +CK_DLL_MFUN( Timestamp_setsecondssinceepoch ); #endif diff -wur ../../chuck-1.2.1.0-orig/src/chuck_oo.h ./chuck_oo.h --- ../../chuck-1.2.1.0-orig/src/chuck_oo.h 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_oo.h 2007-11-21 09:51:39.000000000 +0100 @@ -343,9 +343,6 @@ std::string str; }; - - - //----------------------------------------------------------------------------- // name: Chuck_IO // desc: base Chuck IO class @@ -463,7 +460,19 @@ std::string m_path; }; +//----------------------------------------------------------------------------- +// name: Chuck_Timestamp +// desc: base Chuck time class +//----------------------------------------------------------------------------- +struct Chuck_Timestamp : Chuck_Object +{ +public: + Chuck_Timestamp() : value( 0 ) { } + ~Chuck_Timestamp() { } + void setToCurrent() { ::time( &value ); } - +public: + time_t value; +}; #endif diff -wur ../../chuck-1.2.1.0-orig/src/chuck_type.cpp ./chuck_type.cpp --- ../../chuck-1.2.1.0-orig/src/chuck_type.cpp 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_type.cpp 2007-11-21 10:52:33.000000000 +0100 @@ -69,6 +69,7 @@ Chuck_Type t_fileio( te_fileio, "FileIO", &t_io, sizeof(void *) ); Chuck_Type t_thread( te_thread, "Thread", &t_object, sizeof(void *) ); Chuck_Type t_class( te_class, "Class", &t_object, sizeof(void *) ); +Chuck_Type t_timestamp( te_timestamp, "Timestamp", &t_object, sizeof(void *) ); /* exile struct Chuck_Type t_adc = { te_adc, "adc", &t_ugen, t_ugen.size }; @@ -225,6 +226,7 @@ env->global()->type.add( t_event.name, &t_event ); t_event.lock(); env->global()->type.add( t_io.name, &t_io ); t_io.lock(); env->global()->type.add( t_fileio.name, &t_fileio ); t_fileio.lock(); + env->global()->type.add( t_timestamp.name, &t_timestamp ); t_timestamp.lock(); // dur value t_CKDUR samp = 1.0; @@ -249,6 +251,7 @@ init_class_shred( env, &t_shred ); init_class_event( env, &t_event ); init_class_io( env, &t_io ); + init_class_Timestamp( env, &t_timestamp ); EM_log( CK_LOG_SEVERE, "class 'class'" ); t_class.info = new Chuck_Namespace; diff -wur ../../chuck-1.2.1.0-orig/src/chuck_type.h ./chuck_type.h --- ../../chuck-1.2.1.0-orig/src/chuck_type.h 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_type.h 2007-11-21 09:20:39.000000000 +0100 @@ -52,7 +52,7 @@ te_complex, te_polar, te_string, te_thread, te_shred, te_class, te_function, te_object, te_user, te_array, te_null, te_ugen, te_uana, te_event, te_void, te_stdout, te_stderr, te_adc, te_dac, te_bunghole, - te_uanablob, te_io, te_fileio, te_multi + te_uanablob, te_io, te_fileio, te_multi, te_timestamp } te_Type; @@ -811,8 +811,7 @@ extern Chuck_Type t_ugen; extern Chuck_Type t_uana; extern Chuck_Type t_uanablob; - - +extern Chuck_Type t_timestamp; #endif diff -wur ../../chuck-1.2.1.0-orig/src/ulib_std.cpp ./ulib_std.cpp --- ../../chuck-1.2.1.0-orig/src/ulib_std.cpp 2007-08-23 18:52:47.000000000 +0200 +++ ./ulib_std.cpp 2007-11-21 06:27:59.000000000 +0100 @@ -164,6 +164,10 @@ QUERY->add_sfun( QUERY, fabs_impl, "float", "fabs" ); QUERY->add_arg( QUERY, "float", "value" ); + // add time + + QUERY->add_sfun( QUERY, time_impl, "int", "time" ); + // add rand QUERY->add_sfun( QUERY, rand_impl, "int", "rand"); //! return int between 0 and RAND_MAX @@ -527,6 +531,13 @@ //RETURN->v_float = ::fabs( GET_CK_FLOAT(ARGS) ); } +// time + +CK_DLL_SFUN( time_impl ) +{ + RETURN->v_int = ::time( NULL ); +} + // rand CK_DLL_SFUN( rand_impl ) { diff -wur ../../chuck-1.2.1.0-orig/src/ulib_std.h ./ulib_std.h --- ../../chuck-1.2.1.0-orig/src/ulib_std.h 2007-08-23 18:52:47.000000000 +0200 +++ ./ulib_std.h 2007-11-21 06:29:26.000000000 +0100 @@ -41,6 +41,7 @@ // exports CK_DLL_SFUN( abs_impl ); CK_DLL_SFUN( fabs_impl ); +CK_DLL_SFUN( time_impl ); CK_DLL_SFUN( rand_impl ); CK_DLL_SFUN( randf_impl ); CK_DLL_SFUN( rand2f_impl );
One additional note: The changes to ulib_std.* can be ignored -- those were part of the first thing I messed with before introducing this as a type. -Scott
Whoa -- actually the current Java API for dates and times is seriously broken. There is an ongoing JSR to build a replacement API, but it probably won't be ready for some months yet. JSR 310:
https://jsr-310.dev.java.net/ https://jsr-310.dev.java.net/nonav/doc-2007-11-19/index.html
There are some great threads on the mailing list regarding API design and implementation details (long+int vs. double+double, etc).
https://jsr-310.dev.java.net/servlets/SummarizeList?listName=dev
All that said, what you have for ChucK looks like a good start.
michael
Scott Wheeler
Scott Wheeler wrote:
Here are a couple examples of date / time APIs:
http://doc.trolltech.com/4.3/time.html http://www.boost.org/doc/html/date_time.html
After looking at the Java API for dates and times I found that it delegates things in a way that I found nice.
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Date.html http://java.sun.com/j2se/1.5.0/docs/api/java/util/Calendar.html
It has separation between a Date, which is basically a unix-epoch timestamp and a calendar class which manages all conversions done on that date (and a separate formatting class for reading and wring dates). Mostly just to see how much work it actually is to extend ChucK's type system I wrote something similar to the Date class, called Timestamp (Time is already taken).
The API is:
Timestamp - int secondsSinceEpoch() - void setSecondsSinceEpoch(int seconds) + Timestamp current() [static]
So, a simple example:
<<< Timestamp.current().secondsSinceEpoch() >>>;
1::second => now;
Timestamp t;
t.setSecondsSinceEpoch(1);
<<< t.secondsSinceEpoch() >>>;
Timestamp.current() @=> t;
<<< t.secondsSinceEpoch() >>>;
Produces:
1195641120 :(int) 1 :(int) 1195641121 :(int)
Random other notes:
- The CVS server isn't responding at the moment. It connects, but diffs don't work, so this is based on the last release.
- ChucK's type system is scattered across quite a few places. On the wishlist-of-things-nobody'll-every-have-time-for would be consolidating (and cleaning it up) a bit. Possibly en route to a 64-bit port since a lot of the type system relies on casts from integers to pointers. (Sidenote there -- would simply using a long long for the t_CKUINT potentially work on 64-bit platforms? May try that later...)
- I tried to follow the current coding style despite difference in taste (or some things that are generally not great C++ practice) so that the code would fit with the rest if the authors want to check it in.
- This may not work on Windows. Should work on Mac and Linux. There's a universal binary (Mac) here:
http://developer.kde.org/~wheeler/files/chuck.gz
-Scott
diff -wur ../../chuck-1.2.1.0-orig/src/chuck_dl.h ./chuck_dl.h --- ../../chuck-1.2.1.0-orig/src/chuck_dl.h 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_dl.h 2007-11-21 09:17:18.000000000 +0100 @@ -443,6 +443,7 @@ t_CKPOLAR v_polar; Chuck_Object * v_object; Chuck_String * v_string; + Chuck_Timestamp * v_timestamp;
Chuck_DL_Return() { v_complex.re = 0.0; v_complex.im = 0.0; } }; diff -wur ../../chuck-1.2.1.0-orig/src/chuck_lang.cpp ./chuck_lang.cpp --- ../../chuck-1.2.1.0-orig/src/chuck_lang.cpp 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_lang.cpp 2007-11-21 11:11:43.000000000 +0100 @@ -1432,6 +1430,46 @@ return FALSE; }
+//----------------------------------------------------------------------------- +// name: init_class_Timestamp() +// desc: ... +//----------------------------------------------------------------------------- +t_CKBOOL init_class_Timestamp( Chuck_Env * env, Chuck_Type * type ) +{ + Chuck_DL_Func * func = NULL; + + if( !type_engine_import_class_begin( env, type, env->global(), object_ctor, object_dtor ) ) + return FALSE; + + // add current() + + func = make_new_sfun("Timestamp", "current", Timestamp_current ); + if( !type_engine_import_sfun( env, func ) ) goto error; + + // add secondsSinceEpoch() + + func = make_new_mfun( "int", "secondsSinceEpoch", Timestamp_secondssinceepoch ); + if( !type_engine_import_mfun( env, func ) ) goto error; + + // add setSecondsSinceEpoch() + + func = make_new_mfun( "void", "setSecondsSinceEpoch", Timestamp_setsecondssinceepoch ); + func->add_arg( "int", "seconds" ); + if( !type_engine_import_mfun( env, func ) ) goto error; + + // end the class import + + type_engine_import_class_end( env ); + + return TRUE; + +error: + + // end the class import + type_engine_import_class_end( env ); + + return FALSE; +}
// Object ctor CK_DLL_CTOR( object_ctor ) @@ -2824,3 +2896,26 @@ OBJ_MEMBER_TIME(fake_msg, MidiMsg_offset_when) = time; }
+//----------------------------------------------------------------------------- +// Timestamp API +//----------------------------------------------------------------------------- + +CK_DLL_SFUN( Timestamp_current ) +{ + Chuck_Timestamp *time = (Chuck_Timestamp *) instantiate_and_initialize_object( &t_timestamp, SHRED ); + time->setToCurrent(); + RETURN->v_timestamp = time; +} + +CK_DLL_MFUN( Timestamp_secondssinceepoch ) +{ + Chuck_Timestamp *time = (Chuck_Timestamp *) SELF; + RETURN->v_int = (t_CKUINT) time->value; +} + +CK_DLL_MFUN( Timestamp_setsecondssinceepoch ) +{ + Chuck_Timestamp *time = (Chuck_Timestamp *) SELF; + t_CKINT seconds = GET_CK_INT( ARGS ); + time->value = (time_t) seconds; +} diff -wur ../../chuck-1.2.1.0-orig/src/chuck_lang.h ./chuck_lang.h --- ../../chuck-1.2.1.0-orig/src/chuck_lang.h 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_lang.h 2007-11-21 10:55:10.000000000 +0100 @@ -60,7 +60,7 @@ t_CKBOOL init_class_Midi( Chuck_Env * env ); t_CKBOOL init_class_MidiRW( Chuck_Env * env ); t_CKBOOL init_class_HID( Chuck_Env * env ); - +t_CKBOOL init_class_Timestamp( Chuck_Env * env, Chuck_Type * type );
@@ -357,7 +357,13 @@ CK_DLL_MFUN( HidOut_printerr ); CK_DLL_MFUN( HidOut_send );
- - +//----------------------------------------------------------------------------- +// Timestamp API +//----------------------------------------------------------------------------- +CK_DLL_CTOR( Timestamp_ctor ); +CK_DLL_DTOR( Timestamp_dtor ); +CK_DLL_SFUN( Timestamp_current ); +CK_DLL_MFUN( Timestamp_secondssinceepoch ); +CK_DLL_MFUN( Timestamp_setsecondssinceepoch );
#endif diff -wur ../../chuck-1.2.1.0-orig/src/chuck_oo.h ./chuck_oo.h --- ../../chuck-1.2.1.0-orig/src/chuck_oo.h 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_oo.h 2007-11-21 09:51:39.000000000 +0100 @@ -343,9 +343,6 @@ std::string str; };
- - - //----------------------------------------------------------------------------- // name: Chuck_IO // desc: base Chuck IO class @@ -463,7 +460,19 @@ std::string m_path; };
+//----------------------------------------------------------------------------- +// name: Chuck_Timestamp +// desc: base Chuck time class +//----------------------------------------------------------------------------- +struct Chuck_Timestamp : Chuck_Object +{ +public: + Chuck_Timestamp() : value( 0 ) { } + ~Chuck_Timestamp() { } + void setToCurrent() { ::time( &value ); }
- +public: + time_t value; +};
#endif diff -wur ../../chuck-1.2.1.0-orig/src/chuck_type.cpp ./chuck_type.cpp --- ../../chuck-1.2.1.0-orig/src/chuck_type.cpp 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_type.cpp 2007-11-21 10:52:33.000000000 +0100 @@ -69,6 +69,7 @@ Chuck_Type t_fileio( te_fileio, "FileIO", &t_io, sizeof(void *) ); Chuck_Type t_thread( te_thread, "Thread", &t_object, sizeof(void *) ); Chuck_Type t_class( te_class, "Class", &t_object, sizeof(void *) ); +Chuck_Type t_timestamp( te_timestamp, "Timestamp", &t_object, sizeof(void *) );
/* exile struct Chuck_Type t_adc = { te_adc, "adc", &t_ugen, t_ugen.size }; @@ -225,6 +226,7 @@ env->global()->type.add( t_event.name, &t_event ); t_event.lock(); env->global()->type.add( t_io.name, &t_io ); t_io.lock(); env->global()->type.add( t_fileio.name, &t_fileio ); t_fileio.lock(); + env->global()->type.add( t_timestamp.name, &t_timestamp ); t_timestamp.lock();
// dur value t_CKDUR samp = 1.0; @@ -249,6 +251,7 @@ init_class_shred( env, &t_shred ); init_class_event( env, &t_event ); init_class_io( env, &t_io ); + init_class_Timestamp( env, &t_timestamp );
EM_log( CK_LOG_SEVERE, "class 'class'" ); t_class.info = new Chuck_Namespace; diff -wur ../../chuck-1.2.1.0-orig/src/chuck_type.h ./chuck_type.h --- ../../chuck-1.2.1.0-orig/src/chuck_type.h 2007-08-23 18:52:47.000000000 +0200 +++ ./chuck_type.h 2007-11-21 09:20:39.000000000 +0100 @@ -52,7 +52,7 @@ te_complex, te_polar, te_string, te_thread, te_shred, te_class, te_function, te_object, te_user, te_array, te_null, te_ugen, te_uana, te_event, te_void, te_stdout, te_stderr, te_adc, te_dac, te_bunghole, - te_uanablob, te_io, te_fileio, te_multi + te_uanablob, te_io, te_fileio, te_multi, te_timestamp } te_Type;
@@ -811,8 +811,7 @@ extern Chuck_Type t_ugen; extern Chuck_Type t_uana; extern Chuck_Type t_uanablob; - - +extern Chuck_Type t_timestamp;
#endif diff -wur ../../chuck-1.2.1.0-orig/src/ulib_std.cpp ./ulib_std.cpp --- ../../chuck-1.2.1.0-orig/src/ulib_std.cpp 2007-08-23 18:52:47.000000000 +0200 +++ ./ulib_std.cpp 2007-11-21 06:27:59.000000000 +0100 @@ -164,6 +164,10 @@ QUERY->add_sfun( QUERY, fabs_impl, "float", "fabs" ); QUERY->add_arg( QUERY, "float", "value" );
+ // add time + + QUERY->add_sfun( QUERY, time_impl, "int", "time" ); + // add rand QUERY->add_sfun( QUERY, rand_impl, "int", "rand"); //! return int between 0 and RAND_MAX
@@ -527,6 +531,13 @@ //RETURN->v_float = ::fabs( GET_CK_FLOAT(ARGS) ); }
+// time + +CK_DLL_SFUN( time_impl ) +{ + RETURN->v_int = ::time( NULL ); +} + // rand CK_DLL_SFUN( rand_impl ) { diff -wur ../../chuck-1.2.1.0-orig/src/ulib_std.h ./ulib_std.h --- ../../chuck-1.2.1.0-orig/src/ulib_std.h 2007-08-23 18:52:47.000000000 +0200 +++ ./ulib_std.h 2007-11-21 06:29:26.000000000 +0100 @@ -41,6 +41,7 @@ // exports CK_DLL_SFUN( abs_impl ); CK_DLL_SFUN( fabs_impl ); +CK_DLL_SFUN( time_impl ); CK_DLL_SFUN( rand_impl ); CK_DLL_SFUN( randf_impl ); CK_DLL_SFUN( rand2f_impl );
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Uhm, I still don't get it. I tried your example on two platforms > yesterday (Mac and Windows -- my Linux machine is 64-bit) and the > numbers are random -- with the exception of the first one
Strange, On my windowsXP system I get excatly the same numbers every time I start the code:51 :(int)585 :(int)233 :(int)819 :(int)606 :(int)506 :(int) ...and infinitely more numbers This relationship between the numbers seems randomly enough, but 51 is always the first, 585 is always the second one, and so on. Therefor it does not seem to use the system time. (At least not with my version, but I am using the latest precompiled one for windows) Jakob _________________________________________________________________ News, entertainment and everything you care about at Live.com. Get it now! http://www.live.com/getstarted.aspx
On 21/11/2007, jakob kaiser
Strange, On my windowsXP system I get excatly the same numbers every time I start the code:
Oh. I read about a weakness of XP's random number generator a while ago from a crypto point of view but that's just silly. On my own XP laptop I just got the same results. On a whim I also tried Std.rand2 instead of Math.rand2 and got the same. This isn't so nice, to put it politely. I'm also kicking myself for never hearing it. Kas.
jakob kaiser wrote:
Uhm, I still don't get it. I tried your example on two platforms yesterday (Mac and Windows -- my Linux machine is 64-bit) and the numbers are random -- with the exception of the first one
Strange, On my windowsXP system I get excatly the same numbers every time I start the code: 51 :(int) 585 :(int) 233 :(int) 819 :(int) 606 :(int) 506 :(int) ...and infinitely more numbers
This relationship between the numbers seems randomly enough, but 51 is always the first, 585 is always the second one, and so on. Therefor it does not seem to use the system time. (At least not with my version, but I am using the latest precompiled one for windows)
I found the pattern -- I was using "--silent" on Windows. Windows seems to use the number of milliseconds since the program started running in its computation of rand(). If you remove the 1::second => now from the loop the numbers are in fact random. Effectively using --silent did that to my runs (since durations aren't respected then). All of the different durations that I tried in your loop seem to produce a different, repeated sequence. -Scott
On 21/11/2007, Scott Wheeler
I found the pattern -- I was using "--silent" on Windows. Windows seems to use the number of milliseconds since the program started running in its computation of rand(). If you remove the 1::second => now from the loop the numbers are in fact random. Effectively using --silent did that to my runs (since durations aren't respected then). All of the different durations that I tried in your loop seem to produce a different, repeated sequence.
Ah! Good work!
Assuming the random number generator itself is solid enough for our
purposes (sounds safe to me as a assumption, it's not that hard) this could
still be fixed by coming up with a per session initial seed for the series,
then basing every new one the last permutation right?
Interestingly this;
----------------------------------
Noise n => blackhole;
//avoid generating a zero (perhaps done to avoid clicks, perhaps it's the
first of the series?)
ms => now;
<<
Kassen wrote:
Assuming the random number generator itself is solid enough for our purposes (sounds safe to me as a assumption, it's not that hard) this could still be fixed by coming up with a per session initial seed for the series, then basing every new one the last permutation right?
From what I saw earlier today (not around a Windows machine at the moment), just adding this at the beginning should work:
srand(rand()); -Scott
On 19/11/2007, jakob kaiser
deep into random generator programming. But the function does not really what you would expect of a random generator, does it?
How about amping up your ADC by lots&lots, casting to int and using that as a seed? Performance will depend on the bit-depth compared to quality of the analogue part of the ADC (I'm seeing very "good" results on the phono pre-amp of my EMU if I leave it open....). What you could also do is start a very fast counter at the start of your program and ask the user to hit the space-bar to stop it, then use the resultant value as a seed. Not matter how deep you get into random number generators, if you want to get around your current problem you will have to come up with some way to get a seed that's not the same every time the program runs, once you get that the default one should be fine. Random number generators aren't very hard to implement anyway, at least not as long as you don't have and secret service agencies chasing you ;¬) Yours, Kas.
jakob kaiser wrote:
Hi, I want to write a small script for ear training with Chuck. Therefore Chuck should produce values that seem to be quite random. But it seems like that the standard functions here are too deterministic. I know that a non-deterministic random function would not be possible, but most programming languages provide functions that create at least new numbers every time I start the same code. However, in chuck something like the following always prints the same numbers when I run it:
Actually the second number should seem random. It's just the first number that's being repeated, most likely. That's the same behavior that you get with the system rand() because it's seeded with the time and when reduced to the range of { 50, 1000 } is the same between two sequential runs. (Admittedly, this behavior annoys me in most C, and ChucK could work around it, but it's just passing on the behavior from a lower level.) -Scott
participants (6)
-
AlgoMantra
-
David Powers
-
jakob kaiser
-
Kassen
-
Michael Heuer
-
Scott Wheeler