Audio fixes: gain() DSP effect, sfxr phase wrap, SDL2 backend compat

- SoundBuffer.gain(factor): new DSP method for amplitude scaling before
  mixing (0.5 = half volume, 2.0 = double, clamped to int16 range)
- Fix sfxr square/saw waveform artifacts: phase now wraps at period
  boundary instead of growing unbounded; noise buffer refreshes per period
- Fix PySound construction from SoundBuffer on SDL2 backend: use
  loadFromSamples() directly instead of copy-assign (deleted on SDL2)
- Add Image::create(w, h, pixels) overload to HeadlessTypes and
  SDL2Types for pixel data initialization
- Waveform test suite (62 lines)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
John McCardle 2026-02-20 23:17:41 -05:00
commit 732897426a
9 changed files with 125 additions and 1 deletions

View file

@ -289,6 +289,21 @@ std::vector<int16_t> normalize(const std::vector<int16_t>& samples) {
return result;
}
// ============================================================================
// Gain (multiply all samples by scalar factor)
// ============================================================================
std::vector<int16_t> gain(const std::vector<int16_t>& samples, double factor) {
if (samples.empty()) return samples;
std::vector<int16_t> result(samples.size());
for (size_t i = 0; i < samples.size(); i++) {
double s = samples[i] * factor;
result[i] = static_cast<int16_t>(std::max(-32768.0, std::min(32767.0, s)));
}
return result;
}
// ============================================================================
// Reverse (frame-aware for multichannel)
// ============================================================================