]> git.sesse.net Git - nageru/blobdiff - nageru/audio_mixer.h
Support delaying audio sources selectively.
[nageru] / nageru / audio_mixer.h
index a7ab9a5a0d60378e632fbd34a7105865c05b0ef0..de6ff5414032a7f414d82b7195156c2921400a7c 100644 (file)
@@ -37,6 +37,10 @@ namespace bmusb {
 struct AudioFormat;
 }  // namespace bmusb
 
+// Convert the given audio from {16,24,32}-bit M-channel to 32-bit N-channel PCM.
+// Assumes little-endian and chunky, signed PCM throughout.
+std::vector<int32_t> convert_audio_to_fixed32(const uint8_t *data, unsigned num_samples, bmusb::AudioFormat audio_format, unsigned num_destination_channels);
+
 enum EQBand {
        EQ_BAND_BASS = 0,
        EQ_BAND_MID,
@@ -54,9 +58,9 @@ public:
        // the lock wasn't successfully taken; if so, you should simply try again.
        // (This is to avoid a deadlock where a card hangs on the mutex in add_audio()
        // while we are trying to shut it down from another thread that also holds
-       // the mutex.) frame_length is in TIMEBASE units.
-       bool add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, bmusb::AudioFormat audio_format, int64_t frame_length, std::chrono::steady_clock::time_point frame_time);
-       bool add_silence(DeviceSpec device_spec, unsigned samples_per_frame, unsigned num_frames, int64_t frame_length);
+       // the mutex.)
+       bool add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, bmusb::AudioFormat audio_format, std::chrono::steady_clock::time_point frame_time);
+       bool add_silence(DeviceSpec device_spec, unsigned samples_per_frame, unsigned num_frames);
 
        // If a given device is offline for whatever reason and cannot deliver audio
        // (by means of add_audio() or add_silence()), you can call put it in silence mode,
@@ -208,51 +212,51 @@ public:
 
        void set_gain_staging_db(unsigned bus_index, float gain_db)
        {
-               std::unique_lock<std::mutex> lock(compressor_mutex);
+               std::lock_guard<std::mutex> lock(compressor_mutex);
                level_compressor_enabled[bus_index] = false;
                gain_staging_db[bus_index] = gain_db;
        }
 
        float get_gain_staging_db(unsigned bus_index) const
        {
-               std::unique_lock<std::mutex> lock(compressor_mutex);
+               std::lock_guard<std::mutex> lock(compressor_mutex);
                return gain_staging_db[bus_index];
        }
 
        void set_gain_staging_auto(unsigned bus_index, bool enabled)
        {
-               std::unique_lock<std::mutex> lock(compressor_mutex);
+               std::lock_guard<std::mutex> lock(compressor_mutex);
                level_compressor_enabled[bus_index] = enabled;
        }
 
        bool get_gain_staging_auto(unsigned bus_index) const
        {
-               std::unique_lock<std::mutex> lock(compressor_mutex);
+               std::lock_guard<std::mutex> lock(compressor_mutex);
                return level_compressor_enabled[bus_index];
        }
 
        void set_final_makeup_gain_db(float gain_db)
        {
-               std::unique_lock<std::mutex> lock(compressor_mutex);
+               std::lock_guard<std::mutex> lock(compressor_mutex);
                final_makeup_gain_auto = false;
                final_makeup_gain = from_db(gain_db);
        }
 
        float get_final_makeup_gain_db()
        {
-               std::unique_lock<std::mutex> lock(compressor_mutex);
+               std::lock_guard<std::mutex> lock(compressor_mutex);
                return to_db(final_makeup_gain);
        }
 
        void set_final_makeup_gain_auto(bool enabled)
        {
-               std::unique_lock<std::mutex> lock(compressor_mutex);
+               std::lock_guard<std::mutex> lock(compressor_mutex);
                final_makeup_gain_auto = enabled;
        }
 
        bool get_final_makeup_gain_auto() const
        {
-               std::unique_lock<std::mutex> lock(compressor_mutex);
+               std::lock_guard<std::mutex> lock(compressor_mutex);
                return final_makeup_gain_auto;
        }
 
@@ -320,6 +324,10 @@ private:
                // Which channels we consider interesting (ie., are part of some input_mapping).
                std::set<unsigned> interesting_channels;
                bool silenced = false;
+
+               // Positive means the audio is delayed, negative means we try to have it earlier
+               // (although we can't time-travel!). Stored together with the input mapping.
+               double extra_delay_ms = 0.0;
        };
 
        const AudioDevice *find_audio_device(DeviceSpec device_spec) const