carta1 1.1.9 → 1.2.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 +149 -75
- package/bin/cli.js +8 -4
- package/codec/{coding/bitallocation.js → allocation/solve.js} +131 -97
- package/codec/allocation/source.js +69 -0
- package/codec/allocation/stage.js +38 -0
- package/codec/analysis/bands.js +49 -0
- package/codec/analysis/{transient.js → blocks.js} +90 -47
- package/codec/analysis/spectrum.js +160 -0
- package/codec/analysis/stage.js +32 -0
- package/codec/{browser/interface.js → boundary/browser.js} +1 -1
- package/codec/boundary/container.js +96 -0
- package/codec/boundary/pcm.js +193 -0
- package/codec/boundary/processor.js +208 -0
- package/codec/{io/readers.js → boundary/reader.js} +2 -1
- package/codec/boundary/stream.js +361 -0
- package/codec/{browser → boundary}/worker.js +45 -42
- package/codec/core/constants.js +9 -131
- package/codec/core/geometry.js +25 -0
- package/codec/core/tables.js +117 -0
- package/codec/dequantization.js +54 -0
- package/codec/index.js +12 -11
- package/codec/pipeline/decoder.js +10 -399
- package/codec/pipeline/encoder.js +12 -434
- package/codec/quantization/spectrum.js +67 -0
- package/codec/quantization/stage.js +45 -0
- package/codec/{transforms/qmf.js → signal/bands.js} +8 -5
- package/codec/{transforms → signal}/fft.js +1 -1
- package/codec/{transforms/mdct.js → signal/spectrum.js} +16 -1
- package/codec/{core/buffers.js → state.js} +46 -35
- package/codec/{io → syntax}/bitstream.js +28 -9
- package/codec/{io/serialization.js → syntax/frame.js} +5 -101
- package/codec/synthesis/bands.js +201 -0
- package/codec/synthesis/pcm.js +50 -0
- package/codec/synthesis/stage.js +17 -0
- package/codec/utils.js +9 -52
- package/dist/carta1-worker-interface.min.js +1 -1
- package/dist/carta1-worker-interface.min.js.map +1 -1
- package/dist/carta1-worker.min.js +1 -1
- package/dist/carta1-worker.min.js.map +1 -1
- package/dist/carta1.min.js +1 -1
- package/dist/carta1.min.js.map +1 -1
- package/package.json +16 -16
- package/codec/coding/quantization.js +0 -149
- package/codec/io/processor.js +0 -558
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "carta1",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "An ATRAC1 audio codec implementation in
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "An ATRAC1 audio codec implementation in JavaScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "codec/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"lint": "eslint bin/ codec/ tests/",
|
|
23
23
|
"format": "prettier --write .",
|
|
24
24
|
"build": "webpack --config webpack.config.js",
|
|
25
|
-
"
|
|
25
|
+
"check": "npm run lint && npm test && npm run build",
|
|
26
|
+
"prepublishOnly": "npm run check"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
29
|
"cli-progress": "^3.12.0",
|
|
29
|
-
"
|
|
30
|
-
"commander": "^11.0.0",
|
|
30
|
+
"commander": "^11.1.0",
|
|
31
31
|
"wav": "^1.0.2"
|
|
32
32
|
},
|
|
33
33
|
"engines": {
|
|
@@ -54,18 +54,18 @@
|
|
|
54
54
|
},
|
|
55
55
|
"homepage": "https://github.com/aynik/carta1#readme",
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@babel/core": "^7.
|
|
58
|
-
"@babel/preset-env": "^7.
|
|
59
|
-
"babel-loader": "^10.
|
|
60
|
-
"eslint": "^9.
|
|
61
|
-
"eslint-config-prettier": "^10.1.
|
|
62
|
-
"eslint-plugin-prettier": "^5.5.
|
|
57
|
+
"@babel/core": "^7.29.7",
|
|
58
|
+
"@babel/preset-env": "^7.29.7",
|
|
59
|
+
"babel-loader": "^10.1.1",
|
|
60
|
+
"eslint": "^9.39.5",
|
|
61
|
+
"eslint-config-prettier": "^10.1.8",
|
|
62
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
63
63
|
"husky": "^9.1.7",
|
|
64
|
-
"lint-staged": "^16.
|
|
65
|
-
"prettier": "^3.6
|
|
66
|
-
"terser-webpack-plugin": "^5.
|
|
67
|
-
"vitest": "^3.2.
|
|
68
|
-
"webpack": "^5.
|
|
64
|
+
"lint-staged": "^16.4.0",
|
|
65
|
+
"prettier": "^3.9.6",
|
|
66
|
+
"terser-webpack-plugin": "^5.6.1",
|
|
67
|
+
"vitest": "^3.2.7",
|
|
68
|
+
"webpack": "^5.109.2",
|
|
69
69
|
"webpack-cli": "^6.0.1"
|
|
70
70
|
},
|
|
71
71
|
"lint-staged": {
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Carta1 Audio Codec - Quantization Module
|
|
3
|
-
*
|
|
4
|
-
* This module handles the quantization and dequantization of MDCT frequency coefficients
|
|
5
|
-
* for the Carta1 audio codec. It provides functions to convert floating-point frequency
|
|
6
|
-
* domain data into integer representations suitable for bitstream encoding.
|
|
7
|
-
*
|
|
8
|
-
* Key functions:
|
|
9
|
-
* - Quantization of coefficients using scale factors and bit depths
|
|
10
|
-
* - Dequantization for reconstruction during decoding
|
|
11
|
-
* - BFU (Band Frequency Unit) organization for psychoacoustic processing
|
|
12
|
-
*
|
|
13
|
-
* The quantization process uses configurable scale factors to maintain audio quality
|
|
14
|
-
* while achieving the target compression ratio. The module supports both uniform
|
|
15
|
-
* and non-uniform quantization schemes based on perceptual importance.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
SPECS_PER_BFU,
|
|
20
|
-
BFU_START_LONG,
|
|
21
|
-
BFU_START_SHORT,
|
|
22
|
-
BFU_BAND_BOUNDARIES,
|
|
23
|
-
SCALE_FACTORS,
|
|
24
|
-
QUANTIZATION_SIGN_BIT_SHIFT,
|
|
25
|
-
} from '../core/constants.js'
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Quantize coefficients.
|
|
29
|
-
* @param {Float32Array} coefficients
|
|
30
|
-
* @param {number} scaleFactorIndex
|
|
31
|
-
* @param {number} bitsPerSample
|
|
32
|
-
* @returns {Int32Array} out
|
|
33
|
-
*/
|
|
34
|
-
export function quantize(coefficients, scaleFactorIndex, bitsPerSample) {
|
|
35
|
-
const length = coefficients.length
|
|
36
|
-
const out = new Int32Array(length)
|
|
37
|
-
if (bitsPerSample === 0 || scaleFactorIndex === 0) {
|
|
38
|
-
out.fill(0, 0, length)
|
|
39
|
-
return out
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const scaleFactor = SCALE_FACTORS[scaleFactorIndex]
|
|
43
|
-
const quantRange = (1 << (bitsPerSample - QUANTIZATION_SIGN_BIT_SHIFT)) - 1
|
|
44
|
-
const normFactor = quantRange / scaleFactor
|
|
45
|
-
|
|
46
|
-
const hi = quantRange
|
|
47
|
-
const lo = -quantRange
|
|
48
|
-
|
|
49
|
-
for (let i = 0; i < length; i++) {
|
|
50
|
-
const x = coefficients[i] * normFactor
|
|
51
|
-
const y = (x + (x >= 0 ? 0.5 : -0.5)) | 0
|
|
52
|
-
out[i] = y > hi ? hi : y < lo ? lo : y
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return out
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Dequantize coefficients.
|
|
60
|
-
* @param {Int32Array} quantized
|
|
61
|
-
* @param {number} scaleFactorIndex
|
|
62
|
-
* @param {number} bitsPerSample
|
|
63
|
-
* @returns {Float32Array}
|
|
64
|
-
*/
|
|
65
|
-
export function dequantize(quantized, scaleFactorIndex, bitsPerSample) {
|
|
66
|
-
if (bitsPerSample === 0 || scaleFactorIndex === 0) {
|
|
67
|
-
return new Float32Array(quantized.length)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const scaleFactor = SCALE_FACTORS[scaleFactorIndex]
|
|
71
|
-
const quantRange = (1 << (bitsPerSample - QUANTIZATION_SIGN_BIT_SHIFT)) - 1
|
|
72
|
-
|
|
73
|
-
const deq = new Float32Array(quantized.length)
|
|
74
|
-
for (let i = 0; i < quantized.length; i++) {
|
|
75
|
-
deq[i] = (quantized[i] * scaleFactor) / quantRange
|
|
76
|
-
}
|
|
77
|
-
return deq
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Groups MDCT coefficients into Band Frequency Units (BFUs) for bit allocation.
|
|
82
|
-
*
|
|
83
|
-
* This function organizes frequency-domain coefficients into perceptually meaningful
|
|
84
|
-
* frequency bands (BFUs) based on the block modes for each of the three frequency bands.
|
|
85
|
-
* It handles both long and short blocks, with different frequency resolutions and
|
|
86
|
-
* BFU start positions for each block type.
|
|
87
|
-
*
|
|
88
|
-
* The function implements copy-avoidance optimization: when a BFU slice is fully
|
|
89
|
-
* contained within a frequency band, it directly copies the data without buffer
|
|
90
|
-
* filling. For BFUs that span band boundaries or extend beyond the available
|
|
91
|
-
* coefficients, it handles partial copying and zero-padding appropriately.
|
|
92
|
-
*
|
|
93
|
-
* Frequency Band Structure:
|
|
94
|
-
* - Band 0: 0-128 coefficients (low frequencies)
|
|
95
|
-
* - Band 1: 128-256 coefficients (mid frequencies)
|
|
96
|
-
* - Band 2: 256-512 coefficients (high frequencies)
|
|
97
|
-
*
|
|
98
|
-
* Block Types:
|
|
99
|
-
* - Long blocks (mode 0): Higher frequency resolution, fewer temporal segments
|
|
100
|
-
* - Short blocks (mode 1): Lower frequency resolution, more temporal segments
|
|
101
|
-
*
|
|
102
|
-
* @param {Float32Array} coefficients
|
|
103
|
-
* @param {Array<number>} blockModes
|
|
104
|
-
* @returns {{bfuData: Array<Float32Array>, bfuSizes: Array<number>, bfuCount: number}}
|
|
105
|
-
*/
|
|
106
|
-
export function groupIntoBFUs(coefficients, blockModes) {
|
|
107
|
-
const bfuData = []
|
|
108
|
-
const bfuSizes = []
|
|
109
|
-
|
|
110
|
-
let coeffIndex = 0
|
|
111
|
-
let bfuIndex = 0
|
|
112
|
-
|
|
113
|
-
for (let band = 0; band < 3; band++) {
|
|
114
|
-
const bandStart = coeffIndex
|
|
115
|
-
const bandSize = band === 2 ? 256 : 128
|
|
116
|
-
const bandEnd = band < 2 ? BFU_BAND_BOUNDARIES[band] : SPECS_PER_BFU.length
|
|
117
|
-
const isLongBlock = blockModes[band] === 0
|
|
118
|
-
const startPositions = isLongBlock ? BFU_START_LONG : BFU_START_SHORT
|
|
119
|
-
|
|
120
|
-
while (bfuIndex < bandEnd) {
|
|
121
|
-
const size = SPECS_PER_BFU[bfuIndex]
|
|
122
|
-
const startPos = startPositions[bfuIndex] - bandStart
|
|
123
|
-
const endPos = startPos + size
|
|
124
|
-
const bfu = new Float32Array(size)
|
|
125
|
-
|
|
126
|
-
if (startPos >= 0 && endPos <= bandSize) {
|
|
127
|
-
bfu.set(coefficients.subarray(bandStart + startPos, bandStart + endPos))
|
|
128
|
-
} else {
|
|
129
|
-
bfu.fill(0)
|
|
130
|
-
if (startPos < bandSize && endPos > 0) {
|
|
131
|
-
const srcStart = Math.max(0, startPos)
|
|
132
|
-
const srcEnd = Math.min(bandSize, endPos)
|
|
133
|
-
bfu.set(
|
|
134
|
-
coefficients.subarray(bandStart + srcStart, bandStart + srcEnd),
|
|
135
|
-
Math.max(0, -startPos)
|
|
136
|
-
)
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
bfuData.push(bfu)
|
|
141
|
-
bfuSizes.push(size)
|
|
142
|
-
bfuIndex++
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
coeffIndex += bandSize
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return { bfuData, bfuSizes, bfuCount: bfuIndex }
|
|
149
|
-
}
|