Skip to content

Commit

Permalink
Merge branch 'move-morphing-to-utils'
Browse files Browse the repository at this point in the history
* move-morphing-to-utils:
  LIB: MorphUtils: cleanup MorphUtils API a bit more
  LIB: MorphUtils: remove some function from public API
  LIB: move merge morph() function into MorphUtils::morph()
  LIB: MorphLinearModule: cleanup morph() function
  LIB: MorphLinearModule: move special cases handling in morph() function
  LIB: MorphLinearModule: move morphing into morph() function
  LIB: move morph_scale function to MorphUtils
  LIB: move interp_mag_one to MorphUtils
  LIB: MorphLinearModule: use optimized db linear morphing
  LIB: move linear/grid morph mag data initialization to MorphUtils
  LIB: MagData: move struct to MorphUtils

Signed-off-by: Stefan Westerfeld <[email protected]>
  • Loading branch information
swesterfeld committed Jan 19, 2024
2 parents e232af4 + 69ee659 commit 972e58a
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 441 deletions.
206 changes: 6 additions & 200 deletions lib/smmorphgridmodule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,201 +114,6 @@ get_normalized_block (MorphGridModule::InputNode& input_node, size_t index, RTAu
return MorphUtils::get_normalized_block (source, time_ms, out_audio_block);
}

namespace
{
struct MagData
{
enum {
BLOCK_LEFT = 0,
BLOCK_RIGHT = 1
} block;
size_t index;
uint16_t mag;
};

static bool
md_cmp (const MagData& m1, const MagData& m2)
{
return m1.mag > m2.mag; // sort with biggest magnitude first
}

static void
interp_mag_one (double interp, uint16_t *left, uint16_t *right)
{
const uint16_t lmag_idb = max<uint16_t> (left ? *left : 0, SM_IDB_CONST_M96);
const uint16_t rmag_idb = max<uint16_t> (right ? *right : 0, SM_IDB_CONST_M96);

const uint16_t mag_idb = sm_round_positive ((1 - interp) * lmag_idb + interp * rmag_idb);

if (left)
*left = mag_idb;
if (right)
*right = mag_idb;
}

static void
morph_scale (RTAudioBlock& out_block, const RTAudioBlock& in_block, double factor)
{
const int ddb = sm_factor2delta_idb (factor);

out_block.assign (in_block);
for (size_t i = 0; i < out_block.noise.size(); i++)
out_block.noise[i] = sm_bound<int> (0, out_block.noise[i] + ddb, 65535);

for (size_t i = 0; i < out_block.freqs.size(); i++)
interp_mag_one (factor, NULL, &out_block.mags[i]);
}

}

static bool
morph (RTAudioBlock& out_block,
bool have_left, const RTAudioBlock& left_block,
bool have_right, const RTAudioBlock& right_block,
double morphing)
{
const double interp = (morphing + 1) / 2; /* examples => 0: only left; 0.5 both equally; 1: only right */

if (!have_left && !have_right) // nothing + nothing = nothing
return false;

if (!have_left) // nothing + interp * right = interp * right
{
morph_scale (out_block, right_block, interp);
return true;
}
if (!have_right) // (1 - interp) * left + nothing = (1 - interp) * left
{
morph_scale (out_block, left_block, 1 - interp);
return true;
}

// set out_block capacity
const size_t max_partials = left_block.freqs.size() + right_block.freqs.size();
out_block.freqs.set_capacity (max_partials);
out_block.mags.set_capacity (max_partials);

// FIXME: lpc stuff
MagData mds[max_partials + AVOID_ARRAY_UB];
size_t mds_size = 0;
for (size_t i = 0; i < left_block.freqs.size(); i++)
{
MagData& md = mds[mds_size];

md.block = MagData::BLOCK_LEFT;
md.index = i;
md.mag = left_block.mags[i];
mds_size++;
}
for (size_t i = 0; i < right_block.freqs.size(); i++)
{
MagData& md = mds[mds_size];

md.block = MagData::BLOCK_RIGHT;
md.index = i;
md.mag = right_block.mags[i];
mds_size++;
}
sort (mds, mds + mds_size, md_cmp);

size_t left_freqs_size = left_block.freqs.size();
size_t right_freqs_size = right_block.freqs.size();

MorphUtils::FreqState left_freqs[left_freqs_size + AVOID_ARRAY_UB];
MorphUtils::FreqState right_freqs[right_freqs_size + AVOID_ARRAY_UB];

init_freq_state (left_block.freqs, left_freqs);
init_freq_state (right_block.freqs, right_freqs);

for (size_t m = 0; m < mds_size; m++)
{
size_t i, j;
bool match = false;
if (mds[m].block == MagData::BLOCK_LEFT)
{
i = mds[m].index;

if (!left_freqs[i].used)
match = MorphUtils::find_match (left_freqs[i].freq_f, right_freqs, right_freqs_size, &j);
}
else // (mds[m].block == MagData::BLOCK_RIGHT)
{
j = mds[m].index;
if (!right_freqs[j].used)
match = MorphUtils::find_match (right_freqs[j].freq_f, left_freqs, left_freqs_size, &i);
}
if (match)
{
/* prefer frequency of louder partial:
*
* if the magnitudes are similar, mfact will be close to 1, and freq will become approx.
*
* freq = (1 - interp) * lfreq + interp * rfreq
*
* if the magnitudes are very different, mfact will be close to 0, and freq will become
*
* freq ~= lfreq // if left partial is louder
* freq ~= rfreq // if right partial is louder
*/
const double lfreq = left_block.freqs[i];
const double rfreq = right_block.freqs[j];
double freq;

if (left_block.mags[i] > right_block.mags[j])
{
const double mfact = right_block.mags_f (j) / left_block.mags_f (i);

freq = lfreq + mfact * interp * (rfreq - lfreq);
}
else
{
const double mfact = left_block.mags_f (i) / right_block.mags_f (j);

freq = rfreq + mfact * (1 - interp) * (lfreq - rfreq);
}
// FIXME: lpc
// FIXME: non-db

const uint16_t lmag_idb = max (left_block.mags[i], SM_IDB_CONST_M96);
const uint16_t rmag_idb = max (right_block.mags[j], SM_IDB_CONST_M96);
const uint16_t mag_idb = sm_round_positive ((1 - interp) * lmag_idb + interp * rmag_idb);

out_block.freqs.push_back (freq);
out_block.mags.push_back (mag_idb);

left_freqs[i].used = 1;
right_freqs[j].used = 1;
}
}
for (size_t i = 0; i < left_freqs_size; i++)
{
if (!left_freqs[i].used)
{
out_block.freqs.push_back (left_block.freqs[i]);
out_block.mags.push_back (left_block.mags[i]);

interp_mag_one (interp, &out_block.mags.back(), NULL);
}
}
for (size_t i = 0; i < right_freqs_size; i++)
{
if (!right_freqs[i].used)
{
out_block.freqs.push_back (right_block.freqs[i]);
out_block.mags.push_back (right_block.mags[i]);

interp_mag_one (interp, NULL, &out_block.mags.back());
}
}
out_block.noise.set_capacity (left_block.noise.size());
for (size_t i = 0; i < left_block.noise.size(); i++)
out_block.noise.push_back (sm_factor2idb ((1 - interp) * left_block.noise_f (i) + interp * right_block.noise_f (i)));

out_block.sort_freqs();
return true;
}


