ReverbSC: Initial implementation (#3202)
* ReverbSC - Plugin. lmplementation of the Sean Costello reverb algorithm
This commit is contained in:
committed by
Oskar Wallgren
parent
de2e164aae
commit
0cb6c72e1d
@@ -66,6 +66,7 @@ IF("${PLUGIN_LIST}" STREQUAL "")
|
||||
patman
|
||||
peak_controller_effect
|
||||
GigPlayer
|
||||
ReverbSC
|
||||
sfxr
|
||||
sid
|
||||
SpectrumAnalyzer
|
||||
|
||||
24
plugins/ReverbSC/CMakeLists.txt
Normal file
24
plugins/ReverbSC/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
# Enable C++11 for CXXFLAGS only
|
||||
# This is needed since this plugin uses C. Otherwise Travis fails
|
||||
REMOVE_DEFINITIONS(-std=c++0x)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
|
||||
BUILD_PLUGIN(
|
||||
reverbsc
|
||||
ReverbSC.cpp
|
||||
ReverbSCControls.cpp
|
||||
ReverbSCControlDialog.cpp
|
||||
base.c
|
||||
revsc.c
|
||||
dcblock.c
|
||||
MOCFILES
|
||||
ReverbSC.h
|
||||
ReverbSCControls.h
|
||||
ReverbSCControlDialog.h
|
||||
base.h
|
||||
revsc.h
|
||||
dcblock.h
|
||||
EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png"
|
||||
)
|
||||
141
plugins/ReverbSC/ReverbSC.cpp
Normal file
141
plugins/ReverbSC/ReverbSC.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* ReverbSC.cpp - A native reverb based on an algorithm by Sean Costello
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "ReverbSC.h"
|
||||
|
||||
#include "embed.cpp"
|
||||
|
||||
#define DB2LIN(X) pow(10, X / 20.0f);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
Plugin::Descriptor PLUGIN_EXPORT reverbsc_plugin_descriptor =
|
||||
{
|
||||
STRINGIFY( PLUGIN_NAME ),
|
||||
"ReverbSC",
|
||||
QT_TRANSLATE_NOOP( "pluginBrowser", "Reverb algorithm by Sean Costello" ),
|
||||
"Paul Batchelor",
|
||||
0x0123,
|
||||
Plugin::Effect,
|
||||
new PluginPixmapLoader( "logo" ),
|
||||
NULL,
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
ReverbSCEffect::ReverbSCEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ) :
|
||||
Effect( &reverbsc_plugin_descriptor, parent, key ),
|
||||
m_reverbSCControls( this )
|
||||
{
|
||||
sp_create(&sp);
|
||||
sp->sr = Engine::mixer()->processingSampleRate();
|
||||
|
||||
sp_revsc_create(&revsc);
|
||||
sp_revsc_init(sp, revsc);
|
||||
|
||||
sp_dcblock_create(&dcblk[0]);
|
||||
sp_dcblock_create(&dcblk[1]);
|
||||
|
||||
sp_dcblock_init(sp, dcblk[0]);
|
||||
sp_dcblock_init(sp, dcblk[1]);
|
||||
}
|
||||
|
||||
ReverbSCEffect::~ReverbSCEffect()
|
||||
{
|
||||
sp_revsc_destroy(&revsc);
|
||||
sp_dcblock_destroy(&dcblk[0]);
|
||||
sp_dcblock_destroy(&dcblk[1]);
|
||||
sp_destroy(&sp);
|
||||
}
|
||||
|
||||
bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
double outSum = 0.0;
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
|
||||
SPFLOAT tmpL, tmpR;
|
||||
SPFLOAT dcblkL, dcblkR;
|
||||
|
||||
ValueBuffer * inGainBuf = m_reverbSCControls.m_inputGainModel.valueBuffer();
|
||||
ValueBuffer * sizeBuf = m_reverbSCControls.m_sizeModel.valueBuffer();
|
||||
ValueBuffer * colorBuf = m_reverbSCControls.m_colorModel.valueBuffer();
|
||||
ValueBuffer * outGainBuf = m_reverbSCControls.m_outputGainModel.valueBuffer();
|
||||
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
{
|
||||
sample_t s[2] = { buf[f][0], buf[f][1] };
|
||||
|
||||
const SPFLOAT inGain = (SPFLOAT)DB2LIN((inGainBuf ?
|
||||
inGainBuf->values()[f]
|
||||
: m_reverbSCControls.m_inputGainModel.value()));
|
||||
const SPFLOAT outGain = (SPFLOAT)DB2LIN((outGainBuf ?
|
||||
outGainBuf->values()[f]
|
||||
: m_reverbSCControls.m_outputGainModel.value()));
|
||||
|
||||
s[0] *= inGain;
|
||||
s[1] *= inGain;
|
||||
revsc->feedback = (SPFLOAT)(sizeBuf ?
|
||||
sizeBuf->values()[f]
|
||||
: m_reverbSCControls.m_sizeModel.value());
|
||||
|
||||
revsc->lpfreq = (SPFLOAT)(colorBuf ?
|
||||
colorBuf->values()[f]
|
||||
: m_reverbSCControls.m_colorModel.value());
|
||||
|
||||
|
||||
sp_revsc_compute(sp, revsc, &s[0], &s[1], &tmpL, &tmpR);
|
||||
sp_dcblock_compute(sp, dcblk[0], &tmpL, &dcblkL);
|
||||
sp_dcblock_compute(sp, dcblk[1], &tmpR, &dcblkR);
|
||||
buf[f][0] = d * buf[f][0] + w * dcblkL * outGain;
|
||||
buf[f][1] = d * buf[f][1] + w * dcblkR * outGain;
|
||||
|
||||
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
|
||||
}
|
||||
|
||||
|
||||
checkGate( outSum / frames );
|
||||
|
||||
return isRunning();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// necessary for getting instance out of shared lib
|
||||
Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data )
|
||||
{
|
||||
return new ReverbSCEffect(
|
||||
parent,
|
||||
static_cast<const Plugin::Descriptor::SubPluginFeatures::Key*>(data)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
60
plugins/ReverbSC/ReverbSC.h
Normal file
60
plugins/ReverbSC/ReverbSC.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* RerverbSC.h - Reverb algorithm by Sean Costello
|
||||
*
|
||||
* Copyright (c) 2017 Paul Batchelor
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef REVERBSC_H
|
||||
#define REVERBSC_H
|
||||
|
||||
#include "Effect.h"
|
||||
#include "ReverbSCControls.h"
|
||||
#include "ValueBuffer.h"
|
||||
|
||||
extern "C" {
|
||||
#include "base.h"
|
||||
#include "revsc.h"
|
||||
#include "dcblock.h"
|
||||
}
|
||||
|
||||
class ReverbSCEffect : public Effect
|
||||
{
|
||||
public:
|
||||
ReverbSCEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
|
||||
virtual ~ReverbSCEffect();
|
||||
virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames );
|
||||
|
||||
virtual EffectControls* controls()
|
||||
{
|
||||
return &m_reverbSCControls;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
ReverbSCControls m_reverbSCControls;
|
||||
sp_data *sp;
|
||||
sp_revsc *revsc;
|
||||
sp_dcblock *dcblk[2];
|
||||
friend class ReverbSCControls;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
63
plugins/ReverbSC/ReverbSCControlDialog.cpp
Normal file
63
plugins/ReverbSC/ReverbSCControlDialog.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* ReverbSCControlDialog.cpp - control dialog for ReverbSC
|
||||
*
|
||||
* Copyright (c) 2017 Paul Batchelor
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QLayout>
|
||||
|
||||
#include "ReverbSCControlDialog.h"
|
||||
#include "ReverbSCControls.h"
|
||||
#include "embed.h"
|
||||
|
||||
ReverbSCControlDialog::ReverbSCControlDialog( ReverbSCControls* controls ) :
|
||||
EffectControlDialog( controls )
|
||||
{
|
||||
setAutoFillBackground( true );
|
||||
QPalette pal;
|
||||
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
|
||||
setPalette( pal );
|
||||
setFixedSize( 185, 55 );
|
||||
|
||||
Knob * inputGainKnob = new Knob( knobBright_26, this);
|
||||
inputGainKnob -> move( 16, 10 );
|
||||
inputGainKnob->setModel( &controls->m_inputGainModel );
|
||||
inputGainKnob->setLabel( tr( "Input" ) );
|
||||
inputGainKnob->setHintText( tr( "Input Gain:" ) , "dB" );
|
||||
|
||||
Knob * sizeKnob = new Knob( knobBright_26, this);
|
||||
sizeKnob -> move( 57, 10 );
|
||||
sizeKnob->setModel( &controls->m_sizeModel );
|
||||
sizeKnob->setLabel( tr( "Size" ) );
|
||||
sizeKnob->setHintText( tr( "Size:" ) , "" );
|
||||
|
||||
Knob * colorKnob = new Knob( knobBright_26, this);
|
||||
colorKnob -> move( 98, 10 );
|
||||
colorKnob->setModel( &controls->m_colorModel );
|
||||
colorKnob->setLabel( tr( "Color" ) );
|
||||
colorKnob->setHintText( tr( "Color:" ) , "" );
|
||||
|
||||
Knob * outputGainKnob = new Knob( knobBright_26, this);
|
||||
outputGainKnob -> move( 139, 10 );
|
||||
outputGainKnob->setModel( &controls->m_outputGainModel );
|
||||
outputGainKnob->setLabel( tr( "Output" ) );
|
||||
outputGainKnob->setHintText( tr( "Output Gain:" ) , "dB" );
|
||||
}
|
||||
45
plugins/ReverbSC/ReverbSCControlDialog.h
Normal file
45
plugins/ReverbSC/ReverbSCControlDialog.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* ReverbSCControlDialog.h - control dialog for ReverbSC
|
||||
*
|
||||
* Copyright (c) 2017 Paul Batchelor
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef REVERBSC_CONTROL_DIALOG_H
|
||||
#define REVERBSC_CONTROL_DIALOG_H
|
||||
|
||||
#include "EffectControlDialog.h"
|
||||
|
||||
|
||||
class ReverbSCControls;
|
||||
|
||||
|
||||
class ReverbSCControlDialog : public EffectControlDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ReverbSCControlDialog( ReverbSCControls* controls );
|
||||
virtual ~ReverbSCControlDialog()
|
||||
{
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
62
plugins/ReverbSC/ReverbSCControls.cpp
Normal file
62
plugins/ReverbSC/ReverbSCControls.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* ReverbSCControls.cpp - controls for ReverbSC
|
||||
*
|
||||
* Copyright (c) 2017 Paul Batchelor
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <QDomElement>
|
||||
|
||||
#include "ReverbSCControls.h"
|
||||
#include "ReverbSC.h"
|
||||
#include "Engine.h"
|
||||
#include "Song.h"
|
||||
|
||||
ReverbSCControls::ReverbSCControls( ReverbSCEffect* effect ) :
|
||||
EffectControls( effect ),
|
||||
m_effect( effect ),
|
||||
m_inputGainModel( 0.0f, -60.0f, 15, 0.1f, this, tr( "Input Gain" ) ),
|
||||
m_sizeModel( 0.89f, 0.0f, 1.0f, 0.01f, this, tr( "Size" ) ),
|
||||
m_colorModel( 10000.0f, 100.0f, 15000.0f, 0.1f, this, tr( "Color" ) ),
|
||||
m_outputGainModel( 0.0f, -60.0f, 15, 0.1f, this, tr( "Output Gain" ) )
|
||||
{
|
||||
}
|
||||
|
||||
void ReverbSCControls::changeControl()
|
||||
{
|
||||
}
|
||||
|
||||
void ReverbSCControls::loadSettings( const QDomElement& _this )
|
||||
{
|
||||
m_inputGainModel.loadSettings( _this, "input_gain" );
|
||||
m_sizeModel.loadSettings( _this, "size" );
|
||||
m_colorModel.loadSettings( _this, "color" );
|
||||
m_outputGainModel.loadSettings( _this, "output_gain" );
|
||||
}
|
||||
|
||||
void ReverbSCControls::saveSettings( QDomDocument& doc, QDomElement& _this )
|
||||
{
|
||||
m_inputGainModel.saveSettings( doc, _this, "input_gain" );
|
||||
m_sizeModel.saveSettings( doc, _this, "size" );
|
||||
m_colorModel.saveSettings( doc, _this, "color" );
|
||||
m_outputGainModel.saveSettings( doc, _this, "output_gain" );
|
||||
}
|
||||
|
||||
77
plugins/ReverbSC/ReverbSCControls.h
Normal file
77
plugins/ReverbSC/ReverbSCControls.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* ReverbSCControls.h
|
||||
*
|
||||
* Copyright (c) 2017 Paul Batchelor
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef REVERBSC_CONTROLS_H
|
||||
#define REVERBSC_CONTROLS_H
|
||||
|
||||
#include "EffectControls.h"
|
||||
#include "ReverbSCControlDialog.h"
|
||||
#include "Knob.h"
|
||||
|
||||
|
||||
class ReverbSCEffect;
|
||||
|
||||
class ReverbSCControls : public EffectControls
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ReverbSCControls( ReverbSCEffect* effect );
|
||||
virtual ~ReverbSCControls()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
inline virtual QString nodeName() const
|
||||
{
|
||||
return "ReverbSCControls";
|
||||
}
|
||||
|
||||
virtual int controlCount()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
virtual EffectControlDialog* createView()
|
||||
{
|
||||
return new ReverbSCControlDialog( this );
|
||||
}
|
||||
|
||||
|
||||
private slots:
|
||||
void changeControl();
|
||||
|
||||
private:
|
||||
ReverbSCEffect* m_effect;
|
||||
FloatModel m_inputGainModel;
|
||||
FloatModel m_sizeModel;
|
||||
FloatModel m_colorModel;
|
||||
FloatModel m_outputGainModel;
|
||||
|
||||
friend class ReverbSCControlDialog;
|
||||
friend class ReverbSCEffect;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
BIN
plugins/ReverbSC/artwork.png
Normal file
BIN
plugins/ReverbSC/artwork.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 262 B |
214
plugins/ReverbSC/base.c
Normal file
214
plugins/ReverbSC/base.c
Normal file
@@ -0,0 +1,214 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "base.h"
|
||||
|
||||
int sp_create(sp_data **spp)
|
||||
{
|
||||
*spp = (sp_data *) malloc(sizeof(sp_data));
|
||||
sp_data *sp = *spp;
|
||||
sprintf(sp->filename, "test.wav");
|
||||
sp->nchan = 1;
|
||||
SPFLOAT *out = malloc(sizeof(SPFLOAT) * sp->nchan);
|
||||
*out = 0;
|
||||
sp->out = out;
|
||||
sp->sr = 44100;
|
||||
sp->len = 5 * sp->sr;
|
||||
sp->pos = 0;
|
||||
sp->rand = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sp_createn(sp_data **spp, int nchan)
|
||||
{
|
||||
*spp = (sp_data *) malloc(sizeof(sp_data));
|
||||
sp_data *sp = *spp;
|
||||
sprintf(sp->filename, "test.wav");
|
||||
sp->nchan = nchan;
|
||||
SPFLOAT *out = malloc(sizeof(SPFLOAT) * sp->nchan);
|
||||
*out = 0;
|
||||
sp->out = out;
|
||||
sp->sr = 44100;
|
||||
sp->len = 5 * sp->sr;
|
||||
sp->pos = 0;
|
||||
sp->rand = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sp_destroy(sp_data **spp)
|
||||
{
|
||||
sp_data *sp = *spp;
|
||||
free(sp->out);
|
||||
free(*spp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NO_LIBSNDFILE
|
||||
|
||||
int sp_process(sp_data *sp, void *ud, void (*callback)(sp_data *, void *))
|
||||
{
|
||||
SNDFILE *sf[sp->nchan];
|
||||
char tmp[140];
|
||||
SF_INFO info;
|
||||
memset(&info, 0, sizeof(SF_INFO));
|
||||
SPFLOAT buf[sp->nchan][SP_BUFSIZE];
|
||||
info.samplerate = sp->sr;
|
||||
info.channels = 1;
|
||||
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
|
||||
int numsamps, i, chan;
|
||||
if(sp->nchan == 1) {
|
||||
sf[0] = sf_open(sp->filename, SFM_WRITE, &info);
|
||||
} else {
|
||||
for(chan = 0; chan < sp->nchan; chan++) {
|
||||
sprintf(tmp, "%02d_%s", chan, sp->filename);
|
||||
sf[chan] = sf_open(tmp, SFM_WRITE, &info);
|
||||
}
|
||||
}
|
||||
|
||||
while(sp->len > 0){
|
||||
if(sp->len < SP_BUFSIZE) {
|
||||
numsamps = sp->len;
|
||||
}else{
|
||||
numsamps = SP_BUFSIZE;
|
||||
}
|
||||
for(i = 0; i < numsamps; i++){
|
||||
callback(sp, ud);
|
||||
for(chan = 0; chan < sp->nchan; chan++) {
|
||||
buf[chan][i] = sp->out[chan];
|
||||
}
|
||||
sp->pos++;
|
||||
}
|
||||
for(chan = 0; chan < sp->nchan; chan++) {
|
||||
#ifdef USE_DOUBLE
|
||||
sf_write_double(sf[chan], buf[chan], numsamps);
|
||||
#else
|
||||
sf_write_float(sf[chan], buf[chan], numsamps);
|
||||
#endif
|
||||
}
|
||||
sp->len -= numsamps;
|
||||
}
|
||||
for(i = 0; i < sp->nchan; i++) {
|
||||
sf_close(sf[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int sp_process_raw(sp_data *sp, void *ud, void (*callback)(sp_data *, void *))
|
||||
{
|
||||
int chan;
|
||||
if(sp->len == 0) {
|
||||
while(1) {
|
||||
callback(sp, ud);
|
||||
for (chan = 0; chan < sp->nchan; chan++) {
|
||||
fwrite(&sp->out[chan], sizeof(SPFLOAT), 1, stdout);
|
||||
}
|
||||
sp->len--;
|
||||
}
|
||||
} else {
|
||||
while(sp->len > 0) {
|
||||
callback(sp, ud);
|
||||
for (chan = 0; chan < sp->nchan; chan++) {
|
||||
fwrite(&sp->out[chan], sizeof(SPFLOAT), 1, stdout);
|
||||
}
|
||||
sp->len--;
|
||||
sp->pos++;
|
||||
}
|
||||
}
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
#ifdef USE_SPA
|
||||
int sp_process_spa(sp_data *sp, void *ud, void (*callback)(sp_data *, void *))
|
||||
{
|
||||
sp_audio spa;
|
||||
if(spa_open(sp, &spa, sp->filename, SPA_WRITE) == SP_NOT_OK) {
|
||||
fprintf(stderr, "Error: could not open file %s.\n", sp->filename);
|
||||
}
|
||||
while(sp->len > 0) {
|
||||
callback(sp, ud);
|
||||
spa_write_buf(sp, &spa, sp->out, sp->nchan);
|
||||
sp->len--;
|
||||
sp->pos++;
|
||||
}
|
||||
spa_close(&spa);
|
||||
return SP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
int sp_process_plot(sp_data *sp, void *ud, void (*callback)(sp_data *, void *))
|
||||
{
|
||||
int chan;
|
||||
fprintf(stdout, "sp_out = [ ... \n");
|
||||
while(sp->len > 0) {
|
||||
callback(sp, ud);
|
||||
for (chan = 0; chan < sp->nchan; chan++) {
|
||||
/* fwrite(&sp->out[chan], sizeof(SPFLOAT), 1, stdout); */
|
||||
fprintf(stdout, "%g ", sp->out[chan]);
|
||||
}
|
||||
fprintf(stdout, "; ...\n");
|
||||
sp->len--;
|
||||
sp->pos++;
|
||||
}
|
||||
fprintf(stdout, "];\n");
|
||||
|
||||
fprintf(stdout, "plot(sp_out);\n");
|
||||
fprintf(stdout, "title('Plot generated by Soundpipe');\n");
|
||||
fprintf(stdout, "xlabel('Time (samples)');\n");
|
||||
fprintf(stdout, "ylabel('Amplitude');\n");
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
int sp_auxdata_alloc(sp_auxdata *aux, size_t size)
|
||||
{
|
||||
aux->ptr = malloc(size);
|
||||
aux->size = size;
|
||||
memset(aux->ptr, 0, size);
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
int sp_auxdata_free(sp_auxdata *aux)
|
||||
{
|
||||
free(aux->ptr);
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
|
||||
SPFLOAT sp_midi2cps(SPFLOAT nn)
|
||||
{
|
||||
return pow(2, (nn - 69.0) / 12.0) * 440.0;
|
||||
}
|
||||
|
||||
int sp_set(sp_param *p, SPFLOAT val) {
|
||||
p->state = 1;
|
||||
p->val = val;
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
int sp_out(sp_data *sp, uint32_t chan, SPFLOAT val)
|
||||
{
|
||||
if(chan > sp->nchan - 1) {
|
||||
fprintf(stderr, "sp_out: Invalid channel\n");
|
||||
return SP_NOT_OK;
|
||||
}
|
||||
sp->out[chan] = val;
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
uint32_t sp_rand(sp_data *sp)
|
||||
{
|
||||
uint32_t val = (1103515245 * sp->rand + 12345) % SP_RANDMAX;
|
||||
sp->rand = val;
|
||||
return val;
|
||||
}
|
||||
*/
|
||||
|
||||
void sp_srand(sp_data *sp, uint32_t val)
|
||||
{
|
||||
sp->rand = val;
|
||||
}
|
||||
|
||||
|
||||
84
plugins/ReverbSC/base.h
Normal file
84
plugins/ReverbSC/base.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NO_LIBSNDFILE
|
||||
|
||||
#ifndef NO_LIBSNDFILE
|
||||
#include "sndfile.h"
|
||||
#endif
|
||||
|
||||
#define SP_BUFSIZE 4096
|
||||
#ifndef SPFLOAT
|
||||
#define SPFLOAT float
|
||||
#endif
|
||||
#define SP_OK 1
|
||||
#define SP_NOT_OK 0
|
||||
|
||||
#define SP_RANDMAX 2147483648
|
||||
|
||||
typedef unsigned long sp_frame;
|
||||
|
||||
typedef struct sp_auxdata {
|
||||
size_t size;
|
||||
void *ptr;
|
||||
} sp_auxdata;
|
||||
|
||||
typedef struct sp_data {
|
||||
SPFLOAT *out;
|
||||
int sr;
|
||||
int nchan;
|
||||
unsigned long len;
|
||||
unsigned long pos;
|
||||
char filename[200];
|
||||
uint32_t rand;
|
||||
} sp_data;
|
||||
|
||||
typedef struct {
|
||||
char state;
|
||||
SPFLOAT val;
|
||||
} sp_param;
|
||||
|
||||
int sp_auxdata_alloc(sp_auxdata *aux, size_t size);
|
||||
int sp_auxdata_free(sp_auxdata *aux);
|
||||
|
||||
int sp_create(sp_data **spp);
|
||||
int sp_createn(sp_data **spp, int nchan);
|
||||
|
||||
int sp_destroy(sp_data **spp);
|
||||
int sp_process(sp_data *sp, void *ud, void (*callback)(sp_data *, void *));
|
||||
int sp_process_raw(sp_data *sp, void *ud, void (*callback)(sp_data *, void *));
|
||||
int sp_process_plot(sp_data *sp, void *ud, void (*callback)(sp_data *, void *));
|
||||
int sp_process_spa(sp_data *sp, void *ud, void (*callback)(sp_data *, void *));
|
||||
|
||||
SPFLOAT sp_midi2cps(SPFLOAT nn);
|
||||
|
||||
int sp_set(sp_param *p, SPFLOAT val);
|
||||
|
||||
int sp_out(sp_data *sp, uint32_t chan, SPFLOAT val);
|
||||
|
||||
uint32_t sp_rand(sp_data *sp);
|
||||
void sp_srand(sp_data *sp, uint32_t val);
|
||||
|
||||
|
||||
typedef struct {
|
||||
SPFLOAT *utbl;
|
||||
int16_t *BRLow;
|
||||
int16_t *BRLowCpx;
|
||||
} sp_fft;
|
||||
|
||||
void sp_fft_create(sp_fft **fft);
|
||||
void sp_fft_init(sp_fft *fft, int M);
|
||||
void sp_fftr(sp_fft *fft, SPFLOAT *buf, int FFTsize);
|
||||
void sp_fft_cpx(sp_fft *fft, SPFLOAT *buf, int FFTsize);
|
||||
void sp_ifftr(sp_fft *fft, SPFLOAT *buf, int FFTsize);
|
||||
void sp_fft_destroy(sp_fft *fft);
|
||||
#ifndef kiss_fft_scalar
|
||||
#define kiss_fft_scalar SPFLOAT
|
||||
#endif
|
||||
typedef struct {
|
||||
kiss_fft_scalar r;
|
||||
kiss_fft_scalar i;
|
||||
}kiss_fft_cpx;
|
||||
|
||||
typedef struct kiss_fft_state* kiss_fft_cfg;
|
||||
typedef struct kiss_fftr_state* kiss_fftr_cfg;
|
||||
52
plugins/ReverbSC/dcblock.c
Normal file
52
plugins/ReverbSC/dcblock.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* DCblock
|
||||
*
|
||||
* This code has been extracted from the Csound opcode "dcblock".
|
||||
* It has been modified to work as a Soundpipe module.
|
||||
*
|
||||
* Original Author(s): Perry R. Cook
|
||||
* Year: 1995
|
||||
* Location: Opcodes/biquad.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "base.h"
|
||||
#include "dcblock.h"
|
||||
|
||||
int sp_dcblock_create(sp_dcblock **p)
|
||||
{
|
||||
*p = malloc(sizeof(sp_dcblock));
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
int sp_dcblock_destroy(sp_dcblock **p)
|
||||
{
|
||||
free(*p);
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
int sp_dcblock_init(sp_data *sp, sp_dcblock *p)
|
||||
{
|
||||
p->outputs = 0.0;
|
||||
p->inputs = 0.0;
|
||||
p->gain = 0.99;
|
||||
if (p->gain == 0.0 || p->gain>=1.0 || p->gain<=-1.0)
|
||||
p->gain = 0.99;
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
int sp_dcblock_compute(sp_data *sp, sp_dcblock *p, SPFLOAT *in, SPFLOAT *out)
|
||||
{
|
||||
SPFLOAT gain = p->gain;
|
||||
SPFLOAT outputs = p->outputs;
|
||||
SPFLOAT inputs = p->inputs;
|
||||
|
||||
SPFLOAT sample = *in;
|
||||
outputs = sample - inputs + (gain * outputs);
|
||||
inputs = sample;
|
||||
*out = outputs;
|
||||
p->outputs = outputs;
|
||||
p->inputs = inputs;
|
||||
return SP_OK;
|
||||
}
|
||||
11
plugins/ReverbSC/dcblock.h
Normal file
11
plugins/ReverbSC/dcblock.h
Normal file
@@ -0,0 +1,11 @@
|
||||
typedef struct {
|
||||
SPFLOAT gg;
|
||||
SPFLOAT outputs;
|
||||
SPFLOAT inputs;
|
||||
SPFLOAT gain;
|
||||
} sp_dcblock;
|
||||
|
||||
int sp_dcblock_create(sp_dcblock **p);
|
||||
int sp_dcblock_destroy(sp_dcblock **p);
|
||||
int sp_dcblock_init(sp_data *sp, sp_dcblock *p);
|
||||
int sp_dcblock_compute(sp_data *sp, sp_dcblock *p, SPFLOAT *in, SPFLOAT *out);
|
||||
BIN
plugins/ReverbSC/logo.png
Normal file
BIN
plugins/ReverbSC/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 774 B |
276
plugins/ReverbSC/revsc.c
Normal file
276
plugins/ReverbSC/revsc.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* RevSC
|
||||
*
|
||||
* This code has been extracted from the Csound opcode "reverbsc".
|
||||
* It has been modified to work as a Soundpipe module.
|
||||
*
|
||||
* Original Author(s): Sean Costello, Istvan Varga
|
||||
* Year: 1999, 2005
|
||||
* Location: Opcodes/reverbsc.c
|
||||
*
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "base.h"
|
||||
#include "revsc.h"
|
||||
|
||||
#define DEFAULT_SRATE 44100.0
|
||||
#define MIN_SRATE 5000.0
|
||||
#define MAX_SRATE 1000000.0
|
||||
#define MAX_PITCHMOD 20.0
|
||||
#define DELAYPOS_SHIFT 28
|
||||
#define DELAYPOS_SCALE 0x10000000
|
||||
#define DELAYPOS_MASK 0x0FFFFFFF
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#endif
|
||||
|
||||
/* reverbParams[n][0] = delay time (in seconds) */
|
||||
/* reverbParams[n][1] = random variation in delay time (in seconds) */
|
||||
/* reverbParams[n][2] = random variation frequency (in 1/sec) */
|
||||
/* reverbParams[n][3] = random seed (0 - 32767) */
|
||||
|
||||
static const SPFLOAT reverbParams[8][4] = {
|
||||
{ (2473.0 / DEFAULT_SRATE), 0.0010, 3.100, 1966.0 },
|
||||
{ (2767.0 / DEFAULT_SRATE), 0.0011, 3.500, 29491.0 },
|
||||
{ (3217.0 / DEFAULT_SRATE), 0.0017, 1.110, 22937.0 },
|
||||
{ (3557.0 / DEFAULT_SRATE), 0.0006, 3.973, 9830.0 },
|
||||
{ (3907.0 / DEFAULT_SRATE), 0.0010, 2.341, 20643.0 },
|
||||
{ (4127.0 / DEFAULT_SRATE), 0.0011, 1.897, 22937.0 },
|
||||
{ (2143.0 / DEFAULT_SRATE), 0.0017, 0.891, 29491.0 },
|
||||
{ (1933.0 / DEFAULT_SRATE), 0.0006, 3.221, 14417.0 }
|
||||
};
|
||||
|
||||
static int delay_line_max_samples(SPFLOAT sr, SPFLOAT iPitchMod, int n);
|
||||
static int init_delay_line(sp_revsc *p, sp_revsc_dl *lp, int n);
|
||||
static int delay_line_bytes_alloc(SPFLOAT sr, SPFLOAT iPitchMod, int n);
|
||||
static const SPFLOAT outputGain = 0.35;
|
||||
static const SPFLOAT jpScale = 0.25;
|
||||
int sp_revsc_create(sp_revsc **p){
|
||||
*p = malloc(sizeof(sp_revsc));
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
int sp_revsc_init(sp_data *sp, sp_revsc *p)
|
||||
{
|
||||
p->iSampleRate = sp->sr;
|
||||
p->sampleRate = sp->sr;
|
||||
p->feedback = 0.97;
|
||||
p->lpfreq = 10000;
|
||||
p->iPitchMod = 1;
|
||||
p->iSkipInit = 0;
|
||||
p->dampFact = 1.0;
|
||||
p->prv_LPFreq = 0.0;
|
||||
p->initDone = 1;
|
||||
int i, nBytes = 0;
|
||||
for(i = 0; i < 8; i++){
|
||||
nBytes += delay_line_bytes_alloc(sp->sr, 1, i);
|
||||
}
|
||||
sp_auxdata_alloc(&p->aux, nBytes);
|
||||
nBytes = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
p->delayLines[i].buf = (p->aux.ptr) + nBytes;
|
||||
init_delay_line(p, &p->delayLines[i], i);
|
||||
nBytes += delay_line_bytes_alloc(sp->sr, 1, i);
|
||||
}
|
||||
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
|
||||
int sp_revsc_destroy(sp_revsc **p)
|
||||
{
|
||||
sp_revsc *pp = *p;
|
||||
sp_auxdata_free(&pp->aux);
|
||||
free(*p);
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
static int delay_line_max_samples(SPFLOAT sr, SPFLOAT iPitchMod, int n)
|
||||
{
|
||||
SPFLOAT maxDel;
|
||||
|
||||
maxDel = reverbParams[n][0];
|
||||
maxDel += (reverbParams[n][1] * (SPFLOAT) iPitchMod * 1.125);
|
||||
return (int) (maxDel * sr + 16.5);
|
||||
}
|
||||
|
||||
static int delay_line_bytes_alloc(SPFLOAT sr, SPFLOAT iPitchMod, int n)
|
||||
{
|
||||
int nBytes = 0;
|
||||
|
||||
nBytes += (delay_line_max_samples(sr, iPitchMod, n) * (int) sizeof(SPFLOAT));
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
static void next_random_lineseg(sp_revsc *p, sp_revsc_dl *lp, int n)
|
||||
{
|
||||
SPFLOAT prvDel, nxtDel, phs_incVal;
|
||||
|
||||
/* update random seed */
|
||||
if (lp->seedVal < 0)
|
||||
lp->seedVal += 0x10000;
|
||||
lp->seedVal = (lp->seedVal * 15625 + 1) & 0xFFFF;
|
||||
if (lp->seedVal >= 0x8000)
|
||||
lp->seedVal -= 0x10000;
|
||||
/* length of next segment in samples */
|
||||
lp->randLine_cnt = (int) ((p->sampleRate / reverbParams[n][2]) + 0.5);
|
||||
prvDel = (SPFLOAT) lp->writePos;
|
||||
prvDel -= ((SPFLOAT) lp->readPos
|
||||
+ ((SPFLOAT) lp->readPosFrac / (SPFLOAT) DELAYPOS_SCALE));
|
||||
while (prvDel < 0.0)
|
||||
prvDel += lp->bufferSize;
|
||||
prvDel = prvDel / p->sampleRate; /* previous delay time in seconds */
|
||||
nxtDel = (SPFLOAT) lp->seedVal * reverbParams[n][1] / 32768.0;
|
||||
/* next delay time in seconds */
|
||||
nxtDel = reverbParams[n][0] + (nxtDel * (SPFLOAT) p->iPitchMod);
|
||||
/* calculate phase increment per sample */
|
||||
phs_incVal = (prvDel - nxtDel) / (SPFLOAT) lp->randLine_cnt;
|
||||
phs_incVal = phs_incVal * p->sampleRate + 1.0;
|
||||
lp->readPosFrac_inc = (int) (phs_incVal * DELAYPOS_SCALE + 0.5);
|
||||
}
|
||||
|
||||
static int init_delay_line(sp_revsc *p, sp_revsc_dl *lp, int n)
|
||||
{
|
||||
SPFLOAT readPos;
|
||||
/* int i; */
|
||||
|
||||
/* calculate length of delay line */
|
||||
lp->bufferSize = delay_line_max_samples(p->sampleRate, 1, n);
|
||||
lp->dummy = 0;
|
||||
lp->writePos = 0;
|
||||
/* set random seed */
|
||||
lp->seedVal = (int) (reverbParams[n][3] + 0.5);
|
||||
/* set initial delay time */
|
||||
readPos = (SPFLOAT) lp->seedVal * reverbParams[n][1] / 32768;
|
||||
readPos = reverbParams[n][0] + (readPos * (SPFLOAT) p->iPitchMod);
|
||||
readPos = (SPFLOAT) lp->bufferSize - (readPos * p->sampleRate);
|
||||
lp->readPos = (int) readPos;
|
||||
readPos = (readPos - (SPFLOAT) lp->readPos) * (SPFLOAT) DELAYPOS_SCALE;
|
||||
lp->readPosFrac = (int) (readPos + 0.5);
|
||||
/* initialise first random line segment */
|
||||
next_random_lineseg(p, lp, n);
|
||||
/* clear delay line to zero */
|
||||
lp->filterState = 0.0;
|
||||
memset(lp->buf, 0, sizeof(SPFLOAT) * lp->bufferSize);
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
|
||||
int sp_revsc_compute(sp_data *sp, sp_revsc *p, SPFLOAT *in1, SPFLOAT *in2, SPFLOAT *out1, SPFLOAT *out2)
|
||||
{
|
||||
SPFLOAT ainL, ainR, aoutL, aoutR;
|
||||
SPFLOAT vm1, v0, v1, v2, am1, a0, a1, a2, frac;
|
||||
sp_revsc_dl *lp;
|
||||
int readPos;
|
||||
uint32_t n;
|
||||
int bufferSize; /* Local copy */
|
||||
SPFLOAT dampFact = p->dampFact;
|
||||
|
||||
if (p->initDone <= 0) return SP_NOT_OK;
|
||||
|
||||
/* calculate tone filter coefficient if frequency changed */
|
||||
|
||||
if (p->lpfreq != p->prv_LPFreq) {
|
||||
p->prv_LPFreq = p->lpfreq;
|
||||
dampFact = 2.0 - cos(p->prv_LPFreq * (2 * M_PI) / p->sampleRate);
|
||||
dampFact = p->dampFact = dampFact - sqrt(dampFact * dampFact - 1.0);
|
||||
}
|
||||
|
||||
/* calculate "resultant junction pressure" and mix to input signals */
|
||||
|
||||
ainL = aoutL = aoutR = 0.0;
|
||||
for (n = 0; n < 8; n++) {
|
||||
ainL += p->delayLines[n].filterState;
|
||||
}
|
||||
ainL *= jpScale;
|
||||
ainR = ainL + *in2;
|
||||
ainL = ainL + *in1;
|
||||
|
||||
/* loop through all delay lines */
|
||||
|
||||
for (n = 0; n < 8; n++) {
|
||||
lp = &p->delayLines[n];
|
||||
bufferSize = lp->bufferSize;
|
||||
|
||||
/* send input signal and feedback to delay line */
|
||||
|
||||
lp->buf[lp->writePos] = (SPFLOAT) ((n & 1 ? ainR : ainL)
|
||||
- lp->filterState);
|
||||
if (++lp->writePos >= bufferSize) {
|
||||
lp->writePos -= bufferSize;
|
||||
}
|
||||
|
||||
/* read from delay line with cubic interpolation */
|
||||
|
||||
if (lp->readPosFrac >= DELAYPOS_SCALE) {
|
||||
lp->readPos += (lp->readPosFrac >> DELAYPOS_SHIFT);
|
||||
lp->readPosFrac &= DELAYPOS_MASK;
|
||||
}
|
||||
if (lp->readPos >= bufferSize)
|
||||
lp->readPos -= bufferSize;
|
||||
readPos = lp->readPos;
|
||||
frac = (SPFLOAT) lp->readPosFrac * (1.0 / (SPFLOAT) DELAYPOS_SCALE);
|
||||
|
||||
/* calculate interpolation coefficients */
|
||||
|
||||
a2 = frac * frac; a2 -= 1.0; a2 *= (1.0 / 6.0);
|
||||
a1 = frac; a1 += 1.0; a1 *= 0.5; am1 = a1 - 1.0;
|
||||
a0 = 3.0 * a2; a1 -= a0; am1 -= a2; a0 -= frac;
|
||||
|
||||
/* read four samples for interpolation */
|
||||
|
||||
if (readPos > 0 && readPos < (bufferSize - 2)) {
|
||||
vm1 = (SPFLOAT) (lp->buf[readPos - 1]);
|
||||
v0 = (SPFLOAT) (lp->buf[readPos]);
|
||||
v1 = (SPFLOAT) (lp->buf[readPos + 1]);
|
||||
v2 = (SPFLOAT) (lp->buf[readPos + 2]);
|
||||
}
|
||||
else {
|
||||
|
||||
/* at buffer wrap-around, need to check index */
|
||||
|
||||
if (--readPos < 0) readPos += bufferSize;
|
||||
vm1 = (SPFLOAT) lp->buf[readPos];
|
||||
if (++readPos >= bufferSize) readPos -= bufferSize;
|
||||
v0 = (SPFLOAT) lp->buf[readPos];
|
||||
if (++readPos >= bufferSize) readPos -= bufferSize;
|
||||
v1 = (SPFLOAT) lp->buf[readPos];
|
||||
if (++readPos >= bufferSize) readPos -= bufferSize;
|
||||
v2 = (SPFLOAT) lp->buf[readPos];
|
||||
}
|
||||
v0 = (am1 * vm1 + a0 * v0 + a1 * v1 + a2 * v2) * frac + v0;
|
||||
|
||||
/* update buffer read position */
|
||||
|
||||
lp->readPosFrac += lp->readPosFrac_inc;
|
||||
|
||||
/* apply feedback gain and lowpass filter */
|
||||
|
||||
v0 *= (SPFLOAT) p->feedback;
|
||||
v0 = (lp->filterState - v0) * dampFact + v0;
|
||||
lp->filterState = v0;
|
||||
|
||||
/* mix to output */
|
||||
|
||||
if (n & 1) {
|
||||
aoutR += v0;
|
||||
}else{
|
||||
aoutL += v0;
|
||||
}
|
||||
|
||||
/* start next random line segment if current one has reached endpoint */
|
||||
|
||||
if (--(lp->randLine_cnt) <= 0) {
|
||||
next_random_lineseg(p, lp, n);
|
||||
}
|
||||
}
|
||||
/* someday, use aoutR for multimono out */
|
||||
|
||||
*out1 = aoutL * outputGain;
|
||||
*out2 = aoutR * outputGain;
|
||||
return SP_OK;
|
||||
}
|
||||
28
plugins/ReverbSC/revsc.h
Normal file
28
plugins/ReverbSC/revsc.h
Normal file
@@ -0,0 +1,28 @@
|
||||
typedef struct {
|
||||
int writePos;
|
||||
int bufferSize;
|
||||
int readPos;
|
||||
int readPosFrac;
|
||||
int readPosFrac_inc;
|
||||
int dummy;
|
||||
int seedVal;
|
||||
int randLine_cnt;
|
||||
SPFLOAT filterState;
|
||||
SPFLOAT *buf;
|
||||
} sp_revsc_dl;
|
||||
|
||||
typedef struct {
|
||||
SPFLOAT feedback, lpfreq;
|
||||
SPFLOAT iSampleRate, iPitchMod, iSkipInit;
|
||||
SPFLOAT sampleRate;
|
||||
SPFLOAT dampFact;
|
||||
SPFLOAT prv_LPFreq;
|
||||
int initDone;
|
||||
sp_revsc_dl delayLines[8];
|
||||
sp_auxdata aux;
|
||||
} sp_revsc;
|
||||
|
||||
int sp_revsc_create(sp_revsc **p);
|
||||
int sp_revsc_destroy(sp_revsc **p);
|
||||
int sp_revsc_init(sp_data *sp, sp_revsc *p);
|
||||
int sp_revsc_compute(sp_data *sp, sp_revsc *p, SPFLOAT *in1, SPFLOAT *in2, SPFLOAT *out1, SPFLOAT *out2);
|
||||
Reference in New Issue
Block a user