How to look up sine of different frequencies from a fixed sized lookup table?

前端 未结 5 2046
孤城傲影
孤城傲影 2021-02-08 11:06

I am sampling a sine wave at 48 kHz, the frequency range of my sine wave can vary from 0 to 20000 Hz with a step of about 100 Hz. I am using a lookup table approach. So I genera

5条回答
  •  情话喂你
    2021-02-08 11:34

    You're on the right track - first we need to generate a sine wave LUT:

    const int Fs = 48000;       // sample rate (Hz)
    const int LUT_SIZE = 1024;  // lookup table size
    
    int16_t LUT[LUT_SIZE];      // our sine wave LUT
    
    for (int i = 0; i < LUT_SIZE; ++i)
    {
        LUT[i] = (int16_t)roundf(SHRT_MAX * sinf(2.0f * M_PI * (float)i / LUT_SIZE));
    }                           // fill LUT with 16 bit sine wave sample values
    

    Note that we only need to generate this LUT once, e.g. during initialisation.

    Now that we have a sine wave LUT we can use it to generate any frequency we wish to using a phase accumulator:

    const int BUFF_SIZE = 4096;  // size of output buffer (samples)
    int16_t buff[BUFF_SIZE];     // output buffer
    
    const int f = 1000;          // frequency we want to generate (Hz)
    
    const float delta_phi = (float) f / Fs * LUT_SIZE;
                                 // phase increment
    
    float phase = 0.0f;          // phase accumulator
    
    // generate buffer of output
    for (int i = 0; i < BUFF_SIZE; ++i)
    {
        int phase_i = (int)phase;        // get integer part of our phase
        buff[i] = LUT[phase_i];          // get sample value from LUT
        phase += delta_phi;              // increment phase
        if (phase >= (float)LUT_SIZE)    // handle wraparound
            phase -= (float)LUT_SIZE;
    }
    

    Note: for higher quality output you can use linear interpolation between the LUT values at phase_i and phase_i + 1, but the above approach is good enough for most audio applications.

提交回复
热议问题