MultiChannel.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Concepts.h>
  8. #include <AK/FixedArray.h>
  9. #include <LibAudio/Sample.h>
  10. namespace Audio {
  11. // Downmixes any number of channels to stereo, under the assumption that standard channel layout is followed:
  12. // 1 channel = mono
  13. // 2 channels = stereo (left, right)
  14. // 3 channels = left, right, center
  15. // 4 channels = front left/right, back left/right
  16. // 5 channels = front left/right, center, back left/right
  17. // 6 channels = front left/right, center, LFE, back left/right
  18. // 7 channels = front left/right, center, LFE, back center, side left/right
  19. // 8 channels = front left/right, center, LFE, back left/right, side left/right
  20. // Additionally, performs sample rescaling to go from integer samples to floating-point samples.
  21. template<ArrayLike<i64> ChannelType, ArrayLike<ChannelType> InputType>
  22. ErrorOr<FixedArray<Sample>> downmix_surround_to_stereo(InputType const& input, float sample_scale_factor)
  23. {
  24. if (input.size() == 0)
  25. return Error::from_string_view("Cannot resample from 0 channels"sv);
  26. auto channel_count = input.size();
  27. auto sample_count = input[0].size();
  28. FixedArray<Sample> output = TRY(FixedArray<Sample>::create(sample_count));
  29. // FIXME: We could figure out a better way to mix the channels, possibly spatially, but for now:
  30. // - Center and LFE channels are added to both left and right.
  31. // - All left channels are added together on the left, all right channels are added together on the right.
  32. switch (channel_count) {
  33. case 1:
  34. for (auto i = 0u; i < sample_count; ++i)
  35. output[i] = Sample { input[0][i] * sample_scale_factor };
  36. break;
  37. case 2:
  38. for (auto i = 0u; i < sample_count; ++i)
  39. output[i] = Sample {
  40. input[0][i] * sample_scale_factor,
  41. input[1][i] * sample_scale_factor
  42. };
  43. break;
  44. case 3:
  45. for (auto i = 0u; i < sample_count; ++i)
  46. output[i] = Sample {
  47. input[0][i] * sample_scale_factor + input[2][i] * sample_scale_factor,
  48. input[1][i] * sample_scale_factor + input[2][i] * sample_scale_factor
  49. };
  50. break;
  51. case 4:
  52. for (auto i = 0u; i < sample_count; ++i)
  53. output[i] = Sample {
  54. input[0][i] * sample_scale_factor + input[2][i] * sample_scale_factor,
  55. input[1][i] * sample_scale_factor + input[3][i] * sample_scale_factor
  56. };
  57. break;
  58. case 5:
  59. for (auto i = 0u; i < sample_count; ++i)
  60. output[i] = Sample {
  61. input[0][i] * sample_scale_factor + input[3][i] * sample_scale_factor + input[2][i] * sample_scale_factor,
  62. input[1][i] * sample_scale_factor + input[4][i] * sample_scale_factor + input[2][i] * sample_scale_factor
  63. };
  64. break;
  65. case 6:
  66. for (auto i = 0u; i < sample_count; ++i) {
  67. output[i] = Sample {
  68. input[0][i] * sample_scale_factor + input[4][i] * sample_scale_factor + input[2][i] * sample_scale_factor + input[3][i] * sample_scale_factor,
  69. input[1][i] * sample_scale_factor + input[5][i] * sample_scale_factor + input[2][i] * sample_scale_factor + input[3][i] * sample_scale_factor
  70. };
  71. }
  72. break;
  73. case 7:
  74. for (auto i = 0u; i < sample_count; ++i) {
  75. output[i] = Sample {
  76. input[0][i] * sample_scale_factor + input[5][i] * sample_scale_factor + input[2][i] * sample_scale_factor + input[3][i] * sample_scale_factor + input[4][i] * sample_scale_factor,
  77. input[1][i] * sample_scale_factor + input[6][i] * sample_scale_factor + input[2][i] * sample_scale_factor + input[3][i] * sample_scale_factor + input[4][i] * sample_scale_factor
  78. };
  79. }
  80. break;
  81. case 8:
  82. for (auto i = 0u; i < sample_count; ++i) {
  83. output[i] = Sample {
  84. input[0][i] * sample_scale_factor + input[4][i] * sample_scale_factor + input[6][i] * sample_scale_factor + input[2][i] * sample_scale_factor + input[3][i] * sample_scale_factor,
  85. input[1][i] * sample_scale_factor + input[5][i] * sample_scale_factor + input[7][i] * sample_scale_factor + input[2][i] * sample_scale_factor + input[3][i] * sample_scale_factor
  86. };
  87. }
  88. break;
  89. default:
  90. return Error::from_string_view("Invalid number of channels greater than 8"sv);
  91. }
  92. return output;
  93. }
  94. }