padenot / ringbuf.js

Wait-free thread-safe single-consumer single-producer ring buffer using SharedArrayBuffer
https://ringbuf-js.netlify.app/
Mozilla Public License 2.0
201 stars 18 forks source link

Does `deinterleave` work correctly? #21

Closed grazder closed 1 year ago

grazder commented 1 year ago

it looks like here should be input.length / 128?

https://github.com/padenot/ringbuf.js/blob/329137af8d6ba4e8bdbb79e99ded6ffa64c2c719/js/audioqueue.js#L13

For example, we've got simple stereo input - 2 * 128 frames and we want to get in output 2 arrays of 128

here is example like i understood it

function deinterleave(input, output) {
  const channel_count = input.length / 256;
  if (output.length !== channel_count) {
    throw RangeError("not enough space in output arrays");
  }
  for (let i = 0; i < channel_count; i++) {
    const out_channel = output[i];
    let interleaved_idx = i;
    for (let j = 0; j < 128; ++j) {
      out_channel[j] = input[interleaved_idx];
      interleaved_idx += channel_count;
    }
  }
}

input = Array.from(Array(256).keys())
output = [new Array(128).fill(0), new Array(128).fill(0)]

console.log(input);
console.log(output.length);

deinterleave(input, output)
console.log('result')
console.log(output)

output:

[
   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
  12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
  24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
  36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
  60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
  72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
  84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
  96, 97, 98, 99,
  ... 156 more items
]
2
ERROR!
/tmp/BjrpFXL3HK.js:7
    throw RangeError("not enough space in output arrays");
    ^

And if i provide output with length = 1 It turns out that we are losing the last 128 floats.

and how i suggest

function deinterleave(input, output) {
  const channel_count = input.length / 128;
  if (output.length !== channel_count) {
    throw RangeError("not enough space in output arrays");
  }
  for (let i = 0; i < channel_count; i++) {
    const out_channel = output[i];
    let interleaved_idx = i;
    for (let j = 0; j < 128; ++j) {
      out_channel[j] = input[interleaved_idx];
      interleaved_idx += channel_count;
    }
  }
}

input = Array.from(Array(256).keys())
output = [new Array(128).fill(0), new Array(128).fill(0)]

console.log(input);
console.log(output.length);

deinterleave(input, output)
console.log('result')
console.log(output)

output:

[
   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
  12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
  24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
  36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
  60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
  72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
  84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
  96, 97, 98, 99,
  ... 156 more items
]
2
result
[
  [
      0,   2,   4,   6,   8,  10,  12,  14,  16,  18,  20,  22,
     24,  26,  28,  30,  32,  34,  36,  38,  40,  42,  44,  46,
     48,  50,  52,  54,  56,  58,  60,  62,  64,  66,  68,  70,
     72,  74,  76,  78,  80,  82,  84,  86,  88,  90,  92,  94,
     96,  98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118,
    120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142,
    144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166,
    168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190,
    192, 194, 196, 198,
    ... 28 more items
  ],
  [
      1,   3,   5,   7,   9,  11,  13,  15,  17,  19,  21,  23,
     25,  27,  29,  31,  33,  35,  37,  39,  41,  43,  45,  47,
     49,  51,  53,  55,  57,  59,  61,  63,  65,  67,  69,  71,
     73,  75,  77,  79,  81,  83,  85,  87,  89,  91,  93,  95,
     97,  99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119,
    121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143,
    145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167,
    169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191,
    193, 195, 197, 199,
    ... 28 more items
  ]
]

Correct me please if i didn't understand the logic

padenot commented 1 year ago

Thanks a lot for the report, fixed in https://github.com/padenot/ringbuf.js/commit/0a15bf3b85679e7bcfb8c9a1d561ab49dad820e0, with a test in the following commit.

padenot commented 1 year ago

And released a new minor version (with a bunch of deps updated).

grazder commented 1 year ago

cool, thanks!