///|
pub fn spectral_centroid(
  magnitudes : ArrayView[Double],
  sample_rate : Double,
) -> Double raise SpectrumError {
  let half = positive_spectrum_length(magnitudes)
  if sample_rate <= 0.0 {
    raise InvalidArgument(message="sample_rate must be positive")
  }
  let mut weighted = 0.0
  let mut total = 0.0
  for i in 0.. Double raise SpectrumError {
  let centroid = spectral_centroid(magnitudes, sample_rate)
  let half = positive_spectrum_length(magnitudes)
  let mut weighted = 0.0
  let mut total = 0.0
  for i in 0.. Double raise SpectrumError {
  if magnitudes.length() == 0 {
    raise EmptySignal
  }
  let half = magnitudes.length()
  let mut logarithmic_sum = 0.0
  let mut arithmetic_sum = 0.0
  for i in 0.. Double raise SpectrumError {
  if magnitudes.length() == 0 {
    raise EmptySignal
  }
  let half = magnitudes.length()
  let mut total = 0.0
  for i in 0.. 0.0 {
      entropy = entropy - probability * @math.log2(probability)
    }
  }
  entropy
}

///|
pub fn spectral_rolloff(
  magnitudes : ArrayView[Double],
  sample_rate : Double,
  ratio? : Double = 0.85,
) -> Double raise SpectrumError {
  let half = positive_spectrum_length(magnitudes)
  if sample_rate <= 0.0 {
    raise InvalidArgument(message="sample_rate must be positive")
  }
  if ratio <= 0.0 || ratio > 1.0 {
    raise InvalidArgument(message="ratio must be in (0, 1]")
  }
  let mut total = 0.0
  for i in 0..= target {
      return Double::from_int(i) *
        sample_rate /
        Double::from_int(magnitudes.length())
    }
  }
  sample_rate / 2.0
}

///|
fn positive_spectrum_length(
  magnitudes : ArrayView[Double],
) -> Int raise SpectrumError {
  if magnitudes.length() == 0 {
    raise EmptySignal
  }
  magnitudes.length() / 2 + 1
}