add a-law companding functions
This commit is contained in:
38
companding/alaw.h
Normal file
38
companding/alaw.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace trnr {
|
||||||
|
|
||||||
|
constexpr float A_LAW_A = 87.6f;
|
||||||
|
|
||||||
|
inline float alaw_encode(float input)
|
||||||
|
{
|
||||||
|
float sign = (input >= 0.0f) ? 1.0f : -1.0f;
|
||||||
|
float abs_sample = std::fabs(input);
|
||||||
|
|
||||||
|
float output;
|
||||||
|
if (abs_sample < (1.0f / A_LAW_A)) {
|
||||||
|
output = sign * (A_LAW_A * abs_sample) / (1.0f + std::log(A_LAW_A));
|
||||||
|
} else {
|
||||||
|
output = sign * (1.0f + std::log(A_LAW_A * abs_sample)) / (1.0f + std::log(A_LAW_A));
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float alaw_decode(float input)
|
||||||
|
{
|
||||||
|
float sign = (input >= 0.0f) ? 1.0f : -1.0f;
|
||||||
|
float abs_comp = std::fabs(input);
|
||||||
|
|
||||||
|
float sample;
|
||||||
|
if (abs_comp < (1.0f / (1.0f + std::log(A_LAW_A)))) {
|
||||||
|
sample = sign * (abs_comp * (1.0f + std::log(A_LAW_A))) / A_LAW_A;
|
||||||
|
} else {
|
||||||
|
sample = sign * std::exp(abs_comp * (1.0f + std::log(A_LAW_A)) - 1.0f) / A_LAW_A;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
} // namespace trnr
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace trnr {
|
|
||||||
// mulaw companding based on code by Emilie Gillet / Mutable Instruments
|
|
||||||
class mulaw {
|
|
||||||
public:
|
|
||||||
int8_t encode_samples(int16_t pcm_val)
|
|
||||||
{
|
|
||||||
int16_t mask;
|
|
||||||
int16_t seg;
|
|
||||||
uint8_t uval;
|
|
||||||
pcm_val = pcm_val >> 2;
|
|
||||||
if (pcm_val < 0) {
|
|
||||||
pcm_val = -pcm_val;
|
|
||||||
mask = 0x7f;
|
|
||||||
} else {
|
|
||||||
mask = 0xff;
|
|
||||||
}
|
|
||||||
if (pcm_val > 8159) pcm_val = 8159;
|
|
||||||
pcm_val += (0x84 >> 2);
|
|
||||||
|
|
||||||
if (pcm_val <= 0x3f) seg = 0;
|
|
||||||
else if (pcm_val <= 0x7f) seg = 1;
|
|
||||||
else if (pcm_val <= 0xff) seg = 2;
|
|
||||||
else if (pcm_val <= 0x1ff) seg = 3;
|
|
||||||
else if (pcm_val <= 0x3ff) seg = 4;
|
|
||||||
else if (pcm_val <= 0x7ff) seg = 5;
|
|
||||||
else if (pcm_val <= 0xfff) seg = 6;
|
|
||||||
else if (pcm_val <= 0x1fff) seg = 7;
|
|
||||||
else seg = 8;
|
|
||||||
if (seg >= 8) return static_cast<uint8_t>(0x7f ^ mask);
|
|
||||||
else {
|
|
||||||
uval = static_cast<uint8_t>((seg << 4) | ((pcm_val >> (seg + 1)) & 0x0f));
|
|
||||||
return (uval ^ mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t decode_samples(uint8_t u_val)
|
|
||||||
{
|
|
||||||
int16_t t;
|
|
||||||
u_val = ~u_val;
|
|
||||||
t = ((u_val & 0xf) << 3) + 0x84;
|
|
||||||
t <<= ((unsigned)u_val & 0x70) >> 4;
|
|
||||||
return ((u_val & 0x80) ? (0x84 - t) : (t - 0x84));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace trnr
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
namespace trnr {
|
|
||||||
// ulaw compansion based on code by Chris Johnson
|
|
||||||
class ulaw {
|
|
||||||
public:
|
|
||||||
ulaw()
|
|
||||||
{
|
|
||||||
fpd_l = 1.0;
|
|
||||||
while (fpd_l < 16386) fpd_l = rand() * UINT32_MAX;
|
|
||||||
fpd_r = 1.0;
|
|
||||||
while (fpd_r < 16386) fpd_r = rand() * UINT32_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
void encode_samples(double& input_sample_l, double& input_sample_r)
|
|
||||||
{
|
|
||||||
|
|
||||||
// ulaw encoding
|
|
||||||
static int noisesource_l = 0;
|
|
||||||
static int noisesource_r = 850010;
|
|
||||||
int residue;
|
|
||||||
double applyresidue;
|
|
||||||
|
|
||||||
noisesource_l = noisesource_l % 1700021;
|
|
||||||
noisesource_l++;
|
|
||||||
residue = noisesource_l * noisesource_l;
|
|
||||||
residue = residue % 170003;
|
|
||||||
residue *= residue;
|
|
||||||
residue = residue % 17011;
|
|
||||||
residue *= residue;
|
|
||||||
residue = residue % 1709;
|
|
||||||
residue *= residue;
|
|
||||||
residue = residue % 173;
|
|
||||||
residue *= residue;
|
|
||||||
residue = residue % 17;
|
|
||||||
applyresidue = residue;
|
|
||||||
applyresidue *= 0.00000001;
|
|
||||||
applyresidue *= 0.00000001;
|
|
||||||
input_sample_l += applyresidue;
|
|
||||||
if (input_sample_l < 1.2e-38 && -input_sample_l < 1.2e-38) { input_sample_l -= applyresidue; }
|
|
||||||
|
|
||||||
noisesource_r = noisesource_r % 1700021;
|
|
||||||
noisesource_r++;
|
|
||||||
residue = noisesource_r * noisesource_r;
|
|
||||||
residue = residue % 170003;
|
|
||||||
residue *= residue;
|
|
||||||
residue = residue % 17011;
|
|
||||||
residue *= residue;
|
|
||||||
residue = residue % 1709;
|
|
||||||
residue *= residue;
|
|
||||||
residue = residue % 173;
|
|
||||||
residue *= residue;
|
|
||||||
residue = residue % 17;
|
|
||||||
applyresidue = residue;
|
|
||||||
applyresidue *= 0.00000001;
|
|
||||||
applyresidue *= 0.00000001;
|
|
||||||
input_sample_r += applyresidue;
|
|
||||||
if (input_sample_r < 1.2e-38 && -input_sample_r < 1.2e-38) { input_sample_r -= applyresidue; }
|
|
||||||
|
|
||||||
if (input_sample_l > 1.0) input_sample_l = 1.0;
|
|
||||||
if (input_sample_l < -1.0) input_sample_l = -1.0;
|
|
||||||
|
|
||||||
if (input_sample_r > 1.0) input_sample_r = 1.0;
|
|
||||||
if (input_sample_r < -1.0) input_sample_r = -1.0;
|
|
||||||
|
|
||||||
if (input_sample_l > 0) input_sample_l = log(1.0 + (255 * fabs(input_sample_l))) / log(256);
|
|
||||||
if (input_sample_l < 0) input_sample_l = -log(1.0 + (255 * fabs(input_sample_l))) / log(256);
|
|
||||||
|
|
||||||
if (input_sample_r > 0) input_sample_r = log(1.0 + (255 * fabs(input_sample_r))) / log(256);
|
|
||||||
if (input_sample_r < 0) input_sample_r = -log(1.0 + (255 * fabs(input_sample_r))) / log(256);
|
|
||||||
}
|
|
||||||
|
|
||||||
void decode_samples(double& input_sample_l, double& input_sample_r)
|
|
||||||
{
|
|
||||||
|
|
||||||
// ulaw decoding
|
|
||||||
if (fabs(input_sample_l) < 1.18e-23) input_sample_l = fpd_l * 1.18e-17;
|
|
||||||
if (fabs(input_sample_r) < 1.18e-23) input_sample_r = fpd_r * 1.18e-17;
|
|
||||||
|
|
||||||
if (input_sample_l > 1.0) input_sample_l = 1.0;
|
|
||||||
if (input_sample_l < -1.0) input_sample_l = -1.0;
|
|
||||||
|
|
||||||
if (input_sample_r > 1.0) input_sample_r = 1.0;
|
|
||||||
if (input_sample_r < -1.0) input_sample_r = -1.0;
|
|
||||||
|
|
||||||
if (input_sample_l > 0) input_sample_l = (pow(256, fabs(input_sample_l)) - 1.0) / 255;
|
|
||||||
if (input_sample_l < 0) input_sample_l = -(pow(256, fabs(input_sample_l)) - 1.0) / 255;
|
|
||||||
|
|
||||||
if (input_sample_r > 0) input_sample_r = (pow(256, fabs(input_sample_r)) - 1.0) / 255;
|
|
||||||
if (input_sample_r < 0) input_sample_r = -(pow(256, fabs(input_sample_r)) - 1.0) / 255;
|
|
||||||
|
|
||||||
// 64 bit stereo floating point dither
|
|
||||||
fpd_l ^= fpd_l << 13;
|
|
||||||
fpd_l ^= fpd_l >> 17;
|
|
||||||
fpd_l ^= fpd_l << 5;
|
|
||||||
fpd_r ^= fpd_r << 13;
|
|
||||||
fpd_r ^= fpd_r >> 17;
|
|
||||||
fpd_r ^= fpd_r << 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t fpd_l;
|
|
||||||
uint32_t fpd_r;
|
|
||||||
};
|
|
||||||
} // namespace trnr
|
|
||||||
Reference in New Issue
Block a user