orion-sdr 0.0.21

DSP/SDR block library targeting HF-to-UHF, satellites, and Python bindings. Roadmap inside.
Documentation
+
ޱ�i�c���Rt^RIt^RIHuHt^RIt^RI	t	^RI
t^RIH
t
HtHtHtRtRtRtRtRtRtR	tR
tRtRt]	P6P9R
.RO4R4tR#)uQRoundtrip tests for the orion_sdr Python extension.

Analog tests modulate a tone, demodulate it, and assert that SNR in the
recovered audio exceeds a minimum threshold.

Digital tests perform noiseless bit-exact roundtrips through the full
mod/demod pipeline (mapper → waveform → demod → decider) and assert
perfect bit recovery.
N)�FS�	real_tone�snr_db�taili�c	���RpRpRp\P!\V4Uu.uF&q3V,\,R,R8dRMRNK(	up\PR7p\
P!\VRR4PV4p\
P!\VR	4PV4p\R
\,4pWgRpWGRp\\P!\P!W�R8�,^,444p	\\P!\P!W�R8,^,444R,p
R
\P!W�,4,pRq�V8�q�'g�\P!RV
3RW�34RR\ P"!49g\P$!V4'd\P&!V4MRR\P&!V4/,p\P(!RVR
R24R,RV/,p\+\P,!V44hR;r�R#uupi)z=Recovered keying envelope should have >14 dB ON/OFF contrast.i�]g��@g@��?��?���dtypeg@g�r@g�������?Ng�-���q=�4@g,@�py0�contrast_db�py3zCW ON/OFF contrast �.1fz dB < 14 dB�
>assert %(py5)s�py5��>�z%(py0)s > %(py3)s)�np�array�ranger�float32�sdr�
CwKeyedMod�process�CwEnvelopeDemod�int�float�sqrt�mean�log10�
@pytest_ar�_call_reprcompare�@py_builtins�locals�_should_repr_global_name�	_saferepr�_format_assertmsg�AssertionError�_format_explanation)�n�pitch_hz�key_f�k�key_env�iq�audio�skip�a�on_rms�off_rmsr
�@py_assert2�@py_assert1�@py_format4�@py_format6s                �u/Users/glenn/Library/Mobile Documents/com~apple~CloudDocs/work/rust/projects/orion-sdr/python/tests/test_roundtrip.py�test_roundtrip_cw_enveloper;s����A��H��E��h�h�AF�q��J��A�e�)�b�.�C�'�#�-�#�3�
6��J��j�j��G�


����H�c�3�	/�	7�	7��	@�B�����H�e�4�<�<�R�@�E��u�r�z�?�D�
�e��A����A��B�G�G�B�G�G�A�#�g�J�!�O�4�5�6�F��B�G�G�B�G�G�A�#�g�J�!�O�4�5�6��>�G�����&�"2�3�3�K��Q���Q�Q�Q�Q�;�Q�Q�Q�Q�Q�Q�;�Q�Q�Q�Q�;�Q�Q�Q��Q�Q�Q�Q�!4�[��4E�[�Q�Q�Q�Q�Q�Q�Q�Q�Q��	Ks�,I.c���Rp\\V\R4p\P!\RRR4PV4p\P!\R4PV4p\\V4\V4pRqTV8�qf'g�\P!RV3RWE34RR\P!49g\P!V4'd\P!V4MRR\P!V4/,p\P!R	VR

