diff --git a/Makefile b/Makefile
index 6b77fed..1752fc9 100644
--- a/Makefile
+++ b/Makefile
@@ -38,9 +38,10 @@ PARAMS_RASPI = -mfloat-abi=hard -mcpu=arm1176jzf-s -mfpu=vfp -funsafe-math-optim
PARAMS_ARM = $(if $(call cpufeature,BCM2708,dummy-text),$(PARAMS_RASPI),$(PARAMS_NEON))
PARAMS_SIMD = $(if $(call cpufeature,sse,dummy-text),$(PARAMS_SSE),$(PARAMS_ARM))
PARAMS_LOOPVECT = -O3 -ffast-math -fdump-tree-vect-details -dumpbase dumpvect
-PARAMS_LIBS = -g -lm -lrt -lfftw3f -DUSE_FFTW -DLIBCSDR_GPL
+PARAMS_LIBS = -g -lm -lrt -lfftw3f -DUSE_FFTW -DLIBCSDR_GPL -DUSE_IMA_ADPCM
PARAMS_SO = -fpic
PARAMS_MISC = -Wno-unused-result
+FFTW_PACKAGE = fftw-3.3.3
all: clean-vect
@echo NOTE: you may have to manually edit Makefile to optimize for your CPU \(especially if you compile on ARM, please edit PARAMS_NEON\).
@@ -64,3 +65,22 @@ install:
uninstall:
rm /usr/lib/libcsdr.so /usr/bin/csdr /usr/bin/csdr-fm
ldconfig
+emcc-clean:
+ -rm sdr.js/sdr.js
+ -rm sdr.js/sdrjs-compiled.js
+ -rm -rf sdr.js/$(FFTW_PACKAGE)
+emcc-get-deps:
+ echo "getting and compiling fftw3 with emscripten..."
+ cd sdr.js; \
+ wget http://fftw.org/$(FFTW_PACKAGE).tar.gz; \
+ tar -xvf $(FFTW_PACKAGE).tar.gz; \
+ rm $(FFTW_PACKAGE).tar.gz; \
+ cd $(FFTW_PACKAGE); \
+ emconfigure ./configure --enable-float --disable-fortran --prefix=`pwd`/emscripten-install --libdir=`pwd`/emscripten-lib; \
+ emmake make; \
+ emmake make install
+emcc:
+ emcc -O3 -Isdr.js/$(FFTW_PACKAGE)/api -Lsdr.js/$(FFTW_PACKAGE)/emscripten-lib -o sdr.js/sdrjs-compiled.js fft_fftw.c libcsdr_wrapper.c -DLIBCSDR_GPL -DUSE_IMA_ADPCM -DUSE_FFTW -lfftw3f -s EXPORTED_FUNCTIONS="`python sdr.js/exported_functions.py`"
+ cat sdr.js/sdrjs-header.js sdr.js/sdrjs-compiled.js sdr.js/sdrjs-footer.js > sdr.js/sdr.js
+emcc-beautify:
+ bash -c 'type js-beautify >/dev/null 2>&1; if [ $$? -eq 0 ]; then js-beautify sdr.js/sdr.js >sdr.js/sdr.js.beautiful; mv sdr.js/sdr.js.beautiful sdr.js/sdr.js; fi'
diff --git a/README.md b/README.md
index c306814..b0c9d79 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,8 @@ Most of the code is available under the permissive BSD license, with some option
- The code of *libcsdr* was intended to be easy to follow.
- *libcsdr* was designed to use auto-vectorization available in *gcc*. It means that it can achieve some speedup by taking advantage of SIMD command sets available in today's CPUs (e.g. SSE on x86 and NEON on ARM).
+Moreover, *libcsdr* serves as the base for the new, experimental sdr.js, which takes Software Defined Radio DSP to today's web browsers that provide JavScript JIT compilation.
+
How to compile
--------------
The project was only tested on Linux. It has the following dependencies: `libfftw3-dev`
@@ -155,15 +157,33 @@ It multiplies all samples by `gain`.
It copies the input to the output.
+ none
+
+The `csdr` process just exits with 0.
+
yes_f [buf_times]
It outputs continously the `to_repeat` float number.
If `buf_times` is not given, it never stops.
Else, after outputing `buf_times` number of buffers (the size of which is stated in the `BUFSIZE` macro), it exits.
+ detect_nan_ff
+
+Along with copying its input samples to the output, it prints a warning message to *stderr* if it finds any IEEE floating point NaN values among the samples.
+
+ floatdump_f
+
+It prints any floating point input samples.
+The format string used is `"%g "`.
+
+ flowcontrol
+
+It limits the data rate of a stream to a given `data_rate` number of bytes per second.
+It copies `data_rate / reads_per_second` bytes from the input to the output, doing it `reads_per_second` times every second.
+
shift_math_cc
-It shifts the complex spectrum by `rate`.
+It shifts the signal in the frequency domain by `rate`.
`rate` is a floating point number between -0.5 and 0.5.
`rate` is relative to the sampling rate.
@@ -179,6 +199,17 @@ Internally, this function uses trigonometric addition formulas to generate sine
This function was used to test the accuracy of the method above.
+ shift_table_cc [table_size]
+
+Operation is the same as with `shift_math_cc`.
+Internally, this function uses a look-up table (LUT) to recall the values of the sine function (for the first quadrant).
+The higher the table size is, the smaller the phase error is.
+
+ decimating_shift_addition_cc [decimation]
+
+It shifts the input signal in the frequency domain, and also decimates it, without filtering. It will be useful as a part of the FFT channelizer implementation (to be done).
+It cannot be used as a channelizer by itself, use `fir_decimate_cc` instead.
+
dcblock_ff
This is a DC blocking IIR filter.
@@ -214,7 +245,7 @@ It uses fixed filters so it works only on predefined sample rates, for the actua
It is an AM demodulator that uses `sqrt`. On some architectures `sqrt` can be directly calculated by dedicated CPU instructions, but on others it may be slower.
-amdemod_estimator_cf
+ amdemod_estimator_cf
It is an AM demodulator that uses an estimation method that is faster but less accurate than `amdemod_cf`.
@@ -296,10 +327,28 @@ FFTW can be faster if we let it optimalize a while before starting the first tra
It measures the time taken to process `fft_cycles` transforms of `fft_size`.
It lets FFTW optimalize if used with the `--benchmark` switch.
- lowpower_cf [add_db]
+ logpower_cf [add_db]
Calculates `10*log10(i^2+q^2)+add_db` for the input complex samples. It is useful for drawing power spectrum graphs.
+ encode_ima_adpcm_i16_u8
+
+Encodes the audio stream to IMA ADPCM, which decreases the size to 25% of the original.
+
+ decode_ima_adpcm_u8_i16
+
+Decodes the audio stream from IMA ADPCM.
+
+ compress_fft_adpcm_f_u8
+
+Encodes the FFT output vectors of `fft_size`. It should be used on the data output from `logpower_cf`.
+It resets the ADPCM encoder at the beginning of every vector, and to compensate it, `COMPRESS_FFT_PAD_N` samples are added at beginning (these equal to the first relevant sample).
+The actual number of padding samples can be determined by running `cat csdr.c | grep "define COMPRESS_FFT_PAD_N"`.
+
+ fft_exchange_sides_ff
+
+It exchanges the first and second part of the FFT vector, to prepare it for the waterfall/spectrum display. It should operate on the data output from `logpower_cf`.
+
#### Control via pipes
Some parameters can be changed while the `csdr` process is running. To achieve this, some `csdr` functions have special parameters. You have to supply a fifo previously created by the `mkfifo` command. Processing will only start after the first control command has been received by `csdr` over the FIFO.
@@ -326,6 +375,28 @@ E.g. you can send `-0.05 0.02\n`
`csdr` was tested with GNU Radio Companion flowgraphs. These flowgraphs are available under the directory `grc_tests`, and they require the gr-ha5kfu set of blocks for GNU Radio.
+## [sdr.js] (#sdr.js)
+
+*sdr.js* is *libcsdr* compiled to JavaScript code with *Emscripten*. Nowadays JavaScript runs quite fast in browsers, as all major browser vendors included JavaScript JIT machines into their product. You can find a great introductory slideshow here about *Emscripten*.
+
+The purpose of *sdr.js* is to make SDR DSP processing available in the web browser. However, it is not easy to use in production yet. By now, only those functions have wrappers that the front-end of OpenWebRX uses.
+
+To compile *sdr.js*, you will need emscripten. (It turns out that *emscripten* is already included in Ubuntu repositories.)
+
+To install and build dependencies (for now, only FFTW3):
+
+ make emcc-get-deps
+
+To compile *sdr.js* (which will be created in the `sdr.js` subdirectory):
+
+ make emcc
+
+You can test *sdr.js* by opening *sdr.html*. It contains a test for *firdes_lowpass_f* for this time.
+
+To remove *sdr.js* and the compiled dependencies:
+
+ make emcc-clean
+
## [Licensing] (#licensing)
Most of the code of `libcsdr` is under BSD license.
diff --git a/csdr.c b/csdr.c
index 6aea2a8..905a879 100644
--- a/csdr.c
+++ b/csdr.c
@@ -44,6 +44,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include
#include "libcsdr.h"
#include "libcsdr_gpl.h"
+#include "ima_adpcm.h"
+#include
+#include
char usage[]=
"csdr - a simple commandline tool for Software Defined Radio receiver DSP.\n\n"
@@ -59,10 +62,16 @@ char usage[]=
" limit_ff [max_amplitude]\n"
" gain_ff \n"
" clone\n"
+" none\n"
" yes_f [buf_times]\n"
+" detect_nan_ff\n"
+" floatdump_f\n"
+" flowcontrol \n"
" shift_math_cc \n"
" shift_addition_cc \n"
" shift_addition_cc_test\n"
+" shift_table_cc [table_size]\n"
+" decimating_shift_addition_cc [decimation]\n"
" dcblock_ff\n"
" fastdcblock_ff\n"
" fmdemod_atan_cf\n"
@@ -83,12 +92,22 @@ char usage[]=
" logpower_cf [add_db]\n"
" fft_benchmark [--benchmark]\n"
" bandpass_fir_fft_cc [window]\n"
+" encode_ima_adpcm_i16_u8\n"
+" decode_ima_adpcm_u8_i16\n"
+" compress_fft_adpcm_f_u8 \n"
+" fft_exchange_sides_ff \n"
+" \n"
;
-#define BUFSIZE (1024*8)
+#define BUFSIZE (1024)
+#define BIG_BUFSIZE (1024*16)
//should be multiple of 16! (size of double complex)
//also, keep in mind that shift_addition_cc works better the smaller this buffer is.
+#define YIELD_EVERY_N_TIMES 3
+#define TRY_YIELD if(++yield_counter%YIELD_EVERY_N_TIMES==0) sched_yield()
+unsigned yield_counter=0;
+
int badsyntax(char* why)
{
if(why==0) fprintf(stderr, "%s", usage);
@@ -113,6 +132,7 @@ int clone()
{
fread(clone_buffer, sizeof(unsigned char), BUFSIZE, stdin);
fwrite(clone_buffer, sizeof(unsigned char), BUFSIZE, stdout);
+ TRY_YIELD;
}
}
@@ -121,6 +141,8 @@ int clone()
#define FWRITE_R fwrite(output_buffer, sizeof(float), BUFSIZE, stdout)
#define FWRITE_C fwrite(output_buffer, sizeof(float)*2, BUFSIZE, stdout)
#define FEOF_CHECK if(feof(stdin)) return 0
+#define BIG_FREAD_C fread(input_buffer, sizeof(float)*2, BIG_BUFSIZE, stdin)
+#define BIG_FWRITE_C fwrite(output_buffer, sizeof(float)*2, BIG_BUFSIZE, stdout)
int init_fifo(int argc, char *argv[])
{
@@ -179,12 +201,12 @@ int read_fifo_ctl(int fd, char* format, ...)
}
int main(int argc, char *argv[])
-{
- static float input_buffer[BUFSIZE*2];
- static unsigned char buffer_u8[BUFSIZE*2];
- static float output_buffer[BUFSIZE*2];
- static short buffer_i16[BUFSIZE*2];
- static float temp_f[BUFSIZE*4];
+{
+ static float input_buffer[BIG_BUFSIZE*2];
+ static unsigned char buffer_u8[BIG_BUFSIZE*2];
+ static float output_buffer[BIG_BUFSIZE*2];
+ static short buffer_i16[BIG_BUFSIZE*2];
+ static float temp_f[BIG_BUFSIZE*4];
if(argc<=1) return badsyntax(0);
if(!strcmp(argv[1],"--help")) return badsyntax(0);
if(!strcmp(argv[1],"convert_u8_f"))
@@ -195,6 +217,7 @@ int main(int argc, char *argv[])
fread(buffer_u8, sizeof(unsigned char), BUFSIZE, stdin);
convert_u8_f(buffer_u8, output_buffer, BUFSIZE);
FWRITE_R;
+ TRY_YIELD;
}
}
if(!strcmp(argv[1],"convert_f_u8")) //not tested
@@ -205,6 +228,7 @@ int main(int argc, char *argv[])
FREAD_R;
convert_f_u8(input_buffer, buffer_u8, BUFSIZE);
fwrite(buffer_u8, sizeof(unsigned char), BUFSIZE, stdout);
+ TRY_YIELD;
}
}
if(!strcmp(argv[1],"convert_f_i16"))
@@ -215,6 +239,7 @@ int main(int argc, char *argv[])
FREAD_R;
convert_f_i16(input_buffer, buffer_i16, BUFSIZE);
fwrite(buffer_i16, sizeof(short), BUFSIZE, stdout);
+ TRY_YIELD;
}
}
if(!strcmp(argv[1],"convert_i16_f")) //not tested
@@ -225,6 +250,7 @@ int main(int argc, char *argv[])
fread(buffer_i16, sizeof(short), BUFSIZE, stdin);
convert_i16_f(buffer_i16, output_buffer, BUFSIZE);
FWRITE_R;
+ TRY_YIELD;
}
}
if(!strcmp(argv[1],"realpart_cf"))
@@ -235,6 +261,7 @@ int main(int argc, char *argv[])
FREAD_C;
for(int i=0;i=4) sscanf(argv[3],"%d",&buf_times);
for(int i=0;i/dev/null
//csdr yes_f 1 1000000 | time csdr shift_addition_cc 0.2 >/dev/null
+ //csdr yes_f 1 1000000 | time csdr shift_table_cc 0.2 >/dev/null
+
+ if(!strcmp(argv[1],"shift_table_cc"))
+ {
+ if(argc<=2) return badsyntax("need required parameter (rate)");
+ float starting_phase=0;
+ float rate;
+ int table_size=65536;
+ sscanf(argv[2],"%g",&rate);
+ if(argc>3) sscanf(argv[3],"%d",&table_size);
+ shift_table_data_t table_data=shift_table_init(table_size);
+ fprintf(stderr,"shift_table_cc: LUT initialized\n");
+ for(;;)
+ {
+ FEOF_CHECK;
+ if(!BIG_FREAD_C) break;
+ starting_phase=shift_table_cc((complexf*)input_buffer, (complexf*)output_buffer, BIG_BUFSIZE, rate, table_data, starting_phase);
+ BIG_FWRITE_C;
+ TRY_YIELD;
+ }
+ return 0;
+ }
+
#ifdef LIBCSDR_GPL
+ if(!strcmp(argv[1],"decimating_shift_addition_cc"))
+ {
+ if(argc<=2) return badsyntax("need required parameter (rate)");
+ float starting_phase=0;
+ float rate;
+ int decimation=1;
+ sscanf(argv[2],"%g",&rate);
+ if(argc>3) sscanf(argv[3],"%d",&decimation);
+ shift_addition_data_t d=decimating_shift_addition_init(rate, decimation);
+ decimating_shift_addition_status_t s;
+ s.decimation_remain=0;
+ s.starting_phase=0;
+ for(;;)
+ {
+ FEOF_CHECK;
+ if(!BIG_FREAD_C) break;
+ s=decimating_shift_addition_cc((complexf*)input_buffer, (complexf*)output_buffer, BIG_BUFSIZE, d, decimation, s);
+ fwrite(output_buffer, sizeof(float)*2, s.output_size, stdout);
+ TRY_YIELD;
+ }
+ return 0;
+ }
+
if(!strcmp(argv[1],"shift_addition_cc"))
{
float starting_phase=0;
@@ -329,10 +410,11 @@ int main(int argc, char *argv[])
for(;;)
{
FEOF_CHECK;
- if(!FREAD_C) break;
- starting_phase=shift_addition_cc((complexf*)input_buffer, (complexf*)output_buffer, BUFSIZE, data, starting_phase);
- FWRITE_C;
+ if(!BIG_FREAD_C) break;
+ starting_phase=shift_addition_cc((complexf*)input_buffer, (complexf*)output_buffer, BIG_BUFSIZE, data, starting_phase);
+ BIG_FWRITE_C;
if(read_fifo_ctl(fd,"%g\n",&rate)) break;
+ TRY_YIELD;
}
}
return 0;
@@ -357,6 +439,7 @@ int main(int argc, char *argv[])
FREAD_R;
dcp=dcblock_ff(input_buffer, output_buffer, BUFSIZE, 0, dcp);
FWRITE_R;
+ TRY_YIELD;
}
}
@@ -372,6 +455,7 @@ int main(int argc, char *argv[])
fread(dcblock_buffer, sizeof(float), dcblock_bufsize, stdin);
last_dc_level=fastdcblock_ff(dcblock_buffer, dcblock_buffer, dcblock_bufsize, last_dc_level);
fwrite(dcblock_buffer, sizeof(float), dcblock_bufsize, stdout);
+ TRY_YIELD;
}
}
@@ -385,6 +469,7 @@ int main(int argc, char *argv[])
if(feof(stdin)) return 0;
last_phase=fmdemod_atan_cf((complexf*)input_buffer, output_buffer, BUFSIZE, last_phase);
FWRITE_R;
+ TRY_YIELD;
}
}
if(!strcmp(argv[1],"fmdemod_quadri_cf"))
@@ -398,6 +483,7 @@ int main(int argc, char *argv[])
FREAD_C;
last_sample=fmdemod_quadri_cf((complexf*)input_buffer, output_buffer, BUFSIZE, temp_f, last_sample);
FWRITE_R;
+ TRY_YIELD;
}
}
if(!strcmp(argv[1],"fmdemod_quadri_novect_cf"))
@@ -411,6 +497,7 @@ int main(int argc, char *argv[])
FREAD_C;
last_sample=fmdemod_quadri_novect_cf((complexf*)input_buffer, output_buffer, BUFSIZE, last_sample);
FWRITE_R;
+ TRY_YIELD;
}
}
if(!strcmp(argv[1],"deemphasis_wfm_ff"))
@@ -421,7 +508,6 @@ int main(int argc, char *argv[])
float tau;
sscanf(argv[3],"%g",&tau);
fprintf(stderr,"deemphasis_wfm_ff: tau = %g, sample_rate = %d\n",tau,sample_rate);
-
float last_output=0;
for(;;)
{
@@ -429,8 +515,42 @@ int main(int argc, char *argv[])
FREAD_R;
last_output=deemphasis_wfm_ff(input_buffer, output_buffer, BUFSIZE, tau, sample_rate, last_output);
FWRITE_R;
+ TRY_YIELD;
}
}
+
+ if(!strcmp(argv[1],"detect_nan_ff"))
+ {
+ for(;;)
+ {
+ FEOF_CHECK;
+ FREAD_R;
+ int nan_detect=0;
+ for(int i=0; ioutput, sizeof(complexf), input_size, stdout);
if(read_fifo_ctl(fd,"%g %g\n",&low_cut,&high_cut)) break;
+ TRY_YIELD;
}
}
}
+#ifdef USE_IMA_ADPCM
+#define IMA_ADPCM_BUFSIZE BUFSIZE
+
+ if(!strcmp(argv[1],"encode_ima_adpcm_i16_u8"))
+ {
+ ima_adpcm_state_t d;
+ d.index=d.previousValue=0;
+ for(;;)
+ {
+ FEOF_CHECK;
+ fread(buffer_i16, sizeof(short), IMA_ADPCM_BUFSIZE, stdin);
+ d=encode_ima_adpcm_i16_u8(buffer_i16, buffer_u8, IMA_ADPCM_BUFSIZE, d);
+ fwrite(buffer_u8, sizeof(unsigned char), IMA_ADPCM_BUFSIZE/2, stdout);
+ TRY_YIELD;
+ }
+ }
+
+ if(!strcmp(argv[1],"decode_ima_adpcm_u8_i16"))
+ {
+ ima_adpcm_state_t d;
+ d.index=d.previousValue=0;
+ for(;;)
+ {
+ FEOF_CHECK;
+ fread(buffer_u8, sizeof(unsigned char), IMA_ADPCM_BUFSIZE/2, stdin);
+ d=decode_ima_adpcm_u8_i16(buffer_u8, buffer_i16, IMA_ADPCM_BUFSIZE/2, d);
+ fwrite(buffer_i16, sizeof(short), IMA_ADPCM_BUFSIZE, stdout);
+ TRY_YIELD;
+ }
+ }
+#endif
+
+ if(!strcmp(argv[1],"flowcontrol"))
+ {
+ if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)");
+ int data_rate;
+ sscanf(argv[2],"%d",&data_rate);
+ int reads_per_second;
+ sscanf(argv[3],"%d",&reads_per_second);
+ int flowcontrol_bufsize=ceil(1.*(double)data_rate/reads_per_second);
+ unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize);
+ int flowcontrol_sleep=floor(1000000./reads_per_second);
+ fprintf(stderr, "flowcontrol: flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_bufsize, flowcontrol_sleep);
+ for(;;)
+ {
+ FEOF_CHECK;
+ fread(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdin);
+ fwrite(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdout);
+ usleep(flowcontrol_sleep);
+ TRY_YIELD;
+ }
+ }
+
if(!strcmp(argv[1],"none"))
{
return 0;
diff --git a/grc_tests/test_ima_adpcm.grc b/grc_tests/test_ima_adpcm.grc
new file mode 100644
index 0000000..c0b77f8
--- /dev/null
+++ b/grc_tests/test_ima_adpcm.grc
@@ -0,0 +1,844 @@
+
+
+
+ Sun Jan 25 13:25:30 2015
+
+ options
+
+ id
+ top_block
+
+
+ _enabled
+ True
+
+
+ title
+
+
+
+ author
+
+
+
+ description
+
+
+
+ window_size
+ 1280, 1024
+
+
+ generate_options
+ wx_gui
+
+
+ category
+ Custom
+
+
+ run_options
+ prompt
+
+
+ run
+ True
+
+
+ max_nouts
+ 0
+
+
+ realtime_scheduling
+
+
+
+ alias
+
+
+
+ _coordinate
+ (10, 10)
+
+
+ _rotation
+ 0
+
+
+
+ variable
+
+ id
+ samp_rate
+
+
+ _enabled
+ True
+
+
+ value
+ 32000
+
+
+ alias
+
+
+
+ _coordinate
+ (176, 11)
+
+
+ _rotation
+ 0
+
+
+
+ variable_slider
+
+ id
+ amp
+
+
+ _enabled
+ True
+
+
+ label
+
+
+
+ value
+ 0.5
+
+
+ min
+ 0
+
+
+ max
+ 1
+
+
+ num_steps
+ 100
+
+
+ style
+ wx.SL_HORIZONTAL
+
+
+ converver
+ float_converter
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (544, 11)
+
+
+ _rotation
+ 0
+
+
+
+ analog_sig_source_x
+
+ id
+ analog_sig_source_x_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ samp_rate
+ samp_rate
+
+
+ waveform
+ analog.GR_COS_WAVE
+
+
+ freq
+ freq
+
+
+ amp
+ amp
+
+
+ offset
+ 0
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (8, 163)
+
+
+ _rotation
+ 0
+
+
+
+ blocks_throttle
+
+ id
+ blocks_throttle_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ samples_per_second
+ samp_rate
+
+
+ vlen
+ 1
+
+
+ ignoretag
+ True
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (176, 195)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_scopesink2
+
+ id
+ wxgui_scopesink2_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ title
+ Scope Plot of Original Signal
+
+
+ samp_rate
+ samp_rate
+
+
+ v_scale
+ 0
+
+
+ v_offset
+ 0
+
+
+ t_scale
+ 0
+
+
+ ac_couple
+ False
+
+
+ xy_mode
+ False
+
+
+ num_inputs
+ 1
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb0,0
+
+
+ trig_mode
+ wxgui.TRIG_MODE_AUTO
+
+
+ y_axis_label
+ Counts
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (352, 331)
+
+
+ _rotation
+ 0
+
+
+
+ notebook
+
+ id
+ nb0
+
+
+ _enabled
+ True
+
+
+ style
+ wx.NB_TOP
+
+
+ labels
+ ['Scope', 'FFT']
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (272, 11)
+
+
+ _rotation
+ 0
+
+
+
+ notebook
+
+ id
+ nb1
+
+
+ _enabled
+ True
+
+
+ style
+ wx.NB_TOP
+
+
+ labels
+ ['Scope', 'FFT']
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (272, 99)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_fftsink2
+
+ id
+ wxgui_fftsink2_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ title
+ FFT Plot of Original Signal
+
+
+ samp_rate
+ samp_rate
+
+
+ baseband_freq
+ 0
+
+
+ y_per_div
+ 10
+
+
+ y_divs
+ 10
+
+
+ ref_level
+ 0
+
+
+ ref_scale
+ 2.0
+
+
+ fft_size
+ 1024
+
+
+ fft_rate
+ 15
+
+
+ peak_hold
+ False
+
+
+ average
+ False
+
+
+ avg_alpha
+ 0
+
+
+ win
+ None
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb0,1
+
+
+ freqvar
+ None
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (352, 459)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_scopesink2
+
+ id
+ wxgui_scopesink2_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ title
+ Scope Plot of Processed Signal (csdr)
+
+
+ samp_rate
+ samp_rate
+
+
+ v_scale
+ 0
+
+
+ v_offset
+ 0
+
+
+ t_scale
+ 0
+
+
+ ac_couple
+ False
+
+
+ xy_mode
+ False
+
+
+ num_inputs
+ 1
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb1,0
+
+
+ trig_mode
+ wxgui.TRIG_MODE_AUTO
+
+
+ y_axis_label
+ Counts
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (760, 171)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_fftsink2
+
+ id
+ wxgui_fftsink2_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ float
+
+
+ title
+ FFT Plot of Processed Signal (csdr)
+
+
+ samp_rate
+ samp_rate
+
+
+ baseband_freq
+ 0
+
+
+ y_per_div
+ 10
+
+
+ y_divs
+ 10
+
+
+ ref_level
+ 0
+
+
+ ref_scale
+ 2.0
+
+
+ fft_size
+ 1024
+
+
+ fft_rate
+ 15
+
+
+ peak_hold
+ False
+
+
+ average
+ False
+
+
+ avg_alpha
+ 0
+
+
+ win
+ None
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb1,1
+
+
+ freqvar
+ None
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (760, 299)
+
+
+ _rotation
+ 0
+
+
+
+ ha5kfu_execproc_xx
+
+ id
+ ha5kfu_execproc_xx_0
+
+
+ _enabled
+ True
+
+
+ type
+ ff
+
+
+ commandline
+ csdr convert_f_i16 | csdr encode_ima_adpcm_i16_u8 | csdr decode_ima_adpcm_u8_i16 | csdr convert_i16_f
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (448, 195)
+
+
+ _rotation
+ 0
+
+
+
+ variable_slider
+
+ id
+ freq
+
+
+ _enabled
+ True
+
+
+ label
+
+
+
+ value
+ 1000
+
+
+ min
+ 0
+
+
+ max
+ samp_rate/2
+
+
+ num_steps
+ 100
+
+
+ style
+ wx.SL_HORIZONTAL
+
+
+ converver
+ float_converter
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (424, 11)
+
+
+ _rotation
+ 0
+
+
+
+ analog_sig_source_x_0
+ blocks_throttle_0
+ 0
+ 0
+
+
+ blocks_throttle_0
+ ha5kfu_execproc_xx_0
+ 0
+ 0
+
+
+ blocks_throttle_0
+ wxgui_scopesink2_0
+ 0
+ 0
+
+
+ blocks_throttle_0
+ wxgui_fftsink2_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0
+ wxgui_scopesink2_0_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0
+ wxgui_fftsink2_0_0
+ 0
+ 0
+
+
diff --git a/grc_tests/test_rational_resampler.grc b/grc_tests/test_rational_resampler.grc
index 7bb2e71..fe8e838 100644
--- a/grc_tests/test_rational_resampler.grc
+++ b/grc_tests/test_rational_resampler.grc
@@ -1,7 +1,7 @@
- Tue Nov 25 18:15:25 2014
+ Tue Mar 17 19:40:27 2015
options
@@ -77,7 +77,7 @@
value
- 2
+ 1
alias
@@ -104,7 +104,7 @@
value
- 5
+ 4
alias
@@ -939,49 +939,6 @@
0
-
- ha5kfu_execproc_xx
-
- id
- ha5kfu_execproc_xx_0
-
-
- _enabled
- True
-
-
- type
- ff
-
-
- commandline
- "csdr rational_resampler_ff %d %d 0.05"%(interpolation,decimation)
-
-
- alias
-
-
-
- affinity
-
-
-
- minoutbuf
- 0
-
-
- maxoutbuf
- 0
-
-
- _coordinate
- (752, 195)
-
-
- _rotation
- 0
-
-
notebook
@@ -1076,6 +1033,49 @@
0
+
+ ha5kfu_execproc_xx
+
+ id
+ ha5kfu_execproc_xx_0
+
+
+ _enabled
+ True
+
+
+ type
+ ff
+
+
+ commandline
+ "csdr rational_resampler_ff %d %d 0.05"%(interpolation,decimation)
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (752, 195)
+
+
+ _rotation
+ 0
+
+
blocks_throttle_0
ha5kfu_execproc_xx_0
diff --git a/grc_tests/test_shift.grc b/grc_tests/test_shift.grc
index 5f5a9ab..9fc1eb7 100644
--- a/grc_tests/test_shift.grc
+++ b/grc_tests/test_shift.grc
@@ -1,7 +1,7 @@
- Sat Nov 15 22:24:14 2014
+ Thu Jan 15 18:51:48 2015
options
@@ -65,6 +65,60 @@
0
+
+ variable
+
+ id
+ rate
+
+
+ _enabled
+ True
+
+
+ value
+ -0.055
+
+
+ alias
+
+
+
+ _coordinate
+ (8, 195)
+
+
+ _rotation
+ 0
+
+
+
+ variable
+
+ id
+ decimation
+
+
+ _enabled
+ True
+
+
+ value
+ 3
+
+
+ alias
+
+
+
+ _coordinate
+ (16, 267)
+
+
+ _rotation
+ 0
+
+
variable
@@ -85,7 +139,7 @@
_coordinate
- (10, 170)
+ (176, 11)
_rotation
@@ -144,7 +198,132 @@
_coordinate
- (56, 243)
+ (8, 75)
+
+
+ _rotation
+ 0
+
+
+
+ ha5kfu_execproc_xx
+
+ id
+ ha5kfu_execproc_xx_0
+
+
+ _enabled
+ True
+
+
+ type
+ cc
+
+
+ commandline
+ "csdr shift_math_cc %g"%rate
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (488, 251)
+
+
+ _rotation
+ 0
+
+
+
+ ha5kfu_execproc_xx
+
+ id
+ ha5kfu_execproc_xx_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ cc
+
+
+ commandline
+ "csdr shift_addition_cc %g"%rate
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (472, 411)
+
+
+ _rotation
+ 0
+
+
+
+ notebook
+
+ id
+ nb0
+
+
+ _enabled
+ True
+
+
+ style
+ wx.NB_TOP
+
+
+ labels
+ ['shift_math_cc', 'shift_addition_cc', 'shift_table_cc', 'decimating_shift_addition_cc','original']
+
+
+ grid_pos
+
+
+
+ notebook
+
+
+
+ alias
+
+
+
+ _coordinate
+ (272, 11)
_rotation
@@ -155,7 +334,7 @@
wxgui_fftsink2
id
- wxgui_fftsink2_0
+ wxgui_fftsink2_0_0
_enabled
@@ -227,7 +406,7 @@
notebook
- nb0,0
+ nb0,4
freqvar
@@ -243,7 +422,7 @@
_coordinate
- (952, 275)
+ (496, 27)
_rotation
@@ -251,22 +430,105 @@
- notebook
+ blocks_throttle
id
- nb0
+ blocks_throttle_0
_enabled
True
- style
- wx.NB_TOP
+ type
+ complex
- labels
- ['shift_math_ff', 'shift_addition_ff', 'original']
+ samples_per_second
+ samp_rate
+
+
+ vlen
+ 1
+
+
+ ignoretag
+ True
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (224, 107)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_scopesink2
+
+ id
+ wxgui_scopesink2_0_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ complex
+
+
+ title
+ Scope Plot
+
+
+ samp_rate
+ samp_rate
+
+
+ v_scale
+ 0
+
+
+ v_offset
+ 0
+
+
+ t_scale
+ 0
+
+
+ ac_couple
+ False
+
+
+ xy_mode
+ False
+
+
+ num_inputs
+ 1
+
+
+ win_size
+
grid_pos
@@ -274,15 +536,27 @@
notebook
-
+ nb0,2
+
+
+ trig_mode
+ wxgui.TRIG_MODE_NORM
+
+
+ y_axis_label
+ Counts
alias
+
+ affinity
+
+
_coordinate
- (256, 27)
+ (1080, 899)
_rotation
@@ -293,7 +567,275 @@
wxgui_fftsink2
id
- wxgui_fftsink2_0_0
+ wxgui_fftsink2_0_1_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ complex
+
+
+ title
+ FFT Plot
+
+
+ samp_rate
+ samp_rate/decimation
+
+
+ baseband_freq
+ 0
+
+
+ y_per_div
+ 10
+
+
+ y_divs
+ 10
+
+
+ ref_level
+ 0
+
+
+ ref_scale
+ 2.0
+
+
+ fft_size
+ 1024
+
+
+ fft_rate
+ 15
+
+
+ peak_hold
+ False
+
+
+ average
+ False
+
+
+ avg_alpha
+ 0
+
+
+ win
+ None
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb0,3
+
+
+ freqvar
+ None
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (320, 667)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_scopesink2
+
+ id
+ wxgui_scopesink2_0_0_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ complex
+
+
+ title
+ Scope Plot
+
+
+ samp_rate
+ samp_rate/decimation
+
+
+ v_scale
+ 0
+
+
+ v_offset
+ 0
+
+
+ t_scale
+ 0
+
+
+ ac_couple
+ False
+
+
+ xy_mode
+ False
+
+
+ num_inputs
+ 1
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb0,3
+
+
+ trig_mode
+ wxgui.TRIG_MODE_NORM
+
+
+ y_axis_label
+ Counts
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (320, 883)
+
+
+ _rotation
+ 0
+
+
+
+ ha5kfu_execproc_xx
+
+ id
+ ha5kfu_execproc_xx_0_0_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ cc
+
+
+ commandline
+ "csdr decimating_shift_addition_cc %g %d"%(rate, decimation)
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (80, 835)
+
+
+ _rotation
+ 0
+
+
+
+ ha5kfu_execproc_xx
+
+ id
+ ha5kfu_execproc_xx_0_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ cc
+
+
+ commandline
+ "csdr shift_table_cc %g 32768"%rate
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ minoutbuf
+ 0
+
+
+ maxoutbuf
+ 0
+
+
+ _coordinate
+ (824, 771)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_fftsink2
+
+ id
+ wxgui_fftsink2_0_1_0
_enabled
@@ -381,7 +923,90 @@
_coordinate
- (952, 59)
+ (1080, 691)
+
+
+ _rotation
+ 0
+
+
+
+ wxgui_scopesink2
+
+ id
+ wxgui_scopesink2_0_0
+
+
+ _enabled
+ True
+
+
+ type
+ complex
+
+
+ title
+ Scope Plot
+
+
+ samp_rate
+ samp_rate
+
+
+ v_scale
+ 0
+
+
+ v_offset
+ 0
+
+
+ t_scale
+ 0
+
+
+ ac_couple
+ False
+
+
+ xy_mode
+ False
+
+
+ num_inputs
+ 1
+
+
+ win_size
+
+
+
+ grid_pos
+
+
+
+ notebook
+ nb0,1
+
+
+ trig_mode
+ wxgui.TRIG_MODE_NORM
+
+
+ y_axis_label
+ Counts
+
+
+ alias
+
+
+
+ affinity
+
+
+
+ _coordinate
+ (824, 571)
_rotation
@@ -480,58 +1105,7 @@
_coordinate
- (952, 635)
-
-
- _rotation
- 0
-
-
-
- blocks_throttle
-
- id
- blocks_throttle_0
-
-
- _enabled
- True
-
-
- type
- complex
-
-
- samples_per_second
- samp_rate
-
-
- vlen
- 1
-
-
- ignoretag
- True
-
-
- alias
-
-
-
- affinity
-
-
-
- minoutbuf
- 0
-
-
- maxoutbuf
- 0
-
-
- _coordinate
- (232, 275)
+ (824, 355)
_rotation
@@ -614,7 +1188,7 @@
_coordinate
- (952, 491)
+ (824, 235)
_rotation
@@ -622,10 +1196,10 @@
- wxgui_scopesink2
+ wxgui_fftsink2
id
- wxgui_scopesink2_0_0
+ wxgui_fftsink2_0
_enabled
@@ -637,35 +1211,55 @@
title
- Scope Plot
+ FFT Plot
samp_rate
samp_rate
- v_scale
+ baseband_freq
0
- v_offset
+ y_per_div
+ 10
+
+
+ y_divs
+ 10
+
+
+ ref_level
0
- t_scale
- 0
+ ref_scale
+ 2.0
- ac_couple
+ fft_size
+ 1024
+
+
+ fft_rate
+ 15
+
+
+ peak_hold
False
- xy_mode
+ average
False
- num_inputs
- 1
+ avg_alpha
+ 0
+
+
+ win
+ None
win_size
@@ -677,15 +1271,11 @@
notebook
- nb0,1
+ nb0,0
- trig_mode
- wxgui.TRIG_MODE_NORM
-
-
- y_axis_label
- Counts
+ freqvar
+ None
alias
@@ -697,93 +1287,7 @@
_coordinate
- (952, 875)
-
-
- _rotation
- 0
-
-
-
- ha5kfu_execproc_xx
-
- id
- ha5kfu_execproc_xx_0
-
-
- _enabled
- True
-
-
- type
- cc
-
-
- commandline
- csdr shift_math_cc -0.25
-
-
- alias
-
-
-
- affinity
-
-
-
- minoutbuf
- 0
-
-
- maxoutbuf
- 0
-
-
- _coordinate
- (496, 483)
-
-
- _rotation
- 0
-
-
-
- ha5kfu_execproc_xx
-
- id
- ha5kfu_execproc_xx_0_0
-
-
- _enabled
- True
-
-
- type
- cc
-
-
- commandline
- csdr shift_addition_cc -0.25
-
-
- alias
-
-
-
- affinity
-
-
-
- minoutbuf
- 0
-
-
- maxoutbuf
- 0
-
-
- _coordinate
- (504, 635)
+ (824, 19)
_rotation
@@ -838,4 +1342,40 @@
0
0
+
+ blocks_throttle_0
+ ha5kfu_execproc_xx_0_0_0
+ 0
+ 0
+
+
+ blocks_throttle_0
+ ha5kfu_execproc_xx_0_0_0_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0_0_0_0
+ wxgui_scopesink2_0_0_0_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0_0_0_0
+ wxgui_fftsink2_0_1_0_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0_0_0
+ wxgui_fftsink2_0_1_0
+ 0
+ 0
+
+
+ ha5kfu_execproc_xx_0_0_0
+ wxgui_scopesink2_0_0_0
+ 0
+ 0
+
diff --git a/ima_adpcm.c b/ima_adpcm.c
new file mode 100644
index 0000000..03a9b7c
--- /dev/null
+++ b/ima_adpcm.c
@@ -0,0 +1,176 @@
+/*
+
+This software is part of libcsdr, a set of simple DSP routines for
+Software Defined Radio.
+
+Copyright (c) 2015, Andras Retzler
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ANDRAS RETZLER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright 1997 Tim Kientzle. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ This product includes software developed by Tim Kientzle
+ and published in ``The Programmer's Guide to Sound.''
+4. Neither the names of Tim Kientzle nor Addison-Wesley
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL TIM KIENTZLE OR ADDISON-WESLEY BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/***********************************************************
+Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#ifdef USE_IMA_ADPCM
+
+#include "ima_adpcm.h"
+
+const int indexAdjustTable[16] = {
+ -1, -1, -1, -1, // +0 - +3, decrease the step size
+ 2, 4, 6, 8, // +4 - +7, increase the step size
+ -1, -1, -1, -1, // -0 - -3, decrease the step size
+ 2, 4, 6, 8, // -4 - -7, increase the step size
+};
+
+const int _stepSizeTable[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34,
+ 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
+ 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494,
+ 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552,
+ 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
+ 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
+ 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623,
+ 27086, 29794, 32767
+};
+
+static inline short ImaAdpcmDecode(unsigned char deltaCode, ima_adpcm_state_t* state) {
+ // Get the current step size
+ int step = _stepSizeTable[state->index];
+
+ // Construct the difference by scaling the current step size
+ // This is approximately: difference = (deltaCode+.5)*step/4
+ int difference = step>>3;
+ if ( deltaCode & 1 ) difference += step>>2;
+ if ( deltaCode & 2 ) difference += step>>1;
+ if ( deltaCode & 4 ) difference += step;
+ if ( deltaCode & 8 ) difference = -difference;
+
+ // Build the new sample
+ state->previousValue += difference;
+ if (state->previousValue > 32767) state->previousValue = 32767;
+ else if (state->previousValue < -32768) state->previousValue = -32768;
+
+ // Update the step for the next sample
+ state->index += indexAdjustTable[deltaCode];
+ if (state->index < 0) state->index = 0;
+ else if (state->index > 88) state->index = 88;
+
+ return state->previousValue;
+}
+
+static inline unsigned char ImaAdpcmEncode(short sample, ima_adpcm_state_t* state) {
+ int diff = sample - state->previousValue;
+ int step = _stepSizeTable[state->index];
+ int deltaCode = 0;
+
+ // Set sign bit
+ if (diff < 0) { deltaCode = 8; diff = -diff; }
+
+ // This is essentially deltaCode = (diff<<2)/step,
+ // except the roundoff is handled differently.
+ if ( diff >= step ) { deltaCode |= 4; diff -= step; }
+ step >>= 1;
+ if ( diff >= step ) { deltaCode |= 2; diff -= step; }
+ step >>= 1;
+ if ( diff >= step ) { deltaCode |= 1; diff -= step; }
+
+ ImaAdpcmDecode(deltaCode,state); // update state
+ return deltaCode;
+}
+
+ima_adpcm_state_t encode_ima_adpcm_i16_u8(short* input, unsigned char* output, int input_length, ima_adpcm_state_t state)
+{
+ int k=0;
+ for(int i=0;i>4)&0xf,&state);
+ }
+ return state;
+}
+
+#endif
diff --git a/ima_adpcm.h b/ima_adpcm.h
new file mode 100644
index 0000000..7e7bd9d
--- /dev/null
+++ b/ima_adpcm.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#ifdef USE_IMA_ADPCM
+
+typedef struct ImaState {
+ int index; // Index into step size table
+ int previousValue; // Most recent sample value
+} ima_adpcm_state_t;
+
+ima_adpcm_state_t encode_ima_adpcm_i16_u8(short* input, unsigned char* output, int input_length, ima_adpcm_state_t state);
+ima_adpcm_state_t decode_ima_adpcm_u8_i16(unsigned char* input, short* output, int input_length, ima_adpcm_state_t state);
+
+#endif
diff --git a/libcsdr.c b/libcsdr.c
index 7d6e449..2cf5e9b 100644
--- a/libcsdr.c
+++ b/libcsdr.c
@@ -205,6 +205,64 @@ float shift_math_cc(complexf *input, complexf* output, int input_size, float rat
return phase;
}
+
+
+shift_table_data_t shift_table_init(int table_size)
+{
+ //RTODO
+ shift_table_data_t output;
+ output.table=(float*)malloc(sizeof(float)*table_size);
+ output.table_size=table_size;
+ for(int i=0;i1)?-1:1; //in quadrant 2 and 3
+ cos_sign=(quadrant&&quadrant<3)?-1:1; //in quadrant 1 and 2
+ sinval=sin_sign*table_data.table[sin_index];
+ cosval=cos_sign*table_data.table[cos_index];
+ //we multiply two complex numbers.
+ //how? enter this to maxima (software) for explanation:
+ // (a+b*%i)*(c+d*%i), rectform;
+ iof(output,i)=cosval*iof(input,i)-sinval*qof(input,i);
+ qof(output,i)=sinval*iof(input,i)+cosval*qof(input,i);
+ phase+=phase_increment;
+ while(phase>2*PI) phase-=2*PI; //@shift_math_cc: normalize phase
+ while(phase<0) phase+=2*PI;
+ }
+ return phase;
+}
+
int fir_decimate_cc(complexf *input, complexf *output, int input_size, int decimation, float *taps, int taps_length)
{
//Theory: http://www.dspguru.com/dsp/faqs/multirate/decimation
@@ -339,6 +397,8 @@ fractional_decimator_ff_t fractional_decimator_ff(float* input, float* output, i
void apply_fir_fft_cc(FFT_PLAN_T* plan, FFT_PLAN_T* plan_inverse, complexf* taps_fft, complexf* last_overlap, int overlap_size)
{
+ //use the overlap & add method for filtering
+
//calculate FFT on input buffer
fft_execute(plan);
@@ -593,6 +653,14 @@ complexf fmdemod_quadri_cf(complexf* input, float* output, int input_size, float
return input[input_size-1];
}
+inline int is_nan(float f)
+{
+ //http://stackoverflow.com/questions/570669/checking-if-a-double-or-float-is-nan-in-c
+ unsigned u = *(unsigned*)&f;
+ return (u&0x7F800000) == 0x7F800000 && (u&0x7FFFFF); // Both NaN and qNan.
+}
+
+
float deemphasis_wfm_ff (float* input, float* output, int input_size, float tau, int sample_rate, float last_output)
{
/*
@@ -604,6 +672,7 @@ float deemphasis_wfm_ff (float* input, float* output, int input_size, float tau,
*/
float dt = 1.0/sample_rate;
float alpha = dt/(tau+dt);
+ if(is_nan(last_output)) last_output=0.0; //if last_output is NaN
output[0]=alpha*input[0]+(1-alpha)*last_output;
for (int i=1;iPI) s.starting_phase-=2*PI; //@shift_addition_cc: normalize starting_phase
+ while(s.starting_phase<-PI) s.starting_phase+=2*PI;
+ return s;
+}
+
+
float agc_ff(float* input, float* output, int input_size, float reference, float attack_rate, float decay_rate, float max_gain, short hang_time, short attack_wait_time, float gain_filter_alpha, float last_gain)
{
/*
diff --git a/libcsdr_gpl.h b/libcsdr_gpl.h
index 98c0feb..a4bfd23 100644
--- a/libcsdr_gpl.h
+++ b/libcsdr_gpl.h
@@ -35,5 +35,14 @@ void shift_addition_cc_test(shift_addition_data_t d);
float agc_ff(float* input, float* output, int input_size, float reference, float attack_rate, float decay_rate, float max_gain, short hang_time, short attack_wait_time, float gain_filter_alpha, float last_gain);
+typedef struct decimating_shift_addition_status_s
+{
+ int decimation_remain;
+ float starting_phase;
+ int output_size;
+} decimating_shift_addition_status_t;
+decimating_shift_addition_status_t decimating_shift_addition_cc(complexf *input, complexf* output, int input_size, shift_addition_data_t d, int decimation, decimating_shift_addition_status_t s);
+shift_addition_data_t decimating_shift_addition_init(float rate, int decimation);
+
#endif
diff --git a/libcsdr_wrapper.c b/libcsdr_wrapper.c
index 4ab53e3..3e6ab87 100644
--- a/libcsdr_wrapper.c
+++ b/libcsdr_wrapper.c
@@ -1,3 +1,4 @@
#include "libcsdr.c"
#include "libcsdr_gpl.c"
+#include "ima_adpcm.c"
//this wrapper helps parsevect.py to generate better output
diff --git a/predefined.h b/predefined.h
index e0c74bb..a00607f 100644
--- a/predefined.h
+++ b/predefined.h
@@ -50,11 +50,9 @@ function mkdeemph(sr,tapnum,norm_freq)
printf("%g, ",coeffs);
printf("\n")
end
-
-mkdeemph(48000,199,500)
-
*/
+//mkdeemph(48000,199,500)
float deemphasis_nfm_predefined_fir_48000[] =
{ 0.00172568, 0.00179665, 0.00191952, 0.00205318, 0.00215178, 0.00217534, 0.00209924, 0.00192026, 0.00165789, 0.0013502, 0.00104545, 0.000790927, 0.000621911, 0.000553077, 0.000574554, 0.000653624, 0.000741816, 0.000785877, 0.000740151, 0.000577506, 0.000296217, -7.89273e-05, -0.0005017, -0.000914683, -0.00126243, -0.00150456, -0.00162564, -0.0016396, -0.00158725, -0.00152751, -0.00152401, -0.00163025, -0.00187658, -0.00226223, -0.00275443, -0.003295, -0.0038132, -0.00424193, -0.00453375, -0.00467274, -0.00467943, -0.00460728, -0.00453119, -0.00453056, -0.00467051, -0.00498574, -0.00547096, -0.00608027, -0.00673627, -0.00734698, -0.00782705, -0.00811841, -0.00820539, -0.00812057, -0.00793936, -0.00776415, -0.00770111, -0.00783479, -0.00820643, -0.00880131, -0.00954878, -0.0103356, -0.0110303, -0.011514, -0.0117094, -0.0116029, -0.0112526, -0.0107795, -0.010343, -0.0101053, -0.0101917, -0.0106561, -0.0114608, -0.0124761, -0.0135018, -0.0143081, -0.0146885, -0.0145126, -0.0137683, -0.0125796, -0.0111959, -0.00994914, -0.00918404, -0.00917447, -0.0100402, -0.0116822, -0.0137533, -0.0156723, -0.0166881, -0.0159848, -0.0128153, -0.00664117, 0.00274383, 0.0151313, 0.0298729, 0.0459219, 0.0619393, 0.076451, 0.0880348, 0.0955087, 0.098091, 0.0955087, 0.0880348, 0.076451, 0.0619393, 0.0459219, 0.0298729, 0.0151313, 0.00274383, -0.00664117, -0.0128153, -0.0159848, -0.0166881, -0.0156723, -0.0137533, -0.0116822, -0.0100402, -0.00917447, -0.00918404, -0.00994914, -0.0111959, -0.0125796, -0.0137683, -0.0145126, -0.0146885, -0.0143081, -0.0135018, -0.0124761, -0.0114608, -0.0106561, -0.0101917, -0.0101053, -0.010343, -0.0107795, -0.0112526, -0.0116029, -0.0117094, -0.011514, -0.0110303, -0.0103356, -0.00954878, -0.00880131, -0.00820643, -0.00783479, -0.00770111, -0.00776415, -0.00793936, -0.00812057, -0.00820539, -0.00811841, -0.00782705, -0.00734698, -0.00673627, -0.00608027, -0.00547096, -0.00498574, -0.00467051, -0.00453056, -0.00453119, -0.00460728, -0.00467943, -0.00467274, -0.00453375, -0.00424193, -0.0038132, -0.003295, -0.00275443, -0.00226223, -0.00187658, -0.00163025, -0.00152401, -0.00152751, -0.00158725, -0.0016396, -0.00162564, -0.00150456, -0.00126243, -0.000914683, -0.0005017, -7.89273e-05, 0.000296217, 0.000577506, 0.000740151, 0.000785877, 0.000741816, 0.000653624, 0.000574554, 0.000553077, 0.000621911, 0.000790927, 0.00104545, 0.0013502, 0.00165789, 0.00192026, 0.00209924, 0.00217534, 0.00215178, 0.00205318, 0.00191952, 0.00179665, 0.00172568 };
@@ -64,3 +62,7 @@ float deemphasis_nfm_predefined_fir_8000[] =
float deemphasis_nfm_predefined_fir_44100[] =
{ 0.0025158, 0.00308564, 0.00365507, 0.00413598, 0.00446279, 0.00461162, 0.00460866, 0.00452474, 0.00445739, 0.00450444, 0.00473648, 0.0051757, 0.0057872, 0.00648603, 0.00715856, 0.00769296, 0.00801081, 0.00809096, 0.00797853, 0.00777577, 0.00761627, 0.00762871, 0.00789987, 0.00844699, 0.00920814, 0.0100543, 0.0108212, 0.0113537, 0.011551, 0.0113994, 0.0109834, 0.0104698, 0.0100665, 0.00996618, 0.0102884, 0.0110369, 0.0120856, 0.0131998, 0.0140907, 0.0144924, 0.0142417, 0.0133401, 0.0119771, 0.0105043, 0.00935909, 0.00895022, 0.00952985, 0.0110812, 0.0132522, 0.015359, 0.0164664, 0.0155409, 0.0116496, 0.00416925, -0.00703664, -0.021514, -0.0382135, -0.0555955, -0.0718318, -0.0850729, -0.0937334, -0.0967458, -0.0937334, -0.0850729, -0.0718318, -0.0555955, -0.0382135, -0.021514, -0.00703664, 0.00416925, 0.0116496, 0.0155409, 0.0164664, 0.015359, 0.0132522, 0.0110812, 0.00952985, 0.00895022, 0.00935909, 0.0105043, 0.0119771, 0.0133401, 0.0142417, 0.0144924, 0.0140907, 0.0131998, 0.0120856, 0.0110369, 0.0102884, 0.00996618, 0.0100665, 0.0104698, 0.0109834, 0.0113994, 0.011551, 0.0113537, 0.0108212, 0.0100543, 0.00920814, 0.00844699, 0.00789987, 0.00762871, 0.00761627, 0.00777577, 0.00797853, 0.00809096, 0.00801081, 0.00769296, 0.00715856, 0.00648603, 0.0057872, 0.0051757, 0.00473648, 0.00450444, 0.00445739, 0.00452474, 0.00460866, 0.00461162, 0.00446279, 0.00413598, 0.00365507, 0.00308564, 0.0025158 };
+
+//mkdeemph(11025,79,500)
+float deemphasis_nfm_predefined_fir_11025[] =
+{ 0.00113162, 0.000911207, 0.00173815, -0.000341385, -0.000849373, -0.00033066, -0.00290692, -0.00357326, -0.0031917, -0.00607078, -0.00659201, -0.00601551, -0.00886603, -0.00880243, -0.00759841, -0.0100344, -0.0088993, -0.00664423, -0.00835258, -0.00572919, -0.00214109, -0.00302443, 0.00132902, 0.00627003, 0.00596494, 0.0120731, 0.0180437, 0.0176243, 0.0253776, 0.0316572, 0.0298485, 0.0393389, 0.0446019, 0.0389943, 0.0516463, 0.0521951, 0.0350192, 0.0600945, 0.0163128, -0.217526, -0.378533, -0.217526, 0.0163128, 0.0600945, 0.0350192, 0.0521951, 0.0516463, 0.0389943, 0.0446019, 0.0393389, 0.0298485, 0.0316572, 0.0253776, 0.0176243, 0.0180437, 0.0120731, 0.00596494, 0.00627003, 0.00132902, -0.00302443, -0.00214109, -0.00572919, -0.00835258, -0.00664423, -0.0088993, -0.0100344, -0.00759841, -0.00880243, -0.00886603, -0.00601551, -0.00659201, -0.00607078, -0.0031917, -0.00357326, -0.00290692, -0.00033066, -0.000849373, -0.000341385, 0.00173815, 0.000911207, 0.00113162 };
diff --git a/sdr.js/exported_functions.py b/sdr.js/exported_functions.py
new file mode 100644
index 0000000..28b0021
--- /dev/null
+++ b/sdr.js/exported_functions.py
@@ -0,0 +1,81 @@
+"""
+This software is part of libcsdr, a set of simple DSP routines for
+Software Defined Radio.
+
+Copyright (c) 2014, Andras Retzler
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ANDRAS RETZLER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""
+
+
+exported_functions= \
+"""firdes_lowpass_f
+firdes_bandpass_c
+firdes_wkernel_blackman
+firdes_wkernel_hamming
+firdes_wkernel_boxcar
+firdes_get_window_from_string
+firdes_get_string_from_window
+firdes_filter_len
+fmdemod_quadri_cf
+fmdemod_quadri_novect_cf
+fmdemod_atan_cf
+amdemod_cf
+amdemod_estimator_cf
+limit_ff
+fir_decimate_cc
+deemphasis_nfm_ff
+deemphasis_wfm_ff
+shift_math_cc
+dcblock_ff
+fastdcblock_ff
+fastagc_ff
+rational_resampler_ff
+rational_resampler_get_lowpass_f
+apply_window_c
+apply_window_f
+logpower_cf
+fractional_decimator_ff
+shift_table_deinit
+shift_table_init
+shift_table_cc
+log2n
+next_pow2
+apply_fir_fft_cc
+gain_ff
+convert_u8_f
+convert_f_u8
+convert_f_i16
+convert_i16_f
+shift_addition_init
+shift_addition_cc
+shift_addition_cc_test
+agc_ff
+decimating_shift_addition_cc
+decimating_shift_addition_init
+encode_ima_adpcm_i16_u8
+decode_ima_adpcm_u8_i16"""
+
+exported_functions_quoted=map(lambda x:"'_"+x+"'",exported_functions.split("\n"))
+print "["+(", ".join(exported_functions_quoted))+"]"
diff --git a/sdr.js/sdrjs-footer.js b/sdr.js/sdrjs-footer.js
new file mode 100644
index 0000000..21ea992
--- /dev/null
+++ b/sdr.js/sdrjs-footer.js
@@ -0,0 +1,296 @@
+// ==========================================================
+// ========= / THE CODE COMPILED BY EMCC ENDS HERE ==========
+// ==========================================================
+
+asm$ =
+{
+ malloc: function(type, size)
+ {
+ real_size=size*type.BYTES_PER_ELEMENT;
+ pointer = Module._malloc(real_size);
+ heap = new Uint8Array(Module.HEAPU8.buffer, pointer, real_size);
+ return {
+ asm$: true,
+ ptr: heap.byteOffset,
+ free: function() { Module._free(this.ptr); },
+ arr: new type(heap.buffer, heap.byteOffset, size),
+ size: size
+ };
+ },
+ cpy: function(dst, dst_offset, src, src_offset, size)
+ {
+ if(typeof dst.asm$!='undefined') dst=dst.arr;
+ if(typeof src.asm$!='undefined') src=src.arr;
+ for(var i=0;i rwithin");
+ for(var i=0;i this.buffer_size)
+ {
+ return new Float32Array(0); console.log("sdrjs.RationalResamplerFF: critical audio buffering error"); //This should not happen...
+ /* console.log("RationalResamplerFF: splitting..."); //TODO: this branch has not been checked
+ output_buffers=Array();
+ new_buffer_size=this.buffer_size/2;
+ i=0;
+ //process the input in chunks of new_buffer_size, and add the output product Float32Array-s to output_buffers.
+ while((i++)*new_buffer_size<=input.length)
+ {
+ output_buffers.push(this._process_noheapcheck(input.subarray(i*new_buffer_size,(i+1)*new_buffer_size)));
+ }
+ //add up the sizes of the output_buffer-s.
+ total_output_length=0;
+ output_buffers.forEach(function(a){total_output_length+=a.length;});
+ //create one big buffer from concatenating the output_buffer-s
+ output=new Float32Array(total_output_length);
+ output_pos=0;
+ output_buffers.forEach(function(a){
+ asm$.cpy(output,output_pos,a,0,a.length);
+ output_pos+=a.length;
+ });
+ return output;*/
+ }
+ else return this._process_noheapcheck(input);
+ };
+ this._process_noheapcheck=function(input) //if we are sure we have enough space in the buffers
+ {
+ asm$.cpy(this.input_buffer.arr,0,this.input_buffer.arr,this.remain_offset,this.remain);
+ asm$.cpy(this.input_buffer.arr, this.remain, input, 0, input.length);
+ var total_input_size=input.length+this.remain;
+ 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);
+ this.last_taps_delay=d.last_taps_delay;
+ this.remain=total_input_size-d.input_processed;
+ this.remain_offset=d.input_processed;
+ var output_copy_arr=new Float32Array(d.output_size);
+ asm$.cpy(output_copy_arr,0,this.output_buffer.arr,0,d.output_size);
+ return output_copy_arr;
+ };
+};
+
+
+_sdrjs_logb=function(what) { document.body.innerHTML+=what+"
"; }
+
+
+function test_firdes_lowpass_f_original()
+{
+ //Original method explained over here:
+ //http://kapadia.github.io/emscripten/2013/09/13/emscripten-pointers-and-pointers.html
+ _sdrjs_logb("test_firdes_lowpass_f_original():");
+ _sdrjs_logb("Now designing FIR filter with firdes_lowpass_f in sdr.js...");
+ _sdrjs_logb("output should be the same as: csdr firdes_lowpass_f 0.1 101 HAMMING");
+
+ var outputSize = 101*4;
+ var outputPtr = Module._malloc(outputSize);
+ var outputHeap = new Uint8Array(Module.HEAPU8.buffer, outputPtr, outputSize);
+ firdes_lowpass_f(outputHeap.byteOffset,101,0.1,2);
+ var output = new Float32Array(outputHeap.buffer, outputHeap.byteOffset, 101);
+ outputStr=String();
+ for(i=0;icsdr firdes_lowpass_f 0.1 101 HAMMING");
+
+ output=asm$.malloc(Float32Array,101);
+ firdes_lowpass_f(output.ptr,101,0.1,2);
+ outputStr=String();
+ for(i=0;i
+ Copyright (c) Warren Pratt, NR0V
+ Copyright 2006,2010,2012 Free Software Foundation, Inc.
+
+ libcsdr is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ libcsdr is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libcsdr. If not, see .
+*/
+
+// ==========================================================
+// ========= THE CODE COMPILED BY EMCC STARTS HERE: =========
+// ==========================================================
+