use alaw companding, apply formatting

This commit is contained in:
2025-11-06 10:58:34 +01:00
parent 3b4d069ece
commit a362ab6c91

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "../companding/alaw.h"
#include "../filter/chebyshev.h" #include "../filter/chebyshev.h"
#include "../companding/ulaw.h"
namespace trnr { namespace trnr {
@@ -18,35 +18,33 @@ struct retro_buf_modulation {
double deviation; double deviation;
}; };
// base class for accessing a sample buffer with adjustable samplerate, bitrate and other options. // base class for accessing a sample buffer with adjustable samplerate, bitrate and other
// options.
class retro_buf { class retro_buf {
public: public:
void set_host_samplerate(double _samplerate) { void set_host_samplerate(double _samplerate)
{
m_host_samplerate = _samplerate; m_host_samplerate = _samplerate;
m_imaging_filter_l.set_samplerate(_samplerate); m_imaging_filter_l.set_samplerate(_samplerate);
m_imaging_filter_r.set_samplerate(_samplerate); m_imaging_filter_r.set_samplerate(_samplerate);
} }
void set_buf_samplerate(double _samplerate) { void set_buf_samplerate(double _samplerate) { m_buf_samplerate = _samplerate; }
m_buf_samplerate = _samplerate;
}
void set_buffer_size(size_t _buffer_size) { void set_buffer_size(size_t _buffer_size) { m_buffer_size = _buffer_size; }
m_buffer_size = _buffer_size;
}
void set_channel_count(size_t _channel_count) { void set_channel_count(size_t _channel_count) { m_channel_count = _channel_count; }
m_channel_count = _channel_count;
}
void start_playback() { void start_playback()
{
if (m_modulation.reset || (!m_modulation.reset && m_playback_pos == -1)) { if (m_modulation.reset || (!m_modulation.reset && m_playback_pos == -1)) {
m_playback_pos = (double)m_modulation.start; m_playback_pos = (double)m_modulation.start;
} }
} }
// @return is active // @return is active
bool process_block(double** _outputs, size_t _block_size, retro_buf_modulation _mod) { bool process_block(double** _outputs, size_t _block_size, retro_buf_modulation _mod)
{
m_modulation = _mod; m_modulation = _mod;
@@ -59,12 +57,19 @@ public:
// quantize index // quantize index
double samplerate_divisor = m_host_samplerate / _mod.samplerate; double samplerate_divisor = m_host_samplerate / _mod.samplerate;
size_t quantized_index = static_cast<size_t>(static_cast<size_t>(m_playback_pos / samplerate_divisor) * samplerate_divisor); size_t quantized_index = static_cast<size_t>(
static_cast<size_t>(m_playback_pos / samplerate_divisor) *
samplerate_divisor);
// get sample for each channel // get sample for each channel
output_l = get_sample((size_t)wrap(quantized_index + jitterize(_mod.jitter), m_buffer_size), 0); output_l = get_sample(
(size_t)wrap(quantized_index + jitterize(_mod.jitter), m_buffer_size),
0);
if (m_channel_count > 0) { if (m_channel_count > 0) {
output_r = get_sample((size_t)wrap(quantized_index + jitterize(_mod.jitter), m_buffer_size), 1); output_r =
get_sample((size_t)wrap(quantized_index + jitterize(_mod.jitter),
m_buffer_size),
1);
} else { } else {
output_r = output_l; output_r = output_l;
} }
@@ -76,13 +81,14 @@ public:
reduce_bitrate(output_l, output_r, _mod.bitrate); reduce_bitrate(output_l, output_r, _mod.bitrate);
// calculate imaging filter frequency + deviation // calculate imaging filter frequency + deviation
double filter_frequency = ((_mod.samplerate / 2) * note_ratio) * ((_mod.deviation * 9) + 1); double filter_frequency =
((_mod.samplerate / 2) * note_ratio) * ((_mod.deviation * 9) + 1);
m_imaging_filter_l.process_sample(output_l, filter_frequency); m_imaging_filter_l.process_sample(output_l, filter_frequency);
m_imaging_filter_r.process_sample(output_r, filter_frequency); m_imaging_filter_r.process_sample(output_r, filter_frequency);
} }
// else if loop // else if loop
else if(_mod.looping) { else if (_mod.looping) {
// loop // loop
m_playback_pos = (double)_mod.start; m_playback_pos = (double)_mod.start;
} }
@@ -110,15 +116,16 @@ private:
chebyshev m_imaging_filter_l; chebyshev m_imaging_filter_l;
chebyshev m_imaging_filter_r; chebyshev m_imaging_filter_r;
ulaw m_compander;
retro_buf_modulation m_modulation; retro_buf_modulation m_modulation;
float midi_to_ratio(double midi_note) { float midi_to_ratio(double midi_note)
{
return powf(powf(2, (float)midi_note - 60.f), 1.f / 12.f); return powf(powf(2, (float)midi_note - 60.f), 1.f / 12.f);
} }
template <typename T> template <typename T>
T clamp(T& value, T min, T max) { T clamp(T& value, T min, T max)
{
if (value < min) { if (value < min) {
value = min; value = min;
} else if (value > max) { } else if (value > max) {
@@ -127,14 +134,14 @@ private:
return value; return value;
} }
double wrap(double value, double max) { double wrap(double value, double max)
while (value > max) { {
value -= max; while (value > max) { value -= max; }
}
return value; return value;
} }
int jitterize(int jitter) { int jitterize(int jitter)
{
if (jitter > 0) { if (jitter > 0) {
return static_cast<int>(rand() % jitter); return static_cast<int>(rand() % jitter);
} else { } else {
@@ -142,14 +149,17 @@ private:
} }
} }
void reduce_bitrate(double& value1, double& value2, double bit) { void reduce_bitrate(double& value1, double& value2, double bit)
m_compander.encode_samples(value1, value2); {
value1 = alaw_encode(value1);
value2 = alaw_encode(value2);
float resolution = powf(2, bit); float resolution = powf(2, bit);
value1 = round(value1 * resolution) / resolution; value1 = round(value1 * resolution) / resolution;
value2 = round(value2 * resolution) / resolution; value2 = round(value2 * resolution) / resolution;
m_compander.decode_samples(value1, value2); value1 = alaw_decode(value1);
value2 = alaw_decode(value2);
} }
}; };
} } // namespace trnr