⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmwavegen.c

📁 pxa270平台 windows mobile 5.2 wm9713 触摸屏+音频驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
};
#endif

/*
 * 10th partial
 *
 * y = sin(x) + sin(3x)/3 + sin(5x)/5 + sin(7x)/7 + sin(9x)/9 + sin(11x)/11
 *     + sin(13x)/13 + sin(15x)/15 + sin(17x)/17 + sin(19x)/19
 *
 * Nyquist divisor 38 => max frequency 1160Hz at 44.1kHz
 */
#if WM_SQUAREWAVE_PARTIAL10
static const short SquareWave10[] =
{
         0,  16514,  28196,  32767,  31449,  27802,  25342,  25571,
     27612,  29443,  29640,  28335,  26836,  26406,  27263,  28538,
     29115,  28574,  27475,  26799,  27094,  28040,  28785,  28695,
     27889,  27098,  27010,  27680,  28501,  28748,  28214,  27379,
     26984,  27379,  28214,  28748,  28501,  27680,  27010,  27098,
     27889,  28695,  28785,  28040,  27094,  26799,  27475,  28574,
     29115,  28538,  27263,  26406,  26836,  28335,  29640,  29443,
     27612,  25571,  25342,  27802,  31449,  32767,  28196,  16514,
         0, -16514, -28196, -32767, -31449, -27802, -25342, -25571,
    -27612, -29443, -29640, -28335, -26836, -26406, -27263, -28538,
    -29115, -28574, -27475, -26799, -27094, -28040, -28785, -28695,
    -27889, -27098, -27010, -27680, -28501, -28748, -28214, -27379,
    -26984, -27379, -28214, -28748, -28501, -27680, -27010, -27098,
    -27889, -28695, -28785, -28040, -27094, -26799, -27475, -28574,
    -29115, -28538, -27263, -26406, -26836, -28335, -29640, -29443,
    -27612, -25571, -25342, -27802, -31449, -32767, -28196, -16514,
         0
};
#endif

/*
 * Now an array to work from.
 * Note the entries in the array should be in decreasing order of
 * quality - i.e. should decrease in nyquistDivisor, and hence increase
 * in maximum frequency.  The last entry in the table should be the sine
 * wave - this is the table used by default if no other table is
 * appropriate.
 */
static const WaveTable SquareWavePartials[] =
{
#if WM_SQUAREWAVE_PARTIAL10
    {  38, SquareWave10 },
#endif
#if WM_SQUAREWAVE_PARTIAL9
    {  34, SquareWave9 },
#endif
#if WM_SQUAREWAVE_PARTIAL8
    {  30, SquareWave8 },
#endif
#if WM_SQUAREWAVE_PARTIAL7
    {  26, SquareWave7 },
#endif
#if WM_SQUAREWAVE_PARTIAL6
    {  22, SquareWave6 },
#endif
#if WM_SQUAREWAVE_PARTIAL5
    {  18, SquareWave5 },
#endif
#if WM_SQUAREWAVE_PARTIAL4
    {  14, SquareWave4 },
#endif
#if WM_SQUAREWAVE_PARTIAL3
    {  10, SquareWave3 },
#endif
#if WM_SQUAREWAVE_PARTIAL2
    {   6, SquareWave2 },
#endif
    /* We always have a sine wave */
    {   2, SquareWave1 }
};

static const WaveTable SineWave = { 2, SquareWave1 };

#define TABLE_SIZE          WM_ARRAY_COUNT( SquareWave1 )
#define NUM_TABLE_ENTRIES   (TABLE_SIZE - 1)

