Skip to content

Instantly share code, notes, and snippets.

@hirocarma
Last active January 8, 2024 09:11
Show Gist options
  • Save hirocarma/0f6b73dc98f489ca7c642c3e782a3a8c to your computer and use it in GitHub Desktop.
Save hirocarma/0f6b73dc98f489ca7c642c3e782a3a8c to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import sys
import numpy as np
import matplotlib.pyplot as plt
import wave
import scipy.signal as signal
import math
from scipy.interpolate import interp1d
LIMIT_dB = 20
def downsampling(conversion_rate, data, fr) :
decimation_sampleNum = conversion_rate-1
nyqF = (fr/conversion_rate)/2.0
cF = (fr/conversion_rate/2.0-500.)/nyqF
taps = 511
b = signal.firwin(taps, cF)
data = signal.lfilter(b, 1, data)
down_data = []
for i in range(0, len(data), decimation_sampleNum+1):
down_data.append(data[i])
return (down_data, int(fr/conversion_rate))
def smoothing(input, window):
output = []
for i in range(input.shape[0]):
if i < window:
output.append(np.mean(input[:i+window+1]))
elif i > input.shape[0] - 1 - window:
output.append(np.mean(input[i:]))
else:
output.append(np.mean(input[i-window:i+window+1]))
return np.array(output)
def to_db(data, N):
pad = np.zeros(N//2)
pad_data = np.concatenate([pad, data, pad])
rms = np.array([np.sqrt((1/N) * (np.sum(pad_data[i:i+N]))**2) \
for i in range(len(data))])
with np.errstate(divide='ignore'):
db = 20 * np.log10(rms)
return db
def valid_convolve(data, size):
b = np.ones(size)/size
data_mean = np.convolve(data, b, mode="same")
n_conv = math.ceil(size/2)
data_mean[0] *= size/n_conv
for i in range(1, n_conv):
data_mean[i] *= size/(i+n_conv)
data_mean[-i] *= size/(i + n_conv - (size % 2))
return data_mean
def sound_plt(wav_fname, title):
wave_file = wave.open(wav_fname,"rb")
fr = wave_file.getframerate()
nframes = wave_file.getnframes()
data = wave_file.readframes(nframes)
data = np.frombuffer(data, dtype= "int16")
down_rate = 2
down_fr = int(fr / (down_rate * 1000))
down_data, down_fr = downsampling(down_fr , data, fr)
N = int(fr / 42)
db = to_db(down_data, N)
time = np.arange(0, db.shape[0] / down_fr, 1 / down_fr) / 60 / down_rate
sm_db = smoothing(db, 1000)
sm_db_x = [i for i in sm_db if i >= LIMIT_dB]
db_mean = np.mean(sm_db_x)
db_max = (np.max(sm_db_x))
db_max_time = time[np.argmax(sm_db)]
sm_db_s = [i for i in sm_db if i < LIMIT_dB]
silent_time = len(sm_db_s) / down_fr / down_rate
silent_rate = int(int(silent_time) / int(np.max(time) * 60 ) * 1000) / 100
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['IPAPGothic', 'VL PGothic']
fig = plt.figure(figsize=(16, 8), dpi=100, facecolor='tan', tight_layout=True)
ax = fig.add_subplot(111, fc='w', xlabel='分(min)', ylabel='音量(dB)')
ax.set_title(title + " 音量推移")
ax.plot(time, sm_db, 'c', label='signal')
sm_db1 = valid_convolve(sm_db, fr)
time1 = np.linspace(np.min(time), np.max(time), np.size(sm_db1))
ax.plot(time1, sm_db1 , 'r', label='moving average')
ax.set_ylim(LIMIT_dB, 75)
boxdic = {
"facecolor" : "tan",
"edgecolor" : "w",
"boxstyle" : "Round",
"linewidth" : 1
}
ax.axhline(y=db_mean , color='g',linestyle='dashed', linewidth=1)
ax.text(-0.5, db_mean, "average:" + str(round(db_mean,1)) + "dB", size=12)
ax.axvline(x=db_max_time , color='g',linestyle='dashed', linewidth=1)
ax.text(db_max_time, db_max+1, \
"max:" + str(round(db_max,1)) + \
'dB(' + str(round(db_max_time,1)) +'min)', \
size=12)
ax.text(0.01, 0.99, \
"silent time: " + str(int(silent_time)) + 'sec' \
" , silent rate: " + str(silent_rate) + '%' \
" , max(dB): " + str(round(db_max,1)) + 'dB' \
" , average(dB): " + str(round(db_mean,1)) + 'dB' \
, verticalalignment='top', transform=ax.transAxes, size=12, bbox=boxdic)
ax.grid()
plt.legend(bbox_to_anchor=(1, 1), loc='upper right', borderaxespad=0)
fig.savefig(title + str(LIMIT_dB) + 'ret.png', facecolor=fig.get_facecolor())
plt.show()
if __name__ == '__main__':
wav_fname = sys.argv[1]
title = sys.argv[2]
sound_plt(wav_fname,title)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment