Spencer Salazarupdate chuck headers80f02e89 years agoHistory
158 lines · 4.3 KB · C++
RawDownload
/*---------------------------------------------------------------------------- ChucK MagicSine Unit Generator  Implements efficient sine oscillator using the iterative "magic circle"  algorithm, at the expensive of not being able to set the phase (for now at  least). Uses 4 multiplies + 2 adds per sample.   MagicSine is about 25% faster when running a fixed freq sine wave, so its  main use is when you need a lot of sine waves and are hitting a performance bottleneck.   Copyright (c) 2012 Spencer Salazar.  All rights reserved.  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. -----------------------------------------------------------------------------*/  #include "chuck_dl.h"#include "chuck_def.h" #include <stdio.h>#include <limits.h>#include <math.h>  CK_DLL_CTOR(magicsine_ctor);CK_DLL_DTOR(magicsine_dtor); CK_DLL_MFUN(magicsine_setFreq);CK_DLL_MFUN(magicsine_getFreq); CK_DLL_TICK(magicsine_tick); t_CKINT magicsine_data_offset = 0;  class MagicSine{public:        MagicSine(float fs)    {        m_fs = fs;        setFreq(220);                m_x = 1;        m_y = 0;    }        SAMPLE tick(SAMPLE in)    {        m_x = m_x + m_epsilon*m_y;        m_y = -m_epsilon*m_x + m_y;         return m_y;    }        t_CKFLOAT setFreq(t_CKFLOAT f)    {        m_freq = f;        m_epsilon = 2.0*sin(2.0*ONE_PI*(m_freq/m_fs)/2.0);        return m_freq;    }        t_CKFLOAT getFreq() { return m_freq; }    private:        SAMPLE m_x, m_y;    t_CKFLOAT m_fs;    t_CKFLOAT m_freq;    t_CKFLOAT m_epsilon;}; CK_DLL_QUERY(MagicSine){    QUERY->setname(QUERY, "MagicSine");        QUERY->begin_class(QUERY, "MagicSine", "UGen");    QUERY->doc_class(QUERY, "Fast, recursive sine wave generator using the so-called &quot;magic circle&quot; algorithm (see <a href=\"https://ccrma.stanford.edu/~jos/pasp/Digital_Sinusoid_Generators.html\">https://ccrma.stanford.edu/~jos/pasp/Digital_Sinusoid_Generators.html</a>). "        "Can be 30-40% faster than regular SinOsc. "        "Frequency modulation will negate this performance benefit; most useful when pure sine tones are desired or for additive synthesis. ");        QUERY->add_ctor(QUERY, magicsine_ctor);    QUERY->add_dtor(QUERY, magicsine_dtor);        QUERY->add_ugen_func(QUERY, magicsine_tick, NULL, 1, 1);        QUERY->add_mfun(QUERY, magicsine_setFreq, "float", "freq");    QUERY->add_arg(QUERY, "float", "arg");    QUERY->doc_func(QUERY, "Oscillator frequency [Hz]. ");        QUERY->add_mfun(QUERY, magicsine_getFreq, "float", "freq");    QUERY->doc_func(QUERY, "Oscillator frequency [Hz]. ");        magicsine_data_offset = QUERY->add_mvar(QUERY, "int", "@magicsine_data", false);        QUERY->end_class(QUERY);     return TRUE;}  CK_DLL_CTOR(magicsine_ctor){    OBJ_MEMBER_INT(SELF, magicsine_data_offset) = 0;        MagicSine * bcdata = new MagicSine(API->vm->get_srate(API, SHRED));        OBJ_MEMBER_INT(SELF, magicsine_data_offset) = (t_CKINT) bcdata;} CK_DLL_DTOR(magicsine_dtor){    MagicSine * bcdata = (MagicSine *) OBJ_MEMBER_INT(SELF, magicsine_data_offset);    if(bcdata)    {        delete bcdata;        OBJ_MEMBER_INT(SELF, magicsine_data_offset) = 0;        bcdata = NULL;    }} CK_DLL_TICK(magicsine_tick){    MagicSine * c = (MagicSine *) OBJ_MEMBER_INT(SELF, magicsine_data_offset);        if(c) *out = c->tick(in);     return TRUE;} CK_DLL_MFUN(magicsine_setFreq){    MagicSine * bcdata = (MagicSine *) OBJ_MEMBER_INT(SELF, magicsine_data_offset);    // TODO: sanity check    RETURN->v_float = bcdata->setFreq(GET_NEXT_FLOAT(ARGS));} CK_DLL_MFUN(magicsine_getFreq){    MagicSine * bcdata = (MagicSine *) OBJ_MEMBER_INT(SELF, magicsine_data_offset);    RETURN->v_float = bcdata->getFreq();} 

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