All pastes #516377 Raw Edit

Something

public text v1 · immutable
#516377 ·published 2007-05-28 17:36 UTC
rendered paste body
/*-----------------------------------------------------------------------------

© 2002, Jeff M Soft und Hardware GmbH, All Rights Reserved

-----------------------------------------------------------------------------*/

#include "Module.h"
#include "SEMod_struct.h"
#include "SEPin.h"
#include <assert.h>
#include <math.h>
// define some constants to make referencing in/outs clearer
#define PN_INPUT1 0
#define PN_INPUT2 1
#define PN_INPUT3 2
#define PN_INPUT4 3
#define PN_INPUT5 4
#define PN_OUTPUT1 5
#define PN_OUTPUT2 6
#define COEF1 0.45 // 0.15 - 0.25
#define COEF2 1.16 // 1.16
#define MAXR 2.5
#define COEF3 0.3673
// #define COEFR 0.5

// The most important part, processing the audio
void Module::sub_MONO(long buffer_offset, long sampleFrames )
{
	// assign some pointers to your in/output buffers. usually blocks (array) of 96 samples
    float *in1  = buffer_offset + input1_buffer; // AUDIO-L
//  float *in2  = buffer_offset + input2_buffer; // AUTIO-R
    float *in3  = buffer_offset + input3_buffer; // Freq
    float *in4  = buffer_offset + input4_buffer; // Reso
    float *in5  = buffer_offset + input5_buffer; // <spare>
    float *out1 = buffer_offset + output1_buffer;
    float *out2 = buffer_offset + output2_buffer;
    float *o3 = buffer_offset + o3_buffer;
    float *o4 = buffer_offset + o4_buffer;
    float *in6  = buffer_offset + input6_buffer; // <spare>

    while(--sampleFrames >= 0) // sampleFrames = how many samples to process (can vary). repeat (loop) that many times
    {
        FREQ = (*in3 * 20000) * NI; // F / SR
        if( FREQ >= 1 ) { FREQ = 1; }
        else if( FREQ <= 0.000090702 ) { FREQ = 0.000090702; }
        // original 1.16
        F = FREQ * COEF2;
        RES = *in4 * 2.5;
        if( RES >= MAXR ) { RES = MAXR; }
        FB = RES * (1.0 - COEF1 * F * F); // RES * (1.0 - 0.15 * F * F) // COEF1
        LIM = *in5;
        // ------------------------------------------- //
        x0 = *in1 - (y4 * FB); // y4/OUT << (feedback)
        // CX = 1 - (cy4 * FB);
        CR = 0.54 - (RES * 0.0959999);
        COEFR = CR + (FREQ * 0.25);
        x0 *= COEFR * (F * F) * (F * F); // COEFR
                // original 0.35013, good looking 0.5 // COEFR
        // ; ------------------------------------------------------------------- Pole 1
        y1 = x0 + COEF3 * x1 + (1 - F) * y1;
        x1 = x0;
        // ; ------------------------------------------------------------------- Pole 2
        y2 = y1 + COEF3 * x2 + (1 - F) * y2;
        x2 = y1;
        // ; ------------------------------------------------------------------- Pole 3
        y3 = y2 + COEF3 * x3 + (1 - F) * y3;
        x3 = y2;
        // ; ------------------------------------------------------------------- Pole 4
        y4 = y3 + COEF3 * x4 + (1 - F) * y4;
        x4 = y3;
        // COEFX = 1.57 - 1.53 - (((RES - 1.47) * -0.358) + (RES - 3.975) * (((RES * -1) + 2.32) * 0.2225));
        // COEFX = 0.633 + (RES * 0.8668);
        COEFX = 0.404 + (RES * 0.8764001);
        switch (MODE)
        {
            case 1:
                OUT = y4 * 1; // LP
                break;
            case 2:
                OUT = (*in1 - (y4 * COEFX)); // HP (pri res 1.4V e ok)
                break;
            case 3:
                OUT = ((y1 * COEFX) + (y2 * COEFX) + (y3 * COEFX) + ((y4 * -1) * COEFX));
                break;
            case 4:
                OUT = *in1 + ((y1 * COEFX) + (y2 * COEFX) + (y3 * COEFX) + ((y4 * -1) * COEFX));
                break;
            case 5:
                F = 2.f * sin(M_PI * FREQ); //[approximately]
                Q = *in4;
                QS = Q;
                SVFL = SVFL + F * SVFB;
                SVFH = QS * *in1 - SVFL - Q * SVFB;
                SVFB = F * SVFH + SVFB;
                SVFN = SVFH + SVFL;
                OUT = SVFL;
                break;
            default:
            return;
        };
        // if      (OUT > LIM) { OUT = LIM; }
        // else if (OUT < (LIM * -1)) { OUT = (LIM * -1); }
		*out1 = OUT; // OUTPUT
        *out2 = OUT; // MONO
        *o3 = RES * 0.1;
        *o4 = FREQ * 0.1;
        // increment the pointers (move to next sample in buffers)
		in1++;
//		in2++;
        in3++;
		in4++;
        in5++;
		in6++;
		out1++;
        out2++;
        o3++;
        o4++;
    }
}
void Module::sub_STEREO(long buffer_offset, long sampleFrames )
{
	// assign some pointers to your in/output buffers. usually blocks (array) of 96 samples
    float *in1  = buffer_offset + input1_buffer; // AUDIO-L
    float *in2  = buffer_offset + input2_buffer; // AUTIO-R
    float *in3  = buffer_offset + input3_buffer; // Freq
    float *in4  = buffer_offset + input4_buffer; // Reso
    float *in5  = buffer_offset + input5_buffer; // <spare>
    float *in6  = buffer_offset + input6_buffer;
    float *out1 = buffer_offset + output1_buffer;
    float *out2 = buffer_offset + output2_buffer;

    while(--sampleFrames >= 0) // sampleFrames = how many samples to process (can vary). repeat (loop) that many times
    {
        FREQ = (*in3 * 20000) * NI;
        if( FREQ >= 1 ) { FREQ = 1; }
        else if( FREQ <= 0.000090702 ) { FREQ = 0.000090702; }
        // original 1.16
        F = FREQ * COEF2;
        RES = *in4 * 2.5;
        if( RES >= MAXR ) { RES = MAXR; }
        FB = RES * (1.0 - COEF1 * F * F); // RES * (1.0 - 0.15 * F * F) // COEF1
        LIM = *in5;
        // ------------------------------------------- //
        x0 = *in1 - (y4 * FB); // y4/OUT << (feedback)
        v0 = *in2 - (z4 * FB); // y4/OUT << (feedback)
        x0 *= COEFR * (F * F) * (F * F);
        v0 *= COEFR * (F * F) * (F * F);
        // original 0.35013, good looking 0.5 // COEFR
        // ; ------------------------------------------------------------------- Pole 1
        y1 = x0 + COEF3 * x1 + (1 - F) * y1;
        z1 = v0 + COEF3 * v1 + (1 - F) * z1;
        x1 = x0;
        v1 = v0;
        // ; ------------------------------------------------------------------- Pole 2
        y2 = y1 + COEF3 * x2 + (1 - F) * y2;
        z2 = z1 + COEF3 * v2 + (1 - F) * z2;
        x2 = y1;
        v2 = z1;
        // ; ------------------------------------------------------------------- Pole 3
        y3 = y2 + COEF3 * x3 + (1 - F) * y3;
        z3 = z2 + COEF3 * v3 + (1 - F) * z3;
        x3 = y2;
        v3 = z2;
        // ; ------------------------------------------------------------------- Pole 4
        y4 = y3 + COEF3 * x4 + (1 - F) * y4;
        z4 = z3 + COEF3 * v4 + (1 - F) * z4;
        x4 = y3;
        v4 = z3;
        COEFX = 0.633 + (RES * 0.8668);
        switch (MODE)
        {
            case 1:
                OUTL = (y4 * COEFX); // LP
                OUTR = (z4 * COEFX); // LP
                break;
            case 2:
                OUTL = (*in1 - (y4 * COEFX)); // HP (pri res 1.4V e ok)
                OUTR = (*in2 - (z4 * COEFX)); // HP (pri res 1.4V e ok)
                break;
            case 3:
                OUTL = ((y1 * COEFX) + (y2 * COEFX) + (y3 * COEFX) + ((y4 * -1) * COEFX));
                OUTR = ((z1 * COEFX) + (z2 * COEFX) + (z3 * COEFX) + ((z4 * -1) * COEFX));
                break;
            case 4:
                OUTL = *in1 + ((y1 * COEFX) + (y2 * COEFX) + (y3 * COEFX) + ((y4 * -1) * COEFX));
                OUTR = *in2 + ((z1 * COEFX) + (z2 * COEFX) + (z3 * COEFX) + ((z4 * -1) * COEFX));
                break;
            case 5:
                y5 = y4 + COEF3 * x5 + (1 - F) * y5;
                z5 = z4 + COEF3 * v5 + (1 - F) * z5;
                x5 = y4;
                v5 = z4;
                y6 = y5 + COEF3 * x6 + (1 - F) * y6;
                z6 = z5 + COEF3 * v6 + (1 - F) * z6;
                x6 = y5;
                v6 = z5;
                OUTL = (y6 * 0.2);
                OUTR = (z6 * 0.2);
                break;
            default:
            return;
        };
        //OUTL = y4;
        //OUTR = z4;
        //if      (OUTL > LIM) { OUTL = LIM; }
        //else if (OUTL < (LIM * -1)) { OUTL = (LIM * -1); }
		//if      (OUTR > LIM) { OUTR = LIM; }
        //else if (OUTR < (LIM * -1)) { OUTR = (LIM * -1); }
		*out1 = OUTL; // OUTPUT
        *out2 = OUTR; // OUTPUT
        // increment the pointers (move to next sample in buffers)
		in1++;
		in2++;
        in3++;
		in4++;
        in5++;
		out1++;
        out2++;
    }
}
// every module has an output buffer of approx 100 samples.
// before deactivating module, need to fill that buffer with silence.
// "static_count" is counting out those 100 samples.

