void AudioProcAnalyzePitch(int16_t * samples, uint8_t gain, int16_t ** raw_buckets, int16_t ** full_buckets, int16_t ** octave_buckets) { // Apply a window. VectorWindow(ANALOG_BUFFER_LEN, samples, samples, window); // Apply gain and convert to complex. for (unsigned i = 0; i < ANALOG_BUFFER_LEN; ++i) { complex_buf[i].real = samples[i] * gain; complex_buf[i].imag = 0; } // In-place FFT. FFTComplexIP(ANALOG_LOG2_BUFFER_LEN, complex_buf, twiddle, COEFFS_IN_DATA); BitReverseComplex(ANALOG_LOG2_BUFFER_LEN, complex_buf); // Compute magnitude (first half of the buffer). SquareMagnitudeCplx(ANALOG_BUFFER_LEN / 2, complex_buf, samples); // Harmonic suppression. for (int i = ANALOG_BUFFER_LEN / 2 - 1; i >= 0; --i) { samples[i] -= samples[i / 2] / 2; if (samples[i] < 0) samples[i] = 0; } // Apply bucketing. *raw_buckets = samples + ANALOG_BUFFER_LEN / 2; *full_buckets = *raw_buckets + PITCH_COUNT; *octave_buckets = *full_buckets + BUCKET_COUNT; Bucket(samples, *raw_buckets, *full_buckets, *octave_buckets); }
int main(void) { int i = 0; fractional *p_real = &sigCmpx[0].real ; fractcomplex *p_cmpx = &sigCmpx[0] ; #ifndef FFTTWIDCOEFFS_IN_PROGMEM /* Generate TwiddleFactor Coefficients */ TwidFactorInit (LOG2_BLOCK_LENGTH, &twiddleFactors[0], 0); /* We need to do this only once at start-up */ #endif for ( i = 0; i < FFT_BLOCK_LENGTH; i++ )/* The FFT function requires input data */ { /* to be in the fractional fixed-point range [-0.5, +0.5]*/ *p_real = *p_real >>1 ; /* So, we shift all data samples by 1 bit to the right. */ *p_real++; /* Should you desire to optimize this process, perform */ } /* data scaling when first obtaining the time samples */ /* Or within the BitReverseComplex function source code */ p_real = &sigCmpx[(FFT_BLOCK_LENGTH/2)-1].real ; /* Set up pointers to convert real array */ p_cmpx = &sigCmpx[FFT_BLOCK_LENGTH-1] ; /* to a complex array. The input array initially has all */ /* the real input samples followed by a series of zeros */ for ( i = FFT_BLOCK_LENGTH; i > 0; i-- ) /* Convert the Real input sample array */ { /* to a Complex input sample array */ (*p_cmpx).real = (*p_real--); /* We will simpy zero out the imaginary */ (*p_cmpx--).imag = 0x0000; /* part of each data sample */ } /* Perform FFT operation */ #ifndef FFTTWIDCOEFFS_IN_PROGMEM FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], &twiddleFactors[0], COEFFS_IN_DATA); #else FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0])); #endif /* Store output samples in bit-reversed order of their addresses */ BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]); /* Compute the square magnitude of the complex FFT output array so we have a Real output vetor */ SquareMagnitudeCplx(FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real); /* Find the frequency Bin ( = index into the SigCmpx[] array) that has the largest energy*/ /* i.e., the largest spectral component */ VectorMax(FFT_BLOCK_LENGTH/2, &sigCmpx[0].real, &peakFrequencyBin); /* Compute the frequency (in Hz) of the largest spectral component */ peakFrequency = peakFrequencyBin*(SAMPLING_RATE/FFT_BLOCK_LENGTH); while (1); /* Place a breakpoint here and observe the watch window variables */ }
int main(void) { ex_sask_init(); /*Initialise Audio input and output function*/ ADCChannelInit(pADCChannelHandle, adcBuffer); OCPWMInit(pOCPWMHandle, ocPWMBuffer); /*Start Audio input and output function*/ ADCChannelStart(pADCChannelHandle); OCPWMStart(pOCPWMHandle); /*Initialising variables that are needed for calculating the peak frequency*/ int peakFrequency = 0; int peakFrequencyBin = 0; while (1) { /*Wait till the ADC has a new frame available*/ while (ADCChannelIsBusy(pADCChannelHandle)); /*Read in the Audio Samples from the ADC*/ ADCChannelRead(pADCChannelHandle, frctAudioIn, FRAME_SIZE); /*Computing the FFT of the raw signal*/ fourierTransform(FRAME_SIZE, compX, frctAudioIn); /*Removing the negative part of the FFT output (imaginary part) by zeroing it out*/ filterNegativeFreq(FRAME_SIZE, compXfiltered, compX); /*Compute the square magnitude of the complex FFT output array so we have a Real output vetor*/ SquareMagnitudeCplx(FRAME_SIZE / 2, &compXfiltered[0], &compXfiltered[0].real); /*Find the frequency Bin ( = index into the SigCmpx[] array) that has the largest energy*/ /*i.e., the largest spectral component*/ VectorMax(FRAME_SIZE / 2, &compXfiltered[0].real, &peakFrequencyBin); /*Compute the frequency (in Hz) of the largest spectral component*/ peakFrequency = peakFrequencyBin * (8000 / FRAME_SIZE); /*Uses the peak frequency variable to turn on the corresponding LEDs*/ turnOnLEDs(peakFrequency); /* Used for checking whether the user wants to record */ if (CheckSwitchS1() == PRESSED) { if (switchState == 0) { //startRecording(); Code works, but doesn't record much, only a fraction of a second } else if (switchState == 1) { int i = 0; for (i; i < (FRAME_SIZE)*5; i++) { frctAudioOut[i] = 0; } switchState = 0; firstPartExecutedDecision = 0; } } /* Switch two is just used to toggle between different modes */ if (CheckSwitchS2() == PRESSED) { if (switchState2 == 0) { switchState2 = 1; } else if (switchState2 == 1) { switchState2 = 2; } else if (switchState2 == 2) { switchState2 = 0; } } /* Checking whether the peak frequency is above 800 and if so calling the function playPureSignal() */ if (peakFrequency >= 800) { playPureSignal(peakFrequency); } else if (switchState2 != 2) { int i = 0; for (i; i < FRAME_SIZE; i++) { if (switchState2 == 0) { frctAudioOut[i] = frctAudioIn[i]; //Used for the mode that allows for outputting of the original signal } else if (switchState2 == 1) { frctAudioOut[i] = 0; //Used for the mode that requests silence if the threshold has not been met } } } if (switchState2 == 2) { int i = 0; for (i; i < FRAME_SIZE; i++) { frctAudioOut[i] = 0; } } /* Outputting the pure signal or original sound or silence, depending on what's inside frctAudioOut*/ while (OCPWMIsBusy(pOCPWMHandle)); OCPWMWrite(pOCPWMHandle, frctAudioOut, FRAME_SIZE); } /*============================================================================= | Function used for recording the input signal, a snapshot of the frame | is stored inside the frctAudioOut array, this is done five times as that | was the largest possible size for frctAudioOut array as anything larger would | lead to exhausting the memory, the function records correctly but the recording | is not long enough, hence the code was retired as it requires more work. *===========================================================================*/ void startRecording() { if (firstPartExecutedDecision == 0) { int i = 0; for (i; i < FRAME_SIZE; i++) { frctAudioOut[i] = frctAudioIn[i]*0.5; } firstPartExecutedDecision = 1; } if (firstPartExecutedDecision == 1) { int i = FRAME_SIZE; int iFrameSize = 0; for (i; i < (FRAME_SIZE)*2; i++) { frctAudioOut[i] = frctAudioIn[iFrameSize]*0.5; iFrameSize++; } firstPartExecutedDecision = 2; } if (firstPartExecutedDecision == 2) { int i = (FRAME_SIZE)*2; int iFrameSize = 0; for (i; i < (FRAME_SIZE)*3; i++) { frctAudioOut[i] = frctAudioIn[iFrameSize]*0.5; iFrameSize++; } firstPartExecutedDecision = 3; } if (firstPartExecutedDecision == 3) { int i = (FRAME_SIZE)*3; int iFrameSize = 0; for (i; i < (FRAME_SIZE)*4; i++) { frctAudioOut[i] = frctAudioIn[iFrameSize]*0.5; iFrameSize++; } firstPartExecutedDecision = 4; } if (firstPartExecutedDecision == 4) { int i = (FRAME_SIZE)*4; int iFrameSize = 0; for (i; i < (FRAME_SIZE)*5; i++) { frctAudioOut[i] = frctAudioIn[iFrameSize]*0.5; iFrameSize++; } firstPartExecutedDecision = -1; switchState = 1; } } /*============================================================================= | Function used to generate the pure signal using the createSimpleSignal() | function available in the modulate.h header - this function uses the peak | frequency handed through the parameter call to decide what signal to generate. | The output signal is stored inside the frctAudioOut array which is then | later used for the OCPWMWrite() function to output the sound. *===========================================================================*/ void playPureSignal(int peakFrequency) { int simpleSignalFrequency = 0; if (peakFrequency <= 1600) { simpleSignalFrequency = 500; createSimpleSignal(simpleSignalFrequency, FRAME_SIZE, frctAudioOut); } else if (peakFrequency <= 2400) { simpleSignalFrequency = 800; createSimpleSignal(simpleSignalFrequency, FRAME_SIZE, frctAudioOut); } else if (peakFrequency <= 3200) { simpleSignalFrequency = 1000; createSimpleSignal(simpleSignalFrequency, FRAME_SIZE, frctAudioOut); } else if (peakFrequency <= 4000) { simpleSignalFrequency = 1500; createSimpleSignal(simpleSignalFrequency, FRAME_SIZE, frctAudioOut); } }