aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2013-03-08 17:11:01 +0100
committerSylvain Munaut <tnt@246tNt.com>2013-03-08 17:11:01 +0100
commitc0fd99fcd28e3b10a4180fb6afce682821869574 (patch)
tree4c61ea8f10bed3ab35fdef7ae57594ede59faff6
parente97293f89b4b02e6e857fbd6fb9ac60cbbd0595d (diff)
iqbal: Allow caching of fft buffer and plan during the optimize call
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r--src/iqbal.c70
1 files changed, 62 insertions, 8 deletions
diff --git a/src/iqbal.c b/src/iqbal.c
index 2d848f4..ddbd4a7 100644
--- a/src/iqbal.c
+++ b/src/iqbal.c
@@ -98,22 +98,54 @@ osmo_iqbal_cxvec_fix(const struct osmo_cxvec *in, float mag, float phase,
return out;
}
+
+/*! \brief Cache for \ref _osmo_iqbal_estimate when doing lots of calls */
+struct _iqbal_estimate_state {
+ float complex *fft; /*!< \brief Temporary memory for FFT */
+ fftwf_plan fft_plan; /*!< \brief FFTW plan */
+};
+
+/*! \brief Release a cache object created by \ref _osmo_iqbal_estimate */
+static void
+_osmo_iqbal_estimate_release(struct _iqbal_estimate_state *state)
+{
+ if (!state)
+ return;
+
+ fftwf_destroy_plan(state->fft_plan);
+ free(state->fft);
+
+ free(state);
+}
+
/*! \brief Objectively estimate IQ balance in a given complex buffer
* \param[in] data Input complex buffer (at least fft_size * fft_count samples)
* \param[in] fft_size Size of the FFT to use internally
* \param[in] fft_count The number of consecutive FFT to use internally
+ * \param[out] state_p Cache object for multiple calls (can be NULL)
* \returns A number >= 0.0f estimating the IQ balance (the lower, the better)
+ *
+ * The Cache object should only be used for multiple calls with the same parameters
+ * and the same size of input vector. Once you don't plan on using it anymore,
+ * you should call \ref _osmo_iqbal_estimate_release . The initial pointer value
+ * should also be initialized to NULL.
*/
-float
-osmo_iqbal_estimate(const float complex *data, int fft_size, int fft_count)
+static float
+_osmo_iqbal_estimate(const float complex *data, int fft_size, int fft_count,
+ struct _iqbal_estimate_state **state_p)
{
float complex *fft;
float est = 0.0f;
fftwf_plan fft_plan;
int i, j;
- fft = malloc(sizeof(float complex) * fft_size);
- fft_plan = fftwf_plan_dft_1d(fft_size, fft, fft, FFTW_FORWARD, FFTW_ESTIMATE);
+ if (state_p && *state_p) {
+ fft = (*state_p)->fft;
+ fft_plan = (*state_p)->fft_plan;
+ } else {
+ fft = malloc(sizeof(float complex) * fft_size);
+ fft_plan = fftwf_plan_dft_1d(fft_size, fft, fft, FFTW_FORWARD, FFTW_ESTIMATE);
+ }
for (i=0; i<fft_count; i++)
{
@@ -130,12 +162,30 @@ osmo_iqbal_estimate(const float complex *data, int fft_size, int fft_count)
/* est /= fft_count; */
- fftwf_destroy_plan(fft_plan);
- free(fft);
+ if (state_p && !*state_p) {
+ *state_p = malloc(sizeof(struct _iqbal_estimate_state));
+ (*state_p)->fft = fft;
+ (*state_p)->fft_plan = fft_plan;
+ } else if (!state_p) {
+ fftwf_destroy_plan(fft_plan);
+ free(fft);
+ }
return est;
}
+/*! \brief Objectively estimate IQ balance in a given complex buffer
+ * \param[in] data Input complex buffer (at least fft_size * fft_count samples)
+ * \param[in] fft_size Size of the FFT to use internally
+ * \param[in] fft_count The number of consecutive FFT to use internally
+ * \returns A number >= 0.0f estimating the IQ balance (the lower, the better)
+ */
+float
+osmo_iqbal_estimate(const float complex *data, int fft_size, int fft_count)
+{
+ return _osmo_iqbal_estimate(data, fft_size, fft_count, NULL);
+}
+
/*! \brief Objectively estimate IQ balance in a given complex vector
* \param[in] sig Input complex vector (at least fft_size * fft_count samples)
* \param[in] fft_size Size of the FFT to use internally
@@ -172,6 +222,7 @@ struct _iqbal_state
const struct osmo_cxvec *org; /*!< \brief Original vector */
struct osmo_cxvec *tmp; /*!< \brief Temporary vector */
int feval; /*!< \brief # of function evaluation */
+ struct _iqbal_estimate_state *cache; /*!< \brief Cache for estimate func */
};
/*! \brief Optimization objective function - Value
@@ -184,8 +235,9 @@ _iqbal_objfn_value(struct _iqbal_state *state, float x[2])
{
state->feval++;
osmo_iqbal_cxvec_fix(state->org, x[0], x[1], state->tmp);
- return osmo_iqbal_cxvec_estimate(state->tmp,
- state->opts->fft_size, state->opts->fft_count);
+ return _osmo_iqbal_estimate(state->tmp->data,
+ state->opts->fft_size, state->opts->fft_count,
+ &state->cache);
}
/*! \brief Optimization objective function - Gradient estimation
@@ -256,6 +308,7 @@ osmo_iqbal_cxvec_optimize(const struct osmo_cxvec *sig, float *mag, float *phase
state->tmp = osmo_cxvec_alloc(sig->len);
state->opts = opts;
state->feval = 0;
+ state->cache = NULL;
if (opts->start_at_prev) {
cx[0] = *mag;
@@ -290,6 +343,7 @@ osmo_iqbal_cxvec_optimize(const struct osmo_cxvec *sig, float *mag, float *phase
}
osmo_cxvec_free(state->tmp);
+ _osmo_iqbal_estimate_release(state->cache);
*mag = cx[0];
*phase = cx[1];