From 26fb50d1a9fe267595cde380b67c8c4c3003f3c8 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 27 Sep 2024 15:58:52 -0600 Subject: [PATCH] a bit more type-safety when handling audio data during clip recording --- libs/ardour/ardour/triggerbox.h | 45 +++++++++++++++++++++++++++------ libs/ardour/triggerbox.cc | 25 ++++++++++++------ 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 108c3f7b9a..0b8552e5b0 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -549,6 +549,41 @@ class LIBARDOUR_API AudioTrigger : public Trigger { uint32_t channels () const { return data.size(); } RubberBand::RubberBandStretcher* alloc_stretcher () const; + + struct AudioData : std::vector { + samplecnt_t length; + samplecnt_t capacity; + + AudioData () : length (0), capacity (0) {} + + samplecnt_t append (Sample const * src, samplecnt_t cnt, uint32_t chan) { + if (chan >= size()) { + return -1; + } + if (length + cnt >= capacity) { + return -1; + } + samplecnt_t to_copy = std::min (cnt, (capacity - length)); + memcpy (at(chan), src, cnt * sizeof (Sample)); + return to_copy; + } + + samplecnt_t read (Sample * dst, samplecnt_t offset, samplecnt_t cnt, uint32_t chan) { + if (chan >= size()) { + return -1; + } + if (offset + cnt > length) { + return -1; + } + samplecnt_t to_copy = std::min (cnt, (length - (offset + cnt))); + memcpy (dst, at (chan) + offset, to_copy * sizeof (Sample)); + return to_copy; + } + + void alloc (samplecnt_t cnt, uint32_t nchans); + }; + + Sample const * audio_data (size_t n) const; size_t data_length() const { return data.length; } @@ -556,13 +591,7 @@ class LIBARDOUR_API AudioTrigger : public Trigger { void retrigger (); private: - struct Data : std::vector { - samplecnt_t length; - - Data () : length (0) {} - }; - - Data data; + AudioData data; RubberBand::RubberBandStretcher* _stretcher; samplepos_t _start_offset; @@ -770,7 +799,7 @@ struct SlotArmInfo { samplecnt_t capture_length; RTMidiBuffer* midi_buf; /* assumed large enough */ RTMidiBufferBeats* beats; /* will take over data allocated for midi_but */ - std::vector audio_buf; /* assumed large enough */ + AudioTrigger::AudioData audio_buf; RubberBand::RubberBandStretcher* stretcher; }; diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index f0a9e8ec4e..8e8e1eb02b 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -1281,6 +1281,19 @@ Trigger::start_and_roll_to (samplepos_t start_pos, samplepos_t end_position, Tri /*--------------------*/ +void +AudioTrigger::AudioData::alloc (samplecnt_t cnt, uint32_t nchans) +{ + clear (); + reserve (nchans); + for (uint32_t n = 0; n < nchans; ++n) { + push_back (new Sample[cnt]); + } + length = 0; + capacity = cnt; + +} + AudioTrigger::AudioTrigger (uint32_t n, TriggerBox& b) : Trigger (n, b) , _stretcher (0) @@ -1910,8 +1923,9 @@ AudioTrigger::load_data (std::shared_ptr ar) drop_data (); try { + data.alloc (data.length, nchans); + for (uint32_t n = 0; n < nchans; ++n) { - data.push_back (new Sample[data.length]); ar->read (data[n], 0, data.length, n); } @@ -3490,9 +3504,7 @@ TriggerBox::arm_from_another_thread (Trigger& slot, samplepos_t now, uint32_t ch ai->midi_buf->resize (1024); // XXX Config->max_slot_midi_event_size ai->beats = new RTMidiBufferBeats; } else { - for (uint32_t n = 0; n < chans; ++n) { - ai->audio_buf.push_back (new Sample[_session.sample_rate() * 30]); // XXX Config->max_slot_audio_duration - } + ai->audio_buf.alloc (_session.sample_rate() * 30, chans); // XXX Config->max_slot_audio_duration AudioTrigger* at = dynamic_cast (&slot); assert (at); ai->stretcher = at->alloc_stretcher (); @@ -3620,7 +3632,7 @@ TriggerBox::maybe_capture (BufferSet& bufs, samplepos_t start_sample, samplepos_ for (size_t n = 0; n < n_buffers; ++n) { assert (ai->audio_buf.size() >= n); AudioBuffer& buf (bufs.get_audio (n%n_buffers)); - memcpy (ai->audio_buf[n], buf.data() + offset, sizeof (Sample) * nframes); + ai->audio_buf.append (buf.data() + offset, nframes, n); } /* This count is used only for audio */ @@ -5583,10 +5595,7 @@ TriggerBoxThread::build_audio_source (AudioTrigger* t) size_t n = 0; for (auto & src : sources) { - Source::WriterLock lock (src->mutex()); - src->mark_streaming_write_started (lock); std::dynamic_pointer_cast(src)->write (t->audio_data (n), t->data_length()); - src->mark_streaming_write_completed (lock); ++n; }