Skip to content

Commit 51c17e5

Browse files
committed
added modules/shared/common.js and improved some logging
1 parent 816bf7e commit 51c17e5

File tree

6 files changed

+79
-33
lines changed

6 files changed

+79
-33
lines changed

src/modules/example-processor.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
//import { RingBuffer } from './shared/ring-buffer.js'; //not yet supported by FF :-( (Dec 2020)
1+
//TODO: not yet supported by FF :-( (Dec 2020)
2+
//import { SampleSizeException } from './shared/common.js';
3+
//import { RingBuffer } from './shared/ring-buffer.js';
24
class RingBuffer{constructor(a,b,c){this._readIndex=0,this._writeIndex=0,this._framesAvailable=0,this._channelCount=b,this._length=a,this._channelData=[];for(let d=0;d<this._channelCount;++d)this._channelData[d]="Uint16"==c?new Uint16Array(a):"Int16"==c?new Int16Array(a):"Uint8"==c?new Uint8Array(a):"Int8"==c?new Int8Array(a):new Float32Array(a)}get framesAvailable(){return this._framesAvailable}push(a){let b=a[0].length;for(let c,d=0;d<b;++d){c=(this._writeIndex+d)%this._length;for(let b=0;b<this._channelCount;++b)this._channelData[b][c]=a[b][d]}this._writeIndex+=b,this._writeIndex>=this._length&&(this._writeIndex-=this._length),this._framesAvailable+=b,this._framesAvailable>this._length&&(this._framesAvailable=this._length)}pull(a){if(0!==this._framesAvailable){let b=a[0].length;for(let c,d=0;d<b;++d){c=(this._readIndex+d)%this._length;for(let b=0;b<this._channelCount;++b)a[b][d]=this._channelData[b][c]}this._readIndex+=b,this._readIndex>=this._length&&(this._readIndex-=this._length),this._framesAvailable-=b,0>this._framesAvailable&&(this._framesAvailable=0)}}};
35

46
var someExampleVar;

src/modules/example-worker.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//imports
2+
importScripts('./shared/common.js');
23
importScripts('./shared/ring-buffer.min.js');
34

45
onmessage = function(e) {

src/modules/shared/common.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//Exceptions / Errors
2+
3+
function SampleRateException(message) {
4+
this.message = message;
5+
this.name = "SampleRateException";
6+
}
7+
function ArrayTypeException(message) {
8+
this.message = message;
9+
this.name = "ArrayTypeException";
10+
}
11+
function SampleSizeException(message){
12+
this.message = message;
13+
this.name = "SampleSizeException";
14+
}
15+
function BufferSizeException(message){
16+
this.message = message;
17+
this.name = "BufferSizeException";
18+
}
19+
20+
//Converters
21+
22+
var CommonConverters = {};
23+
24+
CommonConverters.floatTo16BitPCM = function (output, input){
25+
for (let i = 0; i < input.length; i++) {
26+
let s = Math.max(-1, Math.min(1, input[i]));
27+
output[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
28+
}
29+
}

src/modules/speex-resample-worker.js

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//imports
2+
importScripts('./shared/common.js');
23
importScripts('./shared/ring-buffer.min.js');
34
importScripts('./shared/speex-resampler-interface.min.js');
45
importScripts('./shared/speex-resampler-wasm.js');
@@ -117,21 +118,26 @@ function constructWorker(options) {
117118
resampleRatio = targetSampleRate/sourceSamplerate;
118119
init();
119120

121+
function onSpeexLog(msg){
122+
console.error("SpeexModuleLog -", msg); //DEBUG (use postMessage?)
123+
}
124+
//function onSpeexError(msg){} //TODO: we could wrap the 'resampler.processChunk' function in try-catch and log the error here
125+
120126
//prepare
121127
if (resamplingMode){
122128
if (!speexModule){
123-
console.error("Init Speex"); //DEBUG
129+
onSpeexLog("Init. Speex WASM module");
124130
SpeexResampler.initPromise = Speex().then(function(s){
125-
console.error("Speex ready"); //DEBUG
126-
speexModule = s;
131+
onSpeexLog("Speex WASM module ready");
132+
speexModule = s; //NOTE: used inside Speex
127133
ready(false);
128134
});
129135
}else{
130-
console.error("Speex already there"); //DEBUG
136+
onSpeexLog("Speex WASM moduel already loaded");
131137
ready(false);
132138
}
133139
}else{
134-
console.error("Speex not needed"); //DEBUG
140+
onSpeexLog("Speex WASM module not needed");
135141
ready(true);
136142
}
137143
}
@@ -202,7 +208,6 @@ function process(data) {
202208
});
203209
}
204210
}
205-
return true;
206211
}
207212

