function f = simod( ss, mm, n, ref, sz, plf) % Default values for room scale % and reference distance if nargin == 3 sz = 1; ref = sqrt( sum( (ss-mm).^2)); plf = 1; end if nargin == 4 sz = 1; plf = 1; end if nargin == 5 plf == 1; end % Make sure inputs are of % the same dimensionality if length( ss) ~= length( mm) error('Non-conformant inputs') end % Accept only odd size grids % so that we have a center room if ~mod( n, 2) n = n + 1; disp( 'Bumped order up by 1') end % Default room size (in meters) xm = 1; ym = 1; zm = 1; % Bring input to scale ss = ss / sz; mm = mm / sz; % Check positions validity for i = 1:length(ss) if ss(i) > 1 error( 'Bad source coordinates'); end if mm(i) > 1 error( 'Bad mike coordinates'); end end % Prepare graphics if n > 7 plf = 0; end if plf clf hold on axis equal end % 2-D room case if length( ss) == 2 % Plot unfolded rooms and % get their origin points xo = zeros( 1, n); yo = zeros( 1, n); for i = 1:n xo(i) = i*xm-1; for j = 1:n if plf plot( [i*xm i*xm], [0 j*ym]) plot( [0 i*xm], [j*ym j*ym]) end yo(j) = j*ym-1; if plf plot( xo(i), yo(j), 'x') end end end % Place source and observer % In center room n2 = round( n/2); if plf plot( xo(n2)+ss(1), yo(n2)+ss(2), '*') plot( xo(n2)+mm(1), yo(n2)+mm(2), 'o') end % Place observers in virtual rooms off = 0; if ~mod( floor(n/2), 2) off = 1; end xi = zeros( 1, n); yi = zeros( 1, n); for i = 1:n if mod( i+off,2) xx = xm-ss(1); else xx = ss(1); end xi(i) = xo(i)+xx; for j = 1:n if mod( j+off,2) yy = ym-ss(2); else yy = ss(2); end yi(j) = yo(j)+yy; if plf plot( xi(i), yi(j), 'x') end end end % Get distances of each virtual % source from the observer xs = xo(n2)+mm(1); ys = yo(n2)+mm(2); k = 1; d = zeros( 1, n*n); for i = 1:n for j = 1:n d(k) = sqrt( (xi(i)-xs)^2 + (yi(j)-ys)^2); k = k + 1; end end elseif length( ss) == 3 % 3-D room % Accept only odd size grids % so that we have a center if ~mod( n, 2) n = n + 1; disp( 'Bumped order up by 1') end % Plot unfolded rooms and % get their origin points xo = zeros( 1, n); yo = zeros( 1, n); zo = zeros( 1, n); for i = 1:n xo(i) = i*xm-1; for j = 1:n yo(j) = j*ym-1; for k = 1:n if plf plot3( [0 i*xm], [j*ym j*ym], [k*zm k*zm]) plot3( [i*xm i*xm], [0 j*ym], [k*zm k*zm]) plot3( [i*xm i*xm], [j*ym j*ym], [0 k*zm]) end zo(k) = k*zm-1; % plot3( xo(i), yo(j), zo(k), 'x') end end end if plf view( 166, 16) end % Place source and observer % In center room n2 = round( n/2); if plf plot3( xo(n2)+ss(1), yo(n2)+ss(2), zo(n2)+ss(3), 'g*') plot3( xo(n2)+mm(1), yo(n2)+mm(2), zo(n2)+mm(3), 'go') end % Place observers in virtual rooms off = 0; if ~mod( floor(n/2), 2) off = 1; end xi = zeros( 1, n); yi = zeros( 1, n); zi = zeros( 1, n); for i = 1:n if mod( i+off,2) xx = xm-ss(1); else xx = ss(1); end xi(i) = xo(i)+xx; for j = 1:n if mod( j+off,2) yy = ym-ss(2); else yy = ss(2); end yi(j) = yo(j)+yy; for k = 1:n if mod( k+off,2) zz = zm-ss(3); else zz = ss(3); end zi(k) = zo(k)+zz; if plf plot3( xi(i), yi(j), zi(k), 'rx') end end end end % Get distances of each virtual % source from the observer xs = xo(n2)+mm(1); ys = yo(n2)+mm(2); zs = zo(n2)+mm(3); l = 1; d = ones( 1, n*n*n); for i = 1:n for j = 1:n for k = 1:n d(l) = sqrt( (xi(i)-xs)^2 + (yi(j)-ys)^2 + (zi(k)-zs)^2); l = l + 1; end end end else if length( ss) == 1 error( 'One dimensional rooms not supported') else error( sprintf('Have you seen many rooms with %d dimensions?', length(ss))) end end % Convert distance to time % assume sampling rate of 44.1kHz and % compute reflection tap addresses t = round( (sz*d / 300) * 44100); % Make the filter, assume the % intensity for each reflection % is the inverse of the distance squared % Flip sign to simulate bounce inversion c = d / ref; f(t) = square(linspace(0,pi*length(c),length(c))) ./ (c.^2); % Release graphics if plf hold off end