/*---------------------------------------------------------------------------- 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.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: ugen_osc.cpp// desc: oscilliator unit generators//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// Philip L. Davidson (philipd@alumni.princeton.edu)// Perry R. Cook (prc@cs.princeton.edu)// Dan Trueman (dtrueman@princeton.edu)// date: Summer 2004//-----------------------------------------------------------------------------#include "ugen_osc.h"#include "chuck_type.h"#include "chuck_ugen.h"#include "chuck_compile.h"#include <math.h>#include <stdio.h> static t_CKUINT g_srateOsc = 0;// for member data offsetstatic t_CKUINT osc_offset_data = 0; //-----------------------------------------------------------------------------// name: osc_query()// desc: ...//-----------------------------------------------------------------------------DLL_QUERY osc_query( Chuck_DL_Query * QUERY ){ // srate g_srateOsc = QUERY->srate; // get the env Chuck_Env * env = QUERY->env(); Chuck_DL_Func * func = NULL; // register deprecate type_engine_register_deprecate( env, "osc", "Osc" ); type_engine_register_deprecate( env, "phasor", "Phasor" ); type_engine_register_deprecate( env, "sinosc", "SinOsc" ); type_engine_register_deprecate( env, "triosc", "TriOsc" ); type_engine_register_deprecate( env, "sawosc", "SawOsc" ); type_engine_register_deprecate( env, "pulseosc", "PulseOsc" ); type_engine_register_deprecate( env, "sqrosc", "SqrOsc" ); std::string doc; //--------------------------------------------------------------------- // init as base class: osc //--------------------------------------------------------------------- doc = "base class for simple oscillator unit generators."; if( !type_engine_import_ugen_begin( env, "Osc", "UGen", env->global(), osc_ctor, osc_dtor, osc_tick, osc_pmsg, doc.c_str() ) ) return FALSE; // add member variable osc_offset_data = type_engine_import_mvar( env, "int", "@osc_data", FALSE ); if( osc_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: freq func = make_new_mfun( "float", "freq", osc_ctrl_freq ); func->add_arg( "float", "hz" ); func->doc = "set frequency of oscillator in Hertz; maintains phase."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", osc_cget_freq ); func->doc = "get frequency of oscillator in Hertz."; if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: period func = make_new_mfun( "dur", "period", osc_ctrl_period ); func->add_arg( "dur", "value" ); func->doc = "set period of oscillator (inverse of frequency)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "period", osc_cget_period ); func->doc = "get period of oscillator (inverse of frequency)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: sfreq ( == freq ) func = make_new_mfun( "float", "sfreq", osc_ctrl_freq ); func->add_arg( "float", "hz" ); func->doc = "set frequency of oscillator in Hertz; resets phase to 0."; if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: phase func = make_new_mfun( "float", "phase", osc_ctrl_phase ); func->add_arg( "float", "phase" ); func->doc = "set oscillator phase, in range [0,1)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "phase", osc_cget_phase ); func->doc = "get oscillator phase, in range [0,1)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: sync func = make_new_mfun( "int", "sync", osc_ctrl_sync ); func->add_arg( "int", "type" ); func->doc = "choose how to interpret input: (0) sync frequency to input; (1) sync phase to input; (2) frequency modulation (add input to internal frequency)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "sync", osc_cget_sync ); func->doc = "get current interpretation of input: (0) sync frequency to input; (1) sync phase to input; (2) frequency modulation (add input to internal frequency)."; if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // phasor //--------------------------------------------------------------------- doc = "a phasor oscillator; linearly rises from 0 to 1; can be used as a phase control."; if( !type_engine_import_ugen_begin( env, "Phasor", "Osc", env->global(), NULL, NULL, osc_tick, NULL, doc.c_str() ) ) return FALSE; // add examples | 1.5.0.0 added if( !type_engine_import_add_ex( env, "basic/phasor.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sinosc //--------------------------------------------------------------------- doc = "a sine wave oscillator."; if( !type_engine_import_ugen_begin( env, "SinOsc", "Osc", env->global(), NULL, NULL, sinosc_tick, NULL, doc.c_str() ) ) return FALSE; // add examples | 1.5.0.0 (ge) type_engine_import_add_ex( env, "otf_05.ck" ); type_engine_import_add_ex( env, "otf_06.ck" ); type_engine_import_add_ex( env, "basic/foo.ck" ); type_engine_import_add_ex( env, "basic/bar.ck" ); type_engine_import_add_ex( env, "basic/chirp.ck" ); type_engine_import_add_ex( env, "basic/alarm.ck" ); type_engine_import_add_ex( env, "basic/whirl.ck" ); type_engine_import_add_ex( env, "analysis/fft.ck" ); // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // triosc - triangle oscillator //--------------------------------------------------------------------- doc = "a triangle wave oscillator."; if( !type_engine_import_ugen_begin( env, "TriOsc", "Osc", env->global(), NULL, NULL, triosc_tick, NULL, doc.c_str() ) ) return FALSE; func = make_new_mfun( "float", "width", osc_ctrl_width ); func->add_arg( "float", "width" ); func->doc = "set width of triangle wave (ratio of rise time to fall time)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "width", osc_cget_width ); func->doc = "get width of triangle wave (ratio of rise time to fall time)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add examples if( !type_engine_import_add_ex( env, "basic/oscillatronx.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "deep/shepard.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sawosc - sawtooth oscillator ( 0 | 1 triangle wave ) //--------------------------------------------------------------------- doc = "sawtooth wave oscillator."; if( !type_engine_import_ugen_begin( env, "SawOsc", "TriOsc", env->global(), sawosc_ctor, NULL, NULL, NULL, doc.c_str() ) ) return FALSE; func = make_new_mfun( "float", "width", sawosc_ctrl_width ); func->add_arg( "float", "width" ); func->doc = "whether sawtooth wave is to fall (0) or rise (1)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "width", osc_cget_width ); func->doc = "whether sawtooth wave is to fall (0) or rise (1)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add examples if( !type_engine_import_add_ex( env, "deep/thx.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "basic/oscillatronx.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // pulseosc - pulse-width oscillator //--------------------------------------------------------------------- doc = "a pulse width oscillator."; if( !type_engine_import_ugen_begin( env, "PulseOsc", "Osc", env->global(), NULL, NULL, pulseosc_tick, NULL, doc.c_str() ) ) return FALSE; func = make_new_mfun( "float", "width", osc_ctrl_width ); func->add_arg( "float", "width" ); func->doc = "set width of duty cycle [0,1)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "width", osc_cget_width ); func->doc = "get width of duty cycle [0,1)/"; if( !type_engine_import_mfun( env, func ) ) goto error; // add examples if( !type_engine_import_add_ex( env, "basic/pulse.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sqrosc - square_wave oscillator ( 0.5 pulse ) //--------------------------------------------------------------------- doc = "a square wave oscillator (same as PulseOsc with 0.5 duty cycle)."; if( !type_engine_import_ugen_begin( env, "SqrOsc", "PulseOsc", env->global(), sqrosc_ctor, NULL, NULL, NULL, doc.c_str() ) ) return FALSE; func = make_new_mfun( "float", "width", sqrosc_ctrl_width ); func->doc = "set width of duty cycle (always 0.5)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add examples if( !type_engine_import_add_ex( env, "basic/oscillatronx.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "filter/brf.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "filter/rlpf.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "filter/rhpf.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); // include GenX!!! if( !genX_query( QUERY ) ) return FALSE; return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE;} //-----------------------------------------------------------------------------// name: struct Osc_Data// desc: ...//-----------------------------------------------------------------------------struct Osc_Data{ t_CKFLOAT num; t_CKFLOAT freq; t_CKINT sync; t_CKUINT srate; t_CKFLOAT width; t_CKFLOAT phase; Osc_Data() { num = 0.0; freq = 220.0; sync = 0; // internal width = 0.5; srate = g_srateOsc; phase = 0.0; }}; //-----------------------------------------------------------------------------// name: osc_ctor()// desc: ...//-----------------------------------------------------------------------------CK_DLL_CTOR( osc_ctor ){ Osc_Data * d = new Osc_Data; Chuck_DL_Return r; // return data to be used later OBJ_MEMBER_UINT(SELF, osc_offset_data) = (t_CKUINT)d; osc_ctrl_freq( SELF, &(d->freq), &r, VM, SHRED, API );} //-----------------------------------------------------------------------------// name: osc_dtor()// desc: ...//-----------------------------------------------------------------------------CK_DLL_DTOR( osc_dtor ){ // get the data Osc_Data * data = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // delete delete data; // set to NULL OBJ_MEMBER_UINT(SELF, osc_offset_data) = 0;} //-----------------------------------------------------------------------------// name: osc_tick()// desc: ...//// basic osx is a phasor...// we use a duty-cycle rep ( 0 - 1 ) rather than angular ( 0 - TWOPI )// sinusoidal oscillators are special//// (maybe) as a rule, we store external phase control values// so that we can have a smooth change back to internal control -pld//// technically this should happen even with external phase control// that we'd be in the right place when translating back to internal...// this was decidely inefficient and nit-picky. -pld////-----------------------------------------------------------------------------CK_DLL_TICK( osc_tick ){ // get the data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; // if input if( ugen->m_num_src ) { // sync frequency to input if( d->sync == 0 ) { // set freq d->freq = in; // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 || d->num < 0.0 ) d->num -= floor( d->num ); } // synch phase to input else if( d->sync == 1 ) { // set phase d->phase = in; // no update inc_phase = FALSE; // bound it (thanks Pyry) if( d->phase > 1.0 || d->phase < 0.0 ) d->phase -= floor( d->phase ); } // fm synthesis else if( d->sync == 2 ) { // set freq t_CKFLOAT freq = d->freq + in; // phase increment d->num = freq / d->srate; // bound it if( d->num >= 1.0 || d->num < 0.0 ) d->num -= floor( d->num ); } // sync to now // else if( d->sync == 3 ) // { // d->phase = now * d->num; // inc_phase = FALSE; // } } // set output to current phase *out = (SAMPLE)d->phase; // check if( inc_phase ) { // step the phase. d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; else if( d->phase < 0.0 ) d->phase += 1.0; } return TRUE;} //-----------------------------------------------------------------------------// name: sinosc_tick()// desc: ...//-----------------------------------------------------------------------------CK_DLL_TICK( sinosc_tick ){ // get the data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; // if input if( ugen->m_num_src ) { // sync frequency to input if( d->sync == 0 ) { // set freq d->freq = in; // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= -1.0 ) d->num += floor( d->num ); } // sync phase to input else if( d->sync == 1 ) { // set freq d->phase = in; inc_phase = FALSE; } // FM synthesis else if( d->sync == 2 ) { // set freq t_CKFLOAT freq = d->freq + in; // phase increment d->num = freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= -1.0 ) d->num += floor( d->num ); } // sync phase to now // else if( d->sync == 3 ) // { // d->phase = now * d->num; // inc_phase = FALSE; // } } // set output *out = (SAMPLE) ::sin( d->phase * TWO_PI ); if( inc_phase ) { // next phase d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; else if( d->phase < 0.0 ) d->phase += 1.0; } return TRUE;} //-----------------------------------------------------------------------------// name: triosc_tick()// desc: ...//-----------------------------------------------------------------------------Lines 1–500 of 1817. Load more
/*---------------------------------------------------------------------------- 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. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_osc.cpp // desc: oscilliator unit generators // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // Philip L. Davidson (philipd@alumni.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Dan Trueman (dtrueman@princeton.edu) // date: Summer 2004 //----------------------------------------------------------------------------- #include "ugen_osc.h" #include "chuck_type.h" #include "chuck_ugen.h" #include "chuck_compile.h" #include <math.h> #include <stdio.h> static t_CKUINT g_srateOsc = 0; // for member data offset static t_CKUINT osc_offset_data = 0; //----------------------------------------------------------------------------- // name: osc_query() // desc: ... //----------------------------------------------------------------------------- DLL_QUERY osc_query( Chuck_DL_Query * QUERY ) { // srate g_srateOsc = QUERY->srate; // get the env Chuck_Env * env = QUERY->env(); Chuck_DL_Func * func = NULL; // register deprecate type_engine_register_deprecate( env, "osc", "Osc" ); type_engine_register_deprecate( env, "phasor", "Phasor" ); type_engine_register_deprecate( env, "sinosc", "SinOsc" ); type_engine_register_deprecate( env, "triosc", "TriOsc" ); type_engine_register_deprecate( env, "sawosc", "SawOsc" ); type_engine_register_deprecate( env, "pulseosc", "PulseOsc" ); type_engine_register_deprecate( env, "sqrosc", "SqrOsc" ); std::string doc; //--------------------------------------------------------------------- // init as base class: osc //--------------------------------------------------------------------- doc = "base class for simple oscillator unit generators."; if( !type_engine_import_ugen_begin( env, "Osc", "UGen", env->global(), osc_ctor, osc_dtor, osc_tick, osc_pmsg, doc.c_str() ) ) return FALSE; // add member variable osc_offset_data = type_engine_import_mvar( env, "int", "@osc_data", FALSE ); if( osc_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: freq func = make_new_mfun( "float", "freq", osc_ctrl_freq ); func->add_arg( "float", "hz" ); func->doc = "set frequency of oscillator in Hertz; maintains phase."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", osc_cget_freq ); func->doc = "get frequency of oscillator in Hertz."; if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: period func = make_new_mfun( "dur", "period", osc_ctrl_period ); func->add_arg( "dur", "value" ); func->doc = "set period of oscillator (inverse of frequency)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "period", osc_cget_period ); func->doc = "get period of oscillator (inverse of frequency)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: sfreq ( == freq ) func = make_new_mfun( "float", "sfreq", osc_ctrl_freq ); func->add_arg( "float", "hz" ); func->doc = "set frequency of oscillator in Hertz; resets phase to 0."; if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: phase func = make_new_mfun( "float", "phase", osc_ctrl_phase ); func->add_arg( "float", "phase" ); func->doc = "set oscillator phase, in range [0,1)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "phase", osc_cget_phase ); func->doc = "get oscillator phase, in range [0,1)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: sync func = make_new_mfun( "int", "sync", osc_ctrl_sync ); func->add_arg( "int", "type" ); func->doc = "choose how to interpret input: (0) sync frequency to input; (1) sync phase to input; (2) frequency modulation (add input to internal frequency)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "sync", osc_cget_sync ); func->doc = "get current interpretation of input: (0) sync frequency to input; (1) sync phase to input; (2) frequency modulation (add input to internal frequency)."; if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // phasor //--------------------------------------------------------------------- doc = "a phasor oscillator; linearly rises from 0 to 1; can be used as a phase control."; if( !type_engine_import_ugen_begin( env, "Phasor", "Osc", env->global(), NULL, NULL, osc_tick, NULL, doc.c_str() ) ) return FALSE; // add examples | 1.5.0.0 added if( !type_engine_import_add_ex( env, "basic/phasor.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sinosc //--------------------------------------------------------------------- doc = "a sine wave oscillator."; if( !type_engine_import_ugen_begin( env, "SinOsc", "Osc", env->global(), NULL, NULL, sinosc_tick, NULL, doc.c_str() ) ) return FALSE; // add examples | 1.5.0.0 (ge) type_engine_import_add_ex( env, "otf_05.ck" ); type_engine_import_add_ex( env, "otf_06.ck" ); type_engine_import_add_ex( env, "basic/foo.ck" ); type_engine_import_add_ex( env, "basic/bar.ck" ); type_engine_import_add_ex( env, "basic/chirp.ck" ); type_engine_import_add_ex( env, "basic/alarm.ck" ); type_engine_import_add_ex( env, "basic/whirl.ck" ); type_engine_import_add_ex( env, "analysis/fft.ck" ); // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // triosc - triangle oscillator //--------------------------------------------------------------------- doc = "a triangle wave oscillator."; if( !type_engine_import_ugen_begin( env, "TriOsc", "Osc", env->global(), NULL, NULL, triosc_tick, NULL, doc.c_str() ) ) return FALSE; func = make_new_mfun( "float", "width", osc_ctrl_width ); func->add_arg( "float", "width" ); func->doc = "set width of triangle wave (ratio of rise time to fall time)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "width", osc_cget_width ); func->doc = "get width of triangle wave (ratio of rise time to fall time)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add examples if( !type_engine_import_add_ex( env, "basic/oscillatronx.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "deep/shepard.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sawosc - sawtooth oscillator ( 0 | 1 triangle wave ) //--------------------------------------------------------------------- doc = "sawtooth wave oscillator."; if( !type_engine_import_ugen_begin( env, "SawOsc", "TriOsc", env->global(), sawosc_ctor, NULL, NULL, NULL, doc.c_str() ) ) return FALSE; func = make_new_mfun( "float", "width", sawosc_ctrl_width ); func->add_arg( "float", "width" ); func->doc = "whether sawtooth wave is to fall (0) or rise (1)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "width", osc_cget_width ); func->doc = "whether sawtooth wave is to fall (0) or rise (1)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add examples if( !type_engine_import_add_ex( env, "deep/thx.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "basic/oscillatronx.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // pulseosc - pulse-width oscillator //--------------------------------------------------------------------- doc = "a pulse width oscillator."; if( !type_engine_import_ugen_begin( env, "PulseOsc", "Osc", env->global(), NULL, NULL, pulseosc_tick, NULL, doc.c_str() ) ) return FALSE; func = make_new_mfun( "float", "width", osc_ctrl_width ); func->add_arg( "float", "width" ); func->doc = "set width of duty cycle [0,1)."; if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "width", osc_cget_width ); func->doc = "get width of duty cycle [0,1)/"; if( !type_engine_import_mfun( env, func ) ) goto error; // add examples if( !type_engine_import_add_ex( env, "basic/pulse.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sqrosc - square_wave oscillator ( 0.5 pulse ) //--------------------------------------------------------------------- doc = "a square wave oscillator (same as PulseOsc with 0.5 duty cycle)."; if( !type_engine_import_ugen_begin( env, "SqrOsc", "PulseOsc", env->global(), sqrosc_ctor, NULL, NULL, NULL, doc.c_str() ) ) return FALSE; func = make_new_mfun( "float", "width", sqrosc_ctrl_width ); func->doc = "set width of duty cycle (always 0.5)."; if( !type_engine_import_mfun( env, func ) ) goto error; // add examples if( !type_engine_import_add_ex( env, "basic/oscillatronx.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "filter/brf.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "filter/rlpf.ck" ) ) goto error; if( !type_engine_import_add_ex( env, "filter/rhpf.ck" ) ) goto error; // end the class import type_engine_import_class_end( env ); // include GenX!!! if( !genX_query( QUERY ) ) return FALSE; return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } //----------------------------------------------------------------------------- // name: struct Osc_Data // desc: ... //----------------------------------------------------------------------------- struct Osc_Data { t_CKFLOAT num; t_CKFLOAT freq; t_CKINT sync; t_CKUINT srate; t_CKFLOAT width; t_CKFLOAT phase; Osc_Data() { num = 0.0; freq = 220.0; sync = 0; // internal width = 0.5; srate = g_srateOsc; phase = 0.0; } }; //----------------------------------------------------------------------------- // name: osc_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( osc_ctor ) { Osc_Data * d = new Osc_Data; Chuck_DL_Return r; // return data to be used later OBJ_MEMBER_UINT(SELF, osc_offset_data) = (t_CKUINT)d; osc_ctrl_freq( SELF, &(d->freq), &r, VM, SHRED, API ); } //----------------------------------------------------------------------------- // name: osc_dtor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_DTOR( osc_dtor ) { // get the data Osc_Data * data = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // delete delete data; // set to NULL OBJ_MEMBER_UINT(SELF, osc_offset_data) = 0; } //----------------------------------------------------------------------------- // name: osc_tick() // desc: ... // // basic osx is a phasor... // we use a duty-cycle rep ( 0 - 1 ) rather than angular ( 0 - TWOPI ) // sinusoidal oscillators are special // // (maybe) as a rule, we store external phase control values // so that we can have a smooth change back to internal control -pld // // technically this should happen even with external phase control // that we'd be in the right place when translating back to internal... // this was decidely inefficient and nit-picky. -pld // //----------------------------------------------------------------------------- CK_DLL_TICK( osc_tick ) { // get the data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; // if input if( ugen->m_num_src ) { // sync frequency to input if( d->sync == 0 ) { // set freq d->freq = in; // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 || d->num < 0.0 ) d->num -= floor( d->num ); } // synch phase to input else if( d->sync == 1 ) { // set phase d->phase = in; // no update inc_phase = FALSE; // bound it (thanks Pyry) if( d->phase > 1.0 || d->phase < 0.0 ) d->phase -= floor( d->phase ); } // fm synthesis else if( d->sync == 2 ) { // set freq t_CKFLOAT freq = d->freq + in; // phase increment d->num = freq / d->srate; // bound it if( d->num >= 1.0 || d->num < 0.0 ) d->num -= floor( d->num ); } // sync to now // else if( d->sync == 3 ) // { // d->phase = now * d->num; // inc_phase = FALSE; // } } // set output to current phase *out = (SAMPLE)d->phase; // check if( inc_phase ) { // step the phase. d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; else if( d->phase < 0.0 ) d->phase += 1.0; } return TRUE; } //----------------------------------------------------------------------------- // name: sinosc_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( sinosc_tick ) { // get the data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; // if input if( ugen->m_num_src ) { // sync frequency to input if( d->sync == 0 ) { // set freq d->freq = in; // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= -1.0 ) d->num += floor( d->num ); } // sync phase to input else if( d->sync == 1 ) { // set freq d->phase = in; inc_phase = FALSE; } // FM synthesis else if( d->sync == 2 ) { // set freq t_CKFLOAT freq = d->freq + in; // phase increment d->num = freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= -1.0 ) d->num += floor( d->num ); } // sync phase to now // else if( d->sync == 3 ) // { // d->phase = now * d->num; // inc_phase = FALSE; // } } // set output *out = (SAMPLE) ::sin( d->phase * TWO_PI ); if( inc_phase ) { // next phase d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; else if( d->phase < 0.0 ) d->phase += 1.0; } return TRUE; } //----------------------------------------------------------------------------- // name: triosc_tick() // desc: ... //-----------------------------------------------------------------------------