add new silence memblock caching subsystem

git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2272 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2008-04-20 19:41:26 +00:00
parent 4b1d684d26
commit 1ddb95a4ce
2 changed files with 119 additions and 45 deletions

View file

@ -42,28 +42,6 @@
#define PA_SILENCE_MAX (PA_PAGE_SIZE*16) #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length) {
pa_memblock *b;
pa_assert(pool);
pa_assert(spec);
if (length <= 0)
length = PA_MIN(pa_bytes_per_second(spec)/20, /* 50 ms */
pa_mempool_block_size_max(pool));
if (length > PA_SILENCE_MAX)
length = PA_SILENCE_MAX;
length = pa_frame_align(length, spec);
b = pa_silence_memblock(pa_memblock_new(pool, length), spec);
pa_memblock_set_is_silence(b, TRUE);
return b;
}
pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
void *data; void *data;
@ -77,7 +55,7 @@ pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
return b; return b;
} }
void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) { pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
void *data; void *data;
pa_assert(c); pa_assert(c);
@ -87,37 +65,38 @@ void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
data = pa_memblock_acquire(c->memblock); data = pa_memblock_acquire(c->memblock);
pa_silence_memory((uint8_t*) data+c->index, c->length, spec); pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
pa_memblock_release(c->memblock); pa_memblock_release(c->memblock);
return c;
} }
void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { static uint8_t silence_byte(pa_sample_format_t format) {
uint8_t c = 0; switch (format) {
pa_assert(p);
pa_assert(length > 0);
pa_assert(spec);
switch (spec->format) {
case PA_SAMPLE_U8: case PA_SAMPLE_U8:
c = 0x80; return 0x80;
break;
case PA_SAMPLE_S16LE: case PA_SAMPLE_S16LE:
case PA_SAMPLE_S16BE: case PA_SAMPLE_S16BE:
case PA_SAMPLE_S32LE: case PA_SAMPLE_S32LE:
case PA_SAMPLE_S32BE: case PA_SAMPLE_S32BE:
case PA_SAMPLE_FLOAT32: case PA_SAMPLE_FLOAT32LE:
case PA_SAMPLE_FLOAT32RE: case PA_SAMPLE_FLOAT32BE:
c = 0; return 0;
break;
case PA_SAMPLE_ALAW: case PA_SAMPLE_ALAW:
c = 0xd5; return 0xd5;
break;
case PA_SAMPLE_ULAW: case PA_SAMPLE_ULAW:
c = 0xff; return 0xff;
break;
default: default:
pa_assert_not_reached(); pa_assert_not_reached();
} }
return 0;
}
memset(p, c, length); void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
pa_assert(p);
pa_assert(length > 0);
pa_assert(spec);
memset(p, silence_byte(spec->format), length);
return p;
} }
static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) {
@ -934,3 +913,90 @@ void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss,
} }
} }
} }
static pa_memblock *silence_memblock_new(pa_mempool *pool, uint8_t c) {
pa_memblock *b;
size_t length;
void *data;
pa_assert(pool);
length = PA_MIN(pa_mempool_block_size_max(pool), PA_SILENCE_MAX);
b = pa_memblock_new(pool, length);
data = pa_memblock_acquire(b);
memset(data, c, length);
pa_memblock_release(b);
pa_memblock_set_is_silence(b, TRUE);
return b;
}
void pa_silence_cache_init(pa_silence_cache *cache) {
pa_assert(cache);
memset(cache, 0, sizeof(pa_silence_cache));
}
void pa_silence_cache_done(pa_silence_cache *cache) {
pa_sample_format_t f;
pa_assert(cache);
for (f = 0; f < PA_SAMPLE_MAX; f++)
if (cache->blocks[f])
pa_memblock_unref(cache->blocks[f]);
memset(cache, 0, sizeof(pa_silence_cache));
}
pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length) {
pa_memblock *b;
size_t l;
pa_assert(cache);
pa_assert(pa_sample_spec_valid(spec));
if (!(b = cache->blocks[spec->format]))
switch (spec->format) {
case PA_SAMPLE_U8:
cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80);
break;
case PA_SAMPLE_S16LE:
case PA_SAMPLE_S16BE:
case PA_SAMPLE_S32LE:
case PA_SAMPLE_S32BE:
case PA_SAMPLE_FLOAT32LE:
case PA_SAMPLE_FLOAT32BE:
cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0);
cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b);
cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b);
cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b);
cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b);
cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b);
break;
case PA_SAMPLE_ALAW:
cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5);
break;
case PA_SAMPLE_ULAW:
cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff);
break;
default:
pa_assert_not_reached();
}
pa_assert(b);
ret->memblock = pa_memblock_ref(b);
l = pa_memblock_get_length(b);
if (length > l || length == 0)
length = l;
ret->length = pa_frame_align(length, spec);
ret->index = 0;
return ret;
}

View file

@ -30,10 +30,18 @@
#include <pulsecore/memblock.h> #include <pulsecore/memblock.h>
#include <pulsecore/memchunk.h> #include <pulsecore/memchunk.h>
typedef struct pa_silence_cache {
pa_memblock* blocks[PA_SAMPLE_MAX];
} pa_silence_cache;
void pa_silence_cache_init(pa_silence_cache *cache);
void pa_silence_cache_done(pa_silence_cache *cache);
void *pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec);
pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec);
pa_memblock* pa_silence_memblock(pa_memblock *b, const pa_sample_spec *spec); pa_memblock* pa_silence_memblock(pa_memblock *b, const pa_sample_spec *spec);
pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length);
void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec); pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length);
void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec);
typedef struct pa_mix_info { typedef struct pa_mix_info {
pa_memchunk chunk; pa_memchunk chunk;