void Module::sub_process_static(long buffer_offset, long sampleFrames )
{
	sub_MONO(buffer_offset, sampleFrames);
	static_count = static_count - sampleFrames;
	if( static_count <= 0 )
	{
		// CallHost(seaudioMasterSleepMode);
	}
}

Module::Module(seaudioMasterCallback2 seaudioMaster, void *p_resvd1) : SEModule_base(seaudioMaster, p_resvd1)
{
}

void Module::open()
{
    // SET SAMPLE RATE
    SR = getSampleRate();
    NI = SR / 2;
    NI = 1 / NI;
	// call the base class
	SEModule_base::open();

	// choose which function is used to process audio
	SET_PROCESS_FUNC(Module::sub_MONO);

	// How to prevent other people using your custom module.
	// query the current registered user's name
	char host_registered_to[100];
	CallHost( seaudioMasterGetRegisteredName, 0,0, host_registered_to );
	bool registered_to_me = strcmp(host_registered_to, "Jeff McClintock") == 0;

	if( !registered_to_me )
	{
		// do something appropriate here if you don't want other people using your module
	}
}

Module::~Module()
{
	// This is where you free any memory/resources your module has created
}

// describe your module
bool Module::getModuleProperties (SEModuleProperties* properties)
{
	// describe the plugin, this is the name the end-user will see.
	properties->name = "AS_F24S";								// !!TODO!!

	// return a unique string 32 characters max
	// if posible include manufacturer and plugin identity
	// this is used internally by SE to identify the plug.
	// No two plugs may have the same id.
	properties->id = "AS_F24S_v0.98";						// !!TODO!!

	// Info, may include Author, Web page whatever
	properties->about = "by Anton Savov [antto]";								// !!TODO!!
	return true;
}

