summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio/wav_dump_backend.cc27
-rw-r--r--src/audio/wav_dump_backend.h6
-rw-r--r--src/tests/test_wav_dump.cc49
3 files changed, 76 insertions, 6 deletions
diff --git a/src/audio/wav_dump_backend.cc b/src/audio/wav_dump_backend.cc
index eda835c..82803a2 100644
--- a/src/audio/wav_dump_backend.cc
+++ b/src/audio/wav_dump_backend.cc
@@ -10,7 +10,7 @@
#include <string.h>
WavDumpBackend::WavDumpBackend()
- : wav_file_(nullptr), samples_written_(0),
+ : wav_file_(nullptr), samples_written_(0), clipped_samples_(0),
output_filename_("audio_dump.wav"), is_active_(false),
duration_sec_(0.0f) {
sample_buffer_.resize(kBufferSize);
@@ -36,6 +36,7 @@ void WavDumpBackend::init() {
write_wav_header(wav_file_, 0);
samples_written_ = 0;
+ clipped_samples_ = 0;
printf("WAV dump backend initialized: %s\n", output_filename_);
}
@@ -50,15 +51,18 @@ void WavDumpBackend::write_audio(const float* samples, int num_samples) {
}
// Convert float samples to int16 and write to WAV
+ // Note: We do NOT clamp samples (matches MiniaudioBackend behavior)
+ // Instead, we count samples that would clip during int16 conversion
for (int i = 0; i < num_samples; ++i) {
float sample = samples[i];
- // Clamp to [-1.0, 1.0]
- if (sample > 1.0f)
- sample = 1.0f;
- if (sample < -1.0f)
- sample = -1.0f;
+ // Track clipping for diagnostics (but don't prevent it)
+ if (sample > 1.0f || sample < -1.0f) {
+ clipped_samples_++;
+ }
+ // Convert to int16 (allows overflow for diagnostic purposes)
+ // This matches hardware behavior where clipping occurs in the DAC
const int16_t sample_i16 = (int16_t)(sample * 32767.0f);
fwrite(&sample_i16, sizeof(int16_t), 1, wav_file_);
}
@@ -76,6 +80,17 @@ void WavDumpBackend::shutdown() {
const float duration_sec = (float)samples_written_ / (kSampleRate * 2);
printf("WAV file written: %s (%.2f seconds, %zu samples)\n",
output_filename_, duration_sec, samples_written_);
+
+ // Report clipping diagnostics
+ if (clipped_samples_ > 0) {
+ const float clip_percent =
+ (float)clipped_samples_ / (float)samples_written_ * 100.0f;
+ printf(" WARNING: %zu samples clipped (%.2f%% of total)\n",
+ clipped_samples_, clip_percent);
+ printf(" This indicates audio distortion - consider reducing volume\n");
+ } else {
+ printf(" āœ“ No clipping detected\n");
+ }
}
is_active_ = false;
diff --git a/src/audio/wav_dump_backend.h b/src/audio/wav_dump_backend.h
index 6482ef3..c3c5302 100644
--- a/src/audio/wav_dump_backend.h
+++ b/src/audio/wav_dump_backend.h
@@ -35,6 +35,11 @@ class WavDumpBackend : public AudioBackend {
return samples_written_;
}
+ // Get number of samples that were clipped (diagnostic metric)
+ size_t get_clipped_samples() const {
+ return clipped_samples_;
+ }
+
private:
// Write WAV header with known sample count
void write_wav_header(FILE* file, uint32_t num_samples);
@@ -45,6 +50,7 @@ class WavDumpBackend : public AudioBackend {
FILE* wav_file_;
std::vector<float> sample_buffer_;
size_t samples_written_;
+ size_t clipped_samples_;
const char* output_filename_;
bool is_active_;
float duration_sec_;
diff --git a/src/tests/test_wav_dump.cc b/src/tests/test_wav_dump.cc
index cc2de19..aa195cc 100644
--- a/src/tests/test_wav_dump.cc
+++ b/src/tests/test_wav_dump.cc
@@ -190,6 +190,54 @@ void test_wav_stereo_buffer_size() {
printf(" āœ“ Buffer size calculations correct for stereo\n");
}
+void test_clipping_detection() {
+ printf("Test: Clipping detection and reporting...\n");
+
+ const char* test_file = "test_clipping.wav";
+
+ audio_init();
+ AudioEngine engine;
+ engine.init();
+
+ WavDumpBackend wav_backend;
+ wav_backend.set_output_file(test_file);
+ wav_backend.init();
+ wav_backend.start();
+
+ // Create test samples with intentional clipping
+ const int num_samples = 1000;
+ float test_samples[1000];
+
+ // Mix of normal and clipped samples
+ for (int i = 0; i < num_samples; ++i) {
+ if (i % 10 == 0) {
+ test_samples[i] = 1.5f; // Clipped high
+ } else if (i % 10 == 1) {
+ test_samples[i] = -1.2f; // Clipped low
+ } else {
+ test_samples[i] = 0.5f; // Normal
+ }
+ }
+
+ // Write samples
+ wav_backend.write_audio(test_samples, num_samples);
+
+ // Verify clipping was detected (20% of samples should be clipped)
+ const size_t clipped = wav_backend.get_clipped_samples();
+ assert(clipped == 200); // 10% + 10% = 20% of 1000
+
+ printf(" Detected %zu clipped samples (expected 200)\n", clipped);
+
+ wav_backend.shutdown();
+ engine.shutdown();
+ audio_shutdown();
+
+ // Clean up
+ remove(test_file);
+
+ printf(" āœ“ Clipping detection works correctly\n");
+}
+
#endif /* !defined(STRIP_ALL) */
int main() {
@@ -197,6 +245,7 @@ int main() {
printf("Running WAV Dump Backend tests...\n\n");
test_wav_format_matches_live_audio();
test_wav_stereo_buffer_size();
+ test_clipping_detection();
printf("\nāœ… All WAV Dump tests PASSED\n");
return 0;
#else