[alsa-devel] snd_dummy on Centos - Redhat

Takashi Iwai tiwai at suse.de
Thu Sep 3 23:37:31 CEST 2009


[Forgot to add Cc to ML, added back now]

At Thu, 3 Sep 2009 21:52:54 +0200,
Giovanni Maruzzelli wrote:
> 
> I had to modify a little the patch, so maybe I ruined it. My mods are
> marked with "giovanni".

Ah sorry, the patch was broken.  I should have compile-tested.
The below is a revised one.

BTW, looking through your numbers:

> Sep  3 21:35:48 localhost kernel: giovanni line: 296,
> dpcm->frac_buf_pos / HZ=0, jiffies=107166054, buffer_size=4096,
> period_size=2048, rate=16000
> Sep  3 21:35:48 localhost kernel: giovanni line: 296,
> dpcm->frac_buf_pos / HZ=48, jiffies=107166057, buffer_size=4096,
> period_size=2048, rate=16000
> Sep  3 21:35:48 localhost kernel: giovanni line: 296,
> dpcm->frac_buf_pos / HZ=48, jiffies=107166057, buffer_size=4096,
> period_size=2048, rate=16000
> Sep  3 21:35:48 localhost kernel: giovanni line: 296,
> dpcm->frac_buf_pos / HZ=80, jiffies=107166059, buffer_size=4096,
> period_size=2048, rate=16000
> Sep  3 21:35:48 localhost kernel: giovanni line: 296,
> dpcm->frac_buf_pos / HZ=80, jiffies=107166059, buffer_size=4096,
> period_size=2048, rate=16000
> Sep  3 21:35:48 localhost kernel: giovanni line: 296,
> dpcm->frac_buf_pos / HZ=0, jiffies=107166133, buffer_size=4096,
> period_size=2048, rate=16000

Here, suddenly you get position 0.  Then...

> Sep  3 21:35:48 localhost kernel: giovanni line: 296,
> dpcm->frac_buf_pos / HZ=2048, jiffies=107166182, buffer_size=4096,
> period_size=2048, rate=16000

Returning to the right position again.  That can be an issue.


Takashi

---
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 0a798bd..f08b9c8 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -207,19 +207,18 @@ struct dummy_systimer_pcm {
 	struct timer_list timer;
 	unsigned long base_time;
 	unsigned int frac_pos;	/* fractional sample position (based HZ) */
+	unsigned int frac_period_rest;
 	unsigned int frac_buffer_size;	/* buffer_size * HZ */
 	unsigned int frac_period_size;	/* period_size * HZ */
 	unsigned int rate;
+	int elapsed;
 	struct snd_pcm_substream *substream;
 };
 
 static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)
 {
-	unsigned long frac;
-
-	frac = dpcm->frac_pos % dpcm->frac_period_size;
 	dpcm->timer.expires = jiffies +
-		(dpcm->frac_period_size + dpcm->rate - 1) / dpcm->rate;
+		(dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate;
 	add_timer(&dpcm->timer);
 }
 
@@ -230,10 +229,16 @@ static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)
 	delta = jiffies - dpcm->base_time;
 	if (!delta)
 		return;
-	dpcm->base_time = jiffies;
-	dpcm->frac_pos += delta * dpcm->rate;
+	dpcm->base_time += delta;
+	delta *= dpcm->rate;
+	dpcm->frac_pos += delta;
 	while (dpcm->frac_pos >= dpcm->frac_buffer_size)
 		dpcm->frac_pos -= dpcm->frac_buffer_size;
+	if (dpcm->frac_period_rest <= delta) {
+		dpcm->elapsed++;
+		dpcm->frac_period_rest += dpcm->frac_period_size;
+	}
+	dpcm->frac_period_rest -= delta;
 }
 
 static int dummy_systimer_start(struct snd_pcm_substream *substream)
@@ -264,6 +269,8 @@ static int dummy_systimer_prepare(struct snd_pcm_substream *substream)
 	dpcm->rate = runtime->rate;
 	dpcm->frac_buffer_size = runtime->buffer_size * HZ;
 	dpcm->frac_period_size = runtime->period_size * HZ;
+	dpcm->frac_period_rest = dpcm->frac_period_size;
+	dpcm->elapsed = 0;
 
 	return 0;
 }
@@ -272,23 +279,29 @@ static void dummy_systimer_callback(unsigned long data)
 {
 	struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data;
 	unsigned long flags;
+	int elapsed = 0;
 	
 	spin_lock_irqsave(&dpcm->lock, flags);
 	dummy_systimer_update(dpcm);
 	dummy_systimer_rearm(dpcm);
+	elapsed = dpcm->elapsed;
+	dpcm->elapsed = 0;
 	spin_unlock_irqrestore(&dpcm->lock, flags);
-	snd_pcm_period_elapsed(dpcm->substream);
+	if (elapsed)
+		snd_pcm_period_elapsed(dpcm->substream);
 }
 
 static snd_pcm_uframes_t
 dummy_systimer_pointer(struct snd_pcm_substream *substream)
 {
 	struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
+	snd_pcm_uframes_t pos;
 
 	spin_lock(&dpcm->lock);
 	dummy_systimer_update(dpcm);
+	pos = dpcm->frac_pos / HZ;
 	spin_unlock(&dpcm->lock);
-	return dpcm->frac_pos / HZ;
+	return pos;
 }
 
 static int dummy_systimer_create(struct snd_pcm_substream *substream)


More information about the Alsa-devel mailing list