QOATypes.cpp 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /*
  2. * Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "QOATypes.h"
  7. #include <AK/Endian.h>
  8. #include <AK/Stream.h>
  9. namespace Audio::QOA {
  10. ErrorOr<FrameHeader> FrameHeader::read_from_stream(Stream& stream)
  11. {
  12. FrameHeader header;
  13. header.num_channels = TRY(stream.read_value<u8>());
  14. u8 sample_rate[3];
  15. // Enforce the order of the reads here, since the order of expression evaluations further down is implementation-defined.
  16. sample_rate[0] = TRY(stream.read_value<u8>());
  17. sample_rate[1] = TRY(stream.read_value<u8>());
  18. sample_rate[2] = TRY(stream.read_value<u8>());
  19. header.sample_rate = (sample_rate[0] << 16) | (sample_rate[1] << 8) | sample_rate[2];
  20. header.sample_count = TRY(stream.read_value<BigEndian<u16>>());
  21. header.frame_size = TRY(stream.read_value<BigEndian<u16>>());
  22. return header;
  23. }
  24. LMSState::LMSState(u64 history_packed, u64 weights_packed)
  25. {
  26. for (size_t i = 0; i < lms_history; ++i) {
  27. // The casts ensure proper sign extension.
  28. history[i] = static_cast<i16>(history_packed >> 48);
  29. history_packed <<= 16;
  30. weights[i] = static_cast<i16>(weights_packed >> 48);
  31. weights_packed <<= 16;
  32. }
  33. }
  34. i32 LMSState::predict() const
  35. {
  36. i32 prediction = 0;
  37. for (size_t i = 0; i < lms_history; ++i)
  38. prediction += history[i] * weights[i];
  39. return prediction >> 13;
  40. }
  41. void LMSState::update(i32 sample, i32 residual)
  42. {
  43. i32 delta = residual >> 4;
  44. for (size_t i = 0; i < lms_history; ++i)
  45. weights[i] += history[i] < 0 ? -delta : delta;
  46. for (size_t i = 0; i < lms_history - 1; ++i)
  47. history[i] = history[i + 1];
  48. history[lms_history - 1] = sample;
  49. }
  50. }