/*-----------------------------------------------------------------------------
 * Function:    WMGenerateSineWave
 *
 * Generates a sine wave of the given frequency.
 *
 * Parameters:
 *      buffer      buffer to receive samples
 *      nSamples    number of samples to generate (mono or stereo,
 *                  according to 'format')
 *      sampleRate  output sample rate (e.g. 44100)
 *      frequency   frequency to generate
 *      amplitude   peak amplitude to generate (0 to 32768)
 *      format      what the resulting data should look like.  One of the
 *                  WM_WAVEGEN_FORMAT constants.
 *      pRestart    pointer to a restart context - position after previous call.
 *                  Used to restart the wave where the previous call left off.
 *                  Updated to the start position for the next call.
 *                  Can be NULL - in this case will always start at the start of
 *                  the wave.
 *
 * Returns:     void
 *
 *---------------------------------------------------------------------------*/
void WMGenerateSineWave(WM_AUDIO_STEREO_SAMPLE   *buffer,
                        int               nSamples,
                        int               sampleRate,
                        unsigned short    frequency,
                        unsigned short    amplitude,
                        WM_WAVEGEN_FORMAT format,
                        WM_WAVEGEN_CTX    *pRestart
                        )
{
    /*
     * Call the common function to do the interpolation.
     */
    private_GenerateWave( buffer,
                          nSamples,
                          sampleRate,
                          frequency,
                          amplitude,
                          format,
                          pRestart,
                          &SineWave
                          );
}

/*-----------------------------------------------------------------------------
 * Function:    WMGenerateSquareWave
 *
 * Generates as close an approximation as possible to a square wave of the
 * given frequency.
 *
 * Parameters:
 *      buffer      buffer to receive samples
 *      nSamples    number of samples to generate (mono or stereo,
 *                  according to 'format')
 *      sampleRate  output sample rate (e.g. 44100)
 *      frequency   frequency to generate
 *      amplitude   peak amplitude to generate (0 to 32768)
 *      format      what the resulting data should look like.  One of the
 *                  WM_WAVEGEN_FORMAT constants.
 *      pRestart    pointer to a restart context - position after previous call.
 *                  Used to restart the wave where the previous call left off.
 *                  Updated to the start position for the next call.
 *                  Can be NULL - in this case will always start at the start of
 *                  the wave.
 *
 * Returns:     void
 *
 *---------------------------------------------------------------------------*/
void WMGenerateSquareWave(WM_AUDIO_STEREO_SAMPLE   *buffer,
                          int               nSamples,
                          int               sampleRate,
                          unsigned short    frequency,
                          unsigned short    amplitude,
                          WM_WAVEGEN_FORMAT format,
                          WM_WAVEGEN_CTX    *pRestart
                          )
{
    const WaveTable *pTable;
    unsigned int    table;
    int             maxFrequency;

    /*
     * Pick the best table possible.
     */
    for ( table = 0; table < WM_ARRAY_COUNT( SquareWavePartials ); table++ )
    {
        pTable = &SquareWavePartials[table];
        maxFrequency = sampleRate/pTable->nyquistDivisor;
        
        if ( maxFrequency > frequency )
        {
            break;
        }
    }

    /*
     * If we couldn't find a table, we will have been left with the
     * last table in the array - this should be the sine wave.
     */

    /*
     * Now call the common function to do the interpolation.
     */
    private_GenerateWave( buffer,
                          nSamples,
                          sampleRate,
                          frequency,
                          amplitude,
                          format,
                          pRestart,
                          pTable
                          );
}
    
