title: Drawing the WaveForm effect of Siri
body: <p>I have been trying to understand how to draw Siri's wave effect in iOS and came across <a href="https://github.com/alankarmisra/SwiftSiriWaveformView" rel="noreferrer">this</a> great repository. 
  The final result looks like this : </p>
  
  <p><a href="https://i.stack.imgur.com/PsT2y.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/PsT2y.gif" alt="enter image description here"></a></p>
  
  <p>However I am having difficulty understanding what is going on with the code that generates the waves.I can generate a single static sine wave but this, I don't quite seem to understand. </p>
  
  <p>Particularly when we calculate the value of y , why does it have to be : </p>
  
  <p><code>let y = scaling * maxAmplitude * normedAmplitude * 
  sin(CGFloat(2 * M_PI) * self.frequency * (x / self.bounds.width)  + self.phase) + self.bounds.height/2.0</code></p>
  
  <p>Source Code:</p>
  
  <pre><code> //MARK : Properties 
  
  
  let density : CGFloat =        1
  let frequency : CGFloat =      1.5
  var phase :CGFloat =           0
  var phaseShift:CGFloat =      -0.15
  var numberOfWaves:Int =        6
  var primaryLineWidth:CGFloat = 1.5
  var idleAmplitude:CGFloat =    0.01
  var waveColor:UIColor =        UIColor.white
  var amplitude:CGFloat =        1.0 {
      didSet {
          amplitude = max(amplitude, self.idleAmplitude)
          self.setNeedsDisplay()
      }
  }
  </code></pre>
  
  <p>Method</p>
  
  <pre><code>  override open func draw(_ rect: CGRect) {
      // Convenience function to draw the wave
      func drawWave(_ index:Int, maxAmplitude:CGFloat, normedAmplitude:CGFloat) {
          let path = UIBezierPath()
          let mid = self.bounds.width/2.0
  
          path.lineWidth = index == 0 ? self.primaryLineWidth : self.secondaryLineWidth
  
          for x in Swift.stride(from:0, to:self.bounds.width + self.density, by:self.density) {
              // Parabolic scaling
              let scaling = -pow(1 / mid * (x - mid), 2) + 1
  
    // The confusing part /////////////////////////////////////////
              let y = scaling * maxAmplitude * normedAmplitude *
       sin(CGFloat(2 * M_PI) * self.frequency * (x / self.bounds.width) + self.phase)  
  + self.bounds.height/2.0
  
    //////////////////////////////////////////////////////////////////
              if x == 0 {
                  path.move(to: CGPoint(x:x, y:y))
              } else {
                  path.addLine(to: CGPoint(x:x, y:y))
              }
          }
  
          path.stroke()
      }
  
      let context = UIGraphicsGetCurrentContext()
      context?.setAllowsAntialiasing(true)
  
      self.backgroundColor?.set()
      context?.fill(rect)
  
      let halfHeight = self.bounds.height / 2.0
      let maxAmplitude = halfHeight - self.primaryLineWidth
  
      for i in 0 ..&lt; self.numberOfWaves {
          let progress = 1.0 - CGFloat(i) / CGFloat(self.numberOfWaves)
          let normedAmplitude = (1.5 * progress - 0.8) * self.amplitude
          let multiplier = min(1.0, (progress/3.0*2.0) + (1.0/3.0))
          self.waveColor.withAlphaComponent(multiplier * self.waveColor.cgColor.alpha).set()
          drawWave(i, maxAmplitude: maxAmplitude, normedAmplitude: normedAmplitude)
      }
      self.phase += self.phaseShift
  }
  </code></pre>
  
  <p>Both the for loops seem very mathematical , I have no clue what's going on in there. 
  Thanks in advance.</p>