|
@@ -0,0 +1,150 @@
|
|
|
|
|
+%% -*- mode: octave -*-
|
|
|
|
|
+%%
|
|
|
|
|
+%% *SpHEAR Project
|
|
|
|
|
+%%
|
|
|
|
|
+%% Design a simple A2B encoder, static matrix and four (WXYZ) FIR filters
|
|
|
|
|
+%%
|
|
|
|
|
+%% Copyright 2016-2017, Fernando Lopez-Lezcano, All Rights Reserved
|
|
|
|
|
+%% nando@ccrma.stanford.edu
|
|
|
|
|
+%%
|
|
|
|
|
+%% This program is free software: you can redistribute it and/or modify
|
|
|
|
|
+%% it under the terms of the GNU General Public License as published by
|
|
|
|
|
+%% the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
+%% (at your option) any later version.
|
|
|
|
|
+%%
|
|
|
|
|
+%% This program is distributed in the hope that it will be useful,
|
|
|
|
|
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
+%% GNU General Public License for more details.
|
|
|
|
|
+%%
|
|
|
|
|
+%% You should have received a copy of the GNU General Public License
|
|
|
|
|
+%% along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
+
|
|
|
|
|
+%% root of the data files, assume we are running in the src/ directory
|
|
|
|
|
+DATA = "../data/";
|
|
|
|
|
+
|
|
|
|
|
+%% default for location of current measurements
|
|
|
|
|
+CURRENT = "current/";
|
|
|
|
|
+
|
|
|
|
|
+%% data is assumed to be in ../data/current/ which is usually a symbolic
|
|
|
|
|
+%% link to the real measurement directory
|
|
|
|
|
+
|
|
|
|
|
+%% before we start the design process we need to equalize the measurements
|
|
|
|
|
+%% to take into account the frequency response of the speaker used. The first
|
|
|
|
|
+%% step is to use the reference microphone measurement to design a filter that
|
|
|
|
|
+%% inverts the frequency response of the speaker. We use DRC to do this.
|
|
|
|
|
+
|
|
|
|
|
+%% calculate speaker calibration filter from reference microphone
|
|
|
|
|
+%% (shell code, uses DRC for filter calculation)
|
|
|
|
|
+%% ./sphear_make_reference_filter emm-6-5850
|
|
|
|
|
+
|
|
|
|
|
+%% at this point we should have the raw impulse responses and a calibration
|
|
|
|
|
+%% filter in ../data/current/cal/drc-filter.wav (see the script for details
|
|
|
|
|
+%% on how this is done). We process all impulse responses through the filter
|
|
|
|
|
+%% and write calibrated impulse responses that are used for the rest of the
|
|
|
|
|
+%% design process.
|
|
|
|
|
+
|
|
|
|
|
+%% read raw impulse response data and generate calibrated impulse responses
|
|
|
|
|
+
|
|
|
|
|
+sphear_af_calibrate((1:16), 0.0045, 0.001);
|
|
|
|
|
+
|
|
|
|
|
+%% (this is a version for the Octathingy which relies on recording two four
|
|
|
|
|
+%% channel impulse responses in Aliki - keep in mind that both recordings
|
|
|
|
|
+%% have to be processed and trimmed alike, otherwise there will be a mismatch
|
|
|
|
|
+%% in arrival times of the impulses)
|
|
|
|
|
+
|
|
|
|
|
+sphear_octa_af_calibrate((1:16), 0.004, 0.001);
|
|
|
|
|
+
|
|
|
|
|
+%% read all the calibrated A-format files
|
|
|
|
|
+[AF, FS] = sphear_af_read((1:16));
|
|
|
|
|
+
|
|
|
|
|
+%% just for checking the data, this plots the frequency response of each
|
|
|
|
|
+%% measurement for each capsule.
|
|
|
|
|
+
|
|
|
|
|
+sphear_capsule_plot_frequency_response(AF, [1:16], 300, 20000, -60, -10, 48000, 8192);
|
|
|
|
|
+
|
|
|
|
|
+sphear_af_plot_frequency_response(AF, 300, 20000, -60, -10, 48000, 8192);
|
|
|
|
|
+
|
|
|
|
|
+%% calculate signal power in reference frequency interval for all
|
|
|
|
|
+%% measurements and capsules
|
|
|
|
|
+
|
|
|
|
|
+[R] = sphear_signal_power(AF, FS, 600, 1000, 8192);
|
|
|
|
|
+
|
|
|
|
|
+%% check that capsule signals are reasonable
|
|
|
|
|
+
|
|
|
|
|
+sphear_plot_r(R, 0);
|
|
|
|
|
+
|
|
|
|
|
+%% calculate a static A2B matrix based on the power measurements in the reference band
|
|
|
|
|
+
|
|
|
|
|
+[A2B, PV, COND] = sphear_calculate_a2b(R);
|
|
|
|
|
+
|
|
|
|
|
+%% generate a B-format signal using the A-format signal and the static A to B matrix
|
|
|
|
|
+
|
|
|
|
|
+[BF] = sphear_af_to_bf(AF, A2B);
|
|
|
|
|
+
|
|
|
|
|
+%% plot frequency response of B-format components for each measurement direction (just a test)
|
|
|
|
|
+
|
|
|
|
|
+sphear_bf_plot_frequency_response(BF, 300, 20000, -60, 0, 48000, 8192);
|
|
|
|
|
+
|
|
|
|
|
+%% calculate power of B-format signals in logarithmically spaced frequency bands
|
|
|
|
|
+
|
|
|
|
|
+[B, FC, FE] = sphear_signal_power_all(BF, FS, 300, 20000, 1200, 2400, 16, 8192);
|
|
|
|
|
+
|
|
|
|
|
+%% above the transition frequency (see plots above) the B-format behavior
|
|
|
|
|
+%% deviates from the ideal as the capsules are no longer co-located, we use
|
|
|
|
|
+%% the signal power to extract filter shapes from the B-format signals.
|
|
|
|
|
+
|
|
|
|
|
+%% extract the shapes of wxyz filters
|
|
|
|
|
+
|
|
|
|
|
+[W X Y Z] = sphear_bf_extract_filter_shapes(B, OCTA_CARDINALS);
|
|
|
|
|
+
|
|
|
|
|
+[W X Y Z] = sphear_bf_extract_filter_shapes(B, TETRA_CARDINALS);
|
|
|
|
|
+
|
|
|
|
|
+[W X Y Z] = sphear_bf_extract_filter_shapes(B, [1:16]);
|
|
|
|
|
+
|
|
|
|
|
+%% now design four FIR filters, one for each B-format component
|
|
|
|
|
+
|
|
|
|
|
+[FIR] = sphear_design_fir_filters(FC, 512, 15, 48000, W, X, Y);
|
|
|
|
|
+
|
|
|
|
|
+%% in the case of the Octathingy we do use Z for now (this is a hack!)
|
|
|
|
|
+%%
|
|
|
|
|
+%% W needs a longer filter for our microphone, 512 really flattens,
|
|
|
|
|
+%% 256 makes a little bump at around 5KHz. XYZ are happy with a lot
|
|
|
|
|
+%% less, 128 seems fine
|
|
|
|
|
+
|
|
|
|
|
+[FIR] = sphear_design_fir_filters(FC, 512, 15, 48000, W, X, Y, Z);
|
|
|
|
|
+
|
|
|
|
|
+%% look at the shapes of the filters
|
|
|
|
|
+%% for tetrahedral microphones Z is an average estimation so do not plot it
|
|
|
|
|
+
|
|
|
|
|
+sphear_bf_plot_filters(FC, W, X, Y);
|
|
|
|
|
+
|
|
|
|
|
+sphear_bf_plot_filters(FC, W, X, Y, Z);
|
|
|
|
|
+
|
|
|
|
|
+%% re-calculate the full B-format signal with the filters
|
|
|
|
|
+
|
|
|
|
|
+[BF, BFF] = sphear_af_to_bf(AF, A2B, FIR, 8192);
|
|
|
|
|
+
|
|
|
|
|
+%% plot the frequency response of the B-format components for each measurement
|
|
|
|
|
+%% direction, they should all be flat
|
|
|
|
|
+
|
|
|
|
|
+sphear_bf_plot_frequency_response(BFF, 300, 20000, -35, -3, 48000, 8192);
|
|
|
|
|
+
|
|
|
|
|
+%% a revealing plot that highlights the cardinal direction response versus
|
|
|
|
|
+%% the diagonal direction response (incomplete code for the 8 capsule case)
|
|
|
|
|
+
|
|
|
|
|
+sphear_plot_directions(BFF, 300, 20000, -15, 3, 48000, 8192, 1);
|
|
|
|
|
+
|
|
|
|
|
+%% plot the polar response of the B-format components
|
|
|
|
|
+
|
|
|
|
|
+sphear_bf_plot_polar_response(BFF, 800, 1600, 300, 20000, 3, 8192, FS);
|
|
|
|
|
+
|
|
|
|
|
+%% replace the Z polar response with a virtual cardioid pointing in the forward direction
|
|
|
|
|
+
|
|
|
|
|
+sphear_bf_plot_polar_response(BFF, 800, 1600, 300, 20000, 3, 8192, FS, 1.0);
|
|
|
|
|
+
|
|
|
|
|
+%% write a simple Faust A to B encoder that includes the static matrix
|
|
|
|
|
+%% and all FIR filters (not efficient but works)
|
|
|
|
|
+
|
|
|
|
|
+sphear_write_simple_a2b_encoder(A2B, FIR);
|
|
|
|
|
+
|