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
This commit is contained in:
Robin Gareus 2019-02-07 15:00:37 +01:00
parent 3c96ba1de6
commit 18af4dd55a
No known key found for this signature in database
GPG key ID: A090BCE02CF57F04
2 changed files with 73 additions and 3 deletions

View file

@ -94,7 +94,7 @@ public:
void reset_tracker (); void reset_tracker ();
bool declick_in_progress () const { 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; } 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); 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: private:
/** The number of samples by which this diskstream's output should be delayed /** 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. with respect to the transport sample. This is used for latency compensation.
@ -135,7 +151,8 @@ private:
IOChange input_change_pending; IOChange input_change_pending;
samplepos_t file_sample[DataType::num_types]; 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); int _do_refill_with_alloc (bool partial_fill);

View file

@ -23,6 +23,7 @@
#include "pbd/memento_command.h" #include "pbd/memento_command.h"
#include "pbd/playback_buffer.h" #include "pbd/playback_buffer.h"
#include "ardour/amp.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/audioplaylist.h" #include "ardour/audioplaylist.h"
#include "ardour/audio_buffer.h" #include "ardour/audio_buffer.h"
@ -57,7 +58,8 @@ DiskReader::DiskReader (Session& s, string const & str, DiskIOProcessor::Flag f)
, overwrite_sample (0) , overwrite_sample (0)
, _pending_overwrite (false) , _pending_overwrite (false)
, overwrite_queued (false) , overwrite_queued (false)
, _declick_gain (0) , _declick_amp (s.nominal_sample_rate ())
, _declick_offs (0)
{ {
file_sample[DataType::AUDIO] = 0; file_sample[DataType::AUDIO] = 0;
file_sample[DataType::MIDI] = 0; file_sample[DataType::MIDI] = 0;
@ -1400,3 +1402,54 @@ DiskReader::set_no_disk_output (bool yn)
*/ */
_no_disk_output = 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;
}
}