-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathChromagram.py
141 lines (91 loc) · 2.72 KB
/
Chromagram.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#Author: ederwander
#http://ederwander.wordpress.com/2012/03/22/chromagram/
#Date: 11/02/2012
import matplotlib.pyplot as plt
import numpy as np
import scipy.signal as signal2
import math
import wave, pylab
import operator
#FFT Size
Nfft=2048
#Chroma centered on A5 = 880Hz
A5=880
#Number of chroma bins
nbin=12
#Semitone
st=2**(1/float(nbin))
#Step
step=128
#Used for Downsample Signal
fr=11025
#DownSample Factor
df=4
tunechroma1=[np.log2(A5*st**i) for i in range(nbin)]
tunechroma2=[int(np.log2(A5*st**i)) for i in range(nbin)]
chroma=np.asarray(tunechroma1)-np.asarray(tunechroma2);
spf = wave.open('Animal_cut.wav','r')
#Extract Raw Audio from Wav File
signal = spf.readframes(-1)
signal = np.fromstring(signal, 'Int16')
fs = spf.getframerate()
#Stereo to Mono
if spf.getnchannels() == 2:
signal=signal[:,0]
plt.figure(1)
plt.title('Signal Wave...')
plt.plot(signal)
#Normalize
#signal = signal/signal.max();
#signal=signal2.resample(signal,int(round(len(signal)*fr)/float(fs)),window=None)
#downsample with low-pass filtering
#signal=signal2.resample(signal, len(signal)/df)
#Starting DownSample signal using Decimation
b = signal2.firwin(30, 1.0/df)
signal = signal2.lfilter(b, 1., signal)
signal = signal.swapaxes(0,-1)[30+1::4].swapaxes(0,-1)
plt.figure(2)
plt.title('Downsampled Signal...')
plt.plot(signal)
fs = fs / df
step=Nfft-step
Pxx, freqs, bins, im = pylab.specgram(signal,Fs=fs,window=np.hamming(Nfft),NFFT=Nfft,noverlap=step,Fc=0)
freqs = freqs[1:,]
freqschroma=np.asarray(np.log2(freqs)) - np.asarray([int(np.log2(f)) for f in freqs])
nchroma=len(chroma)
nfreqschroma=len(freqschroma)
CD=np.zeros((nfreqschroma, nchroma))
for i in range(nchroma):
CD[:,i] = np.abs(freqschroma - chroma[i])
FlipMatrix=np.flipud(CD)
min_index = []
min_value = []
for i in reversed(range(FlipMatrix.shape[0])):
index, value = min(enumerate(FlipMatrix[i]), key=operator.itemgetter(1))
min_index.append(index)
min_value.append(value)
#Numpy Array for Chroma Scale population
CS = np.zeros((len(chroma),Pxx.shape[1]))
Magnitude= np.log(abs(Pxx[1:,]))
for i in range(CS.shape[0]):
#Find index value in min_index list
a = [index for index,x in enumerate(min_index) if x == i]
#Numpy Array for values in each index
AIndex = np.zeros((len(a),Pxx.shape[1]))
t=0;
for value in a:
AIndex[t,:] = Magnitude[value,:]
t=t+1
MeanMag=[]
for M in AIndex.T:
MeanMag.append(np.mean(M))
CS[i,:] = MeanMag
#normalize the chromagram array
CS= CS / CS.max()
plt.figure(3)
plt.title('Original Magnitude')
plt.imshow(Magnitude.astype('float64'),interpolation='nearest',origin='lower',aspect='auto')
plt.figure(4)
plt.title('Chromagram')
plt.imshow(CS.astype('float64'),interpolation='nearest',origin='lower',aspect='auto')
plt.show()