Download src/direction_detection.py from SJTU-TES/WAV2COM: direct link, hf CLI and curl.
- Browser
- Download file 6.97 kB
-
https://huggingface.co/spaces/SJTU-TES/WAV2COM/resolve/main/src/direction_detection.py
- Command line
-
hf download hf://spaces/SJTU-TES/WAV2COM/src/direction_detection.py
-
curl -L -o direction_detection.py https://huggingface.co/spaces/SJTU-TES/WAV2COM/resolve/main/src/direction_detection.py
6.97 kB
| """ | |
| This python script is used for direction detection. | |
| We design the direction detection for 3 wav files types which has | |
| 4, 6 and 8 channels. | |
| """ | |
| import os | |
| import numpy as np | |
| from scipy.io import wavfile | |
| from scipy.signal import butter, lfilter, freqz | |
| from scipy import signal | |
| import matplotlib | |
| import matplotlib.pyplot as plt | |
| offsetVector = [] | |
| """ | |
| The funtion butter_highpass, butter_highpass_filter and calculateResidues are shared | |
| Function offset is used for getAngle_for_eight | |
| """ | |
| def butter_highpass(cutoff, fs, order=5): | |
| nyq = 0.5 * fs | |
| normal_cutoff = cutoff / nyq | |
| b, a = signal.butter(order, normal_cutoff, btype='high', analog=False) | |
| return b, a | |
| def butter_highpass_filter(data, cutoff, fs, order=5): | |
| b, a = butter_highpass(cutoff, fs, order=order) | |
| y = signal.filtfilt(b, a, data) | |
| return y | |
| def calculateResidues(Chan1, Chan2, fs): | |
| S1 = butter_highpass_filter(Chan1, 100, fs, 7) | |
| S2 = butter_highpass_filter(Chan2, 100, fs, 7) | |
| index1 = -1 | |
| index2 = -1 | |
| index = -1 | |
| for i in range(len(S1)): | |
| if S1[i] > 0.03: | |
| index1 = i | |
| break | |
| for i in range(len(S2)): | |
| if S2[i] > 0.03: | |
| index2 = i | |
| break | |
| if (index1 < index2): | |
| index = index1 | |
| else: | |
| index = index2 | |
| residues = np.mean(np.square(S1[index:index + 401] - S2[index:index + 401])) | |
| # offsetVector.append( index1 ) | |
| return residues | |
| def do_iac(signal, pairs, fs): | |
| # signal = data / 32767 | |
| residuesVector = [] | |
| for offset in [5, -5]: | |
| # Computer overall cancellation error for this angle | |
| iterator = 0 | |
| residues = 0 | |
| for mic1, mic2 in pairs: | |
| Chan1 = signal[:, mic1] | |
| Chan2 = signal[:, mic2] | |
| S1 = Chan1 # butter_highpass_filter(Chan1 , 100 , fs , 7) | |
| S2 = Chan2 # butter_highpass_filter(Chan2 , 100 , fs , 7) | |
| index = -1 | |
| for i in range(len(S1)): | |
| if (S1[i] > 0.003 and i > 40): | |
| index = i | |
| break | |
| if (iterator == 0 or iterator == 4): | |
| a = S1[index - 15:index + 15] | |
| b = S2[index - 15:index + 15] | |
| residues += np.square(np.subtract(a, b)) | |
| elif (iterator == 1 or iterator == 3): | |
| a = S1[index - 15 + offset // 2:index + 15 + offset // 2] | |
| b = S2[index - 15:index + 15] | |
| residues += np.square(np.subtract(a, b)) | |
| elif (iterator == 2): | |
| a = S1[index - 15 + offset:index + 15 + offset] | |
| b = S2[index - 15:index + 15] | |
| residues += np.square(np.subtract(a, b)) | |
| elif (iterator == 5 or iterator == 7): | |
| a = S1[index - 15 - offset // 2:index + 15 - offset // 2] | |
| b = S2[index - 15:index + 15] | |
| residues += np.square(np.subtract(a, b)) | |
| elif (iterator == 6): | |
| a = S1[index - 15 - offset:index + 15 - offset] | |
| b = S2[index - 15:index + 15] | |
| residues += np.square(np.subtract(a, b)) | |
| iterator += 1 | |
| residuesVector.append(np.mean(residues)) | |
| return residuesVector[0] < residuesVector[1] | |
| def calculateResidues_eight(Chan1, Chan2, fs): | |
| S1 = Chan1 # butter_highpass_filter(Chan1 , 100 , fs , 7 ) | |
| S2 = Chan2 # butter_highpass_filter(Chan2 , 100 , fs , 7 ) | |
| index1 = -1 | |
| index2 = -1 | |
| index = -1 | |
| for i in range(len(S1)): | |
| if S1[i] > 0.01: | |
| index1 = i | |
| break | |
| for i in range(len(S2)): | |
| if S2[i] > 0.01: | |
| index2 = i | |
| break | |
| if (index1 < index2): | |
| index = index1 | |
| else: | |
| index = index2 | |
| residues = np.mean(np.square(S1[index:index + 401] - S2[index:index + 401])) | |
| return residues | |
| def getAngle_for_eight(data, fs): | |
| signal = data / 32767 | |
| for i in range(8): | |
| column = butter_highpass_filter(signal[:, i], 100, fs, 7) | |
| signal[:, i] = column | |
| pairs = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 0)] | |
| smallestResidues = 100 | |
| closestPair = (0, 0) | |
| offsetIndex = -1 | |
| for iter in range(8): | |
| chan1 = signal[:, pairs[iter][0]] | |
| chan2 = signal[:, pairs[iter][1]] | |
| residues = calculateResidues_eight(chan1, chan2, fs) | |
| if (residues < smallestResidues): | |
| smallestResidues = residues | |
| closestPair = (pairs[iter]) | |
| offsetIndex = iter | |
| if do_iac(signal, pairs, fs) == True: | |
| d1 = abs(offsetIndex - 4) | |
| d2 = abs((offsetIndex + 4) % 8 - 4) | |
| if (d1 < d2): | |
| pass | |
| else: | |
| closestPair = pairs[(offsetIndex + 4) % 8] | |
| mics = (closestPair[0] + 1, closestPair[1] + 1) | |
| return mics | |
| def getAngle_for_six(data, fs): | |
| signal = data / 32767 | |
| pairs = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0)] | |
| smallestResidues = 100 | |
| closestPair = (0, 0) | |
| offsetIndex = -1 | |
| for iter in range(6): | |
| chan1 = signal[:, pairs[iter][0]] | |
| chan2 = signal[:, pairs[iter][1]] | |
| residues = calculateResidues(chan1, chan2, fs) | |
| if (residues < smallestResidues): | |
| smallestResidues = residues | |
| closestPair = (pairs[iter]) | |
| offsetIndex = iter | |
| """ if (offsetVector[offsetIndex] > offsetVector[(offsetIndex+3)%6] ): | |
| closestPair = pairs[(offsetIndex+3)%6] """ | |
| mics = (closestPair[0] + 1, closestPair[1] + 1) | |
| # print(offsetVector) | |
| return mics | |
| def getAngle_for_four(data, fs): | |
| signal = data / 32767 | |
| pairs = [(0, 1), (1, 2), (2, 3), (3, 0)] | |
| smallestResidues = 100 | |
| closestPair = (0, 0) | |
| offsetIndex = -1 | |
| for iter in range(4): | |
| chan1 = signal[:, pairs[iter][0]] | |
| chan2 = signal[:, pairs[iter][1]] | |
| residues = calculateResidues(chan1, chan2, fs) | |
| if (residues < smallestResidues): | |
| smallestResidues = residues | |
| closestPair = (pairs[iter]) | |
| offsetIndex = iter | |
| """ if (offsetVector[offsetIndex] > offsetVector[(offsetIndex+3)%6] ): | |
| closestPair = pairs[(offsetIndex+3)%6] """ | |
| mics = (closestPair[0] + 1, closestPair[1] + 1) | |
| # print(offsetVector) | |
| return mics | |
| def getDirection_Pair(closestPair, num_chan): | |
| """ | |
| :param closestPair: two closet pair, such as (0,1) | |
| :param num_chan: channel numbers, such as 8 | |
| :return: in above parameters, should be [7 0 1 2] | |
| """ | |
| pairs = [0, 0, 0, 0] | |
| pairs[1] = closestPair[0] - 1 | |
| pairs[2] = closestPair[1] - 1 | |
| pairs[0] = (pairs[1] - int(num_chan/2)) % num_chan | |
| pairs[3] = (pairs[2] + int(num_chan/2)) % num_chan | |
| return pairs | |