-
Notifications
You must be signed in to change notification settings - Fork 555
/
Copy pathtest_pitchhps.py
114 lines (93 loc) · 3.42 KB
/
test_pitchhps.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
#!/usr/bin/env python
# Copyright (C) 2006-2021 Music Technology Group - Universitat Pompeu Fabra
#
# This file is part of Essentia
#
# Essentia is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation (FSF), either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the Affero GNU General Public License
# version 3 along with this program. If not, see http://www.gnu.org/licenses/
from essentia_test import *
from numpy import sin, pi, mean, random
class TestPitchHPS(TestCase):
def testEmpty(self):
self.assertComputeFails(PitchHPS(), [])
def testZero(self):
pitch = PitchHPS()(zeros(1024))
self.assertEqual(pitch, 0)
def testSine(self):
sr = 44100
size = sr*1;
freq = 440
signal = [sin(2.0*pi*freq*i/sr) for i in range(size)]
self.runTest(signal, sr, freq)
def testBandLimitedSquare(self):
sr = 44100
size = sr*1;
freq = 660
w = 2.0*pi*freq
nharms = 10
signal = zeros(size)
for i in range(size):
for harm in range(nharms):
signal[i] += .5/(2.*harm+1)*sin((2*harm+1)*i*w/sr)
self.runTest(signal, sr, freq)
def testBandLimitedSaw(self):
sr = 44100
size = sr*1;
freq = 660
w = 2.0*pi*freq
nharms = 10
signal = zeros(size)
for i in range(1,size):
for harm in range(1,nharms+1):
signal[i] += 1./harm*sin(harm*i*w/sr)
self.runTest(signal, sr, freq, 1.1)
def testBandLimitedSawMasked(self):
sr = 44100
size = sr*1;
freq = 440
w = 2.0*pi*freq
subw = 2.0*pi*(freq-100)
nharms = 10
signal = zeros(size)
for i in range(1,size):
# masking noise:
whitenoise = 2*(random.rand(1)-0.5)
signal[i] += 2*whitenoise
for harm in range(1,nharms):
signal[i] += 1./harm*sin(i*harm*w/sr)
signal = 5*LowPass()(signal)
for i in range(1,size):
for harm in range(1,nharms+1):
signal[i] += .1/harm*sin(i*harm*w/sr)
signal[i] += 0.5*sin(i*subw/sr)
max_signal = max(signal) + 1
signal = signal/max_signal
self.runTest(signal, sr, freq, 1.5)
def runTest(self, signal, sr, freq, pitch_precision = 1):
frameSize = 1024
hopsize = frameSize
frames = FrameGenerator(signal, frameSize=frameSize, hopSize=hopsize)
win = Windowing(type='hann')
pitchDetect = PitchHPS(frameSize=frameSize, sampleRate = sr)
pitch = []
for frame in frames:
spec = Spectrum()(win(frame))
f = pitchDetect(spec)
pitch += [f]
self.assertAlmostEqual(mean(f), freq, pitch_precision)
def testInvalidParam(self):
self.assertConfigureFails(PitchHPS(), {'frameSize' : 1})
self.assertConfigureFails(PitchHPS(), {'sampleRate' : 0})
suite = allTests(TestPitchHPS)
if __name__ == '__main__':
TextTestRunner(verbosity=2).run(suite)