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