sphear_fir_design.m 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. %%
  2. %% *SpHEAR Project
  3. %%
  4. %% sphear_fir_design: design a matrix of FIR filters that equalizes the microphone
  5. %%
  6. %% usage:
  7. %% [FIR] = sphear_fir_design(F, A2BF, n, Fs, Fl, W, XYZ)
  8. %%
  9. %% F: array of filter section center frequencies
  10. %% A2BF: vector of A2B matrixes, one for each frequency
  11. %% n: order of the FIR filter being created
  12. %% maxboost: max high and low frequency boost in dB of the final filter
  13. %% Fs: sampling rate
  14. %% Fl: frequency limit, below it use A2B matrixes, above it use WXYZ shapes
  15. %%
  16. %% for the first run do not supply W/XYZ, render the filters and then run
  17. %% sphear_fir_extract to extract the W and XYZ filter shapes, finally run
  18. %% this again with the extra parameters below
  19. %%
  20. %% W: extracted shape of W filter (used above Fl)
  21. %% XYZ: extracted shape of X, Y and Z filters (used above Fl)
  22. %%
  23. %% Copyright 2016, Fernando Lopez-Lezcano, All Rights Reserved
  24. %% nando@ccrma.stanford.edu
  25. %%
  26. %% This program is free software: you can redistribute it and/or modify
  27. %% it under the terms of the GNU General Public License as published by
  28. %% the Free Software Foundation, either version 3 of the License, or
  29. %% (at your option) any later version.
  30. %%
  31. %% This program is distributed in the hope that it will be useful,
  32. %% but WITHOUT ANY WARRANTY; without even the implied warranty of
  33. %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  34. %% GNU General Public License for more details.
  35. %%
  36. %% You should have received a copy of the GNU General Public License
  37. %% along with this program. If not, see <http://www.gnu.org/licenses/>.
  38. function [FIR] = sphear_fir_design(F, A2BF, n, maxboost, Fs, Fl, W, XYZ)
  39. %% all b format components
  40. for b = 1:4
  41. %% all capsules
  42. for c = 1:4
  43. for d = 1:size(A2BF(:,1,1))(1)
  44. if (F(d) <= Fl)
  45. %% below the limit frequency we use the A2B coefficients
  46. vlast = A2BF(d, c, b);
  47. dlast = d;
  48. if (exist("W") == 1)
  49. wlast = W(d);
  50. end
  51. if (exist("XYZ") == 1)
  52. xyzlast = XYZ(d);
  53. end
  54. else
  55. %% above the limit frequency we interpolate the W and XYZ
  56. %% filters if they exist, otherwise keep the last valid value
  57. if (b == 1)
  58. if (exist("W") == 1)
  59. A2BF(d, c, b) = vlast * (W(d)/wlast);
  60. else
  61. A2BF(d, c, b) = vlast;
  62. end
  63. else
  64. if (exist("XYZ") == 1)
  65. A2BF(d, c, b) = vlast * (XYZ(d)/xyzlast);
  66. else
  67. A2BF(d, c, b) = vlast;
  68. end
  69. end
  70. end
  71. end
  72. %% fit a spline to the W and XYZ segments and extrapolate
  73. %% highest frequency if it does not exist in the measurements
  74. fh = (F(dlast)/(Fs/2):200/(Fs/2):1)';
  75. fh(end) = 1;
  76. rh = spline(F(dlast:end)/(Fs/2), A2BF(dlast:end,c,b)', fh);
  77. %% extract the low frequency A2B coefficients
  78. fl = [0 F(1:dlast-1)']' ./ (Fs/2);
  79. rl = [A2BF(1,c,b) A2BF(1:dlast-1,c,b)']';
  80. %% concatenate low and high frequency arrays
  81. fi = cat(1, fl, fh);
  82. ri = cat(1, rl, rh);
  83. printf("low frequency boost %f, high frequency boost %f\n", 20*log10(ri(1)), 20*log10(ri(end)));
  84. %% force a max boost at low and high frequencies
  85. if (maxboost != 0)
  86. if (abs(ri(1)) > 10^(maxboost/20))
  87. printf("limit low freq boost from %f to %f dB (%f)\n", 20*log10(ri(1)), maxboost, ri(1));
  88. ri(1) = sign(ri(1)) * 10^(maxboost/20);
  89. printf("new limit %f\n", ri(1));
  90. end
  91. if (abs(ri(end)) > 10^(maxboost/20))
  92. printf("limit high freq boost from %f dB to %f dB (%f)\n", 20*log10(ri(end)), maxboost, ri(end));
  93. ri(end) = sign(ri(end)) * 10^(maxboost/20);
  94. printf("new limit %f\n", ri(end));
  95. end
  96. end
  97. %% plot real measured points
  98. axis([300, 24000]);
  99. grid on;
  100. if (b == 1)
  101. semilogx(F, 20*log10(abs(A2BF(:,c,b)))','*k');
  102. else
  103. semilogx(F, 20*log10(abs(A2BF(:,c,b)))','*k');
  104. end
  105. hold on;
  106. %% plot extrapolated spline
  107. if (b == 1)
  108. semilogx(fi*(Fs/2), 20*log10(abs(ri)), 'b');
  109. else
  110. semilogx(fi*(Fs/2), 20*log10(abs(ri)), 'r');
  111. end
  112. %% design the filter
  113. FIR(b, c, :) = fir2(n, fi, ri);
  114. end
  115. end
  116. end