Mercurial > hg > vamp-simple-cepstrum
comparison SimpleCepstrum.cpp @ 33:fb862b3418f3
Update to use Vamp SDK 2.4 FFT implementation
author | Chris Cannam |
---|---|
date | Thu, 12 Jul 2012 12:03:58 +0100 |
parents | 44bb93cae288 |
children | c70ebf24b419 |
comparison
equal
deleted
inserted
replaced
32:c3ce99b666b4 | 33:fb862b3418f3 |
---|---|
20 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 20 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
21 */ | 21 */ |
22 | 22 |
23 #include "SimpleCepstrum.h" | 23 #include "SimpleCepstrum.h" |
24 | 24 |
25 #include "vamp-sdk/FFT.h" | |
26 | |
25 #include <vector> | 27 #include <vector> |
26 #include <algorithm> | 28 #include <algorithm> |
27 | 29 |
28 #include <cstdio> | 30 #include <cstdio> |
29 #include <cmath> | 31 #include <cmath> |
30 #include <complex> | 32 #include <complex> |
33 | |
34 #if ( VAMP_SDK_MAJOR_VERSION < 2 || ( VAMP_SDK_MAJOR_VERSION == 2 && VAMP_SDK_MINOR_VERSION < 4 ) ) | |
35 #error Vamp SDK version 2.4 or newer required | |
36 #endif | |
31 | 37 |
32 using std::string; | 38 using std::string; |
33 | 39 |
34 SimpleCepstrum::SimpleCepstrum(float inputSampleRate) : | 40 SimpleCepstrum::SimpleCepstrum(float inputSampleRate) : |
35 Plugin(inputSampleRate), | 41 Plugin(inputSampleRate), |
652 | 658 |
653 double *env = new double[bs]; | 659 double *env = new double[bs]; |
654 double *io = new double[bs]; | 660 double *io = new double[bs]; |
655 | 661 |
656 //!!! This is only right if the previous transform was an inverse one! | 662 //!!! This is only right if the previous transform was an inverse one! |
657 fft(bs, false, ecep, 0, env, io); | 663 Vamp::FFT::forward(bs, ecep, 0, env, io); |
658 | 664 |
659 for (int i = 0; i < hs; ++i) { | 665 for (int i = 0; i < hs; ++i) { |
660 env[i] = exp(env[i]); | 666 env[i] = exp(env[i]); |
661 } | 667 } |
662 Feature envf; | 668 Feature envf; |
722 } | 728 } |
723 | 729 |
724 if (m_method == InverseSymmetric || | 730 if (m_method == InverseSymmetric || |
725 m_method == InverseAsymmetric) { | 731 m_method == InverseAsymmetric) { |
726 | 732 |
727 fft(bs, true, logmag, 0, rawcep, io); | 733 Vamp::FFT::inverse(bs, logmag, 0, rawcep, io); |
728 | 734 |
729 } else { | 735 } else { |
730 | 736 |
731 fft(bs, false, logmag, 0, rawcep, io); | 737 Vamp::FFT::forward(bs, logmag, 0, rawcep, io); |
732 | 738 |
733 if (m_method == ForwardDifference) { | 739 if (m_method == ForwardDifference) { |
734 for (int i = 0; i < hs; ++i) { | 740 for (int i = 0; i < hs; ++i) { |
735 rawcep[i] = fabs(io[i]) - fabs(rawcep[i]); | 741 rawcep[i] = fabs(io[i]) - fabs(rawcep[i]); |
736 } | 742 } |
759 ri[bs - i] = ri[i]; | 765 ri[bs - i] = ri[i]; |
760 ii[bs - i] = -ii[i]; | 766 ii[bs - i] = -ii[i]; |
761 } | 767 } |
762 } | 768 } |
763 | 769 |
764 fft(bs, true, ri, ii, rawcep, io); | 770 Vamp::FFT::inverse(bs, ri, ii, rawcep, io); |
765 | 771 |
766 delete[] ri; | 772 delete[] ri; |
767 delete[] ii; | 773 delete[] ii; |
768 } | 774 } |
769 | 775 |
800 SimpleCepstrum::getRemainingFeatures() | 806 SimpleCepstrum::getRemainingFeatures() |
801 { | 807 { |
802 FeatureSet fs; | 808 FeatureSet fs; |
803 return fs; | 809 return fs; |
804 } | 810 } |
805 | |
806 void | |
807 SimpleCepstrum::fft(unsigned int n, bool inverse, | |
808 double *ri, double *ii, double *ro, double *io) | |
809 { | |
810 if (!ri || !ro || !io) return; | |
811 | |
812 unsigned int bits; | |
813 unsigned int i, j, k, m; | |
814 unsigned int blockSize, blockEnd; | |
815 | |
816 double tr, ti; | |
817 | |
818 if (n < 2) return; | |
819 if (n & (n-1)) return; | |
820 | |
821 double angle = 2.0 * M_PI; | |
822 if (inverse) angle = -angle; | |
823 | |
824 for (i = 0; ; ++i) { | |
825 if (n & (1 << i)) { | |
826 bits = i; | |
827 break; | |
828 } | |
829 } | |
830 | |
831 static unsigned int tableSize = 0; | |
832 static int *table = 0; | |
833 | |
834 if (tableSize != n) { | |
835 | |
836 delete[] table; | |
837 | |
838 table = new int[n]; | |
839 | |
840 for (i = 0; i < n; ++i) { | |
841 | |
842 m = i; | |
843 | |
844 for (j = k = 0; j < bits; ++j) { | |
845 k = (k << 1) | (m & 1); | |
846 m >>= 1; | |
847 } | |
848 | |
849 table[i] = k; | |
850 } | |
851 | |
852 tableSize = n; | |
853 } | |
854 | |
855 if (ii) { | |
856 for (i = 0; i < n; ++i) { | |
857 ro[table[i]] = ri[i]; | |
858 io[table[i]] = ii[i]; | |
859 } | |
860 } else { | |
861 for (i = 0; i < n; ++i) { | |
862 ro[table[i]] = ri[i]; | |
863 io[table[i]] = 0.0; | |
864 } | |
865 } | |
866 | |
867 blockEnd = 1; | |
868 | |
869 for (blockSize = 2; blockSize <= n; blockSize <<= 1) { | |
870 | |
871 double delta = angle / (double)blockSize; | |
872 double sm2 = -sin(-2 * delta); | |
873 double sm1 = -sin(-delta); | |
874 double cm2 = cos(-2 * delta); | |
875 double cm1 = cos(-delta); | |
876 double w = 2 * cm1; | |
877 double ar[3], ai[3]; | |
878 | |
879 for (i = 0; i < n; i += blockSize) { | |
880 | |
881 ar[2] = cm2; | |
882 ar[1] = cm1; | |
883 | |
884 ai[2] = sm2; | |
885 ai[1] = sm1; | |
886 | |
887 for (j = i, m = 0; m < blockEnd; j++, m++) { | |
888 | |
889 ar[0] = w * ar[1] - ar[2]; | |
890 ar[2] = ar[1]; | |
891 ar[1] = ar[0]; | |
892 | |
893 ai[0] = w * ai[1] - ai[2]; | |
894 ai[2] = ai[1]; | |
895 ai[1] = ai[0]; | |
896 | |
897 k = j + blockEnd; | |
898 tr = ar[0] * ro[k] - ai[0] * io[k]; | |
899 ti = ar[0] * io[k] + ai[0] * ro[k]; | |
900 | |
901 ro[k] = ro[j] - tr; | |
902 io[k] = io[j] - ti; | |
903 | |
904 ro[j] += tr; | |
905 io[j] += ti; | |
906 } | |
907 } | |
908 | |
909 blockEnd = blockSize; | |
910 } | |
911 } | |
912 | |
913 |