From ea14279eca40b695e8cca81f714bb44f5c3bc270 Mon Sep 17 00:00:00 2001 From: cvf-bcn-gituser Date: Wed, 14 Apr 2021 14:47:43 +0200 Subject: [PATCH 1/4] New contour (mono and multi) Test Cases --- .../pitchcontoursmelodyconfidence.npy | Bin 0 -> 1192 bytes .../unittests/pitchcontoursmelodypitch.npy | Bin 0 -> 1192 bytes .../pitchcontoursmonomelodyconfidence.npy | Bin 0 -> 1192 bytes .../pitchcontoursmonomelodypitch.npy | Bin 0 -> 1192 bytes .../pitchcontoursmultimelodypitch.npy | Bin 0 -> 1192 bytes .../pitchcontoursmelodyconfidence.npy | Bin 0 -> 1192 bytes .../pitchcontoursmelodypitch.npy | Bin 0 -> 1192 bytes .../pitchcontoursmonomelodyconfidence.npy | Bin 0 -> 1192 bytes .../pitchcontoursmonomelodypitch.npy | Bin 0 -> 1192 bytes .../pitchcontoursmultimelodypitch.npy | Bin 0 -> 1192 bytes .../tonal/test_pitchcontoursmonomelody.py | 121 ++++++++++++++++++ .../tonal/test_pitchcontoursmultimelody.py | 118 +++++++++++++++++ 12 files changed, 239 insertions(+) create mode 100644 test/src/unittests/pitchcontoursmelodyconfidence.npy create mode 100644 test/src/unittests/pitchcontoursmelodypitch.npy create mode 100644 test/src/unittests/pitchcontoursmonomelodyconfidence.npy create mode 100644 test/src/unittests/pitchcontoursmonomelodypitch.npy create mode 100644 test/src/unittests/pitchcontoursmultimelodypitch.npy create mode 100644 test/src/unittests/tonal/pitchcontours/pitchcontoursmelodyconfidence.npy create mode 100644 test/src/unittests/tonal/pitchcontours/pitchcontoursmelodypitch.npy create mode 100644 test/src/unittests/tonal/pitchcontours/pitchcontoursmonomelodyconfidence.npy create mode 100644 test/src/unittests/tonal/pitchcontours/pitchcontoursmonomelodypitch.npy create mode 100644 test/src/unittests/tonal/pitchcontours/pitchcontoursmultimelodypitch.npy create mode 100644 test/src/unittests/tonal/test_pitchcontoursmonomelody.py create mode 100644 test/src/unittests/tonal/test_pitchcontoursmultimelody.py diff --git a/test/src/unittests/pitchcontoursmelodyconfidence.npy b/test/src/unittests/pitchcontoursmelodyconfidence.npy new file mode 100644 index 0000000000000000000000000000000000000000..2e414316d486d24db494b876f7f4654b256e4e90 GIT binary patch literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0^s?~9H*gz33!ES()!z#orVggnx}`ML1ig6P9qhQ G8l3qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0zg~L#~B&hzw~m3VUYM07hh+)Qa>;TiRUc$2eU!q z=on@WOdO^UMuWs*W`fu-acnfm9%;cKXSuzh&J!vlop-v$Iuq~;)ubCjTb$P{ZF4>- z*$T#qlbW3y_?w&=me)J;>D4*wU#N7Rvbo6Fpd-(@S|it4IX}y}LNpVM&+JWi24Sg; zG%yCSL2@89Abj>zHdxCF^JtDUE&Oq1DOp{3(|kGC<*NU7ZwrD zKN>^8VR+un%{d|4j&5N>wZNsLL7?zj>=6vcptJ;IqthU{_}c;Ca0R7tP}-a|#RDTB zfYL4~U4qoYFevSU#9;XX#)i=#bs+O$c3{&76GNs!`eFG6UYXATM literal 0 HcmV?d00001 diff --git a/test/src/unittests/pitchcontoursmonomelodyconfidence.npy b/test/src/unittests/pitchcontoursmonomelodyconfidence.npy new file mode 100644 index 0000000000000000000000000000000000000000..2e414316d486d24db494b876f7f4654b256e4e90 GIT binary patch literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0^s?~9H*gz33!ES()!z#orVggnx}`ML1ig6P9qhQ G8l3qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0zg~L#~B&hzw~m3VUYM07hh+)Qa>;TiRUc$2eU!q z=on@WOdO^UMuWs*W`fu-acnfm9%;cKXSuzh&J!vlop-v$Iuq~;)ubCjTb$P{ZF4>- z*$T#qlbW3y_?w&=me)J;>D4*wU#N7Rvbo6Fpd-(@S|it4IX}y}LNpVM&+JWi24Sg; zG%yCSL2@89Abj>zHdxCF^JtDUE&Oq1DOp{3(|kGC<*NU7ZwrD zKN>^8VR+un%{d|4j&5N>wZNsLL7?zj>=6vcptJ;IqthU{_}c;Ca0R7tP}-a|#RDTB zfYL4~U4qoYFevSU#9;XX#)i=#bs+O$c3{&76GNs!`eFG6UYXATM literal 0 HcmV?d00001 diff --git a/test/src/unittests/pitchcontoursmultimelodypitch.npy b/test/src/unittests/pitchcontoursmultimelodypitch.npy new file mode 100644 index 0000000000000000000000000000000000000000..b484ed279c8acac6067f013dc75a7766e1b8dcb9 GIT binary patch literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b7HhMGDGwF+bcE(QWXTg=B98QZ_~a)x1$_!SplXS-5AFb0X|EcXYq zLE`8bW)4gorVmDg#9?NF*f4QyG{_!l!60Y3y`jz%DkGhDy2UyZ@CwzW8$w&0*DP&w zJ}B7=#)*@fog4U@oEetaJM-z)IqP4jbe^)g$l0JH&$(J7*I79~%eg`{6O7O7O?L)i zsf;u*2C+eMAT=O-_Ea`l-%j5`uo=y*rOpdJmVq&d-5_1!43Yzx4N?ozf3heE?Ee=Q z5zapvL%?Bp-p$Q9A={2_VM4XQrK3Th@LKE<491|e1Y@JqAi4P40pM^2rEyT&oHfM* zBOid$E+}1s)WR?*?SjN$`2xm<(I9mo^I>*i(+3knra}5)`32;bG9_2%GYcJ@->6zU m-+E{6{A87(^SdPm&U|xpohujUgZUt_*13Al7glMIoGt()-~N06 literal 0 HcmV?d00001 diff --git a/test/src/unittests/tonal/pitchcontours/pitchcontoursmelodyconfidence.npy b/test/src/unittests/tonal/pitchcontours/pitchcontoursmelodyconfidence.npy new file mode 100644 index 0000000000000000000000000000000000000000..2e414316d486d24db494b876f7f4654b256e4e90 GIT binary patch literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0^s?~9H*gz33!ES()!z#orVggnx}`ML1ig6P9qhQ G8l3qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0zg~L#~B&hzw~m3VUYM07hh+)Qa>;TiRUc$2eU!q z=on@WOdO^UMuWs*W`fu-acnfm9%;cKXSuzh&J!vlop-v$Iuq~;)ubCjTb$P{ZF4>- z*$T#qlbW3y_?w&=me)J;>D4*wU#N7Rvbo6Fpd-(@S|it4IX}y}LNpVM&+JWi24Sg; zG%yCSL2@89Abj>zHdxCF^JtDUE&Oq1DOp{3(|kGC<*NU7ZwrD zKN>^8VR+un%{d|4j&5N>wZNsLL7?zj>=6vcptJ;IqthU{_}c;Ca0R7tP}-a|#RDTB zfYL4~U4qoYFevSU#9;XX#)i=#bs+O$c3{&76GNs!`eFG6UYXATM literal 0 HcmV?d00001 diff --git a/test/src/unittests/tonal/pitchcontours/pitchcontoursmonomelodyconfidence.npy b/test/src/unittests/tonal/pitchcontours/pitchcontoursmonomelodyconfidence.npy new file mode 100644 index 0000000000000000000000000000000000000000..2e414316d486d24db494b876f7f4654b256e4e90 GIT binary patch literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0^s?~9H*gz33!ES()!z#orVggnx}`ML1ig6P9qhQ G8l3qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0zg~L#~B&hzw~m3VUYM07hh+)Qa>;TiRUc$2eU!q z=on@WOdO^UMuWs*W`fu-acnfm9%;cKXSuzh&J!vlop-v$Iuq~;)ubCjTb$P{ZF4>- z*$T#qlbW3y_?w&=me)J;>D4*wU#N7Rvbo6Fpd-(@S|it4IX}y}LNpVM&+JWi24Sg; zG%yCSL2@89Abj>zHdxCF^JtDUE&Oq1DOp{3(|kGC<*NU7ZwrD zKN>^8VR+un%{d|4j&5N>wZNsLL7?zj>=6vcptJ;IqthU{_}c;Ca0R7tP}-a|#RDTB zfYL4~U4qoYFevSU#9;XX#)i=#bs+O$c3{&76GNs!`eFG6UYXATM literal 0 HcmV?d00001 diff --git a/test/src/unittests/tonal/pitchcontours/pitchcontoursmultimelodypitch.npy b/test/src/unittests/tonal/pitchcontours/pitchcontoursmultimelodypitch.npy new file mode 100644 index 0000000000000000000000000000000000000000..b484ed279c8acac6067f013dc75a7766e1b8dcb9 GIT binary patch literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b7HhMGDGwF+bcE(QWXTg=B98QZ_~a)x1$_!SplXS-5AFb0X|EcXYq zLE`8bW)4gorVmDg#9?NF*f4QyG{_!l!60Y3y`jz%DkGhDy2UyZ@CwzW8$w&0*DP&w zJ}B7=#)*@fog4U@oEetaJM-z)IqP4jbe^)g$l0JH&$(J7*I79~%eg`{6O7O7O?L)i zsf;u*2C+eMAT=O-_Ea`l-%j5`uo=y*rOpdJmVq&d-5_1!43Yzx4N?ozf3heE?Ee=Q z5zapvL%?Bp-p$Q9A={2_VM4XQrK3Th@LKE<491|e1Y@JqAi4P40pM^2rEyT&oHfM* zBOid$E+}1s)WR?*?SjN$`2xm<(I9mo^I>*i(+3knra}5)`32;bG9_2%GYcJ@->6zU m-+E{6{A87(^SdPm&U|xpohujUgZUt_*13Al7glMIoGt()-~N06 literal 0 HcmV?d00001 diff --git a/test/src/unittests/tonal/test_pitchcontoursmonomelody.py b/test/src/unittests/tonal/test_pitchcontoursmonomelody.py new file mode 100644 index 000000000..6c351be61 --- /dev/null +++ b/test/src/unittests/tonal/test_pitchcontoursmonomelody.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +# Copyright (C) 2006-2016 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 numpy import * +from essentia_test import * + +class TestPitchContoursMonoMelody(TestCase): + + def testInvalidParam(self): + self.assertConfigureFails(PitchContoursMonoMelody(), {'binResolution': -1}) + self.assertConfigureFails(PitchContoursMonoMelody(), {'filterIterations': -1}) + self.assertConfigureFails(PitchContoursMonoMelody(), {'hopSize': -1}) + self.assertConfigureFails(PitchContoursMonoMelody(), {'maxFrequency': -1}) + self.assertConfigureFails(PitchContoursMonoMelody(), {'minFrequency': -1}) + self.assertConfigureFails(PitchContoursMonoMelody(), {'referenceFrequency': -1}) + self.assertConfigureFails(PitchContoursMonoMelody(), {'sampleRate': -1}) + + def testZero(self): + bins = [zeros(1024), zeros(1024)] + saliences = [zeros(1024), zeros(1024)] + startTimes = zeros(1024) + duration = 0.0 + pitch, pitchConfidence = PitchContoursMonoMelody()( bins, saliences, startTimes, duration) + self.assertEqualVector(pitch, []) + self.assertEqualVector(pitchConfidence, []) + + def testEmpty(self): + bins = [[],[]] + saliences = [[],[]] + startTimes = [] + duration = 0.0 + self.assertRaises(RuntimeError, lambda: PitchContoursMonoMelody()(bins, saliences, startTimes, duration)) + + + def testOnes(self): + bins = [ones(1024), ones(1024)] + saliences = [ones(1024), ones(1024)] + startTimes = ones(1024) + duration = 0.0 + pitch, pitchConfidence = PitchContoursMonoMelody()( bins, saliences, startTimes, duration) + self.assertEqualVector(pitch, []) + self.assertEqualVector(pitchConfidence, []) + + def testUnequalInputs(self): + peakBins = [ones(4096), ones(4096)] + peakSaliences = [ones(1024), ones(1024)] + startTimes = ones(1024) + duration = 0.0 + pitch, pitchConfidence = PitchContoursMonoMelody()( peakBins, peakSaliences, startTimes, duration) + self.assertEqualVector(pitch, []) + self.assertEqualVector(pitchConfidence, []) + + def testARealCase(self): + frameSize = 1024 + sr = 44100 + hopSize = 512 + filename = join(testdata.audio_dir, 'recorded', 'vignesh.wav') + audio = MonoLoader(filename=filename, sampleRate=44100)() + + # Declare the algorithmns to be called + psf = PitchSalienceFunction() + psfp = PitchSalienceFunctionPeaks() + w = Windowing(type='hann', normalized=False) + spectrum = Spectrum() + spectralpeaks = SpectralPeaks() + pc = PitchContours() + pcm = PitchContoursMonoMelody() + + peakBins = [] + peakSaliences = [] + for frame in FrameGenerator(audio, frameSize=1024, hopSize=hopSize, + startFromZero=True): + + freq_speaks, mag_speaks = SpectralPeaks()(audio) + # Start with default params + calculatedPitchSalience = psf(freq_speaks,mag_speaks) + freq_peaks, mag_peaks = spectralpeaks(spectrum(w(frame))) + len_freq_peaks = len(freq_peaks) + len_mag_peaks = len(mag_peaks) + freq_peaksp1 = freq_peaks[1:len_freq_peaks] + mag_peaksp1 = mag_peaks[1:len_mag_peaks] + salienceFunction = psf(freq_peaksp1, mag_peaksp1) + bins, values = psfp(salienceFunction) + peakBins.append(bins) + peakSaliences.append(values) + + bins, saliences, startTimes, duration = pc(peakBins, peakSaliences) + pitch, pitchConfidence = pcm(bins, saliences, startTimes, duration) + #This code stores reference values in a file for later loading. + save('pitchcontoursmonomelodypitch.npy', pitch) + save('pitchcontoursmonomelodyconfidence.npy', pitchConfidence) + + loadedPitch = load(join(filedir(), 'pitchcontours/pitchcontoursmonomelodypitch.npy')) + loadedPitchConfidence = load(join(filedir(), 'pitchcontours/pitchcontoursmonomelodyconfidence.npy')) + expectedPitch = loadedPitch.tolist() + expectedPitchConfidence = loadedPitchConfidence.tolist() + self.assertAlmostEqualVectorFixedPrecision(pitch, expectedPitch,2) + self.assertAlmostEqualVectorFixedPrecision(pitchConfidence, expectedPitchConfidence,2) + + +suite = allTests(TestPitchContoursMonoMelody) + +if __name__ == '__main__': + TextTestRunner(verbosity=2).run(suite) diff --git a/test/src/unittests/tonal/test_pitchcontoursmultimelody.py b/test/src/unittests/tonal/test_pitchcontoursmultimelody.py new file mode 100644 index 000000000..e7d036bbb --- /dev/null +++ b/test/src/unittests/tonal/test_pitchcontoursmultimelody.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +# Copyright (C) 2006-2016 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 numpy import * +from essentia_test import * + +class TestPitchContoursMultiMelody(TestCase): + + def testInvalidParam(self): + self.assertConfigureFails(PitchContoursMultiMelody(), {'binResolution': -1}) + self.assertConfigureFails(PitchContoursMultiMelody(), {'filterIterations': -1}) + self.assertConfigureFails(PitchContoursMultiMelody(), {'hopSize': -1}) + self.assertConfigureFails(PitchContoursMultiMelody(), {'maxFrequency': -1}) + self.assertConfigureFails(PitchContoursMultiMelody(), {'minFrequency': -1}) + self.assertConfigureFails(PitchContoursMultiMelody(), {'referenceFrequency': -1}) + self.assertConfigureFails(PitchContoursMultiMelody(), {'sampleRate': -1}) + + + def testZero(self): + bins = [zeros(1024), zeros(1024)] + saliences = [zeros(1024), zeros(1024)] + startTimes = zeros(1024) + duration = 0.0 + pitch = PitchContoursMultiMelody()( bins, saliences, startTimes, duration) + self.assertEqualVector(pitch, []) + + + def testEmpty(self): + bins = [[],[]] + saliences = [[],[]] + startTimes = [] + duration = 0.0 + self.assertRaises(RuntimeError, lambda: PitchContoursMultiMelody()(bins, saliences, startTimes, duration)) + + def testOnes(self): + bins = [ones(1024), ones(1024)] + saliences = [ones(1024), ones(1024)] + startTimes = ones(1024) + duration = 0.0 + pitch = PitchContoursMultiMelody()( bins, saliences, startTimes, duration) + self.assertEqualVector(pitch, []) + + + def testUnequalInputs(self): + peakBins = [ones(4096), ones(4096)] + peakSaliences = [ones(1024), ones(1024)] + startTimes = ones(1024) + duration = 0.0 + pitch = PitchContoursMultiMelody()( peakBins, peakSaliences, startTimes, duration) + self.assertEqualVector(pitch, []) + + + def testARealCase(self): + frameSize = 1024 + sr = 44100 + hopSize = 512 + filename = join(testdata.audio_dir, 'recorded', 'vignesh.wav') + audio = MonoLoader(filename=filename, sampleRate=44100)() + + # Declare the algorithmns to be called + psf = PitchSalienceFunction() + psfp = PitchSalienceFunctionPeaks() + w = Windowing(type='hann', normalized=False) + spectrum = Spectrum() + spectralpeaks = SpectralPeaks() + pc = PitchContours() + pcm = PitchContoursMultiMelody() + + peakBins = [] + peakSaliences = [] + for frame in FrameGenerator(audio, frameSize=1024, hopSize=hopSize, + startFromZero=True): + + freq_speaks, mag_speaks = SpectralPeaks()(audio) + # Start with default params + calculatedPitchSalience = psf(freq_speaks,mag_speaks) + freq_peaks, mag_peaks = spectralpeaks(spectrum(w(frame))) + len_freq_peaks = len(freq_peaks) + len_mag_peaks = len(mag_peaks) + freq_peaksp1 = freq_peaks[1:len_freq_peaks] + mag_peaksp1 = mag_peaks[1:len_mag_peaks] + salienceFunction = psf(freq_peaksp1, mag_peaksp1) + bins, values = psfp(salienceFunction) + peakBins.append(bins) + peakSaliences.append(values) + + bins, saliences, startTimes, duration = pc(peakBins, peakSaliences) + pitch = pcm(bins, saliences, startTimes, duration) + #This code stores reference values in a file for later loading. + save('pitchcontoursmultimelodypitch.npy', pitch) + + loadedPitch = load(join(filedir(), 'pitchcontours/pitchcontoursmultimelodypitch.npy')) + expectedPitch = loadedPitch.tolist() + self.assertAlmostEqualVectorFixedPrecision(pitch, expectedPitch,2) + + + +suite = allTests(TestPitchContoursMultiMelody) + +if __name__ == '__main__': + TextTestRunner(verbosity=2).run(suite) From 9384fb034836dfcca635409f6a031d3ddd4db960 Mon Sep 17 00:00:00 2001 From: cvf-bcn-gituser Date: Fri, 16 Apr 2021 14:39:49 +0200 Subject: [PATCH 2/4] Removed bug in reSegment() function and added UT --- .../tonal/pitchcontoursegmentation.cpp | 4 + .../tonal/test_pitchcontoursegmentation.py | 87 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 test/src/unittests/tonal/test_pitchcontoursegmentation.py diff --git a/src/algorithms/tonal/pitchcontoursegmentation.cpp b/src/algorithms/tonal/pitchcontoursegmentation.cpp index d228ecb54..ad663e292 100644 --- a/src/algorithms/tonal/pitchcontoursegmentation.cpp +++ b/src/algorithms/tonal/pitchcontoursegmentation.cpp @@ -52,6 +52,10 @@ void PitchContourSegmentation::reSegment() { // find sequences of consecutive non-zero pitch values startC.clear(); endC.clear(); + + if (pitch.size()==0){ + throw(EssentiaException("PitchContourSegmentation: Empty pitch values")); + } if (pitch[0] > 0) { startC.push_back(0); diff --git a/test/src/unittests/tonal/test_pitchcontoursegmentation.py b/test/src/unittests/tonal/test_pitchcontoursegmentation.py new file mode 100644 index 000000000..883f7e1c6 --- /dev/null +++ b/test/src/unittests/tonal/test_pitchcontoursegmentation.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python + +# Copyright (C) 2006-2016 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 numpy import * +from essentia_test import * + +class TestPitchContourSegmentation(TestCase): + + def testInvalidParam(self): + self.assertConfigureFails(PitchContourSegmentation(), {'hopSize': -1}) + self.assertConfigureFails(PitchContourSegmentation(), {'minDuration': -1}) + self.assertConfigureFails(PitchContourSegmentation(), {'pitchDistanceThreshold': -1}) + self.assertConfigureFails(PitchContourSegmentation(), {'rmsThreshold': 1}) + self.assertConfigureFails(PitchContourSegmentation(), {'sampleRate': -1}) + self.assertConfigureFails(PitchContourSegmentation(), {'tuningFrequency': -1}) + self.assertConfigureFails(PitchContourSegmentation(), {'tuningFrequency': 50000}) + + def testZero(self): + pitch = zeros(1024) + signal = zeros(1024) + onset, duration, MIDIpitch = PitchContourSegmentation()( pitch,signal) + self.assertEqualVector(onset, []) + self.assertEqualVector(duration, []) + self.assertEqualVector(MIDIpitch, []) + + def testOnes(self): + pitch = ones(1024) + signal = ones(1024) + onset, duration, MIDIpitch = PitchContourSegmentation()( pitch,signal) + self.assertEqualVector(onset, [0]) + self.assertAlmostEqualVector(duration, [2.9692516],8) + self.assertEqualVector(MIDIpitch, [-36.]) + + def testEmpty(self): + pitch = [] + signal = [] + onset, duration, MIDIpitch = PitchContourSegmentation()( pitch,signal) + self.assertEqualVector(onset, []) + self.assertEqualVector(duration, []) + self.assertEqualVector(MIDIpitch, []) + + def testARealCase(self): + frameSize = 1024 + sr = 44100 + hopSize = 512 + filename = join(testdata.audio_dir, 'recorded', 'vignesh.wav') + audio = MonoLoader(filename=filename, sampleRate=44100)() + pm = PitchMelodia() + pitch, pitchConfidence = pm(audio) + + onset, duration, MIDIpitch = PitchContourSegmentation()( pitch,audio) + + referenceOnsets = [0.1015873, 0.5717914, 0.6704762, 0.769161, 0.86784583, 1.0013605, + 1.2161452, 1.31483, 1.4135147, 1.5238096, 1.8227664, 1.9272562, + 2.2204082, 2.3800454, 2.818322 ] + + referenceDurations= [0.4643991, 0.09287982, 0.09287982, 0.09287982, 0.12770975, 0.20897959, + 0.09287982, 0.09287982, 0.1044898, 0.18575963, 0.09868481, 0.17124717, + 0.1538322, 0.43247166, 0.13931973] + + referenceMIDIpitch = [56., 59., 60., 58., 60., 58., 59., 56., 52., 55., 55., 54., 56., 56., 54.] + + self.assertAlmostEqualVector(onset, referenceOnsets, 8) + self.assertAlmostEqualVector(duration, referenceDurations, 8) + self.assertAlmostEqualVector(MIDIpitch, referenceMIDIpitch, 8) + +suite = allTests(TestPitchContourSegmentation) + +if __name__ == '__main__': + TextTestRunner(verbosity=2).run(suite) From 2d43ee6017937031b837910491fcf47c03300143 Mon Sep 17 00:00:00 2001 From: cvf-bcn-gituser Date: Fri, 16 Apr 2021 14:52:47 +0200 Subject: [PATCH 3/4] updated copyright year to 2021 --- test/src/unittests/tonal/test_pitchcontoursegmentation.py | 2 +- test/src/unittests/tonal/test_pitchcontoursmonomelody.py | 2 +- test/src/unittests/tonal/test_pitchcontoursmultimelody.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/src/unittests/tonal/test_pitchcontoursegmentation.py b/test/src/unittests/tonal/test_pitchcontoursegmentation.py index 883f7e1c6..b725ab7dd 100644 --- a/test/src/unittests/tonal/test_pitchcontoursegmentation.py +++ b/test/src/unittests/tonal/test_pitchcontoursegmentation.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (C) 2006-2016 Music Technology Group - Universitat Pompeu Fabra +# Copyright (C) 2006-2021 Music Technology Group - Universitat Pompeu Fabra # # This file is part of Essentia # diff --git a/test/src/unittests/tonal/test_pitchcontoursmonomelody.py b/test/src/unittests/tonal/test_pitchcontoursmonomelody.py index 6c351be61..94293576d 100644 --- a/test/src/unittests/tonal/test_pitchcontoursmonomelody.py +++ b/test/src/unittests/tonal/test_pitchcontoursmonomelody.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (C) 2006-2016 Music Technology Group - Universitat Pompeu Fabra +# Copyright (C) 2006-2021 Music Technology Group - Universitat Pompeu Fabra # # This file is part of Essentia # diff --git a/test/src/unittests/tonal/test_pitchcontoursmultimelody.py b/test/src/unittests/tonal/test_pitchcontoursmultimelody.py index e7d036bbb..1820cd335 100644 --- a/test/src/unittests/tonal/test_pitchcontoursmultimelody.py +++ b/test/src/unittests/tonal/test_pitchcontoursmultimelody.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (C) 2006-2016 Music Technology Group - Universitat Pompeu Fabra +# Copyright (C) 2006-2021 Music Technology Group - Universitat Pompeu Fabra # # This file is part of Essentia # From 8321d7c9dbc05d7496fce5b0ef31da8f38f1460d Mon Sep 17 00:00:00 2001 From: cvf-bcn-gituser Date: Mon, 19 Apr 2021 14:41:03 +0200 Subject: [PATCH 4/4] more non-default param tests in segm. and npy file cleanup --- .../pitchcontoursmelodyconfidence.npy | Bin 1192 -> 0 bytes .../unittests/pitchcontoursmelodypitch.npy | Bin 1192 -> 0 bytes .../pitchcontoursmonomelodyconfidence.npy | Bin 1192 -> 0 bytes .../pitchcontoursmonomelodypitch.npy | Bin 1192 -> 0 bytes .../pitchcontoursmultimelodypitch.npy | Bin 1192 -> 0 bytes .../tonal/test_pitchcontoursegmentation.py | 68 ++++++++++++++++-- 6 files changed, 61 insertions(+), 7 deletions(-) delete mode 100644 test/src/unittests/pitchcontoursmelodyconfidence.npy delete mode 100644 test/src/unittests/pitchcontoursmelodypitch.npy delete mode 100644 test/src/unittests/pitchcontoursmonomelodyconfidence.npy delete mode 100644 test/src/unittests/pitchcontoursmonomelodypitch.npy delete mode 100644 test/src/unittests/pitchcontoursmultimelodypitch.npy diff --git a/test/src/unittests/pitchcontoursmelodyconfidence.npy b/test/src/unittests/pitchcontoursmelodyconfidence.npy deleted file mode 100644 index 2e414316d486d24db494b876f7f4654b256e4e90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0^s?~9H*gz33!ES()!z#orVggnx}`ML1ig6P9qhQ G8l3qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0zg~L#~B&hzw~m3VUYM07hh+)Qa>;TiRUc$2eU!q z=on@WOdO^UMuWs*W`fu-acnfm9%;cKXSuzh&J!vlop-v$Iuq~;)ubCjTb$P{ZF4>- z*$T#qlbW3y_?w&=me)J;>D4*wU#N7Rvbo6Fpd-(@S|it4IX}y}LNpVM&+JWi24Sg; zG%yCSL2@89Abj>zHdxCF^JtDUE&Oq1DOp{3(|kGC<*NU7ZwrD zKN>^8VR+un%{d|4j&5N>wZNsLL7?zj>=6vcptJ;IqthU{_}c;Ca0R7tP}-a|#RDTB zfYL4~U4qoYFevSU#9;XX#)i=#bs+O$c3{&76GNs!`eFG6UYXATM diff --git a/test/src/unittests/pitchcontoursmonomelodyconfidence.npy b/test/src/unittests/pitchcontoursmonomelodyconfidence.npy deleted file mode 100644 index 2e414316d486d24db494b876f7f4654b256e4e90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0^s?~9H*gz33!ES()!z#orVggnx}`ML1ig6P9qhQ G8l3qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b8?ItsN4WCJb+0zg~L#~B&hzw~m3VUYM07hh+)Qa>;TiRUc$2eU!q z=on@WOdO^UMuWs*W`fu-acnfm9%;cKXSuzh&J!vlop-v$Iuq~;)ubCjTb$P{ZF4>- z*$T#qlbW3y_?w&=me)J;>D4*wU#N7Rvbo6Fpd-(@S|it4IX}y}LNpVM&+JWi24Sg; zG%yCSL2@89Abj>zHdxCF^JtDUE&Oq1DOp{3(|kGC<*NU7ZwrD zKN>^8VR+un%{d|4j&5N>wZNsLL7?zj>=6vcptJ;IqthU{_}c;Ca0R7tP}-a|#RDTB zfYL4~U4qoYFevSU#9;XX#)i=#bs+O$c3{&76GNs!`eFG6UYXATM diff --git a/test/src/unittests/pitchcontoursmultimelodypitch.npy b/test/src/unittests/pitchcontoursmultimelodypitch.npy deleted file mode 100644 index b484ed279c8acac6067f013dc75a7766e1b8dcb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1192 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7W@b7HhMGDGwF+bcE(QWXTg=B98QZ_~a)x1$_!SplXS-5AFb0X|EcXYq zLE`8bW)4gorVmDg#9?NF*f4QyG{_!l!60Y3y`jz%DkGhDy2UyZ@CwzW8$w&0*DP&w zJ}B7=#)*@fog4U@oEetaJM-z)IqP4jbe^)g$l0JH&$(J7*I79~%eg`{6O7O7O?L)i zsf;u*2C+eMAT=O-_Ea`l-%j5`uo=y*rOpdJmVq&d-5_1!43Yzx4N?ozf3heE?Ee=Q z5zapvL%?Bp-p$Q9A={2_VM4XQrK3Th@LKE<491|e1Y@JqAi4P40pM^2rEyT&oHfM* zBOid$E+}1s)WR?*?SjN$`2xm<(I9mo^I>*i(+3knra}5)`32;bG9_2%GYcJ@->6zU m-+E{6{A87(^SdPm&U|xpohujUgZUt_*13Al7glMIoGt()-~N06 diff --git a/test/src/unittests/tonal/test_pitchcontoursegmentation.py b/test/src/unittests/tonal/test_pitchcontoursegmentation.py index b725ab7dd..f18d75cde 100644 --- a/test/src/unittests/tonal/test_pitchcontoursegmentation.py +++ b/test/src/unittests/tonal/test_pitchcontoursegmentation.py @@ -44,6 +44,10 @@ def testOnes(self): pitch = ones(1024) signal = ones(1024) onset, duration, MIDIpitch = PitchContourSegmentation()( pitch,signal) + # Expected values for onset is 0, with constant "ones" input. + # Expected values for duration is 2.9692516, with constant "ones" input. + # Expected values for MIDIpitch is -36., with constant "ones" input. + # FIXME there should be no such thing as a negative pitch value-. self.assertEqualVector(onset, [0]) self.assertAlmostEqualVector(duration, [2.9692516],8) self.assertEqualVector(MIDIpitch, [-36.]) @@ -56,7 +60,7 @@ def testEmpty(self): self.assertEqualVector(duration, []) self.assertEqualVector(MIDIpitch, []) - def testARealCase(self): + def testARealCaseDefault(self): frameSize = 1024 sr = 44100 hopSize = 512 @@ -68,19 +72,69 @@ def testARealCase(self): onset, duration, MIDIpitch = PitchContourSegmentation()( pitch,audio) referenceOnsets = [0.1015873, 0.5717914, 0.6704762, 0.769161, 0.86784583, 1.0013605, - 1.2161452, 1.31483, 1.4135147, 1.5238096, 1.8227664, 1.9272562, - 2.2204082, 2.3800454, 2.818322 ] - + 1.2161452, 1.31483, 1.4135147, 1.5238096, 1.8227664, 1.9272562, + 2.2204082, 2.3800454, 2.818322 ] referenceDurations= [0.4643991, 0.09287982, 0.09287982, 0.09287982, 0.12770975, 0.20897959, - 0.09287982, 0.09287982, 0.1044898, 0.18575963, 0.09868481, 0.17124717, - 0.1538322, 0.43247166, 0.13931973] - + 0.09287982, 0.09287982, 0.1044898, 0.18575963, 0.09868481, 0.17124717, + 0.1538322, 0.43247166, 0.13931973] referenceMIDIpitch = [56., 59., 60., 58., 60., 58., 59., 56., 52., 55., 55., 54., 56., 56., 54.] self.assertAlmostEqualVector(onset, referenceOnsets, 8) self.assertAlmostEqualVector(duration, referenceDurations, 8) self.assertAlmostEqualVector(MIDIpitch, referenceMIDIpitch, 8) + # Test for different non-default settings of PitchContourSegmentation + def testARealCase1(self): + frameSize = 1024 + sr = 44100 + hopSize = 512 + filename = join(testdata.audio_dir, 'recorded', 'vignesh.wav') + audio = MonoLoader(filename=filename, sampleRate=44100)() + pm = PitchMelodia() + pitch, pitchConfidence = pm(audio) + + onset, duration, MIDIpitch = PitchContourSegmentation(minDuration=0.5,hopSize=256)( pitch,audio) + + referenceOnsets = [0.2031746, 1.1435828, 1.6428118, 2.1420407, 2.64127, 3.6455328, 4.4408164] + referenceDurations = [0.9287982, 0.48761904, 0.48761904, 0.48761904, 0.7778685, 0.5514739, 1.4744672 ] + referenceMIDIpitch = [56.,59., 59., 58., 54., 54., 56.] + + self.assertAlmostEqualVector(onset, referenceOnsets, 8) + self.assertAlmostEqualVector(duration, referenceDurations, 8) + self.assertAlmostEqualVector(MIDIpitch, referenceMIDIpitch, 8) + + onset, duration, MIDIpitch = PitchContourSegmentation(pitchDistanceThreshold=30,rmsThreshold=-1)( pitch,audio) + + referenceOnsets = [0.1015873, 0.2031746, 0.55727893, 0.6559637, 0.7546485, 0.85333335, + 0.95201814, 1.0507029, 1.1755102 , 1.29161 , 1.3902948, 1.4889796, + 1.5876644, 1.8227664, 1.9272562, 2.2204082, 2.3626304, 2.4932427, + 2.8009071 ] + referenceDurations = [0.09578231, 0.34829932, 0.09287982, 0.09287982, 0.09287982, 0.09287982, + 0.09287982, 0.11900227, 0.11029478, 0.09287982, 0.09287982, 0.09287982, + 0.12190476, 0.09868481, 0.17124717,0.13641724, 0.12480725, 0.3018594, + 0.15673469] + referenceMIDIpitch = [56., 56., 58., 60., 58., 60., 59., 58., 59.,57., 53., 53., 55., 55., 54., 56.,56., 56.,54.] + + self.assertAlmostEqualVector(onset, referenceOnsets, 8) + self.assertAlmostEqualVector(duration, referenceDurations, 8) + self.assertAlmostEqualVector(MIDIpitch, referenceMIDIpitch, 8) + + + onset, duration, MIDIpitch = PitchContourSegmentation(pitchDistanceThreshold=100,rmsThreshold=-3)( pitch,audio) + + referenceOnsets = [0.1015873, 0.5834014, 0.68208617, 0.78077096, 0.88816327, 1.0071656, + 1.3322449, 1.4309297, 1.5354195, 1.8227664, 1.9853061, 2.2204082, + 2.829932 ] + referenceDurations = [0.47600907, 0.09287982, 0.09287982,0.1015873, 0.11319728, 0.31927437, + 0.09287982, 0.09868481, 0.17414966, 0.15673469, 0.11319728, 0.6037188, + 0.12770975] + referenceMIDIpitch = [56., 60., 59., 58., 60., 58., 55., 52., 55., 55., 53., 56., 53.] + + self.assertAlmostEqualVector(onset, referenceOnsets, 8) + self.assertAlmostEqualVector(duration, referenceDurations, 8) + self.assertAlmostEqualVector(MIDIpitch, referenceMIDIpitch, 8) + + suite = allTests(TestPitchContourSegmentation) if __name__ == '__main__':