marlin r1339 - trunk/marlin



Author: iain
Date: Sat Nov  8 00:35:25 2008
New Revision: 1339
URL: http://svn.gnome.org/viewvc/marlin?rev=1339&view=rev

Log:
Squashed commit of the following:

commit fc0f016ffe54437d0a7ba4bf02ad903ccf189765
Author: iain <iain gnome org>
Date:   Sat Nov 8 00:32:08 2008 +0000

    Make recording worky

commit e35b55363463c94cb0c2ffe0a2b126e6ecab29e4
Author: iain <iain gnome org>
Date:   Wed Nov 5 00:58:39 2008 +0000

    Add sample ratio handling to jack record


Modified:
   trunk/marlin/marlin-jack-play.c
   trunk/marlin/marlin-jack-record.c

Modified: trunk/marlin/marlin-jack-play.c
==============================================================================
--- trunk/marlin/marlin-jack-play.c	(original)
+++ trunk/marlin/marlin-jack-play.c	Sat Nov  8 00:35:25 2008
@@ -266,8 +266,7 @@
 		g_object_unref (priv->sample);
 	}
 
-	priv->sample = sample;
-	g_object_ref (priv->sample);
+	priv->sample = g_object_ref (sample);
 	g_object_get (G_OBJECT (priv->sample),
 		      "channels", &priv->channels,
 		      "sample_rate", &priv->sample_rate,

Modified: trunk/marlin/marlin-jack-record.c
==============================================================================
--- trunk/marlin/marlin-jack-record.c	(original)
+++ trunk/marlin/marlin-jack-record.c	Sat Nov  8 00:35:25 2008
@@ -53,7 +53,7 @@
 	MARLIN_JACK_RECORD_MODE_RECORDING
 } MarlinJackRecordMode;
 
-#define DEFAULT_RB_SIZE 65536
+#define DEFAULT_RB_SIZE 262144
 static const size_t frame_size = sizeof (jack_default_audio_sample_t);
 
 struct _port_data {
@@ -62,12 +62,11 @@
 	MarlinChannel *channel; /* The channel associated with the port */
 	MarlinBlock *block_list, *bl_end;
 
-	float *data;
-	guint frames_in_data;
-
 	jack_port_t *record; /* The record port */
 
 	jack_ringbuffer_t *rb;
+	float *rb_buffer, *tmp_buffer, *data;
+	guint frames_in_data;
 
 	SRC_STATE *state;
 
@@ -86,7 +85,7 @@
 
 	guint channels;
 
-	guint rate, jrate;
+	guint sample_rate, jack_rate;
 	double src_ratio;
 
 	struct _port_data **port_data;
@@ -96,6 +95,8 @@
 
 G_DEFINE_TYPE (MarlinJackRecord, marlin_jack_record, MARLIN_JACK_TYPE);
 
+static long process_more_frames (gpointer userdata, float **data);
+
 static void
 free_ports (MarlinJackRecord *jack)
 {
@@ -111,7 +112,13 @@
 			jack_ringbuffer_free (pd->rb);
 		}
 
+		g_free (pd->rb_buffer);
+		g_free (pd->tmp_buffer);
 		g_free (pd->data);
+
+		if (pd->state) {
+			src_delete (pd->state);
+		}
 		g_free (pd);
 	}
 
@@ -140,7 +147,6 @@
 						 JackPortIsInput, 0);
 		g_free (name);
 
-		pd->data = g_new0 (float, MARLIN_BLOCK_SIZE);
 		priv->port_data[i] = pd;
 	}
 }
@@ -171,7 +177,7 @@
 	}
 
 	if (priv->sample) {
-		g_signal_handler_disconnect (priv->sample, 
+		g_signal_handler_disconnect (priv->sample,
 					     priv->sample_notify_id);
 		priv->sample_notify_id = 0;
 		g_object_unref (priv->sample);
@@ -181,20 +187,37 @@
 	((GObjectClass *) marlin_jack_record_parent_class)->dispose (object);
 }
 
+static double
+calculate_rate_ratio (guint src_rate,
+		      guint dest_rate)
+{
+	double ratio;
+
+	if (src_rate == 0) {
+		return 1.0;
+	}
+
+	ratio = (1.0 * dest_rate) / src_rate;
+	if (src_is_valid_ratio (ratio) == FALSE) {
+		ratio = 1.0;
+	}
+
+	return ratio;
+}
+
 static void
 sample_changed (GObject          *object,
 		GParamSpec       *pspec,
 		MarlinJackRecord *jack)
 {
-#if 0
 	MarlinJackRecordPrivate *priv = jack->priv;
 
 	if (strcmp (pspec->name, "sample_rate") == 0) {
 		g_object_get (object,
-			      "sample_rate", &priv->rate,
+			      "sample_rate", &priv->sample_rate,
 			      NULL);
-		priv->src_ratio = calculate_rate_ratio (priv->rate,
-							priv->jrate);
+		priv->src_ratio = calculate_rate_ratio (priv->sample_rate,
+							priv->jack_rate);
 		return;
 	}
 
@@ -206,7 +229,6 @@
 		setup_ports (jack);
 		return;
 	}
-#endif
 }
 
 static void
