audio-util.test.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import {
  2. computeRMS,
  3. computeChunkedRMS,
  4. downsampleIfNeeded,
  5. dropEveryOtherSample
  6. } from '../../../src/lib/audio/audio-util';
  7. describe('computeRMS', () => {
  8. test('returns 0 when given no samples', () => {
  9. expect(computeRMS([])).toEqual(0);
  10. });
  11. test('returns the RMS scaled by the given unity value and square rooted', () => {
  12. const unity = 0.5;
  13. const samples = [3, 2, 1];
  14. expect(computeRMS(samples, unity)).toEqual(
  15. Math.sqrt(Math.sqrt(((3 * 3) + (2 * 2) + (1 * 1)) / 3) / 0.5)
  16. );
  17. });
  18. test('uses a default unity value of 0.55', () => {
  19. const samples = [1, 1, 1];
  20. // raw rms is 1, scaled to (1 / 0.55) and square rooted
  21. expect(computeRMS(samples)).toEqual(Math.sqrt(1 / 0.55));
  22. });
  23. });
  24. describe('computeChunkedRMS', () => {
  25. test('computes the rms for each chunk based on chunk size', () => {
  26. const samples = [2, 1, 3, 2, 5];
  27. const chunkedLevels = computeChunkedRMS(samples, 2);
  28. // chunked to [2, 0], [3, 0], [5]
  29. // rms scaled with default unity of 0.55
  30. expect(chunkedLevels.length).toEqual(3);
  31. expect(chunkedLevels).toEqual([
  32. Math.sqrt(Math.sqrt(((2 * 2) + (1 * 1)) / 2) / 0.55),
  33. Math.sqrt(Math.sqrt(((3 * 3) + (2 * 2)) / 2) / 0.55),
  34. Math.sqrt(Math.sqrt((5 * 5) / 1) / 0.55)
  35. ]);
  36. });
  37. test('chunk size larger than sample size creates single chunk', () => {
  38. const samples = [1, 1, 1];
  39. const chunkedLevels = computeChunkedRMS(samples, 7);
  40. // chunked to [1, 1, 1]
  41. // rms scaled with default unity of 0.55
  42. expect(chunkedLevels.length).toEqual(1);
  43. expect(chunkedLevels).toEqual([Math.sqrt(1 / 0.55)]);
  44. });
  45. test('chunk size as multiple is handled correctly', () => {
  46. const samples = [1, 1, 1, 1, 1, 1];
  47. const chunkedLevels = computeChunkedRMS(samples, 3);
  48. // chunked to [1, 1, 1], [1, 1, 1]
  49. // rms scaled with default unity of 0.55
  50. expect(chunkedLevels.length).toEqual(2);
  51. expect(chunkedLevels).toEqual([Math.sqrt(1 / 0.55), Math.sqrt(1 / 0.55)]);
  52. });
  53. });
  54. describe('downsampleIfNeeded', () => {
  55. const samples = {length: 1};
  56. const sampleRate = 44100;
  57. test('returns given data when no downsampling needed', async () => {
  58. samples.length = 1;
  59. const res = await downsampleIfNeeded({samples, sampleRate}, null);
  60. expect(res.samples).toEqual(samples);
  61. expect(res.sampleRate).toEqual(sampleRate);
  62. });
  63. test('downsamples to 22050 if that puts it under the limit', async () => {
  64. samples.length = 44100 * 3 * 60;
  65. const resampler = jest.fn(() => 'TEST');
  66. const res = await downsampleIfNeeded({samples, sampleRate}, resampler);
  67. expect(resampler).toHaveBeenCalledWith({samples, sampleRate}, 22050);
  68. expect(res).toEqual('TEST');
  69. });
  70. test('fails if resampling would not put it under the limit', async () => {
  71. samples.length = 44100 * 4 * 60;
  72. try {
  73. await downsampleIfNeeded({samples, sampleRate}, null);
  74. } catch (e) {
  75. expect(e).toEqual('Sound too large to save, refusing to edit');
  76. }
  77. });
  78. });
  79. describe('dropEveryOtherSample', () => {
  80. const buffer = {
  81. samples: [1, 0, 2, 0, 3, 0],
  82. sampleRate: 2
  83. };
  84. test('result is half the length', () => {
  85. const {samples} = dropEveryOtherSample(buffer);
  86. expect(samples.length).toEqual(Math.floor(buffer.samples.length / 2));
  87. });
  88. test('result contains only even-index items', () => {
  89. const {samples} = dropEveryOtherSample(buffer);
  90. expect(samples).toEqual(new Float32Array([1, 2, 3]));
  91. });
  92. test('result sampleRate is given sampleRate / 2', () => {
  93. const {sampleRate} = dropEveryOtherSample(buffer);
  94. expect(sampleRate).toEqual(buffer.sampleRate / 2);
  95. });
  96. });