carta1 1.1.1 → 1.1.2

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/bin/cli.js CHANGED
@@ -156,7 +156,7 @@ class ProgressTracker {
156
156
  * Provides async iteration over WAV file frames for memory-efficient
157
157
  * processing of large audio files. Automatically handles:
158
158
  * - Multi-channel deinterleaving
159
- * - Bit depth conversion to float32
159
+ * - Bit depth conversion to Float64
160
160
  * - Frame padding for the last partial frame
161
161
  *
162
162
  * @class
@@ -225,9 +225,9 @@ class WavReader {
225
225
  * Async iterator for streaming WAV file frames
226
226
  *
227
227
  * @param {number} [frameSize=SAMPLES_PER_FRAME] - Samples per frame
228
- * @yields {Float32Array|Array<Float32Array>} Audio frame data
229
- * - Mono: Float32Array of samples
230
- * - Stereo: [left, right] Float32Arrays
228
+ * @yields {Float64Array|Array<Float64Array>} Audio frame data
229
+ * - Mono: Float64Array of samples
230
+ * - Stereo: [left, right] Float64Arrays
231
231
  */
232
232
  async *[Symbol.asyncIterator](frameSize = SAMPLES_PER_FRAME) {
233
233
  const fileStream = fs.createReadStream(this.filePath)
@@ -305,23 +305,23 @@ class WavReader {
305
305
  }
306
306
 
307
307
  /**
308
- * Process raw PCM buffer into float32 frame data
308
+ * Process raw PCM buffer into float64 frame data
309
309
  *
310
310
  * @private
311
311
  * @param {Buffer} frameBuffer - Raw PCM data
312
312
  * @param {number} frameSize - Number of samples per channel
313
- * @returns {Float32Array|Array<Float32Array>} Processed frame data
313
+ * @returns {Float64Array|Array<Float64Array>} Processed frame data
314
314
  */
315
315
  _processFrameBuffer(frameBuffer, frameSize) {
316
316
  if (this.channels === 1) {
317
- const frame = new Float32Array(frameSize)
317
+ const frame = new Float64Array(frameSize)
318
318
  for (let i = 0; i < frameSize; i++) {
319
319
  frame[i] = this._sampleToFloat(frameBuffer, i * (this.bitDepth / 8))
320
320
  }
321
321
  return frame
322
322
  } else {
323
- const left = new Float32Array(frameSize)
324
- const right = new Float32Array(frameSize)
323
+ const left = new Float64Array(frameSize)
324
+ const right = new Float64Array(frameSize)
325
325
  for (let i = 0; i < frameSize; i++) {
326
326
  const offset = i * this.channels * (this.bitDepth / 8)
327
327
  left[i] = this._sampleToFloat(frameBuffer, offset)
@@ -332,7 +332,7 @@ class WavReader {
332
332
  }
333
333
 
334
334
  /**
335
- * Convert PCM sample to normalized float32 value
335
+ * Convert PCM sample to normalized Float64 value
336
336
  *
337
337
  * @private
338
338
  * @param {Buffer} buffer - PCM data buffer
@@ -10,13 +10,13 @@ import { FFT } from '../transforms/fft.js'
10
10
 
11
11
  /**
12
12
  * Perform FFT on time-domain samples and return magnitude spectrum
13
- * @param {Float32Array} samples - Time-domain samples
13
+ * @param {Float64Array} samples - Time-domain samples
14
14
  * @param {number} fftSize - FFT size (must be power of 2)
15
- * @returns {Float32Array} Magnitude spectrum (positive frequencies only)
15
+ * @returns {Float64Array} Magnitude spectrum (positive frequencies only)
16
16
  */
17
17
  export function performFFT(samples, fftSize) {
18
- const real = new Float32Array(fftSize)
19
- const imag = new Float32Array(fftSize)
18
+ const real = new Float64Array(fftSize)
19
+ const imag = new Float64Array(fftSize)
20
20
 
21
21
  // Copy samples with zero-padding if necessary
22
22
  const copyLen = Math.min(samples.length, fftSize)
@@ -26,7 +26,7 @@ export function performFFT(samples, fftSize) {
26
26
  FFT.fft(real, imag)
27
27
 
28
28
  // Calculate magnitude spectrum for positive frequencies
29
- const magnitude = new Float32Array(fftSize / 2)
29
+ const magnitude = new Float64Array(fftSize / 2)
30
30
  for (let i = 0; i < fftSize / 2; i++) {
31
31
  magnitude[i] = Math.sqrt(real[i] * real[i] + imag[i] * imag[i])
32
32
  }
@@ -36,8 +36,8 @@ export function performFFT(samples, fftSize) {
36
36
 
37
37
  /**
38
38
  * Detect transients by analyzing spectral changes between frames
39
- * @param {Float32Array} currentCoeffs - Current frame coefficients
40
- * @param {Float32Array} prevCoeffs - Previous frame coefficients
39
+ * @param {Float64Array} currentCoeffs - Current frame coefficients
40
+ * @param {Float64Array} prevCoeffs - Previous frame coefficients
41
41
  * @param {number} threshold - Detection threshold
42
42
  * @returns {boolean} True if transient detected
43
43
  */
@@ -56,8 +56,8 @@ export function detectTransient(currentCoeffs, prevCoeffs, threshold) {
56
56
 
57
57
  /**
58
58
  * Calculate all spectral features for transient detection
59
- * @param {Float32Array} currentCoeffs - Current frame coefficients
60
- * @param {Float32Array} prevCoeffs - Previous frame coefficients
59
+ * @param {Float64Array} currentCoeffs - Current frame coefficients
60
+ * @param {Float64Array} prevCoeffs - Previous frame coefficients
61
61
  * @returns {Object} Computed spectral features
62
62
  */
63
63
  function calculateSpectralFeatures(currentCoeffs, prevCoeffs) {
@@ -114,7 +114,7 @@ function calculateSpectralFlux(currentCoeffs, prevCoeffs) {
114
114
  /**
115
115
  * Calculate spectral flatness (geometric mean / arithmetic mean)
116
116
  * Measures how noise-like vs tonal the spectrum is
117
- * @param {Float32Array} coeffs - Spectral coefficients
117
+ * @param {Float64Array} coeffs - Spectral coefficients
118
118
  * @returns {number} Flatness measure (0 = tonal, 1 = noise-like)
119
119
  */
120
120
  function calculateSpectralFlatness(coeffs) {
@@ -143,7 +143,7 @@ function calculateSpectralFlatness(coeffs) {
143
143
  /**
144
144
  * Calculate ratio of high-frequency to total energy
145
145
  * High values indicate bright/harsh sounds that are perceptually important
146
- * @param {Float32Array} coeffs - Spectral coefficients
146
+ * @param {Float64Array} coeffs - Spectral coefficients
147
147
  * @returns {number} High-frequency energy ratio (0-1)
148
148
  */
149
149
  function calculateHighFrequencyRatio(coeffs) {
@@ -165,8 +165,8 @@ function calculateHighFrequencyRatio(coeffs) {
165
165
 
166
166
  /**
167
167
  * Calculate energy change between frames in dB
168
- * @param {Float32Array} currentCoeffs - Current frame coefficients
169
- * @param {Float32Array} prevCoeffs - Previous frame coefficients
168
+ * @param {Float64Array} currentCoeffs - Current frame coefficients
169
+ * @param {Float64Array} prevCoeffs - Previous frame coefficients
170
170
  * @returns {number} Energy change in dB (positive values only)
171
171
  */
172
172
  function calculateEnergyChange(currentCoeffs, prevCoeffs) {
@@ -64,9 +64,9 @@ class Carta1Worker {
64
64
  /**
65
65
  * Encode PCM audio to ATRAC1 format
66
66
  *
67
- * @param {Float32Array|Array<Float32Array>} pcmData - PCM audio data
68
- * - Mono: Float32Array
69
- * - Stereo: [left, right] Float32Arrays
67
+ * @param {Float64Array|Array<Float64Array>} pcmData - PCM audio data
68
+ * - Mono: Float64Array
69
+ * - Stereo: [left, right] Float64Arrays
70
70
  * @param {Object} [options={}] - Encoder options
71
71
  * @param {number} [options.transientThresholdLow] - Low band transient threshold
72
72
  * @param {number} [options.transientThresholdMid] - Mid band transient threshold
@@ -56,7 +56,7 @@ self.onmessage = async (e) => {
56
56
  /**
57
57
  * Encode PCM audio data to ATRAC1 format
58
58
  *
59
- * @param {Array<Float32Array>} pcmData - PCM audio data [mono] or [left, right]
59
+ * @param {Array<Float64Array>} pcmData - PCM audio data [mono] or [left, right]
60
60
  * @param {Object} options - Encoder options
61
61
  * @returns {Promise<Object>} Encoded AEA blob
62
62
  */
@@ -35,7 +35,7 @@ import {
35
35
 
36
36
  /**
37
37
  * Allocate bits to BFUs using optimized greedy Lp-RDO
38
- * @param {Array<Float32Array>} bfuData
38
+ * @param {Array<Float64Array>} bfuData
39
39
  * @param {Int32Array} bfuSizes
40
40
  * @param {number} maxBfuCount
41
41
  * @returns {{bfuCount:number, allocation:Int32Array, scaleFactorIndices:Int32Array}}
@@ -62,7 +62,7 @@ export function allocateBits(bfuData, bfuSizes, maxBfuCount) {
62
62
  * bits to the BFUs that provide the greatest distortion reduction per bit spent.
63
63
  *
64
64
  * @param {number} activeBfuCount
65
- * @param {Array<Float32Array>} bfuData
65
+ * @param {Array<Float64Array>} bfuData
66
66
  * @param {Int32Array} bfuSizes
67
67
  * @param {number} remainingBits
68
68
  * @returns {{wordLengths: Int32Array, scaleFactorIndices: Int32Array}}
@@ -150,7 +150,7 @@ function distributeBitsRDO(activeBfuCount, bfuData, bfuSizes, remainingBits) {
150
150
  /**
151
151
  * Find the optimal scale factor index for a set of coefficients.
152
152
  * Same semantics as the original.
153
- * @param {Float32Array} coefficients
153
+ * @param {Float64Array} coefficients
154
154
  * @returns {number}
155
155
  */
156
156
  export function findScaleFactor(coefficients) {
@@ -26,7 +26,7 @@ import {
26
26
 
27
27
  /**
28
28
  * Quantize coefficients.
29
- * @param {Float32Array} coefficients
29
+ * @param {Float64Array} coefficients
30
30
  * @param {number} scaleFactorIndex
31
31
  * @param {number} bitsPerSample
32
32
  * @returns {Int32Array} out
@@ -35,7 +35,6 @@ export function quantize(coefficients, scaleFactorIndex, bitsPerSample) {
35
35
  const length = coefficients.length
36
36
  const out = new Int32Array(length)
37
37
  if (bitsPerSample === 0 || scaleFactorIndex === 0) {
38
- // Zero fast path
39
38
  out.fill(0, 0, length)
40
39
  return out
41
40
  }
@@ -45,7 +44,7 @@ export function quantize(coefficients, scaleFactorIndex, bitsPerSample) {
45
44
  const normFactor = quantRange / scaleFactor
46
45
 
47
46
  const hi = quantRange
48
- const lo = -quantRange - 1
47
+ const lo = -quantRange
49
48
 
50
49
  for (let i = 0; i < length; i++) {
51
50
  const x = coefficients[i] * normFactor
@@ -61,20 +60,19 @@ export function quantize(coefficients, scaleFactorIndex, bitsPerSample) {
61
60
  * @param {Int32Array} quantized
62
61
  * @param {number} scaleFactorIndex
63
62
  * @param {number} bitsPerSample
64
- * @returns {Float32Array}
63
+ * @returns {Float64Array}
65
64
  */
66
65
  export function dequantize(quantized, scaleFactorIndex, bitsPerSample) {
67
66
  if (bitsPerSample === 0 || scaleFactorIndex === 0) {
68
- return new Float32Array(quantized.length)
67
+ return new Float64Array(quantized.length)
69
68
  }
70
69
 
71
70
  const scaleFactor = SCALE_FACTORS[scaleFactorIndex]
72
71
  const quantRange = (1 << (bitsPerSample - QUANTIZATION_SIGN_BIT_SHIFT)) - 1
73
- const denormFactor = scaleFactor / quantRange
74
72
 
75
- const deq = new Float32Array(quantized.length)
73
+ const deq = new Float64Array(quantized.length)
76
74
  for (let i = 0; i < quantized.length; i++) {
77
- deq[i] = quantized[i] * denormFactor
75
+ deq[i] = (quantized[i] * scaleFactor) / quantRange
78
76
  }
79
77
  return deq
80
78
  }
@@ -101,9 +99,9 @@ export function dequantize(quantized, scaleFactorIndex, bitsPerSample) {
101
99
  * - Long blocks (mode 0): Higher frequency resolution, fewer temporal segments
102
100
  * - Short blocks (mode 1): Lower frequency resolution, more temporal segments
103
101
  *
104
- * @param {Float32Array} coefficients
102
+ * @param {Float64Array} coefficients
105
103
  * @param {Array<number>} blockModes
106
- * @returns {{bfuData: Array<Float32Array>, bfuSizes: Array<number>, bfuCount: number}}
104
+ * @returns {{bfuData: Array<Float64Array>, bfuSizes: Array<number>, bfuCount: number}}
107
105
  */
108
106
  export function groupIntoBFUs(coefficients, blockModes) {
109
107
  const bfuData = []
@@ -123,7 +121,7 @@ export function groupIntoBFUs(coefficients, blockModes) {
123
121
  const size = SPECS_PER_BFU[bfuIndex]
124
122
  const startPos = startPositions[bfuIndex] - bandStart
125
123
  const endPos = startPos + size
126
- const bfu = new Float32Array(size)
124
+ const bfu = new Float64Array(size)
127
125
 
128
126
  if (startPos >= 0 && endPos <= bandSize) {
129
127
  bfu.set(coefficients.subarray(bandStart + startPos, bandStart + endPos))
@@ -8,74 +8,74 @@ export class BufferPool {
8
8
  constructor() {
9
9
  // Transform buffers
10
10
  this.transformBuffers = {
11
- 64: new Float32Array(64),
12
- 128: new Float32Array(128),
13
- 256: new Float32Array(256),
14
- 512: new Float32Array(512),
11
+ 64: new Float64Array(64),
12
+ 128: new Float64Array(128),
13
+ 256: new Float64Array(256),
14
+ 512: new Float64Array(512),
15
15
  }
16
16
 
17
17
  // QMF work buffers
18
18
  this.qmfWorkBuffers = {
19
19
  delay: {
20
- 128: new Float32Array(QMF_DELAY + 128),
21
- 256: new Float32Array(QMF_DELAY + 256),
22
- 512: new Float32Array(QMF_DELAY + 512),
20
+ 128: new Float64Array(QMF_DELAY + 128),
21
+ 256: new Float64Array(QMF_DELAY + 256),
22
+ 512: new Float64Array(QMF_DELAY + 512),
23
23
  },
24
24
  highBandDelay: {
25
- 128: new Float32Array(QMF_HIGH_BAND_DELAY + 128),
26
- 256: new Float32Array(QMF_HIGH_BAND_DELAY + 256),
25
+ 128: new Float64Array(QMF_HIGH_BAND_DELAY + 128),
26
+ 256: new Float64Array(QMF_HIGH_BAND_DELAY + 256),
27
27
  },
28
28
  }
29
29
 
30
30
  // QMF delay lines
31
31
  this.qmfDelays = {
32
- lowBand: new Float32Array(QMF_DELAY),
33
- midBand: new Float32Array(QMF_DELAY),
34
- highBand: new Float32Array(QMF_HIGH_BAND_DELAY),
32
+ lowBand: new Float64Array(QMF_DELAY),
33
+ midBand: new Float64Array(QMF_DELAY),
34
+ highBand: new Float64Array(QMF_HIGH_BAND_DELAY),
35
35
  }
36
36
 
37
37
  // Transient detector
38
38
  this.transientDetection = [
39
- new Float32Array(64),
40
- new Float32Array(64),
41
- new Float32Array(128),
39
+ new Float64Array(64),
40
+ new Float64Array(64),
41
+ new Float64Array(128),
42
42
  ]
43
43
 
44
44
  // MDCT/IMDCT work buffers
45
45
  this.mdctBuffers = {
46
46
  16: {
47
- real: new Float32Array(16),
48
- imag: new Float32Array(16),
47
+ real: new Float64Array(16),
48
+ imag: new Float64Array(16),
49
49
  },
50
50
  64: {
51
- real: new Float32Array(64),
52
- imag: new Float32Array(64),
51
+ real: new Float64Array(64),
52
+ imag: new Float64Array(64),
53
53
  },
54
54
  128: {
55
- real: new Float32Array(128),
56
- imag: new Float32Array(128),
55
+ real: new Float64Array(128),
56
+ imag: new Float64Array(128),
57
57
  },
58
58
  }
59
59
 
60
- // MDCT overlap buffers (encoder)
60
+ // MDCT overlap buffers
61
61
  this.mdctOverlap = [
62
- new Float32Array(32),
63
- new Float32Array(32),
64
- new Float32Array(32),
62
+ new Float64Array(32),
63
+ new Float64Array(32),
64
+ new Float64Array(32),
65
65
  ]
66
66
 
67
- // IMDCT overlap buffers (decoder)
67
+ // IMDCT overlap buffers
68
68
  this.imdctOverlap = [
69
- new Float32Array(256),
70
- new Float32Array(256),
71
- new Float32Array(512),
69
+ new Float64Array(256),
70
+ new Float64Array(256),
71
+ new Float64Array(512),
72
72
  ]
73
73
 
74
74
  // Spectrum reversal buffers
75
75
  this.reversalBuffers = {
76
- 32: new Float32Array(32),
77
- 128: new Float32Array(128),
78
- 256: new Float32Array(256),
76
+ 32: new Float64Array(32),
77
+ 128: new Float64Array(128),
78
+ 256: new Float64Array(256),
79
79
  }
80
80
  }
81
81
  }
@@ -38,7 +38,7 @@ export const BFU_AMOUNTS = new Int32Array([20, 28, 32, 36, 40, 44, 48, 52])
38
38
  export const BFU_BAND_BOUNDARIES = new Int32Array([20, 36, 52])
39
39
 
40
40
  // BFU center frequencies (Hz)
41
- export const BFU_FREQUENCIES = new Float32Array([
41
+ export const BFU_FREQUENCIES = new Float64Array([
42
42
  172.3, 516.8, 861.3, 1205.9, 1464.3, 1636.5, 1808.8, 1981.1, 2239.5, 2584.0,
43
43
  2928.5, 3273.0, 3574.5, 3832.9, 4091.3, 4349.7, 4608.1, 4866.5, 5124.9,
44
44
  5383.3, 5641.7, 5900.1, 6158.5, 6416.9, 6696.8, 6998.3, 7299.8, 7601.2,
@@ -69,7 +69,7 @@ export const MDCT_SIZE_LONG = 512
69
69
 
70
70
  // Window functions
71
71
  export const WINDOW_SHORT = (() => {
72
- const table = new Float32Array(32)
72
+ const table = new Float64Array(32)
73
73
  for (let i = 0; i < 32; i++) {
74
74
  table[i] = Math.sin(((i + 0.5) * Math.PI) / 64)
75
75
  }
@@ -82,7 +82,7 @@ export const QMF_DELAY = 46
82
82
  export const QMF_HIGH_BAND_DELAY = 39
83
83
 
84
84
  // QMF prototype filter coefficients
85
- export const QMF_COEFFS = new Float32Array([
85
+ export const QMF_COEFFS = new Float64Array([
86
86
  -0.00001461907, -0.00009205479, -0.000056157569, 0.00030117269, 0.0002422519,
87
87
  -0.00085293897, -0.0005205574, 0.0020340169, 0.00078333891, -0.0042153862,
88
88
  -0.00075614988, 0.0078402944, -0.000061169922, -0.01344162, 0.0024626821,
@@ -92,7 +92,7 @@ export const QMF_COEFFS = new Float32Array([
92
92
 
93
93
  // QMF window function
94
94
  export const QMF_WINDOW = (() => {
95
- const window = new Float32Array(QMF_TAPS)
95
+ const window = new Float64Array(QMF_TAPS)
96
96
  for (let i = 0; i < 24; i++) {
97
97
  window[i] = QMF_COEFFS[i] * 2.0
98
98
  window[47 - i] = QMF_COEFFS[i] * 2.0
@@ -102,7 +102,7 @@ export const QMF_WINDOW = (() => {
102
102
 
103
103
  // QMF even/odd taps for optimization
104
104
  export const QMF_EVEN = (() => {
105
- const even = new Float32Array(24)
105
+ const even = new Float64Array(24)
106
106
  for (let i = 0; i < 24; i++) {
107
107
  even[i] = QMF_WINDOW[i * 2]
108
108
  }
@@ -110,47 +110,13 @@ export const QMF_EVEN = (() => {
110
110
  })()
111
111
 
112
112
  export const QMF_ODD = (() => {
113
- const odd = new Float32Array(24)
113
+ const odd = new Float64Array(24)
114
114
  for (let i = 0; i < 24; i++) {
115
115
  odd[i] = QMF_WINDOW[i * 2 + 1]
116
116
  }
117
117
  return odd
118
118
  })()
119
119
 
120
- // Psychoacoustic model
121
- export const BARK_SCALE = (() => {
122
- const table = new Float32Array(NUM_BFUS)
123
- for (let i = 0; i < NUM_BFUS; i++) {
124
- const freq = BFU_FREQUENCIES[i]
125
- table[i] =
126
- 13.0 * Math.atan(0.00076 * freq) + 3.5 * Math.atan((freq / 7500) ** 2)
127
- }
128
- return table
129
- })()
130
-
131
- export const SPREADING_MATRIX = (() => {
132
- const matrix = new Float32Array(NUM_BFUS * NUM_BFUS)
133
- for (let masker = 0; masker < NUM_BFUS; masker++) {
134
- for (let masked = 0; masked < NUM_BFUS; masked++) {
135
- const distance = BARK_SCALE[masker] - BARK_SCALE[masked]
136
- let spreading = -100.0
137
-
138
- if (distance >= -3.0 && distance < -1.0) {
139
- spreading = 17.0 * (distance + 3.0) - 70.0
140
- } else if (distance >= -1.0 && distance < 0) {
141
- spreading = 36.0 * distance
142
- } else if (distance >= 0 && distance < 1.0) {
143
- spreading = -27.0 * distance
144
- } else if (distance >= 1.0 && distance < 8.0) {
145
- spreading = -(distance - 1.0) * 4.0 - 27.0
146
- }
147
-
148
- matrix[masker * NUM_BFUS + masked] = spreading
149
- }
150
- }
151
- return matrix
152
- })()
153
-
154
120
  // FFT sizes for transient detection
155
121
  export const FFT_SIZE_LOW = 128
156
122
  export const FFT_SIZE_MID = 128
@@ -167,9 +133,6 @@ export const MDCT_SHORT_BLOCK_SIZE = 32
167
133
  export const MDCT_OVERLAP_SIZE = 32
168
134
  export const MDCT_TAIL_WINDOW_SIZE = 16
169
135
 
170
- // Quantization
171
- export const QUANTIZATION_SIGN_BIT_SHIFT = 1
172
-
173
136
  // WAV format
174
137
  export const WAV_HEADER_SIZE = 44
175
138
  export const WAV_BYTES_PER_SAMPLE = 2
@@ -184,40 +147,20 @@ export const FRAME_WORD_LENGTH_BITS = 4
184
147
  export const FRAME_SCALE_FACTOR_BITS = 6
185
148
 
186
149
  // Quantization
150
+ export const QUANTIZATION_SIGN_BIT_SHIFT = 1
187
151
  export const MAX_WORD_LENGTH_INDEX = 15
188
152
  export const WORD_LENGTH_BITS = new Int32Array([
189
153
  0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
190
154
  ])
191
- export const QUANT_DISTORTION_TABLE = (() => {
192
- const table = new Float32Array(MAX_WORD_LENGTH_INDEX + 1)
193
- table[0] = 1.0
194
- for (let wl = 1; wl <= MAX_WORD_LENGTH_INDEX; wl++) {
195
- const bitsPerSample = WORD_LENGTH_BITS[wl]
196
- const quantRange = (1 << (bitsPerSample - 1)) - 1
197
- table[wl] = 1.0 / (12.0 * quantRange * quantRange)
198
- }
199
- return table
200
- })()
201
- export const DISTORTION_DELTA_DB = (() => {
202
- const table = new Float32Array(MAX_WORD_LENGTH_INDEX)
203
- for (let i = 0; i < MAX_WORD_LENGTH_INDEX; i++) {
204
- table[i] =
205
- 10 *
206
- Math.log10(
207
- QUANT_DISTORTION_TABLE[i + 1] / (QUANT_DISTORTION_TABLE[i] || 1.0)
208
- )
209
- }
210
- return table
211
- })()
212
155
  export const SCALE_FACTORS = (() => {
213
- const table = new Float32Array(64)
156
+ const table = new Float64Array(64)
214
157
  for (let i = 0; i < 64; i++) {
215
158
  table[i] = Math.pow(2.0, i / 3.0 - 21)
216
159
  }
217
160
  return table
218
161
  })()
219
162
 
220
- // RDO bit allocation
163
+ // Bit allocation
221
164
  export const INV_POWER_OF_TWO = (() => {
222
165
  const maxBits = WORD_LENGTH_BITS[MAX_WORD_LENGTH_INDEX]
223
166
  const table = new Float64Array(maxBits + 1)
@@ -43,7 +43,7 @@ import {
43
43
  export class AudioProcessor {
44
44
  /**
45
45
  * Encodes a stream of audio frames to ATRAC1 format
46
- * @param {AsyncIterable<Float32Array>|AsyncIterable<[Float32Array, Float32Array]>} audioFrames - Audio frame stream
46
+ * @param {AsyncIterable<Float64Array>|AsyncIterable<[Float64Array, Float64Array]>} audioFrames - Audio frame stream
47
47
  * @param {Object} [options={}] - Encoding options
48
48
  * @param {number} [options.channelCount=1] - Number of audio channels (1 or 2)
49
49
  * @param {Function} [options.onProgress] - Progress callback function
@@ -73,7 +73,7 @@ export class AudioProcessor {
73
73
 
74
74
  /**
75
75
  * Internal method for encoding mono audio streams
76
- * @param {AsyncIterable<Float32Array>} audioFrames - Mono audio frame stream
76
+ * @param {AsyncIterable<Float64Array>} audioFrames - Mono audio frame stream
77
77
  * @param {Function} onProgress - Progress callback function
78
78
  * @param {EncoderOptions} encoderOptions - Encoder configuration
79
79
  * @returns {AsyncGenerator<Object>} Stream of encoded frame data
@@ -95,7 +95,7 @@ export class AudioProcessor {
95
95
 
96
96
  /**
97
97
  * Internal method for encoding stereo audio streams
98
- * @param {AsyncIterable<[Float32Array, Float32Array]>} audioFrames - Stereo audio frame stream
98
+ * @param {AsyncIterable<[Float64Array, Float64Array]>} audioFrames - Stereo audio frame stream
99
99
  * @param {Function} onProgress - Progress callback function
100
100
  * @param {EncoderOptions} encoderOptions - Encoder configuration
101
101
  * @returns {AsyncGenerator<Object>} Stream of encoded frame data (left then right)
@@ -128,7 +128,7 @@ export class AudioProcessor {
128
128
  * @param {Object} [options={}] - Decoding options
129
129
  * @param {number} [options.channelCount=1] - Number of audio channels (1 or 2)
130
130
  * @param {Function} [options.onProgress] - Progress callback function
131
- * @returns {AsyncGenerator<Float32Array>|AsyncGenerator<[Float32Array, Float32Array]>} Stream of decoded PCM frames
131
+ * @returns {AsyncGenerator<Float64Array>|AsyncGenerator<[Float64Array, Float64Array]>} Stream of decoded PCM frames
132
132
  * @throws {Error} If unsupported channel count is provided
133
133
  */
134
134
  static async *decodeStream(encodedFrames, options = {}) {
@@ -147,7 +147,7 @@ export class AudioProcessor {
147
147
  * Internal method for decoding mono audio streams
148
148
  * @param {AsyncIterable<Object>} encodedFrames - Mono encoded frame stream
149
149
  * @param {Function} onProgress - Progress callback function
150
- * @returns {AsyncGenerator<Float32Array>} Stream of decoded mono PCM frames
150
+ * @returns {AsyncGenerator<Float64Array>} Stream of decoded mono PCM frames
151
151
  * @private
152
152
  */
153
153
  static async *_decodeMonoStream(encodedFrames, onProgress) {
@@ -174,7 +174,7 @@ export class AudioProcessor {
174
174
  * Internal method for decoding stereo audio streams
175
175
  * @param {AsyncIterable<Object>} encodedFrames - Stereo encoded frame stream (interleaved left/right)
176
176
  * @param {Function} onProgress - Progress callback function
177
- * @returns {AsyncGenerator<[Float32Array, Float32Array]>} Stream of decoded stereo PCM frame pairs
177
+ * @returns {AsyncGenerator<[Float64Array, Float64Array]>} Stream of decoded stereo PCM frame pairs
178
178
  * @private
179
179
  */
180
180
  static async *_decodeStereoStream(encodedFrames, onProgress) {
@@ -225,9 +225,9 @@ export class AudioProcessor {
225
225
 
226
226
  /**
227
227
  * Converts channel buffer arrays to frame-based stream format
228
- * @param {Float32Array[]} buffers - Array of channel buffers (1 for mono, 2 for stereo)
228
+ * @param {Float64Array[]} buffers - Array of channel buffers (1 for mono, 2 for stereo)
229
229
  * @param {number} [frameSize=SAMPLES_PER_FRAME] - Frame size in samples
230
- * @returns {Generator<Float32Array>|Generator<[Float32Array, Float32Array]>} Stream of audio frames
230
+ * @returns {Generator<Float64Array>|Generator<[Float64Array, Float64Array]>} Stream of audio frames
231
231
  * @throws {Error} If unsupported channel count is provided
232
232
  */
233
233
  static *frameBufferToFrames(buffers, frameSize = SAMPLES_PER_FRAME) {
@@ -236,7 +236,7 @@ export class AudioProcessor {
236
236
  if (channelCount === 1) {
237
237
  const [left] = buffers
238
238
  for (let i = 0; i < left.length; i += frameSize) {
239
- const frame = new Float32Array(frameSize)
239
+ const frame = new Float64Array(frameSize)
240
240
  const end = Math.min(i + frameSize, left.length)
241
241
  for (let j = 0; j < end - i; j++) {
242
242
  frame[j] = left[i + j]
@@ -248,8 +248,8 @@ export class AudioProcessor {
248
248
  const maxLength = Math.max(left.length, right.length)
249
249
 
250
250
  for (let i = 0; i < maxLength; i += frameSize) {
251
- const leftFrame = new Float32Array(frameSize)
252
- const rightFrame = new Float32Array(frameSize)
251
+ const leftFrame = new Float64Array(frameSize)
252
+ const rightFrame = new Float64Array(frameSize)
253
253
 
254
254
  const end = Math.min(i + frameSize, maxLength)
255
255
 
@@ -327,7 +327,7 @@ export class AudioProcessor {
327
327
 
328
328
  /**
329
329
  * Creates a WAV file blob from PCM audio frames
330
- * @param {Float32Array[]|Float32Array|[Float32Array, Float32Array][]} pcmFrames - PCM audio frames
330
+ * @param {Float64Array[]|Float64Array|[Float64Array, Float64Array][]} pcmFrames - PCM audio frames
331
331
  * @param {number} [channelCount=1] - Number of audio channels
332
332
  * @param {number} [sampleRate=SAMPLE_RATE] - Audio sample rate
333
333
  * @returns {Blob} WAV file blob
@@ -347,7 +347,7 @@ export class AudioProcessor {
347
347
 
348
348
  /**
349
349
  * Creates a mono WAV file blob from PCM frames
350
- * @param {Float32Array[]} frames - Array of mono PCM frames
350
+ * @param {Float64Array[]} frames - Array of mono PCM frames
351
351
  * @param {number} sampleRate - Audio sample rate
352
352
  * @returns {Blob} Mono WAV file blob
353
353
  * @private
@@ -383,7 +383,7 @@ export class AudioProcessor {
383
383
 
384
384
  /**
385
385
  * Creates a stereo WAV file blob from PCM frame pairs
386
- * @param {[Float32Array, Float32Array][]} framePairs - Array of stereo PCM frame pairs
386
+ * @param {[Float64Array, Float64Array][]} framePairs - Array of stereo PCM frame pairs
387
387
  * @param {number} sampleRate - Audio sample rate
388
388
  * @returns {Blob} Stereo WAV file blob
389
389
  * @private
@@ -524,9 +524,9 @@ export class AudioProcessor {
524
524
 
525
525
  /**
526
526
  * Assembles PCM frames into a continuous buffer
527
- * @param {Float32Array[]|[Float32Array, Float32Array][]} pcmFrames - Array of PCM frames
527
+ * @param {Float64Array[]|[Float64Array, Float64Array][]} pcmFrames - Array of PCM frames
528
528
  * @param {number} channelCount - Number of audio channels
529
- * @returns {Float32Array} Continuous PCM buffer (interleaved for stereo)
529
+ * @returns {Float64Array} Continuous PCM buffer (interleaved for stereo)
530
530
  * @throws {Error} If unsupported channel count is provided
531
531
  */
532
532
  static assemblePcmFrames(pcmFrames, channelCount) {
@@ -535,7 +535,7 @@ export class AudioProcessor {
535
535
  (sum, frame) => sum + frame.length,
536
536
  0
537
537
  )
538
- const pcm = new Float32Array(totalSamples)
538
+ const pcm = new Float64Array(totalSamples)
539
539
  let offset = 0
540
540
  for (const frame of pcmFrames) {
541
541
  pcm.set(frame, offset)
@@ -547,7 +547,7 @@ export class AudioProcessor {
547
547
  (sum, [left, right]) => sum + Math.max(left.length, right.length),
548
548
  0
549
549
  )
550
- const pcm = new Float32Array(totalSamples * 2)
550
+ const pcm = new Float64Array(totalSamples * 2)
551
551
 
552
552
  let pcmOffset = 0
553
553
  for (const [leftFrame, rightFrame] of pcmFrames) {