From 15c0cee6c809a137e0fc7f1d2b0867cc03473c0c Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Fri, 28 May 2010 11:43:45 -0400 Subject: ALSA: pcm: Define G723 3-bit and 5-bit formats This defines the 24bps and 40bps (8khz sample rate) G.723 codec formats. They are going to be used once I submit the driver for an mpeg4/g723 compression card. I've updated the signed value to -1 as per Takashi's comments since these are non-linear formats. Signed-off-by: Ben Collins Signed-off-by: Takashi Iwai --- sound/core/pcm_misc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'sound/core') diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index ea2bf82c9373..434af3c56d52 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -128,6 +128,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = { .width = 4, .phys = 4, .le = -1, .signd = -1, .silence = {}, }, + [SNDRV_PCM_FORMAT_G723_24] = { + .width = 3, .phys = 3, .le = -1, .signd = -1, + .silence = {}, + }, + [SNDRV_PCM_FORMAT_G723_40] = { + .width = 5, .phys = 5, .le = -1, .signd = -1, + .silence = {}, + }, /* FIXME: the following three formats are not defined properly yet */ [SNDRV_PCM_FORMAT_MPEG] = { .le = -1, .signd = -1, @@ -186,6 +194,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = { .width = 18, .phys = 24, .le = 0, .signd = 0, .silence = { 0x02, 0x00, 0x00 }, }, + [SNDRV_PCM_FORMAT_G723_24_1B] = { + .width = 3, .phys = 8, .le = -1, .signd = -1, + .silence = {}, + }, + [SNDRV_PCM_FORMAT_G723_40_1B] = { + .width = 5, .phys = 8, .le = -1, .signd = -1, + .silence = {}, + }, }; -- cgit v1.2.3 From 5daeba34d2aab669aea07abee13d53cd116578fb Mon Sep 17 00:00:00 2001 From: David Dillow Date: Sun, 27 Jun 2010 00:13:20 +0200 Subject: ALSA: pcm_lib: avoid timing jitter in snd_pcm_read/write() When using poll() to wait for the next period -- or avail_min samples -- one gets a consistent delay for each system call that is usually just a little short of the selected period time. However, When using snd_pcm_read/write(), one gets a jittery delay that alternates between less than a millisecond and approximately two period times. This is caused by snd_pcm_lib_{read,write}1() transferring any available samples to the user's buffer and adjusting the application pointer prior to sleeping to the end of the current period. When the next period interrupt occurs, there is then less than avail_min samples remaining to be transferred in the period, so we end up sleeping until a second period occurs. This is solved by using runtime->twake as the number of samples needed for a wakeup in addition to selecting the proper wait queue to wake in snd_pcm_update_state(). This requires twake to be non-zero when used by snd_pcm_lib_{read,write}1() even if avail_min is zero. Signed-off-by: Dave Dillow Signed-off-by: Jaroslav Kysela --- include/sound/pcm.h | 2 +- sound/core/pcm_lib.c | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'sound/core') diff --git a/include/sound/pcm.h b/include/sound/pcm.h index dd76cdede64d..83c6fa6aac43 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -313,7 +313,7 @@ struct snd_pcm_runtime { struct snd_pcm_mmap_control *control; /* -- locking / scheduling -- */ - unsigned int twake: 1; /* do transfer (!poll) wakeup */ + snd_pcm_uframes_t twake; /* do transfer (!poll) wakeup if non-zero */ wait_queue_head_t sleep; /* poll sleep */ wait_queue_head_t tsleep; /* transfer sleep */ struct fasync_struct *fasync; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index e9d98be190c5..bcf95d3ff5c7 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -287,8 +287,11 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, return -EPIPE; } } - if (avail >= runtime->control->avail_min) - wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep); + if (runtime->twake) { + if (avail >= runtime->twake) + wake_up(&runtime->tsleep); + } else if (avail >= runtime->control->avail_min) + wake_up(&runtime->sleep); return 0; } @@ -1707,7 +1710,7 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed); * The available space is stored on availp. When err = 0 and avail = 0 * on the capture stream, it indicates the stream is in DRAINING state. */ -static int wait_for_avail_min(struct snd_pcm_substream *substream, +static int wait_for_avail(struct snd_pcm_substream *substream, snd_pcm_uframes_t *availp) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -1757,7 +1760,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream, avail = snd_pcm_playback_avail(runtime); else avail = snd_pcm_capture_avail(runtime); - if (avail >= runtime->control->avail_min) + if (avail >= runtime->twake) break; } _endloop: @@ -1820,7 +1823,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, goto _end_unlock; } - runtime->twake = 1; + runtime->twake = runtime->control->avail_min ? : 1; while (size > 0) { snd_pcm_uframes_t frames, appl_ptr, appl_ofs; snd_pcm_uframes_t avail; @@ -1833,7 +1836,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, err = -EAGAIN; goto _end_unlock; } - err = wait_for_avail_min(substream, &avail); + runtime->twake = min_t(snd_pcm_uframes_t, size, + runtime->control->avail_min ? : 1); + err = wait_for_avail(substream, &avail); if (err < 0) goto _end_unlock; } @@ -2042,7 +2047,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, goto _end_unlock; } - runtime->twake = 1; + runtime->twake = runtime->control->avail_min ? : 1; while (size > 0) { snd_pcm_uframes_t frames, appl_ptr, appl_ofs; snd_pcm_uframes_t avail; @@ -2060,7 +2065,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, err = -EAGAIN; goto _end_unlock; } - err = wait_for_avail_min(substream, &avail); + runtime->twake = min_t(snd_pcm_uframes_t, size, + runtime->control->avail_min ? : 1); + err = wait_for_avail(substream, &avail); if (err < 0) goto _end_unlock; if (!avail) -- cgit v1.2.3 From 9e216e8a40428cbf689222148c28d0256fbd0186 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 19 Jul 2010 16:37:39 +0200 Subject: ALSA: pcm core - add a safe check to the silence filling function In situation when appl_ptr is far greater then hw_ptr, the hw_avail value can be greater than buffer_size. Check for this. Signed-off-by: Jaroslav Kysela --- sound/core/pcm_lib.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/core') diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index bcf95d3ff5c7..e23e0e7ab26f 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -67,6 +67,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram } else { if (new_hw_ptr == ULONG_MAX) { /* initialization */ snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime); + if (avail > runtime->buffer_size) + avail = runtime->buffer_size; runtime->silence_filled = avail > 0 ? avail : 0; runtime->silence_start = (runtime->status->hw_ptr + runtime->silence_filled) % -- cgit v1.2.3