13
0

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
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 73 additions and 3 deletions

View File

@ -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);

View File

@ -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;
}
}