1817 lines · 57.6 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.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// 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.

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