roctave 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +33 -0
  4. data/ext/roctave/cu8_file_reader.c +331 -0
  5. data/ext/roctave/cu8_file_reader.h +30 -0
  6. data/ext/roctave/extconf.rb +6 -0
  7. data/ext/roctave/fir_filter.c +795 -0
  8. data/ext/roctave/fir_filter.h +29 -0
  9. data/ext/roctave/freq_shifter.c +410 -0
  10. data/ext/roctave/freq_shifter.h +29 -0
  11. data/ext/roctave/iir_filter.c +462 -0
  12. data/ext/roctave/iir_filter.h +29 -0
  13. data/ext/roctave/roctave.c +38 -0
  14. data/ext/roctave/roctave.h +27 -0
  15. data/lib/roctave.rb +168 -0
  16. data/lib/roctave/bilinear.rb +92 -0
  17. data/lib/roctave/butter.rb +87 -0
  18. data/lib/roctave/cheby.rb +180 -0
  19. data/lib/roctave/cu8_file_reader.rb +45 -0
  20. data/lib/roctave/dft.rb +280 -0
  21. data/lib/roctave/filter.rb +64 -0
  22. data/lib/roctave/finite_difference_coefficients.rb +73 -0
  23. data/lib/roctave/fir.rb +121 -0
  24. data/lib/roctave/fir1.rb +134 -0
  25. data/lib/roctave/fir2.rb +246 -0
  26. data/lib/roctave/fir_design.rb +311 -0
  27. data/lib/roctave/firls.rb +380 -0
  28. data/lib/roctave/firpm.rb +499 -0
  29. data/lib/roctave/freq_shifter.rb +47 -0
  30. data/lib/roctave/freqz.rb +233 -0
  31. data/lib/roctave/iir.rb +80 -0
  32. data/lib/roctave/interp1.rb +78 -0
  33. data/lib/roctave/plot.rb +748 -0
  34. data/lib/roctave/poly.rb +46 -0
  35. data/lib/roctave/roots.rb +73 -0
  36. data/lib/roctave/sftrans.rb +157 -0
  37. data/lib/roctave/version.rb +3 -0
  38. data/lib/roctave/window.rb +116 -0
  39. data/roctave.gemspec +79 -0
  40. data/samples/butter.rb +12 -0
  41. data/samples/cheby.rb +28 -0
  42. data/samples/dft.rb +18 -0
  43. data/samples/differentiator.rb +48 -0
  44. data/samples/differentiator_frequency_scaling.rb +52 -0
  45. data/samples/fft.rb +40 -0
  46. data/samples/finite_difference_coefficient.rb +53 -0
  47. data/samples/fir1.rb +13 -0
  48. data/samples/fir2.rb +14 -0
  49. data/samples/fir2_windows.rb +29 -0
  50. data/samples/fir2bank.rb +30 -0
  51. data/samples/fir_low_pass.rb +44 -0
  52. data/samples/firls.rb +77 -0
  53. data/samples/firpm.rb +78 -0
  54. data/samples/hilbert_transformer.rb +20 -0
  55. data/samples/hilbert_transformer_frequency_scaling.rb +47 -0
  56. data/samples/plot.rb +45 -0
  57. data/samples/stem.rb +8 -0
  58. data/samples/type1.rb +25 -0
  59. data/samples/type3.rb +24 -0
  60. data/samples/windows.rb +25 -0
  61. metadata +123 -0
