|
| 1 | +function success=src_export_coef(src, ctype, vtype, hdir, profile) |
| 2 | + |
| 3 | +% src_export_coef - Export FIR coefficients |
| 4 | +% |
| 5 | +% success=src_export_coef(src, ctype, hdir, profile) |
| 6 | +% |
| 7 | +% src - src definition struct |
| 8 | +% ctype - 'float','int32', or 'int24' |
| 9 | +% vtype - 'float','int32_t' |
| 10 | +% hdir - directory for header files |
| 11 | +% profile - string to append to filename |
| 12 | +% |
| 13 | + |
| 14 | +% Copyright (c) 2016, Intel Corporation |
| 15 | +% All rights reserved. |
| 16 | +% |
| 17 | +% Redistribution and use in source and binary forms, with or without |
| 18 | +% modification, are permitted provided that the following conditions are met: |
| 19 | +% * Redistributions of source code must retain the above copyright |
| 20 | +% notice, this list of conditions and the following disclaimer. |
| 21 | +% * Redistributions in binary form must reproduce the above copyright |
| 22 | +% notice, this list of conditions and the following disclaimer in the |
| 23 | +% documentation and/or other materials provided with the distribution. |
| 24 | +% * Neither the name of the Intel Corporation nor the |
| 25 | +% names of its contributors may be used to endorse or promote products |
| 26 | +% derived from this software without specific prior written permission. |
| 27 | +% |
| 28 | +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 29 | +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 30 | +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 31 | +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| 32 | +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 33 | +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 34 | +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 35 | +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 36 | +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 37 | +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 38 | +% POSSIBILITY OF SUCH DAMAGE. |
| 39 | +% |
| 40 | +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> |
| 41 | +% |
| 42 | + |
| 43 | +if nargin < 5 |
| 44 | + profile = ''; |
| 45 | +end |
| 46 | + |
| 47 | +if src.L == src.M |
| 48 | + success = 0; |
| 49 | +else |
| 50 | + pbi = round(src.c_pb*1e4); |
| 51 | + sbi = round(src.c_sb*1e4); |
| 52 | + if isempty(profile) |
| 53 | + hfn = sprintf('%s/src_%s_%d_%d_%d_%d.h', ... |
| 54 | + hdir, ctype, src.L, src.M, pbi, sbi); |
| 55 | + else |
| 56 | + hfn = sprintf('%s/src_%s_%s_%d_%d_%d_%d.h', ... |
| 57 | + hdir, profile, ctype, src.L, src.M, pbi, sbi); |
| 58 | + end |
| 59 | + vfn = sprintf('src_%s_%d_%d_%d_%d_fir', ctype, src.L, src.M, pbi, sbi); |
| 60 | + sfn = sprintf('src_%s_%d_%d_%d_%d', ctype, src.L, src.M, pbi, sbi); |
| 61 | + |
| 62 | + fprintf('Exporting %s ...\n', hfn); |
| 63 | + fh = fopen(hfn, 'w'); |
| 64 | + |
| 65 | + switch ctype |
| 66 | + case 'float' |
| 67 | + fprintf(fh, 'const %s %s[%d] = {\n', ... |
| 68 | + vtype, vfn, src.filter_length); |
| 69 | + fprintf(fh,'\t%16.9e', src.coefs(1)); |
| 70 | + for n=2:src.filter_length |
| 71 | + fprintf(fh, ',\n'); |
| 72 | + fprintf(fh,'\t%16.9e', src.coefs(n)); |
| 73 | + end |
| 74 | + fprintf(fh,'\n\n};'); |
| 75 | + case 'int32' |
| 76 | + print_int_coef(src, fh, vtype, vfn, 32); |
| 77 | + case 'int24' |
| 78 | + print_int_coef(src, fh, vtype, vfn, 24); |
| 79 | + case 'int16' |
| 80 | + print_int_coef(src, fh, vtype, vfn, 16); |
| 81 | + otherwise |
| 82 | + error('Unknown type %s !!!', ctype); |
| 83 | + end |
| 84 | + |
| 85 | + fprintf(fh, '\n'); |
| 86 | + switch ctype |
| 87 | + case 'float' |
| 88 | + fprintf(fh, 'struct src_stage %s = {\n', sfn); |
| 89 | + fprintf(fh, '\t%d, %d, %d, %d, %d, %d, %d, %d, %f,\n\t%s};\n', ... |
| 90 | + src.idm, src.odm, src.num_of_subfilters, ... |
| 91 | + src.subfilter_length, src.filter_length, ... |
| 92 | + src.blk_in, src.blk_out, src.halfband, ... |
| 93 | + src.gain, vfn); |
| 94 | + case { 'int16' 'int24' 'int32' } |
| 95 | + fprintf(fh, 'struct src_stage %s = {\n', sfn); |
| 96 | + fprintf(fh, '\t%d, %d, %d, %d, %d, %d, %d, %d, %d,\n\t%s};\n', ... |
| 97 | + src.idm, src.odm, src.num_of_subfilters, ... |
| 98 | + src.subfilter_length, src.filter_length, ... |
| 99 | + src.blk_in, src.blk_out, src.halfband, ... |
| 100 | + src.shift, vfn); |
| 101 | + otherwise |
| 102 | + error('Unknown type %s !!!', ctype); |
| 103 | + end |
| 104 | + %fprintf(fh, '\n'); |
| 105 | + fclose(fh); |
| 106 | + success = 1; |
| 107 | +end |
| 108 | + |
| 109 | +end |
| 110 | + |
| 111 | +function print_int_coef(src, fh, vtype, vfn, nbits) |
| 112 | + fprintf(fh, 'const %s %s[%d] = {\n', ... |
| 113 | + vtype, vfn, src.filter_length); |
| 114 | + |
| 115 | + cint = coef_quant(src, nbits); |
| 116 | + fprintf(fh,'\t%d', cint(1)); |
| 117 | + for n=2:src.filter_length |
| 118 | + fprintf(fh, ',\n'); |
| 119 | + fprintf(fh,'\t%d', cint(n)); |
| 120 | + end |
| 121 | + fprintf(fh,'\n\n};'); |
| 122 | +end |
| 123 | + |
| 124 | +function cint = coef_quant(src, nbits) |
| 125 | + |
| 126 | + sref = 2^(nbits-1); |
| 127 | + pmax = sref-1; |
| 128 | + nmin = -sref; |
| 129 | + |
| 130 | + if nbits > 16 |
| 131 | + %% Round() is OK |
| 132 | + cint0 = round(sref*src.coefs); |
| 133 | + else |
| 134 | + %% Prepare to optimize coefficient quantization |
| 135 | + fs = max(src.fs1, src.fs2); |
| 136 | + f = linspace(0, fs/2, 1000); |
| 137 | + |
| 138 | + %% Test sensitivity for stopband and find the most sensitive |
| 139 | + % coefficients |
| 140 | + sbf = linspace(src.f_sb,fs/2, 500); |
| 141 | + n = src.filter_length; |
| 142 | + psens = zeros(1,n); |
| 143 | + bq0 = round(sref*src.coefs); |
| 144 | + h = freqz(bq0/sref/src.L, 1, sbf, fs); |
| 145 | + sb1 = 20*log10(sqrt(sum(h.*conj(h)))); |
| 146 | + for i=1:n |
| 147 | + bq = src.coefs; |
| 148 | + bq(i) = round(sref*bq(i))/sref; |
| 149 | + %tbq = bq; %tbq(i) = bq(i)+1; |
| 150 | + h = freqz(bq, 1, sbf, fs); |
| 151 | + psens(i) = sum(h.*conj(h)); |
| 152 | + end |
| 153 | + [spsens, pidx] = sort(psens, 'descend'); |
| 154 | + |
| 155 | + %% Test quantization in the found order |
| 156 | + % The impact to passband is minimal so it's not tested |
| 157 | + bi = round(sref*src.coefs); |
| 158 | + bi0 = bi; |
| 159 | + dl = -1:1; |
| 160 | + nd = length(dl); |
| 161 | + msb = zeros(1,nd); |
| 162 | + for i=pidx |
| 163 | + bit = bi; |
| 164 | + for j=1:nd |
| 165 | + bit(i) = bi(i) + dl(j); |
| 166 | + h = freqz(bit, 1, sbf, fs); |
| 167 | + msb(j) = sum(h.*conj(h)); |
| 168 | + end |
| 169 | + idx = find(msb == min(msb), 1, 'first'); |
| 170 | + bi(i) = bi(i) + dl(idx); |
| 171 | + end |
| 172 | + h = freqz(bi/sref/src.L, 1, sbf, fs); |
| 173 | + sb2 = 20*log10(sqrt(sum(h.*conj(h)))); |
| 174 | + |
| 175 | + %% Plot to compare |
| 176 | + if 0 |
| 177 | + f = linspace(0, fs/2, 1000); |
| 178 | + h1 = freqz(src.coefs/src.L, 1, f, fs); |
| 179 | + h2 = freqz(bq0/sref/src.L, 1, f, fs); |
| 180 | + h3 = freqz(bi/sref/src.L, 1, f, fs); |
| 181 | + figure; |
| 182 | + plot(f, 20*log10(abs(h1)), f, 20*log10(abs(h2)), f, 20*log10(abs(h3))); |
| 183 | + grid on; |
| 184 | + fprintf('Original = %4.1f dB, optimized = %4.1f dB, delta = %4.1f dB\n', ... |
| 185 | + sb1, sb2, sb1-sb2); |
| 186 | + end |
| 187 | + cint0 = bi; |
| 188 | + end |
| 189 | + |
| 190 | + |
| 191 | + %% Re-order coefficients for filter implementation |
| 192 | + cint = zeros(src.filter_length,1); |
| 193 | + for n = 1:src.num_of_subfilters |
| 194 | + i11 = (n-1)*src.subfilter_length+1; |
| 195 | + i12 = i11+src.subfilter_length-1; |
| 196 | + cint(i11:i12) = cint0(n:src.num_of_subfilters:end); |
| 197 | + end |
| 198 | + |
| 199 | + %% Done check for no overflow |
| 200 | + max_fix = max(cint); |
| 201 | + min_fix = min(cint); |
| 202 | + if (max_fix > pmax) |
| 203 | + printf('Fixed point coefficient %d exceeded %d\n.', max_fix, pmax); |
| 204 | + error('Something went wrong!'); |
| 205 | + end |
| 206 | + if (min_fix < nmin) |
| 207 | + printf('Fixed point coefficient %d exceeded %d\n.', min_fix, nmax); |
| 208 | + error('Something went wrong!'); |
| 209 | + end |
| 210 | + |
| 211 | + |
| 212 | +end |
0 commit comments