R24R,R
V/,p\!\P"!V44hR;reR#)�@�@rr皙�����?���@g8@r�snrrzAM roundtrip SNR rz dB < 24 dBrrNrr�rr�Nr�AmDsbModr�AmEnvelopeDemodrrr"r#r$r%r&r'r(r)r*�	�f_mod�audio_inr0�	audio_outr@r6r7r8r9s	         r:�test_roundtrip_am_enveloperI6s����E���U�A�s�+�H�	���b�#�s�C�	(�	0�	0��	:�B��#�#�B��0�8�8��<�I�
��i��"�e�
,�C��?��:�?�?�?�?�3�?�?�?�?�?�?�3�?�?�?�?�3�?�?�?��?�?�?�?�*�3�s�)�;�?�?�?�?�?�?�?�?�?�c���Rp\\V\R4p\P!\RRR4PV4p\P!\RRR7PV4p\\V4\V4pRqTV8�qf'g�\P!RV3RWE34R	R
\P!49g\P!V4'd\P!V4MR
R\P!V4/,p\P!RVR

R24R,RV/,p\!\P"!V44hR;reR#)z5AbsApprox variant should also achieve acceptable SNR.r=rrr>r?T)�
abs_approxrrr@rzAM AbsApprox roundtrip SNR r� dB < 20 dBrrNrrrArEs	         r:�%test_roundtrip_am_envelope_abs_approxrNAs����E���U�A�s�+�H�	���b�#�s�C�	(�	0�	0��	:�B��#�#�B��D�A�I�I�"�M�I�
��i��"�e�
,�C��I��:�I�I�I�I�3�I�I�I�I�I�I�3�I�I�I�I�3�I�I�I��I�I�I�I�4�S��I�[�I�I�I�I�I�I�I�I�IrJc���RpRpRp\\V\R4p\P!\WRR4PV4p\P!\W!4PV4p\R\,4p\WVR\V4pRq�V8�q�'g�\P!RV	3RWx34R	R
\P!49g\P!V4'd\P!V4MR
R\P!V4/,p
\P!RVR

R24R,RV
/,p\!\P"!V44hR;r�R#)g��@g�@gp�@g�������?rTg���Q��?N�2@rr@rzSSB USB roundtrip SNR r� dB < 18 dBrrrr)rrrBr�
SsbPhasingModr�SsbProductDemodrrr"r#r$r%r&r'r(r)r*)�f_audio�audio_bw_hz�audio_if_hzrGr0rHr2r@r6r7r8r9s            r:�test_roundtrip_ssb_usbrWQs����G��K��K���W�a��-�H�	�	�	�2�{��d�	C�	K�	K�H�	U�B��#�#�B��A�I�I�"�M�I��u�r�z�?�D�
��5�!�2�w�
/�C��D��:�D�D�D�D�3�D�D�D�D�D�D�3�D�D�D�D�3�D�D�D��D�D�D�D�/��C�y��D�D�D�D�D�D�D�D�DrJc���Rp\\V\R4p\P!\RR4PV4p\P!\RR4PV4p\\V4\V4pRqTV8�qf'g�\P!RV3RWE34RR\P!49g\P!V4'd\P!V4MRR\P!V4/,p\P!R	VR

R24R,R
V/,p\!\P"!V44hR;reR#)r=rg��@rr?rrr@rzFM roundtrip SNR rrMrrNrr)rrrBr�FmPhaseAccumModr�FmQuadratureDemodrrr"r#r$r%r&r'r(r)r*rEs	         r:�test_roundtrip_fm_quadraturer[cs����E���U�A�s�+�H�	�	�	�R��#�	.�	6�	6�x�	@�B��%�%�b�'�7�;�C�C�B�G�I�
��i��"�e�
,�C��?��:�?�?�?�?�3�?�?�?�?�?�?�3�?�?�?�?�3�?�?�?��?�?�?�?�*�3�s�)�;�?�?�?�?�?�?�?�?�?rJc���Rp\\V\R4p\P!\RR4PV4p\P!\RR4PV4p\\V4\V4pRqTV8�qf'g�\P!RV3RWE34RR\P!49g\P!V4'd\P!V4MRR\P!V4/,p\P!R	VR

