This is FFTControl.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "FFTControl.h" #define LOGBOTTOM 6.9077552 extern rfft(); @implementation FFTControl - setModView:anObject { modView = anObject; [modView setDisplayMode:DISCRETE]; return self; } - setPhiView:anObject { phiView = anObject; return self; } - setWaveView:anObject { int i; waveView = anObject; dataLength = [waveView tableLength]; fprintf(stderr,"dataLength %d\n",dataLength); FFTData = (float*) calloc(dataLength,sizeof(float)); for(i=0;i<4;i++) storeTable[i] = (float*) calloc(dataLength,sizeof(float)); for(i=0;i<2;i++) swap[i] = (float*) calloc(dataLength,sizeof(float)); PHIData = (float*) calloc(dataLength/2,sizeof(float)); MODData = (float*) calloc(dataLength/2,sizeof(float)); currentBuffer = 0; return self; } - setConvView:anObject { convView = anObject; return self; } - setMod:(float*)data { int i; float *indData, *indFFT, *indMod, *indPhi,maxValue,minValue,Value; [self storeCurrent:self]; indFFT = FFTData; indData = data; indMod = MODData; indPhi = PHIData; if(logDisplay) for(i=0;i<dataLength/2;i++) { float value; value = *(indMod++) = *(indData++) ; value = exp((value - 1)* LOGBOTTOM ); if (value - .00101 <= 0) value = 0; *(indFFT++) = value * cos((*indPhi -.5)*2*M_PI); *(indFFT++) = value * sin((*indPhi++ -.5)*2*M_PI); } else for(i=0;i<dataLength/2;i++) { float value; value = *(indMod++) = *(indData++) ; *(indFFT++) = value * cos((*indPhi -.5)*2*M_PI); *(indFFT++) = value * sin((*indPhi++ -.5)*2*M_PI); } FFTData[0] = MODData[0] * cos(phizero); FFTData[1] = MODData[0] * sin(phizero); rfft(FFTData,dataLength/2,FALSE); indFFT = FFTData; for(i=0,maxValue= -10000.,minValue = 10000. ;i<dataLength;i++) { Value = *(indFFT++); maxValue = MAX(Value,maxValue); minValue = MIN(Value,minValue); } if((minValue<0 || maxValue>1) && minValue - maxValue < 0) { maxValue -= minValue; for(i=0,indFFT = FFTData;i<dataLength;i++,indFFT++) *(indFFT) = (*(indFFT) - minValue) / maxValue; } [waveView setFuncTable:FFTData length:dataLength offset:0]; [waveView draw:self]; [waveView setSound:self]; return self; } - setPhi:(float*)data { int i; float *indData, *indFFT, *indMod, *indPhi,maxValue,minValue,Value; [self storeCurrent:self]; indFFT = FFTData; indData = data; indMod = MODData; indPhi = PHIData; if(logDisplay) for(i=0;i<dataLength/2;i++) { float value; *(indPhi++) = *(indData); value = exp((*(indMod++) - 1) * LOGBOTTOM) ; if (value - .00101 <= 0) value = 0; *(indFFT++) = value * cos((*indData - .5)*2*M_PI); *(indFFT++) = value * sin((*indData++ - .5)*2*M_PI); } else for(i=0;i<dataLength/2;i++) { float value; *(indPhi++) = *(indData); value = *(indMod++); *(indFFT++) = value * cos((*indData - .5)*2*M_PI); *(indFFT++) = value * sin((*indData++ - .5)*2*M_PI); } FFTData[0] = MODData[0] * cos(phizero); FFTData[1] = MODData[0] * sin(phizero); rfft(FFTData,dataLength/2,FALSE); indFFT = FFTData; for(i=0,maxValue= -10000.,minValue = 10000. ;i<dataLength;i++) { Value = *(indFFT++); maxValue = MAX(Value,maxValue); minValue = MIN(Value,minValue); } if((minValue<0 || maxValue>1) && minValue - maxValue < 0) { maxValue -= minValue; for(i=0,indFFT = FFTData;i<dataLength;i++,indFFT++) *(indFFT) = (*(indFFT) - minValue) / ((maxValue -1 < 0) ? 1 : maxValue); } [waveView setFuncTable:FFTData length:dataLength offset:0]; [waveView draw:self]; [waveView setSound:self]; return self; } - receiveData:(float*)data length:(int)aLength { int i; float *indData, *indFFT, *indMod, *indPhi,maxValue,Value; indFFT = FFTData; indData = data; indMod = MODData; indPhi = PHIData; for(i=0;i<dataLength;i++) *(indFFT++) = *(indData++); rfft(FFTData,dataLength/2,TRUE); indFFT = FFTData; phizero = atan2(*(indFFT+1),*(indFFT)) ; for(i=0,maxValue=0;i<dataLength/2;i++,indFFT+=2) { Value = *(indMod++) = hypot(*(indFFT),*(indFFT+1)); if(i) maxValue = MAX(Value,maxValue); } // for(i=0;i<20;i++) // fprintf(stderr,"Phase[%d] = %f\n",i*dataLength/20,FFTData[i*dataLength/20]); indFFT = FFTData; for(i=0,indMod = MODData;i<dataLength/2;i++,indFFT+=2) { float value; if(maxValue != 0) *(indMod) /= maxValue; if(*(indMod) - 1e-4 > 0) *(indPhi++) = .5 + atan2(*(indFFT+1),*(indFFT)) / 2 / M_PI; else *(indPhi++) = *(indPhi - 1); if(logDisplay == YES) *(indMod) = log(MAX(*(indMod),.001))/LOGBOTTOM + 1; indMod ++; } [modView setFuncTable:MODData length:(dataLength/2) offset:0]; [phiView setFuncTable:PHIData length:(dataLength/2) offset:0]; [modView draw:self]; [phiView draw:self]; return self; } - convolve:sender { int i; float *indData,*indMod,maxvalue; indData = [convView table]; indMod = MODData; for(i=0,maxvalue = 0;i<dataLength/2;i++) { float value = *(indData++); maxvalue = MAX(maxvalue,value); } indData = [convView table]; if(logDisplay) for(i=0;i<dataLength/2;i++,indMod++) { float value1 = *(indData++); float value2 = *(indMod); *(indMod) = MAX(0, value2 + value1 - maxvalue); } else for(i=0;i<dataLength/2;i++) { *(indMod++) *= *(indData++); } [modView setFuncTable:MODData length:(dataLength/2) offset:0]; [modView draw:self]; [self setMod:MODData]; return self; } - setLogDisplay:sender { logDisplay = [sender intValue]; [self receiveData:[waveView table] length:[waveView tableLength]]; return self; } - multiply:sender { int i; float *indMult,*indWave,*indWavesup; [self storeCurrent:self]; indMult = [convView table] + dataLength/2 -1; indWave = [waveView table]; indWavesup = indWave + dataLength -1 ; for(i=0;i<dataLength/2;i++) { *(indWave) = (*(indWave++) - .5) * *(indMult) + .5; *(indWavesup) = (*(indWavesup--) -.5) * *(indMult--) + .5; } [waveView draw:self]; [waveView setSound:sender]; [self receiveData:[waveView table] length:dataLength]; return self; } - saveTable:sender { int i; float *storeInd,*indData; storeInd = storeTable[[[sender selectedCell] tag]]; indData = [waveView table]; for(i=0;i<dataLength;i++) *(storeInd++) = *(indData++); return self; } - restoreTable:sender { int i; float *storeInd,*indData; [self storeCurrent:self]; storeInd = storeTable[[[sender selectedCell] tag]]; [waveView setFuncTable:storeInd length:dataLength offset:0]; [waveView draw:self]; [waveView setSound:sender]; [self receiveData:storeInd length:dataLength]; return self; } -storeCurrent:sender { float *indData, *indSwap; int i; indData = [waveView table]; indSwap = swap[currentBuffer]; for(i=0;i<dataLength;i++) *(indSwap++) = *(indData++); return self; } -previous:sender { currentBuffer = 1 - currentBuffer; [self storeCurrent:self]; [waveView setFuncTable:swap[1-currentBuffer] length:dataLength offset:0]; [waveView draw:self]; [waveView setSound:sender]; [self receiveData:swap[1-currentBuffer] length:dataLength]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.