summaryrefslogtreecommitdiffstats
path: root/spa/plugins/audioconvert/resample-peaks.c
diff options
context:
space:
mode:
Diffstat (limited to 'spa/plugins/audioconvert/resample-peaks.c')
-rw-r--r--spa/plugins/audioconvert/resample-peaks.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/spa/plugins/audioconvert/resample-peaks.c b/spa/plugins/audioconvert/resample-peaks.c
new file mode 100644
index 0000000..c151d60
--- /dev/null
+++ b/spa/plugins/audioconvert/resample-peaks.c
@@ -0,0 +1,148 @@
+/* Spa
+ *
+ * Copyright © 2018 Wim Taymans
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <math.h>
+#include <errno.h>
+
+#include <spa/param/audio/format.h>
+
+#include "peaks-ops.h"
+#include "resample.h"
+
+struct peaks_data {
+ uint32_t o_count;
+ uint32_t i_count;
+ struct peaks peaks;
+ float max_f[];
+};
+
+static void resample_peaks_process(struct resample *r,
+ const void * SPA_RESTRICT src[], uint32_t *in_len,
+ void * SPA_RESTRICT dst[], uint32_t *out_len)
+{
+ struct peaks_data *pd = r->data;
+ uint32_t c, i, o, end, chunk, i_count, o_count;
+
+ if (SPA_UNLIKELY(r->channels == 0))
+ return;
+
+ for (c = 0; c < r->channels; c++) {
+ const float *s = src[c];
+ float *d = dst[c], m = pd->max_f[c];
+
+ o_count = pd->o_count;
+ i_count = pd->i_count;
+ o = i = 0;
+
+ while (i < *in_len && o < *out_len) {
+ end = ((uint64_t) (o_count + 1)
+ * r->i_rate) / r->o_rate;
+ end = end > i_count ? end - i_count : 0;
+ chunk = SPA_MIN(end, *in_len);
+
+ m = peaks_abs_max(&pd->peaks, &s[i], chunk - i, m);
+
+ i += chunk;
+
+ if (i == end) {
+ d[o++] = m;
+ m = 0.0f;
+ o_count++;
+ }
+ }
+ pd->max_f[c] = m;
+ }
+ *out_len = o;
+ *in_len = i;
+ pd->o_count = o_count;
+ pd->i_count = i_count + i;
+
+ while (pd->i_count >= r->i_rate) {
+ pd->i_count -= r->i_rate;
+ pd->o_count -= r->o_rate;
+ }
+}
+
+static void impl_peaks_free(struct resample *r)
+{
+ struct peaks_data *d = r->data;
+ if (d != NULL) {
+ peaks_free(&d->peaks);
+ free(d);
+ }
+ r->data = NULL;
+}
+
+static void impl_peaks_update_rate(struct resample *r, double rate)
+{
+}
+
+static uint32_t impl_peaks_delay (struct resample *r)
+{
+ return 0;
+}
+
+static uint32_t impl_peaks_in_len(struct resample *r, uint32_t out_len)
+{
+ return out_len;
+}
+
+static void impl_peaks_reset (struct resample *r)
+{
+ struct peaks_data *d = r->data;
+ d->i_count = d->o_count = 0;
+}
+
+int resample_peaks_init(struct resample *r)
+{
+ struct peaks_data *d;
+ int res;
+
+ r->free = impl_peaks_free;
+ r->update_rate = impl_peaks_update_rate;
+
+ d = calloc(1, sizeof(struct peaks_data) + sizeof(float) * r->channels);
+ if (d == NULL)
+ return -errno;
+
+ d->peaks.log = r->log;
+ d->peaks.cpu_flags = r->cpu_flags;
+ if ((res = peaks_init(&d->peaks)) < 0) {
+ free(d);
+ return res;
+ }
+
+ r->data = d;
+ r->process = resample_peaks_process;
+ r->reset = impl_peaks_reset;
+ r->delay = impl_peaks_delay;
+ r->in_len = impl_peaks_in_len;
+
+ spa_log_debug(r->log, "peaks %p: in:%d out:%d features:%08x:%08x", r,
+ r->i_rate, r->o_rate, r->cpu_flags, d->peaks.cpu_flags);
+
+ r->cpu_flags = d->peaks.cpu_flags;
+ d->i_count = d->o_count = 0;
+ return 0;
+}