////////////////////////////////
// NOTE(allen): Audio Generation Decibel Math

function F32
audgen_mul_from_decibel(F32 db){
  F32 div_db = db/10.f;
  F32 exp_db = pow_F32(10.f, div_db);
  return(exp_db);
}

////////////////////////////////
// NOTE(allen): Audio Generation Rate

function AUDGEN_Rate
audgen_rate(F32 sample_per_second){
  AUDGEN_Rate result = {0};
  result.sample_per_second = sample_per_second;
  result.delta_t = 1.f/sample_per_second;
  return(result);
}

function U64
audgen_i_from_t(F32 sample_per_second, F32 t){
  U64 result = (U64)(sample_per_second*t);
  return(result);
}

////////////////////////////////
// NOTE(allen): Audio Generation Basic Arithmetic

function void
audgen_add_in_place(F32 *dst, F32 *src, U64 sample_count){
  F32 *dptr = dst;
  F32 *sptr = src;
  F32 *opl  = src + sample_count;
  for (; sptr < opl; sptr += 1, dptr += 1){
    *dptr += *sptr;
  }
}

function void
audgen_scalar_mul_in_place(F32 scalar, F32 *dst, U64 sample_count){
  F32 *ptr = dst;
  F32 *opl = dst + sample_count;
  for (; ptr < opl; ptr += 1){
    *ptr = scalar*(*ptr);
  }
}

////////////////////////////////
// NOTE(allen): Audio Generation Filters

function void
audgen_low_pass_in_place(F32 alpha, F32 *dst, U64 sample_count){
  // TODO(allen): low-level optimization
  // low pass:  Y = (1 - alpha)*[-1]Y + alpha*X
  
  F32 *ptr = dst;
  F32 *opl = dst + sample_count;
  if (ptr < opl){
    F32 n_alpha = 1.f - alpha;
    F32 v = alpha*(*ptr);
    *ptr = v;
    for (; ptr < opl; ptr += 1){
      v = alpha*(*ptr) + n_alpha*v;
      *ptr = v;
    }
  }
}

function void
audgen_high_pass_in_place(F32 alpha, F32 *dst, U64 sample_count){
  // TODO(allen): low-level optimization
  // high pass: Y = alpha*([-1]Y + X - [-1]X)
  
  F32 *ptr = dst;
  F32 *opl = ptr + sample_count;
  if (ptr < opl){
    F32 d = 0;
    ptr += 1;
    for (; ptr < opl; ptr += 1){
      F32 x = *ptr;
      F32 y = alpha*(d + x);
      *ptr = y;
      d = y - x;
    }
  }
}

function F32
audgen_low_pass_alpha(F32 delta_t, F32 freq){
  F32 rc = 1.f/(tau_F32*freq);
  F32 alpha = delta_t/(delta_t + rc);
  return(alpha);
}

function F32
audgen_high_pass_alpha(F32 delta_t, F32 freq){
  F32 rc = 1.f/(tau_F32*freq);
  F32 alpha = rc/(rc + delta_t);
  return(alpha);
}
