pyACA: Documentation
0.3.1
Source Code for Audio Content Analysis
Loading...
Searching...
No Matches
pyACA
computeChords.py
Go to the documentation of this file.
1
# -*- coding: utf-8 -*-
2
3
import
numpy
as
np
4
5
from
pyACA.computeFeature
import
computeFeature
6
from
pyACA.ToolPreprocAudio
import
ToolPreprocAudio
7
from
pyACA.ToolViterbi
import
ToolViterbi
8
9
10
21
def
computeChords(x, f_s, iBlockLength=8192, iHopLength=2048):
22
23
# chord names
24
cChords = [
'C Maj'
,
'C# Maj'
,
'D Maj'
,
'D# Maj'
,
'E Maj'
,
'F Maj'
,
25
'F# Maj'
,
'G Maj'
,
'G# Maj'
,
'A Maj'
,
'A# Maj'
,
'B Maj'
,
26
'c min'
,
'c# min'
,
'd min'
,
'd# min'
,
'e min'
,
'f min'
,
27
'f# min'
,
'g min'
,
'g# min'
,
'a min'
,
'a# min'
,
'b min'
]
28
29
# chord templates
30
T =
generateTemplateMatrix_I
()
31
32
# transition probabilities
33
P_T =
getChordTransProb_I
()
34
35
# pre-processing
36
x = ToolPreprocAudio(x, iBlockLength)
37
38
# extract pitch chroma
39
v_pc, t = computeFeature(
'SpectralPitchChroma'
, x, f_s,
None
, iBlockLength, iHopLength)
40
41
# estimate chord probabilities
42
P_E = np.matmul(T, v_pc)
43
P_E = P_E / np.sum(P_E, axis=0)
44
45
# allocate space for two rows of results (one raw, one with Viterbi)
46
# assign series of labels/indices starting with 0
47
aiChordIdx = np.zeros([2, len(t)]).astype(int)
48
aiChordIdx[0, :] = np.argmax(P_E, axis=0).astype(int)
49
50
# compute path with Viterbi algorithm
51
aiChordIdx[1, :], P_res = ToolViterbi(P_E, P_T, np.ones(len(cChords)) / len(cChords),
True
)
52
53
# assign result string
54
cChordLabel = [[cChords[i]
for
i
in
aiChordIdx[0, :]], [cChords[i]
for
i
in
aiChordIdx[1, :]]]
55
56
return
cChordLabel, aiChordIdx, t, P_E
57
58
59
def
generateTemplateMatrix_I
():
60
61
iNumRootNotes = 12
62
63
# init: 12 major and 12 minor triads
64
T = np.zeros([24, 12])
65
66
# all chord pitches are weighted equally
67
T[0, np.array([0, 4, 7])] = 1/3.
68
T[iNumRootNotes, np.array([0, 3, 7])] = 1/3.
69
70
# generate templates for all root notes
71
for
i
in
range(1, iNumRootNotes):
72
T[i, :] = np.roll(T[0, :], i)
73
T[i+iNumRootNotes, :] = np.roll(T[iNumRootNotes, :], i)
74
75
return
T
76
77
78
def
getChordTransProb_I
():
79
80
iNumRootNotes = 12
81
82
# circle of fifth tonic distances
83
circ = np.array([0, -5, 2, -3, 4, -1, 6, 1, -4, 3, -2, 5, -3, 4, -1, 6, 1, -4, 3, -2, 5, 0, -5, 2])
84
85
# set the circle radius and distance
86
R = 1
87
d = .5
88
89
# generate key coordinates (mode in z)
90
x = R * np.cos(2 * np.pi * circ/float(iNumRootNotes))
91
y = R * np.sin(2 * np.pi * circ/float(iNumRootNotes))
92
z = np.zeros(2*iNumRootNotes)
93
z[0:iNumRootNotes] = d
94
95
P_T = np.zeros([len(x), len(x)])
96
97
# compute key distances
98
for
m
in
range(len(x)):
99
for
n
in
range(len(x)):
100
P_T[m, n] = np.sqrt((x[m]-x[n])**2 + (y[m]-y[n])**2 + (z[m]-z[n])**2)
101
102
# convert distances into 'probabilities'
103
P_T = .1+P_T
104
P_T = 1 - P_T/(.1 + np.max(P_T))
105
P_T = P_T / np.sum(P_T, axis=0)
106
107
return
P_T
108
109
110
111
113
def
computeChordsCl
(cPath):
114
from
pyACA.ToolReadAudio
import
ToolReadAudio
115
116
# read audio file
117
[f_s, x] = ToolReadAudio(cPath)
118
119
# compute fingerprint
120
[cChordLabel, aiChordIdx, t, P_E] = computeChords(x, f_s)
121
122
return
cChordLabel, aiChordIdx, t, P_E
123
124
125
if
__name__ ==
"__main__"
:
126
import
argparse
127
128
# add command line args and parse them
129
parser = argparse.ArgumentParser(description=
'Compute chords from wav file'
)
130
parser.add_argument(
'--infile'
, metavar=
'path'
, required=
False
,
131
help=
'path to input audio file'
)
132
133
# retrieve command line args
134
args = parser.parse_args()
135
cPath = args.infile
136
137
# only for debugging
138
if
__debug__:
139
if
not
cPath:
140
cPath =
"../ACA-Plots/audio/sax_example.wav"
141
142
# call the function
143
computeChordsCl(cPath)
pyACA.ToolPreprocAudio
Definition
ToolPreprocAudio.py:1
pyACA.computeChords.getChordTransProb_I
getChordTransProb_I()
Definition
computeChords.py:78
pyACA.computeChords.computeChordsCl
computeChordsCl(cPath)
main
Definition
computeChords.py:113
pyACA.computeChords.generateTemplateMatrix_I
generateTemplateMatrix_I()
Definition
computeChords.py:59
Generated by
1.10.0