title: Arduino I2S sine wave
body: <p>I'm working on a project where I want to generate (simple) sound by combining different sine waves. I'm using an arduino mkrZero, as it has I2S interface built in and it seems to have enough processing power for what I want.</p>
  
  <p>I have wired my system exactly like in the tutorial for arduino I2S simpleTone:<a href="https://i.stack.imgur.com/LLZWh.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/LLZWh.png" alt="enter image description here"></a></p>
  
  <p>And the <a href="https://www.arduino.cc/en/Tutorial/I2SSimpleTone" rel="nofollow noreferrer">tutorial</a> code works just fine, and I get a simple square wave tone from the speaker.</p>
  
  <p>Now I have modified the code to generate sine wave, there is a lookup table for the sin function to make it fast enough:</p>
  
  <pre><code>#include &lt;I2S.h&gt;
  
  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&lt;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 &lt; 0)
   {
     x = -x;
     pos = false;  
   }  
   if (x &gt;= 360) x %= 360;  
   if (x &gt; 180)
   {
     x -= 180;
     pos = !pos;
   }
   if (x &gt; 90) x = 180 - x;
   if (pos) return isin16[x]; // = /65535.0
   return isin16[x];
  }
  </code></pre>
  
  <p>This also works fine.</p>
  
  <p><strong>BUT!</strong></p>
  
  <p>If I change the code a bit and I write</p>
  
  <pre><code>I2S.write(LR,2);
  </code></pre>
  
  <p>instead of</p>
  
  <pre><code>I2S.write(LR[0]);//left channel
  I2S.write(LR[1]);//right channel
  </code></pre>
  
  <p>Everything just breaks, the sound from the speaker sounds like a <a href="https://www.youtube.com/watch?v=_Eos0wg7QJU" rel="nofollow noreferrer">horrible scream</a></p>
  
  <p>From the I2S library reference:</p>
  
  <blockquote>
    <p><strong>Description</strong></p>
    
    <p>Writes binary data to the I2S interface. This data is sent as a sample
    or series of samples. </p>
    
    <p><strong>Syntax</strong></p>
    
    <p><code>I2S.write(val)</code> // blocking </p>
    
    <p><code>I2S.write(buf, len)</code> // not blocking</p>
    
    <p><strong>Parameters</strong></p>
    
    <p>val: a value to send as a single sample</p>
    
    <p>buf: an array to send as a series of samples</p>
    
    <p>len: the length of the buffer </p>
    
    <p><strong>Returns</strong></p>
    
    <p>byte write() will return the number of bytes written, though reading
    that number is optional.</p>
  </blockquote>
  
  <p>I'd like to use the latter version of the write function, because it is not blocking and I can generate new samples while the previous ones are playing.</p>
  
  <p>Any ideas on how to make the buffered version work correctly as well?</p>