Skip to content

Commit c0b3262

Browse files
authored
Add keyword arguments to spectrogram (#657)
* re-work spectrogram method, so that RAM can be re-used * update docs with spectrogram changes
1 parent 45f23eb commit c0b3262

16 files changed

+434
-133
lines changed

code/numpy/fft/fft.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* The MIT License (MIT)
77
*
8-
* Copyright (c) 2019-2021 Zoltán Vörös
8+
* Copyright (c) 2019-2024 Zoltán Vörös
99
* 2020 Scott Shawcroft for Adafruit Industries
1010
* 2020 Taku Fukada
1111
*/
@@ -43,16 +43,16 @@
4343
//|
4444
#if ULAB_SUPPORTS_COMPLEX & ULAB_FFT_IS_NUMPY_COMPATIBLE
4545
static mp_obj_t fft_fft(mp_obj_t arg) {
46-
return fft_fft_ifft_spectrogram(arg, FFT_FFT);
46+
return fft_fft_ifft(arg, FFT_FFT);
4747
}
4848

4949
MP_DEFINE_CONST_FUN_OBJ_1(fft_fft_obj, fft_fft);
5050
#else
5151
static mp_obj_t fft_fft(size_t n_args, const mp_obj_t *args) {
5252
if(n_args == 2) {
53-
return fft_fft_ifft_spectrogram(n_args, args[0], args[1], FFT_FFT);
53+
return fft_fft_ifft(n_args, args[0], args[1], FFT_FFT);
5454
} else {
55-
return fft_fft_ifft_spectrogram(n_args, args[0], mp_const_none, FFT_FFT);
55+
return fft_fft_ifft(n_args, args[0], mp_const_none, FFT_FFT);
5656
}
5757
}
5858

@@ -71,17 +71,17 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fft_fft_obj, 1, 2, fft_fft);
7171

7272
#if ULAB_SUPPORTS_COMPLEX & ULAB_FFT_IS_NUMPY_COMPATIBLE
7373
static mp_obj_t fft_ifft(mp_obj_t arg) {
74-
return fft_fft_ifft_spectrogram(arg, FFT_IFFT);
74+
return fft_fft_ifft(arg, FFT_IFFT);
7575
}
7676

7777
MP_DEFINE_CONST_FUN_OBJ_1(fft_ifft_obj, fft_ifft);
7878
#else
7979
static mp_obj_t fft_ifft(size_t n_args, const mp_obj_t *args) {
8080
NOT_IMPLEMENTED_FOR_COMPLEX()
8181
if(n_args == 2) {
82-
return fft_fft_ifft_spectrogram(n_args, args[0], args[1], FFT_IFFT);
82+
return fft_fft_ifft(n_args, args[0], args[1], FFT_IFFT);
8383
} else {
84-
return fft_fft_ifft_spectrogram(n_args, args[0], mp_const_none, FFT_IFFT);
84+
return fft_fft_ifft(n_args, args[0], mp_const_none, FFT_IFFT);
8585
}
8686
}
8787

code/numpy/fft/fft_tools.c

+13-34
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* The MIT License (MIT)
77
*
8-
* Copyright (c) 2019-2021 Zoltán Vörös
8+
* Copyright (c) 2019-2024 Zoltán Vörös
99
*/
1010