// describe the pins (plugs and parameters)
bool Module::getPinProperties (long index, SEPinProperties* properties)
{
	switch( index )								// !!TODO!! list your in / out plugs
	{
		// typical input plug (inputs are listed first)
	case 0:
		properties->name				= "LEFT";
		properties->variable_address	= &input1_buffer;
		properties->direction			= DR_IN;
		properties->datatype			= DT_FSAMPLE;
		properties->default_value		= "0";
		break;
	case 1:
		properties->name				= "RIGHT";
		properties->variable_address	= &input2_buffer;
		properties->direction			= DR_IN;
		properties->datatype			= DT_FSAMPLE;
		properties->default_value		= "0";
		break;
	case 2:
		properties->name				= "Freq(KHz)";
		properties->variable_address	= &input3_buffer;
		properties->direction			= DR_IN;
		properties->datatype			= DT_FSAMPLE;
		properties->default_value		= "0.440";
		break;
		// typical output plug
	case 3:
		properties->name				= "Res";
		properties->variable_address	= &input4_buffer;
		properties->direction			= DR_IN;
		properties->datatype			= DT_FSAMPLE;
		properties->default_value		= "0";
		break;
	case 4:
		properties->name				= "Limit";
		properties->variable_address	= &input5_buffer;
		properties->direction			= DR_IN;
		properties->datatype			= DT_FSAMPLE;
		properties->default_value		= "5";
		break;
	case 5:
		properties->name				= "LEFT";
		properties->variable_address	= &output1_buffer;
		properties->direction			= DR_OUT;
		properties->datatype			= DT_FSAMPLE;
		break;
	case 6:
		properties->name				= "RIGHT";
		properties->variable_address	= &output2_buffer;
		properties->direction			= DR_OUT;
		properties->datatype			= DT_FSAMPLE;
		break;
	case 7:
		properties->name				= "MONO/STEREO";
		properties->variable_address	= &MNST;
		properties->datatype_extra      = "MONO=1,STEREO=2";
		properties->default_value       = "1";
		properties->direction			= DR_IN;
		properties->datatype			= DT_ENUM;
		break;
	case 8:
		properties->name				= "MODE";
		properties->variable_address	= &MODE;
		properties->datatype_extra      = "LP24=1,HP24=2,BP24=3,BR24=4,SVF LP12=5";
		properties->default_value       = "1";
		properties->direction			= DR_IN;
		properties->datatype			= DT_ENUM;
		break;
	case 9:
		properties->name				= "F";
		properties->variable_address	= &o3_buffer;
		properties->direction			= DR_OUT;
		properties->datatype			= DT_FSAMPLE;
		break;
    case 10:
		properties->name				= "FB";
		properties->variable_address	= &o4_buffer;
		properties->direction			= DR_OUT;
		properties->datatype			= DT_FSAMPLE;
		break;
	case 11:
		properties->name				= "zzz";
		properties->variable_address	= &input6_buffer;
		properties->direction			= DR_IN;
		properties->datatype			= DT_FSAMPLE;
		properties->default_value		= "5";
		break;
		default:
		return false; // host will ask for plugs 0,1,2,3 etc. return false to signal when done
	};

	return true;
}

