@fonoster/amd 0.27.0 → 0.31.0
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.
- package/README.md +10 -132
- package/dist/amd/AmdModel.d.ts +5 -0
- package/dist/amd/AmdModel.js +19 -0
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -4
- package/package.json +7 -15
- package/dist/agi/AgiChannel.d.ts +0 -77
- package/dist/agi/AgiChannel.js +0 -171
- package/dist/agi/AgiServer.d.ts +0 -34
- package/dist/agi/AgiServer.js +0 -109
- package/dist/agi/server.d.ts +0 -16
- package/dist/agi/server.js +0 -154
- package/dist/agi/sessionRegistry.d.ts +0 -26
- package/dist/agi/sessionRegistry.js +0 -34
- package/dist/amd/buildAmdVariables.d.ts +0 -13
- package/dist/amd/buildAmdVariables.js +0 -98
- package/dist/audiosocket/server.d.ts +0 -9
- package/dist/audiosocket/server.js +0 -65
- package/dist/envs.d.ts +0 -8
- package/dist/envs.js +0 -61
- package/dist/probe/collectPcm.d.ts +0 -37
- package/dist/probe/collectPcm.js +0 -47
- package/dist/probe/runProbe.d.ts +0 -37
- package/dist/probe/runProbe.js +0 -110
- package/dist/probe/upsample.d.ts +0 -3
- package/dist/probe/upsample.js +0 -53
- package/dist/server.d.ts +0 -1
- package/dist/server.js +0 -27
package/dist/probe/runProbe.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.runProbe = runProbe;
|
|
13
|
-
/**
|
|
14
|
-
* Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
|
|
15
|
-
* http://github.com/fonoster/fonoster
|
|
16
|
-
*
|
|
17
|
-
* This file is part of Fonoster
|
|
18
|
-
*
|
|
19
|
-
* Licensed under the MIT License (the "License");
|
|
20
|
-
* you may not use this file except in compliance with
|
|
21
|
-
* the License. You may obtain a copy of the License at
|
|
22
|
-
*
|
|
23
|
-
* https://opensource.org/licenses/MIT
|
|
24
|
-
*
|
|
25
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
26
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
27
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
28
|
-
* See the License for the specific language governing permissions and
|
|
29
|
-
* limitations under the License.
|
|
30
|
-
*/
|
|
31
|
-
const logger_1 = require("@fonoster/logger");
|
|
32
|
-
const AmdModel_1 = require("../amd/AmdModel");
|
|
33
|
-
const collectPcm_1 = require("./collectPcm");
|
|
34
|
-
const upsample_1 = require("./upsample");
|
|
35
|
-
const logger = (0, logger_1.getLogger)({ service: "amd", filePath: __filename });
|
|
36
|
-
/**
|
|
37
|
-
* Runs Answering Machine Detection on the leading audio of one AGI/AudioSocket
|
|
38
|
-
* session. Always resolves and never throws: any model error, timeout, or
|
|
39
|
-
* empty capture yields `{ kind: "unknown" }` so the caller can always report
|
|
40
|
-
* *something* back over AGI. Confidence thresholding is deliberately not
|
|
41
|
-
* applied here — see `buildAmdVariables`.
|
|
42
|
-
*/
|
|
43
|
-
function runProbe(params) {
|
|
44
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
var _a;
|
|
46
|
-
const { stream, probeMs, timeoutMs, modelDir } = params;
|
|
47
|
-
const classify = (_a = params.classify) !== null && _a !== void 0 ? _a : ((pcm) => (0, AmdModel_1.classifyPcm)(pcm, modelDir !== null && modelDir !== void 0 ? modelDir : AmdModel_1.DEFAULT_MODEL_DIR));
|
|
48
|
-
const startedAt = Date.now();
|
|
49
|
-
const latencyMs = () => Date.now() - startedAt;
|
|
50
|
-
const unknown = (cause) => ({
|
|
51
|
-
kind: "unknown",
|
|
52
|
-
cause,
|
|
53
|
-
latencyMs: latencyMs()
|
|
54
|
-
});
|
|
55
|
-
const controller = new AbortController();
|
|
56
|
-
const deadline = setTimeout(() => controller.abort(), timeoutMs);
|
|
57
|
-
const TIMED_OUT = Symbol("amd-timed-out");
|
|
58
|
-
const onDeadline = new Promise((resolve) => {
|
|
59
|
-
if (controller.signal.aborted)
|
|
60
|
-
resolve(TIMED_OUT);
|
|
61
|
-
else
|
|
62
|
-
controller.signal.addEventListener("abort", () => resolve(TIMED_OUT), {
|
|
63
|
-
once: true
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
try {
|
|
67
|
-
const pcm = yield (0, collectPcm_1.collectPcm)({
|
|
68
|
-
stream,
|
|
69
|
-
probeMs,
|
|
70
|
-
signal: controller.signal
|
|
71
|
-
});
|
|
72
|
-
if (controller.signal.aborted) {
|
|
73
|
-
logger.warn("amd probe: deadline hit while collecting audio");
|
|
74
|
-
return unknown("ML-TIMEOUT");
|
|
75
|
-
}
|
|
76
|
-
if (pcm.length === 0) {
|
|
77
|
-
logger.verbose("amd probe: no usable audio before deadline");
|
|
78
|
-
return unknown("ML-NO-AUDIO");
|
|
79
|
-
}
|
|
80
|
-
// The deadline must also bound classification: a cold model load or a hung
|
|
81
|
-
// inference cannot be allowed to stall the AGI session. ONNX Runtime has no
|
|
82
|
-
// cancellation, so the losing promise is left to settle on its own.
|
|
83
|
-
// The model was trained on 16 kHz input; AudioSocket delivers 8 kHz.
|
|
84
|
-
const classification = classify((0, upsample_1.upsample8kTo16k)(pcm));
|
|
85
|
-
classification.catch(() => undefined); // no unhandled rejection if the deadline wins
|
|
86
|
-
const outcome = yield Promise.race([classification, onDeadline]);
|
|
87
|
-
if (outcome === TIMED_OUT) {
|
|
88
|
-
logger.warn("amd probe: classification did not finish before the deadline");
|
|
89
|
-
return unknown("ML-TIMEOUT");
|
|
90
|
-
}
|
|
91
|
-
logger.verbose("amd probe: verdict", outcome);
|
|
92
|
-
return {
|
|
93
|
-
kind: "classified",
|
|
94
|
-
status: outcome.status,
|
|
95
|
-
confidence: outcome.confidence,
|
|
96
|
-
detector: outcome.detector,
|
|
97
|
-
latencyMs: latencyMs()
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
catch (err) {
|
|
101
|
-
logger.warn("amd probe failed; reporting unknown", {
|
|
102
|
-
error: err.message
|
|
103
|
-
});
|
|
104
|
-
return unknown("ML-ERROR");
|
|
105
|
-
}
|
|
106
|
-
finally {
|
|
107
|
-
clearTimeout(deadline);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
package/dist/probe/upsample.d.ts
DELETED
package/dist/probe/upsample.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.upsample8kTo16k = upsample8kTo16k;
|
|
4
|
-
/**
|
|
5
|
-
* Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
|
|
6
|
-
* http://github.com/fonoster/fonoster
|
|
7
|
-
*
|
|
8
|
-
* This file is part of Fonoster
|
|
9
|
-
*
|
|
10
|
-
* Licensed under the MIT License (the "License");
|
|
11
|
-
* you may not use this file except in compliance with
|
|
12
|
-
* the License. You may obtain a copy of the License at
|
|
13
|
-
*
|
|
14
|
-
* https://opensource.org/licenses/MIT
|
|
15
|
-
*
|
|
16
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
17
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
18
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
19
|
-
* See the License for the specific language governing permissions and
|
|
20
|
-
* limitations under the License.
|
|
21
|
-
*/
|
|
22
|
-
const HALF_TAPS = 16;
|
|
23
|
-
// Half-band windowed-sinc (Blackman) taps at offsets ±(k + 0.5), normalized
|
|
24
|
-
// to unity DC gain. Linear interpolation measurably loses accuracy here: its
|
|
25
|
-
// imaging above 4 kHz is enough to lower the classifier's confidence.
|
|
26
|
-
const TAPS = (() => {
|
|
27
|
-
const taps = new Float64Array(HALF_TAPS);
|
|
28
|
-
let sum = 0;
|
|
29
|
-
for (let k = 0; k < HALF_TAPS; k++) {
|
|
30
|
-
const offset = k + 0.5;
|
|
31
|
-
const sinc = Math.sin(Math.PI * offset) / (Math.PI * offset);
|
|
32
|
-
const u = (offset + HALF_TAPS) / (2 * HALF_TAPS);
|
|
33
|
-
const window = 0.42 - 0.5 * Math.cos(2 * Math.PI * u) + 0.08 * Math.cos(4 * Math.PI * u);
|
|
34
|
-
taps[k] = sinc * window;
|
|
35
|
-
sum += 2 * taps[k];
|
|
36
|
-
}
|
|
37
|
-
return taps.map((t) => t / sum);
|
|
38
|
-
})();
|
|
39
|
-
/** Upsamples 8 kHz s16le mono PCM to 16 kHz s16le mono. */
|
|
40
|
-
function upsample8kTo16k(pcm) {
|
|
41
|
-
const count = Math.floor(pcm.length / 2);
|
|
42
|
-
const out = Buffer.alloc(count * 4);
|
|
43
|
-
const sample = (i) => pcm.readInt16LE(2 * Math.min(Math.max(i, 0), count - 1));
|
|
44
|
-
for (let i = 0; i < count; i++) {
|
|
45
|
-
let interpolated = 0;
|
|
46
|
-
for (let k = 0; k < HALF_TAPS; k++) {
|
|
47
|
-
interpolated += TAPS[k] * (sample(i - k) + sample(i + 1 + k));
|
|
48
|
-
}
|
|
49
|
-
out.writeInt16LE(pcm.readInt16LE(2 * i), 4 * i);
|
|
50
|
-
out.writeInt16LE(Math.max(-32768, Math.min(32767, Math.round(interpolated))), 4 * i + 2);
|
|
51
|
-
}
|
|
52
|
-
return out;
|
|
53
|
-
}
|
package/dist/server.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/server.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/**
|
|
4
|
-
* Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
|
|
5
|
-
* http://github.com/fonoster/fonoster
|
|
6
|
-
*
|
|
7
|
-
* This file is part of Fonoster
|
|
8
|
-
*
|
|
9
|
-
* Licensed under the MIT License (the "License");
|
|
10
|
-
* you may not use this file except in compliance with
|
|
11
|
-
* the License. You may obtain a copy of the License at
|
|
12
|
-
*
|
|
13
|
-
* https://opensource.org/licenses/MIT
|
|
14
|
-
*
|
|
15
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
-
* See the License for the specific language governing permissions and
|
|
19
|
-
* limitations under the License.
|
|
20
|
-
*/
|
|
21
|
-
const logger_1 = require("@fonoster/logger");
|
|
22
|
-
const server_1 = require("./agi/server");
|
|
23
|
-
const server_2 = require("./audiosocket/server");
|
|
24
|
-
const logger = (0, logger_1.getLogger)({ service: "amd", filePath: __filename });
|
|
25
|
-
logger.info("starting amd");
|
|
26
|
-
(0, server_2.startAudioSocketServer)();
|
|
27
|
-
(0, server_1.startAgiServer)();
|