<jupyter_start><jupyter_text>COUGH ONSET AND COUGH COUNTING. As cough is a 'burst' signal, with a sudden rise in the intensity level. Hence, a sudden temporal change can be witnessed both in the time as well as time-frequency domain. In the Coswara data, the human annotations are peformed more or less denoting cough bouts. Each bout of cough can have 1 to 'n' number of continuous streams of coughs.On detecting the onsets of coughs within these bouts, indirectly,we are also detecting the number of coughs. This has task has been demonstrated on 3 sample files<jupyter_code>import os
import pandas as pd
file_list = glob.glob('both/*')
id_list = []
for file in file_list:
    id_list = id_list + [os.path.basename(file)]
#coughwavefiles
wavefile_list=[]
for ids in id_list:
    wavefile_list = wavefile_list + ['bothaudio/'+ids+'/cough-heavy.wav']

json_list = []
for ji in id_list:
    json_list=json_list + ['both/'+ji+'/cough-heavy_v2.json']
    
with open('ids.txt', 'wb') as i:
    pickle.dump(id_list, i)<jupyter_output><empty_output><jupyter_text>Example file 1<jupyter_code>x, sr=librosa.load(wavefile_list[6],sr=16000)
librosa.display.waveplot(x)<jupyter_output><empty_output><jupyter_text>I have taken the second annotated region for demonstration.<jupyter_code>import librosa.display
import matplotlib.pyplot as plt
sr=16000
with open(json_list[6]) as jsonfile:
    data = js.load(jsonfile)
del data['vol']
del data['stage']
del data['cont']
del data['annotator_name']
del data['quality']
    
librosa.display.waveplot(x[int(data['start_3']*sr):int(data['end_3']*sr)],sr)
coughbout=x[int(data['start_3']*sr):int(data['end_3']*sr)]<jupyter_output><empty_output><jupyter_text>The onset is calculated based on spectral flux of the power spectrogram in a given window. For a large/sudden variation, there will be a huge peak for those few time-frames in which the sudden changes are occuring. Here, the window is taken to be 512 sample window, with hop_length as 32 samples<jupyter_code>onset_env = librosa.onset.onset_strength(y=coughbout, sr=sr, lag=1, power=2.0, n_fft=512, hop_length=32)
plt.plot(onset_env)
#print(len(onset_env))
#print((onset_env))<jupyter_output>/home/ananya/anaconda3/lib/python3.7/site-packages/librosa/filters.py:239: UserWarning: Empty filters detected in mel frequency basis. Some channels will produce empty responses. Try increasing your sampling rate (and fmax) or reducing n_mels.
  "Empty filters detected in mel frequency basis. "<jupyter_text>As can be seen in the above plot, 3 prominent peak can be visualised. There are numerous other peaks too. Hence, to pick the right peaks, peak picking based on onset detection is used, which gives a coarse estimation of the time frames.<jupyter_code>times = librosa.times_like(onset_env, sr=sr)
onset_f = librosa.onset.onset_detect(onset_envelope=onset_env, sr=sr)
print(onset_f)
plt.plot(onset_env)
plt.vlines(onset_f,0, onset_env.max(),color='black', alpha=0.8, linestyle='dotted')
print(times[onset_f])<jupyter_output>[ 28  29  30 336 337 338]
[ 0.896  0.928  0.96  10.752 10.784 10.816]<jupyter_text>To refine this estimation of peaks(true onsets), peak picking is performed based on 'prominence' criteria of the onset-strength envelope, wherein,the top 5% quantile peak values for a given audio segment, only are taken into consideration. As cough values can be considered as bursts, this statistic gives decent results.<jupyter_code>from scipy.signal import find_peaks
peaks,_ = find_peaks(onset_env, prominence=np.quantile(onset_env,0.95))
plt.plot(onset_env)
plt.plot(peaks, onset_env[peaks], 'ob')<jupyter_output><empty_output><jupyter_text>The 'peaks' parameter consequently gives the frame at which the peak occurs.The timing instants obtained from onset envelopes is divided by a factor of 16 due to the values of the parameters: window_size=512 and hop_length=32. (512/32=16). This gives us the true instants(in seconds) of the onset of a single cough.<jupyter_code>print(peaks)
print(times[peaks]/16)<jupyter_output>[ 29 337]
[0.058 0.674]<jupyter_text>I have performed similar operations on two more audio segments for better clarity.   Example file 2<jupyter_code>x, sr=librosa.load(wavefile_list[0],sr=16000)
librosa.display.waveplot(x)
import librosa.display
import matplotlib.pyplot as plt
sr=16000
with open(json_list[0]) as jsonfile:
    data = js.load(jsonfile)