// An input plug has changed value

void Module::OnPlugStateChange(SEPin *pin)
{
/*
    if ( pin->getPinID() == 1 ) // Freq has changed!
    {
        float *in2;
        FREQ = (*in2 * 20000) * NI;
        if( FREQ >= 1 ) { FREQ = 1; }
        else if( FREQ <= 0.000090702 ) { FREQ = 0.000090702; }
        // original 1.16
        F = FREQ * 1.16;
        FB = RES * (1.0 - 0.15 * F * F);
    }
    if ( pin->getPinID() == 2 ) // Res has changed!
    {
        float *in3;
        RES = *in3 * 2.5;
        if( RES >= 2.5 ) { RES = 2.5; }
    }
*/
//	float test = getPin(PN_INPUT2)->getValue();
//	int test2 = SampleClock();
    if ( pin->getPinID() == 7 ) // MONO/STEREO has changed!
    {
        if      (MNST == 1) { SET_PROCESS_FUNC(Module::sub_MONO); }
        else if (MNST == 2) { SET_PROCESS_FUNC(Module::sub_STEREO); }
    }
    if ( pin->getPinID() == 11 ) // RESET has changed!
    {
        if (RSTx <= 0 && getPin(11)->getValue() > 0)
        {
            x0 = x1 = x2 = x3 = x4 = 0;
            v0 = v1 = v2 = v3 = v4 = 0;
            y1 = y2 = y3 = y4 = 0;
            z1 = z2 = z3 = z4 = 0;
        }
        RSTx = getPin(11)->getValue();
    }
	// query the 'state of the input plugs...
	//     ST_RUN     = Normal Streaming Audio        (e.g. from an oscillator)
	//     ST_STATIC  = Fixed, unchanging input value (e.g. a slider at rest)
	state_type in_stat1 = getPin(PN_INPUT1)->getStatus();
	state_type in_stat2 = getPin(PN_INPUT2)->getStatus();

	// we need to pass on the state of this module's output signal
	// it depends on the inputs...
	state_type out_stat = in_stat1;
	if( in_stat2 > out_stat)
		out_stat = in_stat2;

	// if user has set either input to zero, we can tell downstream modules that the audio has stopped
/*
	if( in_stat1 < ST_RUN && getPin(PN_INPUT1)->getValue() == 0.f )
	{
		out_stat = ST_STATIC;
	}

	if( in_stat2 < ST_RUN && getPin(PN_INPUT2)->getValue() == 0.f )
	{
		out_stat = ST_STATIC;
	}
*/
	// 'transmit' this modules new output status to next module 'downstream'
	getPin(PN_OUTPUT1)->TransmitStatusChange( SampleClock(), ST_RUN);
    getPin(PN_OUTPUT2)->TransmitStatusChange( SampleClock(), ST_RUN);
    getPin(9)->TransmitStatusChange( SampleClock(), ST_RUN);
	getPin(10)->TransmitStatusChange( SampleClock(), ST_RUN);
	// setup up 'sleep mode' or not
/*	if( out_stat < ST_RUN )
	{
		static_count = getBlockSize();
		SET_PROCESS_FUNC(Module::sub_process_static);
	}
	else
	{
		SET_PROCESS_FUNC(Module::sub_MONO);
	}
*/
}