This is HybridInstrument.m in view mode; [Download] [Up]
#import <objc/Storage.h>
#import <appkit/nextstd.h>
#import <musickit/musickit.h>
#import <soundkit/Sound.h>
#import <sound/convertsound.h>
typedef short HWORD;
#include "../sms.h"
#import "HybridInstrument.h"
#import "hybrid.h"
/*
* function to move the samples to the right in the analysis buffer
*
*/
void moveSamples (float *pFBuffer, int iBufferSize, int iHopSize)
{
memcpy ((char *) pFBuffer, (char *) (pFBuffer+iHopSize),
sizeof(float) * (iBufferSize - iHopSize));
memset ((char *) (pFBuffer+iBufferSize-iHopSize), 0,
sizeof(float) * iHopSize);
}
/*
* function to fill the analysis window with sound samples
*/
void fillWindow (short *pSoundData, int iSample, int iHopSize, short *pIWindow,
int iWindowSize)
{
short * pITemp2, *pITemp1, i;
memcpy ((char *) pIWindow, (char *) (pIWindow+iHopSize),
sizeof(short) * (iWindowSize - iHopSize));
memset ((char *) (pIWindow+iWindowSize-iHopSize), 0,
sizeof(short) * iHopSize);
/* avoid zeroes */
pITemp2 = pIWindow + iWindowSize - iHopSize;
pITemp1 = pSoundData + iSample;
for (i=0;i<iHopSize;++i)
{
*pITemp2++ = !(*pITemp1)? ((random()&2) - 1) :*pITemp1;
pITemp1++;
}
}
@implementation HybridInstrument
/* See HybridInstrument.h for instance variables */
static int iFile1Par = 0,iTimeOffset1Par = 0, iFile2Par = 0,
iTimeOffset2Par = 0, iDur2Par = 0, iFrameRatePar = 0, iOverlapping1Par = 0,
iOverlapping2Par = 0, iGain0Par = 0, iGain1Par = 0, iGainEnvPar = 0,
iNCoefficients0Par = 0, iNCoefficients1Par = 0, iNCoefficientsEnvPar = 0,
iMagBalance0Par = 0, iMagBalance1Par = 0, iMagBalanceEnvPar = 0,
iTimeStretch0Par = 0, iTimeStretch1Par = 0, iTimeStretchEnvPar = 0,
iFilterTypePar = 0, iSmoothOrderPar = 0, iCompression0EnvPar = 0,
iCompression1EnvPar = 0, iCompressionIntEnvPar = 0;
-init
{
[super init];
iCurOutSample = -1;
idSndObj1 = nil;
idSndObj2 = nil;
fFrameRate = 100;
iOverlapping1 = 4;
iOverlapping2 = 4;
fDur1 = 0;
fDur2 = 0;
fTimeOffset1 = 0;
fTimeOffset2 = 0;
fGain0 = 0;
fGain1 = 1;
idGainEnv = nil;
iNCoefficients0 = -1;
iNCoefficients1 = -1;
idNCoefficientsEnv = nil;
fMagBalance0 = 0;
fMagBalance1 = 1;
idMagBalanceEnv = nil;
fTimeStretch0 = 1;
fTimeStretch1 = 0;
idTimeStretchEnv = nil;
iFilterType = 1;
iSmoothOrder = 0;
idCompression0Env = nil;
idCompression1Env = nil;
idCompressionIntEnv = nil;
bNormal = 1;
iFile1Par = [Note parName:"sndFile1"];
iFile2Par = [Note parName:"sndFile2"];
iFrameRatePar = [Note parName:"frameRate"];
iOverlapping1Par = [Note parName:"overlapping1"];
iOverlapping2Par = [Note parName:"overlapping2"];
iTimeOffset1Par = [Note parName:"timeOffset1"];
iTimeOffset2Par = [Note parName:"timeOffset2"];
iDur2Par = [Note parName:"dur2"];
iGain0Par = [Note parName:"gain0"];
iGain1Par = [Note parName:"gain1"];
iGainEnvPar = [Note parName:"gainEnv"];
iNCoefficients0Par = [Note parName:"nCoefficients0"];
iNCoefficients1Par = [Note parName:"nCoefficients1"];
iNCoefficientsEnvPar = [Note parName:"nCoefficientsEnv"];
iMagBalance0Par = [Note parName:"magBalance0"];
iMagBalance1Par = [Note parName:"magBalance1"];
iMagBalanceEnvPar = [Note parName:"magBalanceEnv"];
iTimeStretch0Par = [Note parName:"timeStretch0"];
iTimeStretch1Par = [Note parName:"timeStretch1"];
iTimeStretchEnvPar = [Note parName:"timeStretchEnv"];
iFilterTypePar = [Note parName:"filterType"];
iSmoothOrderPar = [Note parName:"smoothOrder"];
iCompression0EnvPar = [Note parName:"compression0Env"];
iCompression1EnvPar = [Note parName:"compression1Env"];
iCompressionIntEnvPar = [Note parName:"compressionIntEnv"];
iSamplingRate = 22050;
[self addNoteReceiver:[[NoteReceiver alloc] init]];
return self;
}
-setSamplingRate:(double)aSrate normal:(char)bNorm stream:(NXStream *)aStream
/* Invoked once before performance from hybridMk.m. */
{
if ([self inPerformance])
return nil;
iSamplingRate = (int)aSrate;
pStream = aStream;
bNormal = bNorm;
return self;
}
-firstNote:aNote
/* You never invoke this method; it's invoked automatically just before the
receiver writes its first Note. It opens stream to the receiver's filename
(if set) and then sends initializeFile to the receiver.*/
{
SNDAlloc (&pOutSoundStruct,
0, /* data size (we'll set this later) */
SND_FORMAT_LINEAR_16,
iSamplingRate,
1,
0 /* info string space to allocate (for 128 bytes) */ );
/* Write header */
NXWrite(pStream,(char *)pOutSoundStruct, sizeof(*pOutSoundStruct));
pTempStream = NXOpenMemory(NULL, 0L, NX_READWRITE);
return self;
}
-_mixToOutput:(int *)pData length:(int)iLength sample:(int)iFirstSample
{
int iLastSample = iFirstSample + iLength;
int i, iLastCommonSample = 0, iLoc = 0, nSamps = 0;
if (iFirstSample > (iCurOutSample + 1))
{
int *pBuffer;
nSamps = iFirstSample - iCurOutSample;
pBuffer = (int *) calloc (nSamps, sizeof(int));
NXSeek(pTempStream, ((iCurOutSample + 1) * sizeof(int)), NX_FROMSTART);
NXWrite(pTempStream,(char *)pBuffer, nSamps * sizeof(int));
iCurOutSample += nSamps;
free (pBuffer);
}
else if (iCurOutSample >= iFirstSample)
{
int *pBuffer;
NXSeek (pTempStream, (iFirstSample * sizeof (int)), NX_FROMSTART);
iLastCommonSample = MIN (iLastSample, iCurOutSample);
nSamps = MIN (iLength , 1 + iLastCommonSample - iFirstSample);
pBuffer = (int *) calloc (nSamps, sizeof(int));
NXRead (pTempStream, (char *)pBuffer, sizeof(int) * nSamps);
for (i = 0; i < nSamps; i++)
pBuffer[i] += pData[i];
NXSeek(pTempStream, (iFirstSample * sizeof (int)), NX_FROMSTART);
NXWrite (pTempStream, (char *)pBuffer, sizeof(int) * nSamps);
iLoc = nSamps - 1;
free (pBuffer);
}
if (iLastSample > (iCurOutSample + 1))
{
nSamps = iLastSample - (iCurOutSample + 1);
NXSeek(pTempStream, ((iCurOutSample + 1) * sizeof(int)), NX_FROMSTART);
NXWrite(pTempStream,(char *)(pData+iLoc), nSamps * sizeof(int));
iCurOutSample += nSamps;
}
NXFlush(pTempStream);
return self;
}
/* This is invoked when performance is over. */
-afterPerformance
{
if (!pOutSoundStruct) /* Did we never received any notes? */
return self;
pOutSoundStruct->dataSize = iCurOutSample * sizeof(short);
NXSeek(pStream, 0L, NX_FROMSTART);
NXWrite(pStream,(char *)pOutSoundStruct, sizeof(*pOutSoundStruct));
[self normalAmp];
NXFlush(pStream);
NXCloseMemory(pTempStream, NX_FREEBUFFER);
pOutSoundStruct->dataSize = 0;
SNDFree(pOutSoundStruct);
pOutSoundStruct = NULL;
NXSeek(pStream,0L,NX_FROMEND);
NXFlush(pStream);
return self;
}
/* Invoked from afterPerformance, normalizes the amplitude of the resulting
time signal-sound */
-normalAmp
{
int *plBuffer;
short *psBuffer;
int nSamps, iMaxAmp = 0L, nBytes;
register int iSamps;
double fNormFactor;
NXSeek(pTempStream, 0L, NX_FROMEND);
nSamps = MIN ((NXTell(pTempStream) - sizeof(*pOutSoundStruct)) /
sizeof(int),
MAX_BUFF) ;
NXSeek(pTempStream, 0L, NX_FROMSTART);
NXSeek(pStream, sizeof(*pOutSoundStruct), NX_FROMSTART);
if ((plBuffer = (int *) calloc (nSamps, sizeof(int))) == NULL)
{
fprintf(stderr,"Error: out of mem normalAmp1.\n");
return self;
}
if ((psBuffer = (short *) calloc (nSamps, sizeof(short))) == NULL)
{
fprintf(stderr,"Error: out of mem normalAmp2.\n");
return self;
}
if (bNormal)
{
while (nBytes = NXRead (pTempStream, plBuffer, sizeof(int) * nSamps))
for (iSamps = 0; iSamps < nSamps; ++iSamps)
iMaxAmp = MAX(abs(plBuffer[iSamps]), iMaxAmp);
fNormFactor = 32700. / iMaxAmp;
NXSeek(pTempStream, 0L, NX_FROMSTART);
while (nBytes = NXRead (pTempStream, plBuffer, sizeof(int) * nSamps))
{
nSamps = MIN (nBytes >> 2,nSamps);
for (iSamps = 0; iSamps < nSamps; ++iSamps)
psBuffer[iSamps] = plBuffer[iSamps] * fNormFactor;
NXWrite(pStream, psBuffer, nSamps * sizeof(short));
}
}
else while (nBytes = NXRead (pTempStream, plBuffer, sizeof(int) * nSamps))
{
nSamps = MIN (nBytes >> 2,nSamps);
for (iSamps = 0; iSamps < nSamps; ++iSamps)
psBuffer[iSamps] = (short) plBuffer[iSamps];
NXWrite(pStream, psBuffer, nSamps * sizeof(short));
}
free (plBuffer);
free (psBuffer);
return self;
}
-_readParams:aNote
{
char *pChFile1 = [aNote parAsStringNoCopy:iFile1Par];
char *pChFile2 = [aNote parAsStringNoCopy:iFile2Par];
if (!pChFile1 || !strlen(pChFile1)) /* Parameter not present? */
{
fprintf(stderr,"No first input sound file specified.\n");
return nil;
}
if (!pChFile2 || !strlen(pChFile2)) /* Parameter not present? */
{
fprintf(stderr,"No second input sound file specified.\n");
return nil;
}
idSndObj1 = [[Sound alloc] initFromSoundfile:pChFile1];
if (!idSndObj1)
{
fprintf(stderr,"Can't find file %s.\n", pChFile1);
return nil;
}
else if (([idSndObj1 dataFormat] != SND_FORMAT_LINEAR_16) ||
([idSndObj1 channelCount] != 1) ||
([idSndObj1 samplingRate] != iSamplingRate) )
{
[idSndObj1 convertToFormat:SND_FORMAT_LINEAR_16
samplingRate:(double)iSamplingRate
channelCount:1];
if (([idSndObj1 dataFormat] != SND_FORMAT_LINEAR_16) ||
([idSndObj1 channelCount] != 1) ||
([idSndObj1 samplingRate] != iSamplingRate) )
{
fprintf(stderr,"Error: input files must be in 16-bit linear, and \
mono.\n");
return nil;
}
}
idSndObj2 = [[Sound alloc] initFromSoundfile:pChFile2];
if (!idSndObj2)
{
fprintf(stderr,"Can't find file %s.\n", pChFile2);
return nil;
}
else if (([idSndObj2 dataFormat] != SND_FORMAT_LINEAR_16) ||
([idSndObj2 channelCount] != 1) ||
([idSndObj2 samplingRate] != iSamplingRate) )
{
[idSndObj2 convertToFormat:SND_FORMAT_LINEAR_16
samplingRate:(double)iSamplingRate
channelCount:1];
if (([idSndObj2 dataFormat] != SND_FORMAT_LINEAR_16) ||
([idSndObj2 channelCount] != 1) ||
([idSndObj1 samplingRate] != iSamplingRate) )
{
fprintf(stderr,"Error: input files must be in 16-bit linear, and \
mono.\n");
return nil;
}
}
if ([aNote isParPresent:iFrameRatePar])
fFrameRate = [aNote parAsDouble:iFrameRatePar];
if ([aNote isParPresent:iOverlapping1Par])
iOverlapping1 = [aNote parAsInt:iOverlapping1Par];
if ([aNote isParPresent:iOverlapping2Par])
iOverlapping2 = [aNote parAsInt:iOverlapping2Par];
if ([aNote isParPresent:iTimeOffset1Par])
fTimeOffset1 = [aNote parAsDouble:iTimeOffset1Par];
if ([aNote isParPresent:iTimeOffset2Par])
fTimeOffset2 = [aNote parAsDouble:iTimeOffset2Par];
fDur1 = [aNote dur];
if ([aNote isParPresent:iDur2Par])
fDur2 = [aNote parAsDouble:iDur2Par];
if ([aNote isParPresent:iGain0Par])
fGain0 = [aNote parAsDouble:iGain0Par];
if ([aNote isParPresent:iGain1Par])
fGain1 = [aNote parAsDouble:iGain1Par];
if ([aNote isParPresent:iGainEnvPar])
idGainEnv = (Envelope *)[aNote parAsEnvelope:iGainEnvPar];
if ([aNote isParPresent:iNCoefficients0Par])
iNCoefficients0 = [aNote parAsInt:iNCoefficients0Par];
if ([aNote isParPresent:iNCoefficients1Par])
iNCoefficients1 = [aNote parAsInt:iNCoefficients1Par];
if ([aNote isParPresent:iNCoefficientsEnvPar])
idNCoefficientsEnv =
(Envelope *)[aNote parAsEnvelope:iNCoefficientsEnvPar];
if ([aNote isParPresent:iMagBalance0Par])
fMagBalance0 = [aNote parAsDouble:iMagBalance0Par];
if ([aNote isParPresent:iMagBalance1Par])
fMagBalance1 = [aNote parAsDouble:iMagBalance1Par];
if ([aNote isParPresent:iMagBalanceEnvPar])
idMagBalanceEnv = (Envelope *)[aNote parAsEnvelope:iMagBalanceEnvPar];
if ([aNote isParPresent:iTimeStretch0Par])
fTimeStretch0 = [aNote parAsDouble:iTimeStretch0Par];
if ([aNote isParPresent:iTimeStretch1Par])
fTimeStretch1 = [aNote parAsDouble:iTimeStretch1Par];
if ([aNote isParPresent:iTimeStretchEnvPar])
idTimeStretchEnv =
(Envelope *)[aNote parAsEnvelope:iTimeStretchEnvPar];
if ([aNote isParPresent:iFilterTypePar])
iFilterType = [aNote parAsInt:iFilterTypePar];
if ([aNote isParPresent:iSmoothOrderPar])
iSmoothOrder = [aNote parAsInt:iSmoothOrderPar];
if ([aNote isParPresent:iCompression0EnvPar])
idCompression0Env =
(Envelope *)[aNote parAsEnvelope:iCompression0EnvPar];
if ([aNote isParPresent:iCompression1EnvPar])
idCompression1Env =
(Envelope *)[aNote parAsEnvelope:iCompression1EnvPar];
if ([aNote isParPresent:iCompressionIntEnvPar])
idCompressionIntEnv =
(Envelope *)[aNote parAsEnvelope:iCompressionIntEnvPar];
return self;
}
-_generateCompression:(float *)pFArray size:(int)sizeArray
envelope:(id)idEnvelope
{
double xfirst, xlast, y, s, fValT = 1, xval, fVal = 0;
float fXinc;
int lastPoint = [idEnvelope pointCount] - 1;
int i;
[idEnvelope getNth:0 x:&xfirst y:&y smoothing:&s];
[idEnvelope getNth:lastPoint x:&xlast y:&y smoothing:&s];
fXinc = (float) ((xlast - xfirst) / sizeArray);
xval = xfirst;
for (i = 0; i < sizeArray; i++)
{
pFArray[i] = [idEnvelope lookupYForX:xval];
xval += fXinc;
}
return self;
}
-_interpolateArrays:(double)fLocation envelope:(id)idEnvelope
array0:(float *) pFBuffer0 array1:(float *) pFBuffer1
params:(HYB_PARAMS) params
{
double xfirst, xlast, y, s, fVal = 0, xval;
int lastPoint = [idEnvelope pointCount] - 1;
if (idEnvelope)
{
[idEnvelope getNth:0 x:&xfirst y:&y smoothing:&s];
[idEnvelope getNth:lastPoint x:&xlast y:&y smoothing:&s];
xval = xfirst + fLocation * (xlast - xfirst);
fVal = [idEnvelope lookupYForX:xval];
}
InterpolateArrays (pFBuffer0, params.sizeCompressionEnv, pFBuffer1,
params.sizeCompressionEnv, params.pCompressionEnv,
params.sizeCompressionEnv, fVal);
return self;
}
-(float) interpolate:(double)fLocation envelope:(id)idEnvelope
bottom:(double)bottom top:(double)top
{
double xfirst, xlast, y, s, fValT = 1, xval, fVal = 0;
int lastPoint = [idEnvelope pointCount] - 1;
if (idEnvelope)
{
[idEnvelope getNth:0 x:&xfirst y:&y smoothing:&s];
[idEnvelope getNth:lastPoint x:&xlast y:&y smoothing:&s];
xval = xfirst + fLocation * (xlast - xfirst);
fValT = [idEnvelope lookupYForX:xval];
}
fVal = bottom + fValT * (top - bottom);
return (fVal);
}
-realizeNote:aNote fromNoteReceiver:aNoteReceiver
{
MKNoteType type;
/* one of MK_noteDur, MK_noteOn, MK_noteOff, MK_noteUpdate, or MK_mute.
The note type describes the character of the Note, whether it represents
an entire musical note (or event), the beginning, middle, or end of a
note, or no note (no sound) */
if (!aNote) /* el parÖmetre d'entrada */
return self;
type = [aNote noteType]; /* guardem tipus de la nota */
if (type == MK_noteDur || type == MK_noteUpdate)
[self _readParams:aNote];
else
return self;
/* if a real note, synthesize */
if (type == MK_noteDur)
{
short *pSndData1, *pSndData2, *pIWindow1, *pIWindow2;
int iFirstSample, iHopSize1, iRecordSize1, nRecords1, nRecords2,
iHopSize2, iRecordSize2, iSample1, iSample2, nHops, i, iRec,
nSamples, iTmp, sizeMag1, sizeMag2, iLastSample1, iLastSample2;
int *pIBuffer;
float *pFBuffer, fStretch = 1, fLocation, *pFCompBuffer0,
*pFCompBuffer1;
HYB_PARAMS params;
/* Give user feedback: MKGetTime() returns the current time, in
seconds, during a Music Kit performance */
fprintf(stderr,"%f ",MKGetTime());
fflush(stderr);
if (fDur1 < 0)
fDur1 = [idSndObj1 duration];
else
fDur1 = MIN ([idSndObj1 duration], fDur1);
if (fDur2 <= 0)
fDur2 = [idSndObj2 duration];
else
fDur2 = MIN ([idSndObj2 duration], fDur2);
/* loop through the input file */
iFirstSample = MKGetTime() * iSamplingRate;
iHopSize1 = [idSndObj1 samplingRate] / fFrameRate;
iRecordSize1 = iHopSize1 * iOverlapping1;
nRecords2 = nRecords1 = fFrameRate * fDur1;
iHopSize2 = fDur2 * [idSndObj2 samplingRate] / nRecords2;
iRecordSize2 = iHopSize1 * iOverlapping2;
iSample1 = fTimeOffset1 * [idSndObj1 samplingRate];
iSample2 = fTimeOffset2 * [idSndObj2 samplingRate];
iLastSample1 = [idSndObj1 dataSize]/sizeof(short);
iLastSample2 = [idSndObj2 dataSize]/sizeof(short);
pSndData1 = (short *) [idSndObj1 data];
pSndData2 = (short *) [idSndObj2 data];
if ((pFBuffer = (float *) calloc(iRecordSize1, sizeof(float))) == NULL)
return nil;
if ((pIWindow1 = (short *) calloc(iRecordSize1, sizeof(short))) ==
NULL)
return nil;
if ((pIWindow2 = (short *) calloc(iRecordSize2, sizeof(short))) ==
NULL)
return nil;
if ((pIBuffer = (int *) calloc(iHopSize1, sizeof(int))) == NULL)
return nil;
/* initialize window */
nHops = ((iOverlapping1 >> 1) - 1);
for (i = 0; i < nHops; i++)
{
if (iSample1 >= iLastSample1 || iSample2 >= iLastSample2)
{
fprintf(stderr,"Error: reached end of file.\n");
return self;
}
fillWindow (pSndData1, iSample1, iHopSize1, pIWindow1,
iRecordSize1);
fillWindow (pSndData2, iSample2, iHopSize2, pIWindow2,
iRecordSize2);
iSample1 += iHopSize1;
iSample2 += iHopSize2;
}
sizeMag1 =
(int)(pow(2.0,
(double) (1+(floor(log((double)iRecordSize1) /
LOG2)))))/2;
sizeMag2 =
(int) (pow(2.0,
(double) (1+(floor(log((double)iRecordSize2) / LOG2)))))/2;
iTmp = iHopSize2;
if ((pFCompBuffer0 = (float *) calloc(sizeMag1, sizeof(float))) ==
NULL)
return nil;
if ((pFCompBuffer1 = (float *) calloc(sizeMag1, sizeof(float))) ==
NULL)
return nil;
if (idCompression0Env)
[self _generateCompression:pFCompBuffer0 size:sizeMag1
envelope:idCompression0Env];
if (idCompression1Env)
[self _generateCompression:pFCompBuffer1 size:sizeMag1
envelope:idCompression1Env];
if (idCompression1Env || idCompression0Env)
{
if ((params.pCompressionEnv =
(float *) calloc(sizeMag1, sizeof(float))) == NULL)
return nil;
params.sizeCompressionEnv = sizeMag1;
if (!idCompressionIntEnv)
{
if (idCompression0Env)
for (i = 0; i < sizeMag1; i++)
params.pCompressionEnv[i] = pFCompBuffer0[i];
else if (idCompression1Env)
for (i = 0; i < sizeMag1; i++)
params.pCompressionEnv[i] = pFCompBuffer0[i];
}
}
else
{
params.pCompressionEnv = NULL;
params.sizeCompressionEnv = 0;
}
if (iNCoefficients0 == -1)
iNCoefficients0 = MIN (sizeMag1, sizeMag2);
if (iNCoefficients1 == -1)
iNCoefficients1 = MIN (sizeMag1, sizeMag2);
/* Principi del loop principal de tota la aplicacií */
for (iRec = 0; iRec < nRecords1; iRec++)
{
fLocation = iRec / (double) nRecords1;
if (idTimeStretchEnv)
fStretch = [self interpolate:fLocation
envelope:idTimeStretchEnv
bottom:fTimeStretch0
top:fTimeStretch1];
iHopSize2 = fStretch * iTmp;
nSamples = MIN (iHopSize2, iRecordSize2);
if (iSample1+iHopSize1 >= iLastSample1 ||
iSample2+nSamples >= iLastSample2)
{
fprintf(stderr,"Error: reached end of file.\n");
return self;
}
fillWindow (pSndData1, iSample1, iHopSize1, pIWindow1,
iRecordSize1);
fillWindow (pSndData2, iSample2, nSamples, pIWindow2,
iRecordSize2);
params.nCoefficients =
[self interpolate:fLocation envelope:idNCoefficientsEnv
bottom:iNCoefficients0 top:iNCoefficients1];
if (params.nCoefficients > sizeMag1 ||
params.nCoefficients > sizeMag2)
{
params.nCoefficients = MIN (sizeMag1, sizeMag2);
fprintf(stderr,"nCoefficients set to %d\n",
params.nCoefficients);
}
params.fGain =
[self interpolate:fLocation envelope:idGainEnv
bottom:fGain0 top:fGain1];
params.fMagBalance =
[self interpolate:fLocation envelope:idMagBalanceEnv
bottom:fMagBalance0 top:fMagBalance1];
params.iSmoothOrder = iSmoothOrder;
if (params.pCompressionEnv && idCompressionIntEnv)
[self _interpolateArrays:fLocation envelope:idCompressionIntEnv
array0:pFCompBuffer0
array1:pFCompBuffer1
params:params];
if (iFilterType == 1)
Hybridize (pIWindow1, iRecordSize1, pIWindow2, iRecordSize2,
pFBuffer, params);
if (iRec >= iOverlapping1>>1)
{
for (i = 0; i < iHopSize1; i++)
pIBuffer[i] = params.fGain * pFBuffer[i] / iOverlapping1;
[self _mixToOutput:pIBuffer length:iHopSize1
sample:iFirstSample];
}
moveSamples (pFBuffer, iRecordSize1, iHopSize1);
iFirstSample += iHopSize1;
iSample1 += iHopSize1;
iSample2 += iHopSize2;
}
freeBuffers();
[idSndObj1 free];
[idSndObj2 free];
free (pFBuffer);
free (pIWindow1);
free (pIWindow2);
free (pIBuffer);
free (pFCompBuffer0);
free (pFCompBuffer1);
if (params.pCompressionEnv)
free (params.pCompressionEnv);
}
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.