jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
4.1KB

  1. /*
  2. * Copyright (c) 2023 Florian Walpen <dev@submerge.ch>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef SOSSO_CORRECTION_HPP
  17. #define SOSSO_CORRECTION_HPP
  18. #include <cstdint>
  19. namespace sosso {
  20. /*!
  21. * \brief Drift Correction
  22. *
  23. * Calculates drift correction for a channel, relative to another channel if
  24. * required. Usually the playback channel is corrected relative to the recording
  25. * channel, if in use.
  26. * It keeps track of the correction parameter (in frames), and also the
  27. * threshhold values which determine the amount of correction. Above these
  28. * threshholds, either single frame correction is applied for smaller drift,
  29. * or rigorous correction in case of large discrepance. The idea is that single
  30. * frame corrections typically go unnoticed, but it may not be sufficient to
  31. * correct something more grave like packet loss on a USB audio interface.
  32. */
  33. class Correction {
  34. public:
  35. //! Default constructor, threshhold values are set separately.
  36. Correction() = default;
  37. /*!
  38. * \brief Set thresholds for small drift correction.
  39. * \param drift_min Limit for negative drift balance.
  40. * \param drift_max Limit for positive drift balance.
  41. */
  42. void set_drift_limits(std::int64_t drift_min, std::int64_t drift_max) {
  43. if (drift_min < drift_max) {
  44. _drift_min = drift_min;
  45. _drift_max = drift_max;
  46. } else {
  47. _drift_min = drift_max;
  48. _drift_max = drift_min;
  49. }
  50. }
  51. /*!
  52. * \brief Set thresholds for rigorous large discrepance correction.
  53. * \param loss_min Limit for negative discrepance balance.
  54. * \param loss_max Limit for positive discrepance balance.
  55. */
  56. void set_loss_limits(std::int64_t loss_min, std::int64_t loss_max) {
  57. if (loss_min < loss_max) {
  58. _loss_min = loss_min;
  59. _loss_max = loss_max;
  60. } else {
  61. _loss_min = loss_max;
  62. _loss_max = loss_min;
  63. }
  64. }
  65. //! Get current correction parameter.
  66. std::int64_t correction() const { return _correction; }
  67. /*!
  68. * \brief Calculate a new correction parameter.
  69. * \param balance Balance of the corrected channel, compared to FrameClock.
  70. * \param target Balance of a master channel which acts as reference.
  71. * \return Current correction parameter.
  72. */
  73. std::int64_t correct(std::int64_t balance, std::int64_t target = 0) {
  74. std::int64_t corrected_balance = balance - target + _correction;
  75. if (corrected_balance > _loss_max) {
  76. // Large positive discrepance, rigorous correction.
  77. _correction -= corrected_balance - _loss_max;
  78. } else if (corrected_balance < _loss_min) {
  79. // Large negative discrepance, rigorous correction.
  80. _correction += _loss_min - corrected_balance;
  81. } else if (corrected_balance > _drift_max) {
  82. // Small positive drift, correct by a single frame.
  83. _correction -= 1;
  84. } else if (corrected_balance < _drift_min) {
  85. // Small negative drift, correct by a single frame.
  86. _correction += 1;
  87. }
  88. return _correction;
  89. }
  90. //! Clear the current correction parameter, but not the thresholds.
  91. void clear() { _correction = 0; }
  92. private:
  93. std::int64_t _loss_min = -128; // Negative threshold for rigorous correction.
  94. std::int64_t _loss_max = 128; // Positive threshold for rigorous correction.
  95. std::int64_t _drift_min = -64; // Negative threshold for drift correction.
  96. std::int64_t _drift_max = 64; // Positive threshold for drift correction.
  97. std::int64_t _correction = 0; // Correction parameter.
  98. };
  99. } // namespace sosso
  100. #endif // SOSSO_CORRECTION_HPP