如何从固定大小的查找表中查找不同频率的正弦? [英] How to look up sine of different frequencies from a fixed sized lookup table?

查看:227
本文介绍了如何从固定大小的查找表中查找不同频率的正弦?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在以48 KHz采样正弦波,我的正弦波的频率范围可以在0到20000 Hz之间变化,步长约为100 Hz。我正在使用查找表方法。所以我为4096个不同的阶段生成4096个正弦波的样本。我认为这样做的一般思路是增加步长,并为不同的频率使用不同的步长。所以我做了以下(伪代码)。但是我不知道步长如何与我想生成正弦波样本的频率有关?例如,如果我的频率是15000赫兹,我必须穿越的步长是多少?我的样品量(4096)是否太低?

  // Pseudocode 
uint16_t audio_sample [4096] = {...}
NSTEP = freq; //?步长如何与这里的频率有关

for(int i = 0; i< 4096; i = i + NSTEP)
{
sine_f(i)= audio_sample [i];
}

提前感谢

解决方案

你在正确的轨道上 - 首先我们需要生成一个正弦波LUT:

  const int Fs = 48000; // sample rate(Hz)
const int LUT_SIZE = 1024; //查找表大小

int16_t LUT [LUT_SIZE]; //我们的正弦波LUT

(int i = 0; i< LUT_SIZE; ++ i)
{
LUT [i] =(int16_t)roundf(SHRT_MAX * sinf(2.0f * M_PI *(float)i / LUT_SIZE));
} //使用16位正弦波样本值填充LUT

请注意,我们只需要生成该LUT一次,例如在初始化期间。



现在我们有一个正弦波LUT,我们可以使用它来生成我们希望使用相位累加器的任何频率

  const int BUFF_SIZE = 4096; //输出缓冲区大小(样本)
int16_t buff [BUFF_SIZE]; //输出缓冲区

const int f = 1000; //我们要生成的频率(Hz)

const float delta_phi =(float)f / Fs * LUT_SIZE;
//相位增量

float phase = 0.0f; //阶段累加器

//生成
的缓冲区(int i = 0; i< BUFF_SIZE; ++ i)
{
int phase_i = (INT)相; //获取我们阶段的整数部分
buff [i] = LUT [phase_i]; //从LUT获取样本值
phase + = delta_phi; //增量阶段
if(phase> =(float)LUT_SIZE)// handle wraparound
phase - =(float)LUT_SIZE;
}

注意:对于更高质量的输出,您可以使用LUT值之间的线性插值 phase_i phase_i + 1 ,但上述方法对于大多数音频应用来说都是足够好的。


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 generate 4096 samples for a sine wave for 4096 different phases. I think the general idea behind this to increment the step size and use different step sizes for different frequncy. So I do the following (pseudo code). But I am not sure how the step size is going to be related to the frequency I want to generate the samples of the sine wave of? For example if my frequency is 15000 Hz what would be the step size that I have to traverse? Is my sample size (4096) too low for this?

 // Pseudocode
 uint16_t audio_sample[4096] = {...};
 NSTEP = freq; //???How is the step size going to be related to the freq here

 for(int i = 0; i < 4096; i = i+NSTEP)
 {
  sine_f(i) = audio_sample[i];
 }

Thanks in advance.

解决方案

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.

这篇关于如何从固定大小的查找表中查找不同频率的正弦?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