@streaming-sortformer-node/darwin-arm64 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
package/package.json
CHANGED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#include "StreamFeedWorker.h"
|
|
2
|
+
#include <cstring>
|
|
3
|
+
|
|
4
|
+
// Number of speakers output by the model
|
|
5
|
+
static constexpr int NUM_SPEAKERS = 4;
|
|
6
|
+
|
|
7
|
+
StreamFeedWorker::StreamFeedWorker(
|
|
8
|
+
Napi::Env env,
|
|
9
|
+
sortformer_stream_state* stream,
|
|
10
|
+
std::vector<float> audio,
|
|
11
|
+
Napi::Promise::Deferred deferred)
|
|
12
|
+
: Napi::AsyncWorker(env)
|
|
13
|
+
, stream_(stream)
|
|
14
|
+
, audio_(std::move(audio))
|
|
15
|
+
, deferred_(deferred)
|
|
16
|
+
{
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void StreamFeedWorker::Execute() {
|
|
20
|
+
// IMPORTANT: This runs on a worker thread - NO Napi calls allowed!
|
|
21
|
+
|
|
22
|
+
if (!stream_) {
|
|
23
|
+
SetError("Stream is null");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Allocate output buffer (generous size)
|
|
28
|
+
// hop=160, plus margin for padding
|
|
29
|
+
int max_frames = static_cast<int>(audio_.size() / 160) + 100;
|
|
30
|
+
predictions_.resize(max_frames * NUM_SPEAKERS);
|
|
31
|
+
|
|
32
|
+
n_frames_ = sortformer_stream_feed(
|
|
33
|
+
stream_,
|
|
34
|
+
audio_.data(),
|
|
35
|
+
static_cast<int>(audio_.size()),
|
|
36
|
+
predictions_.data(),
|
|
37
|
+
max_frames);
|
|
38
|
+
|
|
39
|
+
if (n_frames_ < 0) {
|
|
40
|
+
SetError("Stream feed failed");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
predictions_.resize(n_frames_ * NUM_SPEAKERS);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void StreamFeedWorker::OnOK() {
|
|
48
|
+
Napi::Env env = Env();
|
|
49
|
+
Napi::HandleScope scope(env);
|
|
50
|
+
|
|
51
|
+
Napi::Object result = Napi::Object::New(env);
|
|
52
|
+
|
|
53
|
+
// Copy predictions to a JS-owned ArrayBuffer
|
|
54
|
+
Napi::ArrayBuffer buffer = Napi::ArrayBuffer::New(
|
|
55
|
+
env,
|
|
56
|
+
predictions_.size() * sizeof(float));
|
|
57
|
+
|
|
58
|
+
std::memcpy(buffer.Data(), predictions_.data(), predictions_.size() * sizeof(float));
|
|
59
|
+
|
|
60
|
+
Napi::Float32Array predictions = Napi::Float32Array::New(
|
|
61
|
+
env,
|
|
62
|
+
predictions_.size(),
|
|
63
|
+
buffer,
|
|
64
|
+
0);
|
|
65
|
+
|
|
66
|
+
result.Set("predictions", predictions);
|
|
67
|
+
result.Set("frameCount", Napi::Number::New(env, n_frames_));
|
|
68
|
+
|
|
69
|
+
deferred_.Resolve(result);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void StreamFeedWorker::OnError(const Napi::Error& e) {
|
|
73
|
+
deferred_.Reject(e.Value());
|
|
74
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#ifndef STREAM_FEED_WORKER_H
|
|
2
|
+
#define STREAM_FEED_WORKER_H
|
|
3
|
+
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
#include <vector>
|
|
6
|
+
|
|
7
|
+
#include "sortformer.h"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* AsyncWorker for non-blocking streaming feed.
|
|
11
|
+
*
|
|
12
|
+
* Runs sortformer_stream_feed() on a worker thread to avoid blocking
|
|
13
|
+
* the Node.js event loop. Returns a Promise that resolves with
|
|
14
|
+
* { predictions: Float32Array, frameCount: number }.
|
|
15
|
+
*/
|
|
16
|
+
class StreamFeedWorker : public Napi::AsyncWorker {
|
|
17
|
+
public:
|
|
18
|
+
StreamFeedWorker(
|
|
19
|
+
Napi::Env env,
|
|
20
|
+
sortformer_stream_state* stream,
|
|
21
|
+
std::vector<float> audio,
|
|
22
|
+
Napi::Promise::Deferred deferred);
|
|
23
|
+
|
|
24
|
+
void Execute() override;
|
|
25
|
+
void OnOK() override;
|
|
26
|
+
void OnError(const Napi::Error& e) override;
|
|
27
|
+
|
|
28
|
+
private:
|
|
29
|
+
sortformer_stream_state* stream_;
|
|
30
|
+
std::vector<float> audio_;
|
|
31
|
+
Napi::Promise::Deferred deferred_;
|
|
32
|
+
|
|
33
|
+
// Results (populated in Execute, used in OnOK)
|
|
34
|
+
std::vector<float> predictions_;
|
|
35
|
+
int n_frames_ = 0;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
#endif // STREAM_FEED_WORKER_H
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#include "StreamFlushWorker.h"
|
|
2
|
+
#include <cstring>
|
|
3
|
+
|
|
4
|
+
// Number of speakers output by the model
|
|
5
|
+
static constexpr int NUM_SPEAKERS = 4;
|
|
6
|
+
|
|
7
|
+
StreamFlushWorker::StreamFlushWorker(
|
|
8
|
+
Napi::Env env,
|
|
9
|
+
sortformer_stream_state* stream,
|
|
10
|
+
Napi::Promise::Deferred deferred)
|
|
11
|
+
: Napi::AsyncWorker(env)
|
|
12
|
+
, stream_(stream)
|
|
13
|
+
, deferred_(deferred)
|
|
14
|
+
{
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void StreamFlushWorker::Execute() {
|
|
18
|
+
// IMPORTANT: This runs on a worker thread - NO Napi calls allowed!
|
|
19
|
+
|
|
20
|
+
if (!stream_) {
|
|
21
|
+
SetError("Stream is null");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
int max_frames = 1000;
|
|
26
|
+
predictions_.resize(max_frames * NUM_SPEAKERS);
|
|
27
|
+
|
|
28
|
+
n_frames_ = sortformer_stream_flush(
|
|
29
|
+
stream_,
|
|
30
|
+
predictions_.data(),
|
|
31
|
+
max_frames);
|
|
32
|
+
|
|
33
|
+
if (n_frames_ < 0) {
|
|
34
|
+
SetError("Stream flush failed");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
predictions_.resize(n_frames_ * NUM_SPEAKERS);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void StreamFlushWorker::OnOK() {
|
|
42
|
+
Napi::Env env = Env();
|
|
43
|
+
Napi::HandleScope scope(env);
|
|
44
|
+
|
|
45
|
+
Napi::Object result = Napi::Object::New(env);
|
|
46
|
+
|
|
47
|
+
// Copy predictions to a JS-owned ArrayBuffer
|
|
48
|
+
Napi::ArrayBuffer buffer = Napi::ArrayBuffer::New(
|
|
49
|
+
env,
|
|
50
|
+
predictions_.size() * sizeof(float));
|
|
51
|
+
|
|
52
|
+
std::memcpy(buffer.Data(), predictions_.data(), predictions_.size() * sizeof(float));
|
|
53
|
+
|
|
54
|
+
Napi::Float32Array predictions = Napi::Float32Array::New(
|
|
55
|
+
env,
|
|
56
|
+
predictions_.size(),
|
|
57
|
+
buffer,
|
|
58
|
+
0);
|
|
59
|
+
|
|
60
|
+
result.Set("predictions", predictions);
|
|
61
|
+
result.Set("frameCount", Napi::Number::New(env, n_frames_));
|
|
62
|
+
|
|
63
|
+
deferred_.Resolve(result);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void StreamFlushWorker::OnError(const Napi::Error& e) {
|
|
67
|
+
deferred_.Reject(e.Value());
|
|
68
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#ifndef STREAM_FLUSH_WORKER_H
|
|
2
|
+
#define STREAM_FLUSH_WORKER_H
|
|
3
|
+
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
#include <vector>
|
|
6
|
+
|
|
7
|
+
#include "sortformer.h"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* AsyncWorker for non-blocking streaming flush.
|
|
11
|
+
*
|
|
12
|
+
* Runs sortformer_stream_flush() on a worker thread to avoid blocking
|
|
13
|
+
* the Node.js event loop. Returns a Promise that resolves with
|
|
14
|
+
* { predictions: Float32Array, frameCount: number }.
|
|
15
|
+
*/
|
|
16
|
+
class StreamFlushWorker : public Napi::AsyncWorker {
|
|
17
|
+
public:
|
|
18
|
+
StreamFlushWorker(
|
|
19
|
+
Napi::Env env,
|
|
20
|
+
sortformer_stream_state* stream,
|
|
21
|
+
Napi::Promise::Deferred deferred);
|
|
22
|
+
|
|
23
|
+
void Execute() override;
|
|
24
|
+
void OnOK() override;
|
|
25
|
+
void OnError(const Napi::Error& e) override;
|
|
26
|
+
|
|
27
|
+
private:
|
|
28
|
+
sortformer_stream_state* stream_;
|
|
29
|
+
Napi::Promise::Deferred deferred_;
|
|
30
|
+
|
|
31
|
+
// Results (populated in Execute, used in OnOK)
|
|
32
|
+
std::vector<float> predictions_;
|
|
33
|
+
int n_frames_ = 0;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
#endif // STREAM_FLUSH_WORKER_H
|