opus-codec 0.0.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
@@ -0,0 +1,8 @@
1
+ import { Runtime } from '../runtime';
2
+ export default class Decoder {
3
+ #private;
4
+ constructor(runtime: Runtime, sampleRate: number, channels: number, frameSize: number);
5
+ decodeFloat(value: Uint8Array, decodeFec?: number): number;
6
+ decoded(): Float32Array;
7
+ destroy(): void;
8
+ }
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const runtime_1 = require("../runtime");
4
+ class Decoder {
5
+ #errorPointer;
6
+ #error;
7
+ #decoder;
8
+ #holder;
9
+ #runtime;
10
+ #pcm;
11
+ #frameSize;
12
+ constructor(runtime, sampleRate, channels, frameSize) {
13
+ this.#frameSize = frameSize;
14
+ this.#runtime = runtime;
15
+ this.#holder = new runtime_1.ResourcesHolder();
16
+ this.#error = new runtime_1.Integer(runtime);
17
+ this.#errorPointer = new runtime_1.Pointer(runtime, this.#error);
18
+ /**
19
+ * holder
20
+ */
21
+ this.#holder.add(this.#error);
22
+ this.#holder.add(this.#errorPointer);
23
+ /**
24
+ * create decoder
25
+ */
26
+ this.#decoder = runtime.originalRuntime()._opus_decoder_create(sampleRate, channels, this.#errorPointer.offset());
27
+ if (!this.#decoder || this.#error.value() < 0) {
28
+ throw new Error('Failed to create decoder');
29
+ }
30
+ this.#pcm = new runtime_1.Buffer(runtime, this.#frameSize * channels * Float32Array.BYTES_PER_ELEMENT);
31
+ }
32
+ #data = null;
33
+ decodeFloat(value, decodeFec = 0) {
34
+ let data = this.#data;
35
+ if (!data) {
36
+ data = new runtime_1.Buffer(this.#runtime, value.byteLength);
37
+ }
38
+ /**
39
+ * reallocate in case current allocated buffer is smaller than the actual
40
+ * incoming data
41
+ */
42
+ if (data.data().byteLength < value.byteLength) {
43
+ data.destroy();
44
+ data = new runtime_1.Buffer(this.#runtime, value.byteLength);
45
+ }
46
+ /**
47
+ * set data
48
+ */
49
+ data.data().set(value);
50
+ /**
51
+ * in case the data buffer has changed, set it back to the class
52
+ * instance so we can later destroy it
53
+ */
54
+ this.#data = data;
55
+ /**
56
+ * decode float data
57
+ */
58
+ const decodedSamples = this.#runtime.originalRuntime()._opus_decode_float(this.#decoder, data.offset(), value.byteLength, this.#pcm.offset(), this.#frameSize, decodeFec);
59
+ if (decodedSamples < 0) {
60
+ throw new Error('Failed to decode float');
61
+ }
62
+ return decodedSamples;
63
+ }
64
+ decoded() {
65
+ const pcm = this.#pcm.data();
66
+ return new Float32Array(pcm.buffer, pcm.byteOffset, pcm.byteLength / Float32Array.BYTES_PER_ELEMENT);
67
+ }
68
+ destroy() {
69
+ this.#runtime.originalRuntime()._opus_decoder_destroy(this.#decoder);
70
+ this.#holder.destroy();
71
+ this.#data?.destroy();
72
+ }
73
+ }
74
+ exports.default = Decoder;
@@ -0,0 +1,23 @@
1
+ import { Runtime } from "../runtime";
2
+ export default class Encoder {
3
+ #private;
4
+ constructor(runtime: Runtime, sampleRate: number, channels: number, application: number,
5
+ /**
6
+ * what is the size of the buffer that holds the encoded data
7
+ */
8
+ outBufferLength: number,
9
+ /**
10
+ * how many bytes will we be receiving through encodeFloat() function
11
+ */
12
+ pcmBufferLength: number);
13
+ encoded(): Uint8Array;
14
+ /**
15
+ *
16
+ * @param value
17
+ * @param frameSize
18
+ * @param maxDataBytes
19
+ * @returns encoded sample count
20
+ */
21
+ encodeFloat(value: Float32Array, frameSize: number, maxDataBytes: number): number;
22
+ destroy(): void;
23
+ }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const runtime_1 = require("../runtime");
4
+ class Encoder {
5
+ #errorPointer;
6
+ #error;
7
+ #runtime;
8
+ #encoder;
9
+ #encoded;
10
+ #pcm;
11
+ #holder;
12
+ constructor(runtime, sampleRate, channels, application,
13
+ /**
14
+ * what is the size of the buffer that holds the encoded data
15
+ */
16
+ outBufferLength,
17
+ /**
18
+ * how many bytes will we be receiving through encodeFloat() function
19
+ */
20
+ pcmBufferLength) {
21
+ if (!outBufferLength) {
22
+ throw new Error("outBufferLength must be more than 0");
23
+ }
24
+ this.#holder = new runtime_1.ResourcesHolder();
25
+ this.#error = new runtime_1.Integer(runtime);
26
+ this.#runtime = runtime;
27
+ this.#errorPointer = new runtime_1.Pointer(runtime, this.#error);
28
+ /**
29
+ * pcm buffer
30
+ */
31
+ this.#pcm = new runtime_1.Buffer(runtime, pcmBufferLength);
32
+ /**
33
+ * out buffer
34
+ */
35
+ this.#encoded = new runtime_1.Buffer(runtime, outBufferLength);
36
+ /**
37
+ * add items to resources holder
38
+ */
39
+ this.#holder.add(this.#encoded);
40
+ this.#holder.add(this.#pcm);
41
+ this.#holder.add(this.#errorPointer);
42
+ this.#holder.add(this.#error);
43
+ /**
44
+ * create encoder
45
+ */
46
+ this.#encoder = runtime
47
+ .originalRuntime()
48
+ ._opus_encoder_create(sampleRate, channels, application, this.#errorPointer.value());
49
+ if (this.#error.value() < 0) {
50
+ throw new Error("Failed to create encoder");
51
+ }
52
+ }
53
+ encoded() {
54
+ return this.#encoded.data();
55
+ }
56
+ /**
57
+ *
58
+ * @param value
59
+ * @param frameSize
60
+ * @param maxDataBytes
61
+ * @returns encoded sample count
62
+ */
63
+ encodeFloat(value, frameSize, maxDataBytes) {
64
+ if (maxDataBytes > this.#encoded.size()) {
65
+ throw new Error(`encoded buffer length is ${this.#encoded.size()}, but maxDataBytes is ${maxDataBytes}`);
66
+ }
67
+ this.#pcm
68
+ .data()
69
+ .set(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
70
+ const result = this.#runtime
71
+ .originalRuntime()
72
+ ._opus_encode_float(this.#encoder, this.#pcm.offset(), frameSize, this.#encoded.offset(), maxDataBytes);
73
+ if (result < 0) {
74
+ throw new Error(`Failed to encode float`);
75
+ }
76
+ return result;
77
+ }
78
+ destroy() {
79
+ this.#holder.destroy();
80
+ this.#runtime.originalRuntime()._opus_encoder_destroy(this.#encoder);
81
+ }
82
+ }
83
+ exports.default = Encoder;
@@ -0,0 +1,6 @@
1
+ export default class RingBuffer {
2
+ #private;
3
+ constructor(frameSize: number);
4
+ write(value: Float32Array): void;
5
+ read(): Float32Array | null;
6
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class RingBuffer {
4
+ #arrayBuffer;
5
+ #readOffset;
6
+ #writeOffset;
7
+ #frameSize;
8
+ constructor(frameSize) {
9
+ this.#readOffset = 0;
10
+ this.#writeOffset = 0;
11
+ this.#arrayBuffer = new ArrayBuffer(1024 * 1024 * 4);
12
+ this.#frameSize = frameSize;
13
+ }
14
+ #view() {
15
+ return new Float32Array(this.#arrayBuffer);
16
+ }
17
+ write(value) {
18
+ this.#maybeReallocate(value.length);
19
+ this.#view().set(value, this.#writeOffset);
20
+ this.#writeOffset += value.length;
21
+ }
22
+ read() {
23
+ if (this.#writeOffset >= this.#frameSize) {
24
+ const view = this.#view().subarray(this.#readOffset, this.#readOffset + this.#frameSize);
25
+ this.#readOffset += this.#frameSize;
26
+ if (this.#readOffset >= this.#writeOffset) {
27
+ this.#writeOffset = 0;
28
+ }
29
+ return view;
30
+ }
31
+ return null;
32
+ }
33
+ #maybeReallocate(samples) {
34
+ const sampleCountInBytes = samples * Float32Array.BYTES_PER_ELEMENT;
35
+ if (this.#view().length <= samples) {
36
+ const oldArrayBuffer = this.#arrayBuffer;
37
+ this.#arrayBuffer = new ArrayBuffer(oldArrayBuffer.byteLength + sampleCountInBytes + 1024 * 1024 * 4);
38
+ this.#view().set(new Uint8Array(oldArrayBuffer));
39
+ }
40
+ }
41
+ }
42
+ exports.default = RingBuffer;
@@ -0,0 +1,3 @@
1
+ export { default as Encoder } from './Encoder';
2
+ export { default as Decoder } from './Decoder';
3
+ export { default as RingBuffer } from './RingBuffer';
package/opus/index.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RingBuffer = exports.Decoder = exports.Encoder = void 0;
7
+ var Encoder_1 = require("./Encoder");
8
+ Object.defineProperty(exports, "Encoder", { enumerable: true, get: function () { return __importDefault(Encoder_1).default; } });
9
+ var Decoder_1 = require("./Decoder");
10
+ Object.defineProperty(exports, "Decoder", { enumerable: true, get: function () { return __importDefault(Decoder_1).default; } });
11
+ var RingBuffer_1 = require("./RingBuffer");
12
+ Object.defineProperty(exports, "RingBuffer", { enumerable: true, get: function () { return __importDefault(RingBuffer_1).default; } });
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "devDependencies": {
3
+ "@types/node": "14.x",
4
+ "prettier": "2.x",
5
+ "ts-loader": "9.x",
6
+ "ts-node": "10.x",
7
+ "typescript": "5.x",
8
+ "webpack": "5.x",
9
+ "webpack-cli": "5.x"
10
+ },
11
+ "name": "opus-codec",
12
+ "version": "0.0.1",
13
+ "license": "MIT",
14
+ "files": [
15
+ "{native,runtime,opus}/*.{d.ts,js,wasm}"
16
+ ],
17
+ "scripts": {
18
+ "prepublishOnly": "npx tsc -b opus runtime",
19
+ "test": "npx ts-node test"
20
+ }
21
+ }
@@ -0,0 +1,10 @@
1
+ import { IResource } from "./ResourcesHolder";
2
+ import Runtime from "./Runtime";
3
+ export default class Buffer implements IResource {
4
+ #private;
5
+ constructor(runtime: Runtime, size: number);
6
+ offset(): number;
7
+ data(): Uint8Array;
8
+ size(): number;
9
+ destroy(): void;
10
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Buffer {
4
+ #offset;
5
+ #size;
6
+ #runtime;
7
+ constructor(runtime, size) {
8
+ this.#runtime = runtime;
9
+ this.#size = size;
10
+ this.#offset = runtime.malloc(size);
11
+ }
12
+ offset() {
13
+ return this.#offset;
14
+ }
15
+ data() {
16
+ return this.#runtime.subarray(this.#offset, this.#offset + this.#size);
17
+ }
18
+ size() {
19
+ return this.#size;
20
+ }
21
+ destroy() {
22
+ this.#runtime.free(this.#offset);
23
+ this.#offset = 0;
24
+ }
25
+ }
26
+ exports.default = Buffer;
@@ -0,0 +1,10 @@
1
+ import { IResource } from "./ResourcesHolder";
2
+ import Runtime from "./Runtime";
3
+ export default class Integer implements IResource {
4
+ #private;
5
+ constructor(runtime: Runtime);
6
+ value(): number;
7
+ size(): number;
8
+ offset(): number;
9
+ destroy(): void;
10
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Integer {
4
+ #runtime;
5
+ #offset;
6
+ constructor(runtime) {
7
+ this.#runtime = runtime;
8
+ this.#offset = runtime.malloc(runtime.originalRuntime()._size_of_int());
9
+ }
10
+ value() {
11
+ if (this.#runtime.originalRuntime()._size_of_int() !== 4) {
12
+ throw new Error('invalid integer byte size');
13
+ }
14
+ return this.#runtime.view().getInt32(this.#offset);
15
+ }
16
+ size() {
17
+ return this.#runtime.originalRuntime()._size_of_int();
18
+ }
19
+ offset() {
20
+ return this.#offset;
21
+ }
22
+ destroy() {
23
+ this.#runtime.free(this.#offset);
24
+ this.#offset = 0;
25
+ }
26
+ }
27
+ exports.default = Integer;
@@ -0,0 +1,10 @@
1
+ import Integer from "./Integer";
2
+ import { IResource } from "./ResourcesHolder";
3
+ import Runtime from "./Runtime";
4
+ export default class Pointer implements IResource {
5
+ #private;
6
+ constructor(runtime: Runtime, value: Integer);
7
+ offset(): number;
8
+ destroy(): void;
9
+ value(): number;
10
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Pointer {
4
+ #offset;
5
+ #runtime;
6
+ constructor(runtime, value) {
7
+ this.#runtime = runtime;
8
+ this.#offset = runtime.malloc(runtime.originalRuntime()._size_of_void_ptr());
9
+ this.#runtime.view().setUint32(this.#offset, value.offset(), true);
10
+ }
11
+ offset() {
12
+ return this.#offset;
13
+ }
14
+ destroy() {
15
+ this.#runtime.free(this.#offset);
16
+ }
17
+ value() {
18
+ return this.#runtime.view().getUint32(this.#offset, true);
19
+ }
20
+ }
21
+ exports.default = Pointer;
@@ -0,0 +1,9 @@
1
+ export default class ResourcesHolder {
2
+ #private;
3
+ constructor();
4
+ add(resource: IResource): void;
5
+ destroy(): void;
6
+ }
7
+ export interface IResource {
8
+ destroy(): void;
9
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class ResourcesHolder {
4
+ #resources = new Set();
5
+ constructor() {
6
+ }
7
+ add(resource) {
8
+ this.#resources.add(resource);
9
+ }
10
+ destroy() {
11
+ for (const r of this.#resources) {
12
+ r.destroy();
13
+ }
14
+ }
15
+ }
16
+ exports.default = ResourcesHolder;
@@ -0,0 +1,10 @@
1
+ import { EmscriptenRuntime } from "../native";
2
+ export default class Runtime {
3
+ #private;
4
+ constructor(runtime: EmscriptenRuntime);
5
+ originalRuntime(): EmscriptenRuntime;
6
+ subarray(start: number, end: number): Uint8Array;
7
+ free(offset: number): void;
8
+ view(): DataView;
9
+ malloc(len: number): number;
10
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Runtime {
4
+ #runtime;
5
+ constructor(runtime) {
6
+ this.#runtime = runtime;
7
+ }
8
+ originalRuntime() {
9
+ return this.#runtime;
10
+ }
11
+ subarray(start, end) {
12
+ return this.#runtime.HEAPU8.subarray(start, end);
13
+ }
14
+ free(offset) {
15
+ this.#runtime._free(offset);
16
+ }
17
+ view() {
18
+ return new DataView(this.#runtime.HEAPU8.buffer);
19
+ }
20
+ malloc(len) {
21
+ const offset = this.#runtime._malloc(len);
22
+ if (!offset) {
23
+ throw new Error(`failed to allocate ${len} bytes`);
24
+ }
25
+ return offset;
26
+ }
27
+ }
28
+ exports.default = Runtime;
@@ -0,0 +1,5 @@
1
+ export { default as Integer } from './Integer';
2
+ export { default as Pointer } from './Pointer';
3
+ export { default as Runtime } from './Runtime';
4
+ export { default as Buffer } from './Buffer';
5
+ export { default as ResourcesHolder, IResource } from './ResourcesHolder';
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ResourcesHolder = exports.Buffer = exports.Runtime = exports.Pointer = exports.Integer = void 0;
7
+ var Integer_1 = require("./Integer");
8
+ Object.defineProperty(exports, "Integer", { enumerable: true, get: function () { return __importDefault(Integer_1).default; } });
9
+ var Pointer_1 = require("./Pointer");
10
+ Object.defineProperty(exports, "Pointer", { enumerable: true, get: function () { return __importDefault(Pointer_1).default; } });
11
+ var Runtime_1 = require("./Runtime");
12
+ Object.defineProperty(exports, "Runtime", { enumerable: true, get: function () { return __importDefault(Runtime_1).default; } });
13
+ var Buffer_1 = require("./Buffer");
14
+ Object.defineProperty(exports, "Buffer", { enumerable: true, get: function () { return __importDefault(Buffer_1).default; } });
15
+ var ResourcesHolder_1 = require("./ResourcesHolder");
16
+ Object.defineProperty(exports, "ResourcesHolder", { enumerable: true, get: function () { return __importDefault(ResourcesHolder_1).default; } });