summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2019-02-07 15:00:37 +0100
committerRobin Gareus <robin@gareus.org>2019-02-07 15:28:25 +0100
commit18af4dd55a37e50968320f07d215049b6e6fb69e (patch)
treef6a11acfa702b78c8e3bf75c80dba95802c632e7 /libs/ardour
parent3c96ba1de615d4ef071692ea69ea8b3722913374 (diff)
Prepare dedicated Disk-reader de-click gain-stage
This allows to specify a shorter fade-duration than default Amp::apply_gain(), also allows to unroll and vectorize the loop
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/disk_reader.h21
-rw-r--r--libs/ardour/disk_reader.cc55
2 files changed, 73 insertions, 3 deletions
diff --git a/libs/ardour/ardour/disk_reader.h b/libs/ardour/ardour/disk_reader.h
index a170fba766..91fcf74d2f 100644
--- a/libs/ardour/ardour/disk_reader.h
+++ b/libs/ardour/ardour/disk_reader.h
@@ -94,7 +94,7 @@ public:
void reset_tracker ();
bool declick_in_progress () const {
- return _declick_gain != 0; // declick-out
+ return _declick_amp.gain() != 0; // declick-out
}
static void set_midi_readahead_samples (samplecnt_t samples_ahead) { midi_readahead = samples_ahead; }
@@ -125,6 +125,22 @@ protected:
int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many);
+ class DeclickAmp
+ {
+ public:
+ DeclickAmp (samplecnt_t sample_rate);
+
+ void apply_gain (AudioBuffer& buf, samplecnt_t n_samples, const float target);
+
+ float gain () const { return _g; }
+ void set_gain (float g) { _g = g; }
+
+ private:
+ float _a;
+ float _l;
+ float _g;
+ };
+
private:
/** The number of samples by which this diskstream's output should be delayed
with respect to the transport sample. This is used for latency compensation.
@@ -135,7 +151,8 @@ private:
IOChange input_change_pending;
samplepos_t file_sample[DataType::num_types];
- gain_t _declick_gain;
+ DeclickAmp _declick_amp;
+ sampleoffset_t _declick_offs;
int _do_refill_with_alloc (bool partial_fill);
diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc
index c5ae34d4f2..285db830fe 100644
--- a/libs/ardour/disk_reader.cc
+++ b/libs/ardour/disk_reader.cc
@@ -23,6 +23,7 @@
#include "pbd/memento_command.h"
#include "pbd/playback_buffer.h"
+#include "ardour/amp.h"
#include "ardour/audioengine.h"
#include "ardour/audioplaylist.h"
#include "ardour/audio_buffer.h"
@@ -57,7 +58,8 @@ DiskReader::DiskReader (Session& s, string const & str, DiskIOProcessor::Flag f)
, overwrite_sample (0)
, _pending_overwrite (false)
, overwrite_queued (false)
- , _declick_gain (0)
+ , _declick_amp (s.nominal_sample_rate ())
+ , _declick_offs (0)
{
file_sample[DataType::AUDIO] = 0;
file_sample[DataType::MIDI] = 0;
@@ -1400,3 +1402,54 @@ DiskReader::set_no_disk_output (bool yn)
*/
_no_disk_output = yn;
}
+
+DiskReader::DeclickAmp::DeclickAmp (samplecnt_t sample_rate)
+{
+ _a = 2200.f / (gain_t)sample_rate;
+ _l = -log1p (_a);
+ _g = 0;
+}
+
+void
+DiskReader::DeclickAmp::apply_gain (AudioBuffer& buf, samplecnt_t n_samples, const float target)
+{
+ if (n_samples == 0) {
+ return;
+ }
+ float g = _g;
+
+ if (g == target) {
+ Amp::apply_simple_gain (buf, n_samples, target, 0);
+ return;
+ }
+
+ const float a = _a;
+ Sample* const buffer = buf.data ();
+
+#define MAX_NPROC 16
+ uint32_t remain = n_samples;
+ uint32_t offset = 0;
+ while (remain > 0) {
+ uint32_t n_proc = remain > MAX_NPROC ? MAX_NPROC : remain;
+ for (uint32_t i = 0; i < n_proc; ++i) {
+ buffer[offset + i] *= g;
+ }
+#if 1
+ g += a * (target - g);
+#else /* accurate exponential fade */
+ if (n_proc == MAX_NPROC) {
+ g += a * (target - g);
+ } else {
+ g = target - (target - g) * expf (_l * n_proc / MAX_NPROC);
+ }
+#endif
+ remain -= n_proc;
+ offset += n_proc;
+ }
+
+ if (fabsf (g - target) < /* GAIN_COEFF_DELTA */ 1e-5) {
+ _g = target;
+ } else {
+ _g = g;
+ }
+}