diff options
author | Rob Sykes <rob@rob-Ideapad-S205.(none)> | 2013-02-28 00:24:01 +0400 |
---|---|---|
committer | Rob Sykes <rob@rob-Ideapad-S205.(none)> | 2013-02-28 00:24:01 +0400 |
commit | fa75beaf0b8d5e594018471d778e98eb7f0a87dd (patch) | |
tree | 286aade8b3442d7ffe9617e73c4b624c9c71fe07 | |
parent | 4d9db78903ab378efaf7fbf9e943695a0e8ac266 (diff) |
Slight reworking of API params for phase-response and pass-/stop-band spec
-rw-r--r-- | src/rate.h | 24 | ||||
-rw-r--r-- | src/soxr.c | 22 | ||||
-rw-r--r-- | src/soxr.h | 12 |
3 files changed, 33 insertions, 25 deletions
@@ -369,7 +369,7 @@ typedef struct { #define have_post_stage (postM * postL != 1) #define TO_3dB(a) ((1.6e-6*a-7.5e-4)*a+.646) -#define LOW_Q_BW0_PC (67 + 5 / 8.) +#define LOW_Q_BW0 (1385 / 2048.) /* 0.67625 rounded to be a FP exact. */ typedef enum { rolloff_none, rolloff_small /* <= 0.01 dB */, rolloff_medium /* <= 0.35 dB */ @@ -385,9 +385,9 @@ static char const * rate_init( double factor, /* Input rate divided by output rate. */ double bits, /* Required bit-accuracy (pass + stop) 16|20|28 */ double phase, /* Linear/minimum etc. filter phase. 50 */ - double bw_pc, /* Pass-band % (0dB pt.) to preserve. 91.3|98.4*/ - double anti_aliasing_pc, /* % bandwidth without aliasing 100 */ - rolloff_t rolloff, /* Pass-band roll-off small */ + double passband_end, /* 0dB pt. bandwidth to preserve; nyquist=1 0.913*/ + double stopband_begin, /* Aliasing/imaging control; > passband_end 1 */ + rolloff_t rolloff, /* Pass-band roll-off small */ bool maintain_3dB_pt, /* true */ double multiplier, /* Linear gain to apply during conversion. 1 */ @@ -400,20 +400,20 @@ static char const * rate_init( int log2_large_dft_size) { double att = (bits + 1) * linear_to_dB(2.), attArb = att; /* pass + stop */ - double tbw0 = 1 - bw_pc / 100, Fs_a = 2 - anti_aliasing_pc / 100; + double tbw0 = 1 - passband_end, Fs_a = stopband_begin; double arbM = factor, tbw_tighten = 1; int n = 0, i, preL = 1, preM = 1, shift = 0, arbL = 1, postL = 1, postM = 1; bool upsample = false, rational = false, iOpt = !noSmallIntOpt; - int mode = rolloff > rolloff_small? factor > 1 || bw_pc > LOW_Q_BW0_PC: + int mode = rolloff > rolloff_small? factor > 1 || passband_end > LOW_Q_BW0: (int)ceil(2 + (bits - 17) / 4); stage_t * s; assert(factor > 0); assert(!bits || (15 <= bits && bits <= 33)); assert(0 <= phase && phase <= 100); - assert(53 <= bw_pc && bw_pc <= 100); - assert(85 <= anti_aliasing_pc && anti_aliasing_pc <= 130); - assert(bw_pc < 200 - anti_aliasing_pc); + assert(.53 <= passband_end); + assert(stopband_begin <= 1.2); + assert(passband_end + .005 < stopband_begin); p->factor = factor; if (bits) while (!n++) { /* Determine stages: */ @@ -690,9 +690,9 @@ static char const * rate_create( channel, shared, io_ratio, q_spec->precision, - q_spec->phase, - q_spec->bw_pc, - q_spec->anti_aliasing_pc, + q_spec->phase_response, + q_spec->passband_end, + q_spec->stopband_begin, "\1\2\0"[q_spec->flags & 3], !!(q_spec->flags & SOXR_MAINTAIN_3DB_PT), scale, @@ -69,7 +69,7 @@ struct soxr { /* TODO: these should not be here. */ #define TO_3dB(a) ((1.6e-6*a-7.5e-4)*a+.646) -#define LOW_Q_BW0_PC (67 + 5 / 8.) +#define LOW_Q_BW0 (1385 / 2048.) /* 0.67625 rounded to be a FP exact. */ soxr_quality_spec_t soxr_quality_spec(unsigned long recipe, unsigned long flags) { @@ -85,24 +85,24 @@ soxr_quality_spec_t soxr_quality_spec(unsigned long recipe, unsigned long flags) quality = 6; else if (quality > 10) quality = 0; - p->phase = "\62\31\144"[(recipe & 0x30)>>8]; - p->anti_aliasing_pc = 100; + p->phase_response = "\62\31\144"[(recipe & 0x30)>>8]; + p->stopband_begin = 1; p->precision = !quality? 0: quality < 3? 16 : quality < 8? 4 + quality * 4 : 55 - quality * 4; rej = p->precision * linear_to_dB(2.); p->flags = flags; if (quality < 8) { - p->bw_pc = quality == 1? LOW_Q_BW0_PC : 100 - 5 / TO_3dB(rej); + p->passband_end = quality == 1? LOW_Q_BW0 : 1 - .05 / TO_3dB(rej); if (quality <= 2) p->flags &= ~SOXR_ROLLOFF_NONE, p->flags |= SOXR_ROLLOFF_MEDIUM; } else { - static float const bw[] = {93.1f, 83.2f, 66.3f}; - p->bw_pc = bw[quality - 8]; + static float const bw[] = {.931f, .832f, .663f}; + p->passband_end = bw[quality - 8]; if (quality - 8 == 2) p->flags &= ~SOXR_ROLLOFF_NONE, p->flags |= SOXR_ROLLOFF_MEDIUM; } if (recipe & SOXR_STEEP_FILTER) - p->bw_pc = 100 - 1 / TO_3dB(rej); + p->passband_end = 1 - .01 / TO_3dB(rej); return spec; } @@ -217,6 +217,14 @@ soxr_t soxr_create( if (p) { p->q_spec = q_spec? *q_spec : soxr_quality_spec(SOXR_HQ, 0); + + if (q_spec) { /* Backwards compatibility with original API: */ + if (p->q_spec.passband_end > 2) + p->q_spec.passband_end /= 100; + if (p->q_spec.stopband_begin > 2) + p->q_spec.stopband_begin = 2 - p->q_spec.stopband_begin / 100; + } + p->io_ratio = io_ratio; p->num_channels = num_channels; if (io_spec) @@ -221,12 +221,12 @@ struct soxr_io_spec { /* Typically */ struct soxr_quality_spec { /* Typically */ - double precision; /* Conversion precision (in bits). 20 */ - double phase; /* Linear/minimum etc. phase. [0,100] 50 */ - double bw_pc; /* Band-width % (0dB pt.) to preserve. 91.3 */ - double anti_aliasing_pc; /* % bandwidth without aliasing. 100 */ - void * e; /* Reserved for internal use. 0 */ - unsigned long flags; /* Per the following #defines. 0 */ + double precision; /* Conversion precision (in bits). 20 */ + double phase_response; /* 0=minimum, ... 50=linear, ... 100=maximum 50 */ + double passband_end; /* 0dB pt. bandwidth to preserve; nyquist=1 0.913*/ + double stopband_begin; /* Aliasing/imaging control; > passband_end 1 */ + void * e; /* Reserved for internal use. 0 */ + unsigned long flags; /* Per the following #defines. 0 */ }; #define SOXR_ROLLOFF_SMALL 0u /* <= 0.01 dB */ |