R24R,R
V/,p\!\P"!V44hR;reR#)g �@rg�������?rr?rPrr@rzPM roundtrip SNR rrQrrNrr)rrrBr�PmDirectPhaseModr�PmQuadratureDemodrrr"r#r$r%r&r'r(r)r*rEs	         r:�test_roundtrip_pm_quadraturer_rs����E���U�A�s�+�H�	�	�	�b�#�s�	+�	3�	3�H�	=�B��%�%�b�#�w�7�?�?��C�I�
��i��"�e�
,�C��?��:�?�?�?�?�3�?�?�?�?�?�?�3�?�?�?�?�3�?�?�?��?�?�?�?�*�3�s�)�;�?�?�?�?�?�?�?�?�?rJc��Rp\P!\V4Uu.uFq^,NK
	up\PR7p\P
!RRR4P
V4p\P!R4P
V4p.qSPq`3qvV8Hq�q�'d"VPp
\Pq�V8Hq�p	V	'Eg\P!RV3RWg34RR\P!49g\P!V4'd\P !V4MRR\P !V4R\P !V4/,p
R	R
V
/,q�P#V4V'Ed\P!RX3RX
X34RR\P!49g\P!V4'd\P !V4MRR\P !V
4R
R\P!49g!\P!\4'd\P !\4MRR\P !V4/,pRRV/,pVP#V4\P$!V^4/,pRRV/,p\'\P(!V44hR;p	;p;p;p;p;p
;r�.qTPq`3qvV8Hq�q�'d"VPp
\Pq�V8Hq�p	V	'Eg\P!RV3RWg34RR\P!49g\P!V4'd\P !V4MRR\P !V4R\P !V4/,p
R	R
V
/,q�P#V4V'Ed\P!RV3RW�34RR\P!49g\P!V4'd\P !V4MRR\P !V
4R
R\P!49g!\P!\4'd\P !\4MRR\P !V4/,pRRV/,pVP#V4\P$!V^4/,pRRV/,p\'\P(!V44hR;p	;p;p;p;p;p
;r�\P*P-W$4R#uupi)uIBpskMod → BpskDemod must recover bits perfectly in a noiseless channel.�r	rr�py2r0�py4�py7�%(py9)s�py9�py11�py13�py15r�py17�%(py19)s�py19�assert %(py22)s�py22N�bits_out��==�z-%(py4)s
{%(py4)s = %(py2)s.shape
} == %(py7)s�zR%(py13)s
{%(py13)s = %(py11)s.dtype
} == %(py17)s
{%(py17)s = %(py15)s.complex64
}�zN%(py13)s
{%(py13)s = %(py11)s.dtype
} == %(py17)s
{%(py17)s = %(py15)s.uint8
})rrr�uint8r�BpskModr�	BpskDemod�shaper
�	complex64r"r#r$r%r&r'�append�_format_boolopr)r*�testing�assert_array_equal)r+�i�bits_inr0ror7�@py_assert3�@py_assert6�@py_assert5�@py_assert0�@py_assert12�@py_assert16�@py_assert14�@py_format8�@py_format10�@py_format18�@py_format20�@py_format21�@py_format23s                   r:�test_roundtrip_bpsk_noiselessr��s����A��h�h�u�Q�x�0�x�!�A���x�0����A�G�	���S�#�s�	#�	+�	+�G�	4�B��}�}�S�!�)�)�"�-�H�8�8�8�8�t�8�t��8�8����8�B�L�L�8�L� 8�8�8�8�8�8�8�8�8�8�8�8�2�8�8�8�8�2�8�8�8�8�8�8�8�t�8�8�8�8�8�8�8�8�8��L�8�8�8�8�8�8��8�8�8�8��8�8�8��8�8�8�8�8�8�B�8�8�8�8�B�8�8�8�L�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�8�@�>�>�@�T�@�T�!�@�@�h�n�n�@����@��&@�@�@�@�@�>�@�@�@�@�@�@�8�@�@�@�@�8�@�@�@�>�@�@�@�T�@�@�@�@�@�@�@�@�@�n�@�@�@�@�@�@�h�@�@�@�@�h�@�@�@�n�@�@�@�@�@�@��@�@�@�@��@�@�@��@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@��J�J�!�!�'�4��1s�V
c	��\\P!R44p\P!.RO\PR7p\
P!RRR4PV4pVPpRqCV8HqU'g�\P!RV3RW434RR\P!49g\P!V4'd\P!V4MRR\P!V4R\P!V4/,pR	R
V/,p\\P !V44hR;p;rT\P!VRV,,VRV,,
V)RV,,V)RV,,
.\P"R7p\P$P'W(R
R7R#)zGCheck all four constellation points against expected normalized values.rr	rrrr0rbrzassert %(py7)srdNy�?g�����ư>)�atol)�r�r��r�r�r�r�)�rp)z-%(py2)s
{%(py2)s = %(py0)s.shape
} == %(py5)s)rrrrrur�QpskModrrxr"r#r$r%r&r'r)r*ryr|�assert_allclose)	�S�bitsr0r7�@py_assert4r�r9r��expecteds	         r:�test_qpsk_mapper_symbolsr��s��
�b�g�g�c�l��A�
�8�8�(����9�D�	���S�#�s�	#�	+�	+�D�	1�B�
�8�8��t��t������8�������2�����2����8����t����������x�x��2�a�4���2�a�4��!��B�q�D��1�"�R��T�'�:�"�,�,�O�H��J�J���r�$��7rJc�V�Rp\P!\V^,4Uu.uFq^,V,^,NK	up\PR7p\P
!RRR4P
V4p\P!R4P
V4p.qSPq`3qvV8Hq�q�'d"VPp
\Pq�V8Hq�p	V	'Eg\P!RV3RWg34RR\P!49g\P!V4'd\P !V4MRR\P !V4R\P !V4/,p
RR	V
/,q�P#V4V'Ed\P!RX3RX
X34R
R\P!49g\P!V4'd\P !V4MRR\P !V
4RR
\P!49g!\P!\4'd\P !\4MR
R\P !V4/,pRRV/,pVP#V4\P$!V^4/,pRRV/,p\'\P(!V44hR;p	;p;p;p;p;p
;r�.qTPq`^,3qvV8Hq�q�'d"VPp
\Pq�V8Hq�p	V	'Eg\P!RV3RWg34RR\P!49g\P!V4'd\P !V4MRR\P !V4R\P !V4/,p
RR	V
/,q�P#V4V'Ed\P!RV3RW�34R
R\P!49g\P!V4'd\P !V4MRR\P !V
4RR
\P!49g!\P!\4'd\P !\4MR
R\P !V4/,pRRV/,pVP#V4\P$!V^4/,pRRV/,p\'\P(!V44hR;p	;p;p;p;p;p
;r�\P*P-W$4R#uupi)rar	rrrbr0rcrdrerfrgrhrirrjrkrlrmrnNrorprrrsrt)rrrrurr�r�	QpskDemodrxr
ryr"r#r$r%r&r'rzr{r)r*r|r})�n_symsr~rr0ror7r�r�r�r�r�r�r�r�r�r�r�r�r�s                   r:�test_roundtrip_qpsk_noiselessr��s���
�F��h�h�%���
�2C�D�2C�Q�a��!��q�(�(�2C�D�B�H�H�U�G�	���S�#�s�	#�	+�	+�G�	4�B��}�}�S�!�)�)�"�-�H�=�8�8�=�y�=�y� �=�=�R�X�X�=����=��%=�=�=�=�=�8�=�=�=�=�=�=�2�=�=�=�=�2�=�=�=�8�=�=�=�y�=�=�=�=�=�=�=�=�=�X��=�=�=�=�=�=�R�=�=�=�=�R�=�=�=�X�=�=�=�=�=�=��=�=�=�=��=�=�=��=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�I�>�>�I�q�j�]�I�]�*�I�I�x�~�~�I����I��/I�I�I�I�I�>�I�I�I�I�I�I�8�I�I�I�I�8�I�I�I�>�I�I�I�]�I�I�I�I�I�I�I�I�I�~�I�I�I�I�I�I�x�I�I�I�I�x�I�I�I�~�I�I�I�I�I�I��I�I�I�I��I�I�I��I�I�I�I�I�I�I�I�I�I�I�I�I�I�I�I��J�J�!�!�'�4��Es�V&zorder,bits_per_symc�j�RpW!,p\P!\V4Uu.uFpWA,WA,,^,NK!	up\PR7p\P
!VRRR4P
V4p\P!VR4P
V4p.q�Pq�3q�V
8Hq�q�'d"VPp
\Pq�V8Hq�pV'Eg\P!RV3RW�34RR\P!49g\P!V4'd\P !V4MRR\P !V	4R\P !V
4/,pR	R
V/,pVP#V4V'Ed\P!RX3RX
X34RR\P!49g\P!V4'd\P !V4MRR\P !V
4R
R\P!49g!\P!\4'd\P !\4MRR\P !V4/,pRRV/,pVP#V4\P$!V^4/,pRRV/,p\'\P(!V44hR;p;p;p	;p;p
;p
;r�.q�Pq�3q�V
8Hq�q�'d"VPp
\Pq�V8Hq�pV'Eg\P!RV3RW�34RR\P!49g\P!V4'd\P !V4MRR\P !V	4R\P !V
4/,pR	R
V/,pVP#V4V'Ed\P!RV3RW�34RR\P!49g\P!V4'd\P !V4MRR\P !V
4R
R\P!49g!\P!\4'd\P !\4MRR\P !V4/,pRRV/,pVP#V4\P$!V^4/,pRRV/,p\'\P(!V44hR;p;p;p	;p;p
;p
;r�\P*P-WWRVR2R7R#uupi)u>QamMod(order) → QamDemod(order) must recover bits perfectly.rar	rrrbr0rcrdrerfrgrhrirrjrkrlrmrnNrozQAM-z noiseless roundtrip failed)�err_msgrprrrsrt)rrrrur�QamModr�QamDemodrxr
ryr"r#r$r%r&r'rzr{r)r*r|r})�order�bits_per_symr��n_bitsr~rr0ror7r�r�r�r�r�r�r�r�r�r�r�r�r�s&&                    r:�test_roundtrip_qam_noiselessr��s����F�
�
"�F��h�h�!&�v��0�!.�A��*�Q�-=�=��B�B�!.�0�79�x�x�A�G�

���E�3��S�	)�	1�	1�'�	:�B��|�|�E�3�'�/�/��3�H�=�8�8�=�y�=�y� �=�=�R�X�X�=����=��%=�=�=�=�=�8�=�=�=�=�=�=�2�=�=�=�=�2�=�=�=�8�=�=�=�y�=�=�=�=�=�=�=�=�=�X��=�=�=�=�=�=�R�=�=�=�=�R�=�=�=�X�=�=�=�=�=�=��=�=�=�=��=�=�=��=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�E�>�>�E�Y�E�Y�&�E�E�8�>�>�E�R�X�X�E�X�+E�E�E�E�E�>�E�E�E�E�E�E�8�E�E�E�E�8�E�E�E�>�E�E�E�Y�E�E�E�E�E�E�E�E�E�>�E�E�E�E�E�E�8�E�E�E�E�8�E�E�E�>�E�E�E�E�E�E�R�E�E�E�E�R�E�E�E�X�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E��J�J�!�!���u�g�8�9�"���0s�%V0))�r�)�@�)ra�)�__doc__�builtinsr$�_pytest.assertion.rewrite�	assertion�rewriter"�numpyr�pytest�	orion_sdrr�conftestrrrrrBr;rIrNrWr[r_r�r�r��mark�parametrizer��rJr:�<module>r�s�������
��1�1���R�:@�	J� E�$@�@�
5�"8�
5�"�����-�/K�L��M�rJ