当前位置: 首页 > 知识库问答 >
问题:

Arduino I2S正弦波

唐利
2023-03-14

我正在做一个项目,我想通过组合不同的正弦波来产生(简单的)声音。我使用的是arduino mkrZero,因为它内置了I2S接口,似乎有足够的处理能力来满足我的需求。

教程代码工作得很好,我从扬声器中得到了一个简单的方波音调。

现在我修改了生成正弦波的代码,有一个sin函数的查找表,使其足够快:

#include <I2S.h>

uint16_t isin16[] = {
 0, 1144, 2287, 3430, 4571, 5712, 6850, 7987, 9121, 10252, 11380,
 12505, 13625, 14742, 15854, 16962, 18064, 19161, 20251, 21336, 22414,
 23486, 24550, 25607, 26655, 27696, 28729, 29752, 30767, 31772, 32768,

 33753, 34728, 35693, 36647, 37589, 38521, 39440, 40347, 41243, 42125,
 42995, 43851, 44695, 45524, 46340, 47142, 47929, 48702, 49460, 50203,
 50930, 51642, 52339, 53019, 53683, 54331, 54962, 55577, 56174, 56755,

 57318, 57864, 58392, 58902, 59395, 59869, 60325, 60763, 61182, 61583,
 61965, 62327, 62671, 62996, 63302, 63588, 63855, 64103, 64331, 64539,
 64728, 64897, 65047, 65176, 65286, 65375, 65445, 65495, 65525, 65535,
 }; //0-90


const int sincount = 2;
int freqs[] = {50*360,51*360};
float amps[] ={0.1,0.1}; 

const int sampleRate = 8000; // sample rate in Hz

short sample = 0;
double t = 0;
double dt = 1.0/(1.0*sampleRate);

short LR[] = {0,0};

void setup() {
 Serial.begin(115200);
  // start I2S at the sample rate with 16-bits per sample
  if (!I2S.begin(I2S_PHILIPS_MODE, sampleRate, 16)) {
    while (1); // do nothing
  }
}

void loop() {
    sample = 0;
    for(int n= 0;n<sincount;n++)
    {
      sample += fSin(freqs[n]*t)*amps[n];
    }
    t += dt;
    LR[0] = sample;
    LR[1] = sample;

   I2S.write(LR[0]);//left channel
   I2S.write(LR[1]);//right channel
}


float fSin(long x)
{
 boolean pos = true;  // positive - keeps an eye on the sign.
 if (x < 0)
 {
   x = -x;
   pos = false;  
 }  
 if (x >= 360) x %= 360;  
 if (x > 180)
 {
   x -= 180;
   pos = !pos;
 }
 if (x > 90) x = 180 - x;
 if (pos) return isin16[x]; // = /65535.0
 return isin16[x];
}

如果我稍微修改一下代码,然后写

I2S.write(LR,2);

而不是

I2S.write(LR[0]);//left channel
I2S.write(LR[1]);//right channel

一切都破裂了,扬声器发出的声音听起来像是可怕的尖叫

I2s.write(val)//阻塞

I2s.write(buf,len)//不阻塞

参数

我想使用后一个版本的write函数,因为它不阻塞,我可以在播放前一个示例时生成新的示例。

关于如何使缓冲版本也能正确工作,有什么想法吗?

共有1个答案

钮安歌
2023-03-14

在代码中,您将LR声明为一个包含2个short的数组,在Arduino中,short的大小2个字节

当你写这个的时候:

I2S.write(LR[0]); //left channel
I2S.write(LR[1]); //right channel

给定

size_t I2SClass::write(uint8_t data)
{
    return write((int32_t)data);
}

size_t I2SClass::write(int sample)
{
    return write((int32_t)sample);
}
I2S.write(LR,2);

给定

size_t I2SClass::write(const uint8_t *buffer, size_t size)
{
    return write((const void*)buffer, size);
}

size_t I2SClass::write(const void *buffer, size_t size)
{
    ...
    written = _doubleBuffer.write(buffer, size);
    ...
}

您的数组包含2个短应强制转换为常量空*

从I2SDoubleBuffer中的这段代码可以看出:

size_t I2SDoubleBuffer::write(const void *buffer, size_t size) {
  size_t space = availableForWrite();

  if (size > space) {
    size = space;
  }

  if (size == 0) {
    return 0;
  }

  memcpy(&_buffer[_index][_length[_index]], buffer, size);

  _length[_index] += size;

  return size;
}
short LR[2] = { 0x89AB, 0xCDEF };
I2S.write(LR[0]); // actual left sample is 0x89AB
I2S.write(LR[1]); // actual right sample is 0xCDEF

I2S.write(LR, 2); // actual left sample is 0x89AB
                  // 0xCDEF is not copied
/* next loop iteration */
I2S.write(LR, 2); // actual right sample is 0x89AB 
                  // 0xCDEF is not copied

提议的解决办法:

尝试要求复制4字节:

I2S.write(LR, 4); // actual left sample is 0x89AB 
                  // actual right sample is 0xCDEF

 类似资料:
  • 我试图在y有最高值时显示x位置。在if语句中,我试图将y值与120进行比较,但它似乎从来都不是真的,所以它没有使用文本函数显示我的x位置。我也试着取整y值,但结果仍然不是我想要的。有人能帮我吗?

  • 我写了一个小函数,它给出了一个基于正弦波的值,当我在0到1之间放一个浮点数时。我用它在游戏中把东西弄得乱七八糟。 它很好用..但我想知道有没有一种数学方法来改变正弦波,这样我就可以让它在中间变得“陡峭”或“浅”?在下面的图中,蓝色曲线是正弦波,我想知道我是否可以让它更像绿线。

  • 用C/C++编写了一个三维正弦波发生器 代码:

  • 我如何建立一个方程来产生扫频正弦波。我是信号处理新手,在网上找不到太多关于生成扫描正弦波的话题。请告诉我一些我可以用来生成方程式并在代码中使用的源代码。非常感谢。

  • /编辑:很抱歉缺少一个问题。我需要知道如何使用正弦和余弦来画一个正方形或矩形,旋转中心在正方形或矩形的左上角。用角度的sin和cos得到坐标(x1,y1),然后用角度的sin和cos函数加上90度得到坐标(x2,y2)。使用计数器变量从左到右,从上到下绘制线条,随角度变化。

  • 本文向大家介绍使用HTML5绘制正弦波,包括了使用HTML5绘制正弦波的使用技巧和注意事项,需要的朋友参考一下 要使用HTML5绘制正弦波,请使用SVG。 使用以下近似正弦波的一半。我使用了三次贝塞尔近似。