3096 lines · 93.0 KB · C++
RawDownload
/*----------------------------------------------------------------------------  ChucK Concurrent, On-the-fly Audio Programming Language    Compiler and Virtual Machine   Copyright (c) 2004 Ge Wang and Perry R. Cook.  All rights reserved.    http://chuck.stanford.edu/    http://chuck.cs.princeton.edu/   This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 of the License, or  (at your option) any later version.   This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.   You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// name: chuck_lang.cpp// desc: chuck class library base//// authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)//          Spencer Salazar (spencer@ccrma.stanford.edu)//          Ananya Misra (amisra@cs.princeton.edu)//          Andrew Schran (aschran@princeton.edu)//    date: spring 2005//-----------------------------------------------------------------------------#include "chuck_lang.h"#include "chuck_type.h"#include "chuck_instr.h"#include "chuck_vm.h"#include "chuck_errmsg.h"#include "chuck_ugen.h"#include "util_string.h" #include <math.h>#include <iostream>#include <iomanip>#include <sstream>using namespace std; // dac tickCK_DLL_TICK(__ugen_tick) { *out = in; return TRUE; }// object string offsetstatic t_CKUINT Object_offset_string = 0;    //-----------------------------------------------------------------------------// name: init_class_object()// desc: initialize the base Object class//-----------------------------------------------------------------------------t_CKBOOL init_class_object( Chuck_Env * env, Chuck_Type * type ){    Chuck_DL_Func * func = NULL;     // log    EM_log( CK_LOG_SEVERE, "class 'Object'" );     const char * doc = "base class for all class types in ChucK.";     // init as base class    if( !type_engine_import_class_begin( env, type, env->global(), object_ctor, object_dtor, doc ) )        return FALSE;     // add member to hold string    Object_offset_string = type_engine_import_mvar( env, "string", "@string", FALSE );    if( Object_offset_string == CK_INVALID_OFFSET ) goto error;     // add toString()    func = make_new_mfun( "string", "toString", object_toString );    func->doc = "get a textual description of this object.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add help()    func = make_new_sfun( "void", "help", object_help );    func->doc = "output helpful information about a class or an instance thereof.";    if( !type_engine_import_sfun( env, func ) ) goto error;     // add getType() // 1.4.2.1    func = make_new_sfun( "Type", "typeOf", object_typeInfo );    func->doc = "get the type of this object (or class).";    if( !type_engine_import_sfun( env, func ) ) goto error; //    // add dump()//    func = make_new_mfun( "void", "dump", object_dump );//    func->doc = "output current state of the object.";//    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;}    //-----------------------------------------------------------------------------// name: init_class_ugen()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL init_class_ugen( Chuck_Env * env, Chuck_Type * type ){    Chuck_DL_Func * func = NULL;     EM_log( CK_LOG_SEVERE, "class 'UGen'" );     // add ugen info    type->ugen_info = new Chuck_UGen_Info;    type->ugen_info->add_ref();    type->ugen_info->tick = __ugen_tick;    type->ugen_info->num_ins = 1;    type->ugen_info->num_outs = 1;     const char * doc = "base class for all unit generator (UGen) types.";     // init as base class    // TODO: ctor/dtor, ugen's sometimes created internally?    if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )        return FALSE;     // gain    func = make_new_mfun( "float", "gain", ugen_gain );    func->add_arg( "float", "val" );    func->doc = "set the gain of the unit generator.";    if( !type_engine_import_mfun( env, func ) ) goto error;    func = make_new_mfun( "float", "gain", ugen_cget_gain );    func->doc = "get the gain of the unit generator.";    if( !type_engine_import_mfun( env, func ) ) goto error; /*    // next    func = make_new_mfun( "float", "next", ugen_next );    func->add_arg( "float", "val" );    if( !type_engine_import_mfun( env, func ) ) goto error;    func = make_new_mfun( "float", "next", ugen_cget_next );    if( !type_engine_import_mfun( env, func ) ) goto error;*/    // last    func = make_new_mfun( "float", "last", ugen_last );    func->doc = "get the last sample value of the unit generator.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // op    func = make_new_mfun( "int", "op", ugen_op );    func->add_arg( "int", "val" );    func->doc = "set the unit generator's operation mode. Accepted values are: 1 (sum inputs), 2 (take difference between first input and subsequent inputs), 3 (multiply inputs), 4 (divide first input by subsequent inputs), 0 (do not synthesize audio, output 0) or -1 (passthrough inputs to output).";    if( !type_engine_import_mfun( env, func ) ) goto error;    func = make_new_mfun( "int", "op", ugen_cget_op );    func->doc = "get the unit generator's operation mode.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add numChannels    func = make_new_mfun( "int", "channels", ugen_numChannels );    func->add_arg( "int", "num" );    func->doc = "set number of channels. (currently NOT supported)";    if( !type_engine_import_mfun( env, func ) ) goto error;    func = make_new_mfun( "int", "channels", ugen_cget_numChannels );    func->doc = "get number of channels.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add chan    func = make_new_mfun( "UGen", "chan", ugen_chan );    func->add_arg( "int", "num" );    func->doc = "get channel (as a UGen) at specified index.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add isConnectedTo    func = make_new_mfun( "int", "isConnectedTo", ugen_connected );    func->add_arg( "UGen", "right" );    func->doc = "return true if this UGen's output is connected to the input of the argument; return false otherwise.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add buffered    func = make_new_mfun( "int", "buffered", ugen_buffered );    func->add_arg( "int", "val" );    func->doc = "set the unit generator's buffered operation mode, typically used externally from hosts that embed ChucK as a component. If true, the UGen stores a buffer of its most recent samples, which can be fetched using global variables in the host language.";    if( !type_engine_import_mfun( env, func ) ) goto error;    func = make_new_mfun( "int", "buffered", ugen_cget_buffered );    func->doc = "get the ugen's buffered operation mode.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // end    type_engine_import_class_end( env );     return TRUE; error:     // end the class import    type_engine_import_class_end( env );     return FALSE;}    // virtual table offsetstatic t_CKINT uana_offset_blob = 0;//-----------------------------------------------------------------------------// name: init_class_uana()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL init_class_uana( Chuck_Env * env, Chuck_Type * type ){    Chuck_DL_Func * func = NULL;     EM_log( CK_LOG_SEVERE, "class 'UAna'" );     // add uana info    type->ugen_info = new Chuck_UGen_Info;    type->ugen_info->add_ref();    type->ugen_info->tick = __ugen_tick;    type->ugen_info->num_ins = 1;    type->ugen_info->num_outs = 1;     const char * doc = "base class from which all unit analyzer (UAna) types inherit; UAnae (note plural form) can be interconnected using => (chuck operator for synthesis; all UAnae are also UGens) or using =^ (upchuck operator for analysis) -- the operator used will determine how data is passed. When .upchuck() is invoked on a given UAna, the UAna-chain (i.e., UAnae connected via =^) is traversed upstream from the upchucked UAna, and analysis is performed at each UAna along the chain; the analysis results are returned in UAnaBlobs.";     // init as base class, type should already know the parent type    // TODO: ctor/dtor, ugen's sometimes created internally?    if( !type_engine_import_class_begin( env, type, env->global(), uana_ctor, uana_dtor, doc ) )        return FALSE;     // add variables    uana_offset_blob = type_engine_import_mvar( env, "UAnaBlob", "m_blob", FALSE );    if( uana_offset_blob == CK_INVALID_OFFSET ) goto error;     // add upchuck    func = make_new_mfun( "UAnaBlob", "upchuck", uana_upchuck );    func->doc = "initiate analysis at the UAna and return result.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add fvals    func = make_new_mfun( "float[]", "fvals", uana_fvals );    func->doc = "get blob's float array.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add cvals    func = make_new_mfun( "complex[]", "cvals", uana_cvals );    func->doc = "get blob's complex array.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add fval    func = make_new_mfun( "float", "fval", uana_fval );    func->add_arg( "int", "index" );    func->doc = "get blob's float value at index.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add cval    func = make_new_mfun( "complex", "cval", uana_cval );    func->add_arg( "int", "index" );    func->doc = "get blob's complex value at index.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add isUpConnectedTo    func = make_new_mfun( "int", "isUpConnectedTo", uana_connected );    func->add_arg( "UAna", "right" );    func->doc = "is connected to another uana via =^?";    if( !type_engine_import_mfun( env, func ) ) goto error;     // TODO: add nonchuck    // func = make_new_mfun( "void", "nonchuck", uana_nonchuck );    // if( !type_engine_import_mfun( env, func ) ) goto error;     // TODO: add event    // func = make_new_mfun( "Event", "event", uana_event );    // if( !type_engine_import_mfun( env, func ) ) goto error;     // end    type_engine_import_class_end( env );     return TRUE; error:     // end the class import    type_engine_import_class_end( env );     return FALSE;}    // virtual table offsetstatic t_CKINT uanablob_offset_when = 0;static t_CKINT uanablob_offset_fvals = 0;static t_CKINT uanablob_offset_cvals = 0;//-----------------------------------------------------------------------------// name: init_class_blob()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL init_class_blob( Chuck_Env * env, Chuck_Type * type ){    Chuck_DL_Func * func = NULL;    // Chuck_Value * value = NULL;     // log    EM_log( CK_LOG_SEVERE, "class 'UAnaBlob'" );     const char * doc = "a data structure that contains results associated with UAna analysis. There is a UAnaBlob associated with every UAna. As a UAna is upchucked (using .upchuck()), the result is stored in the UAnaBlob's floating point vector and/or complex vector. The interpretation of the results depends on the specific UAna.";     // init class    // TODO: ctor/dtor    if( !type_engine_import_class_begin( env, type, env->global(), uanablob_ctor, uanablob_dtor, doc ) )        return FALSE;     // add variables    uanablob_offset_when = type_engine_import_mvar( env, "time", "m_when", FALSE );    if( uanablob_offset_when == CK_INVALID_OFFSET ) goto error;    uanablob_offset_fvals = type_engine_import_mvar( env, "float[]", "m_fvals", FALSE );    if( uanablob_offset_fvals == CK_INVALID_OFFSET ) goto error;    uanablob_offset_cvals = type_engine_import_mvar( env, "complex[]", "m_cvals", FALSE );    if( uanablob_offset_cvals == CK_INVALID_OFFSET ) goto error;     // add when    func = make_new_mfun( "time", "when", uanablob_when );    func->doc = "get the time when blob was last upchucked.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add fvals    func = make_new_mfun( "float[]", "fvals", uanablob_fvals );    func->doc = "get blob's float array.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add cvals    func = make_new_mfun( "complex[]", "cvals", uanablob_cvals );    func->doc = "get blob's complex array.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add fval    func = make_new_mfun( "float", "fval", uanablob_fval );    func->add_arg( "int", "index" );    func->doc = "get blob's float value at index.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add cval    func = make_new_mfun( "complex", "cval", uanablob_cval );    func->add_arg( "int", "index" );    func->doc = "get blob's complex value at index.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // end class import    type_engine_import_class_end( env );     // done    return TRUE; error:     // end class import    type_engine_import_class_end( env );     // error    return FALSE;}    // static t_CKUINT event_offset_data = 0;//-----------------------------------------------------------------------------// name: init_class_event()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL init_class_event( Chuck_Env * env, Chuck_Type * type ){    Chuck_DL_Func * func = NULL;    Chuck_Value * value = NULL;     // log    EM_log( CK_LOG_SEVERE, "class 'Event'" );     const char *doc = "a mechanism for precise synchronization across shreds.";     // init as base class    // TODO: ctor/dtor?    if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )        return FALSE;     // add signal()    func = make_new_mfun( "void", "signal", event_signal );    func->doc = "signal one shred that is waiting on this event.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add broadcast()    func = make_new_mfun( "void", "broadcast", event_broadcast );    func->doc = "signal all shreds that are waiting on this event.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add wait() | commented out 1.4.1.0 (ge) -- it doesn't DO anything!!!    // func = make_new_mfun( "void", "wait", event_wait );    // func->add_arg( "Shred", "me" );    // func->doc = "(currently unsupported; use Event => now to wait on event)";    // if( !type_engine_import_mfun( env, func ) ) goto error;     // add can_wait()    func = make_new_mfun( "int", "can_wait", event_can_wait );    func->doc = "can the event can be waited on? Currently always returns true.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // end the class import    type_engine_import_class_end( env );     // find the offset for can_wait    value = type_engine_find_value( type, "can_wait" );    assert( value != NULL );    assert( value->func_ref != NULL );    // remember it    Chuck_Event::our_can_wait = value->func_ref->vt_index;     return TRUE; error:     // end the class import    type_engine_import_class_end( env );     return FALSE;}    // static t_CKUINT shred_offset_args = 0;//-----------------------------------------------------------------------------// name: init_class_shred()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL init_class_shred( Chuck_Env * env, Chuck_Type * type ){    // init as base class    Chuck_DL_Func * func = NULL;     // log    EM_log( CK_LOG_SEVERE, "class 'Shred'" );     const char *doc = "a strongly-timed ChucK thread of execution.";     // init as base class    // TODO: ctor/dtor?    if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )        return FALSE;     // add dtor    // not     // add fromId()    func = make_new_sfun( "Shred", "fromId", shred_fromId );    func->add_arg( "int", "id" );    func->doc = "get Shred corresponding to a Shred ID.";    if( !type_engine_import_sfun( env, func ) ) goto error;     // add clone()    func = make_new_mfun( "void", "clone", shred_clone );    if( !type_engine_import_mfun( env, func ) ) goto error;     // add exit()    func = make_new_mfun( "void", "exit", shred_exit );    func->doc = "halt the shred's operation and remove it from the virtual machine.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add id()    func = make_new_mfun( "int", "id", shred_id );    func->doc = "get the unique numeric id of the Shred.";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add yield()    func = make_new_mfun( "void", "yield", shred_yield );    func->doc = "cause the current Shred to temporarily suspend without advancing time, allowing other simultaneously schreduled shreds to run as needed. NOTE: yield() is equivalent to '0::second +=> now;'";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add running()    func = make_new_mfun( "int", "running", shred_running );    func->doc = "is the Shred currently running?";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add done()    func = make_new_mfun( "int", "done", shred_done );    func->doc = "is the Shred done running?";    if( !type_engine_import_mfun( env, func ) ) goto error;     // add nargs()    // func = make_new_mfun( "int", "numArgs", shred_numArgs );

Lines 1–500 of 3096.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t