[asterisk-commits] russell: branch russell/jack r93153 - /team/russell/jack/apps/app_jack.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sat Dec 15 13:08:19 CST 2007
Author: russell
Date: Sat Dec 15 13:08:17 2007
New Revision: 93153
URL: http://svn.digium.com/view/asterisk?view=rev&rev=93153
Log:
Check in progress on implementation of queue_voice_frame(). This function takes
a frame from a channel, resamples the audio if necessary, and writes the result
into a lock-free ringbuffer for the jack process callback to consume later.
Modified:
team/russell/jack/apps/app_jack.c
Modified: team/russell/jack/apps/app_jack.c
URL: http://svn.digium.com/view/asterisk/team/russell/jack/apps/app_jack.c?view=diff&rev=93153&r1=93152&r2=93153
==============================================================================
--- team/russell/jack/apps/app_jack.c (original)
+++ team/russell/jack/apps/app_jack.c Sat Dec 15 13:08:17 2007
@@ -48,6 +48,8 @@
#include "asterisk/lock.h"
#include "libresample.h"
+
+#define RESAMPLE_QUALITY 0
static char *jack_app = "Jack";
static char *jack_synopsis =
@@ -62,6 +64,8 @@
jack_port_t *output_port;
jack_ringbuffer_t *rb;
struct ast_smoother *smoother;
+ void *resampler;
+ double resample_factor;
unsigned int stop:1;
};
@@ -161,6 +165,11 @@
ast_smoother_free(jack_data->smoother);
jack_data->smoother = NULL;
}
+
+ if (jack_data->resampler) {
+ resample_close(jack_data->resampler);
+ jack_data->resampler = NULL;
+ }
}
static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
@@ -181,7 +190,7 @@
destroy_jack_data(jack_data);
return -1;
}
-
+
jack_data->client = jack_client_open(chan_name, 0, &status);
log_jack_status("Client Open Status", status);
@@ -223,11 +232,88 @@
return 0;
}
-static void queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
-{
- /* XXX Here we need to resample the frame from the asterisk channel into the
- * current sample rate for Jack. Then, it should be written to the ring buffer
- * to be read in the jack process callback. */
+static int queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
+{
+ float f_buf[f->samples * 8];
+ size_t f_buf_used = 0;
+ int i;
+ uint16_t *s_buf = f->data;
+ jack_ringbuffer_data_t write_vector[2];
+
+ do {
+ double from_srate, to_srate;
+
+ if (jack_data->resampler)
+ break;
+
+ from_srate = 8000.0; /* XXX Hard coded 8 kHz */
+ to_srate = jack_get_sample_rate(jack_data->client);
+
+ if (from_srate == to_srate) {
+ /* Awesome! The jack sample rate is the same as ours.
+ * Resampling isn't needed. */
+ break;
+ }
+
+ jack_data->resample_factor = to_srate / from_srate;
+
+ if (!(jack_data->resampler = resample_open(RESAMPLE_QUALITY,
+ jack_data->resample_factor, jack_data->resample_factor))) {
+ ast_log(LOG_ERROR, "Failed to open resampler\n");
+ return -1;
+ }
+ } while (0);
+
+ if (jack_data->resampler) {
+ float in_buf[f->samples];
+ int in_buf_used;
+
+ /* XXX Does this need to be normalized? */
+ for (i = 0; i < f->samples; i++)
+ in_buf[i] = s_buf[i];
+
+ /* XXX Need to run this in a loop to ensure all samples get processed */
+ resample_process(jack_data->resampler, jack_data->resample_factor,
+ in_buf, sizeof(in_buf), 0 /* XXX Should this ever get set? */, &in_buf_used,
+ f_buf, sizeof(f_buf));
+
+ f_buf_used = sizeof(f_buf[0]) * jack_data->resample_factor;
+ } else {
+ /* No resampling needed */
+
+ /* XXX Does this need to be normalized? */
+ for (i = 0; i < f->samples; i++)
+ f_buf[i] = s_buf[i];
+
+ f_buf_used = sizeof(f_buf[0]) * f->samples;
+ }
+
+ jack_ringbuffer_get_write_vector(jack_data->rb, write_vector);
+
+ if (!write_vector[1].len) {
+ ast_log(LOG_WARNING, "Not enough room in ringbuffer to write frame data\n");
+ return 0;
+ }
+
+ if (write_vector[1].len >= f_buf_used) {
+ memcpy(write_vector[1].buf, f_buf, f_buf_used);
+ } else {
+ char *out_buf = (char *) f_buf;
+ size_t len_left;
+
+ memcpy(write_vector[1].buf, f_buf, write_vector[1].len);
+
+ len_left = f_buf_used - write_vector[1].len;
+
+ if (write_vector[2].len < len_left) {
+ ast_log(LOG_WARNING, "Not enough room in ringbuffer to write frame data\n");
+ return 0;
+ }
+
+ memcpy(write_vector[2].buf, out_buf + write_vector[1].len, len_left);
+ }
+
+ return 0;
}
static int jack_exec(struct ast_channel *chan, void *data)
More information about the asterisk-commits
mailing list