[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