summaryrefslogtreecommitdiff
path: root/resample.c
diff options
context:
space:
mode:
Diffstat (limited to 'resample.c')
-rw-r--r--resample.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/resample.c b/resample.c
new file mode 100644
index 0000000..c77367e
--- /dev/null
+++ b/resample.c
@@ -0,0 +1,54 @@
+#include "resample.h"
+
+#include <stdint.h>
+
+static GQuark resample_quark() {
+ return g_quark_from_string("resample");
+}
+
+SRC_STATE *resample_init(int channels, GError **error) {
+ int err;
+ SRC_STATE *state = src_new(SRC_LINEAR, channels, &err);
+ if(!state) {
+ *error = g_error_new(resample_quark(), 0, g_strdup(src_strerror(err)));
+ }
+
+ return state;
+}
+
+void resample(SRC_STATE *state, unsigned int from_rate, unsigned int to_rate, int channels,
+ gpointer in_data, gsize in_size, gpointer *out_data, gsize *out_size, gboolean done, GError **error) {
+ int len = in_size / 2;
+ int frames = in_size / 2 / channels;
+ float *temp_in = g_new(float, len);
+ float *temp_out = g_new(float, len);
+
+ src_short_to_float_array(in_data, temp_in, len);
+
+ SRC_DATA data = {
+ .data_in = temp_in,
+ .data_out = temp_out,
+ .input_frames = frames,
+ .output_frames = frames,
+ .src_ratio = (double)to_rate / (double)from_rate,
+ .end_of_input = done ? 1 : 0
+ };
+
+ int err = src_process(state, &data);
+ if(err) {
+ *error = g_error_new(resample_quark(), 0, g_strdup(src_strerror(err)));
+ goto resample_free;
+ }
+
+ *out_data = g_new(int16_t, data.output_frames_gen * channels);
+ src_float_to_short_array(temp_out, *out_data, data.output_frames_gen * channels);
+ *out_size = sizeof(int16_t) * data.output_frames_gen * channels;
+
+resample_free:
+ g_free(temp_in);
+ g_free(temp_out);
+}
+
+void resample_free(SRC_STATE *state) {
+ src_delete(state);
+}