@@ -149,6 +149,46 @@ def test_src_vpu_rat_prepare():
149149 build_c (poly_ds_int , poly_us_int )
150150
151151
152+ def build_c_48t (poly_ds_48t_int ):
153+ coeffs_path = Path (__file__ ).resolve ().parent / "vpu_rat_48t_test" / "autogen"
154+ coeffs_path .mkdir (exist_ok = True , parents = True )
155+ gf .generate_48t_ds_header_file (coeffs_path )
156+ gf .generate_48t_ds_c_file (coeffs_path , poly_ds_48t_int )
157+ # Note: The autogenerated files are not compiled as part of the application. The copies of these committed in lib_src are compiled instead
158+ build_firmware_xcommon_cmake (Path (__file__ ).parent / "vpu_rat_48t_test" )
159+
160+
161+ def run_c_48t (fc_ex ):
162+ file_path = Path (__file__ ).parent
163+ testname = "vpu_rat_48t_test"
164+ xe = file_path / testname / "bin" / f"{ testname } .xe"
165+ app = f"xsim { xe } "
166+ subprocess .check_output (app .split ())
167+
168+ sig_bin = Path ("sig_c_32k.bin" )
169+ assert sig_bin .is_file (), "could not find output bin"
170+ sig32k_int = np .fromfile (sig_bin , dtype = np .int32 )
171+
172+ thdn , freq = THDN_and_freq (sig32k_int .astype (np .float64 ), 32000 )
173+ print (f"C 32k THDN: { thdn } , fc: { freq } " )
174+ assert_thdn_and_fc (thdn , freq , - 60 , fc_ex )
175+
176+ sig_bin = Path ("sig_c_48k.bin" )
177+ assert sig_bin .is_file (), "could not find output bin"
178+ sig48k_int = np .fromfile (sig_bin , dtype = np .int32 )
179+
180+ thdn , freq = THDN_and_freq (sig48k_int .astype (np .float64 ), 48000 )
181+ print (f"C 48k THDN: { thdn } , fc: { freq } " )
182+ assert_thdn_and_fc (thdn , freq , - 50 , fc_ex )
183+
184+
185+ @pytest .mark .prepare
186+ def test_src_vpu_rat_48t_prepare ():
187+ print (f"Preparing rat 48t test" )
188+ _ , _ , poly_ds_48t_int = gf .gen_coefs_48t_ds () # 2 phases x 24 taps, uses push_s32_24t and fir_s32_24t
189+ build_c_48t (poly_ds_48t_int )
190+
191+
152192@pytest .mark .parametrize (
153193 "test_freq" , [
154194 100 , 14000
@@ -166,3 +206,36 @@ def test_src_vpu_rat(test_freq):
166206 sig32k = downsample (sig_fl , taps , poly_ds , test_freq )
167207 upsample (sig32k , taps , poly_us , test_freq )
168208 run_c (test_freq )
209+
210+
211+ @pytest .mark .parametrize (
212+ "test_freq" , [
213+ 100 , 14000
214+ ]
215+ )
216+ @pytest .mark .main
217+ def test_src_vpu_rat_48t (test_freq ):
218+ """Test src_rat_2_3_48t_ds (exercises push_s32_24t and fir_s32_24t).
219+ Downsamples 48k->32k using 48t DS filter; upsamples back 32k->48k using existing 96t US filter.
220+ """
221+ print (f"Testing 48t rat DS { test_freq } Hz sinewave" )
222+ total_num_taps_us = 8 * 2 * 3 * 2 # 96 taps for US (reuse existing 96t design)
223+ taps_ds , poly_ds_48t , poly_ds_48t_int = gf .gen_coefs_48t_ds () # 2 phases x 24 taps per phase
224+ taps_us , _ , _ , poly_us , poly_us_int = gf .gen_coefs (total_num_taps_us )
225+
226+ working_dir = Path (tempfile .mkdtemp (prefix = "test_src_vpu_rat_48t" , dir = Path (__file__ ).parent ))
227+ with tmp_dir (working_dir ):
228+ sig_fl , sig_int = get_sig (test_freq )
229+
230+ # Python-side downsampling check with bounds appropriate for a 48t filter
231+ sig32k = np .zeros (len (sig_fl ) * 2 // 3 )
232+ buff = np .zeros (len (sig_fl ) * 2 )
233+ buff [0 ::2 ] = sig_fl
234+ buff = signal .convolve (buff , taps_ds , "same" , "direct" ) * 2
235+ sig32k = buff [0 ::3 ]
236+ thdn , freq = THDN_and_freq (sig32k .astype (np .float64 ), 32000 )
237+ print (f"PY 32k THDN: { thdn } , fc: { freq } " )
238+ assert_thdn_and_fc (thdn , freq , - 60 , test_freq )
239+
240+ upsample (sig32k , taps_us , poly_us , test_freq )
241+ run_c_48t (test_freq )
0 commit comments