@@ -224,13 +246,19 @@
 		g_object_unref (priv->sample);
 	}
 
-	priv->sample = sample;
-	g_object_ref (priv->sample);
+	priv->sample = g_object_ref (sample);
+	g_object_get (G_OBJECT (priv->sample),
+		      "channels", &priv->channels,
+		      "sample_rate", &priv->sample_rate,
+		      NULL);
 
 	priv->sample_notify_id = g_signal_connect (priv->sample, "notify",
 						   G_CALLBACK (sample_changed),
 						   jack);
 
+	priv->src_ratio = calculate_rate_ratio (priv->sample_rate,
+						priv->jack_rate);
+
 	setup_ports ((MarlinJackRecord *) jack);
 }
 
@@ -257,6 +285,7 @@
 		if (jack_ringbuffer_write (pd->rb, (void *) i_buf,
 					   bytes_avail) < bytes_avail) {
 			/* Not sure what to do with this... signal? */
+			g_print ("xrun...\n");
 			overruns++;
 		}
 	}
@@ -271,6 +300,7 @@
 
 	switch (priv->mode) {
 	case MARLIN_JACK_RECORD_MODE_RECORDING:
+	case MARLIN_JACK_RECORD_MODE_PREROLLING:
 		process_recording (jack, nframes);
 		break;
 
@@ -312,6 +342,28 @@
 	}
 }
 
+static long
+process_more_frames (gpointer userdata,
+		     float  **data)
+{
+	struct _port_data *pd = userdata;
+	MarlinJackRecord *jack = pd->jack;
+	size_t bytes_avail;
+
+	/* We want to put as much into the SRC as possible */
+	bytes_avail = jack_ringbuffer_read_space (pd->rb);
+	if (bytes_avail == 0) {
+		return 0;
+	}
+
+	jack_ringbuffer_read (pd->rb, (char *) pd->tmp_buffer, bytes_avail);
+
+	fprintf (stderr, "Got more frames: %d [%p]\n", bytes_avail / sizeof (float), pd);
+
+	*data = pd->tmp_buffer;
+	return bytes_avail / sizeof (float);
+}
+
 /* Reader function: Reads data from the ringbuffer and puts it in the sample */
 static gboolean
 process_reader (gpointer data)
