Skip to content
Snippets Groups Projects
Commit 4ec719fc authored by ferrari's avatar ferrari
Browse files

Reuse dependent TDOA

parent 6f20cdd0
No related branches found
No related tags found
No related merge requests found
......@@ -78,28 +78,28 @@ def corr(data, pos, w_size, max_tdoa, decimate=1, mode='prepare', hyper=True):
else:
raise ValueError(f'Unknown mode {mode}')
tdoas = np.zeros((len(pos), num_channels), np.float32)
tdoas = np.zeros((len(pos), num_channel_pairs + 1), np.float32)
if hyper: # prepare hyper res
tdoas2 = np.zeros((len(pos), num_channels), np.float32)
tdoas2 = np.zeros((len(pos), num_channel_pairs + 1), np.float32)
poly = PolynomialFeatures(2)
lin = LinearRegression()
pipe = Pipeline([('poly', poly), ('lin', lin)])
ind = np.triu_indices(num_channels - 1)
def _hyperres(taus, cc):
taus = taus + np.stack(np.meshgrid(*(num_channels - 1) * (np.arange(-2, 3),)), 0).reshape(
taus = taus[:num_channels-1] + np.stack(np.meshgrid(*(num_channels - 1) * (np.arange(-2, 3),)), 0).reshape(
num_channels - 1, -1).T
taus = np.matmul(mat, taus.T)
taus = taus[:, np.abs(taus).max(0) <= cc_size // 2]
mean = taus.mean(-1)[:3]
coef = pipe.fit(taus.T[:, :3] - mean,
cc[np.expand_dims(np.arange(num_channel_pairs), 1), taus.astype(np.int)].prod(0)
cc[np.expand_dims(np.arange(num_channel_pairs), 1), taus.astype(int)].prod(0)
).named_steps['lin'].coef_
der = np.zeros((num_channels - 1, num_channels - 1))
der[ind] = coef[4:]
poly_min = np.linalg.lstsq(der + der.T, -coef[1:4], rcond=None)[0] + mean
return pipe.predict(poly_min[np.newaxis]).item(), poly_min
return pipe.predict(poly_min[np.newaxis]).item(), mat @ poly_min
cc = np.empty((num_channel_pairs, dw_size), np.float32)
for i in trange(len(pos)):
......@@ -111,15 +111,15 @@ def corr(data, pos, w_size, max_tdoa, decimate=1, mode='prepare', hyper=True):
cc -= cc.min(-1, keepdims=True)
if mode == 'prepare':
tdoas[i, 0], index = c_corr.c_corr_at(cc, tausf)
tdoas[i, 1:] = ((tausf[:(num_channels - 1), index] + dw_size // 2) % dw_size) - dw_size // 2
tdoas[i, 1:] = ((tausf[:, index] + dw_size // 2) % dw_size) - dw_size // 2
elif mode == 'on-the-fly':
tdoas[i, 0], tij = c_corr.c_corr_all(cc, cc_size//2, num_channels - 1)
tdoas[i, 1:] = tij[:(num_channels - 1)]
tdoas[i, 0], tdoas[i, 1:] = c_corr.c_corr_all(cc, cc_size//2, num_channels - 1)
elif mode == 'smart':
maxs = cc.max(1, keepdims=True)
cc /= maxs
val, tij = smart_gsrp(cc, num_channels - 1, num_channel_pairs, cc_size // 2, tree, program, clean_list)
tdoas[i, 0], tdoas[i, 1:] = np.log10(val * maxs.prod()), tij[:(num_channels - 1)]
val, tdoas[i, 1:] = smart_gsrp(cc, num_channels - 1, num_channel_pairs, cc_size // 2,
tree, program, clean_list)
tdoas[i, 0] = np.log10(val * maxs.prod())
cc *= maxs
else:
raise ValueError(f'Unknown mode {mode}')
......@@ -159,7 +159,7 @@ def main(args):
if not (args.low is None and args.up is None):
print("Filtering...")
if args.low is not None:
if args.highpass is None:
if args.up is None:
sos = sg.butter(3, 2 * args.low / sr, 'highpass', output='sos')
else:
sos = sg.butter(3, [2 * args.low / sr, 2 * args.up / sr], 'bandpass', output='sos')
......@@ -182,17 +182,11 @@ def main(args):
print("Computing TDOAs...")
results = corr(sound, pos, int(sr * args.frame_size), max_tdoa=int(np.ceil(sr * args.max_tdoa)),
decimate=args.decimate if not args.temporal else 1, mode=args.mode, hyper=not args.no_hyperes)
decimate=args.decimate if not args.temporal else 1, mode=args.mode, hyper=not args.no_hyperres)
if args.no_hyperres:
result1 = results
else:
result1, result2 = results
# compute additional non-independent TDOAs # TODO dont recompute them
additional1 = [(b - a) for a, b in itertools.combinations(result1.T[2:], 2)]
result1 = np.hstack((result1,) + tuple(a[:, np.newaxis] for a in additional1))
if not args.no_hyperres:
additional2 = [(b - a) for a, b in itertools.combinations(result2.T[2:], 2)]
result2 = np.hstack((result2,) + tuple(a[:, np.newaxis] for a in additional2))
if args.outfile.endswith('.npy'):
np.save(args.outfile, result1)
......@@ -238,9 +232,9 @@ if __name__ == "__main__":
'with 0 referring to the first channel once channels have been chosen by --channels.')
group2 = parser.add_argument_group('Size settings')
group2.add_argument('-f', '--frame-size', type=float, default=0.2,
group2.add_argument('-f', '--frame-size', type=float, default=0.02,
help='The size of the cross-correlation frames in seconds (default: %(default)s)')
group2.add_argument('-s', '--stride', type=str, default=0.01,
group2.add_argument('-s', '--stride', type=str, default='0.01',
help='The step between the beginnings of sequential frames in seconds (default: %(default)s), '
'or the postion in second if csv file path is given.')
group2.add_argument('-m', '--max-tdoa', type=float, default=0.0011,
......@@ -262,9 +256,9 @@ if __name__ == "__main__":
group4 = parser.add_argument_group('Other')
group4.add_argument('-e', '--erase', action='store_false', help='Erase existing outfile. If outfile exist and '
'--erase is not provide, the script will exit.')
group4.add_argument('-n', '--no-hyperres', action='store_True', help='Disable the hyper resolution evalutation of '
group4.add_argument('-n', '--no-hyperres', action='store_true', help='Disable the hyper resolution evalutation of '
'the TDOA')
group4.add_argument('-M', '--mode', choices={'prepare', 'on-the-fly', 'smart', 'auto'}, default='prepare',
group4.add_argument('-M', '--mode', choices={'prepare', 'on-the-fly', 'smart', 'auto'}, default='smart',
help=f'R|How to explore the TDOA space (default: %(default)s).\n'
f'{BColors.BOLD}prepare{BColors.ENDC} precomputes all the possible TDOA pairs and then '
f'evaluate them. All the results are save in memory.\n'
......@@ -277,11 +271,11 @@ if __name__ == "__main__":
args = parser.parse_args()
try:
if args.mode in ['estimate', 'auto']:
if args.mode in ['auto']:
raise NotImplementedError(f'mode {args.mode} is not yet implemented')
sys.exit(main(args))
except Exception as e:
except KeyError as e:
print(e)
sys.exit(2)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment