[Sound-open-firmware] [PATCH] SOFT: Add SRC coefficients generate tool
Seppo Ingalsuo
seppo.ingalsuo at linux.intel.com
Mon Jun 4 10:02:00 CEST 2018
This patch adds the scripts src_std_int32.m and src_tiny_int16.m those
were used to create the conversions matrices for the default and tiny
profiles. The scripts call the included src_generate function that
does the task with help from the filter design and coefficients
export utilities.
The quality and resources consumption of SRC can be customized with
this tool.
Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
---
tune/src/README | 36 +++++
tune/src/src_export_coef.m | 212 ++++++++++++++++++++++++++++
tune/src/src_export_defines.m | 66 +++++++++
tune/src/src_export_table_2s.m | 190 +++++++++++++++++++++++++
tune/src/src_factor1_lm.m | 44 ++++++
tune/src/src_factor2_lm.m | 155 ++++++++++++++++++++
tune/src/src_find_l0m0.m | 71 ++++++++++
tune/src/src_generate.m | 311 +++++++++++++++++++++++++++++++++++++++++
tune/src/src_get.m | 254 +++++++++++++++++++++++++++++++++
tune/src/src_param.m | 87 ++++++++++++
tune/src/src_std_int32.m | 30 ++++
tune/src/src_tiny_int16.m | 41 ++++++
12 files changed, 1497 insertions(+)
create mode 100644 tune/src/README
create mode 100644 tune/src/src_export_coef.m
create mode 100644 tune/src/src_export_defines.m
create mode 100644 tune/src/src_export_table_2s.m
create mode 100644 tune/src/src_factor1_lm.m
create mode 100644 tune/src/src_factor2_lm.m
create mode 100644 tune/src/src_find_l0m0.m
create mode 100644 tune/src/src_generate.m
create mode 100644 tune/src/src_get.m
create mode 100644 tune/src/src_param.m
create mode 100644 tune/src/src_std_int32.m
create mode 100644 tune/src/src_tiny_int16.m
diff --git a/tune/src/README b/tune/src/README
new file mode 100644
index 0000000..e135f9a
--- /dev/null
+++ b/tune/src/README
@@ -0,0 +1,36 @@
+Sample rate converter (SRC) Setup Tools
+=======================================
+
+This is a tool to set up SRC conversions sample rates list, define
+quality related parameters, and test the C implementation for a number
+of objective audio quality parameters.
+
+The tools need GNU Octave version 4.0.0 or later with octave-signal
+package.
+
+src_std_int32.m
+---------------
+
+This script creates the default coefficient set and contains nothing
+else but call for src_generate.
+
+src_tiny_int16.m
+----------------
+
+This script creates the tiny coefficient set. The script contains an
+example how to customize the input/output rates matrix and in a simple
+way the scale conversions quality. More controlled quality adjust can
+be done by editing file src_param.m directly. Note that int16
+presentation for SRC coefficients will degrade even the default
+quality.
+
+src_generate.m
+--------------
+
+Creates the header files to include to C into directory "include". A
+report of create modes is written to directory "reports". The
+coefficients need to be copied to directory
+sof.git/src/include/sof/audio/coefficients/src.
+
+The default quality of SRC is defined in module src_param.m. The
+quality impacts the complexity and coefficents tables size of SRC.
diff --git a/tune/src/src_export_coef.m b/tune/src/src_export_coef.m
new file mode 100644
index 0000000..f6fdbb4
--- /dev/null
+++ b/tune/src/src_export_coef.m
@@ -0,0 +1,212 @@
+function success=src_export_coef(src, ctype, vtype, hdir, profile)
+
+% src_export_coef - Export FIR coefficients
+%
+% success=src_export_coef(src, ctype, hdir, profile)
+%
+% src - src definition struct
+% ctype - 'float','int32', or 'int24'
+% vtype - 'float','int32_t'
+% hdir - directory for header files
+% profile - string to append to filename
+%
+
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+if nargin < 5
+ profile = '';
+end
+
+if src.L == src.M
+ success = 0;
+else
+ pbi = round(src.c_pb*1e4);
+ sbi = round(src.c_sb*1e4);
+ if isempty(profile)
+ hfn = sprintf('%s/src_%s_%d_%d_%d_%d.h', ...
+ hdir, ctype, src.L, src.M, pbi, sbi);
+ else
+ hfn = sprintf('%s/src_%s_%s_%d_%d_%d_%d.h', ...
+ hdir, profile, ctype, src.L, src.M, pbi, sbi);
+ end
+ vfn = sprintf('src_%s_%d_%d_%d_%d_fir', ctype, src.L, src.M, pbi, sbi);
+ sfn = sprintf('src_%s_%d_%d_%d_%d', ctype, src.L, src.M, pbi, sbi);
+
+ fprintf('Exporting %s ...\n', hfn);
+ fh = fopen(hfn, 'w');
+
+ switch ctype
+ case 'float'
+ fprintf(fh, 'const %s %s[%d] = {\n', ...
+ vtype, vfn, src.filter_length);
+ fprintf(fh,'\t%16.9e', src.coefs(1));
+ for n=2:src.filter_length
+ fprintf(fh, ',\n');
+ fprintf(fh,'\t%16.9e', src.coefs(n));
+ end
+ fprintf(fh,'\n\n};');
+ case 'int32'
+ print_int_coef(src, fh, vtype, vfn, 32);
+ case 'int24'
+ print_int_coef(src, fh, vtype, vfn, 24);
+ case 'int16'
+ print_int_coef(src, fh, vtype, vfn, 16);
+ otherwise
+ error('Unknown type %s !!!', ctype);
+ end
+
+ fprintf(fh, '\n');
+ switch ctype
+ case 'float'
+ fprintf(fh, 'struct src_stage %s = {\n', sfn);
+ fprintf(fh, '\t%d, %d, %d, %d, %d, %d, %d, %d, %f,\n\t%s};\n', ...
+ src.idm, src.odm, src.num_of_subfilters, ...
+ src.subfilter_length, src.filter_length, ...
+ src.blk_in, src.blk_out, src.halfband, ...
+ src.gain, vfn);
+ case { 'int16' 'int24' 'int32' }
+ fprintf(fh, 'struct src_stage %s = {\n', sfn);
+ fprintf(fh, '\t%d, %d, %d, %d, %d, %d, %d, %d, %d,\n\t%s};\n', ...
+ src.idm, src.odm, src.num_of_subfilters, ...
+ src.subfilter_length, src.filter_length, ...
+ src.blk_in, src.blk_out, src.halfband, ...
+ src.shift, vfn);
+ otherwise
+ error('Unknown type %s !!!', ctype);
+ end
+ %fprintf(fh, '\n');
+ fclose(fh);
+ success = 1;
+end
+
+end
+
+function print_int_coef(src, fh, vtype, vfn, nbits)
+ fprintf(fh, 'const %s %s[%d] = {\n', ...
+ vtype, vfn, src.filter_length);
+
+ cint = coef_quant(src, nbits);
+ fprintf(fh,'\t%d', cint(1));
+ for n=2:src.filter_length
+ fprintf(fh, ',\n');
+ fprintf(fh,'\t%d', cint(n));
+ end
+ fprintf(fh,'\n\n};');
+end
+
+function cint = coef_quant(src, nbits)
+
+ sref = 2^(nbits-1);
+ pmax = sref-1;
+ nmin = -sref;
+
+ if nbits > 16
+ %% Round() is OK
+ cint0 = round(sref*src.coefs);
+ else
+ %% Prepare to optimize coefficient quantization
+ fs = max(src.fs1, src.fs2);
+ f = linspace(0, fs/2, 1000);
+
+ %% Test sensitivity for stopband and find the most sensitive
+ % coefficients
+ sbf = linspace(src.f_sb,fs/2, 500);
+ n = src.filter_length;
+ psens = zeros(1,n);
+ bq0 = round(sref*src.coefs);
+ h = freqz(bq0/sref/src.L, 1, sbf, fs);
+ sb1 = 20*log10(sqrt(sum(h.*conj(h))));
+ for i=1:n
+ bq = src.coefs;
+ bq(i) = round(sref*bq(i))/sref;
+ %tbq = bq; %tbq(i) = bq(i)+1;
+ h = freqz(bq, 1, sbf, fs);
+ psens(i) = sum(h.*conj(h));
+ end
+ [spsens, pidx] = sort(psens, 'descend');
+
+ %% Test quantization in the found order
+ % The impact to passband is minimal so it's not tested
+ bi = round(sref*src.coefs);
+ bi0 = bi;
+ dl = -1:1;
+ nd = length(dl);
+ msb = zeros(1,nd);
+ for i=pidx
+ bit = bi;
+ for j=1:nd
+ bit(i) = bi(i) + dl(j);
+ h = freqz(bit, 1, sbf, fs);
+ msb(j) = sum(h.*conj(h));
+ end
+ idx = find(msb == min(msb), 1, 'first');
+ bi(i) = bi(i) + dl(idx);
+ end
+ h = freqz(bi/sref/src.L, 1, sbf, fs);
+ sb2 = 20*log10(sqrt(sum(h.*conj(h))));
+
+ %% Plot to compare
+ if 0
+ f = linspace(0, fs/2, 1000);
+ h1 = freqz(src.coefs/src.L, 1, f, fs);
+ h2 = freqz(bq0/sref/src.L, 1, f, fs);
+ h3 = freqz(bi/sref/src.L, 1, f, fs);
+ figure;
+ plot(f, 20*log10(abs(h1)), f, 20*log10(abs(h2)), f, 20*log10(abs(h3)));
+ grid on;
+ fprintf('Original = %4.1f dB, optimized = %4.1f dB, delta = %4.1f dB\n', ...
+ sb1, sb2, sb1-sb2);
+ end
+ cint0 = bi;
+ end
+
+
+ %% Re-order coefficients for filter implementation
+ cint = zeros(src.filter_length,1);
+ for n = 1:src.num_of_subfilters
+ i11 = (n-1)*src.subfilter_length+1;
+ i12 = i11+src.subfilter_length-1;
+ cint(i11:i12) = cint0(n:src.num_of_subfilters:end);
+ end
+
+ %% Done check for no overflow
+ max_fix = max(cint);
+ min_fix = min(cint);
+ if (max_fix > pmax)
+ printf('Fixed point coefficient %d exceeded %d\n.', max_fix, pmax);
+ error('Something went wrong!');
+ end
+ if (min_fix < nmin)
+ printf('Fixed point coefficient %d exceeded %d\n.', min_fix, nmax);
+ error('Something went wrong!');
+ end
+
+
+end
diff --git a/tune/src/src_export_defines.m b/tune/src/src_export_defines.m
new file mode 100644
index 0000000..63fb4c2
--- /dev/null
+++ b/tune/src/src_export_defines.m
@@ -0,0 +1,66 @@
+function src_export_defines(defs, ctype, hdir, profile)
+
+% src_export_defines - Exports the constants to header files
+%
+% src_export_defines(defs, ctype, hdir)
+%
+% defs - defs struct
+% ctype - e.g. 'int24' appended to file name
+% hdir - directory for header file
+% profile - string to append to file name
+%
+
+
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+if nargin < 4
+ profile = '';
+end
+
+if isempty(profile)
+ hfn = sprintf('src_%s_define.h', ctype);
+else
+ hfn = sprintf('src_%s_%s_define.h', profile, ctype);
+end
+fh = fopen(fullfile(hdir,hfn), 'w');
+fprintf(fh, '/* SRC constants */\n');
+fprintf(fh, '#define MAX_FIR_DELAY_SIZE %d\n', defs.fir_delay_size);
+fprintf(fh, '#define MAX_OUT_DELAY_SIZE %d\n', defs.out_delay_size);
+fprintf(fh, '#define MAX_BLK_IN %d\n', defs.blk_in);
+fprintf(fh, '#define MAX_BLK_OUT %d\n', defs.blk_out);
+fprintf(fh, '#define NUM_IN_FS %d\n', defs.num_in_fs);
+fprintf(fh, '#define NUM_OUT_FS %d\n', defs.num_out_fs);
+fprintf(fh, '#define STAGE1_TIMES_MAX %d\n', defs.stage1_times_max);
+fprintf(fh, '#define STAGE2_TIMES_MAX %d\n', defs.stage2_times_max);
+fprintf(fh, '#define STAGE_BUF_SIZE %d\n', defs.stage_buf_size);
+fprintf(fh, '#define NUM_ALL_COEFFICIENTS %d\n', defs.sum_filter_lengths);
+fclose(fh);
+
+end
diff --git a/tune/src/src_export_table_2s.m b/tune/src/src_export_table_2s.m
new file mode 100644
index 0000000..7772b93
--- /dev/null
+++ b/tune/src/src_export_table_2s.m
@@ -0,0 +1,190 @@
+function sfl = src_export_table_2s(fs_in, fs_out, l_2s, m_2s, ...
+ pb_2s, sb_2s, taps_2s, ctype, vtype, ppath, hdir, profile)
+
+% src_export_table_2s - Export src setup table
+%
+% src_export_table_2s(fs_in, fs_out, l, m, pb, sb, ctype, vtype, hdir, profile)
+%
+% The parameters are used to differentiate files for possibly many same
+% conversion factor filters with possibly different characteristic.
+%
+% fs_in - input sample rates
+% fs_out - output sample rates
+% l - interpolation factors
+% m - decimation factors
+% pb - passband widths
+% sb - stopband start frequencies
+% ctype - coefficient quantization
+% vtype - C variable type
+% ppath - print directory prefix to header file name include
+% hdir - directory for header files
+% profile - string to append to file name
+%
+
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+if nargin < 12
+ profile = '';
+end
+
+if isempty(profile)
+ hfn = sprintf('src_%s_table.h', ctype);
+else
+ hfn = sprintf('src_%s_%s_table.h', profile, ctype);
+end
+fh = fopen(fullfile(hdir,hfn), 'w');
+
+fprintf(fh, '/* SRC conversions */\n');
+sfl = 0;
+n_in = length(fs_in);
+n_out = length(fs_out);
+i=1;
+all_modes = zeros(2*n_in*n_out, 7);
+for n=1:2
+ for b=1:n_out
+ for a=1:n_in
+ all_modes(i,:) = [ l_2s(n,a,b) m_2s(n,a,b) ...
+ pb_2s(n,a,b) sb_2s(n,a,b) n a b ];
+ i=i+1;
+ end
+ end
+end
+
+all_modes_sub = all_modes(:,1:4);
+[unique_modes, ia] = unique(all_modes_sub,'rows');
+sm = size(unique_modes);
+
+if isempty(profile)
+ prof_ctype = ctype;
+else
+ prof_ctype = sprintf('%s_%s', profile, ctype);
+end
+for i=1:sm(1)
+ um_tmp = unique_modes(i,:);
+ if isequal(um_tmp(1:2),[1 1]) || isequal(um_tmp(1:2),[0 0])
+ else
+ fprintf(fh, '#include <%ssrc_%s_%d_%d_%d_%d.h>\n', ...
+ ppath, prof_ctype, um_tmp(1:4));
+
+ n = all_modes(ia(i), 5);
+ a = all_modes(ia(i), 6);
+ b = all_modes(ia(i), 7);
+ sfl = sfl +taps_2s(n, a, b); % Count sum of filter lengths
+ end
+end
+fprintf(fh,'\n');
+
+fprintf(fh, '/* SRC table */\n');
+switch ctype
+ case 'float'
+ fprintf(fh, '%s fir_one = 1.0;\n', vtype);
+ fprintf(fh, 'struct src_stage src_double_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, 1.0, &fir_one };\n');
+ fprintf(fh, 'struct src_stage src_double_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0.0, &fir_one };\n');
+ case 'int16'
+ scale16 = 2^15;
+ fprintf(fh, '%s fir_one = %d;\n', vtype, round(scale16*0.5));
+ fprintf(fh, 'struct src_stage src_int16_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n');
+ fprintf(fh, 'struct src_stage src_int16_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n');
+ case 'int24'
+ scale24 = 2^23;
+ fprintf(fh, '%s fir_one = %d;\n', vtype, round(scale24*0.5));
+ fprintf(fh, 'struct src_stage src_int24_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n');
+ fprintf(fh, 'struct src_stage src_int24_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n');
+ case 'int32'
+ scale32 = 2^31;
+ fprintf(fh, '%s fir_one = %d;\n', vtype, round(scale32*0.5));
+ fprintf(fh, 'struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n');
+ fprintf(fh, 'struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n');
+ otherwise
+ error('Unknown coefficient type!');
+end
+
+fprintf(fh, 'int src_in_fs[%d] = {', n_in);
+j = 1;
+for i=1:n_in
+ fprintf(fh, ' %d', fs_in(i));
+ if i < n_in
+ fprintf(fh, ',');
+ end
+ j = j + 1;
+ if (j > 8)
+ fprintf(fh, '\n\t');
+ j = 1;
+ end
+end
+fprintf(fh, '};\n');
+
+fprintf(fh, 'int src_out_fs[%d] = {', n_out);
+j = 1;
+for i=1:n_out
+ fprintf(fh, ' %d', fs_out(i));
+ if i < n_out
+ fprintf(fh, ',');
+ end
+ j = j + 1;
+ if (j > 8)
+ fprintf(fh, '\n\t');
+ j = 1;
+ end
+end
+fprintf(fh, '};\n');
+
+for n = 1:2
+ fprintf(fh, 'struct src_stage *src_table%d[%d][%d] = {\n', ...
+ n, n_out, n_in);
+ i = 1;
+ for b = 1:n_out
+ fprintf(fh, '\t{');
+ for a = 1:n_in
+ fprintf(fh, ' &src_%s_%d_%d_%d_%d', ...
+ ctype, l_2s(n,a,b), m_2s(n,a,b), ...
+ pb_2s(n,a,b), sb_2s(n,a,b));
+ if a < n_in
+ fprintf(fh, ',');
+ end
+ i = i + 1;
+ if i > 2
+ fprintf(fh, '\n\t');
+ i = 1;
+ end
+ end
+ fprintf(fh, '}');
+ if b < n_out
+ fprintf(fh, ',\n');
+ else
+ fprintf(fh, '\n');
+ end
+ end
+ fprintf(fh, '};\n');
+end
+
+fclose(fh);
+
+end
diff --git a/tune/src/src_factor1_lm.m b/tune/src/src_factor1_lm.m
new file mode 100644
index 0000000..54e9173
--- /dev/null
+++ b/tune/src/src_factor1_lm.m
@@ -0,0 +1,44 @@
+function [l, m] = src_factor1_lm(fs1, fs2)
+
+% factor1_lm - factorize input and output sample rates ratio to fraction l/m
+%
+% [l, m] = factor1_lm(fs1, fs2)
+%
+% fs1 - input sample rate
+% fs2 - output sample rate
+%
+
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+k = gcd(fs1, fs2);
+l = fs2/k;
+m = fs1/k;
+
+end
diff --git a/tune/src/src_factor2_lm.m b/tune/src/src_factor2_lm.m
new file mode 100644
index 0000000..6ac8602
--- /dev/null
+++ b/tune/src/src_factor2_lm.m
@@ -0,0 +1,155 @@
+function [l1, m1, l2, m2] = src_factor2_lm(fs1, fs2)
+
+% factor2_lm - factorize input and output sample rates ratio to fraction l1/m2*l2/m2
+%
+% [l1, m1, l2, m2] = factor2_lm(fs1, fs2)
+%
+% fs1 - input sample rate
+% fs2 - output sample rate
+%
+
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+
+%% The same sample rate?
+if abs(fs1-fs2) < eps
+ l1 = 1; m1 = 1; l2 = 1; m2 = 1;
+ return
+end
+
+%% Find fraction, and factorize
+k = gcd(fs1, fs2);
+l = fs2/k;
+m = fs1/k;
+[l01, l02] = factor2(l);
+[m01, m02] = factor2(m);
+
+%% Hand fixing for some ratios, guide to reuse some common filters
+if (l==147) && (m==640)
+ l01 = 7; m01 = 8; l02 = l/l01; m02 = m/m01; % 192 to 44.1
+end
+if (l==147) && (m==320)
+ l01 = 7; m01 = 8; l02 = l/l01; m02 = m/m01; % 96 to 44.1
+end
+if (l==147) && (m==160)
+ l01 = 7; m01 = 8; l02 = l/l01; m02 = m/m01; % 48 to 44.1
+end
+if (l==160) && (m==147)
+ l01 = 8; m01 = 7; l02 = l/l01; m02 = m/m01; % 44.1 to 48
+end
+if (l==320) && (m==147)
+ l01 = 8; m01 = 7; l02 = l/l01; m02 = m/m01; % 44.1 to 96
+end
+if (l==4) && (m==3)
+ l01 = 4; m01 = 3; l02 = l/l01; m02 = m/m01; % 24 to 32, no 2 stage
+end
+if (l==3) && (m==4)
+ l01 = 3; m01 = 4; l02 = l/l01; m02 = m/m01; % 24 to 32, no 2 stage
+end
+
+
+r11 = l01/m01;
+r22 = l02/m02;
+r12 = l01/m02;
+r21 = l02/m01;
+fs3 = [r11 r12 r21 r22].*fs1;
+
+
+if fs1 > fs2 % Decrease sample rate, dont go below output rate
+ idx = find(fs3 >= fs2);
+ if length(idx) < 1
+ error('Cant factorise interpolations');
+ end
+ fs3_possible = fs3(idx);
+ delta = fs3_possible-fs2; % Fs3 that is nearest to fs2
+ idx = find(delta == min(delta), 1, 'first');
+ fs3_min = fs3_possible(idx);
+ idx = find(fs3 == fs3_min, 1, 'first');
+ switch idx
+ case 1, l1 = l01; m1 = m01; l2 = l02; m2 = m02;
+ case 2, l1 = l01; m1 = m02; l2 = l02; m2 = m01;
+ case 3, l1 = l02; m1 = m01; l2 = l01; m2 = m02;
+ case 4, l1 = l02; m1 = m02; l2 = l01; m2 = m01;
+ end
+else % Increase sample rate, don't go below input rate
+ idx = find(fs3 >= fs1);
+ if length(idx) < 1
+ error('Cant factorise interpolations');
+ end
+ fs3_possible = fs3(idx);
+ delta = fs3_possible-fs1; % Fs2 that is nearest to fs1
+ idx = find(delta == min(delta), 1, 'first');
+ fs3_min = fs3_possible(idx);
+ idx = find(fs3 == fs3_min, 1, 'first');
+ switch idx
+ case 1, l1 = l01; m1 = m01; l2 = l02; m2 = m02;
+ case 2, l1 = l01; m1 = m02; l2 = l02; m2 = m01;
+ case 3, l1 = l02; m1 = m01; l2 = l01; m2 = m02;
+ case 4, l1 = l02; m1 = m02; l2 = l01; m2 = m01;
+ end
+end
+
+%% If 1st stage is 1:1
+if (l1 == 1) && (m1 == 1)
+ l1 = l2;
+ m1 = m2;
+ l2 = 1;
+ m2 = 1;
+end
+
+f1=l/m;
+f2=l1/m1*l2/m2;
+if abs(f1 - f2) > 1e-6
+ error('Bug in factorization code!');
+end
+
+end
+
+
+function [a, b]=factor2(c)
+x = round(sqrt(c));
+t1 = x:2*x;
+d1 = c./t1;
+idx1 = find(d1 == floor(d1), 1, 'first');
+a1 = t1(idx1);
+t2 = x:-1:floor(x/2);
+d2 = c./t2;
+idx2 = find(d2 == floor(d2), 1, 'first');
+a2 = t2(idx2);
+if (a1-x) < (x-a2)
+ a = a1;
+else
+ a = a2;
+end
+b = c/a;
+end
+
+
+
diff --git a/tune/src/src_find_l0m0.m b/tune/src/src_find_l0m0.m
new file mode 100644
index 0000000..2a360a3
--- /dev/null
+++ b/tune/src/src_find_l0m0.m
@@ -0,0 +1,71 @@
+function [l0, m0] = src_find_l0m0(L, M)
+
+% find_l0m0 - find l0, m0 to meet -l0*L + m0*M == 1
+%
+% [l0, m0] = find_l0m0(L, M)
+%
+% L - interpolatation factor
+% M - decimation factor
+%
+
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+if M == 1
+ l0 = 0;
+ m0 = 1;
+ return
+end
+
+if L == 1
+ l0 = 1;
+ m0 = 0;
+ return
+end
+
+l0 = [];
+m0 = [];
+for lt=1:4*L
+ mt = (1+lt*L)/M; % Check if -lt*L + mt*M == 1
+ if floor(mt) == mt
+ l0 = [l0 lt];
+ m0 = [m0 mt];
+ end
+end
+
+s = l0+m0;
+idx = find(s == min(s), 1, 'first');
+l0 = l0(idx);
+m0 = m0(idx);
+
+if -l0*L + m0*M ~= 1
+ error('Something went wrong!');
+end
+
+end
diff --git a/tune/src/src_generate.m b/tune/src/src_generate.m
new file mode 100644
index 0000000..b01b29d
--- /dev/null
+++ b/tune/src/src_generate.m
@@ -0,0 +1,311 @@
+function src_generate(fs_in, fs_out, ctype, fs_inout, profile, qc)
+
+% src_generate - export src conversions for given fs_in and fs_out
+%
+% src_generate(fs_in, fs_out <, ctype, fs_inout>>)
+%
+% fs_in - vector of input sample rates (M)
+% fs_out - vector of output sample rates (N)
+% ctype - coefficient type, use 'int16','int24', 'int32', or 'float'
+% fs_inout - matrix of supported conversions (MxN),
+% 0 = no support, 1 = supported
+% %
+% if ctype is omitted then ctype defaults to 'int16'.
+%
+% If fs_inout matrix is omitted this script will compute coefficients
+% for all fs_in <-> fs_out combinations.
+%
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+if (nargin == 1) || (nargin > 6)
+ error('Incorrect arguments for function!');
+end
+if nargin == 0
+ %% Default input and output rates
+ fs_in = [8e3 11025 12e3 16e3 18900 22050 24e3 32e3 44100 48e3 ...
+ 64e3 88.2e3 96e3 176400 192e3];
+
+ fs_out = [8e3 11025 12e3 16e3 18900 22050 24e3 32e3 44100 48e3];
+
+ fs_inout = [ 0 0 0 1 0 0 1 1 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 1 0 0 0 0 0 1 1 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 1 0 0 1 0 0 0 1 0 1 ; ...
+ 1 0 0 1 0 0 1 0 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 1 1 1 1 0 1 1 1 1 0 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ; ...
+ 0 0 0 0 0 0 0 0 0 1 ];
+
+ ctype = 'int32';
+ profile = 'std';
+ qc = 1.0;
+else
+ if nargin < 3
+ ctype = 'int16';
+ end
+ if nargin < 4
+ fs_inout = ones(length(fs_in), length(fs_out));
+ end
+ if nargin < 5
+ profile = '';
+ end
+ if nargin < 6
+ qc = 1.0;
+ end
+end
+
+sio = size(fs_inout);
+if (length(fs_in) ~= sio(1)) || (length(fs_out) ~= sio(2))
+ error('Sample rates in/out matrix size mismatch!');
+end
+
+%% Exported coefficients type int16, int24, int32, float
+
+switch ctype
+ case 'int16'
+ coef_label = 'int16';
+ coef_ctype = 'int16_t';
+ coef_bits = 16;
+ coef_bytes = 2;
+ case 'int24'
+ coef_label = 'int24';
+ coef_ctype = 'int32_t';
+ coef_bits = 24;
+ coef_bytes = 4;
+ case 'int32'
+ coef_label = 'int32';
+ coef_ctype = 'int32_t';
+ coef_bits = 32;
+ coef_bytes = 4;
+ case 'float'
+ coef_label = 'float'; coef_ctype = 'float';
+ coef_bits = 24;
+ coef_bytes = 4;
+ otherwise
+ error('Request for incorrect coefficient type');
+end
+data_bytes = 4;
+
+hdir = mkdir_check('include');
+rdir = mkdir_check('reports');
+
+%% Find fractional conversion factors
+nfsi = length(fs_in);
+nfso = length(fs_out);
+l_2s = zeros(2, nfsi, nfso);
+m_2s = zeros(2, nfsi, nfso);
+mops_2s = zeros(2, nfsi, nfso);
+pb_2s = zeros(2,nfsi, nfso);
+sb_2s = zeros(2,nfsi, nfso);
+taps_2s = zeros(2,nfsi, nfso);
+defs.fir_delay_size = 0;
+defs.out_delay_size = 0;
+defs.blk_in = 0;
+defs.blk_out = 0;
+defs.num_in_fs = nfsi;
+defs.num_out_fs = nfso;
+defs.stage1_times_max = 0;
+defs.stage2_times_max = 0;
+defs.stage_buf_size = 0;
+h = 1;
+for b = 1:nfso
+ for a = 1:nfsi
+ fs1 = fs_in(a);
+ fs2 = fs_out(b);
+ [l1, m1, l2, m2] = src_factor2_lm(fs1, fs2);
+ fs3 = fs1*l1/m1;
+ cnv1 = src_param(fs1, fs3, coef_bits, qc);
+ cnv2 = src_param(fs3, fs2, coef_bits, qc);
+ if (fs2 < fs1)
+ % When decimating 1st stage passband can be limited
+ % for wider transition band
+ f_pb = fs2*cnv2.c_pb;
+ cnv1.c_pb = f_pb/min(fs1,fs3);
+ end
+ if (fs2 > fs1)
+ % When interpolating 2nd stage passband can be limited
+ % for wider transition band
+ f_pb = fs1*cnv1.c_pb;
+ cnv2.c_pb = f_pb/min(fs2,fs3);
+ end
+ if fs_inout(a,b) > 0 || (a == b)
+ if cnv2.fs1-cnv2.fs2 > eps
+ % Allow half ripple for dual stage SRC parts
+ cnv1.rp = cnv1.rp/2;
+ cnv2.rp = cnv2.rp/2;
+ end
+ src1 = src_get(cnv1);
+ src2 = src_get(cnv2);
+ k = gcd(src1.blk_out, src2.blk_in);
+ stage1_times = src2.blk_in/k;
+ stage2_times = stage1_times*src1.blk_out/src2.blk_in;
+ defs.stage1_times_max = max(defs.stage1_times_max, stage1_times);
+ defs.stage2_times_max = max(defs.stage2_times_max, stage2_times);
+ l_2s(:,a,b) = [src1.L src2.L];
+ m_2s(:,a,b) = [src1.M src2.M];
+ mops_2s(:,a,b) = [src1.MOPS src2.MOPS];
+ pb_2s(:,a,b) = [round(1e4*src1.c_pb) round(1e4*src2.c_pb)];
+ sb_2s(:,a,b) = [round(1e4*src1.c_sb) round(1e4*src2.c_sb)];
+ taps_2s(:,a,b) = [src1.filter_length src2.filter_length];
+ defs.fir_delay_size = max(defs.fir_delay_size, src1.fir_delay_size);
+ defs.out_delay_size = max(defs.out_delay_size, src1.out_delay_size);
+ defs.blk_in = max(defs.blk_in, src1.blk_in);
+ defs.blk_out = max(defs.blk_out, src1.blk_out);
+ defs.fir_delay_size = max(defs.fir_delay_size, src2.fir_delay_size);
+ defs.out_delay_size = max(defs.out_delay_size, src2.out_delay_size);
+ defs.blk_in = max(defs.blk_in, src2.blk_in);
+ defs.blk_out = max(defs.blk_out, src2.blk_out);
+ defs.stage_buf_size = max(defs.stage_buf_size, src1.blk_out*stage1_times);
+ src_export_coef(src1, coef_label, coef_ctype, hdir, profile);
+ src_export_coef(src2, coef_label, coef_ctype, hdir, profile);
+ end
+ end
+end
+
+%% Export modes table
+defs.sum_filter_lengths = src_export_table_2s(fs_in, fs_out, l_2s, m_2s, ...
+ pb_2s, sb_2s, taps_2s, coef_label, coef_ctype, ...
+ 'sof/audio/coefficients/src/', hdir, profile);
+src_export_defines(defs, coef_label, hdir, profile);
+
+%% Print 2 stage conversion factors
+fn = sprintf('%s/src_2stage.txt', rdir);
+fh = fopen(fn,'w');
+fprintf(fh,'\n');
+fprintf(fh,'Dual stage fractional SRC: Ratios\n');
+fprintf(fh,'%8s, ', 'in \ out');
+for b = 1:nfso
+ fprintf(fh,'%12.1f, ', fs_out(b)/1e3);
+end
+fprintf(fh,'\n');
+for a = 1:nfsi
+ fprintf(fh,'%8.1f, ', fs_in(a)/1e3);
+ for b = 1:nfso
+ cstr = print_ratios(l_2s, m_2s, a, b);
+ fprintf(fh,'%12s, ', cstr);
+ end
+ fprintf(fh,'\n');
+end
+fprintf(fh,'\n');
+
+%% Print 2 stage MOPS
+fprintf(fh,'Dual stage fractional SRC: MOPS\n');
+fprintf(fh,'%8s, ', 'in \ out');
+for b = 1:nfso
+ fprintf(fh,'%8.1f, ', fs_out(b)/1e3);
+end
+fprintf(fh,'\n');
+for a = 1:nfsi
+ fprintf(fh,'%8.1f, ', fs_in(a)/1e3);
+ for b = 1:nfso
+ mops = sum(mops_2s(:,a,b));
+ if sum(l_2s(:,a,b)) < eps
+ mops_str = 'x';
+ else
+ mops_str = sprintf('%.2f', mops);
+ end
+ fprintf(fh,'%8s, ', mops_str);
+ end
+ fprintf(fh,'\n');
+end
+fprintf(fh,'\n');
+
+%% Print 2 stage MOPS per stage
+fprintf(fh,'Dual stage fractional SRC: MOPS per stage\n');
+fprintf(fh,'%10s, ', 'in \ out');
+for b = 1:nfso
+ fprintf(fh,'%10.1f, ', fs_out(b)/1e3);
+end
+fprintf(fh,'\n');
+for a = 1:nfsi
+ fprintf(fh,'%10.1f, ', fs_in(a)/1e3);
+ for b = 1:nfso
+ mops = mops_2s(:,a,b);
+ if sum(l_2s(:,a,b)) < eps
+ mops_str = 'x';
+ else
+ mops_str = sprintf('%.2f+%.2f', mops(1), mops(2));
+ end
+ fprintf(fh,'%10s, ', mops_str);
+ end
+ fprintf(fh,'\n');
+end
+fprintf(fh,'\n');
+
+fprintf(fh,'Coefficient RAM %.1f kB\n', ...
+ defs.sum_filter_lengths*coef_bytes/1024);
+fprintf(fh,'Max. data RAM %.1f kB\n', ...
+ (defs.fir_delay_size + defs.out_delay_size+defs.stage_buf_size) ...
+ * data_bytes/1024);
+
+fprintf(fh,'\n');
+fclose(fh);
+type(fn);
+
+end
+
+function d = mkdir_check(d)
+if exist(d) ~= 7
+ mkdir(d);
+end
+end
+
+function cstr = print_ratios(l_2s, m_2s, a, b)
+l1 = l_2s(1,a,b);
+m1 = m_2s(1,a,b);
+l2 = l_2s(2,a,b);
+m2 = m_2s(2,a,b);
+if l1+m2+l2+m2 == 0
+ cstr = 'x';
+else
+ if m2 == 1
+ if l2 == 1
+ cstr2 = '';
+ else
+ cstr2 = sprintf('*%d', l2);
+ end
+ else
+ cstr2 = sprintf('*%d/%d', l2, m2);
+ end
+ if m1 == 1
+ cstr1 = sprintf('%d', l1);
+ else
+ cstr1 = sprintf('%d/%d', l1, m1);
+ end
+ cstr = sprintf('%s%s', cstr1, cstr2);
+end
+end
diff --git a/tune/src/src_get.m b/tune/src/src_get.m
new file mode 100644
index 0000000..4520af9
--- /dev/null
+++ b/tune/src/src_get.m
@@ -0,0 +1,254 @@
+function src = src_get(cnv)
+
+% src_get - calculate coefficients for a src
+%
+% src = src_get(cnv);
+%
+% cnv - src parameters
+% src - src result
+%
+
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+use_firpm = 0;
+use_remez = 0;
+use_kaiser = 0;
+switch lower(cnv.design)
+ case 'firpm'
+ if exist('OCTAVE_VERSION', 'builtin')
+ use_remez = 1;
+ else
+ use_firpm = 1;
+ end
+ case 'kaiser'
+ use_kaiser = 1;
+ otherwise
+ error('Unknown FIR design request!');
+end
+
+if abs(cnv.fs1-cnv.fs2) < 1
+ %% Return minimum needed for scripts to work
+ src.L=1;
+ src.M=1;
+ src.odm=1;
+ src.idm=1;
+ src.MOPS=0;
+ src.c_pb = 0;
+ src.c_sb = 0;
+ src.fir_delay_size = 0;
+ src.out_delay_size = 0;
+ src.blk_in = 1;
+ src.blk_out = 1;
+ src.gain = 1;
+ src.filter_length = 0;
+ return
+end
+
+%% fractional SRC parameters
+[L, M] = src_factor1_lm(cnv.fs1, cnv.fs2);
+src.L = L;
+src.M = M;
+src.num_of_subfilters = L;
+[src.idm src.odm] = src_find_l0m0(src.L, src.M);
+min_fs = min(cnv.fs1,cnv.fs2);
+src.f_pb = min_fs*cnv.c_pb;
+src.f_sb = min_fs*cnv.c_sb;
+src.c_pb = cnv.c_pb;
+src.c_sb = cnv.c_sb;
+src.fs1 = cnv.fs1;
+src.fs2 = cnv.fs2;
+src.rp = cnv.rp;
+src.rs = cnv.rs;
+
+%% FIR PM design
+fs3 = src.L*cnv.fs1;
+f = [src.f_pb src.f_sb];
+a = [1 0];
+
+% Kaiser fir is not equiripple, can allow more ripple in the passband
+% lower freq.
+dev = [(10^(cnv.rp/20)-1)/(10^(cnv.rp/20)+1) 10^(-cnv.rs/20)];
+[kn0, kw, kbeta, kftype] = kaiserord(f, a, dev, fs3);
+if use_firpm
+ %dev = [(10^(cnv.rp/20)-1)/(10^(cnv.rp/20)+1) 10^(-cnv.rs/20)];
+ [n0,fo,ao,w] = firpmord(f,a,dev,fs3);
+ n0 = round(n0*0.95); % Decrease order to 95%
+end
+if use_remez
+ n0 = round(kn0*0.60); % Decrease order to 70%
+ fo = [0 2*f/fs3 1];
+ ao = [1 1 0 0];
+ w = [1 dev(1)/dev(2)];
+end
+if use_kaiser
+ n0 = round(kn0*0.70); % Decrease order to 70%
+end
+
+% Constrain filter length to be a suitable multiple. Multiple of
+% interpolation factor ensures that all subfilters are equal length.
+% Make each sub-filter order multiple of N helps in making efficient
+% implementation.
+nfir_increment = src.num_of_subfilters * cnv.filter_length_mult;
+
+nsf0 = (n0+1)/nfir_increment;
+if nsf0 > floor(nsf0)
+ n = (floor(nsf0)+1)*nfir_increment-1;
+else
+ n = n0;
+end
+
+src.subfilter_length = (n+1)/src.num_of_subfilters;
+src.filter_length = n+1;
+nfir = n;
+f_sb = linspace(src.f_sb, fs3/2, 500);
+stopband_ok = 0;
+need_to_stop = 0;
+delta = 100;
+n_worse = 0;
+n_worse_max = 20;
+n = 1;
+n_max = 100;
+dn = ones(1, n_max)*1000;
+fn = zeros(1, n_max);
+while (stopband_ok) == 0 && (n < n_max)
+ if use_firpm || use_remez
+ if nfir > 1800
+ b = fir1(nfir, kw, kftype, kaiser(nfir+1, kbeta));
+ else
+ if use_firpm
+ b = firpm(nfir,fo,ao,w);
+ else
+ b = remez(nfir,fo,ao,w);
+ end
+ end
+ else
+ b = fir1(nfir, kw, kftype, kaiser(nfir+1, kbeta));
+ end
+ m_b = max(abs(b));
+ %sref = 2^(cnv.coef_bits-1);
+ %bq = round(b*sref/m_b)*m_b/sref;
+ bq = b;
+ h_sb = freqz(bq, 1, f_sb, fs3);
+ m_sb = 20*log10(abs(h_sb));
+ delta_prev = delta;
+ delta = cnv.rs+max(m_sb);
+ fprintf('Step=%3d, Delta=%f dB, N=%d\n', n, delta, nfir);
+ dn(n) = delta;
+ fn(n) = nfir;
+ if delta < 0
+ stopband_ok = 1;
+ else
+ if delta_prev < delta
+ n_worse = n_worse+1;
+ if n_worse > n_worse_max
+ need_to_stop = 1; % No improvement, reverse
+ idx = find(dn == min(dn), 1, 'first');
+ nfir = fn(idx);
+ else
+ nfir = nfir + nfir_increment;
+ end
+ else
+ if need_to_stop == 0
+ nfir = nfir + nfir_increment;
+ else
+ stopband_ok = 1; % Exit after reverse
+ fprintf('Warning: Filter stop band could not be ');
+ fprintf('reached.\n', cnv.coef_bits);
+ end
+ end
+ end
+ n = n + 1;
+end
+
+f_p = linspace(0, fs3/2, 2000);
+m_db = 20*log10(abs(freqz(bq, 1, f_p, fs3)));
+i_pb = find(f_p < src.f_pb);
+g_pb = max(m_db(i_pb));
+g_att_lin = 10^(-g_pb/20);
+
+if 1
+ p_ymin = floor((-cnv.rs-50)/10)*10;
+ p_ymax = 10;
+ figure;
+ clf;
+ plot(f_p, m_db);
+ grid on;
+ xlabel('Frequency (Hz)');
+ ylabel('Magnitude (dB)');
+ axis([0 fs3/2 p_ymin p_ymax]);
+ hold on
+ plot([src.f_sb src.f_sb],[p_ymin p_ymax], 'r--');
+ plot([0 fs3],[-cnv.rs -cnv.rs], 'r--');
+ hold off
+ axes('Position', [ 0.58 0.7 0.3 0.2]);
+ box on;
+ plot(f_p(i_pb), m_db(i_pb));
+ axis([0 src.f_pb -cnv.rp-0.01 cnv.rp+0.01]);
+ hold on
+ plot([0 src.f_pb], +0.5*cnv.rp*ones(1,2), 'r--');
+ plot([0 src.f_pb], -0.5*cnv.rp*ones(1,2), 'r--');
+ hold off
+ grid on;
+ box off;
+end
+
+src.subfilter_length = ceil((nfir+1)/src.num_of_subfilters);
+src.filter_length = src.subfilter_length*src.num_of_subfilters;
+src.b = zeros(src.filter_length,1);
+src.gain = 1;
+src.b(1:nfir+1) = b*src.L*g_att_lin;
+m = max(abs(src.b));
+gmax = (32767/32768)/m;
+maxshift = floor(log(gmax)/log(2));
+src.b = src.b * 2^maxshift;
+src.gain = 1/2^maxshift;
+src.shift = maxshift;
+
+%% Reorder coefficients
+if 1
+ src.coefs = src.b;
+else
+ src.coefs = zeros(src.filter_length,1);
+ for n = 1:src.num_of_subfilters
+ i11 = (n-1)*src.subfilter_length+1;
+ i12 = i11+src.subfilter_length-1;
+ src.coefs(i11:i12) = src.b(n:src.num_of_subfilters:end);
+ end
+end
+
+src.halfband = 0;
+src.blk_in = M;
+src.blk_out = L;
+src.MOPS = cnv.fs1/M*src.filter_length/1e6;
+src.fir_delay_size = src.subfilter_length + ...
+ (src.num_of_subfilters-1)*src.idm + src.blk_in;
+src.out_delay_size = (src.num_of_subfilters-1)*src.odm + 1;
+
+end
diff --git a/tune/src/src_param.m b/tune/src/src_param.m
new file mode 100644
index 0000000..49e935c
--- /dev/null
+++ b/tune/src/src_param.m
@@ -0,0 +1,87 @@
+function cnv = src_param(fs1, fs2, coef_bits, q)
+
+% src_param - get converter parameters
+%
+% cnv = src_param(fs1, fs2, coef_bits, q)
+%
+% fs1 - input rate
+% fs2 - output rate
+% coef_bits - word length identifier
+% q - quality scale filter bandwidth and stopband attenuation,
+% 1 is default
+%
+
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+% Note: firpm design with rs 93 dB, or kaiser with 69 dB rs is fair quality.
+% Both give about -80 dB THD+N with 24 bit coefficients. With 16 bit
+% coefficients THD+N is limited to about -76 dB.
+
+if nargin < 4
+ q = 1.0;
+end
+
+%% Copy input parameters
+cnv.fs1 = fs1;
+cnv.fs2 = fs2;
+cnv.coef_bits = coef_bits;
+
+%% FIR design
+cnv.design = 'kaiser'; % Use firpm or kaiser
+
+%% Default SRC quality
+cnv.c_pb = q * 22/48; % Gives 22 kHz BW @ 48 kHz
+cnv.c_sb = 0.5; % Start stopband at Fs/2
+cnv.rs = 70; % Stopband attenuation in dB
+cnv.rp = 0.1; % Passband ripple in dB
+cnv.rp_tot = 0.1; % Max +/- passband ripple allowed, used in test script only
+
+%% Constrain sub-filter lengths. Make subfilters lengths multiple of four
+% is a good assumption for processors.
+cnv.filter_length_mult = 4;
+
+%% Exceptions for quality
+if min(fs1, fs2) > 80e3
+ cnv.c_pb = 30e3/min(fs1, fs2); % 30 kHz BW for > 80 kHz
+end
+
+%% Sanity checks
+if cnv.c_pb > 0.49
+ error('Too wide passband');
+end
+if cnv.c_pb < 0.15
+ error('Too narrow passband');
+end
+if cnv.rs > 160
+ error('Too large stopband attenuation');
+end
+if cnv.rs < 40
+ error('Too low stopband attenuation');
+end
diff --git a/tune/src/src_std_int32.m b/tune/src/src_std_int32.m
new file mode 100644
index 0000000..125ae96
--- /dev/null
+++ b/tune/src/src_std_int32.m
@@ -0,0 +1,30 @@
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+src_generate();
diff --git a/tune/src/src_tiny_int16.m b/tune/src/src_tiny_int16.m
new file mode 100644
index 0000000..be310fb
--- /dev/null
+++ b/tune/src/src_tiny_int16.m
@@ -0,0 +1,41 @@
+% Copyright (c) 2016, Intel Corporation
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% * Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in the
+% documentation and/or other materials provided with the distribution.
+% * Neither the name of the Intel Corporation nor the
+% names of its contributors may be used to endorse or promote products
+% derived from this software without specific prior written permission.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.
+%
+% Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+%
+
+fs1 = [8e3 16e3 24e3 32e3 44.1e3 48e3];
+fs2 = [8e3 16e3 24e3 32e3 44.1e3 48e3];
+fsm = [0 0 0 0 0 1; ...
+ 0 0 0 0 0 1; ...
+ 0 0 0 0 0 1; ...
+ 0 0 0 0 0 1; ...
+ 0 0 0 0 0 1; ...
+ 1 1 1 1 1 0; ...
+ ];
+fmt = 'int16'; profile = 'tiny'; q = 0.75;
+
+src_generate(fs1, fs2, fmt, fsm, profile, q);
--
2.14.1
More information about the Sound-open-firmware
mailing list