namespace
{

Expand Down Expand Up @@ -364,6 +169,7 @@ MorphGridModule::MySource::rt_audio_block (size_t index, RTAudioBlock& out_block
{
const double x_morphing = module->apply_modulation (module->cfg->x_morphing_mod);
const double y_morphing = module->apply_modulation (module->cfg->y_morphing_mod);
const MorphUtils::MorphMode morph_mode = MorphUtils::MorphMode::DB_LINEAR;

const LocalMorphParams x_morph_params = global_to_local_params (x_morphing, module->cfg->width);
const LocalMorphParams y_morph_params = global_to_local_params (y_morphing, module->cfg->height);
Expand All @@ -383,7 +189,7 @@ MorphGridModule::MySource::rt_audio_block (size_t index, RTAudioBlock& out_block
bool have_a = get_normalized_block (node_a, index, audio_block_a);
bool have_b = get_normalized_block (node_b, index, audio_block_b);

bool have_ab = morph (out_block, have_a, audio_block_a, have_b, audio_block_b, x_morph_params.morphing);
bool have_ab = MorphUtils::morph (out_block, have_a, audio_block_a, have_b, audio_block_b, x_morph_params.morphing, morph_mode);
if (have_ab)
{
double delta_db = morph_delta_db (node_a.delta_db, node_b.delta_db, x_morph_params.morphing);
Expand Down Expand Up @@ -414,7 +220,7 @@ MorphGridModule::MySource::rt_audio_block (size_t index, RTAudioBlock& out_block
bool have_a = get_normalized_block (node_a, index, audio_block_a);
bool have_b = get_normalized_block (node_b, index, audio_block_b);

bool have_ab = morph (out_block, have_a, audio_block_a, have_b, audio_block_b, y_morph_params.morphing);
bool have_ab = MorphUtils::morph (out_block, have_a, audio_block_a, have_b, audio_block_b, y_morph_params.morphing, morph_mode);
if (have_ab)
{
double delta_db = morph_delta_db (node_a.delta_db, node_b.delta_db, y_morph_params.morphing);
Expand Down Expand Up @@ -452,9 +258,9 @@ MorphGridModule::MySource::rt_audio_block (size_t index, RTAudioBlock& out_block
bool have_c = get_normalized_block (node_c, index, audio_block_c);
bool have_d = get_normalized_block (node_d, index, audio_block_d);

bool have_ab = morph (audio_block_ab, have_a, audio_block_a, have_b, audio_block_b, x_morph_params.morphing);
bool have_cd = morph (audio_block_cd, have_c, audio_block_c, have_d, audio_block_d, x_morph_params.morphing);
bool have_abcd = morph (out_block, have_ab, audio_block_ab, have_cd, audio_block_cd, y_morph_params.morphing);
bool have_ab = MorphUtils::morph (audio_block_ab, have_a, audio_block_a, have_b, audio_block_b, x_morph_params.morphing, morph_mode);
bool have_cd = MorphUtils::morph (audio_block_cd, have_c, audio_block_c, have_d, audio_block_d, x_morph_params.morphing, morph_mode);
bool have_abcd = MorphUtils::morph (out_block, have_ab, audio_block_ab, have_cd, audio_block_cd, y_morph_params.morphing, morph_mode);

if (have_abcd)
{
Expand Down
Loading

0 comments on commit 972e58a

Please sign in to comment.