This is hybridize.c in view mode; [Download] [Up]
#include "../sms.h" #import "hybrid.h" static float *pFWindow1 = NULL, *pFWindow2 = NULL; static int sizeFft1, sizeFft2, sizeMag1, sizeMag2, sizeSmooth; static float *pFMagSpectrum1, *pFMagSpectrum2, *pFPhaseSpectrum1, *pFPhaseSpectrum2, *pFMagEnv, *pFEnvBuffer, *pFMagEnvFilt; /* * initialize static arrays */ static int InitializeHybrid (int sizeWave1, int sizeWave2, HYB_PARAMS params) { int i; if ((pFWindow1 = (float *) calloc(sizeWave1, sizeof(float))) == NULL) return -1; if ((pFWindow2 = (float *) calloc(sizeWave2, sizeof(float))) == NULL) return -1; for (i=0; i<sizeWave1; i++) pFWindow1[i] = 1.0; Hamming (sizeWave1, pFWindow1); Hamming (sizeWave2, pFWindow2); sizeFft1 = (int) pow(2.0, (double)(1+(floor(log((double)sizeWave1) / LOG2)))); sizeFft2 = (int) pow(2.0, (double) (1+(floor(log((double)sizeWave2) / LOG2)))); sizeMag1 = sizeFft1 >> 1; sizeMag2 = sizeFft2 >> 1; sizeSmooth = 1 + params.iSmoothOrder; if ((pFMagSpectrum2 = (float *) calloc(sizeMag2, sizeof(float))) == NULL) return -1; if ((pFMagSpectrum1 = (float *) calloc(sizeMag1, sizeof(float))) == NULL) return -1; pFPhaseSpectrum2 = NULL; if ((pFPhaseSpectrum1 = (float *) calloc(sizeMag1, sizeof(float))) == NULL) return -1; if ((pFMagEnv = (float *) calloc(sizeMag1, sizeof(float))) == NULL) return -1; if ((pFEnvBuffer = (float *) calloc(sizeMag1 * sizeSmooth, sizeof(float))) == NULL) return -1; if ((pFMagEnvFilt = (float *) calloc(sizeMag1, sizeof(float))) == NULL) return -1; return 1; } int freeBuffers () { free (pFWindow1); pFWindow1 = NULL; free (pFWindow2); pFWindow2 = NULL; if (pFMagSpectrum2) free (pFMagSpectrum2); if (pFMagSpectrum1) free (pFMagSpectrum1); if (pFPhaseSpectrum1) free (pFPhaseSpectrum1); if (pFPhaseSpectrum2) free (pFPhaseSpectrum2); free (pFMagEnv); free (pFEnvBuffer); free (pFMagEnvFilt); return 1; } /* * Compress-Expand a given spectral envelope */ static int CompExp(float *pFEnv,float *pFSpec,float *pFWeight,int sizeSpec) { float *pFEnd=pFSpec+sizeSpec; do { if (*pFWeight == 2.) *pFSpec=1.; else if (!*pFWeight) *pFEnv=1.; else if (*pFWeight > 1 && *pFSpec) *pFSpec=(float)pow(10.,(2.-*pFWeight)*log10((double)*pFSpec)); else if (*pFWeight < 1 && *pFEnv) *pFEnv=(float)pow(10.,*pFWeight*log10((double)*pFEnv)); ++pFWeight; ++pFSpec; ++pFEnv; } while (pFSpec<pFEnd); return 1; } /* * filter each magnitude in a spectrum by the surounding magnitudes */ static int FilterMagEnv (float *pFMagEnv, float *pFMagEnvFilt, int sizeMag) { int sizeEnvBuffer = sizeSmooth * sizeMag; memcpy ((char *) pFEnvBuffer, (char *) (pFEnvBuffer+sizeMag), sizeof(float) * sizeEnvBuffer); memcpy ((char *) (pFEnvBuffer+sizeEnvBuffer-sizeMag), (char *) pFMagEnv, sizeof(float) * sizeMag); FilterArray (pFEnvBuffer, sizeMag, sizeSmooth, pFMagEnvFilt); return 1; } /* * multiply spectral envelope of one sound with magnitude spectrum of the other * * float *pFMagEnv envelope from hybridizing sound * float *pFMagSpectrum magnitude spectrum of excitation sound * int sizeMag size of magnitude spectrum * HYB_PARAMS params control parameters */ static int MultiplySpectra (float *pFMagEnv, float *pFMagSpectrum, int sizeMag, float *pFMagSpectrum2, int sizeMag2, HYB_PARAMS params) { float *pFBuffer, fMag = 0, fAverageMag, fMagEnv = 0, fAverageMagEnv, fHybAverage, fMagHyb = 0, fAverageMagHyb; int i; /* allocate buffers */ if ((pFBuffer = (float *) calloc(sizeMag, sizeof(float))) == NULL) return -1; /* get energy of excitation spectrum and envelope and normalize them */ for (i = 0; i < sizeMag; i++) { fMag += pFMagSpectrum[i]; fMagEnv += pFMagEnv[i]; } for (i = 0; i < sizeMag2; i++) fMagHyb += pFMagSpectrum2[i]; fAverageMag = MAX (fMag / sizeMag, ENV_THRESHOLD); fAverageMagEnv = MAX (fMagEnv / sizeMag, ENV_THRESHOLD); fAverageMagHyb = MAX (fMagHyb / sizeMag2, ENV_THRESHOLD); for (i = 0; i < sizeMag; i++) { pFMagSpectrum[i] /= fAverageMag; pFMagEnv[i] /= fAverageMagEnv; } /* compress the spectral envelope from one or other sound */ if (params.pCompressionEnv) if (params.sizeCompressionEnv == sizeMag1) CompExp (pFMagEnv, pFMagSpectrum, params.pCompressionEnv, sizeMag); else return -1; /* do the hybridation */ for (i = 0; i < sizeMag; i++) pFMagSpectrum[i] *= pFMagEnv[i]; /* get the new average magnitude */ fHybAverage = params.fMagBalance * fAverageMagHyb + (1 - params.fMagBalance) * fAverageMag; if (fHybAverage < .0001 || fHybAverage > 1000) fHybAverage = 1; /* scale the new spectrum by the new average magnitude */ for (i = 0; i < sizeMag; i++) pFMagSpectrum[i] *= fHybAverage; free (pFBuffer); return 1; } /* * function to hybridize the magnitude of two waveforms * * short *pIWaveform1 excitation waveform * int sizeWave1 size of excitation waveform * short *pIWaveform2 hybridization waveform * int sizeWave2 size of hybridization waveform * float *pFWaveform output waveform (hybridized) * HYB_PARAMS params control parameters * */ void HybridizeMag (short *pIWaveform1, int sizeWave1, short *pIWaveform2, int sizeWave2, float *pFWaveform, HYB_PARAMS params) { int i; double fMag1 = 0, fMag2 = 0, fScalar; for (i = 0; i < sizeWave1; i++) { pFWaveform[i] = pIWaveform1[i] * pFWindow1[i]; fMag1 += fabs (pFWaveform[i]); } fMag1 /= sizeWave1; for (i = 0; i < sizeWave2; i++) fMag2 += fabs (pIWaveform2[i] * pFWindow2[i]); fMag2 /= sizeWave2; fScalar = params.fMagBalance * fMag2 + (1- params.fMagBalance) * fMag1; for (i = 0; i < sizeWave1; i++) pFWaveform[i] = (pIWaveform1[i] / fMag1) * fScalar; } /* * function to hybridize two waveforms * * short *pIWaveform1 excitation waveform * int sizeWave1 size of excitation waveform * short *pIWaveform2 hybridization waveform * int sizeWave2 size of hybridization waveform * float *pFWaveform output waveform (hybridized) * HYB_PARAMS params control parameters * */ int Hybridize (short *pIWaveform1, int sizeWave1, short *pIWaveform2, int sizeWave2, float *pFWaveform, HYB_PARAMS params) { /* initialize static variables and arrays */ if (pFWindow1 == NULL) InitializeHybrid (sizeWave1, sizeWave2, params); if (!params.pCompressionEnv) { HybridizeMag (pIWaveform1, sizeWave1, pIWaveform2, sizeWave2, pFWaveform, params); return (1); } /* compute the two spectra */ QuickSpectrum (pIWaveform1, pFWindow1, sizeWave1, pFMagSpectrum1, pFPhaseSpectrum1, sizeFft1); QuickSpectrum (pIWaveform2, pFWindow2, sizeWave2, pFMagSpectrum2, pFPhaseSpectrum2, sizeFft2); /* approximate the second spectrum by line segments and obtain a magnitude * spectrum of size sizeMag1 */ SpectralApprox (pFMagSpectrum2, sizeMag2, sizeMag2, pFMagEnv, sizeMag1, params.nCoefficients); /* filter the smoothed spectrum */ FilterMagEnv (pFMagEnv, pFMagEnvFilt, sizeMag1); /* hybridize the two spectra */ MultiplySpectra (pFMagEnvFilt, pFMagSpectrum1, sizeMag1, pFMagSpectrum2, sizeMag2, params); /* perform the inverse FFT from the hybridized spectrum */ InverseQuickSpectrum (pFMagSpectrum1, pFPhaseSpectrum1, sizeFft1, pFWaveform, sizeWave1); return 1; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.