Skip to content

Commit 4f987e3

Browse files
committed
Improve PianoSynth acoustic realism
- Add decaying noise burst to KS excitation, seeded by note for consistency. Models brief hammer-felt impact transient before the tonal string response settles. - Double note-dependent brightness range (0.3 → 0.6) for more dramatic bass/treble contrast across the keyboard. - Reduce default string detune from 0.3 (4.5 cents) to 0.1 (1.5 cents); tighter unison is closer to a well-tuned acoustic piano rather than EP-style chorus.
1 parent f0702f0 commit 4f987e3

3 files changed

Lines changed: 13 additions & 4 deletions

File tree

src/domain/devices/piano_synth_device.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ PianoSynthDevice::PianoSynthDevice(std::string name)
4242
addParameter(Parameter(Constants::NahdXml::xmlKeyReleaseTime().toStdString(), 0.3f, 0, 10000, 3000, 100));
4343
addParameter(Parameter(Constants::NahdXml::xmlKeyPanSpread().toStdString(), 0.7f, 0, 10000, 7000, 100));
4444
addParameter(Parameter(Constants::NahdXml::xmlKeyHardness().toStdString(), 0.5f, 0, 10000, 5000, 100));
45-
addParameter(Parameter(Constants::NahdXml::xmlKeyStringDetune().toStdString(), 0.3f, 0, 10000, 3000, 100));
45+
addParameter(Parameter(Constants::NahdXml::xmlKeyStringDetune().toStdString(), 0.1f, 0, 10000, 1000, 100));
4646

4747
PianoSynthDevice::syncParameters();
4848
}
@@ -283,8 +283,8 @@ void PianoSynthDevice::handleNoteOn(uint8_t note, uint8_t velocity)
283283
{
284284
const float vel = static_cast<float>(velocity) / 127.0f;
285285
const float velBright = vel * m_hammerHardness;
286-
// Higher notes are naturally brighter; shift brightness by ±0.15 across the keyboard.
287-
const float noteBrightOffset = (static_cast<float>(note) - 60.0f) / 127.0f * 0.3f;
286+
// Higher notes are naturally brighter; shift brightness by ±0.24 across the keyboard.
287+
const float noteBrightOffset = (static_cast<float>(note) - 60.0f) / 127.0f * 0.6f;
288288
const float effectiveBright = std::clamp(m_brightness + velBright + noteBrightOffset, 0.0f, 1.0f);
289289
// Detuning in cents for the second string (0–15 cents).
290290
const double detuneCents = static_cast<double>(m_stringDetune) * 15.0;

src/domain/devices/piano_synth_device.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class PianoSynthDevice : public Device
104104
float m_releaseTime { 0.3f };
105105
float m_stereoWidth { 0.7f };
106106
float m_hammerHardness { 0.5f };
107-
float m_stringDetune { 0.3f };
107+
float m_stringDetune { 0.1f };
108108

109109
void handleNoteOn(uint8_t note, uint8_t velocity);
110110
void handleNoteOff(uint8_t note);

src/domain/dsp/waveguide_string.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <algorithm>
1919
#include <cmath>
2020
#include <numbers>
21+
#include <random>
2122

2223
namespace noteahead {
2324

@@ -73,6 +74,13 @@ void WaveguideString::trigger(uint8_t note, float velocity, float brightness, fl
7374
const size_t width = std::max(size_t { 1 }, N / std::max(size_t { 1 }, static_cast<size_t>(2.0 + static_cast<double>(velocity) * 6.0)));
7475
const double amplitude = static_cast<double>(velocity) * 0.5;
7576

77+
// Noise burst seeded by note so repeated strikes are consistent but each pitch differs.
78+
// Decays in ~N/6 samples to model brief hammer-felt impact noise before the tone settles.
79+
std::minstd_rand rng { static_cast<uint32_t>(note) + 17u };
80+
std::uniform_real_distribution<double> noiseDist { -1.0, 1.0 };
81+
const double noiseGain = static_cast<double>(velocity) * 0.08;
82+
const double noiseDecay = 6.0 / static_cast<double>(N);
83+
7684
// Pre-load excitation into the delay buffer so output starts immediately.
7785
m_delay.reset();
7886
for (size_t i = 0; i < N; i++) {
@@ -81,6 +89,7 @@ void WaveguideString::trigger(uint8_t note, float velocity, float brightness, fl
8189
const double t = static_cast<double>(i) / static_cast<double>(width);
8290
excite = amplitude * 0.5 * (1.0 - std::cos(2.0 * std::numbers::pi * t));
8391
}
92+
excite += noiseDist(rng) * noiseGain * std::exp(-noiseDecay * static_cast<double>(i));
8493
m_delay.write(excite);
8594
}
8695

0 commit comments

Comments
 (0)