@mediabunny/mp3-encoder 1.17.0 → 1.17.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.
@@ -17,35 +17,156 @@ import { CustomAudioEncoder, EncodedPacket, registerEncoder } from "mediabunny";
17
17
 
18
18
  // shared/mp3-misc.ts
19
19
  var FRAME_HEADER_SIZE = 4;
20
- var MPEG_V1_BITRATES = {
21
- // Layer 3
22
- 1: [-1, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1],
23
- // Layer 2
24
- 2: [-1, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1],
25
- // Layer 1
26
- 3: [-1, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1]
27
- };
28
- var MPEG_V2_BITRATES = {
29
- // Layer 3
30
- 1: [-1, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1],
31
- // Layer 2
32
- 2: [-1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1],
33
- // Layer 1
34
- 3: [-1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1]
35
- };
36
- var SAMPLING_RATES = {
37
- // MPEG Version 2.5
38
- 0: [11025, 12e3, 8e3, -1],
39
- // MPEG Version 2 (ISO/IEC 13818-3)
40
- 2: [22050, 24e3, 16e3, -1],
41
- // MPEG Version 1 (ISO/IEC 11172-3)
42
- 3: [44100, 48e3, 32e3, -1]
43
- };
44
- var computeMp3FrameSize = (layer, bitrate, sampleRate, padding) => {
45
- if (layer === 3) {
46
- return Math.floor((12 * bitrate / sampleRate + padding) * 4);
20
+ var SAMPLING_RATES = [44100, 48e3, 32e3];
21
+ var KILOBIT_RATES = [
22
+ // lowSamplingFrequency === 0
23
+ -1,
24
+ -1,
25
+ -1,
26
+ -1,
27
+ -1,
28
+ -1,
29
+ -1,
30
+ -1,
31
+ -1,
32
+ -1,
33
+ -1,
34
+ -1,
35
+ -1,
36
+ -1,
37
+ -1,
38
+ -1,
39
+ // layer = 0
40
+ -1,
41
+ 32,
42
+ 40,
43
+ 48,
44
+ 56,
45
+ 64,
46
+ 80,
47
+ 96,
48
+ 112,
49
+ 128,
50
+ 160,
51
+ 192,
52
+ 224,
53
+ 256,
54
+ 320,
55
+ -1,
56
+ // layer 1
57
+ -1,
58
+ 32,
59
+ 48,
60
+ 56,
61
+ 64,
62
+ 80,
63
+ 96,
64
+ 112,
65
+ 128,
66
+ 160,
67
+ 192,
68
+ 224,
69
+ 256,
70
+ 320,
71
+ 384,
72
+ -1,
73
+ // layer = 2
74
+ -1,
75
+ 32,
76
+ 64,
77
+ 96,
78
+ 128,
79
+ 160,
80
+ 192,
81
+ 224,
82
+ 256,
83
+ 288,
84
+ 320,
85
+ 352,
86
+ 384,
87
+ 416,
88
+ 448,
89
+ -1,
90
+ // layer = 3
91
+ // lowSamplingFrequency === 1
92
+ -1,
93
+ -1,
94
+ -1,
95
+ -1,
96
+ -1,
97
+ -1,
98
+ -1,
99
+ -1,
100
+ -1,
101
+ -1,
102
+ -1,
103
+ -1,
104
+ -1,
105
+ -1,
106
+ -1,
107
+ -1,
108
+ // layer = 0
109
+ -1,
110
+ 8,
111
+ 16,
112
+ 24,
113
+ 32,
114
+ 40,
115
+ 48,
116
+ 56,
117
+ 64,
118
+ 80,
119
+ 96,
120
+ 112,
121
+ 128,
122
+ 144,
123
+ 160,
124
+ -1,
125
+ // layer = 1
126
+ -1,
127
+ 8,
128
+ 16,
129
+ 24,
130
+ 32,
131
+ 40,
132
+ 48,
133
+ 56,
134
+ 64,
135
+ 80,
136
+ 96,
137
+ 112,
138
+ 128,
139
+ 144,
140
+ 160,
141
+ -1,
142
+ // layer = 2
143
+ -1,
144
+ 32,
145
+ 48,
146
+ 56,
147
+ 64,
148
+ 80,
149
+ 96,
150
+ 112,
151
+ 128,
152
+ 144,
153
+ 160,
154
+ 176,
155
+ 192,
156
+ 224,
157
+ 256,
158
+ -1
159
+ // layer = 3
160
+ ];
161
+ var computeMp3FrameSize = (lowSamplingFrequency, layer, bitrate, sampleRate, padding) => {
162
+ if (layer === 0) {
163
+ return 0;
164
+ } else if (layer === 1) {
165
+ return Math.round(144 * bitrate / (sampleRate << lowSamplingFrequency)) + padding;
166
+ } else if (layer === 2) {
167
+ return Math.round(144 * bitrate / sampleRate) + padding;
47
168
  } else {
48
- return Math.floor(144 * bitrate / sampleRate + padding);
169
+ return (Math.round(12 * bitrate / sampleRate) + padding) * 4;
49
170
  }
50
171
  };
51
172
  var readFrameHeader = (word, remainingBytes) => {
@@ -65,26 +186,31 @@ var readFrameHeader = (word, remainingBytes) => {
65
186
  if ((secondByte & 224) !== 224) {
66
187
  return { header: null, bytesAdvanced: 1 };
67
188
  }
189
+ let lowSamplingFrequency = 0;
190
+ let mpeg25 = 0;
191
+ if (secondByte & 1 << 4) {
192
+ lowSamplingFrequency = secondByte & 1 << 3 ? 0 : 1;
193
+ } else {
194
+ lowSamplingFrequency = 1;
195
+ mpeg25 = 1;
196
+ }
68
197
  const mpegVersionId = secondByte >> 3 & 3;
69
198
  const layer = secondByte >> 1 & 3;
70
199
  const bitrateIndex = thirdByte >> 4 & 15;
71
- const frequencyIndex = thirdByte >> 2 & 3;
200
+ const frequencyIndex = (thirdByte >> 2 & 3) % 3;
72
201
  const padding = thirdByte >> 1 & 1;
73
202
  const channel = fourthByte >> 6 & 3;
74
203
  const modeExtension = fourthByte >> 4 & 3;
75
204
  const copyright = fourthByte >> 3 & 1;
76
205
  const original = fourthByte >> 2 & 1;
77
206
  const emphasis = fourthByte & 3;
78
- const kilobitRate = mpegVersionId === 3 ? MPEG_V1_BITRATES[layer]?.[bitrateIndex] : MPEG_V2_BITRATES[layer]?.[bitrateIndex];
79
- if (!kilobitRate || kilobitRate === -1) {
207
+ const kilobitRate = KILOBIT_RATES[lowSamplingFrequency * 16 * 4 + layer * 16 + bitrateIndex];
208
+ if (kilobitRate === -1) {
80
209
  return { header: null, bytesAdvanced: 1 };
81
210
  }
82
211
  const bitrate = kilobitRate * 1e3;
83
- const sampleRate = SAMPLING_RATES[mpegVersionId]?.[frequencyIndex];
84
- if (!sampleRate || sampleRate === -1) {
85
- return { header: null, bytesAdvanced: 1 };
86
- }
87
- const frameLength = computeMp3FrameSize(layer, bitrate, sampleRate, padding);
212
+ const sampleRate = SAMPLING_RATES[frequencyIndex] >> lowSamplingFrequency + mpeg25;
213
+ const frameLength = computeMp3FrameSize(lowSamplingFrequency, layer, bitrate, sampleRate, padding);
88
214
  if (remainingBytes !== null && remainingBytes < frameLength) {
89
215
  return { header: null, bytesAdvanced: 1 };
90
216
  }
@@ -158,7 +284,9 @@ var Mp3Encoder = class extends CustomAudioEncoder {
158
284
  this.chunkMetadata = {};
159
285
  }
160
286
  static supports(codec, config) {
161
- return codec === "mp3" && (config.numberOfChannels === 1 || config.numberOfChannels === 2) && Object.values(SAMPLING_RATES).some((x) => x.includes(config.sampleRate));
287
+ return codec === "mp3" && (config.numberOfChannels === 1 || config.numberOfChannels === 2) && Object.values(SAMPLING_RATES).some(
288
+ (x) => x === config.sampleRate || x / 2 === config.sampleRate || x / 4 === config.sampleRate
289
+ );
162
290
  }
163
291
  async init() {
164
292
  this.worker = await Worker2();
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqLH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,YAE9B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAuLH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,YAE9B,CAAC"}
@@ -29,7 +29,7 @@ class Mp3Encoder extends mediabunny_1.CustomAudioEncoder {
29
29
  static supports(codec, config) {
30
30
  return codec === 'mp3'
31
31
  && (config.numberOfChannels === 1 || config.numberOfChannels === 2)
32
- && Object.values(mp3_misc_1.SAMPLING_RATES).some(x => x.includes(config.sampleRate));
32
+ && Object.values(mp3_misc_1.SAMPLING_RATES).some(x => x === config.sampleRate || (x / 2) === config.sampleRate || (x / 4) === config.sampleRate);
33
33
  }
34
34
  async init() {
35
35
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mediabunny/mp3-encoder",
3
3
  "author": "Vanilagy",
4
- "version": "1.17.0",
4
+ "version": "1.17.2",
5
5
  "description": "MP3 encoder extension for Mediabunny, based on LAME.",
6
6
  "main": "./dist/bundles/mediabunny-mp3-encoder.mjs",
7
7
  "module": "./dist/bundles/mediabunny-mp3-encoder.mjs",
package/src/index.ts CHANGED
@@ -28,7 +28,9 @@ class Mp3Encoder extends CustomAudioEncoder {
28
28
  static override supports(codec: AudioCodec, config: AudioDecoderConfig): boolean {
29
29
  return codec === 'mp3'
30
30
  && (config.numberOfChannels === 1 || config.numberOfChannels === 2)
31
- && Object.values(SAMPLING_RATES).some(x => x.includes(config.sampleRate));
31
+ && Object.values(SAMPLING_RATES).some(x =>
32
+ x === config.sampleRate || (x / 2) === config.sampleRate || (x / 4) === config.sampleRate,
33
+ );
32
34
  }
33
35
 
34
36
  async init() {