LCOV - code coverage report
Current view: top level - src/audio/recorder - recorder.h (source / functions) Coverage Total Hit
Test: merged.info Lines: 100.0 % 6 6
Test Date: 2026-06-01 11:15:25 Functions: 100.0 % 6 6

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include "common.h"
       4              : #include <fstream>
       5              : #include <chrono>
       6              : #include <array>
       7              : #include <thread>
       8              : 
       9              : namespace Amplitron {
      10              : 
      11              : class AudioEngine;
      12              : 
      13              : class Recorder {
      14              : public:
      15              :     static constexpr int WAVEFORM_SIZE = 512;
      16              : 
      17              :     Recorder();
      18              :     ~Recorder();
      19              : 
      20              :     // Start recording to a temporary WAV file
      21              :     bool start(const std::string& filepath, int sample_rate, int channels = 1);
      22              : 
      23              :     // Stop recording and finalize the WAV file
      24              :     void stop();
      25              : 
      26              :     // Pause / resume recording
      27              :     void pause();
      28              :     void resume();
      29              : 
      30              :     // Write audio samples (called from audio callback)
      31              :     void write_samples(const float* buffer, int num_samples);
      32              : 
      33              :     void write_samples_stereo(const float* left, const float* right, int num_samples);
      34              : 
      35              :     // Write metadata JSON sidecar file
      36              :     void write_metadata(const std::string& wav_path, AudioEngine& engine);
      37              : 
      38              :     // Move the recorded temp file to a user-chosen path
      39              :     bool save_to(const std::string& dest_path);
      40              : 
      41              :     // Discard the recorded temp file
      42              :     void discard();
      43              : 
      44         4808 :     bool is_recording() const { return recording_.load(); }
      45           18 :     bool is_paused() const { return paused_.load(); }
      46           21 :     bool has_unsaved() const { return has_unsaved_.load(); }
      47              :     float get_duration() const;
      48           52 :     int64_t get_samples_written() const { return samples_written_.load(); }
      49            9 :     int get_channels() const { return channels_; }
      50              :     const std::string& filepath() const { return filepath_; }
      51              : 
      52              :     // Waveform visualization data (lock-free ring buffer of peak values)
      53              :     void get_waveform(float* out, int count) const;
      54           15 :     float get_current_peak() const { return current_peak_.load(); }
      55              : 
      56              :     // Get default recordings directory
      57              :     static std::string get_recordings_dir();
      58              : 
      59              :     // Generate a timestamped filename
      60              :     static std::string generate_filename();
      61              : 
      62              : private:
      63              :     std::ofstream file_;
      64              :     std::atomic<bool> recording_{false};
      65              :     std::atomic<bool> paused_{false};
      66              :     std::atomic<bool> has_unsaved_{false};
      67              :     std::atomic<int64_t> samples_written_{0};
      68              :     int sample_rate_ = 48000;
      69              :     int channels_ = 1;
      70              :     std::string filepath_;
      71              : 
      72              :     std::chrono::steady_clock::time_point start_time_;
      73              :     float pause_duration_ = 0.0f;  // GUI thread only (accessed from pause/resume)
      74              :     std::chrono::steady_clock::time_point pause_start_;
      75              : 
      76              :     // Waveform ring buffer (written from audio thread, read from UI thread)
      77              :     std::array<std::atomic<float>, WAVEFORM_SIZE> waveform_buf_;
      78              :     std::atomic<int> waveform_write_pos_{0};
      79              :     std::atomic<float> current_peak_{0.0f};
      80              :     int samples_per_bin_ = 0;
      81              :     int bin_sample_count_ = 0;
      82              :     float bin_peak_ = 0.0f;
      83              : 
      84              :     // WAV header helpers
      85              :     void write_wav_header();
      86              :     void finalize_wav_header();
      87              : 
      88              :     // Lock-free ring buffer for real-time audio thread -> disk writer thread
      89              :     static constexpr int RING_BUFFER_SIZE = 48000 * 4;
      90              :     std::vector<float> ring_buffer_;
      91              :     std::atomic<int64_t> ring_write_pos_{0};
      92              :     std::atomic<int64_t> ring_read_pos_{0};
      93              : 
      94              :     // Disk writer thread (keeps file I/O off the real-time audio thread)
      95              :     std::thread writer_thread_;
      96              :     std::atomic<bool> writer_running_{false};
      97              :     std::vector<int16_t> pcm_buffer_;
      98              : 
      99              :     void writer_thread_func();
     100              : };
     101              : 
     102              : } // namespace Amplitron
        

Generated by: LCOV version 2.0-1