diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/Makefile.am | 12 | ||||
-rw-r--r-- | src/test/test_compander.c | 122 |
2 files changed, 134 insertions, 0 deletions
diff --git a/src/test/Makefile.am b/src/test/Makefile.am new file mode 100644 index 0000000..2375047 --- /dev/null +++ b/src/test/Makefile.am @@ -0,0 +1,12 @@ +AM_CPPFLAGS = -Wall -g $(all_includes) + +noinst_PROGRAMS = \ + test_compander + +test_compander_SOURCES = test_compander.c + +test_compander_LDADD = \ + $(COMMON_LA) \ + $(top_builddir)/src/common/libcommon.a \ + -lm + diff --git a/src/test/test_compander.c b/src/test/test_compander.c new file mode 100644 index 0000000..d1661b4 --- /dev/null +++ b/src/test/test_compander.c @@ -0,0 +1,122 @@ +#include <stdio.h> +#include <stdint.h> +#include <math.h> +#include <string.h> +#include "../common/compander.h" + +#define level2db(level) (20 * log10(level)) +#define db2level(db) pow(10, (double)db / 20.0) + +#define SAMPLERATE 48000 +#define ATTACK_MS 15.0 +#define RECOVERY_MS 15.0 +#define UNAFFECTED 10000.0 + +static double test_frequency[3] = { 2000.0, 4000.0, 1000.0 }; + +static int16_t samples_4db[SAMPLERATE]; +static int16_t samples_16db[SAMPLERATE]; +static int16_t samples_2db[SAMPLERATE]; +static int16_t samples_8db[SAMPLERATE]; +static int16_t samples_0db[SAMPLERATE]; + +/* generate 2 samples: one with -4 dB, the other with -16 dB */ +static void generate_test_sample(double test_frequency) +{ + int i; + double value; + + for (i = 0; i < SAMPLERATE; i++) { + value = cos(2.0 * M_PI * test_frequency / (double)SAMPLERATE * i); + samples_4db[i] = (int)(UNAFFECTED * value * db2level(-4)); + samples_16db[i] = (int)(UNAFFECTED * value * db2level(-16)); + samples_2db[i] = (int)(UNAFFECTED * value * db2level(-2)); + samples_8db[i] = (int)(UNAFFECTED * value * db2level(-8)); + samples_0db[i] = (int)(UNAFFECTED * value); + } +} + +static void check_level(int16_t *samples, double duration, const char *desc, double target_db) +{ + int i; + int last = 0, envelop = 0; + int up = 0; + double factor; + + int when = (int)((double)SAMPLERATE + (double)SAMPLERATE * duration / 1000.0 + 0.5); + + for (i = 0; i < when; i++) { + if (last < samples[i]) { + up = 1; + } else if (last > samples[i]) { + if (up) { + envelop = last; + } + up = 0; + } +#if 0 + if (i >= (SAMPLERATE-(SAMPLERATE/100)) && (i % (SAMPLERATE/(SAMPLERATE/10))) == 0) + printf("%s: envelop = %.4f (when=%d)\n", desc, level2db((double)envelop / UNAFFECTED), i); +#endif + last = samples[i]; + } + factor = (envelop / UNAFFECTED) / db2level(target_db); + printf("%s: envelop after the instance of %.1f ms is %.4f db factor =%.4f\n", desc, duration, level2db((double)envelop / UNAFFECTED), factor); +} + +int main(void) +{ + compander_t cstate; + int16_t samples[SAMPLERATE * 2]; + int f; + + init_compander(&cstate, SAMPLERATE, ATTACK_MS, RECOVERY_MS, UNAFFECTED); + + for (f = 0; f < 3; f++) { + /* -16 and -4 dB */ + generate_test_sample(test_frequency[f]); + + /* low to high transition */ + memcpy(samples, samples_16db, SAMPLERATE * 2); + memcpy(samples + SAMPLERATE, samples_4db, SAMPLERATE * 2); + + compress_audio(&cstate, samples, SAMPLERATE * 2); + + check_level(samples, ATTACK_MS, "compressor attack", -2.0); + + /* high to low transition */ + memcpy(samples, samples_4db, SAMPLERATE * 2); + memcpy(samples + SAMPLERATE, samples_16db, SAMPLERATE * 2); + + compress_audio(&cstate, samples, SAMPLERATE * 2); + + check_level(samples, RECOVERY_MS, "compressor recovery", -8.0); + + /* low to high transition */ + memcpy(samples, samples_8db, SAMPLERATE * 2); + memcpy(samples + SAMPLERATE, samples_2db, SAMPLERATE * 2); + + expand_audio(&cstate, samples, SAMPLERATE * 2); + + check_level(samples, ATTACK_MS, "expander attack", -4.0); + + /* high to low transition */ + memcpy(samples, samples_2db, SAMPLERATE * 2); + memcpy(samples + SAMPLERATE, samples_8db, SAMPLERATE * 2); + + expand_audio(&cstate, samples, SAMPLERATE * 2); + + check_level(samples, RECOVERY_MS, "expander recovery", -16.0); + + /* 0 DB */ + memcpy(samples, samples_0db, SAMPLERATE * 2); + memcpy(samples + SAMPLERATE, samples_0db, SAMPLERATE * 2); + + check_level(samples, RECOVERY_MS, "unaffected level", 0.0); + + puts(""); + } + + return 0; +} + |