diff --git a/CMakeLists.txt b/CMakeLists.txt index 285fa40d..9abc5b18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,14 +17,35 @@ else() find_package(codec2 REQUIRED) endif() +# test variables +set(FRAMESPERBURST 3) +set(BURSTS 1) +set(TESTFRAMES 3) + add_test(NAME 000_audio_tests COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/test/000_audio_tests; python3 sinustest.py") -add_test(NAME 001_highsnr_stdio + +add_test(NAME 001_highsnr_stdio_P<>C COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src; PATH=$PATH:${CODEC2_BUILD_DIR}/src; cd ${CMAKE_CURRENT_SOURCE_DIR}/test/001_highsnr_stdio_audio; - python3 test_tx.py --mode 14 --delay 500 --framesperburst 3 --bursts 1 | - freedv_data_raw_rx datac0 - - --framesperburst 3 | hexdump -C") - set_tests_properties(001_highsnr_stdio PROPERTIES PASS_REGULAR_EXPRESSION "HELLO WORLD") + python3 test_tx.py --mode 14 --delay 500 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} | + freedv_data_raw_rx datac0 - - --framesperburst ${FRAMESPERBURST} | hexdump -C") + set_tests_properties(001_highsnr_stdio_P<>C PROPERTIES PASS_REGULAR_EXPRESSION "HELLO WORLD") +add_test(NAME 001_highsnr_stdio_C<>P + COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src; + PATH=$PATH:${CODEC2_BUILD_DIR}/src; + cd ${CMAKE_CURRENT_SOURCE_DIR}/test/001_highsnr_stdio_audio; + freedv_data_raw_tx --testframes ${TESTFRAMES} --bursts ${BURSTS} --framesperburst ${FRAMESPERBURST} datac0 /dev/zero - | + python3 test_rx.py --mode 14 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS}") + set_tests_properties(001_highsnr_stdio_C<>P PROPERTIES PASS_REGULAR_EXPRESSION "RECEIVED BURSTS: ${BURSTS} RECEIVED FRAMES: ${FRAMESPERBURST}") + +add_test(NAME 001_highsnr_stdio_P<>P + COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src; + PATH=$PATH:${CODEC2_BUILD_DIR}/src; + cd ${CMAKE_CURRENT_SOURCE_DIR}/test/001_highsnr_stdio_audio; + python3 test_tx.py --mode 14 --delay 500 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS} | + python3 test_rx.py --mode 14 --framesperburst ${FRAMESPERBURST} --bursts ${BURSTS}") + set_tests_properties(001_highsnr_stdio_P<>P PROPERTIES PASS_REGULAR_EXPRESSION "RECEIVED BURSTS: ${BURSTS} RECEIVED FRAMES: ${FRAMESPERBURST}") diff --git a/test/001_highsnr_stdio_audio/test_rx.py b/test/001_highsnr_stdio_audio/test_rx.py index 298f11ce..a854dbc5 100644 --- a/test/001_highsnr_stdio_audio/test_rx.py +++ b/test/001_highsnr_stdio_audio/test_rx.py @@ -21,9 +21,8 @@ import argparse #--------------------------------------------GET PARAMETER INPUTS parser = argparse.ArgumentParser(description='Simons TEST TNC') parser.add_argument('--bursts', dest="N_BURSTS", default=0, type=int) -parser.add_argument('--frames', dest="N_FRAMES_PER_BURST", default=0, type=int) -parser.add_argument('--mode', dest="FREEDV_MODE", default=0, type=int) -parser.add_argument('--input', dest="DATA_INPUT", type=str) +parser.add_argument('--framesperburst', dest="N_FRAMES_PER_BURST", default=0, type=int) +parser.add_argument('--mode', dest="FREEDV_MODE", default=14, type=int) parser.add_argument('--audioinput', dest="AUDIO_INPUT", default=0, type=int) parser.add_argument('--debug', dest="DEBUGGING_MODE", action="store_true") @@ -31,39 +30,19 @@ args = parser.parse_args() N_BURSTS = args.N_BURSTS N_FRAMES_PER_BURST = args.N_FRAMES_PER_BURST -DATA_INPUT = args.DATA_INPUT AUDIO_INPUT_DEVICE = args.AUDIO_INPUT -FREEDV_MODE = args.FREEDV_MODE +MODE = args.FREEDV_MODE DEBUGGING_MODE = args.DEBUGGING_MODE -# 1024 good for mode 6 + +# AUDIO PARAMETERS AUDIO_FRAMES_PER_BUFFER = 2048 MODEM_SAMPLE_RATE = 8000 +AUDIO_SAMPLE_RATE_TX = 48000 - - - - - - - - - #-------------------------------------------- LOAD FREEDV - -libname = "libcodec2.so" -c_lib = ctypes.CDLL(libname) - - #--------------------------------------------CREATE PYAUDIO INSTANCE - - - #--------------------------------------------GET SUPPORTED SAMPLE RATES FROM SOUND DEVICE - - - #--------------------------------------------OPEN AUDIO CHANNEL RX - -if DATA_INPUT == "audio": +# check if we want to use an audio device then do an pyaudio init +if AUDIO_INPUT_DEVICE != 0: p = pyaudio.PyAudio() - AUDIO_SAMPLE_RATE_RX = int(p.get_device_info_by_index(AUDIO_INPUT_DEVICE)['defaultSampleRate']) stream_rx = p.open(format=pyaudio.paInt16, channels=1, rate=AUDIO_SAMPLE_RATE_RX, @@ -72,18 +51,48 @@ if DATA_INPUT == "audio": input_device_index=AUDIO_INPUT_DEVICE, ) +# LOAD FREEDV +libname = "libcodec2.so" +c_lib = ctypes.CDLL(libname) - # GENERAL PARAMETERS -c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) - +# ctypes function init + +c_lib.freedv_open.argype = [c_int] +c_lib.freedv_open.restype = c_void_p + +c_lib.freedv_get_bits_per_modem_frame.argtype = [c_void_p] +c_lib.freedv_get_bits_per_modem_frame.restype = c_int + +c_lib.freedv_nin.argtype = [c_void_p] +c_lib.freedv_nin.restype = c_int + +c_lib.freedv_rawdatarx.argtype = [c_void_p, c_char_p, c_char_p] +c_lib.freedv_rawdatarx.restype = c_int + +c_lib.freedv_get_n_max_modem_samples.argtype = [c_void_p] +c_lib.freedv_get_n_max_modem_samples.restype = c_int + +c_lib.freedv_set_frames_per_burst.argtype = [c_void_p, c_int] +c_lib.freedv_set_frames_per_burst.restype = c_void_p + +c_lib.freedv_get_rx_status.argtype = [c_void_p] +c_lib.freedv_get_rx_status.restype = c_int + + +# ---------------------------------------------------------------- + # DATA CHANNEL INITIALISATION -freedv = c_lib.freedv_open(FREEDV_MODE) +# open codec2 instance +freedv = cast(c_lib.freedv_open(MODE), c_void_p) + +# get number of bytes per frame for mode bytes_per_frame = int(c_lib.freedv_get_bits_per_modem_frame(freedv)/8) +payload_bytes_per_frame = bytes_per_frame -2 + n_max_modem_samples = c_lib.freedv_get_n_max_modem_samples(freedv) -bytes_out = (ctypes.c_ubyte * bytes_per_frame) #bytes_per_frame -bytes_out = bytes_out() #get pointer from bytes_out +bytes_out = create_string_buffer(bytes_per_frame * 2) c_lib.freedv_set_frames_per_burst(freedv,N_FRAMES_PER_BURST) @@ -92,32 +101,32 @@ total_n_bytes = 0 rx_total_frames = 0 rx_frames = 0 rx_bursts = 0 +timeout = time.time() + 10 receive = True -while receive == True: - time.sleep(0.01) + +while receive and time.time() < timeout: data_in = b'' - if DATA_INPUT == "audio": + if AUDIO_INPUT_DEVICE != 0: nin = c_lib.freedv_nin(freedv) nin_converted = int(nin*(AUDIO_SAMPLE_RATE_RX/MODEM_SAMPLE_RATE)) if DEBUGGING_MODE == True: - print("-----------------------------") - print("NIN: " + str(nin) + " [ " + str(nin_converted) + " ]") + print(f"NIN: {nin} [{nin_converted}]", file=sys.stderr) data_in = stream_rx.read(nin_converted, exception_on_overflow = False) data_in = audioop.ratecv(data_in,2,1,AUDIO_SAMPLE_RATE_RX, MODEM_SAMPLE_RATE, None) data_in = data_in[0].rstrip(b'\x00') else: - nin = c_lib.freedv_nin(freedv)*2 + nin = c_lib.freedv_nin(freedv) * 2 data_in = sys.stdin.buffer.read(nin) - c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), bytes_out, data_in] # check if really neccessary nbytes = c_lib.freedv_rawdatarx(freedv, bytes_out, data_in) # demodulate audio total_n_bytes = total_n_bytes + nbytes + if DEBUGGING_MODE == True: - print("SYNC: " + str(c_lib.freedv_get_rx_status(freedv))) + print(f"SYNC: {c_lib.freedv_get_rx_status(freedv)}", file=sys.stderr) if nbytes == bytes_per_frame: rx_total_frames = rx_total_frames + 1 @@ -126,13 +135,15 @@ while receive == True: if rx_frames == N_FRAMES_PER_BURST: rx_frames = 0 rx_bursts = rx_bursts + 1 - #c_lib.freedv_set_sync(freedv,0) #this should be automatically done by c_lib.freedv_set_frames_per_burst(freedv,N_FRAMES_PER_BURST) + if rx_bursts == N_BURSTS: receive = False -print("------------------------------") -print("BURSTS: " + str(rx_bursts)) -print("TOTAL RECEIVED BYTES: " + str(total_n_bytes)) -print("RECEIVED FRAMES: " + str(rx_total_frames)) +print(f"RECEIVED BURSTS: {rx_bursts} RECEIVED FRAMES: {rx_total_frames}", file=sys.stderr) + +# and at last check if we had an openend pyaudio instance and close it +if AUDIO_INPUT_DEVICE != 0: + stream_tx.close() + p.terminate() diff --git a/test/001_highsnr_stdio_audio/test_tx.py b/test/001_highsnr_stdio_audio/test_tx.py index 30794dd8..9efe7c26 100644 --- a/test/001_highsnr_stdio_audio/test_tx.py +++ b/test/001_highsnr_stdio_audio/test_tx.py @@ -17,8 +17,7 @@ parser = argparse.ArgumentParser(description='Simons TEST TNC') parser.add_argument('--bursts', dest="N_BURSTS", default=0, type=int) parser.add_argument('--framesperburst', dest="N_FRAMES_PER_BURST", default=0, type=int) parser.add_argument('--delay', dest="DELAY_BETWEEN_BURSTS", default=0, type=int) -parser.add_argument('--mode', dest="FREEDV_MODE", default=0, type=int) -parser.add_argument('--output', dest="DATA_OUTPUT", type=str) +parser.add_argument('--mode', dest="FREEDV_MODE", default=14, type=int) parser.add_argument('--audiooutput', dest="AUDIO_OUTPUT", default=0, type=int) args = parser.parse_args() @@ -26,17 +25,17 @@ args = parser.parse_args() N_BURSTS = args.N_BURSTS N_FRAMES_PER_BURST = args.N_FRAMES_PER_BURST DELAY_BETWEEN_BURSTS = args.DELAY_BETWEEN_BURSTS/1000 -DATA_OUTPUT = args.DATA_OUTPUT AUDIO_OUTPUT_DEVICE = args.AUDIO_OUTPUT MODE = args.FREEDV_MODE + # AUDIO PARAMETERS AUDIO_FRAMES_PER_BUFFER = 2048 MODEM_SAMPLE_RATE = 8000 AUDIO_SAMPLE_RATE_TX = 48000 # check if we want to use an audio device then do an pyaudio init -if DATA_OUTPUT == "audio": +if AUDIO_OUTPUT_DEVICE != 0: # pyaudio init p = pyaudio.PyAudio() stream_tx = p.open(format=pyaudio.paInt16, @@ -143,7 +142,7 @@ for i in range(1,N_BURSTS+1): print(f"samples_delay: {samples_delay} DELAY_BETWEEN_BURSTS: {DELAY_BETWEEN_BURSTS}", file=sys.stderr) # check if we want to use an audio device or stdout - if DATA_OUTPUT == "audio": + if AUDIO_OUTPUT_DEVICE != 0: # sample rate conversion from 8000Hz to 48000Hz audio = audioop.ratecv(txbuffer,2,1,MODEM_SAMPLE_RATE, AUDIO_SAMPLE_RATE_TX, None) @@ -156,6 +155,6 @@ for i in range(1,N_BURSTS+1): # and at last check if we had an openend pyaudio instance and close it -if DATA_OUTPUT == "audio": +if AUDIO_OUTPUT_DEVICE != 0: stream_tx.close() p.terminate()