208213
function handleEvent(data){
@@ -242,19 +247,11 @@ function release(options){
242247
_newInputBuffer = null;
243248
_newOutputBuffer = null;
244249
resampler = null;
250+
speexModule = null;
245251
}
246252

247253
//--- helpers ---
248254

249-
function SampleSizeException(message){
250-
this.message = message;
251-
this.name = "SampleSizeException";
252-
}
253-
function BufferSizeException(message){
254-
this.message = message;
255-
this.name = "BufferSizeException";
256-
}
257-
258255
function floatTo16BitInterleavedPCM(inFloat32, outInt16, i){
259256
let sampleVal = Math.max(-1, Math.min(1, inFloat32[0][i])); //we need -1 to 1 - If this is the first processor we could skip clipping
260257
outInt16[0][i] = sampleVal < 0 ? sampleVal * 0x8000 : sampleVal * 0x7FFF;

src/modules/wave-encoder-worker.js

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,33 @@ onmessage = function(e) {
3636
//custom interface
3737
if (e.data.gate != undefined){
3838
console.error("Message", e.data); //DEBUG
39-
gateControl(e.data.gate && e.data.gate == "open");
39+
gateControl(e.data.gate && e.data.gate == "open", e.data.gateOptions);
4040
}
4141
if (e.data.request){
4242
console.error("Message", e.data); //DEBUG
43-
switch (e.data.request.get){
44-
case "buffer":
45-
getBuffer(e.data.request.start, e.data.request.end);
46-
break;
47-
case "wave":
48-
getWave(e.data.request.start, e.data.request.end);
49-
break;
50-
default:
51-
console.log("Unknown request message:", e.data);
52-
break;
43+
if (e.data.request.get){
44+
switch (e.data.request.get){
45+
case "buffer":
46+
getBuffer(e.data.request.start, e.data.request.end);
47+
break;
48+
case "wave":
49+
getWave(e.data.request.start, e.data.request.end);
50+
break;
51+
default:
52+
console.log("Unknown request message:", e.data);
53+
break;
54+
}
55+
}else if (e.data.request.clear){
56+
switch (e.data.request.clear){
57+
case "buffer":
58+
//TODO: clear buffer and release lookback lock
59+
break;
60+
default:
61+
console.log("Unknown request message:", e.data);
62+
break;
63+
}
64+
}else{
65+
console.log("Unknown request message:", e.data);
5366
}
5467
}else if (e.data.encode && e.data.encode.data){
5568
encodeInterface(e.data.encode);
@@ -145,7 +158,8 @@ function encodeInterface(e){
145158
}
146159
}
147160

148-
function gateControl(open){
161+
function gateControl(open, gateOptions){
162+
if (!gateOptions) gateOptions = {}; //TODO: use e.g. for (lookbackBufferNeedsReset = false)
149163
var msg = {
150164
moduleEvent: true, //use 'moduleEvent' to distinguish from normal processing result
151165
gate: {}
@@ -197,6 +211,7 @@ function constructWorker(options){
197211
moduleInfo: {
198212
inputSampleRate: inputSampleRate,
199213
inputSampleSize: inputSampleSize,
214+
inputIsFloat32: isFloat32Input,
200215
channelCount: channelCount,
201216
lookbackBufferSizeKb: Math.ceil((_lookbackBufferSize * 2)/1024), //1 sample = 2 bytes
202217
lookbackLimitMs: lookbackBufferMs,
@@ -210,21 +225,21 @@ function process(data){
210225
//TODO: check process values against constructor values (sampleSize etc.)
211226
if (data && data.samples){
212227
if (_isFirstValidProcess){
228+
//console.error("data info", data); //DEBUG
213229
_isFirstValidProcess = false;
214-
console.error("data info", data); //DEBUG
215230
//check: inputSampleRate, inputSampleSize, channelCount, float32
216231
if (data.sampleRate != inputSampleRate){
217232
var msg = "Sample-rate mismatch! Should be '" + inputSampleRate + "' is '" + data.sampleRate + "'";
218233
console.error("Audio Worker sample-rate exception - Msg.: " + msg);
219-
throw new SampleRateException(msg); //TODO: this probably needs to be a string to show up in worker.onerror properly :-/
234+
throw JSON.stringify(new SampleRateException(msg)); //NOTE: this needs to be a string to show up in worker.onerror properly :-/
220235
return;
221236
}
222-
var inputArrayType = data.samples[0].constructor.name;
237+
var inputArrayType = data.type || data.samples[0].constructor.name;
223238
var isFloat32 = (inputArrayType.indexOf("Float32") >= 0);
224239
if (isFloat32 != isFloat32Input){
225240
var msg = "Array type mismatch! Input samples are of type '" + inputArrayType + "' but expected: " + (isFloat32Input? "Float32" : "Int16");
226241
console.error("Audio Worker type exception - Msg.: " + msg);
227-
throw new ArrayTypeException(msg); //TODO: this probably needs to be a string to show up in worker.onerror properly :-/
242+
throw JSON.stringify(new ArrayTypeException(msg)); //NOTE: this needs to be a string to show up in worker.onerror properly :-/
228243
return;
229244
}
230245
//TODO: should we re-init. instead of fail?
@@ -295,6 +310,7 @@ function buildBuffer(start, end){
295310
_lookbackRingBuffer.pull(lookbackSamples);
296311
}
297312
var dataLength = recordedBuffers.length * inputSampleSize + (lookbackSamples? lookbackSamples[0].length : 0);
313+
//TODO: any chance to allocate 'collectBuffer' in advance and keep it? (max. rec + lookback maybe?)
298314
var collectBuffer = isFloat32? new Float32Array(dataLength) : new Int16Array(dataLength); //TODO: this is usually too big because the last buffer is not full ...
299315
var n = 0;
300316
if (lookbackSamples){
@@ -316,6 +332,7 @@ function buildBuffer(start, end){
316332
isFloat32: isFloat32
317333
}
318334
//TODO: we clear lookback buffer here ... so we should clear everything
335+
lookbackBufferNeedsReset = false;
319336
}
320337

321338
function encodeWAV(samples, sampleRate, numChannels, convertFromFloat32){

src/processor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ if (!(typeof SepiaFW == "object")){
10931093
var offlineAudioContext = new OfflineAudioContext(channels, buffer.length, inputSampleRate); //we just need this to setup the module
10941094
var moduleFolder = WebAudio.defaultProcessorOptions.moduleFolder.replace(/\/$/, "") + "/";
10951095
var moduleName = "speex-resample-switch";
1096-
offlineAudioContext.audioWorklet.addModule(moduleFolder + moduleName + ".js").then(function(){
1096+
offlineAudioContext.audioWorklet.addModule(moduleFolder + moduleName + ".js").then(function(){ //NOTE: if the folder is wrong this can fail with poor error message
10971097
var options = {
10981098
processorOptions: {
10991099
ctxInfo: {

0 commit comments

Comments
 (0)