@@ -327,46 +379,65 @@
 
 	for (i = 0; i < 2; i++) {
 		struct _port_data *pd = priv->port_data[i];
-		size_t bytes_avail;
 		guint frames;
+		long frames_needed;
+		size_t bytes_avail;
 
 		bytes_avail = jack_ringbuffer_read_space (pd->rb);
-		frames = bytes_avail / frame_size;
+		/* Roll until we've got half the ringbuffer filled */
+		if (bytes_avail < DEFAULT_RB_SIZE / 2) {
+			g_print ("Got %d bytes, rolling\n", bytes_avail);
+			return TRUE;
+		}
 
+		g_print ("Starting: %p\n", pd);
+		frames_needed = MIN (MARLIN_BLOCK_SIZE - pd->frames_in_data,
+				     (bytes_avail / sizeof (float)) / 8);
+		g_print ("Frames needed [%p] - %d (%d, %d)\n", pd, frames_needed, MARLIN_BLOCK_SIZE - pd->frames_in_data, (bytes_avail / sizeof (float)) / 8);
+
+		if (frames_needed == 0) {
+			continue;
+		}
+
+		frames = src_callback_read (pd->state, priv->src_ratio,
+					    frames_needed, pd->rb_buffer);
+		g_print ("Got %d frames\n", frames);
 		if (frames == 0) {
 			continue;
 		}
 
+		fprintf (stderr, "Bing got %d frames\n", frames);
 		/* The amount of frames available will be fill a block */
-		if (pd->frames_in_data + frames > MARLIN_BLOCK_SIZE) {
+		if (pd->frames_in_data + frames >= MARLIN_BLOCK_SIZE) {
 			guint32 needed, remain;
 			float *fd;
 
 			needed = MARLIN_BLOCK_SIZE - pd->frames_in_data;
 			remain = frames - needed;
 
+			fprintf (stderr, "Needed: %d - remains: %d\n", needed, remain);
 			/* Read from the ringbuffer into the next free space
 			   in the frame buffer */
 			fd = pd->data + pd->frames_in_data;
-			jack_ringbuffer_read (pd->rb, (char *) fd,
-					      needed * sizeof (float));
+			memcpy (fd, pd->rb_buffer, needed * sizeof (float));
 
 			/* Now we have a whole block, we can store it */
-			store_block (jack, pd, pd->data, MARLIN_BLOCK_SIZE);
+			store_block (jack, pd, pd->data,
+				     MARLIN_BLOCK_SIZE);
 
 			memset (pd->data, 0,
 				MARLIN_BLOCK_SIZE * sizeof (float));
 
 			if (remain > 0) {
-				jack_ringbuffer_read (pd->rb, (char *) pd->data,
-						      remain * sizeof (float));
+				memcpy (pd->data, pd->rb_buffer + needed,
+					remain * sizeof (float));
 			}
 			pd->frames_in_data = remain;
 		} else {
 			float *fd;
 
 			fd = pd->data + pd->frames_in_data;
-			jack_ringbuffer_read (pd->rb, (char *) fd, bytes_avail);
+			memcpy (fd, pd->rb_buffer, frames * sizeof (float));
 			pd->frames_in_data += frames;
 		}
 	}
@@ -383,7 +454,9 @@
 	MarlinJackRecord *jack = data;
 	MarlinJackRecordPrivate *priv = jack->priv;
 
-	priv->jrate = nframes;
+	priv->jack_rate = nframes;
+	priv->src_ratio = calculate_rate_ratio (priv->sample_rate,
+						priv->jack_rate);
 
 	return 0;
 }
@@ -440,6 +513,7 @@
 
 	for (i = 0; i < 2; i++) {
 		struct _port_data *pd = priv->port_data[i];
+		int err;
 
 		if (ports[i] == NULL) {
 			return FALSE;
@@ -457,17 +531,28 @@
 			return FALSE;
 		}
 
-		pd->rb = jack_ringbuffer_create (frame_size * DEFAULT_RB_SIZE);
 		pd->channel = marlin_sample_get_channel (priv->sample, i);
+		pd->rb = jack_ringbuffer_create (frame_size * DEFAULT_RB_SIZE);
+
+		pd->rb_buffer = g_new (float, DEFAULT_RB_SIZE);
+		pd->tmp_buffer = g_new (float, DEFAULT_RB_SIZE);
+		pd->data = g_new (float, MARLIN_BLOCK_SIZE);
+
+		pd->state = src_callback_new (process_more_frames,
+					      SRC_SINC_BEST_QUALITY,
+					      1, &err, pd);
 	}
 
 	free (ports);
 
-	priv->mode = MARLIN_JACK_RECORD_MODE_RECORDING;
+	priv->mode = MARLIN_JACK_RECORD_MODE_PREROLLING;
 
-	/* Start an idle function to read from the ringbuffer and write data
-	   to a sample */
-	priv->reader_id = g_idle_add (process_reader, jack);
+	/* Start an timeout to read from the ringbuffer and write data
+	   to a sample, don't really care about how fast this happens
+	   the important thing is not to starve the writer process:
+	   really the balance is between this timeout and the size of the
+	   ringbuffer */
+	priv->reader_id = g_timeout_add (250, process_reader, jack);
 
 	return TRUE;
 }
@@ -601,7 +686,7 @@
 	priv->jack_buf = g_new0 (jack_default_audio_sample_t, priv->bufsize * 16);
 
 	jack_set_sample_rate_callback (priv->client, srate_changed, jack);
-	priv->jrate = jack_get_sample_rate (priv->client);
+	priv->jack_rate = jack_get_sample_rate (priv->client);
 
 	return jack;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]