// File: Sleepwalking[P]world-octave/cheaptrick.cpp
// Function: (anonymous namespace)::SmoothingWithRecovery(double, int, int, ForwardRealFFT*, InverseRealFFT*, double*)
void SmoothingWithRecovery(double current_f0, int fs, int fft_size,
    ForwardRealFFT *forward_real_fft, InverseRealFFT *inverse_real_fft,
    double *spectral_envelope) {
  const double q1 = -0.09;  // Please see the reference in CheapTrick.
  double *smoothing_lifter = new double[fft_size];
  double *compensation_lifter = new double[fft_size];

  smoothing_lifter[0] = 1;
  compensation_lifter[0] = (1.0 - 2.0 * q1) + 2.0 * q1;
  double quefrency;
  for (int i = 1; i <= forward_real_fft->fft_size / 2; ++i) {
    quefrency = static_cast<double>(i) / fs;
    smoothing_lifter[i] = sin(world::kPi * current_f0 * quefrency) /
      (world::kPi * current_f0 * quefrency);
    compensation_lifter[i] = (1.0 - 2.0 * q1) + 2.0 * q1 *
      cos(2.0 * world::kPi * quefrency * current_f0);
  }

  for (int i = 0; i <= fft_size / 2; ++i)
    forward_real_fft->waveform[i] = log(forward_real_fft->waveform[i]);
  for (int i = 1; i < fft_size / 2; ++i)
    forward_real_fft->waveform[fft_size - i] = forward_real_fft->waveform[i];
  fft_execute(forward_real_fft->forward_fft);

  for (int i = 0; i <= fft_size / 2; ++i) {
    inverse_real_fft->spectrum[i][0] = forward_real_fft->spectrum[i][0] *
      smoothing_lifter[i] * compensation_lifter[i] / fft_size;
    inverse_real_fft->spectrum[i][1] = 0.0;
  }
  fft_execute(inverse_real_fft->inverse_fft);

  for (int i = 0; i <= fft_size / 2; ++i)
    spectral_envelope[i] = exp(inverse_real_fft->waveform[i]);

  delete[] smoothing_lifter;
  delete[] compensation_lifter;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
movsd %xmm0, -0x8(%rbp)
movl %edi, -0xc(%rbp)
movl %esi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movsd 0x1376e(%rip), %xmm0    # 0x1c3c8
movsd %xmm0, -0x30(%rbp)
movslq -0x10(%rbp), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x1030
movq %rax, -0x38(%rbp)
movslq -0x10(%rbp), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x1030
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
movsd 0x13353(%rip), %xmm0    # 0x1c010
movsd %xmm0, (%rax)
movq -0x40(%rbp), %rax
movsd 0x13343(%rip), %xmm0    # 0x1c010
movsd %xmm0, (%rax)
movl $0x1, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movl %eax, -0xf8(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0xf8(%rbp), %eax
cmpl %ecx, %eax
jg 0x8d96
cvtsi2sdl -0x4c(%rbp), %xmm0
cvtsi2sdl -0xc(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movsd 0x1339e(%rip), %xmm0    # 0x1c0b8
mulsd -0x8(%rbp), %xmm0
mulsd -0x48(%rbp), %xmm0
callq 0x1060
movsd 0x13387(%rip), %xmm1    # 0x1c0b8
mulsd -0x8(%rbp), %xmm1
mulsd -0x48(%rbp), %xmm1
divsd %xmm1, %xmm0
movq -0x38(%rbp), %rax
movslq -0x4c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movsd 0x1330c(%rip), %xmm0    # 0x1c060
mulsd -0x48(%rbp), %xmm0
mulsd -0x8(%rbp), %xmm0
callq 0x11a0
movsd 0x13665(%rip), %xmm1    # 0x1c3d0
mulsd %xmm1, %xmm0
movsd 0x13661(%rip), %xmm1    # 0x1c3d8
addsd %xmm1, %xmm0
movq -0x40(%rbp), %rax
movslq -0x4c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x8cd8
movl $0x0, -0x50(%rbp)
movl -0x50(%rbp), %eax
movl %eax, -0xfc(%rbp)
movl -0x10(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0xfc(%rbp), %eax
cmpl %ecx, %eax
jg 0x8def
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x50(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
callq 0x10a0
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x50(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x8d9d
movl $0x1, -0x54(%rbp)
movl -0x54(%rbp), %eax
movl %eax, -0x100(%rbp)
movl -0x10(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0x100(%rbp), %eax
cmpl %ecx, %eax
jge 0x8e48
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x54(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movl -0x10(%rbp), %ecx
subl -0x54(%rbp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x8df6
movq -0x18(%rbp), %rsi
addq $0x18, %rsi
leaq -0xa0(%rbp), %rdi
movl $0x48, %edx
callq 0x10b0
movq -0x60(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x40(%rax)
movups -0xa0(%rbp), %xmm0
movups -0x90(%rbp), %xmm1
movups -0x80(%rbp), %xmm2
movups -0x70(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0xd500
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
movl %eax, -0x104(%rbp)
movl -0x10(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0x104(%rbp), %eax
cmpl %ecx, %eax
jg 0x8f56
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0xa4(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd (%rax), %xmm0
movq -0x38(%rbp), %rax
movslq -0xa4(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm0
movq -0x40(%rbp), %rax
movslq -0xa4(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm0
cvtsi2sdl -0x10(%rbp), %xmm1
divsd %xmm1, %xmm0
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0xa4(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd %xmm0, (%rax)
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0xa4(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0x8(%rax)
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x8ea0
movq -0x20(%rbp), %rsi
addq $0x18, %rsi
leaq -0xf0(%rbp), %rdi
movl $0x48, %edx
callq 0x10b0
movq -0xb0(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x40(%rax)
movups -0xf0(%rbp), %xmm0
movups -0xe0(%rbp), %xmm1
movups -0xd0(%rbp), %xmm2
movups -0xc0(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0xd500
movl $0x0, -0xf4(%rbp)
movl -0xf4(%rbp), %eax
movl %eax, -0x108(%rbp)
movl -0x10(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0x108(%rbp), %eax
cmpl %ecx, %eax
jg 0x9014
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xf4(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
callq 0x1190
movq -0x28(%rbp), %rax
movslq -0xf4(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0xf4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf4(%rbp)
jmp 0x8fb7
movq -0x38(%rbp), %rax
movq %rax, -0x110(%rbp)
cmpq $0x0, %rax
je 0x9031
movq -0x110(%rbp), %rdi
callq 0x1110
movq -0x40(%rbp), %rax
movq %rax, -0x118(%rbp)
cmpq $0x0, %rax
je 0x904e
movq -0x118(%rbp), %rdi
callq 0x1110
addq $0x160, %rsp            # imm = 0x160
popq %rbp
retq
nopw (%rax,%rax)