mirror of
https://github.com/thestk/stk
synced 2026-01-11 20:11:52 +00:00
Added new Recorder class, fixed bug in StifKarp.
This commit is contained in:
167
include/Recorder.h
Normal file
167
include/Recorder.h
Normal file
@@ -0,0 +1,167 @@
|
||||
#ifndef STK_RECORDER_H
|
||||
#define STK_RECORDER_H
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "Iir.h"
|
||||
#include "DelayL.h"
|
||||
#include "Noise.h"
|
||||
#include "SineWave.h"
|
||||
#include "ADSR.h"
|
||||
|
||||
namespace stk {
|
||||
|
||||
/***************************************************/
|
||||
/*! \class Recorder
|
||||
\brief A recorder / flute physical model.
|
||||
|
||||
This class implements a physical model of a recorder /
|
||||
flute instrument, based on the paper "Sound production
|
||||
in recorderlike instruments. II. A simulation model."
|
||||
by M.P. Verge, A. Hirschberg and R. Causse, Journal of
|
||||
the Acoustical Society of America, 1997.
|
||||
|
||||
Control Change Numbers:
|
||||
- Softness = 2
|
||||
- Noise Gain = 4
|
||||
- Noise Cutoff = 16
|
||||
- Vibrato Frequency = 11
|
||||
- Vibrato Gain = 1
|
||||
- Breath Pressure = 128
|
||||
|
||||
by Mathias Bredholt, McGill University.
|
||||
Formatted for STK by Gary Scavone, 2019.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
class Recorder : public Instrmnt
|
||||
{
|
||||
public:
|
||||
//! Class constructor.
|
||||
Recorder( void );
|
||||
|
||||
//! Class destructor.
|
||||
~Recorder( void );
|
||||
|
||||
//! Reset and clear all internal state.
|
||||
void clear( void );
|
||||
|
||||
//! Set instrument parameters for a particular frequency.
|
||||
void setFrequency( StkFloat val );
|
||||
|
||||
//! Apply breath velocity to instrument with given amplitude and rate of increase.
|
||||
void startBlowing( StkFloat amplitude, StkFloat rate );
|
||||
|
||||
//! Decrease breath velocity with given rate of decrease.
|
||||
void stopBlowing( StkFloat rate );
|
||||
|
||||
//! Start a note with the given frequency and amplitude.
|
||||
void noteOn( StkFloat frequency, StkFloat amplitude );
|
||||
|
||||
//! Stop a note with the given amplitude (speed of decay).
|
||||
void noteOff( StkFloat amplitude );
|
||||
|
||||
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
|
||||
void controlChange( int number, StkFloat value );
|
||||
|
||||
//! Compute and return one output sample.
|
||||
StkFloat tick( unsigned int channel = 0 );
|
||||
|
||||
//! Fill a channel of the StkFrames object with computed outputs.
|
||||
/*!
|
||||
The \c channel argument must be less than the number of
|
||||
channels in the StkFrames argument (the first channel is specified
|
||||
by 0). However, range checking is only performed if _STK_DEBUG_
|
||||
is defined during compilation, in which case an out-of-range value
|
||||
will trigger an StkError exception.
|
||||
*/
|
||||
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
|
||||
|
||||
void setBlowPressure( StkFloat val );
|
||||
void setVibratoGain( StkFloat val );
|
||||
void setVibratoFrequency( StkFloat val );
|
||||
void setNoiseGain( StkFloat val );
|
||||
void setBreathCutoff( StkFloat val );
|
||||
void setSoftness( StkFloat val );
|
||||
|
||||
private:
|
||||
DelayL pinDelay_;
|
||||
DelayL poutDelay_;
|
||||
DelayL jetDelay_;
|
||||
Iir radiation_filter_;
|
||||
Iir visco_in_filter_;
|
||||
Iir visco_out_filter_;
|
||||
Iir jetFilter_;
|
||||
Noise turb_;
|
||||
Iir turbFilter_;
|
||||
SineWave vibrato_;
|
||||
ADSR adsr_;
|
||||
|
||||
//StkFloat M{ 0 };
|
||||
//StkFloat maxPressure_( 0 );
|
||||
double maxPressure_;
|
||||
//StkFloat blow{ 0 };
|
||||
StkFloat vibratoGain_;
|
||||
StkFloat noiseGain_;
|
||||
StkFloat breathCutoff_;
|
||||
StkFloat outputGain_;
|
||||
StkFloat psi_;
|
||||
|
||||
StkFloat poutL_;
|
||||
StkFloat pout_;
|
||||
StkFloat poutm1_;
|
||||
StkFloat poutm2_;
|
||||
StkFloat pin_;
|
||||
StkFloat pinm1_;
|
||||
StkFloat pinm2_;
|
||||
|
||||
StkFloat b1;
|
||||
StkFloat b3;
|
||||
StkFloat b4;
|
||||
|
||||
StkFloat Uj_;
|
||||
StkFloat Ujm1_;
|
||||
|
||||
StkFloat Qj_;
|
||||
StkFloat Qjm1_;
|
||||
StkFloat Qjm2_;
|
||||
|
||||
StkFloat Q1_;
|
||||
StkFloat Q1m1_;
|
||||
StkFloat Q1m2_;
|
||||
|
||||
StkFloat Qp_;
|
||||
StkFloat Qpm1_;
|
||||
|
||||
StkFloat pm_;
|
||||
};
|
||||
|
||||
inline StkFrames& Recorder :: tick( StkFrames& frames, unsigned int channel )
|
||||
{
|
||||
unsigned int nChannels = lastFrame_.channels();
|
||||
#if defined(_STK_DEBUG_)
|
||||
if ( channel > frames.channels() - nChannels ) {
|
||||
oStream_ << "Recorder::tick(): channel and StkFrames arguments are incompatible!";
|
||||
handleError( StkError::FUNCTION_ARGUMENT );
|
||||
}
|
||||
#endif
|
||||
|
||||
StkFloat *samples = &frames[channel];
|
||||
unsigned int j, hop = frames.channels() - nChannels;
|
||||
if ( nChannels == 1 ) {
|
||||
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
|
||||
*samples++ = tick();
|
||||
}
|
||||
else {
|
||||
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
|
||||
*samples++ = tick();
|
||||
for ( j=1; j<nChannels; j++ )
|
||||
*samples++ = lastFrame_[j];
|
||||
}
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
} // stk namespace
|
||||
|
||||
#endif
|
||||
@@ -37,7 +37,7 @@ class StifKarp : public Instrmnt
|
||||
{
|
||||
public:
|
||||
//! Class constructor, taking the lowest desired playing frequency.
|
||||
StifKarp( StkFloat lowestFrequency = 8.0 );
|
||||
StifKarp( StkFloat lowestFrequency = 10.0 );
|
||||
|
||||
//! Class destructor.
|
||||
~StifKarp( void );
|
||||
@@ -95,7 +95,6 @@ class StifKarp : public Instrmnt
|
||||
Noise noise_;
|
||||
BiQuad biquad_[4];
|
||||
|
||||
unsigned long length_;
|
||||
StkFloat loopGain_;
|
||||
StkFloat baseLoopGain_;
|
||||
StkFloat lastFrequency_;
|
||||
|
||||
@@ -10,13 +10,13 @@ vpath %.o $(OBJECT_PATH)
|
||||
OBJECTS = Stk.o Noise.o Envelope.o ADSR.o \
|
||||
Modulate.o SingWave.o SineWave.o FileRead.o FileWrite.o \
|
||||
FileWvIn.o FileLoop.o FileWvOut.o \
|
||||
OneZero.o OnePole.o PoleZero.o TwoZero.o Fir.o \
|
||||
OneZero.o OnePole.o PoleZero.o TwoZero.o Fir.o Iir.o \
|
||||
BiQuad.o FormSwep.o Delay.o DelayL.o DelayA.o \
|
||||
ReedTable.o JetTable.o BowTable.o \
|
||||
JCRev.o \
|
||||
Voicer.o Vector3D.o Sphere.o Twang.o \
|
||||
\
|
||||
Clarinet.o BlowHole.o Saxofony.o Flute.o Brass.o BlowBotl.o \
|
||||
Clarinet.o BlowHole.o Saxofony.o Flute.o Brass.o BlowBotl.o Recorder.o \
|
||||
Bowed.o Plucked.o StifKarp.o Sitar.o PluckTwo.o Mandolin.o Mesh2D.o \
|
||||
FM.o Rhodey.o Wurley.o TubeBell.o HevyMetl.o PercFlut.o BeeThree.o FMVoices.o \
|
||||
Sampler.o Moog.o Simple.o Drummer.o Shakers.o \
|
||||
|
||||
@@ -151,6 +151,8 @@ menu .menu.instrument -tearoff 0
|
||||
-value 2600 -command { patchChange $patchnum }
|
||||
.menu.instrument add radio -label "Police Whistle" -variable patchnum \
|
||||
-value 2700 -command { patchChange $patchnum }
|
||||
.menu.instrument add radio -label "Recorder" -variable patchnum \
|
||||
-value 2800 -command { patchChange $patchnum }
|
||||
|
||||
. configure -menu .menu
|
||||
|
||||
@@ -744,6 +746,23 @@ proc patchChange {value} {
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
flush stdout
|
||||
}
|
||||
if {$program==28} { # Recorder
|
||||
.pretty config -bitmap @$bitmappath/KFloot.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Softness"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 10.0
|
||||
set cont2 64.0
|
||||
set cont4 40.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
set oldpatch $value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ radiobutton .radios2.sitr -text "Sitar" -bg grey66 \
|
||||
-variable patchnum -value 9 -command { patchChange $patchnum }
|
||||
radiobutton .radios2.mand -text "Mandolin" -bg grey66 \
|
||||
-variable patchnum -value 10 -command { patchChange $patchnum }
|
||||
radiobutton .radios2.recdr -text "Recorder" -bg grey66 \
|
||||
-variable patchnum -value 28 -command { patchChange $patchnum }
|
||||
|
||||
pack .radios1.clar -side left -padx 5 -pady 10
|
||||
pack .radios1.hole -side left -padx 5 -pady 10
|
||||
@@ -55,6 +57,7 @@ pack .radios2.pluk -side left -padx 5 -pady 10
|
||||
pack .radios2.karp -side left -padx 5 -pady 10
|
||||
pack .radios2.sitr -side left -padx 5 -pady 10
|
||||
pack .radios2.mand -side left -padx 5 -pady 10
|
||||
pack .radios2.recdr -side left -padx 5 -pady 10
|
||||
|
||||
pack .radios1
|
||||
pack .radios2
|
||||
@@ -169,178 +172,195 @@ proc noteOff {pitchVal pressVal} {
|
||||
proc patchChange {value} {
|
||||
global bitmappath cont1 cont2 cont4 cont11 pitch oldpatch
|
||||
puts [format "ProgramChange 0.0 1 %i" $value]
|
||||
if {$value==0} { # Clarinet
|
||||
.pretty config -bitmap @$bitmappath/Klar.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Reed Stiffness"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 20.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==1} { # BlowHole
|
||||
.pretty config -bitmap @$bitmappath/Klar.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Reed Stiffness"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Tonehole Openness"
|
||||
.right.cont1 config -state normal -label "Register Vent Openness"
|
||||
set cont1 0.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 0.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==2} { # Saxofony
|
||||
.pretty config -bitmap @$bitmappath/prcFunny.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Reed Stiffness"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Blow Position"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 20.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 26.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==3} { # Flute
|
||||
.pretty config -bitmap @$bitmappath/KFloot.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Embouchure Adjustment"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 20.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==4} { # Brass
|
||||
.pretty config -bitmap @$bitmappath/KHose.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Lip Adjustment"
|
||||
.right.cont4 config -state normal -label "Slide Length"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 0.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 64.0
|
||||
set press 80.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
puts [format "NoteOn 0.0 1 %3.2f %3.2f" $pitch $press]
|
||||
}
|
||||
if {$value==5} { # Bottle
|
||||
.pretty config -bitmap @$bitmappath/prcFunny.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state disabled -label "Disabled"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 20.0
|
||||
set cont4 20.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==6} { # Bowed String
|
||||
.pretty config -bitmap @$bitmappath/KFiddl.xbm
|
||||
.left.bPressure config -state normal -label "Volume"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Bow Pressure"
|
||||
.right.cont4 config -state normal -label "Bow Position"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 4.0
|
||||
set cont2 64.0
|
||||
set cont4 24.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==7} { # Yer Basic Pluck
|
||||
.pretty config -bitmap @$bitmappath/KPluk.xbm
|
||||
.left.bPressure config -state normal -label "Pluck Strength"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state disabled -label "Disabled"
|
||||
.right.cont4 config -state disabled -label "Disabled"
|
||||
.right.cont11 config -state disabled -label "Disabled"
|
||||
.right.cont1 config -state disabled -label "Disabled"
|
||||
}
|
||||
if {$value==8} { # Stiff String
|
||||
.pretty config -bitmap @$bitmappath/KPluk.xbm
|
||||
.left.bPressure config -state normal -label "Pluck Strength"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state disabled -label "Disabled"
|
||||
.right.cont4 config -state normal -label "Pickup Position"
|
||||
.right.cont11 config -state normal -label "String Sustain"
|
||||
.right.cont1 config -state normal -label "String Stretch"
|
||||
set cont1 10.0
|
||||
set cont4 64.0
|
||||
set cont11 96.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==9} { # Sitar
|
||||
.pretty config -bitmap @$bitmappath/KPluk.xbm
|
||||
.left.bPressure config -state normal -label "Pluck Strength"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state disabled -label "Disabled"
|
||||
.right.cont4 config -state disabled -label "Disabled"
|
||||
.right.cont11 config -state disabled -label "Disabled"
|
||||
.right.cont1 config -state disabled -label "Disabled"
|
||||
}
|
||||
if {$value==10} { # Mandolin
|
||||
.pretty config -bitmap @$bitmappath/KPluk.xbm
|
||||
.left.bPressure config -state normal -label "Microphone Position and Gain"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Mandolin Body Size"
|
||||
.right.cont4 config -state normal -label "Pick Position"
|
||||
.right.cont11 config -state normal -label "String Sustain"
|
||||
.right.cont1 config -state normal -label "String Detune"
|
||||
set cont1 10.0
|
||||
set cont2 64.0
|
||||
set cont4 64.0
|
||||
set cont11 96.0
|
||||
set press 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
changePress $press
|
||||
}
|
||||
set oldpatch $value
|
||||
if {$value==0} { # Clarinet
|
||||
.pretty config -bitmap @$bitmappath/Klar.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Reed Stiffness"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 20.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==1} { # BlowHole
|
||||
.pretty config -bitmap @$bitmappath/Klar.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Reed Stiffness"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Tonehole Openness"
|
||||
.right.cont1 config -state normal -label "Register Vent Openness"
|
||||
set cont1 0.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 0.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==2} { # Saxofony
|
||||
.pretty config -bitmap @$bitmappath/prcFunny.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Reed Stiffness"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Blow Position"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 20.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 26.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==3} { # Flute
|
||||
.pretty config -bitmap @$bitmappath/KFloot.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Embouchure Adjustment"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 20.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==4} { # Brass
|
||||
.pretty config -bitmap @$bitmappath/KHose.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Lip Adjustment"
|
||||
.right.cont4 config -state normal -label "Slide Length"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 0.0
|
||||
set cont2 64.0
|
||||
set cont4 20.0
|
||||
set cont11 64.0
|
||||
set press 80.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
puts [format "NoteOn 0.0 1 %3.2f %3.2f" $pitch $press]
|
||||
}
|
||||
if {$value==5} { # Bottle
|
||||
.pretty config -bitmap @$bitmappath/prcFunny.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state disabled -label "Disabled"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 20.0
|
||||
set cont4 20.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==6} { # Bowed String
|
||||
.pretty config -bitmap @$bitmappath/KFiddl.xbm
|
||||
.left.bPressure config -state normal -label "Volume"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Bow Pressure"
|
||||
.right.cont4 config -state normal -label "Bow Position"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 4.0
|
||||
set cont2 64.0
|
||||
set cont4 24.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==7} { # Yer Basic Pluck
|
||||
.pretty config -bitmap @$bitmappath/KPluk.xbm
|
||||
.left.bPressure config -state normal -label "Pluck Strength"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state disabled -label "Disabled"
|
||||
.right.cont4 config -state disabled -label "Disabled"
|
||||
.right.cont11 config -state disabled -label "Disabled"
|
||||
.right.cont1 config -state disabled -label "Disabled"
|
||||
}
|
||||
if {$value==8} { # Stiff String
|
||||
.pretty config -bitmap @$bitmappath/KPluk.xbm
|
||||
.left.bPressure config -state normal -label "Pluck Strength"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state disabled -label "Disabled"
|
||||
.right.cont4 config -state normal -label "Pickup Position"
|
||||
.right.cont11 config -state normal -label "String Sustain"
|
||||
.right.cont1 config -state normal -label "String Stretch"
|
||||
set cont1 10.0
|
||||
set cont4 64.0
|
||||
set cont11 96.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
if {$value==9} { # Sitar
|
||||
.pretty config -bitmap @$bitmappath/KPluk.xbm
|
||||
.left.bPressure config -state normal -label "Pluck Strength"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state disabled -label "Disabled"
|
||||
.right.cont4 config -state disabled -label "Disabled"
|
||||
.right.cont11 config -state disabled -label "Disabled"
|
||||
.right.cont1 config -state disabled -label "Disabled"
|
||||
}
|
||||
if {$value==10} { # Mandolin
|
||||
.pretty config -bitmap @$bitmappath/KPluk.xbm
|
||||
.left.bPressure config -state normal -label "Microphone Position and Gain"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Mandolin Body Size"
|
||||
.right.cont4 config -state normal -label "Pick Position"
|
||||
.right.cont11 config -state normal -label "String Sustain"
|
||||
.right.cont1 config -state normal -label "String Detune"
|
||||
set cont1 10.0
|
||||
set cont2 64.0
|
||||
set cont4 64.0
|
||||
set cont11 96.0
|
||||
set press 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
changePress $press
|
||||
}
|
||||
if {$value==28} { # Recorder
|
||||
.pretty config -bitmap @$bitmappath/KFloot.xbm
|
||||
.left.bPressure config -state normal -label "Breath Pressure"
|
||||
.left.pitch config -state normal -label "MIDI Note Number"
|
||||
.left.cont2 config -state normal -label "Softness"
|
||||
.right.cont4 config -state normal -label "Breath Noise"
|
||||
.right.cont11 config -state normal -label "Vibrato Rate"
|
||||
.right.cont1 config -state normal -label "Vibrato Amount"
|
||||
set cont1 10.0
|
||||
set cont2 64.0
|
||||
set cont4 40.0
|
||||
set cont11 64.0
|
||||
printWhatz "ControlChange 0.0 1 " 1 $cont1
|
||||
printWhatz "ControlChange 0.0 1 " 2 $cont2
|
||||
printWhatz "ControlChange 0.0 1 " 4 $cont4
|
||||
printWhatz "ControlChange 0.0 1 " 11 $cont11
|
||||
}
|
||||
set oldpatch $value
|
||||
}
|
||||
|
||||
proc printWhatz {tag value1 value2 } {
|
||||
@@ -389,4 +409,4 @@ proc center_the_toplevel { w } {
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "BlowHole.h"
|
||||
#include "Saxofony.h"
|
||||
#include "Flute.h"
|
||||
#include "Recorder.h"
|
||||
#include "Brass.h"
|
||||
#include "BlowBotl.h"
|
||||
#include "Bowed.h"
|
||||
@@ -37,7 +38,7 @@
|
||||
|
||||
using namespace stk;
|
||||
|
||||
#define NUM_INSTS 28
|
||||
#define NUM_INSTS 29
|
||||
|
||||
// The order of the following list is important. The location of a particular
|
||||
// instrument in the list should correspond to that instrument's ProgramChange
|
||||
@@ -46,7 +47,7 @@ char insts[NUM_INSTS][10] = { "Clarinet", "BlowHole", "Saxofony", "Flute", "Bras
|
||||
"BlowBotl", "Bowed", "Plucked", "StifKarp", "Sitar", "Mandolin",
|
||||
"Rhodey", "Wurley", "TubeBell", "HevyMetl", "PercFlut",
|
||||
"BeeThree", "FMVoices", "VoicForm", "Moog", "Simple", "Drummer",
|
||||
"BandedWG", "Shakers", "ModalBar", "Mesh2D", "Resonate", "Whistle" };
|
||||
"BandedWG", "Shakers", "ModalBar", "Mesh2D", "Resonate", "Whistle", "Recorder" };
|
||||
|
||||
int voiceByNumber(int number, Instrmnt **instrument)
|
||||
{
|
||||
@@ -82,6 +83,7 @@ int voiceByNumber(int number, Instrmnt **instrument)
|
||||
else if (number==25) *instrument = new Mesh2D(10, 10);
|
||||
else if (number==26) *instrument = new Resonate;
|
||||
else if (number==27) *instrument = new Whistle;
|
||||
else if (number==28) *instrument = new Recorder;
|
||||
|
||||
else {
|
||||
printf("\nUnknown instrument or program change requested!\n");
|
||||
|
||||
@@ -47,8 +47,8 @@ Flute :: Flute( StkFloat lowestFrequency )
|
||||
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010 );
|
||||
endReflection_ = 0.5;
|
||||
jetReflection_ = 0.5;
|
||||
noiseGain_ = 0.15; // Breath pressure random component.
|
||||
vibratoGain_ = 0.05; // Breath periodic vibrato component.
|
||||
noiseGain_ = 0.15; // Breath pressure random component
|
||||
vibratoGain_ = 0.05; // Breath periodic vibrato component
|
||||
jetRatio_ = 0.32;
|
||||
|
||||
maxPressure_ = 0.0;
|
||||
|
||||
@@ -26,7 +26,7 @@ OBJECTS = Stk.o Generator.o Noise.o Blit.o BlitSaw.o BlitSquare.o Granulate.o \
|
||||
Function.o ReedTable.o JetTable.o BowTable.o Cubic.o \
|
||||
Voicer.o Vector3D.o Sphere.o Twang.o Guitar.o \
|
||||
\
|
||||
Instrmnt.o Clarinet.o BlowHole.o Saxofony.o Flute.o Brass.o BlowBotl.o \
|
||||
Instrmnt.o Clarinet.o BlowHole.o Saxofony.o Flute.o Recorder.o Brass.o BlowBotl.o \
|
||||
Bowed.o Plucked.o StifKarp.o Sitar.o Mandolin.o Mesh2D.o \
|
||||
FM.o Rhodey.o Wurley.o TubeBell.o HevyMetl.o PercFlut.o BeeThree.o FMVoices.o \
|
||||
Sampler.o Moog.o Simple.o Drummer.o Shakers.o \
|
||||
|
||||
345
src/Recorder.cpp
Normal file
345
src/Recorder.cpp
Normal file
@@ -0,0 +1,345 @@
|
||||
/***************************************************/
|
||||
/*! \class Recorder
|
||||
\brief A recorder / flute physical model.
|
||||
|
||||
This class implements a physical model of a recorder /
|
||||
flute instrument, based on the paper "Sound production
|
||||
in recorderlike instruments. II. A simulation model."
|
||||
by M.P. Verge, A. Hirschberg and R. Causse, Journal of
|
||||
the Acoustical Society of America, 1997.
|
||||
|
||||
Control Change Numbers:
|
||||
- Softness = 2
|
||||
- Noise Gain = 4
|
||||
- Noise Cutoff = 16
|
||||
- Vibrato Frequency = 11
|
||||
- Vibrato Gain = 1
|
||||
- Breath Pressure = 128
|
||||
|
||||
by Mathias Bredholt, McGill University.
|
||||
Formatted for STK by Gary Scavone, 2019.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
#include "Recorder.h"
|
||||
#include "SKINImsg.h"
|
||||
|
||||
namespace stk {
|
||||
|
||||
// Air constants
|
||||
const stk::StkFloat rho = 1.2041; // density of air
|
||||
const stk::StkFloat c0 = 343.21; // speed of sound in air
|
||||
|
||||
// Flute constants
|
||||
const stk::StkFloat lc = 0.02; // length of flue canal
|
||||
const stk::StkFloat h = 0.001; // height of flue exit
|
||||
const stk::StkFloat H = 0.02; // pipe diameter
|
||||
const stk::StkFloat W = 4 * h; // width of mouth
|
||||
const stk::StkFloat Sp = H * H; // cross-section of pipe
|
||||
const stk::StkFloat Sm = W * H; // cross-section of mouth
|
||||
const stk::StkFloat din = 0.0030; // end correction
|
||||
const stk::StkFloat dout = 0.0063; // end correction
|
||||
const stk::StkFloat dm = din + dout; // end correction of mouth
|
||||
const stk::StkFloat dd = 0.0035; // acoustic distance between Q1 and Q2
|
||||
const stk::StkFloat rp = sqrt(Sp / stk::PI);
|
||||
const stk::StkFloat b = 0.4 * h; // jet width
|
||||
|
||||
// Calculation coefficients
|
||||
const stk::StkFloat b2 = Sp / (rho * c0);
|
||||
|
||||
Recorder :: Recorder()
|
||||
{
|
||||
vibratoGain_ = 0.0;
|
||||
noiseGain_ = 0.2;
|
||||
breathCutoff_ = 0.0;
|
||||
outputGain_ = 0.0;
|
||||
psi_ = 1.0;
|
||||
poutL_ = 0;
|
||||
pout_ = 0;
|
||||
poutm1_ = 0;
|
||||
poutm2_ = 0;
|
||||
pin_ = 0;
|
||||
pinm1_ = 0;
|
||||
pinm2_ = 0;
|
||||
Uj_ = 0;
|
||||
Ujm1_ = 0;
|
||||
Qj_ = 0;
|
||||
Qjm1_ = 0;
|
||||
Qjm2_ = 0;
|
||||
Q1_ = 0;
|
||||
Q1m1_ = 0;
|
||||
Q1m2_ = 0;
|
||||
Qp_ = 0;
|
||||
Qpm1_ = 0;
|
||||
pm_ = 0;
|
||||
|
||||
pinDelay_.tick( 0 );
|
||||
poutDelay_.tick( 0 );
|
||||
jetDelay_.tick( 0 );
|
||||
|
||||
jetDelay_.setDelay(200);
|
||||
vibrato_.setFrequency(4);
|
||||
|
||||
// Calculation coefficients ... would need to be recalculated if sample rate changes
|
||||
StkFloat T = 1.0 / Stk::sampleRate();
|
||||
b1 = rho / (4.0 * PI * c0 * T * T);
|
||||
b3 = dm * Sp / (T * Sm * c0);
|
||||
b4 = rho * dout / (Sm * T);
|
||||
|
||||
// Radiation loss filter
|
||||
StkFloat A = rp * rp / (4 * c0 * c0 * T * T);
|
||||
StkFloat B = 0.82 * rp / (c0*T);
|
||||
StkFloat b_rad[3] = { 1 + A - B, B - 2 * A, A };
|
||||
StkFloat a_rad[3] = { A - B - 1, B - 2 * A, A };
|
||||
std::vector<StkFloat> b_coeffs( &b_rad[0], &b_rad[0]+3 );
|
||||
std::vector<StkFloat> a_coeffs( &a_rad[0], &a_rad[0]+3 );
|
||||
radiation_filter_.setCoefficients(b_coeffs, a_coeffs);
|
||||
|
||||
// Visco-thermal loss filter
|
||||
StkFloat b_visco[4] = { 0.83820223947141, -0.16888603248373, -0.64759781930259, 0.07424498608506 };
|
||||
StkFloat a_visco[4] = { 1.0, -0.33623476246554, -0.71257915055968, 0.14508304017256 };
|
||||
b_coeffs.clear();
|
||||
b_coeffs.assign( &b_visco[0], &b_visco[0]+4 );
|
||||
a_coeffs.clear();
|
||||
a_coeffs.assign( &a_visco[0], &a_visco[0]+4 );
|
||||
visco_in_filter_.setCoefficients(b_coeffs, a_coeffs);
|
||||
visco_out_filter_.setCoefficients(b_coeffs, a_coeffs);
|
||||
|
||||
setBreathCutoff( 500 );
|
||||
setFrequency( 880 );
|
||||
}
|
||||
|
||||
Recorder :: ~Recorder( void )
|
||||
{
|
||||
}
|
||||
|
||||
void Recorder :: clear( void )
|
||||
{
|
||||
pinDelay_.clear();
|
||||
poutDelay_.clear();
|
||||
jetDelay_.clear();
|
||||
radiation_filter_.clear();
|
||||
visco_in_filter_.clear();
|
||||
visco_out_filter_.clear();
|
||||
turbFilter_.clear();
|
||||
}
|
||||
|
||||
void Recorder :: setFrequency( StkFloat val )
|
||||
{
|
||||
#if defined(_STK_DEBUG_)
|
||||
if ( val <= 0.0 ) {
|
||||
oStream_ << "Recorder::setFrequency: argument is less than or equal to zero!";
|
||||
handleError( StkError::WARNING ); return;
|
||||
}
|
||||
#endif
|
||||
|
||||
StkFloat M = Stk::sampleRate() / val - 4 - 3;
|
||||
pinDelay_.setDelay( M );
|
||||
poutDelay_.setDelay( M );
|
||||
}
|
||||
|
||||
void Recorder :: setBlowPressure( StkFloat val )
|
||||
{
|
||||
maxPressure_ = val;
|
||||
}
|
||||
|
||||
void Recorder :: setVibratoGain( StkFloat val )
|
||||
{
|
||||
vibratoGain_ = val;
|
||||
}
|
||||
|
||||
void Recorder :: setVibratoFrequency( StkFloat val )
|
||||
{
|
||||
vibrato_.setFrequency( val );
|
||||
}
|
||||
|
||||
void Recorder :: setNoiseGain( StkFloat val )
|
||||
{
|
||||
noiseGain_ = val;
|
||||
}
|
||||
|
||||
void Recorder :: setBreathCutoff( StkFloat val )
|
||||
{
|
||||
// The gain of this filter is quite high
|
||||
breathCutoff_ = val;
|
||||
StkFloat Q = 0.99;
|
||||
StkFloat r = 2.0 * sin(PI * val / sampleRate());
|
||||
StkFloat q = 1.0 - r * Q;
|
||||
StkFloat as[3] = { 1.0, r * r - q - 1, q };
|
||||
std::vector<StkFloat> b_turb(1, r*r);
|
||||
std::vector<StkFloat> a_turb( &as[0], &as[0]+3 );
|
||||
turbFilter_.setCoefficients(b_turb, a_turb);
|
||||
}
|
||||
|
||||
void Recorder :: setSoftness( StkFloat val )
|
||||
{
|
||||
psi_ = val;
|
||||
}
|
||||
|
||||
void Recorder :: startBlowing( StkFloat amplitude, StkFloat rate )
|
||||
{
|
||||
if ( amplitude <= 0.0 || rate <= 0.0 ) {
|
||||
oStream_ << "Recorder::startBlowing: one or more arguments is less than or equal to zero!";
|
||||
handleError( StkError::WARNING ); return;
|
||||
}
|
||||
|
||||
adsr_.setAttackRate( rate );
|
||||
//maxPressure_ = amplitude / (StkFloat) 0.8;
|
||||
maxPressure_ = 35 * amplitude;
|
||||
adsr_.keyOn();
|
||||
}
|
||||
|
||||
void Recorder :: stopBlowing( StkFloat rate )
|
||||
{
|
||||
if ( rate <= 0.0 ) {
|
||||
oStream_ << "Recorder::stopBlowing: argument is less than or equal to zero!";
|
||||
handleError( StkError::WARNING ); return;
|
||||
}
|
||||
|
||||
adsr_.setReleaseRate( rate );
|
||||
adsr_.keyOff();
|
||||
}
|
||||
|
||||
void Recorder :: noteOn( StkFloat frequency, StkFloat amplitude )
|
||||
{
|
||||
this->setFrequency( frequency );
|
||||
this->startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02 );
|
||||
outputGain_ = amplitude / 40.0;
|
||||
}
|
||||
|
||||
void Recorder :: noteOff( StkFloat amplitude )
|
||||
{
|
||||
this->stopBlowing( amplitude * 0.02 );
|
||||
}
|
||||
|
||||
void Recorder :: controlChange( int number, StkFloat value )
|
||||
{
|
||||
#if defined(_STK_DEBUG_)
|
||||
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
|
||||
oStream_ << "Recorder::controlChange: value (" << value << ") is out of range!";
|
||||
handleError( StkError::WARNING ); return;
|
||||
}
|
||||
#endif
|
||||
|
||||
StkFloat normalizedValue = value * ONE_OVER_128;
|
||||
if (number == 2) // 2
|
||||
psi_ = 2.0 * normalizedValue;
|
||||
else if (number == 16)
|
||||
setBreathCutoff( normalizedValue * 2000 );
|
||||
else if (number == __SK_NoiseLevel_) // 4
|
||||
noiseGain_ = normalizedValue;
|
||||
else if (number == __SK_ModFrequency_) // 11
|
||||
vibrato_.setFrequency( normalizedValue * 12.0);
|
||||
else if (number == __SK_ModWheel_) // 1
|
||||
vibratoGain_ = ( normalizedValue * 0.4 );
|
||||
else if (number == __SK_AfterTouch_Cont_) // 128
|
||||
maxPressure_ = 35.0 * normalizedValue;
|
||||
#if defined(_STK_DEBUG_)
|
||||
else {
|
||||
oStream_ << "Recorder::controlChange: undefined control number (" << number << ")!";
|
||||
handleError( StkError::WARNING );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
StkFloat Recorder::tick( unsigned int )
|
||||
{
|
||||
// Read in from delay lines
|
||||
pinm2_ = pinm1_;
|
||||
pinm1_ = pin_;
|
||||
pin_ = pinDelay_.lastOut();
|
||||
|
||||
poutm2_ = poutm1_;
|
||||
poutm1_ = pout_;
|
||||
poutL_ = poutDelay_.lastOut();
|
||||
|
||||
// Filter wave components for visco-thermal losses
|
||||
pin_ = visco_in_filter_.tick(pin_);
|
||||
poutL_ = visco_out_filter_.tick(poutL_);
|
||||
|
||||
// Get input blow pressure
|
||||
StkFloat pf = maxPressure_ * adsr_.tick() * (vibrato_.tick() * vibratoGain_ + (1 - vibratoGain_));
|
||||
|
||||
StkFloat T = 1.0 / sampleRate();
|
||||
|
||||
// Jet velocity at flue exit
|
||||
Ujm1_ = Uj_;
|
||||
Uj_ = Ujm1_ + T / (rho * lc) * (pf - pm_ - 0.5 * rho * Ujm1_ * Ujm1_);
|
||||
|
||||
// Jet flow at flue exit
|
||||
Qjm2_ = Qjm1_;
|
||||
Qjm1_ = Qj_;
|
||||
Qj_ = h * H * Uj_;
|
||||
|
||||
// Jet drive
|
||||
StkFloat Uj_steady = fmax(sqrt(2 * pf / rho), 0.1);
|
||||
StkFloat fc_jet = 0.36 / W * Uj_steady;
|
||||
StkFloat g_jet = 0.002004 * exp(-0.06046 * Uj_steady);
|
||||
StkFloat r_jet = 0.95 - Uj_steady * 0.015;
|
||||
StkFloat b0_jet = g_jet * (1 - r_jet * r_jet) / 2;
|
||||
|
||||
// Calculate coefficients for resonant filter
|
||||
StkFloat b_jet[3] = { b0_jet, 0, -b0_jet };
|
||||
StkFloat a_jet[3] = { 1, -2 * r_jet * cos(2 * PI * fc_jet * T), r_jet * r_jet };
|
||||
std::vector<StkFloat> b_jetcoeffs( &b_jet[0], &b_jet[0]+3 );
|
||||
std::vector<StkFloat> a_jetcoeffs( &a_jet[0], &a_jet[0]+3 );
|
||||
jetFilter_.setCoefficients( b_jetcoeffs, a_jetcoeffs );
|
||||
StkFloat eta = jetFilter_.tick(jetDelay_.lastOut());
|
||||
|
||||
// Calculate flow source Q1
|
||||
Q1m1_ = Q1_;
|
||||
Q1_ = b * H * Uj_ * (1 + tanh(eta / (psi_ * b)));
|
||||
|
||||
// Calculate pressure pulse modeling the jet drive
|
||||
StkFloat pjd = -rho * dd / Sm * (Q1_ - Q1m1_) / T;
|
||||
|
||||
// Vortex shedding
|
||||
int Qp_sign = 0;
|
||||
if (Qp_ < 0) Qp_sign = -1;
|
||||
else if (Qp_ > 0) Qp_sign = 1;
|
||||
|
||||
StkFloat pa = -0.5 * rho * (Qp_ / (0.6 * Sm)) * (Qp_ / (0.6 * Sm)) * Qp_sign;
|
||||
|
||||
// Turbulence
|
||||
StkFloat pt = turbFilter_.tick(noiseGain_ * turb_.tick() * 0.5 * rho * Uj_ * Uj_);
|
||||
|
||||
// Pressure pulse delta p
|
||||
StkFloat dp = pjd + pa + pt;
|
||||
|
||||
// Calculate outgoing pressure pout
|
||||
pout_ = ((b3 - b1 * b2 - 1) * pin_ +
|
||||
(2 * b1 * b2 - b3) * (pinm1_ - poutm1_) +
|
||||
b1 * b2 * (poutm2_ - pinm2_) -
|
||||
b1 * (Qj_ - 2 * Qjm1_ + Qjm2_) +
|
||||
b4 * (Qj_ - Qjm1_) + dp) / (1 - b1 * b2 + b3);
|
||||
|
||||
// Flow in the pipe
|
||||
Qpm1_ = Qp_;
|
||||
Qp_ = Sp / (rho * c0) * (pout_ - pin_);
|
||||
|
||||
// Mouth pressure
|
||||
pm_ = pout_ + pin_ - dp + rho * din / Sm * (Qp_ - Qpm1_)/T;
|
||||
|
||||
// Calculate transverse acoustic velocity
|
||||
StkFloat Q1d = Q1_ - 0.5 * b * H * Uj_;
|
||||
StkFloat Vac = 2.0 / PI * Qp_ / Sm - 0.38 * Q1d / Sm;
|
||||
jetDelay_.tick(Vac);
|
||||
|
||||
// Calculate new jet delay line length
|
||||
//jet_.setDelay(fmin(W / (0.6 * Uj_steady) * sampleRate(), 200.0));
|
||||
jetDelay_.setDelay(fmin(W / (0.6 * Uj_steady * T), 200.0));
|
||||
|
||||
// Radiation loss filtering
|
||||
StkFloat pin_L = radiation_filter_.tick(poutL_);
|
||||
|
||||
// Write to delay lines
|
||||
poutDelay_.tick(pout_);
|
||||
pinDelay_.tick(pin_L);
|
||||
|
||||
lastFrame_[0] = outputGain_ * (pout_ + pin_);
|
||||
return lastFrame_[0];
|
||||
|
||||
//return (pout_0 + pin_0) * 0.01;
|
||||
}
|
||||
|
||||
} // stk namespace
|
||||
@@ -89,7 +89,7 @@ void StifKarp :: setStretch( StkFloat stretch )
|
||||
StkFloat freq = lastFrequency_ * 2.0;
|
||||
StkFloat dFreq = ( (0.5 * Stk::sampleRate()) - freq ) * 0.25;
|
||||
StkFloat temp = 0.5 + (stretch * 0.5);
|
||||
if ( temp > 0.9999 ) temp = 0.9999;
|
||||
if ( temp > 0.99999 ) temp = 0.99999;
|
||||
for ( int i=0; i<4; i++ ) {
|
||||
coefficient = temp * temp;
|
||||
biquad_[i].setA2( coefficient );
|
||||
@@ -131,7 +131,7 @@ void StifKarp :: pluck( StkFloat amplitude )
|
||||
}
|
||||
|
||||
pluckAmplitude_ = amplitude;
|
||||
for ( unsigned long i=0; i<length_; i++ ) {
|
||||
for ( unsigned long i=0; i<lastLength_; i++ ) {
|
||||
// Fill delay with noise additively with current contents.
|
||||
delayLine_.tick( (delayLine_.lastOut() * 0.6) + 0.4 * noise_.tick() * pluckAmplitude_ );
|
||||
//delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) );
|
||||
|
||||
Reference in New Issue
Block a user