@@ -0,0 +1,29 @@
1
+ /* Copyright (C) 2019 Théotime Bollengier <theotime.bollengier@gmail.com>
2
+ *
3
+ * This file is part of Roctave
4
+ *
5
+ * Roctave is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * Roctave is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with Roctave. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+
19
+
20
+ #ifndef FIR_FILTER_H
21
+ #define FIR_FILTER_H
22
+
23
+ #include <ruby.h>
24
+
25
+ extern VALUE c_FIR;
26
+
27
+ void Init_fir_filter();
28
+
29
+ #endif /* FIR_FILTER_H */
@@ -0,0 +1,410 @@
1
+ /* Copyright (C) 2019 Théotime Bollengier <theotime.bollengier@gmail.com>
2
+ *
3
+ * This file is part of Roctave
4
+ *
5
+ * Roctave is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * Roctave is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with Roctave. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+
19
+
20
+ #include <ruby.h>
21
+ #include "roctave.h"
22
+ #include "freq_shifter.h"
23
+
24
+ VALUE c_FreqShifter;
25
+
26
+
27
+ static ID id_real;
28
+ static ID id_imag;
29
+ static ID id_freq;
30
+ static ID id_fs;
31
+ static ID id_initial_phase;
32
+
33
+
34
+ struct freq_shifter {
35
+ double phase;
36
+ double sampling_frequency;
37
+ double frequency;
38
+ double phase_increment;
39
+ };
40
+
41
+
42
+ static void freq_shifter_free(void *p)
43
+ {
44
+ struct freq_shifter *frqsh = (struct freq_shifter*)p;
45
+
46
+ xfree(frqsh);
47
+ }
48
+
49
+
50
+ static size_t freq_shifter_size(const void* data)
51
+ {
52
+ return sizeof(struct freq_shifter);
53
+ }
54
+
55
+
56
+ static const rb_data_type_t freq_shifter_type = {
57
+ .wrap_struct_name = "roctave_freq_shifter_struct",
58
+ .function = {
59
+ .dmark = NULL,
60
+ .dfree = freq_shifter_free,
61
+ .dsize = freq_shifter_size,
62
+ },
63
+ .data = NULL,
64
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
65
+ };
66
+
67
+
68
+ static VALUE freq_shifter_alloc(VALUE klass)
69
+ {
70
+ VALUE obj;
71
+ struct freq_shifter *frqsh;
72
+
73
+ frqsh = ZALLOC(struct freq_shifter);
74
+
75
+ obj = TypedData_Wrap_Struct(klass, &freq_shifter_type, frqsh);
76
+
77
+ frqsh->phase = 0.0;
78
+ frqsh->sampling_frequency = 1.0;
79
+ frqsh->frequency = 1.0;
80
+ frqsh->phase_increment = 2.0*M_PI*frqsh->frequency/frqsh->sampling_frequency;
81
+
82
+ return obj;
83
+ }
84
+
85
+
86
+ /* @overload initialize(freq: 0.5, fs: 1.0, initial_phase: 0.0)
87
+ * @param freq [Float] the amount of frequency to shift
88
+ * @param fs [Float] the sampling frequency
89
+ * @param initial_phase [Float] the initial phase of the oscillator
90
+ * @return [Roctave::FreqShifter]
91
+ */
92
+ static VALUE freq_shifter_initialize(int argc, VALUE *argv, VALUE self)
93
+ {
94
+ struct freq_shifter *frqsh;
95
+ VALUE hash;
96
+ const ID kwkeys[] = {id_freq, id_fs, id_initial_phase};
97
+ VALUE kwvalues[] = {Qundef, Qundef, Qundef};
98
+
99
+ // int i;
100
+ // for (i = 0; i < argc; i++)
101
+ // rb_warn("argv[%d] = %"PRIsVALUE, i, rb_class_name(rb_obj_class(argv[i])));
102
+
103
+ rb_scan_args(argc, argv, ":", &hash);
104
+
105
+ if (!NIL_P(hash))
106
+ rb_get_kwargs(hash, kwkeys, 0, 3, kwvalues);
107
+
108
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
109
+
110
+ if (kwvalues[0] != Qundef)
111
+ frqsh->frequency = NUM2DBL(kwvalues[0]);
112
+ else
113
+ frqsh->frequency = 0.5;
114
+
115
+ if (kwvalues[1] != Qundef)
116
+ if (NUM2DBL(kwvalues[1]) > 0.0) frqsh->sampling_frequency = NUM2DBL(kwvalues[1]);
117
+ else
118
+ frqsh->sampling_frequency = 1.0;
119
+
120
+ if (kwvalues[2] != Qundef)
121
+ frqsh->phase = fmod(NUM2DBL(kwvalues[2]), 2.0*M_PI);
122
+ else
123
+ frqsh->phase = 0.0;
124
+
125
+ frqsh->phase_increment = 2.0*M_PI*frqsh->frequency/frqsh->sampling_frequency;
126
+
127
+ // rb_warn(" ");
128
+ // rb_warn("phase = %g", frqsh->phase);
129
+ // rb_warn("frequency = %g", frqsh->frequency);
130
+ // rb_warn("sampling_frequency = %g", frqsh->sampling_frequency);
131
+ // rb_warn(" ");
132
+
133
+ return self;
134
+ }
135
+
136
+
137
+ /* Get the current phase of the oscillator.
138
+ * @return [Float] the current phase of the oscillator
139
+ */
140
+ static VALUE freq_shifter_get_phase(VALUE self)
141
+ {
142
+ struct freq_shifter *frqsh;
143
+
144
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
145
+
146
+ return DBL2NUM(frqsh->phase);
147
+ }
148
+
149
+
150
+ /* Set the current phase of the oscillator.
151
+ * @param phase [Float] the requested phase of the oscillator
152
+ * @return [Float] the phase of the oscillator
153
+ */
154
+ static VALUE freq_shifter_set_phase(VALUE self, VALUE phase)
155
+ {
156
+ struct freq_shifter *frqsh;
157
+
158
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
159
+
160
+ frqsh->phase = fmod(NUM2DBL(phase), 2.0*M_PI);
161
+
162
+ return DBL2NUM(frqsh->phase);
163
+ }
164
+
165
+
166
+ /* Get the sampling frequency
167
+ * @return [Float] the sampling frequency
168
+ */
169
+ static VALUE freq_shifter_get_sampling_frequency(VALUE self)
170
+ {
171
+ struct freq_shifter *frqsh;
172
+
173
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
174
+
175
+ return DBL2NUM(frqsh->sampling_frequency);
176
+ }
177
+
178
+
179
+ /* Set the sampling frequency
180
+ * @param fs [Float] the requested sampling frequency. Must be > 0.
181
+ * @return [Float] the sampling frequency
182
+ */
183
+ static VALUE freq_shifter_set_sampling_frequency(VALUE self, VALUE fs)
184
+ {
185
+ struct freq_shifter *frqsh;
186
+
187
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
188
+
189
+ if (NUM2DBL(fs) > 0.0)
190
+ frqsh->sampling_frequency = NUM2DBL(fs);
191
+
192
+ frqsh->phase_increment = 2.0*M_PI*frqsh->frequency/frqsh->sampling_frequency;
193
+
194
+ return DBL2NUM(frqsh->sampling_frequency);
195
+ }
196
+
197
+
198
+ /* Get the frequency
199
+ * @return [Float] the frequency
200
+ */
201
+ static VALUE freq_shifter_get_frequency(VALUE self)
202
+ {
203
+ struct freq_shifter *frqsh;
204
+
205
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
206
+
207
+ return DBL2NUM(frqsh->frequency);
208
+ }
209
+
210
+
211
+ /* Set the frequency
212
+ * @param f [Float] the requested frequency. Must be > 0.
213
+ * @return [Float] the frequency
214
+ */
215
+ static VALUE freq_shifter_set_frequency(VALUE self, VALUE f)
216
+ {
217
+ struct freq_shifter *frqsh;
218
+
219
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
220
+
221
+ frqsh->sampling_frequency = NUM2DBL(f);
222
+
223
+ frqsh->phase_increment = 2.0*M_PI*frqsh->frequency/frqsh->sampling_frequency;
224
+
225
+ return DBL2NUM(frqsh->frequency);
226
+ }
227
+
228
+
229
+ static VALUE freq_shifter_shift_one_sample(struct freq_shifter *frqsh, VALUE sample)
230
+ {
231
+ const double i = cos(frqsh->phase);
232
+ const double q = sin(frqsh->phase);
233
+ double real, imag;
234
+ VALUE res;
235
+
236
+ if (rb_class_of(sample) == rb_cComplex) {
237
+ real = NUM2DBL(rb_funcallv(sample, id_real, 0, NULL));
238
+ imag = NUM2DBL(rb_funcallv(sample, id_imag, 0, NULL));
239
+ res = rb_complex_raw(
240
+ DBL2NUM(real*i - imag*q),
241
+ DBL2NUM(real*q + imag*i));
242
+ }
243
+ else {
244
+ real = NUM2DBL(sample);
245
+ res = rb_complex_raw(
246
+ DBL2NUM(real*i),
247
+ DBL2NUM(real*q));
248
+ }
249
+
250
+ frqsh->phase = fmod(frqsh->phase + frqsh->phase_increment, 2*M_PI);
251
+
252
+ return res;
253
+ }
254
+
255
+
256
+ static VALUE freq_shifter_am_one_sample(struct freq_shifter *frqsh, VALUE sample)
257
+ {
258
+ const double i = cos(frqsh->phase);
259
+ double real, imag;
260
+ VALUE res;
261
+
262
+ if (rb_class_of(sample) == rb_cComplex) {
263
+ real = NUM2DBL(rb_funcallv(sample, id_real, 0, NULL));
264
+ imag = NUM2DBL(rb_funcallv(sample, id_imag, 0, NULL));
265
+ res = rb_complex_raw(
266
+ DBL2NUM(real*i),
267
+ DBL2NUM(imag*i));
268
+ }
269
+ else
270
+ res = DBL2NUM(NUM2DBL(sample) * i);
271
+
272
+ frqsh->phase = fmod(frqsh->phase + frqsh->phase_increment, 2*M_PI);
273
+
274
+ return res;
275
+ }
276
+
277
+
278
+ /* Multiply the signal with exp(2*i*pi*f*t)
279
+ * @param signal [Array<Float,Complex>, Float, Complex] a single or and array of float or complex numbers
280
+ * @return [Array<Float,Complex>, Float, Complex] a single or and array of float or complex numbers
281
+ */
282
+ static VALUE freq_shifter_shift(VALUE self, VALUE sig)
283
+ {
284
+ struct freq_shifter *frqsh;
285
+ VALUE res;
286
+ int len, i;
287
+
288
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
289
+
290
+ if (rb_class_of(sig) == rb_cArray) {
291
+ len = rb_array_len(sig);
292
+ res = rb_ary_new_capa(len);
293
+ for (i = 0; i < len; i++)
294
+ rb_ary_store(res, i, freq_shifter_shift_one_sample(frqsh, rb_ary_entry(sig, i)));
295
+ }
296
+ else {
297
+ res = freq_shifter_shift_one_sample(frqsh, sig);
298
+ }
299
+
300
+ return res;
301
+ }
302
+
303
+
304
+ /* Multiply the signal with cos(2*i*pi*f*t)
305
+ * @param signal [Array<Float,Complex>, Float, Complex] a single or and array of float or complex numbers
306
+ * @return [Array<Float,Complex>, Float, Complex] a single or and array of float or complex numbers
307
+ */
308
+ static VALUE freq_shifter_am(VALUE self, VALUE sig)
309
+ {
310
+ struct freq_shifter *frqsh;
311
+ VALUE res;
312
+ int len, i;
313
+
314
+ TypedData_Get_Struct(self, struct freq_shifter, &freq_shifter_type, frqsh);
315
+
316
+ if (rb_class_of(sig) == rb_cArray) {
317
+ len = rb_array_len(sig);
318
+ res = rb_ary_new_capa(len);
319
+ for (i = 0; i < len; i++)
320
+ rb_ary_store(res, i, freq_shifter_am_one_sample(frqsh, rb_ary_entry(sig, i)));
321
+ }
322
+ else {
323
+ res = freq_shifter_am_one_sample(frqsh, sig);
324
+ }
325
+
326
+ return res;
327
+ }
328
+
329
+
330
+ #if 0
331
+ // Makes segmentation faults, maybe because rbo is garbage collected
332
+ // befor it can finish its shift.
333
+
334
+ /* Multiply the signal with exp(2*i*pi*f*t)
335
+ * @overload shift(signal, freq: 0.5, fs: 1.0, initial_phase: 0.0)
336
+ * @param signal [Array<Float,Complex>, Float, Complex] a single or and array of float or complex numbers
337
+ * @param freq [Float] the amount of frequency to shift
338
+ * @param fs [Float] the sampling frequency
339
+ * @param initial_phase [Float] the initial phase of the oscillator
340
+ * @return [Array<Float,Complex>, Float, Complex] a single or and array of float or complex numbers
341
+ */
342
+ static VALUE freq_shifter_module_shift(int argc, VALUE *argv, VALUE self)
343
+ {
344
+ VALUE sig;
345
+ VALUE hash;
346
+ VALUE rbo;
347
+ VALUE res;
348
+
349
+ rb_scan_args(argc, argv, "1:", &sig, &hash);
350
+
351
+ if (NIL_P(hash))
352
+ hash = rb_hash_new();
353
+
354
+ rbo = rb_class_new_instance(1, &hash, c_FreqShifter);
355
+ res = freq_shifter_shift(rbo, sig);
356
+
357
+ return res;
358
+ }
359
+
360
+
361
+ /* Multiply the signal with cos(2*i*pi*f*t)
362
+ * @overload shift(signal, freq: 0.5, fs: 1.0, initial_phase: 0.0)
363
+ * @param signal [Array<Float,Complex>, Float, Complex] a single or and array of float or complex numbers
364
+ * @param freq [Float] the amount of frequency to shift
365
+ * @param fs [Float] the sampling frequency
366
+ * @param initial_phase [Float] the initial phase of the oscillator
367
+ * @return [Array<Float,Complex>, Float, Complex] a single or and array of float or complex numbers
368
+ */
369
+ static VALUE freq_shifter_module_am(int argc, VALUE *argv, VALUE self)
370
+ {
371
+ VALUE sig;
372
+ VALUE hash;
373
+ VALUE rbo;
374
+
375
+ rb_scan_args(argc, argv, "1:", &sig, &hash);
376
+
377
+ if (NIL_P(hash))
378
+ hash = rb_hash_new();
379
+
380
+ rbo = rb_class_new_instance(1, &hash, c_FreqShifter);
381
+
382
+ return freq_shifter_am(rbo, sig);
383
+ }
384
+ #endif
385
+
386
+
387
+ void Init_freq_shifter()
388
+ {
389
+ id_real = rb_intern("real");
390
+ id_imag = rb_intern("imag");
391
+ id_freq = rb_intern("freq");
392
+ id_fs = rb_intern("fs");
393
+ id_initial_phase = rb_intern("initial_phase");
394
+
395
+ c_FreqShifter = rb_define_class_under(m_Roctave, "FreqShifter", rb_cData);
396
+
397
+ rb_define_alloc_func(c_FreqShifter, freq_shifter_alloc);
398
+ //rb_define_singleton_method(c_FreqShifter, "shift", freq_shifter_module_shift, -1);
399
+ //rb_define_singleton_method(c_FreqShifter, "amplitude_modulate", freq_shifter_module_am, -1);
400
+ rb_define_method(c_FreqShifter, "initialize", freq_shifter_initialize, -1);
401
+ rb_define_method(c_FreqShifter, "shift", freq_shifter_shift, 1);
402
+ rb_define_method(c_FreqShifter, "amplitude_modulate", freq_shifter_am, 1);
403
+ rb_define_method(c_FreqShifter, "frequency", freq_shifter_get_frequency, 0);
404
+ rb_define_method(c_FreqShifter, "frequency=", freq_shifter_set_frequency, 1);
405
+ rb_define_method(c_FreqShifter, "sampling_frequency", freq_shifter_get_sampling_frequency, 0);
406
+ rb_define_method(c_FreqShifter, "sampling_frequency=", freq_shifter_set_sampling_frequency, 1);
407
+ rb_define_method(c_FreqShifter, "phase", freq_shifter_get_phase, 0);
408
+ rb_define_method(c_FreqShifter, "phase=", freq_shifter_set_phase, 1);
409
+ }
410
+
@@ -0,0 +1,29 @@
1
+ /* Copyright (C) 2019 Théotime Bollengier <theotime.bollengier@gmail.com>
2
+ *
3
+ * This file is part of Roctave
4
+ *
5
+ * Roctave is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * Roctave is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with Roctave. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+
19
+
20
+ #ifndef FREQ_SHIFTER_H
21
+ #define FREQ_SHIFTER_H
22
+
23
+ #include <ruby.h>
24
+
25
+ extern VALUE c_FreqShifter;
26
+
27
+ void Init_freq_shifter();
28
+
29
+ #endif /* FREQ_SHIFTER_H */