mirror of
https://github.com/thestk/stk
synced 2026-02-05 17:06:16 +00:00
New default argument to keyOn and keyOff in Envelope, fix in setTime function, updates to Guitar string coupling, EGuitar tcl interface, reordering of operations in Flute algorithm.
This commit is contained in:
@@ -12,7 +12,8 @@ namespace stk {
|
|||||||
This class implements a simple linear line envelope generator
|
This class implements a simple linear line envelope generator
|
||||||
which is capable of ramping to an arbitrary target value by a
|
which is capable of ramping to an arbitrary target value by a
|
||||||
specified \e rate. It also responds to simple \e keyOn and \e
|
specified \e rate. It also responds to simple \e keyOn and \e
|
||||||
keyOff messages, ramping to 1.0 on keyOn and to 0.0 on keyOff.
|
keyOff messages, ramping to a specified target (default = 1.0) on
|
||||||
|
keyOn and to a specified target (default = 0.0) on keyOff.
|
||||||
|
|
||||||
by Perry R. Cook and Gary P. Scavone, 1995--2019.
|
by Perry R. Cook and Gary P. Scavone, 1995--2019.
|
||||||
*/
|
*/
|
||||||
@@ -31,11 +32,11 @@ class Envelope : public Generator
|
|||||||
//! Assignment operator.
|
//! Assignment operator.
|
||||||
Envelope& operator= ( const Envelope& e );
|
Envelope& operator= ( const Envelope& e );
|
||||||
|
|
||||||
//! Set target = 1.
|
//! Start ramping to specified target (default = 1).
|
||||||
void keyOn( void ) { this->setTarget( 1.0 ); };
|
void keyOn( StkFloat target = 1.0 ) { this->setTarget( target ); };
|
||||||
|
|
||||||
//! Set target = 0.
|
//! Start ramping to specified target (default = 0).
|
||||||
void keyOff( void ) { this->setTarget( 0.0 ); };
|
void keyOff( StkFloat target = 0.0 ) { this->setTarget( target ); };
|
||||||
|
|
||||||
//! Set the \e rate.
|
//! Set the \e rate.
|
||||||
/*!
|
/*!
|
||||||
@@ -46,7 +47,7 @@ class Envelope : public Generator
|
|||||||
//! Set the \e rate based on a positive time duration (seconds).
|
//! Set the \e rate based on a positive time duration (seconds).
|
||||||
/*!
|
/*!
|
||||||
The \e rate is calculated such that the envelope will ramp from
|
The \e rate is calculated such that the envelope will ramp from
|
||||||
a value of 0.0 to 1.0 in the specified time duration.
|
the current value to the current target in the specified time duration.
|
||||||
*/
|
*/
|
||||||
void setTime( StkFloat time );
|
void setTime( StkFloat time );
|
||||||
|
|
||||||
|
|||||||
@@ -123,11 +123,12 @@ inline StkFloat Flute :: tick( unsigned int )
|
|||||||
breathPressure += breathPressure * ( noiseGain_ * noise_.tick() + vibratoGain_ * vibrato_.tick() );
|
breathPressure += breathPressure * ( noiseGain_ * noise_.tick() + vibratoGain_ * vibrato_.tick() );
|
||||||
|
|
||||||
StkFloat temp = -filter_.tick( boreDelay_.lastOut() );
|
StkFloat temp = -filter_.tick( boreDelay_.lastOut() );
|
||||||
temp = dcBlock_.tick( temp ); // Block DC on reflection.
|
//temp = dcBlock_.tick( temp ); // Block DC on reflection.
|
||||||
|
|
||||||
pressureDiff = breathPressure - (jetReflection_ * temp);
|
pressureDiff = breathPressure - (jetReflection_ * temp);
|
||||||
pressureDiff = jetDelay_.tick( pressureDiff );
|
pressureDiff = jetDelay_.tick( pressureDiff );
|
||||||
pressureDiff = jetTable_.tick( pressureDiff ) + (endReflection_ * temp);
|
//pressureDiff = jetTable_.tick( pressureDiff ) + (endReflection_ * temp);
|
||||||
|
pressureDiff = dcBlock_.tick(jetTable_.tick( pressureDiff )) + (endReflection_ * temp); // moved the DC blocker to after the jet non-linearity (GPS, 29 Jan. 2020)
|
||||||
lastFrame_[0] = (StkFloat) 0.3 * boreDelay_.tick( pressureDiff );
|
lastFrame_[0] = (StkFloat) 0.3 * boreDelay_.tick( pressureDiff );
|
||||||
|
|
||||||
lastFrame_[0] *= outputGain_;
|
lastFrame_[0] *= outputGain_;
|
||||||
|
|||||||
@@ -132,17 +132,20 @@ class Guitar : public Stk
|
|||||||
StkFrames lastFrame_;
|
StkFrames lastFrame_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NOTE: It is not possible to implement the Smith coupled string model here because the Twang class does
|
||||||
|
// not currently offer the chance to have access to a traveling-wave component. Thus, the coupling
|
||||||
|
// implemented here is approximate.
|
||||||
inline StkFloat Guitar :: tick( StkFloat input )
|
inline StkFloat Guitar :: tick( StkFloat input )
|
||||||
{
|
{
|
||||||
StkFloat temp, output = 0.0;
|
StkFloat temp, output = 0.0;
|
||||||
lastFrame_[0] /= strings_.size(); // evenly spread coupling across strings
|
lastFrame_[0] = couplingGain_ * couplingFilter_.tick( lastFrame_[0] ) / strings_.size();
|
||||||
for ( unsigned int i=0; i<strings_.size(); i++ ) {
|
for ( unsigned int i=0; i<strings_.size(); i++ ) {
|
||||||
if ( stringState_[i] ) {
|
if ( stringState_[i] ) {
|
||||||
temp = input;
|
temp = input;
|
||||||
// If pluckGain < 0.2, let string ring but don't pluck it.
|
// If pluckGain < 0.2, let string ring but don't pluck it.
|
||||||
if ( filePointer_[i] < excitation_.frames() && pluckGains_[i] > 0.2 )
|
if ( filePointer_[i] < excitation_.frames() && pluckGains_[i] > 0.2 )
|
||||||
temp += pluckGains_[i] * excitation_[filePointer_[i]++];
|
temp += pluckGains_[i] * excitation_[filePointer_[i]++];
|
||||||
temp += couplingGain_ * couplingFilter_.tick( lastFrame_[0] ); // bridge coupling
|
temp += lastFrame_[0]; // bridge coupling
|
||||||
output += strings_[i].tick( temp );
|
output += strings_[i].tick( temp );
|
||||||
// Check if string energy has decayed sufficiently to turn it off.
|
// Check if string energy has decayed sufficiently to turn it off.
|
||||||
if ( stringState_[i] == 1 ) {
|
if ( stringState_[i] == 1 ) {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ scale .left.bPressure -from 0 -to 128 -length 200 \
|
|||||||
-tickinterval 32 -showvalue true -bg grey66
|
-tickinterval 32 -showvalue true -bg grey66
|
||||||
|
|
||||||
scale .left.pitch -from 0 -to 128 -length 200 \
|
scale .left.pitch -from 0 -to 128 -length 200 \
|
||||||
-command {changePitch } -variable pitch \
|
-command {changePitch } -variable pitch -resolution 0.1 \
|
||||||
-orient horizontal -label "MIDI Note Number" \
|
-orient horizontal -label "MIDI Note Number" \
|
||||||
-tickinterval 32 -showvalue true -bg grey66
|
-tickinterval 32 -showvalue true -bg grey66
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ array set stringNote {
|
|||||||
5 59
|
5 59
|
||||||
6 64
|
6 64
|
||||||
}
|
}
|
||||||
|
array set powerNote {
|
||||||
|
1 40
|
||||||
|
2 47
|
||||||
|
3 52
|
||||||
|
4 59
|
||||||
|
}
|
||||||
#array set stringAmp { 1 64 2 64 3 64 4 64 5 64 6 64 }
|
#array set stringAmp { 1 64 2 64 3 64 4 64 5 64 6 64 }
|
||||||
array set stringAmp {
|
array set stringAmp {
|
||||||
1 64
|
1 64
|
||||||
@@ -53,10 +59,12 @@ pack .message -padx 5 -pady 10
|
|||||||
|
|
||||||
# Configure "note on" buttons
|
# Configure "note on" buttons
|
||||||
frame .top
|
frame .top
|
||||||
button .top.on -text Strum -bg grey66 -command strum
|
button .top.on -text Strum -padx 5 -bg grey66 -command strum
|
||||||
button .top.off -text "All Off" -bg grey66 -command allOff
|
button .top.power -text "Power Chord" -padx 5 -bg grey66 -command powerchord
|
||||||
button .top.exit -text "Quit" -bg grey66 -command quit
|
button .top.off -text "All Off" -padx 5 -bg grey66 -command allOff
|
||||||
|
button .top.exit -text "Quit" -padx 5 -bg grey66 -command quit
|
||||||
pack .top.on -side left -padx 5
|
pack .top.on -side left -padx 5
|
||||||
|
pack .top.power -side left -padx 5 -padx 5
|
||||||
pack .top.off -side left -padx 5 -pady 10
|
pack .top.off -side left -padx 5 -pady 10
|
||||||
pack .top.exit -side left -padx 5 -pady 10
|
pack .top.exit -side left -padx 5 -pady 10
|
||||||
pack .top
|
pack .top
|
||||||
@@ -117,13 +125,26 @@ proc quit {} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc strum {} {
|
proc strum {} {
|
||||||
global stringNote stringAmp
|
global stringAmp stringNote
|
||||||
for {set n 1} {$n < 7} {incr n} {
|
for {set n 1} {$n < 7} {incr n} {
|
||||||
puts [format "NoteOn %2.3f %d %3.2f %3.2f" [expr rand()*0.04] $n $stringNote($n) $stringAmp($n)]
|
puts [format "NoteOn %2.3f %d %3.2f %3.2f" [expr rand()*0.04] $n $stringNote($n) $stringAmp($n)]
|
||||||
}
|
}
|
||||||
flush stdout
|
flush stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc powerchord {} {
|
||||||
|
global stringNote powerNote stringAmp cont28 cont72
|
||||||
|
set cont72 80
|
||||||
|
set cont28 90
|
||||||
|
puts [format "ControlChange 0.0 0 72 %3.2f" $cont72]
|
||||||
|
puts [format "ControlChange 0.0 0 28 %3.2f" $cont28]
|
||||||
|
for {set n 1} {$n < 5} {incr n} {
|
||||||
|
set stringNote($n) $powerNote($n)
|
||||||
|
puts [format "NoteOn %2.3f %d %3.2f %3.2f" [expr rand()*0.01] $n $powerNote($n) $stringAmp($n)]
|
||||||
|
}
|
||||||
|
flush stdout
|
||||||
|
}
|
||||||
|
|
||||||
proc allOff {} {
|
proc allOff {} {
|
||||||
global stringNote stringAmp
|
global stringNote stringAmp
|
||||||
for {set n 1} {$n < 7} {incr n} {
|
for {set n 1} {$n < 7} {incr n} {
|
||||||
@@ -167,32 +188,32 @@ proc setStringAmp {value} {
|
|||||||
frame .strings -bg grey88 -borderwidth 5 -relief groove
|
frame .strings -bg grey88 -borderwidth 5 -relief groove
|
||||||
scale .strings.s1 -from $stringMin(1) -to [expr $stringMin(1)+$stringRange] \
|
scale .strings.s1 -from $stringMin(1) -to [expr $stringMin(1)+$stringRange] \
|
||||||
-length 350 -orient horizontal -label "String 1: Note Number" \
|
-length 350 -orient horizontal -label "String 1: Note Number" \
|
||||||
-tickinterval 5 -showvalue true -variable $stringNote(1) \
|
-tickinterval 5 -showvalue true -variable stringNote(1) \
|
||||||
-command {setNote 1}
|
-command {setNote 1}
|
||||||
|
|
||||||
scale .strings.s2 -from $stringMin(2) -to [expr $stringMin(2)+$stringRange] \
|
scale .strings.s2 -from $stringMin(2) -to [expr $stringMin(2)+$stringRange] \
|
||||||
-length 350 -orient horizontal -label "String 2: Note Number" \
|
-length 350 -orient horizontal -label "String 2: Note Number" \
|
||||||
-tickinterval 5 -showvalue true -variable $stringNote(2) \
|
-tickinterval 5 -showvalue true -variable stringNote(2) \
|
||||||
-command {setNote 2}
|
-command {setNote 2}
|
||||||
|
|
||||||
scale .strings.s3 -from $stringMin(3) -to [expr $stringMin(3)+$stringRange] \
|
scale .strings.s3 -from $stringMin(3) -to [expr $stringMin(3)+$stringRange] \
|
||||||
-length 350 -orient horizontal -label "String 3: Note Number" \
|
-length 350 -orient horizontal -label "String 3: Note Number" \
|
||||||
-tickinterval 5 -showvalue true -variable $stringNote(3) \
|
-tickinterval 5 -showvalue true -variable stringNote(3) \
|
||||||
-command {setNote 3}
|
-command {setNote 3}
|
||||||
|
|
||||||
scale .strings.s4 -from $stringMin(4) -to [expr $stringMin(4)+$stringRange] \
|
scale .strings.s4 -from $stringMin(4) -to [expr $stringMin(4)+$stringRange] \
|
||||||
-length 350 -orient horizontal -label "String 4: Note Number" \
|
-length 350 -orient horizontal -label "String 4: Note Number" \
|
||||||
-tickinterval 5 -showvalue true -variable $stringNote(4) \
|
-tickinterval 5 -showvalue true -variable stringNote(4) \
|
||||||
-command {setNote 4}
|
-command {setNote 4}
|
||||||
|
|
||||||
scale .strings.s5 -from $stringMin(5) -to [expr $stringMin(5)+$stringRange] \
|
scale .strings.s5 -from $stringMin(5) -to [expr $stringMin(5)+$stringRange] \
|
||||||
-length 350 -orient horizontal -label "String 5: Note Number" \
|
-length 350 -orient horizontal -label "String 5: Note Number" \
|
||||||
-tickinterval 5 -showvalue true -variable $stringNote(5) \
|
-tickinterval 5 -showvalue true -variable stringNote(5) \
|
||||||
-command {setNote 5}
|
-command {setNote 5}
|
||||||
|
|
||||||
scale .strings.s6 -from $stringMin(6) -to [expr $stringMin(6)+$stringRange] \
|
scale .strings.s6 -from $stringMin(6) -to [expr $stringMin(6)+$stringRange] \
|
||||||
-length 350 -orient horizontal -label "String 6: Note Number" \
|
-length 350 -orient horizontal -label "String 6: Note Number" \
|
||||||
-tickinterval 5 -showvalue true -variable $stringNote(6) \
|
-tickinterval 5 -showvalue true -variable stringNote(6) \
|
||||||
-command {setNote 6}
|
-command {setNote 6}
|
||||||
|
|
||||||
button .strings.b1 -text Pluck -command { pluckOne 1 }
|
button .strings.b1 -text Pluck -command { pluckOne 1 }
|
||||||
@@ -202,7 +223,6 @@ button .strings.b4 -text Pluck -command { pluckOne 4 }
|
|||||||
button .strings.b5 -text Pluck -command { pluckOne 5 }
|
button .strings.b5 -text Pluck -command { pluckOne 5 }
|
||||||
button .strings.b6 -text Pluck -command { pluckOne 6 }
|
button .strings.b6 -text Pluck -command { pluckOne 6 }
|
||||||
|
|
||||||
grid .strings -column 0 -row 0
|
|
||||||
grid .strings.b1 -column 1 -row 0 -padx 5 -pady 5
|
grid .strings.b1 -column 1 -row 0 -padx 5 -pady 5
|
||||||
grid .strings.b2 -column 1 -row 1
|
grid .strings.b2 -column 1 -row 1
|
||||||
grid .strings.b3 -column 1 -row 2
|
grid .strings.b3 -column 1 -row 2
|
||||||
@@ -218,9 +238,20 @@ grid .strings.s5 -column 0 -row 4 -padx 5 -pady 5
|
|||||||
grid .strings.s6 -column 0 -row 5 -padx 5 -pady 5
|
grid .strings.s6 -column 0 -row 5 -padx 5 -pady 5
|
||||||
|
|
||||||
set stringSelect "All"
|
set stringSelect "All"
|
||||||
ttk::combobox .strings.combo \
|
set values [ list "All" "String 1" "String 2" "String 3" "String 4" "String 5" "String 6" ]
|
||||||
-values [ list "All" "String 1" "String 2" "String 3" "String 4" "String 5" "String 6" ] \
|
ttk::combobox .strings.combo -values $values \
|
||||||
-width 8 -textvariable stringSelect -justify center
|
-width 10 -state readonly -textvariable stringSelect -justify center
|
||||||
|
bind .strings.combo <<ComboboxSelected>> {
|
||||||
|
global stringAmp velocity
|
||||||
|
switch [%W get] {
|
||||||
|
"String 1" { set velocity $stringAmp(1) }
|
||||||
|
"String 2" { set velocity $stringAmp(2) }
|
||||||
|
"String 3" { set velocity $stringAmp(3) }
|
||||||
|
"String 4" { set velocity $stringAmp(4) }
|
||||||
|
"String 5" { set velocity $stringAmp(5) }
|
||||||
|
"String 6" { set velocity $stringAmp(6) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scale .strings.velocity -from 0 -to 128 -length 350 \
|
scale .strings.velocity -from 0 -to 128 -length 350 \
|
||||||
-orient horizontal -label "Note Velocity" \
|
-orient horizontal -label "Note Velocity" \
|
||||||
@@ -229,7 +260,7 @@ scale .strings.velocity -from 0 -to 128 -length 350 \
|
|||||||
grid .strings.combo -column 1 -row 7
|
grid .strings.combo -column 1 -row 7
|
||||||
grid .strings.velocity -column 0 -row 7 -padx 5 -pady 10
|
grid .strings.velocity -column 0 -row 7 -padx 5 -pady 10
|
||||||
|
|
||||||
pack .strings
|
pack .strings -side right
|
||||||
|
|
||||||
set cbpath .strings.combo
|
set cbpath .strings.combo
|
||||||
|
|
||||||
@@ -261,4 +292,4 @@ proc center_the_toplevel { w } {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
This class implements a simple linear line envelope generator
|
This class implements a simple linear line envelope generator
|
||||||
which is capable of ramping to an arbitrary target value by a
|
which is capable of ramping to an arbitrary target value by a
|
||||||
specified \e rate. It also responds to simple \e keyOn and \e
|
specified \e rate. It also responds to simple \e keyOn and \e
|
||||||
keyOff messages, ramping to 1.0 on keyOn and to 0.0 on keyOff.
|
keyOff messages, ramping to a specified target (default = 1.0) on
|
||||||
|
keyOn and to a specified target (default = 0.0) on keyOff.
|
||||||
|
|
||||||
by Perry R. Cook and Gary P. Scavone, 1995--2019.
|
by Perry R. Cook and Gary P. Scavone, 1995--2019.
|
||||||
*/
|
*/
|
||||||
@@ -64,7 +65,8 @@ void Envelope :: setTime( StkFloat time )
|
|||||||
handleError( StkError::WARNING ); return;
|
handleError( StkError::WARNING ); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rate_ = 1.0 / ( time * Stk::sampleRate() );
|
//rate_ = 1.0 / ( time * Stk::sampleRate() );
|
||||||
|
rate_ = fabs(target_ - value_) / ( time * Stk::sampleRate() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Envelope :: setTarget( StkFloat target )
|
void Envelope :: setTarget( StkFloat target )
|
||||||
|
|||||||
Reference in New Issue
Block a user