示例#1
0
文件: cepstrum.c 项目: libsms/libsms
/*! \brief Discrete Cepstrum Transform
 *
 * method for computing cepstrum aenalysis from a discrete
 * set of partial peaks (frequency and amplitude)
 *
 * This implementation is owed to the help of Jordi Janer (thanks!) from the MTG,
 * along with the following paper:
 * "Regularization Techniques for Discrete Cepstrum Estimation"
 * Olivier Cappe and Eric Moulines, IEEE Signal Processing Letters, Vol. 3
 * No.4, April 1996
 *
 * \todo add anchor point add at frequency = 0 with the same magnitude as the first
 * peak in pMag.  This does not change the size of the cepstrum, only helps to smoothen it
 * at the very beginning.
 *
 * \param sizeCepstrum order+1 of the discrete cepstrum
 * \param pCepstrum pointer to output array of cepstrum coefficients
 * \param sizeFreq number of partials peaks (the size of pFreq should be the same as pMag
 * \param pFreq pointer to partial peak frequencies (hertz)
 * \param pMag pointer to partial peak magnitudes (linear)
 * \param fLambda regularization factor
 * \param iMaxFreq maximum frequency of cepstrum
 */
void sms_dCepstrum( int sizeCepstrum, sfloat *pCepstrum, int sizeFreq, sfloat *pFreq, sfloat *pMag, 
                    sfloat fLambda, int iMaxFreq)
{
        int i, k;
        sfloat factor;
        sfloat fNorm = PI  / (float)iMaxFreq; /* value to normalize frequencies to 0:0.5 */
        //static sizeCepstrumStatic
        static CepstrumMatrices m;
        //printf("nPoints: %d, nCoeff: %d \n", m.nPoints, m.nCoeff);
        if(m.nPoints != sizeCepstrum || m.nCoeff != sizeFreq)
                AllocateDCepstrum(sizeFreq, sizeCepstrum, &m);
        int s; /* signum: "(-1)^n, where n is the number of interchanges in the permutation." */
        /* compute matrix M (eq. 4)*/
	for (i=0; i<sizeFreq; i++)
	{
                gsl_matrix_set (m.pM, i, 0, 1.); // first colum is all 1
		for (k=1; k <sizeCepstrum; k++)
                        gsl_matrix_set (m.pM, i, k , 2.*sms_sine(PI_2 + fNorm * k * pFreq[i]) );
	}

        /* compute transpose of M */
        gsl_matrix_transpose_memcpy (m.pMt, m.pM);
                               
        /* compute R diagonal matrix (for eq. 7)*/
        factor = COEF * (fLambda / (1.-fLambda)); /* \todo why is this divided like this again? */
	for (k=0; k<sizeCepstrum; k++)
                gsl_matrix_set(m.pR, k, k, factor * powf((sfloat) k,2.));

        /* MtM = Mt * M, later will add R */
        gsl_blas_dgemm  (CblasNoTrans, CblasNoTrans, 1., m.pMt, m.pM, 0.0, m.pMtMR);
        /* add R to make MtMR */
        gsl_matrix_add (m.pMtMR, m.pR);

        /* set pMag in X and multiply with Mt to get pMtXk */
        for(k = 0; k <sizeFreq; k++)
                gsl_vector_set(m.pXk, k, log(pMag[k]));
        gsl_blas_dgemv (CblasNoTrans, 1., m.pMt, m.pXk, 0., m.pMtXk);

        /* solve x (the cepstrum) in Ax = b, where A=MtMR and b=pMtXk */ 

        /* ==== the Cholesky Decomposition way ==== */
        /* MtM is 'symmetric and positive definite?' */
        //gsl_linalg_cholesky_decomp (m.pMtMR);
        //gsl_linalg_cholesky_solve (m.pMtMR, m.pMtXk, m.pC);

        /* ==== the LU decomposition way ==== */
        gsl_linalg_LU_decomp (m.pMtMR, m.pPerm, &s);
        gsl_linalg_LU_solve (m.pMtMR, m.pPerm, m.pMtXk, m.pC);

        
        /* copy pC to pCepstrum */
        for(i = 0; i  < sizeCepstrum; i++)
                pCepstrum[i] = gsl_vector_get (m.pC, i);
}
示例#2
0
/*! \brief generate a sinusoid given two frames, current and last
 * 
 * \param fFreq          current frequency 
 * \param fMag                 current magnitude  
 * \param pLastFrame      stucture with values from last frame 
 * \param pFBuffer           pointer to output waveform 
 * \param sizeBuffer     size of the synthesis buffer 
 * \param iTrack               current track 
 */
static void SineSynth(sfloat fFreq, sfloat fMag, SMS_Data *pLastFrame,
                      sfloat *pFBuffer, int sizeBuffer, int iTrack)
{
    sfloat  fMagIncr, fInstMag, fFreqIncr, fInstPhase, fInstFreq;
    int i;

    /* if no mag in last frame copy freq from current */
    if(pLastFrame->pFSinAmp[iTrack] <= 0)
    {
        pLastFrame->pFSinFreq[iTrack] = fFreq;
        pLastFrame->pFSinPha[iTrack] = TWO_PI * sms_random();
    }
    /* and the other way */
    else if(fMag <= 0)
        fFreq = pLastFrame->pFSinFreq[iTrack];

    /* calculate the instantaneous amplitude */
    fMagIncr = (fMag - pLastFrame->pFSinAmp[iTrack]) / sizeBuffer;
    fInstMag = pLastFrame->pFSinAmp[iTrack];
    /* calculate instantaneous frequency */
    fFreqIncr = (fFreq - pLastFrame->pFSinFreq[iTrack]) / sizeBuffer;
    fInstFreq = pLastFrame->pFSinFreq[iTrack];
    fInstPhase = pLastFrame->pFSinPha[iTrack];

    /* generate all the samples */    
    for(i = 0; i < sizeBuffer; i++)
    {
        fInstMag += fMagIncr;
        fInstFreq += fFreqIncr;
        fInstPhase += fInstFreq;
        pFBuffer[i] += sms_dBToMag(fInstMag) * sms_sine(fInstPhase);
    }

    /* save current values into last values */
    pLastFrame->pFSinFreq[iTrack] = fFreq;
    pLastFrame->pFSinAmp[iTrack] = fMag;
    pLastFrame->pFSinPha[iTrack] = fInstPhase - floor(fInstPhase / TWO_PI) * TWO_PI;
}