del data['vol']
del data['stage']
del data['cont']
del data['annotator_name']
del data['quality']
    
librosa.display.waveplot(x[int(data['start_1']*sr):int(data['end_1']*sr)],sr)
coughbout=x[int(data['start_1']*sr):int(data['end_1']*sr)]
onset_env = librosa.onset.onset_strength(y=coughbout, sr=sr, lag=1, power=2.0, n_fft=512, hop_length=32)
plt.plot(onset_env)
plt.title('Onsets of cough')
#print(len(onset_env))
#print((onset_env))
times = librosa.times_like(onset_env, sr=sr)
onset_f = librosa.onset.onset_detect(onset_envelope=onset_env, sr=sr)
print(onset_f)
plt.plot(onset_env, color = 'green')
plt.vlines(onset_f,0, onset_env.max(),color='black', alpha=0.8, linestyle='dotted')
print(times[onset_f])

from scipy.signal import find_peaks
peaks,_ = find_peaks(onset_env, prominence=np.quantile(onset_env,0.95))
plt.plot(onset_env, color = 'purple')
plt.plot(peaks, onset_env[peaks], 'ob')<jupyter_output><empty_output><jupyter_text>Example file 3<jupyter_code>x, sr=librosa.load(wavefile_list[1],sr=16000)
librosa.display.waveplot(x)<jupyter_output><empty_output><jupyter_text>I have chosen the first segment for demostration purpose again.<jupyter_code>import librosa.display
import matplotlib.pyplot as plt
sr=16000
with open(json_list[1]) as jsonfile:
    data = js.load(jsonfile)
del data['vol']
del data['stage']
del data['cont']
del data['annotator_name']
del data['quality']
    
librosa.display.waveplot(x[int(data['start_1']*sr):int(data['end_1']*sr)],sr)
coughbout=x[int(data['start_1']*sr):int(data['end_1']*sr)]
onset_env = librosa.onset.onset_strength(y=coughbout, sr=sr, lag=1, power=2.0, n_fft=512, hop_length=32)
plt.plot(onset_env)
plt.title('Onsets of cough')
times = librosa.times_like(onset_env, sr=sr)
onset_f = librosa.onset.onset_detect(onset_envelope=onset_env, sr=sr)
print(onset_f)
plt.plot(onset_env, color = 'green')
plt.vlines(onset_f,0, onset_env.max(),color='black', alpha=0.8, linestyle='dotted')
print(times[onset_f])
from scipy.signal import find_peaks
peaks,_ = find_peaks(onset_env, prominence=np.quantile(onset_env,0.95))
plt.plot(onset_env, color = 'purple')
plt.plot(peaks, onset_env[peaks], 'ob')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12387352986100504, 'fraction_numerical': 0.027340766763403086, 'mean_word_length': 6.985365853658537, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '377979', 'license': 'Apache-2.0', 'n_tokens_mistral': 2551, 'n_tokens_neox': 2322, 'n_words': 594, 'path': '_notebooks/2020-10-16-Cough-onset-and-counting.ipynb', 'repo_name': 'Ananyamuguli/Blogs', 'size': '6547'}