finally good audio
This commit is contained in:
@@ -33,7 +33,7 @@ private:
|
|||||||
void calculateCoefficients();
|
void calculateCoefficients();
|
||||||
|
|
||||||
Type type_ = Type::BiquadLowpass;
|
Type type_ = Type::BiquadLowpass;
|
||||||
float sampleRate_ = 44100.0f;
|
float sampleRate_ = 1.0f;
|
||||||
|
|
||||||
float frequency_ = 6000.0f;
|
float frequency_ = 6000.0f;
|
||||||
float q_ = 0.707f;
|
float q_ = 0.707f;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ PianoString::PianoString(ConfigService* config, LoggerService* logger) : Instrum
|
|||||||
|
|
||||||
void PianoString::noteOn(float frequency, float velocity) {
|
void PianoString::noteOn(float frequency, float velocity) {
|
||||||
|
|
||||||
logger_->log("Piano", LogFlag::Debug, "Note On");
|
|
||||||
active_ = true;
|
active_ = true;
|
||||||
frequency_ = frequency;
|
frequency_ = frequency;
|
||||||
|
|
||||||
@@ -45,7 +44,6 @@ void PianoString::noteOn(float frequency, float velocity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PianoString::noteOff() {
|
void PianoString::noteOff() {
|
||||||
logger_->log("Piano", LogFlag::Debug, "Note Off");
|
|
||||||
damping_ = 10.0f;
|
damping_ = 10.0f;
|
||||||
recalculateConstants();
|
recalculateConstants();
|
||||||
}
|
}
|
||||||
@@ -67,41 +65,68 @@ bool PianoString::isActive() {
|
|||||||
|
|
||||||
float PianoString::process(bool& scopeTrigger) {
|
float PianoString::process(bool& scopeTrigger) {
|
||||||
|
|
||||||
// simulate over string
|
// supersample
|
||||||
for(size_t i = 2; i < segmentCount_ - 2; i++) {
|
for(uint32_t n = 0; n < samplingSteps_; n++) {
|
||||||
float y_xx = stringY_current_[i-1] - 2.0f*stringY_current_[i] + stringY_current_[i+1];
|
|
||||||
float y_xxxx = stringY_current_[i-2] - 4.0f*stringY_current_[i-1] + 6.0f*stringY_current_[i] - 4.0f*stringY_current_[i+1] + stringY_current_[i+2];
|
|
||||||
stringY_next_[i] = a1_ * stringY_current_[i] + a2_ * stringY_previous_[i] + r2_ * y_xx - s2_ * y_xxxx;
|
|
||||||
}
|
|
||||||
stringY_next_[0] = 0.0f;
|
|
||||||
stringY_next_[1] = 0.0f;
|
|
||||||
stringY_next_[segmentCount_-1] = 0.0f;
|
|
||||||
stringY_next_[segmentCount_-2] = 0.0f;
|
|
||||||
|
|
||||||
stringY_previous_ = stringY_current_;
|
// simulate over string
|
||||||
stringY_current_ = stringY_next_;
|
for(size_t i = 2; i < segmentCount_ - 2; i++) {
|
||||||
|
float y_xx = stringY_current_[i-1] - 2.0f*stringY_current_[i] + stringY_current_[i+1];
|
||||||
|
float y_xxxx = stringY_current_[i-2] - 4.0f*stringY_current_[i-1] + 6.0f*stringY_current_[i] - 4.0f*stringY_current_[i+1] + stringY_current_[i+2];
|
||||||
|
stringY_next_[i] = a1_ * stringY_current_[i] + a2_ * stringY_previous_[i] + r2_ * y_xx - s2_ * y_xxxx;
|
||||||
|
}
|
||||||
|
stringY_next_[0] = 0.0f;
|
||||||
|
stringY_next_[1] = 0.0f;
|
||||||
|
stringY_next_[segmentCount_-1] = 0.0f;
|
||||||
|
stringY_next_[segmentCount_-2] = 0.0f;
|
||||||
|
|
||||||
|
stringY_previous_ = stringY_current_;
|
||||||
|
stringY_current_ = stringY_next_;
|
||||||
|
}
|
||||||
|
|
||||||
|
phaseTracker_ += frequency_ / sampleRate_;
|
||||||
|
if(phaseTracker_ > 1.0f) {
|
||||||
|
phaseTracker_ -= 1.0f;
|
||||||
|
scopeTrigger = true;
|
||||||
|
}
|
||||||
|
|
||||||
float sampleOut = stringY_next_[static_cast<size_t>(samplePosition_*L_*segmentCount_)];
|
float sampleOut = stringY_next_[static_cast<size_t>(samplePosition_*L_*segmentCount_)];
|
||||||
|
|
||||||
rms_ = 0.99f * rms_ + 0.01f * sampleOut*sampleOut;
|
rms_ = 0.99f * rms_ + 0.01f * sampleOut*sampleOut;
|
||||||
|
|
||||||
return 5.0f * sampleOut;
|
return sampleOut;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PianoString::recalculateConstants() {
|
void PianoString::recalculateConstants() {
|
||||||
|
|
||||||
L_ = stringLength_ * std::pow(1.005f, -frequency_ + 20.0f) + 0.5f;
|
L_ = stringLength_ * std::pow(1.001f, -frequency_ + 20.0f) + 0.5f;
|
||||||
|
|
||||||
waveVelocity_ = 1.0f * frequency_ * L_;
|
waveVelocity_ = 2.0f * frequency_ * L_;
|
||||||
|
|
||||||
|
samplingSteps_ = 0;
|
||||||
|
do {
|
||||||
|
samplingSteps_++;
|
||||||
|
float effectiveSampleRate_ = sampleRate_ * static_cast<float>(samplingSteps_);
|
||||||
|
dt_ = 1.0f / effectiveSampleRate_;
|
||||||
|
|
||||||
|
float a = (waveVelocity_*dt_/L_)*(waveVelocity_*dt_/L_);
|
||||||
|
float b = 4.0f*(stiffness_*dt_/(L_*L_))*(stiffness_*dt_/(L_*L_));
|
||||||
|
if(stiffness_ < 0.00001f) { // avoid divide by zero
|
||||||
|
segmentCount_ = static_cast<size_t>((L_ * effectiveSampleRate_)/waveVelocity_) - 1;
|
||||||
|
} else {
|
||||||
|
segmentCount_ = static_cast<size_t>(std::sqrt((-a+std::sqrt(a*a+4.0*b))/(2.0*b))) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (segmentCount_ < 80);
|
||||||
|
|
||||||
|
segmentCount_ = std::min(segmentCount_, static_cast<size_t>(80));
|
||||||
|
|
||||||
dx_ = L_ / static_cast<float>(segmentCount_);
|
dx_ = L_ / static_cast<float>(segmentCount_);
|
||||||
dt_ = 1.0f / sampleRate_;
|
|
||||||
|
|
||||||
r1_ = waveVelocity_ * dt_/dx_;
|
r1_ = waveVelocity_ * dt_/dx_;
|
||||||
r2_ = std::pow(waveVelocity_ * dt_/dx_, 2.0f);
|
r2_ = (waveVelocity_ * dt_/dx_)*(waveVelocity_ * dt_/dx_);
|
||||||
s1_ = stiffness_ * dt_/std::pow(dx_, 2.0f);
|
s1_ = stiffness_ * dt_/(dx_*dx_);
|
||||||
s2_ = std::pow(stiffness_ * dt_/std::pow(dx_, 2.0f), 2.0f);
|
s2_ = (stiffness_ * dt_/(dx_*dx_))*(stiffness_ * dt_/(dx_*dx_));
|
||||||
a1_ = 2.0f - 2.0f * damping_ * dt_;
|
a1_ = 2.0f - 2.0f * damping_ * dt_;
|
||||||
a2_ = 2.0f * damping_ * dt_ - 1.0f;
|
a2_ = 2.0f * damping_ * dt_ - 1.0f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,15 +35,15 @@ private:
|
|||||||
// constants
|
// constants
|
||||||
|
|
||||||
// string parameters
|
// string parameters
|
||||||
size_t segmentCount_ = 50;
|
size_t segmentCount_ = 80;
|
||||||
static constexpr float rho_ = 8000.0f; // density, steel, kg/m^3
|
static constexpr float rho_ = 8000.0f; // density, steel, kg/m^3
|
||||||
static constexpr float radius_ = 0.001f; // meters
|
static constexpr float radius_ = 0.001f; // meters
|
||||||
static constexpr float stringTension_ = 1200.0f; // string tension, N
|
static constexpr float stringTension_ = 1200.0f; // string tension, N
|
||||||
static constexpr float stiffness_ = 0.000f; // stiffness coefficient
|
static constexpr float stiffness_ = 0.0f; // stiffness coefficient
|
||||||
float damping_ = 0.5f; // damping coefficient
|
float damping_ = 0.5f; // damping coefficient
|
||||||
static constexpr float stringLength_ = 5.0f; // length of string at lowest frequency (20 hz)
|
static constexpr float stringLength_ = 4.0f; // length of string at lowest frequency (20 hz)
|
||||||
static constexpr float strikePosition_ = 0.2f; // x of impulse location
|
static constexpr float strikePosition_ = 0.2f; // x of impulse location
|
||||||
static constexpr float impulseWidth_ = 0.02f; // x of impulse width
|
static constexpr float impulseWidth_ = 0.1f; // x of impulse width
|
||||||
static constexpr float impulseVelocity_ = 10000.0f; // x/t of impulse magnitude
|
static constexpr float impulseVelocity_ = 10000.0f; // x/t of impulse magnitude
|
||||||
static constexpr float samplePosition_ = 0.1f; // percentage along L of sampling for audio
|
static constexpr float samplePosition_ = 0.1f; // percentage along L of sampling for audio
|
||||||
float crossSectionalArea_ = pi * std::pow(radius_, 2.0f); // string cross sectional area, assuming circular
|
float crossSectionalArea_ = pi * std::pow(radius_, 2.0f); // string cross sectional area, assuming circular
|
||||||
@@ -54,6 +54,9 @@ private:
|
|||||||
// f0_ = waveVelocity_ / (2.0f * stringLength_); // fundamental frequency of a non-stiff string
|
// f0_ = waveVelocity_ / (2.0f * stringLength_); // fundamental frequency of a non-stiff string
|
||||||
// f1_ = f0_ * std::sqrt(1.0f + stiffness_); // fundamental frequency of the stiff string
|
// f1_ = f0_ * std::sqrt(1.0f + stiffness_); // fundamental frequency of the stiff string
|
||||||
|
|
||||||
|
uint32_t samplingSteps_ = 1;
|
||||||
|
float phaseTracker_ = 0.0f;
|
||||||
|
|
||||||
float dx_ = L_ / static_cast<float>(segmentCount_);
|
float dx_ = L_ / static_cast<float>(segmentCount_);
|
||||||
float dt_ = 1.0f / sampleRate_;
|
float dt_ = 1.0f / sampleRate_;
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void Synth::process(float* out, size_t nFrames) {
|
|||||||
mix += voices_[j].process(temp);
|
mix += voices_[j].process(temp);
|
||||||
if(j == lowestVoice) triggered = temp;
|
if(j == lowestVoice) triggered = temp;
|
||||||
}
|
}
|
||||||
mix = tanh(mix/4.0f); // prevent clipping
|
mix = tanh(mix); // prevent clipping
|
||||||
|
|
||||||
sampleOut = filter_.biquadProcess(mix);
|
sampleOut = filter_.biquadProcess(mix);
|
||||||
out[2*i] = sampleOut;
|
out[2*i] = sampleOut;
|
||||||
|
|||||||
Reference in New Issue
Block a user