1111
#include <math.h>
@@ -45,7 +45,7 @@
4545
imag[i] = data[2i+1]
4646
4747
*/
48-
void fft_kernel_complex(mp_float_t *data, size_t n, int isign) {
48+
void fft_kernel(mp_float_t *data, size_t n, int isign) {
4949
size_t j, m, mmax, istep;
5050
mp_float_t tempr, tempi;
5151
mp_float_t wtemp, wr, wpr, wpi, wi, theta;
@@ -94,9 +94,9 @@ void fft_kernel_complex(mp_float_t *data, size_t n, int isign) {
9494
/*
9595
* The following function is a helper interface to the python side.
9696
* It has been factored out from fft.c, so that the same argument parsing
97-
* routine can be called from scipy.signal.spectrogram.
97+
* routine can be called from utils.spectrogram.
9898
*/
99-
mp_obj_t fft_fft_ifft_spectrogram(mp_obj_t data_in, uint8_t type) {
99+
mp_obj_t fft_fft_ifft(mp_obj_t data_in, uint8_t type) {
100100
if(!mp_obj_is_type(data_in, &ulab_ndarray_type)) {
101101
mp_raise_NotImplementedError(MP_ERROR_TEXT("FFT is defined for ndarrays only"));
102102
}
@@ -134,20 +134,10 @@ mp_obj_t fft_fft_ifft_spectrogram(mp_obj_t data_in, uint8_t type) {
134134
}
135135
data -= 2 * len;
136136

137-
if((type == FFT_FFT) || (type == FFT_SPECTROGRAM)) {
138-
fft_kernel_complex(data, len, 1);
139-
if(type == FFT_SPECTROGRAM) {
140-
ndarray_obj_t *spectrum = ndarray_new_linear_array(len, NDARRAY_FLOAT);
141-
mp_float_t *sarray = (mp_float_t *)spectrum->array;
142-
for(size_t i = 0; i < len; i++) {
143-
*sarray++ = MICROPY_FLOAT_C_FUN(sqrt)(data[0] * data[0] + data[1] * data[1]);
144-
data += 2;
145-
}
146-
m_del(mp_float_t, data, 2 * len);
147-
return MP_OBJ_FROM_PTR(spectrum);
148-
}
137+
if(type == FFT_FFT) {
138+
fft_kernel(data, len, 1);
149139
} else { // inverse transform
150-
fft_kernel_complex(data, len, -1);
140+
fft_kernel(data, len, -1);
151141
// TODO: numpy accepts the norm keyword argument
152142
for(size_t i = 0; i < 2 * len; i++) {
153143
*data++ /= len;
@@ -202,7 +192,7 @@ void fft_kernel(mp_float_t *real, mp_float_t *imag, size_t n, int isign) {
202192
}
203193
}
204194

205-
mp_obj_t fft_fft_ifft_spectrogram(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_im, uint8_t type) {
195+
mp_obj_t fft_fft_ifft(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_im, uint8_t type) {
206196
if(!mp_obj_is_type(arg_re, &ulab_ndarray_type)) {
207197
mp_raise_NotImplementedError(MP_ERROR_TEXT("FFT is defined for ndarrays only"));
208198
}
@@ -258,15 +248,8 @@ mp_obj_t fft_fft_ifft_spectrogram(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_i
258248
data_im -= len;
259249
}
260250

261-
if((type == FFT_FFT) || (type == FFT_SPECTROGRAM)) {
251+
if(type == FFT_FFT) {
262252
fft_kernel(data_re, data_im, len, 1);
263-
if(type == FFT_SPECTROGRAM) {
264-
for(size_t i=0; i < len; i++) {
265-
*data_re = MICROPY_FLOAT_C_FUN(sqrt)(*data_re * *data_re + *data_im * *data_im);
266-
data_re++;
267-
data_im++;
268-
}
269-
}
270253
} else { // inverse transform
271254
fft_kernel(data_re, data_im, len, -1);
272255
// TODO: numpy accepts the norm keyword argument
@@ -275,13 +258,9 @@ mp_obj_t fft_fft_ifft_spectrogram(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_i
275258
*data_im++ /= len;
276259
}
277260
}
278-
if(type == FFT_SPECTROGRAM) {
279-
return MP_OBJ_FROM_PTR(out_re);
280-
} else {
281-
mp_obj_t tuple[2];
282-
tuple[0] = MP_OBJ_FROM_PTR(out_re);
283-
tuple[1] = MP_OBJ_FROM_PTR(out_im);
284-
return mp_obj_new_tuple(2, tuple);
285-
}
261+
mp_obj_t tuple[2];
262+
tuple[0] = MP_OBJ_FROM_PTR(out_re);
263+
tuple[1] = MP_OBJ_FROM_PTR(out_im);
264+
return mp_obj_new_tuple(2, tuple);
286265
}
287266
#endif /* ULAB_SUPPORTS_COMPLEX & ULAB_FFT_IS_NUMPY_COMPATIBLE */

code/numpy/fft/fft_tools.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@
1414
enum FFT_TYPE {
1515
FFT_FFT,
1616
FFT_IFFT,
17-
FFT_SPECTROGRAM,
1817
};
1918

2019
#if ULAB_SUPPORTS_COMPLEX & ULAB_FFT_IS_NUMPY_COMPATIBLE
2120
void fft_kernel(mp_float_t *, size_t , int );
22-
mp_obj_t fft_fft_ifft_spectrogram(mp_obj_t , uint8_t );
21+
mp_obj_t fft_fft_ifft(mp_obj_t , uint8_t );
2322
#else
2423
void fft_kernel(mp_float_t *, mp_float_t *, size_t , int );
25-
mp_obj_t fft_fft_ifft_spectrogram(size_t , mp_obj_t , mp_obj_t , uint8_t );
24+
mp_obj_t fft_fft_ifft(size_t , mp_obj_t , mp_obj_t , uint8_t );
2625
#endif /* ULAB_SUPPORTS_COMPLEX & ULAB_FFT_IS_NUMPY_COMPATIBLE */
2726

2827
#endif /* _FFT_TOOLS_ */

code/numpy/poly.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) {
121121
ndarray_obj_t *beta = ndarray_new_linear_array(deg+1, NDARRAY_FLOAT);
122122
mp_float_t *betav = (mp_float_t *)beta->array;
123123
// x[0..(deg+1)] contains now the product X^T * y; we can get rid of y
124-
m_del(float, y, leny);
124+
m_del(mp_float_t, y, leny);
125125

126126
// now, we calculate beta, i.e., we apply prod = (X^T * X)^(-1) on x = X^T * y; x is a column vector now
127127
for(uint8_t i=0; i < deg+1; i++) {

code/ulab.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "user/user.h"
3434
#include "utils/utils.h"
3535

36-
#define ULAB_VERSION 6.5.4
36+
#define ULAB_VERSION 6.5.5
3737
#define xstr(s) str(s)
3838
#define str(s) #s
3939

code/ulab.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@
440440
// Note that in this case, the input also must be numpythonic,
441441
// i.e., the real an imaginary parts cannot be passed as two arguments
442442
#ifndef ULAB_FFT_IS_NUMPY_COMPATIBLE
443-
#define ULAB_FFT_IS_NUMPY_COMPATIBLE (0)
443+
#define ULAB_FFT_IS_NUMPY_COMPATIBLE (1)
444444
#endif
445445

446446
#ifndef ULAB_FFT_HAS_FFT

0 commit comments

Comments
 (0)