/* SigLib Frequency Domain Pitch Shifting Example by interpolation, using a sine wave This algorithm benefits from using overlapping windows, in general, the greater the overlap, the better the performance. ie. the lower the distortion. */ #include #include #include "GraphFunctions.h" #define DEBUG 1 #define LEN 256L #define FFT_SIZE ((SLArrayIndex_t)64) #define INTERP_SIZE ((SLArrayIndex_t)64) #define LOG_FFT_SIZE 6L #define FFT_LEN 256L #define LOG_FFT_LEN ((SLArrayIndex_t)8) #define INPUT_LEN (LEN+INTERP_SIZE) #define RATIO_UP 5L #define RATIO_DOWN 3L SLData_t pRealInput[INPUT_LEN], pImagInput[LEN], pRealOutput[LEN], pImagOutput[LEN]; SLData_t pResults[LEN]; SLData_t RealTime[FFT_SIZE], ImagTime[FFT_SIZE]; SLData_t RealNew[FFT_SIZE], ImagNew[FFT_SIZE]; SLData_t SinePhase; SLData_t *pFFTCoeffs; void main(void) { GraphObject *h2DGraph; /* Declare graph object */ SLArrayIndex_t i, j; /* Allocate enough space for largest FFT */ pFFTCoeffs = SUF_FftCoefficientAllocate (FFT_LEN); h2DGraph = /* Initialize graph */ Create2DGraph ("Frequency Domain Interpolation", /* Graph title */ "Time / Frequency", /* X-Axis label */ "Magnitude", /* Y-Axis label */ SV_AUTO_SCALE, /* Scaling mode */ SV_SIGNED, /* Sign mode */ SV_GRAPH_LINE, /* Graph type */ "localhost"); /* Graph server */ if (h2DGraph == NULL) /* Graph creation failed - e.g is server running ? */ { printf ("\nGraph creation failure. Please check that the server is running\n"); exit (1); } /* Initialise FFT */ SIF_Fft (pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_SIZE); /* FFT Size */ SinePhase = SIGLIB_ZERO; /* If shifting up, generate a low frequency, if shifting down generate a high frequency note : i and j are dummy variables to stop compiler warnings */ if ((i = RATIO_UP) > (j = RATIO_DOWN)) { SDA_SignalGenerate (pRealInput, /* Pointer to destination array */ SIGLIB_SINE_WAVE, /* Signal type - Sine wave */ ((SLData_t)0.9), /* Signal peak level */ SIGLIB_FILL, /* Fill (overwrite) or add to existing array contents */ ((SLData_t)0.038), /* Signal frequency */ SIGLIB_ZERO, /* D.C. Offset */ SIGLIB_ZERO, /* Unused */ SIGLIB_ZERO, /* Signal end value - Unused */ &SinePhase, /* Signal phase - maintained across array boundaries */ SIGLIB_NULL_DATA_PTR, /* Unused */ LEN); /* Output array length */ } else { SDA_SignalGenerate (pRealInput, /* Pointer to destination array */ SIGLIB_SINE_WAVE, /* Signal type - Sine wave */ ((SLData_t)0.9), /* Signal peak level */ SIGLIB_FILL, /* Fill (overwrite) or add to existing array contents */ ((SLData_t)0.138), /* Signal frequency */ SIGLIB_ZERO, /* D.C. Offset */ SIGLIB_ZERO, /* Unused */ SIGLIB_ZERO, /* Signal end value - Unused */ &SinePhase, /* Signal phase - maintained across array boundaries */ SIGLIB_NULL_DATA_PTR, /* Unused */ LEN); /* Output array length */ } for (i = 0; i < LEN; i += (FFT_SIZE / 2)) { /* Copy input data */ SDA_Copy (pRealInput+i, /* Pointer to source array */ RealTime, /* Pointer to destination array */ FFT_SIZE); /* Array length */ /* Perform real FFT */ SDA_Rfft (RealTime, /* Pointer to real array */ ImagTime, /* Pointer to imaginary array */ pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_SIZE, /* FFT size */ LOG_FFT_SIZE); /* log2 FFT size */ /* Perform frequency domain interpolation */ SDA_FdInterpolate (RealTime, /* Pointer to real source array */ ImagTime, /* Pointer to imaginary source array */ RealNew, /* Pointer to real destination array */ ImagNew, /* Pointer to imaginary destination array */ RATIO_UP, /* Ratio up */ RATIO_DOWN, /* Ratio down */ INTERP_SIZE); #if DEBUG Display2DGraph (h2DGraph, /* Graph handle */ "FFT'd RealTime", /* Title of the dataset */ RealTime, /* Array of Double dataset */ FFT_SIZE, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nFFT'd RealTime\nPlease hit to continue . . ."); getchar (); Display2DGraph (h2DGraph, /* Graph handle */ "FFT'd ImagTime", /* Title of the dataset */ ImagTime, /* Array of Double dataset */ FFT_SIZE, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_BLUE, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_ADD); /* New graph */ printf ("\nFFT'd ImagTime\nPlease hit to continue . . ."); getchar (); #endif #if DEBUG Display2DGraph (h2DGraph, /* Graph handle */ "FFT'd RealNew", /* Title of the dataset */ RealNew, /* Array of Double dataset */ FFT_SIZE, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nFFT'd RealNew\nPlease hit to continue . . ."); getchar (); Display2DGraph (h2DGraph, /* Graph handle */ "FFT'd ImagNew", /* Title of the dataset */ ImagNew, /* Array of Double dataset */ FFT_SIZE, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_BLUE, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_ADD); /* New graph */ printf ("\nFFT'd ImagNew\nPlease hit to continue . . ."); getchar (); #endif /* Perform complex inverse FFT */ SDA_Cifft (RealNew, /* Pointer to real array */ ImagNew, /* Pointer to imaginary array */ pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_SIZE, /* FFT size */ LOG_FFT_SIZE); /* log2 FFT size */ for (j = 0; j < FFT_SIZE / 2; j++) { pRealOutput[i+j] = RealNew[j] / FFT_SIZE; pImagOutput[i+j] = ImagNew[j] / FFT_SIZE; } } /* Initialise FFT */ SIF_Fft (pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_LEN); /* FFT Size */ Display2DGraph (h2DGraph, /* Graph handle */ "Real Input", /* Title of the dataset */ pRealInput, /* Array of Double dataset */ LEN, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nReal Input\nPlease hit to continue . . ."); getchar (); Display2DGraph (h2DGraph, /* Graph handle */ "Real Output", /* Title of the dataset */ pRealOutput, /* Array of Double dataset */ LEN, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nReal Output\nPlease hit to continue . . ."); getchar (); /* Perform real FFT */ SDA_Rfft (pRealInput, /* Pointer to real array */ pImagInput, /* Pointer to imaginary array */ pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_LEN, /* FFT size */ LOG_FFT_LEN); /* log2 FFT size */ /* Perform real FFT */ SDA_Rfft (pRealOutput, /* Pointer to real array */ pImagOutput, /* Pointer to imaginary array */ pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_LEN, /* FFT size */ LOG_FFT_LEN); /* log2 FFT size */ /* Calculate real power from complex */ SDA_LogMagnitude (pRealInput, /* Pointer to real source array */ pImagInput, /* Pointer to imaginary source array */ pResults, /* Pointer to log magnitude destination array */ FFT_LEN); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Input spectrum", /* Title of the dataset */ pResults, /* Array of Double dataset */ LEN, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nInput spectrum\nPlease hit to continue . . ."); getchar (); /* Scale arrays for display */ SDA_ComplexScalarDivide (pRealOutput, /* Pointer to real source array */ pImagOutput, /* Pointer to imaginary source array */ ((SLData_t)FFT_LEN), /* Scalar divisor */ pRealOutput, /* Pointer to real destination array */ pImagOutput, /* Pointer to imaginary destination array */ FFT_LEN); /* Array lengths */ /* Calculate real power from complex */ SDA_Magnitude (pRealOutput, /* Pointer to real source array */ pImagOutput, /* Pointer to imaginary source array */ pResults, /* Pointer to log magnitude destination array */ FFT_LEN); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Output spectrum", /* Title of the dataset */ pResults, /* Array of Double dataset */ LEN, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nOutput spectrum\n"); SUF_MemoryFree (pFFTCoeffs); /* Free memory */ }