sdrjs-footer.js
1 // ========================================================== 2 // ========= / THE CODE COMPILED BY EMCC ENDS HERE ========== 3 // ========================================================== 4 5 asm$ = 6 { 7 malloc: function(type, size) 8 { 9 real_size=size*type.BYTES_PER_ELEMENT; 10 pointer = Module._malloc(real_size); 11 heap = new Uint8Array(Module.HEAPU8.buffer, pointer, real_size); 12 return { 13 asm$: true, 14 ptr: heap.byteOffset, 15 free: function() { Module._free(this.ptr); }, 16 arr: new type(heap.buffer, heap.byteOffset, size), 17 size: size 18 }; 19 }, 20 cpy: function(dst, dst_offset, src, src_offset, size) 21 { 22 if(typeof dst.asm$!='undefined') dst=dst.arr; 23 if(typeof src.asm$!='undefined') src=src.arr; 24 for(var i=0;i<size;i++) 25 dst[dst_offset+i]=src[src_offset+i]; 26 } 27 }; 28 29 // void firdes_lowpass_f(float *output, int length, float cutoff_rate, window_t window) 30 firdes_lowpass_f = Module.cwrap('firdes_lowpass_f', null, ['number', 'number', 'number', 'number']); 31 32 // rational_resampler_ff_t rational_resampler_ff(float *input, float *output, int input_size, int interpolation, int decimation, float *taps, int taps_length, int last_taps_delay) 33 rational_resampler_ff = Module.cwrap('rational_resampler_ff', 'struct', ['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number']); 34 35 36 rational_resampler_ff=function(pinput,poutput,input_length,interpolation,decimation,ptaps,taps_length,last_taps_delay ) 37 { stackbase=STACKTOP; 38 STACKTOP+=4*3; 39 _rational_resampler_ff(stackbase, pinput, poutput, input_length, interpolation, decimation, ptaps, taps_length,last_taps_delay); 40 returnstruct={ input_processed: getValue(stackbase,'i32'), output_size: getValue(stackbase+4,'i32'), last_taps_delay: getValue(stackbase+8,'i32') }; 41 STACKTOP=stackbase; 42 return returnstruct; 43 } 44 45 sdrjs={}; 46 47 sdrjs.WINDOW_BOXCAR=0; 48 sdrjs.WINDOW_BLACKMAN=1; 49 sdrjs.WINDOW_HAMMING=2; 50 51 //this will be impportant whil converting arrays 52 //http://stackoverflow.com/questions/25839216/convert-float32array-to-int16array 53 54 /*sdrjs.prototype.FirdesLowpassF=function(taps_length,transition_bw,window) 55 { 56 this.calculate=function(){} 57 this.get_output=function(){} 58 this.get_output_heap=function(){} 59 };*/ 60 61 62 sdrjs.ConvertI16_F=function(i16data) 63 { 64 var f32data=new Float32Array(i16data.length); 65 for(var i=0;i<i16data.length;i++) f32data[i]=i16data[i]/32768; 66 return f32data; 67 } 68 69 ima_adpcm_codec=function(encode,pinput,poutput,input_length,state) 70 { 71 myfunc=(encode)?_encode_ima_adpcm_i16_u8:_decode_ima_adpcm_u8_i16; 72 stackbase=STACKTOP; 73 STACKTOP+=4*2; //sizeof(int)*2 74 myfunc(stackbase, pinput, poutput, input_length, state.ptr); 75 state.arr[0]=getValue(stackbase+0,'i32'); 76 state.arr[1]=getValue(stackbase+4,'i32'); 77 STACKTOP=stackbase; 78 }; 79 80 sdrjs.ImaAdpcm=function() 81 { 82 this.BUFSIZE=1024*64; 83 this.ima_adpcm_state=asm$.malloc(Int32Array,2); 84 this.i16_buffer=asm$.malloc(Int16Array,this.BUFSIZE*2); 85 this.u8_buffer=asm$.malloc(Uint8Array,this.BUFSIZE); 86 this.ima_adpcm_state.arr[0]=0; 87 this.ima_adpcm_state.arr[1]=0; 88 89 this.encode=function(data) 90 { 91 //not_tested_yet 92 asm$.cpy(this.i16_buffer.arr,0,data,0,data.length); 93 ima_adpcm_codec(true,this.i16_buffer.ptr,this.u8_buffer.ptr,data.length,this.ima_adpcm_state); 94 out=new Uint8Array(data.length/2); 95 asm$.cpy(out,0,this.u8_buffer,0,data.length/2); 96 return out; 97 }; 98 99 this.decode=function(data) 100 { 101 asm$.cpy(this.u8_buffer.arr,0,data,0,data.length); 102 ima_adpcm_codec(false,this.u8_buffer.ptr,this.i16_buffer.ptr,data.length,this.ima_adpcm_state); 103 out=new Int16Array(data.length*2); 104 asm$.cpy(out,0,this.i16_buffer.arr,0,data.length*2); 105 return out; 106 }; 107 this.reset=function() { this.ima_adpcm_state.arr[0]=this.ima_adpcm_state.arr[1]=0|0; } 108 }; 109 110 sdrjs.REBUFFER_FIXED=0; //rebuffer should return arrays of fixed size 111 sdrjs.REBUFFER_MAX=1; //rebuffer should return arrays with a maximal size of the parameter size 112 113 sdrjs.Rebuffer=function(size,mode) 114 { 115 this.mode=mode; 116 this.size=size; 117 this.total_size=0; 118 this.arrays=[]; 119 this.last_arr=[]; 120 this.last_arr_offset=0; 121 this.push=function(data) 122 { 123 this.total_size+=data.length; 124 this.arrays.push(data); 125 }; 126 this.remaining=function() 127 { 128 var fixed_bufs_num=Math.floor(this.total_size/this.size); 129 if(!this.mode) return fixed_bufs_num; 130 else return fixed_bufs_num+(!!(this.total_size-fixed_bufs_num*this.size)); //if REBUFFER_MAX, add one if we could return one more buffer (smaller than the fixed size) 131 }; 132 this.take=function() { var a=this._take(); /*console.log(a);*/ return a; }; 133 this._take=function() 134 { 135 var remain=this.size; 136 var offset=0; 137 var obuf=new Float32Array(size); 138 //console.log("==== get new obuf ====", size); 139 while(remain) 140 { 141 if(this.last_arr_offset==this.last_arr.length) 142 { 143 if(this.arrays.length==0) 144 { 145 //console.log("this should not happen"); 146 if(this.mode) //REBUFFER_MAX 147 { 148 this.total_size=0; 149 return obuf.subarray(0,offset); 150 } 151 else return new Float32Array(0); //REBUFFER_FIXED 152 } 153 //console.log("pick new last_arr"); 154 this.last_arr=this.arrays.shift(); 155 this.last_arr_offset=0; 156 } 157 var rwithin=this.last_arr.length-this.last_arr_offset; 158 //console.log("b :: ","remain", remain, "rwithin",rwithin,"last_arr.length",this.last_arr.length,"larroffset",this.last_arr_offset,"offset",offset); 159 if(remain<rwithin) 160 { 161 //console.log("remain < rwithin"); //seems problematic @Andris 162 for(var i=0;i<remain;i++) obuf[offset++]=this.last_arr[this.last_arr_offset++]; 163 remain=0; 164 } 165 else 166 { 167 //console.log("remain > rwithin"); 168 for(var i=0;i<rwithin;i++) obuf[offset++]=this.last_arr[this.last_arr_offset++]; 169 remain-=rwithin; 170 } 171 //console.log("e :: ","remain", remain, "rwithin",rwithin,"last_arr.length",this.last_arr.length,"larroffset",this.last_arr_offset,"offset",offset); 172 } 173 174 this.total_size-=obuf.length; 175 //console.log("return _take"); 176 return obuf; 177 }; 178 }; 179 180 sdrjs.RationalResamplerFF=function(interpolation,decimation,transition_bw,window) 181 { 182 this.interpolation=interpolation; 183 this.decimation=decimation; 184 this.transition_bw = (typeof transition_bw=='undefined')?0.05:transition_bw; 185 this.window = (typeof window=='undefined')?1:window; 186 this.buffer_size=1024*512; 187 this.output_buffer_size=Math.floor((this.buffer_size*interpolation)/decimation); 188 this.input_buffer = asm$.malloc(Float32Array,this.buffer_size); 189 this.output_buffer = asm$.malloc(Float32Array,this.output_buffer_size); 190 //Calculate filter 191 this.taps_length = Math.floor(4/this.transition_bw); 192 this.taps = asm$.malloc(Float32Array,this.taps_length); 193 var cutoff_for_interpolation=1.0/interpolation; 194 var cutoff_for_decimation=1.0/decimation; 195 var cutoff = (cutoff_for_interpolation<cutoff_for_decimation)?cutoff_for_interpolation:cutoff_for_decimation; //get the lower 196 firdes_lowpass_f(this.taps.ptr, this.taps_length, cutoff/2, window); 197 198 this.remain = 0; 199 this.remain_offset=0; 200 this.last_taps_delay=0; 201 202 this.process=function(input) 203 { 204 205 if(input.length+this.remain > this.buffer_size) 206 { 207 return new Float32Array(0); console.log("sdrjs.RationalResamplerFF: critical audio buffering error"); //This should not happen... 208 /* console.log("RationalResamplerFF: splitting..."); //TODO: this branch has not been checked 209 output_buffers=Array(); 210 new_buffer_size=this.buffer_size/2; 211 i=0; 212 //process the input in chunks of new_buffer_size, and add the output product Float32Array-s to output_buffers. 213 while((i++)*new_buffer_size<=input.length) 214 { 215 output_buffers.push(this._process_noheapcheck(input.subarray(i*new_buffer_size,(i+1)*new_buffer_size))); 216 } 217 //add up the sizes of the output_buffer-s. 218 total_output_length=0; 219 output_buffers.forEach(function(a){total_output_length+=a.length;}); 220 //create one big buffer from concatenating the output_buffer-s 221 output=new Float32Array(total_output_length); 222 output_pos=0; 223 output_buffers.forEach(function(a){ 224 asm$.cpy(output,output_pos,a,0,a.length); 225 output_pos+=a.length; 226 }); 227 return output;*/ 228 } 229 else return this._process_noheapcheck(input); 230 }; 231 this._process_noheapcheck=function(input) //if we are sure we have enough space in the buffers 232 { 233 asm$.cpy(this.input_buffer.arr,0,this.input_buffer.arr,this.remain_offset,this.remain); 234 asm$.cpy(this.input_buffer.arr, this.remain, input, 0, input.length); 235 var total_input_size=input.length+this.remain; 236 d=rational_resampler_ff(this.input_buffer.ptr, this.output_buffer.ptr, total_input_size, this.interpolation, this.decimation, this.taps.ptr, this.taps_length, this.last_taps_delay); 237 this.last_taps_delay=d.last_taps_delay; 238 this.remain=total_input_size-d.input_processed; 239 this.remain_offset=d.input_processed; 240 var output_copy_arr=new Float32Array(d.output_size); 241 asm$.cpy(output_copy_arr,0,this.output_buffer.arr,0,d.output_size); 242 return output_copy_arr; 243 }; 244 }; 245 246 247 _sdrjs_logb=function(what) { document.body.innerHTML+=what+"<br />"; } 248 249 250 function test_firdes_lowpass_f_original() 251 { 252 //Original method explained over here: 253 //http://kapadia.github.io/emscripten/2013/09/13/emscripten-pointers-and-pointers.html 254 _sdrjs_logb("test_firdes_lowpass_f_original():"); 255 _sdrjs_logb("Now designing FIR filter with firdes_lowpass_f in sdr.js..."); 256 _sdrjs_logb("output should be the same as: <strong>csdr firdes_lowpass_f 0.1 101 HAMMING</strong>"); 257 258 var outputSize = 101*4; 259 var outputPtr = Module._malloc(outputSize); 260 var outputHeap = new Uint8Array(Module.HEAPU8.buffer, outputPtr, outputSize); 261 firdes_lowpass_f(outputHeap.byteOffset,101,0.1,2); 262 var output = new Float32Array(outputHeap.buffer, outputHeap.byteOffset, 101); 263 outputStr=String(); 264 for(i=0;i<output.length;i++) outputStr+=output[i].toFixed(6)+", "; 265 Module._free(outputHeap.byteOffset); 266 _sdrjs_logb(outputStr); 267 } 268 269 270 function test_firdes_lowpass_f_new() 271 { 272 //This is much simpler, using asm$ 273 _sdrjs_logb("test_firdes_lowpass_f_new():"); 274 _sdrjs_logb("Now designing FIR filter with firdes_lowpass_f in sdr.js..."); 275 _sdrjs_logb("output should be the same as: <strong>csdr firdes_lowpass_f 0.1 101 HAMMING</strong>"); 276 277 output=asm$.malloc(Float32Array,101); 278 firdes_lowpass_f(output.ptr,101,0.1,2); 279 outputStr=String(); 280 for(i=0;i<output.arr.length;i++) outputStr+=(output.arr[i]).toFixed(6)+", "; 281 output.free(); 282 _sdrjs_logb(outputStr); 283 } 284 285 function test_struct_return_value() 286 { 287 v=STACKTOP; 288 STACKTOP+=4*3; 289 _shift_addition_init(v,0.2); 290 console.log( 291 "sinval=", getValue(v,'float'), 292 "cosval=", getValue(v+4,'float'), 293 "rate=", getValue(v+8,'float') 294 ); 295 STACKTOP=v; 296 }