pyACA: Documentation 0.3.1
Source Code for Audio Content Analysis
Loading...
Searching...
No Matches
computeBeatHisto.py
Go to the documentation of this file.
1# -*- coding: utf-8 -*-
2
3import numpy as np
4
5from pyACA.computeSpectrogram import computeSpectrogram
6from pyACA.computeNoveltyFunction import computeNoveltyFunction
7from pyACA.ToolPreprocAudio import ToolPreprocAudio
8from pyACA.ToolComputeHann import ToolComputeHann
9from pyACA.ToolReadAudio import ToolReadAudio
10
11
12
23def computeBeatHisto(x, f_s, cMethod='FFT', afWindow=None, iBlockLength=1024, iHopLength=8):
24 # compute window function for FFT
25 if afWindow is None:
26 afWindow = ToolComputeHann(iBlockLength)
27
28 assert (afWindow.shape[0] == iBlockLength), "parameter error: invalid window dimension"
29
30 # pre-processing
31 x = ToolPreprocAudio(x)
32
33 # novelty function
34 [d, t, peaks] = computeNoveltyFunction('Flux', x, f_s, afWindow, iBlockLength, iHopLength)
35
36 if cMethod == 'Corr':
37 # compute autocorrelation of result
38 r_dd = np.correlate(d, d, "full") / np.dot(d, d)
39 r_dd = r_dd[np.arange(d.shape[0], r_dd.size)]
40
41 Bpm = np.flip(60 / t[np.arange(1, t.shape[0])])
42 T = np.flip(r_dd)
43
44 elif cMethod == 'FFT':
45 # compute the magnitude spectrum of result
46 iHistoLength = 65536
47 afWindow = np.zeros(2*iHistoLength)
48 afWindow[np.arange(0, iHistoLength)] = ToolComputeHann(iHistoLength)
49 f_s = f_s / iHopLength
50 if len(d) < 2 * iHistoLength:
51 d = [d, np.zeros([1, 2 * iHistoLength - len(d)])]
52
53 [D, f, t] = computeSpectrogram(d, f_s, afWindow, 2*iHistoLength, iHistoLength/4)
54
55 T = D.mean(axis=1, keepdims=True)
56
57 # restrict Bpm range
58 Bpm = f * 60
59 lIdx = np.argwhere(Bpm < 30)[-1]
60 hIdx = np.argwhere(Bpm > 200)[0]
61 T = T[np.arange(lIdx, hIdx)]
62 Bpm = Bpm[np.arange(lIdx, hIdx)]
63 else:
64 T = 0
65 Bpm = 0
66
67 return T, Bpm
68
69
70def computeBeatHistoCl(cInPath, cOutPath):
71 [f_s, afAudioData] = ToolReadAudio(cInPath)
72
73 [T, Bpm] = computeBeatHisto(afAudioData, f_s)
74
75 result = np.vstack((T, Bpm))
76
77 np.savetxt(cOutPath, result)
78
79
80if __name__ == "__main__":
81 import argparse
82
83 parser = argparse.ArgumentParser(description='Compute simple beat histogram of wav file')
84 parser.add_argument('--infile', metavar='path', required=False,
85 help='path to input audio file')
86 parser.add_argument('--outfile', metavar='path', required=False,
87 help='path to output file')
88
89 args = parser.parse_args()
90 cInPath = args.infile
91 cOutPath = args.outfile
92
93 # only for debugging
94 if __debug__:
95 if not cInPath:
96 cInPath = "../../ACA-Plots/audio/sax_example.wav"
97 if not cOutPath:
98 cOutPath = "c:/temp/out.txt"
99
100 # call the function
101 computeBeatHistoCl(cInPath, cOutPath)
computeBeatHistoCl(cInPath, cOutPath)