From b95562740a464e9b56499dc734a1a1868db8cede Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 16 Dec 2021 07:50:24 +1030 Subject: [PATCH] automated test for FreeDV resampler --- CMakeLists.txt | 6 +++ test/000_resampler/t48_8_short.py | 49 ++++++++++++++++++++++++- test/001_highsnr_stdio_audio/test_tx.py | 4 +- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15a5b975..4be3d23b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,12 @@ set(FRAMESPERBURST 3) set(BURSTS 1) set(TESTFRAMES 3) +add_test(NAME 000_resampler + COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src; + cd ${CMAKE_CURRENT_SOURCE_DIR}/test/000_resampler; + python3 t48_8_short.py") + set_tests_properties(000_resampler PROPERTIES PASS_REGULAR_EXPRESSION "PASS") + add_test(NAME 001_highsnr_stdio_P_C_SM COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src; PATH=$PATH:${CODEC2_BUILD_DIR}/src; diff --git a/test/000_resampler/t48_8_short.py b/test/000_resampler/t48_8_short.py index 10bcb0cf..2acb40ed 100644 --- a/test/000_resampler/t48_8_short.py +++ b/test/000_resampler/t48_8_short.py @@ -38,25 +38,72 @@ AMP = 16000 # sine wave amplitude FTEST8 = 800 # input test frequency at FS=8kHz FINTER48 = 10000 # interferer frequency at FS=48kHz +# Due to the design of these resamplers, the processing buffer (at 8kHz) +# must be an integer multiple of oversampling ratio +assert N8 % FDMDV_OS_48 == 0 + in8k = np.zeros(MEM8 + N8, dtype=np.int16) out48k = np.zeros(N48, dtype=np.int16) in48k = np.zeros(MEM48 + N48, dtype=np.int16) out8k = np.zeros(N8, dtype=np.int16) +# time indexes, we advance every frame t = 0 +t1 = 0 + fin8 = open("in8.raw", mode='wb') f48 = open("out48.raw", mode='wb') +fout8 = open("out8.raw", mode='wb') for f in range(FRAMES): - + + # input sine wave in8k[MEM8:] = AMP*np.cos(2*np.pi*np.arange(t,t+N8)*FTEST8/FS8) t += N8 in8k[MEM8:].tofile(fin8) + # upsample pin8k,flag = in8k.__array_interface__['data'] pin8k += 2*MEM8 codec2.api.fdmdv_8_to_48_short(out48k.ctypes, pin8k, N8); out48k.tofile(f48) + # add interfering sine wave (down sampling filter should remove) + in48k[MEM48:] = out48k + (AMP/2)*np.cos(2*np.pi*np.arange(t1,t1+N48)*FINTER48/FS48) + t1 += N48 + + # downsample + pin48k,flag = in48k.__array_interface__['data'] + pin48k += 2*MEM48 + codec2.api.fdmdv_48_to_8_short(out8k.ctypes, pin48k, N8); + out8k.tofile(fout8) + fin8.close() f48.close() +fout8.close() + +# Automated test evaluation -------------------------------------------- + +# The input and output signals will not be time aligned due to the filter +# delays, so compare the magnitude spectrum + +in8k = np.fromfile("in8.raw", dtype=np.int16) +out8k = np.fromfile("out8.raw", dtype=np.int16) +assert len(in8k) == len(out8k) + +n = len(in8k) + +h = np.hanning(len(in8k)) +S1 = np.abs(np.fft.fft(in8k * h)) +S2 = np.abs(np.fft.fft(out8k * h)) + +error = S1-S2 +error_energy = np.dot(error,error) +ratio = error_energy/np.dot(S1,S1) +ratio_dB = 10*np.log10(ratio); +print("ratio_dB: %4.2f" % (ratio_dB)); +threshdB = -40 +if ratio_dB < threshdB: + print("PASS") +else: + print("FAIL") diff --git a/test/001_highsnr_stdio_audio/test_tx.py b/test/001_highsnr_stdio_audio/test_tx.py index acb13792..19a838fb 100644 --- a/test/001_highsnr_stdio_audio/test_tx.py +++ b/test/001_highsnr_stdio_audio/test_tx.py @@ -1,4 +1,4 @@ - #!/usr/bin/env python3 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- @@ -7,8 +7,6 @@ from ctypes import * import pathlib import pyaudio import time -import threading -import audioop import argparse import sys sys.path.insert(0,'..')