Skip to content

Commit 5509bd5

Browse files
authored
Merge pull request #80 from shuchitak/feature/high_precision_rate_ratio
High precision fs_rate_ratio
2 parents af63c32 + d13b965 commit 5509bd5

9 files changed

Lines changed: 347 additions & 266 deletions

File tree

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ lib_src change log
1414
* REMOVED: AN00231 ASRC App Note. See github.com/xmos/sln_voice/examples
1515
* CHANGED: Increased precision of the fFsRatioDeviation used in the C emulator
1616
from float to double
17+
* CHANGED: Allow for 64 bits in the rate ratio passed to asrc_process() for
18+
extra precision
1719

1820
* Changes to dependencies:
1921

lib_src/api/src.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,21 +77,21 @@ unsigned ssrc_process(int in_buff[], int out_buff[], ssrc_ctrl_t ssrc_ctrl[]);
7777
* \param n_channels_per_instance Number of channels handled by this instance of SSRC
7878
* \param n_in_samples Number of input samples per SSRC call
7979
* \param dither_on_off Dither to 24b on/off
80-
* \returns The nominal sample rate ratio of in to out in Q4.28 format
80+
* \returns The nominal sample rate ratio of in to out in Q4.60 format
8181
*/
82-
unsigned asrc_init(const fs_code_t sr_in, const fs_code_t sr_out,
82+
uint64_t asrc_init(const fs_code_t sr_in, const fs_code_t sr_out,
8383
asrc_ctrl_t asrc_ctrl[], const unsigned n_channels_per_instance,
8484
const unsigned n_in_samples, const dither_flag_t dither_on_off);
8585

8686
/** Perform asynchronous sample rate conversion processing on block of input samples using previously initialized settings.
8787
*
8888
* \param in_buff Reference to input sample buffer array
8989
* \param out_buff Reference to output sample buffer array
90-
* \param fs_ratio Fixed point ratio of in/out sample rates in Q4.28 format
90+
* \param fs_ratio Fixed point ratio of in/out sample rates in Q4.60 format
9191
* \param asrc_ctrl Reference to array of ASRC control structures
9292
* \returns The number of output samples produced by the SRC operation.
9393
*/
94-
unsigned asrc_process(int in_buff[], int out_buff[], unsigned fs_ratio,
94+
unsigned asrc_process(int in_buff[], int out_buff[], uint64_t fs_ratio,
9595
asrc_ctrl_t asrc_ctrl[]);
9696

9797
/**@}*/ // END: addtogroup src_asrc

lib_src/src/multirate_hifi/asrc/src_mrhf_asrc.c

Lines changed: 136 additions & 100 deletions
Large diffs are not rendered by default.

lib_src/src/multirate_hifi/asrc/src_mrhf_asrc.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2016-2021 XMOS LIMITED.
1+
// Copyright 2016-2023 XMOS LIMITED.
22
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
33
// ===========================================================================
44
// ===========================================================================
@@ -33,9 +33,10 @@
3333

3434
// General defines
3535
// ---------------
36+
#define ASRC_FS_RATIO_UNIT_BIT 28
3637
#define ASRC_STACK_LENGTH_MULT (ASRC_N_CHANNELS * 4) // Multiplier for stack length (stack length = this value x the number of input samples to process)
37-
#define ASRC_ADFIR_COEFS_LENGTH FILTER_DEFS_ADFIR_PHASE_N_TAPS // Length of AD FIR coefficients buffer
38-
#define ASRC_NOMINAL_FS_SCALE (268435456) //Nominal Fs Ratio scale value in 4.28 format
38+
#define ASRC_ADFIR_COEFS_LENGTH FILTER_DEFS_ADFIR_PHASE_N_TAPS // Length of AD FIR coefficients buffer
39+
#define ASRC_NOMINAL_FS_SCALE (1 << ASRC_FS_RATIO_UNIT_BIT)
3940

4041

4142
// Parameter values
@@ -105,6 +106,7 @@
105106
typedef struct _ASRCFsRatioConfigs
106107
{
107108
unsigned int uiNominalFsRatio;
109+
unsigned int uiNominalFsRatio_lo;
108110
unsigned int uiMinFsRatio;
109111
unsigned int uiMaxFsRatio;
110112
int iFsRatioShift;
@@ -142,6 +144,7 @@
142144
ADFIRCtrl_t sADFIRF3Ctrl; // F3 ADFIR controller
143145

144146
unsigned int uiFsRatio; // Fs ratio: Fsin / Fsout
147+
unsigned int uiFsRatio_lo;
145148

146149
int iTimeInt; // Integer part of time
147150
unsigned int uiTimeFract; // Fractional part of time
@@ -170,6 +173,7 @@
170173
ADFIRCtrl_t sADFIRF3Ctrl; // F3 ADFIR controller
171174

172175
unsigned int uiFsRatio; // Fs ratio: Fsin / Fsout
176+
unsigned int uiFsRatio_lo;
173177

174178
int iTimeInt; // Integer part of time
175179
unsigned int uiTimeFract; // Fractional part of time

lib_src/src/multirate_hifi/asrc/src_mrhf_asrc_wrapper.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2016-2021 XMOS LIMITED.
1+
// Copyright 2016-2023 XMOS LIMITED.
22
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
33
// General includes
44
#include <stdlib.h>
@@ -23,21 +23,21 @@ static void asrc_error(int code)
2323
}
2424

2525

26-
unsigned asrc_init(const fs_code_t sr_in, const fs_code_t sr_out, asrc_ctrl_t asrc_ctrl[], const unsigned n_channels_per_instance,
26+
uint64_t asrc_init(const fs_code_t sr_in, const fs_code_t sr_out, asrc_ctrl_t asrc_ctrl[], const unsigned n_channels_per_instance,
2727
const unsigned n_in_samples, const dither_flag_t dither_on_off)
2828
{
2929
unsigned ui;
3030

3131
ASRCReturnCodes_t ret_code;
3232

3333
ret_code = ASRC_prepare_coefs();
34+
3435
if (ret_code != ASRC_NO_ERROR) asrc_error(10);
3536

3637
//Check to see if n_channels_per_instance, n_in_samples are reasonable
3738
if ((n_in_samples & 0x1) || (n_in_samples < 4)) asrc_error(100);
3839
if (n_channels_per_instance < 1) asrc_error(101);
3940

40-
4141
for(ui = 0; ui < n_channels_per_instance; ui++)
4242
{
4343
// Set number of channels per instance
@@ -56,47 +56,54 @@ unsigned asrc_init(const fs_code_t sr_in, const fs_code_t sr_out, asrc_ctrl_t as
5656

5757
// Init ASRC instances
5858
ret_code = ASRC_init(&asrc_ctrl[ui]);
59+
5960
if (ret_code != ASRC_NO_ERROR) asrc_error(11);
6061
}
6162

6263
// Sync
6364
// ----
6465
// Sync ASRC. This is just to show that the function works and returns success
66+
6567
for(ui = 0; ui < n_channels_per_instance; ui++) {
6668
ret_code = ASRC_sync(&asrc_ctrl[ui]);
6769
if (ret_code != ASRC_NO_ERROR) asrc_error(12);
6870
}
6971

70-
return (asrc_ctrl[0].uiFsRatio);
72+
return (uint64_t)((((uint64_t)asrc_ctrl[0].uiFsRatio) << 32) | asrc_ctrl[0].uiFsRatio_lo);
7173
}
7274

73-
unsigned asrc_process(int *in_buff, int *out_buff, unsigned fs_ratio, asrc_ctrl_t asrc_ctrl[]){
75+
unsigned asrc_process(int *in_buff, int *out_buff, uint64_t fs_ratio, asrc_ctrl_t asrc_ctrl[]){
7476

7577
int ui, uj; //General counters
7678
int uiSplCntr; //Spline counter
7779

7880
// Get the number of channels per instance from first channel
7981
const unsigned n_channels_per_instance = asrc_ctrl[0].uiNchannels;
8082

83+
uint32_t fs_ratio_hi = (uint32_t)(fs_ratio >> 32);
84+
uint32_t fs_ratio_lo = (uint32_t)(fs_ratio);
8185

8286
for(ui = 0; ui < n_channels_per_instance; ui++)
8387
{
8488
// Update Fs Ratio
85-
asrc_ctrl[ui].uiFsRatio = fs_ratio;
89+
asrc_ctrl[ui].uiFsRatio = fs_ratio_hi;
90+
asrc_ctrl[ui].uiFsRatio_lo = fs_ratio_lo;
8691

8792
#if DO_FS_BOUNDS_CHECK
8893
// Check for bounds of new Fs ratio
89-
if( (fs_ratio < sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiMinFsRatio) ||
90-
(fs_ratio > sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiMaxFsRatio) )
94+
if( (fs_ratio_hi < sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiMinFsRatio) ||
95+
(fs_ratio_hi > sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiMaxFsRatio) )
9196
{
92-
//debug_printf("Passed = %x, Nominal = 0x%x\n", fs_ratio, sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiNominalFsRatio);
93-
fs_ratio = sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiNominalFsRatio; //Important to prevent buffer overflow if fs_ratio requests too many samples.
97+
//debug_printf("Passed = %x, Nominal = 0x%x\n", fs_ratio_hi, sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiNominalFsRatio);
98+
fs_ratio_hi = sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiNominalFsRatio; //Important to prevent buffer overflow if fs_ratio requests too many samples.
99+
fs_ratio_lo = sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].uiNominalFsRatio_lo;
94100
//debug_printf("!");
95101
}
96102
#endif
97103
// Apply shift to time ratio to build integer and fractional parts of time step
98-
asrc_ctrl[ui].iTimeStepInt = fs_ratio >> (sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].iFsRatioShift);
99-
asrc_ctrl[ui].uiTimeStepFract = fs_ratio << (32 - sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].iFsRatioShift);
104+
asrc_ctrl[ui].iTimeStepInt = fs_ratio_hi >> (sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].iFsRatioShift);
105+
asrc_ctrl[ui].uiTimeStepFract = fs_ratio_hi << (32 - sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].iFsRatioShift);
106+
asrc_ctrl[ui].uiTimeStepFract |= (uint32_t)(fs_ratio_lo >> sFsRatioConfigs[asrc_ctrl[ui].eInFs][asrc_ctrl[ui].eOutFs].iFsRatioShift);
100107

101108

102109

tests/asrc_test/dut/asrc_test.xc

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void dsp_slave(chanend c_dsp)
5858

5959
unsigned int n_samps_out = 0; //number of samples produced by last call to ASRC
6060
unsigned int n_samps_in_tot = 0; //Total number of input samples through ASRC
61-
unsigned int FsRatio = ASRC_NOMINAL_FS_SCALE; //Deviation between in Fs and out Fs
61+
uint64_t FsRatio = ASRC_NOMINAL_FS_SCALE; //Deviation between in Fs and out Fs
6262

6363
for(int ui = 0; ui < ASRC_CHANNELS_PER_INSTANCE; ui++)
6464
unsafe {
@@ -68,19 +68,6 @@ void dsp_slave(chanend c_dsp)
6868
asrc_ctrl[ui].piADCoefs = asrc_adfir_coefs.iASRCADFIRCoefs;
6969
}
7070

71-
/*
72-
// Update Fs Ratio
73-
for(int i = 0; i < ASRC_N_CHANNELS; i++)
74-
{
75-
// Make Fs Ratio deviate
76-
asrc_ctrl[i].uiFsRatio = (unsigned int)((double)asrc_ctrl[i].uiFsRatio * fFsRatioDeviation);
77-
if(ASRC_update_fs_ratio(&asrc_ctrl[i]) != ASRC_NO_ERROR)
78-
{
79-
printf("Error updating ASRC fs ratio\n");
80-
}
81-
}
82-
*/
83-
8471
memset(out_buff, 0, ASRC_N_IN_SAMPLES * ASRC_N_OUT_IN_RATIO_MAX * ASRC_CHANNELS_PER_INSTANCE * sizeof(int));
8572

8673
while(1){
@@ -120,10 +107,10 @@ void dsp_slave(chanend c_dsp)
120107
unsigned InFs = (sr_in_out_new >> 16) & 0xffff;
121108
unsigned OutFs = sr_in_out_new & 0xffff;
122109

123-
unsigned nominal_FsRatio = asrc_init(InFs, OutFs, asrc_ctrl, ASRC_CHANNELS_PER_INSTANCE, ASRC_N_IN_SAMPLES, ASRC_DITHER_SETTING);
110+
uint64_t nominal_FsRatio = asrc_init(InFs, OutFs, asrc_ctrl, ASRC_CHANNELS_PER_INSTANCE, ASRC_N_IN_SAMPLES, ASRC_DITHER_SETTING);
124111

125112
sr_in_out = sr_in_out_new;
126-
printf("DSP init Initial nominal_FsRatio=%d, SR in=%d, SR out=%d\n", nominal_FsRatio, InFs, OutFs);
113+
printf("DSP init Initial nominal_FsRatio=%lld, SR in=%d, SR out=%d\n", nominal_FsRatio, InFs, OutFs);
127114
}
128115
t:> t1;
129116
n_samps_out = asrc_process(in_buff, out_buff, FsRatio, asrc_ctrl);
@@ -139,10 +126,11 @@ void dsp_mgr(chanend c_dsp[], double fFsRatioDeviation){
139126
unsigned count_in = 0, count_out = 0;
140127
unsigned iEndOfFile = 0;
141128
unsigned int sr_in_out = uiInFs << 16 | uiOutFs ; //Input fs in upper 16bits and Output fs in lower 16bits
142-
unsigned FsRatio = (unsigned) (((unsigned long long)sample_rates[uiInFs] * (unsigned long long)(1<<28)) / (unsigned long long)sample_rates[uiOutFs]);
143129

144-
FsRatio = (unsigned int)((double)FsRatio * fFsRatioDeviation); //Ensure is precisely the same as golden value complete with trucation due to 32b float
145-
printf("Adjusted FsRatio dsp_mgr = %d, 0x%x\n", FsRatio, FsRatio);
130+
uint64_t FsRatio = (unsigned long long)(((double)sample_rates[uiInFs] / sample_rates[uiOutFs]) * ((unsigned long long)1 << (28 + 32)));
131+
132+
FsRatio = (uint64_t)((double)FsRatio * fFsRatioDeviation); //Ensure is precisely the same as golden value complete with trucation due to 32b float
133+
printf("Adjusted FsRatio dsp_mgr = %lld, 0x%llx\n", FsRatio, FsRatio);
146134

147135

148136

@@ -346,7 +334,7 @@ void ParseCmdLine(char *input, char * unsafe * argv, int ui)
346334
}
347335
}
348336

349-
int main(int argc, char * unsafe argv[])
337+
int main(unsigned int argc, char * unsafe argv[argc])
350338
{
351339
int ui;
352340

0 commit comments

Comments
 (0)