From 781792f9e557ea263ce1c54da91abc1818c42a54 Mon Sep 17 00:00:00 2001 From: cm-ayf Date: Sun, 26 May 2024 13:07:03 +0900 Subject: [PATCH] use built-in cache in readable (#38) --- lib/index.js | 36 +++++++++--------------------------- test/index.js | 9 +++++---- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/lib/index.js b/lib/index.js index 6e228f7..3797245 100644 --- a/lib/index.js +++ b/lib/index.js @@ -19,6 +19,8 @@ exports.Application = Application; const { version: OM_SYRINX_VERSION } = require("../package.json"); exports.OM_SYRINX_VERSION = OM_SYRINX_VERSION; +const { setTimeout } = require("node:timers/promises"); + class SyrinxStream extends Readable { /** * @param {import("./native").Syrinx} syrinx @@ -43,21 +45,6 @@ class SyrinxStream extends Readable { * @private */ this._option = option; - /** - * @type {Buffer[]} - * @private - */ - this._cache = []; - /** - * @type {number} - * @private - */ - this._waiting = 0; - /** - * @type {boolean} - * @private - */ - this._ended = false; } /** @@ -74,22 +61,17 @@ class SyrinxStream extends Readable { callback(error); await synthesizer?.synthesize((err, result) => { - if (err) return this.emit("error", err); - if (this._waiting > 0) { - this._waiting--; - this.push(result); - } else this._cache.push(result); + if (err) this.emit("error", err); + else this.push(result); }); - this._ended = true; + // The last push sometimes occurs after the Promise resolution, + // so we need to make sure that the last push occurs before the stream ends. + await setTimeout(); + this.push(null); } - _read() { - const cache = this._cache.shift(); - if (cache) this.push(cache); - else if (this._ended) this.push(null); - else this._waiting++; - } + _read() {} } class Syrinx { diff --git a/test/index.js b/test/index.js index 6413e18..a42dcd3 100644 --- a/test/index.js +++ b/test/index.js @@ -79,15 +79,16 @@ async function fetchAndExtract(url, path) { * @param {Syrinx} syrinx * @param {string} inputText * @param {import("../lib").SynthesisOption} option + * @param {boolean} [wait] * @returns {Promise} */ -async function synthesize(syrinx, inputText, option) { +async function synthesize(syrinx, inputText, option, wait = false) { const stream = syrinx.synthesize(inputText, option); /** @type {Buffer[]} */ const result = []; for await (const item of stream) { result.push(item); - await setTimeout(20); + if (wait) await setTimeout(20); } return result; } @@ -130,7 +131,7 @@ describe("synthesis", () => { encoder: { type: EncoderType.Raw }, }); - const bonsai = await synthesize(pcm, "盆栽", {}); + const bonsai = await synthesize(pcm, "盆栽", {}, true); await checksum( Buffer.concat(bonsai), "36050aef60896f56bbfe59868a3f57b6bbc5b147", @@ -160,7 +161,7 @@ describe("synthesis", () => { encoder: { type: EncoderType.Opus }, }); - const bonsai = await synthesize(opus, "盆栽", {}); + const bonsai = await synthesize(opus, "盆栽", {}, true); assert.strictEqual(bonsai.length, 78); const bonsaiDecoded = decoder.decodeFrames(bonsai);