Skip to content

Commit 3db1496

Browse files
Merge pull request #424 from Aditya30ag/Float32Array.subarray
fix: Float32Array.subarray() Memory Allocation
2 parents 8de65f6 + d1d5857 commit 3db1496

File tree

4 files changed

+452
-91
lines changed

4 files changed

+452
-91
lines changed

src/audio-worklet/free-queue/src/free-queue.js

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -118,18 +118,34 @@ class FreeQueue {
118118
}
119119
let nextWrite = currentWrite + blockLength;
120120
if (this.bufferLength < nextWrite) {
121+
// Handle wrap-around: split data into two chunks
121122
nextWrite -= this.bufferLength;
123+
const firstChunkLength = this.bufferLength - currentWrite;
124+
const secondChunkLength = nextWrite;
125+
122126
for (let channel = 0; channel < this.channelCount; channel++) {
123-
const blockA = this.channelData[channel].subarray(currentWrite);
124-
const blockB = this.channelData[channel].subarray(0, nextWrite);
125-
blockA.set(input[channel].subarray(0, blockA.length));
126-
blockB.set(input[channel].subarray(blockA.length));
127+
const channelData = this.channelData[channel];
128+
const inputChannel = input[channel];
129+
130+
// Copy first chunk (from currentWrite to end of buffer)
131+
for (let i = 0; i < firstChunkLength; i++) {
132+
channelData[currentWrite + i] = inputChannel[i];
133+
}
134+
135+
// Copy second chunk (from start of buffer to nextWrite)
136+
for (let i = 0; i < secondChunkLength; i++) {
137+
channelData[i] = inputChannel[firstChunkLength + i];
138+
}
127139
}
128140
} else {
141+
// No wrap-around: simple linear copy
129142
for (let channel = 0; channel < this.channelCount; channel++) {
130-
this.channelData[channel]
131-
.subarray(currentWrite, nextWrite)
132-
.set(input[channel].subarray(0, blockLength));
143+
const channelData = this.channelData[channel];
144+
const inputChannel = input[channel];
145+
146+
for (let i = 0; i < blockLength; i++) {
147+
channelData[currentWrite + i] = inputChannel[i];
148+
}
133149
}
134150
if (nextWrite === this.bufferLength) nextWrite = 0;
135151
}
@@ -154,18 +170,34 @@ class FreeQueue {
154170
}
155171
let nextRead = currentRead + blockLength;
156172
if (this.bufferLength < nextRead) {
173+
// Handle wrap-around: split data into two chunks
157174
nextRead -= this.bufferLength;
175+
const firstChunkLength = this.bufferLength - currentRead;
176+
const secondChunkLength = nextRead;
177+
158178
for (let channel = 0; channel < this.channelCount; channel++) {
159-
const blockA = this.channelData[channel].subarray(currentRead);
160-
const blockB = this.channelData[channel].subarray(0, nextRead);
161-
output[channel].set(blockA);
162-
output[channel].set(blockB, blockA.length);
179+
const channelData = this.channelData[channel];
180+
const outputChannel = output[channel];
181+
182+
// Copy first chunk (from currentRead to end of buffer)
183+
for (let i = 0; i < firstChunkLength; i++) {
184+
outputChannel[i] = channelData[currentRead + i];
185+
}
186+
187+
// Copy second chunk (from start of buffer to nextRead)
188+
for (let i = 0; i < secondChunkLength; i++) {
189+
outputChannel[firstChunkLength + i] = channelData[i];
190+
}
163191
}
164192
} else {
193+
// No wrap-around: simple linear copy
165194
for (let channel = 0; channel < this.channelCount; ++channel) {
166-
output[channel].set(
167-
this.channelData[channel].subarray(currentRead, nextRead)
168-
);
195+
const channelData = this.channelData[channel];
196+
const outputChannel = output[channel];
197+
198+
for (let i = 0; i < blockLength; i++) {
199+
outputChannel[i] = channelData[currentRead + i];
200+
}
169201
}
170202
if (nextRead === this.bufferLength) {
171203
nextRead = 0;

src/experiments/webgpuaudio/lib/free-queue.js

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,18 +119,34 @@ class FreeQueue {
119119
}
120120
let nextWrite = currentWrite + blockLength;
121121
if (this.bufferLength < nextWrite) {
122+
// Handle wrap-around: split data into two chunks
122123
nextWrite -= this.bufferLength;
124+
const firstChunkLength = this.bufferLength - currentWrite;
125+
const secondChunkLength = nextWrite;
126+
123127
for (let channel = 0; channel < this.channelCount; channel++) {
124-
const blockA = this.channelData[channel].subarray(currentWrite);
125-
const blockB = this.channelData[channel].subarray(0, nextWrite);
126-
blockA.set(input[channel].subarray(0, blockA.length));
127-
blockB.set(input[channel].subarray(blockA.length));
128+
const channelData = this.channelData[channel];
129+
const inputChannel = input[channel];
130+
131+
// Copy first chunk (from currentWrite to end of buffer)
132+
for (let i = 0; i < firstChunkLength; i++) {
133+
channelData[currentWrite + i] = inputChannel[i];
134+
}
135+
136+
// Copy second chunk (from start of buffer to nextWrite)
137+
for (let i = 0; i < secondChunkLength; i++) {
138+
channelData[i] = inputChannel[firstChunkLength + i];
139+
}
128140
}
129141
} else {
142+
// No wrap-around: simple linear copy
130143
for (let channel = 0; channel < this.channelCount; channel++) {
131-
this.channelData[channel]
132-
.subarray(currentWrite, nextWrite)
133-
.set(input[channel].subarray(0, blockLength));
144+
const channelData = this.channelData[channel];
145+
const inputChannel = input[channel];
146+
147+
for (let i = 0; i < blockLength; i++) {
148+
channelData[currentWrite + i] = inputChannel[i];
149+
}
134150
}
135151
if (nextWrite === this.bufferLength) nextWrite = 0;
136152
}
@@ -156,18 +172,34 @@ class FreeQueue {
156172
}
157173
let nextRead = currentRead + blockLength;
158174
if (this.bufferLength < nextRead) {
175+
// Handle wrap-around: split data into two chunks
159176
nextRead -= this.bufferLength;
177+
const firstChunkLength = this.bufferLength - currentRead;
178+
const secondChunkLength = nextRead;
179+
160180
for (let channel = 0; channel < this.channelCount; channel++) {
161-
const blockA = this.channelData[channel].subarray(currentRead);
162-
const blockB = this.channelData[channel].subarray(0, nextRead);
163-
output[channel].set(blockA);
164-
output[channel].set(blockB, blockA.length);
181+
const channelData = this.channelData[channel];
182+
const outputChannel = output[channel];
183+
184+
// Copy first chunk (from currentRead to end of buffer)
185+
for (let i = 0; i < firstChunkLength; i++) {
186+
outputChannel[i] = channelData[currentRead + i];
187+
}
188+
189+
// Copy second chunk (from start of buffer to nextRead)
190+
for (let i = 0; i < secondChunkLength; i++) {
191+
outputChannel[firstChunkLength + i] = channelData[i];
192+
}
165193
}
166194
} else {
195+
// No wrap-around: simple linear copy
167196
for (let channel = 0; channel < this.channelCount; ++channel) {
168-
output[channel].set(
169-
this.channelData[channel].subarray(currentRead, nextRead)
170-
);
197+
const channelData = this.channelData[channel];
198+
const outputChannel = output[channel];
199+
200+
for (let i = 0; i < blockLength; i++) {
201+
outputChannel[i] = channelData[currentRead + i];
202+
}
171203
}
172204
if (nextRead === this.bufferLength) {
173205
nextRead = 0;

0 commit comments

Comments
 (0)