/*-----------------------------------------------------------------------------
 * Function:    private_GenerateWave (static)
 *
 * Generates the wave data, given the table to work from.
 * Assumes 44.1kHz.
 *
 * Parameters:
 *      buffer      buffer to receive samples
 *      nSamples    number of samples to generate (mono or stereo,
 *                  according to 'format')
 *      sampleRate  output sample rate (e.g. 44100)
 *      frequency   frequency to generate
 *      amplitude   peak amplitude to generate (0 to 32768)
 *      format      what the resulting data should look like.  One of the
 *                  WM_WAVEGEN_FORMAT constants.
 *      pRestart    pointer to a restart context - position after previous call.
 *                  Used to restart the wave where the previous call left off.
 *                  Updated to the start position for the next call.
 *                  Can be NULL - in this case will always start at the start of
 *                  the wave.
 *      waveTable   wave table containing samples to use
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
void private_GenerateWave(WM_AUDIO_STEREO_SAMPLE   *buffer,
                          int               nSamples,
                          int               sampleRate,
                          unsigned short    frequency,
                          unsigned short    amplitude,
                          WM_WAVEGEN_FORMAT format,
                          WM_WAVEGEN_CTX    *pRestart,
                          const WaveTable   *waveTable
                          )
{
    div_t                   delta;
    div_t                   pos;
    int                     tableLength;
    int                     sample;
    const short             *waveData = waveTable->waveData;
    WM_AUDIO_SAMPLE  *sampleBuf = (WM_AUDIO_SAMPLE *) buffer;

    /*WM_TRACE( hDevice, ("WMWaveGen: Generating %dHz at %dHz", frequency, sampleRate) );*/
    
    /* 
     * Calculate the step size for the interpolation.
     * (frequency/sampleRate) * samplesPerCycle
     */
    tableLength = NUM_TABLE_ENTRIES;
    delta = div( tableLength * frequency, sampleRate );
   
    /* Set up pos */
    if ( pRestart )
    {
        pos.quot = pRestart->quot;
        pos.rem = pRestart->rem;
    }
    else
    {
        pos.quot = pos.rem = 0;
    }
        
    /* 
     * Now do the generation
     */
    for ( sample = 0; sample < nSamples; sample++ )
    {
        int     sampleVal;
        short   scaledVal;
        
        /*
         * If it's an integer (no remainder), we've landed directly on
         * a sample, so we can just use it without interpolation.
         */
        if ( 0 == pos.rem )
        {
            sampleVal = waveData[pos.quot];
        }
        else 
        {
            /*
             * Otherwise do a linear interpolation between the nearest
             * two samples - the value we want is the lower of the two
             * values plus the appropriate portion of the difference
             * between the upper and lower values.  Or, if v1 is the
             * lower value, v2 is the upper value, and r is the fraction
             * of the difference between the v1 and v2:
             * 
             *      v = v1 + r*(v2-v1)
             * 
             * Note r is the remainder portion of the current position,
             * divided by the sample rate.
             */
            int difference = waveData[pos.quot+1] - waveData[pos.quot];
            int sampleDelta = difference * pos.rem / sampleRate;
            sampleVal = waveData[pos.quot] + sampleDelta;
        }
        
        /* Now scale according to the amplitude */
        scaledVal = (short)((sampleVal*amplitude)/AMPLITUDE_DIVISOR);

        /* Save the sample to the buffer */
        switch ( format )
        {
            case WM_WAVEGEN_CONTIGUOUS:
                sampleBuf[sample] = scaledVal;
                break;
                
            case WM_WAVEGEN_CONTIGUOUS_WIDE:
            case WM_WAVEGEN_MONO:
                buffer[sample].sampleVal = 0;
                buffer[sample].mono = scaledVal;
                break;
                
            case WM_WAVEGEN_LEFT:
                buffer[sample].stereo.left = scaledVal;
                break;
                
            case WM_WAVEGEN_RIGHT:
                buffer[sample].stereo.right = scaledVal;
                break;
                
            case WM_WAVEGEN_STEREO:
                buffer[sample].stereo.left = scaledVal;
                buffer[sample].stereo.right = scaledVal;
                break;
        }
        
        /*
         * Increment our position in the wave table, wrapping around
         * if necessary.
         */
        pos.rem += delta.rem;
        if ( pos.rem >= sampleRate )
        {
            pos.quot++;
            pos.rem -= sampleRate;
        }
        pos.quot += delta.quot;

        if ( pos.quot >= tableLength)
        {
            pos.quot %= tableLength;
        }
    }
    
    /* Update the restart context for the next call. */
    if ( pRestart )
    {
        pRestart->quot = pos.quot;
        pRestart->rem = pos.rem;
    }
}

#endif /* WM_TESTING  || WM_AUDIO_WAVEGEN */

/*------------------------------ END OF FILE ---------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -