Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/shared/audiodsp_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "shared/audiodsp_graph_overdrive.h"

#include <float.h>
#include <math.h>
#include <string.h>

Expand Down Expand Up @@ -807,14 +808,35 @@ static void derive(audiodsp_graph_t *graph, audiodsp_graph_node_t *n) {
}
}

// Every sample every node writes goes through sat16, so its rounding is the
// runner's hottest arithmetic. Adding 1.5 * 2^23 puts a clamped sample in
// [2^23, 2^24), where a float holds whole numbers only: the add rounds it to
// an integer the way the FPU rounds, nearest with ties to even, and the
// subtract takes it back exactly. That is round_even's answer for every float
// (all 2^32 of them checked against it), in two adds instead of a dozen
// instructions and two branches; on the P4 it is a fifth of a mixer's time.
// It needs float arithmetic done in float (FLT_EVAL_METHOD 0); a target that
// carries floats wider, as x87 does, keeps round_even.
#if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD == 0
#define GRAPH_SAT16_MAGIC 1
#define GRAPH_ROUND_MAGIC 12582912.0f
#endif

static inline int16_t sat16(float v) {
if (v > 32767.0f) {
return 32767;
}
if (v < -32768.0f) {
return -32768;
}
#ifdef GRAPH_SAT16_MAGIC
if (!(v == v)) {
return 0;
}
return (int16_t)(int32_t)((v + GRAPH_ROUND_MAGIC) - GRAPH_ROUND_MAGIC);
#else
return (int16_t)round_even(v);
#endif
}

static void run_env(audiodsp_graph_node_t *n, const int16_t *gate, int16_t *out,
Expand Down
Loading