// File: bradleybossard[P]karplus-strong-in-c/karplus-strong.cpp
// Function: GenerateSamples(std::vector<float, std::allocator<float>>&, int)
void GenerateSamples (std::vector<float>& samples, int sampleRate) {
  std::vector<StringPluck> notes;

  enum ESongMode {
    e_twinkleTwinkle,
    e_strum
  };

  int timeBegin = 0;
  ESongMode mode = e_twinkleTwinkle;
  for (int index = 0, numSamples = samples.size(); index < numSamples; ++index) {
    switch (mode) {
      case e_twinkleTwinkle: {
         const int c_noteTime = sampleRate / 2;
         int time = index - timeBegin;
         // if we should start a new note
         if (time % c_noteTime == 0) {
           int note = time / c_noteTime;
           switch (note) {
             case 0:
             case 1: notes.push_back(StringPluck(CalcFrequency(3, 0), float(sampleRate), 0.996f));
                     break;
             case 2:
             case 3: notes.push_back(StringPluck(CalcFrequency(3, 7), float(sampleRate), 0.996f));
                     break;
             case 4:
             case 5: notes.push_back(StringPluck(CalcFrequency(3, 9), float(sampleRate), 0.996f));
                     break;
             case 6: notes.push_back(StringPluck(CalcFrequency(3, 7), float(sampleRate), 0.996f));
                     break;
             case 7: mode = e_strum;
                     timeBegin = index+1;
                     break;
           }
         }
         break;
       }
      case e_strum: {
                      const int c_noteTime = sampleRate / 32;
                      int time = index - timeBegin - sampleRate;
                      // if we should start a new note
                      if (time % c_noteTime == 0) {
                        int note = time / c_noteTime;
                        switch (note) {
                          case 0: notes.push_back(StringPluck(55.0f, float(sampleRate), 0.996f)); break;
                          case 1: notes.push_back(StringPluck(55.0f + 110.0f, float(sampleRate), 0.996f)); break;
                          case 2: notes.push_back(StringPluck(55.0f + 220.0f, float(sampleRate), 0.996f)); break;
                          case 3: notes.push_back(StringPluck(55.0f + 330.0f, float(sampleRate), 0.996f)); break;
                          case 4: mode = e_strum; timeBegin = index + 1; break;
                        }
                      }
                      break;
                    }
    }

    // generate and mix our samples from our notes
    samples[index] = 0;
    for (StringPluck& note : notes)
      samples[index] += note.GenerateSample();

    // to keep from clipping
    samples[index] *= 0.5f;
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1f0, %rsp            # imm = 0x1F0
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x1980
movl $0x0, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movq -0x8(%rbp), %rdi
callq 0x19a0
movl %eax, -0x38(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x38(%rbp), %eax
jge 0x1830
movl -0x30(%rbp), %eax
movl %eax, -0x1cc(%rbp)
testl %eax, %eax
je 0x130b
jmp 0x12f7
movl -0x1cc(%rbp), %eax
subl $0x1, %eax
je 0x153d
jmp 0x1753
movl -0xc(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x3c(%rbp)
movl -0x34(%rbp), %eax
subl -0x2c(%rbp), %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
cltd
idivl -0x3c(%rbp)
cmpl $0x0, %edx
jne 0x1538
movl -0x40(%rbp), %eax
movl -0x3c(%rbp), %ecx
cltd
idivl %ecx
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
movq %rax, -0x1d8(%rbp)
subq $0x7, %rax
ja 0x1536
movq -0x1d8(%rbp), %rax
leaq 0x3d08(%rip), %rcx      # 0x5068
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movss 0x3ccb(%rip), %xmm0     # 0x503c
xorps %xmm1, %xmm1
callq 0x1230
cvtsi2ssl -0xc(%rbp), %xmm1
leaq -0x70(%rbp), %rdi
movss 0x3ca2(%rip), %xmm2     # 0x502c
callq 0x19f0
jmp 0x1391
leaq -0x28(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x19c0
jmp 0x13a0
leaq -0x70(%rbp), %rdi
callq 0x1af0
jmp 0x1536
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0x1842
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x1af0
jmp 0x1842
movss 0x3c5b(%rip), %xmm0     # 0x503c
movss 0x3c57(%rip), %xmm1     # 0x5040
callq 0x1230
cvtsi2ssl -0xc(%rbp), %xmm1
leaq -0xa8(%rbp), %rdi
movss 0x3c2a(%rip), %xmm2     # 0x502c
callq 0x19f0
jmp 0x1409
leaq -0x28(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x19c0
jmp 0x141b
leaq -0xa8(%rbp), %rdi
callq 0x1af0
jmp 0x1536
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x1af0
jmp 0x1842
movss 0x3beb(%rip), %xmm0     # 0x503c
movss 0x3beb(%rip), %xmm1     # 0x5044
callq 0x1230
cvtsi2ssl -0xc(%rbp), %xmm1
leaq -0xd0(%rbp), %rdi
movss 0x3bba(%rip), %xmm2     # 0x502c
callq 0x19f0
jmp 0x1479
leaq -0x28(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x19c0
jmp 0x148b
leaq -0xd0(%rbp), %rdi
callq 0x1af0
jmp 0x1536
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0x1af0
jmp 0x1842
movss 0x3b7b(%rip), %xmm0     # 0x503c
movss 0x3b77(%rip), %xmm1     # 0x5040
callq 0x1230
cvtsi2ssl -0xc(%rbp), %xmm1
leaq -0xf8(%rbp), %rdi
movss 0x3b4a(%rip), %xmm2     # 0x502c
callq 0x19f0
jmp 0x14e9
leaq -0x28(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x19c0
jmp 0x14fb
leaq -0xf8(%rbp), %rdi
callq 0x1af0
jmp 0x1536
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x1af0
jmp 0x1842
movl $0x1, -0x30(%rbp)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x1538
jmp 0x1753
movl -0xc(%rbp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl %eax, -0xfc(%rbp)
movl -0x34(%rbp), %eax
subl -0x2c(%rbp), %eax
subl -0xc(%rbp), %eax
movl %eax, -0x100(%rbp)
movl -0x100(%rbp), %eax
cltd
idivl -0xfc(%rbp)
cmpl $0x0, %edx
jne 0x1751
movl -0x100(%rbp), %eax
movl -0xfc(%rbp), %ecx
cltd
idivl %ecx
movl %eax, -0x104(%rbp)
movl -0x104(%rbp), %eax
movq %rax, -0x1e0(%rbp)
subq $0x4, %rax
ja 0x174f
movq -0x1e0(%rbp), %rax
leaq 0x3aa7(%rip), %rcx      # 0x5054
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cvtsi2ssl -0xc(%rbp), %xmm1
leaq -0x130(%rbp), %rdi
movss 0x3a6e(%rip), %xmm0     # 0x5038
movss 0x3a5a(%rip), %xmm2     # 0x502c
callq 0x19f0
jmp 0x15d9
leaq -0x28(%rbp), %rdi
leaq -0x130(%rbp), %rsi
callq 0x19c0
jmp 0x15eb
leaq -0x130(%rbp), %rdi
callq 0x1af0
jmp 0x174f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x130(%rbp), %rdi
callq 0x1af0
jmp 0x1842
cvtsi2ssl -0xc(%rbp), %xmm1
leaq -0x158(%rbp), %rdi
movss 0x3a07(%rip), %xmm0     # 0x5034
movss 0x39f7(%rip), %xmm2     # 0x502c
callq 0x19f0
jmp 0x163c
leaq -0x28(%rbp), %rdi
leaq -0x158(%rbp), %rsi
callq 0x19c0
jmp 0x164e
leaq -0x158(%rbp), %rdi
callq 0x1af0
jmp 0x174f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x1af0
jmp 0x1842
cvtsi2ssl -0xc(%rbp), %xmm1
leaq -0x180(%rbp), %rdi
movss 0x39a0(%rip), %xmm0     # 0x5030
movss 0x3994(%rip), %xmm2     # 0x502c
callq 0x19f0
jmp 0x169f
leaq -0x28(%rbp), %rdi
leaq -0x180(%rbp), %rsi
callq 0x19c0
jmp 0x16b1
leaq -0x180(%rbp), %rdi
callq 0x1af0
jmp 0x174f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x180(%rbp), %rdi
callq 0x1af0
jmp 0x1842
cvtsi2ssl -0xc(%rbp), %xmm1
leaq -0x1a8(%rbp), %rdi
movss 0x3935(%rip), %xmm0     # 0x5028
movss 0x3931(%rip), %xmm2     # 0x502c
callq 0x19f0
jmp 0x1702
leaq -0x28(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x19c0
jmp 0x1714
leaq -0x1a8(%rbp), %rdi
callq 0x1af0
jmp 0x174f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x1a8(%rbp), %rdi
callq 0x1af0
jmp 0x1842
movl $0x1, -0x30(%rbp)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x1751
jmp 0x1753
movq -0x8(%rbp), %rdi
movslq -0x34(%rbp), %rsi
callq 0x1b10
xorps %xmm0, %xmm0
movss %xmm0, (%rax)
leaq -0x28(%rbp), %rax
movq %rax, -0x1b0(%rbp)
movq -0x1b0(%rbp), %rdi
callq 0x1b30
movq %rax, -0x1b8(%rbp)
movq -0x1b0(%rbp), %rdi
callq 0x1b60
movq %rax, -0x1c0(%rbp)
leaq -0x1b8(%rbp), %rdi
leaq -0x1c0(%rbp), %rsi
callq 0x1b90
testb $0x1, %al
jne 0x17b1
jmp 0x1805
leaq -0x1b8(%rbp), %rdi
callq 0x1bd0
movq %rax, -0x1c8(%rbp)
movq -0x1c8(%rbp), %rdi
callq 0x1bf0
movss %xmm0, -0x1e4(%rbp)
jmp 0x17da
movq -0x8(%rbp), %rdi
movslq -0x34(%rbp), %rsi
callq 0x1b10
movss -0x1e4(%rbp), %xmm0
addss (%rax), %xmm0
movss %xmm0, (%rax)
leaq -0x1b8(%rbp), %rdi
callq 0x1cd0
jmp 0x1798
movq -0x8(%rbp), %rdi
movslq -0x34(%rbp), %rsi
callq 0x1b10
movss 0x382e(%rip), %xmm0     # 0x5048
mulss (%rax), %xmm0
movss %xmm0, (%rax)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x12dc
leaq -0x28(%rbp), %rdi
callq 0x1cf0
addq $0x1f0, %rsp            # imm = 0x1F0
popq %rbp
retq
leaq -0x28(%rbp), %rdi
callq 0x1cf0
movq -0x78(%rbp), %rdi
callq 0x1110
nopw %cs:(%rax,%rax)