asterisk-chan-dongle/mixbuffer.c

119 lines
2.5 KiB
C
Raw Normal View History

2023-05-25 08:30:27 +00:00
/*
Copyright (C) 2010 bg <bg_one@mail.ru>
*/
#include "ast_config.h"
#include <asterisk/utils.h> /* ast_slinear_saturated_add() */
#include "mixbuffer.h"
#/* */
EXPORT_DEF void mixb_attach(struct mixbuffer * mb, struct mixstream * stream)
{
stream->entry.next = NULL;
stream->used = 0;
stream->write = mb->rb.read;
AST_LIST_INSERT_TAIL(&mb->streams, stream, entry);
mb->attached++;
}
#/* */
EXPORT_DEF void mixb_detach(struct mixbuffer * mb, struct mixstream * stream)
{
mb->attached--;
AST_LIST_REMOVE(&mb->streams, stream, entry);
}
#/* TODO: move up */
static void * saturated_sum(void* s1, const void *s2, size_t n)
{
short* s11 = s1;
short* s22 = (short*)s2;
/* FIXME: odd bytes */
for(n /= 2; n; n--, s11++, s22++)
ast_slinear_saturated_add(s11, s22);
return s1;
}
#/* function not update rb */
static inline size_t mixb_mix_write(struct mixbuffer * mb, struct mixstream * stream, const char * data, size_t len)
{
size_t rv;
/* save global state */
size_t save_write = mb->rb.write;
size_t save_used = mb->rb.used;
/* load local state */
mb->rb.write = stream->write;
mb->rb.used = stream->used;
rv = rb_write_core(&mb->rb, data, len, saturated_sum);
/* update local state */
stream->write = mb->rb.write;
stream->used = mb->rb.used;
/* restore global state */
mb->rb.used = save_used;
mb->rb.write = save_write;
return rv;
}
#/* */
EXPORT_DEF size_t mixb_write(struct mixbuffer * mb, struct mixstream * stream, const char * data, size_t len)
{
/* local state: how many data you fit? */
size_t max_mix = mixb_free(mb, stream);
if(max_mix < len)
len = max_mix;
if(len > 0)
{
max_mix = mb->rb.used - stream->used;
if(len > max_mix)
{
/* optitional Mix followed by copy */
if(max_mix)
mixb_mix_write(mb, stream, data, max_mix);
rb_write(&mb->rb, data + max_mix, len - max_mix);
/* save local state */
stream->write = mb->rb.write;
stream->used = mb->rb.used;
}
else
{
/* Mix only */
mixb_mix_write(mb, stream, data, len);
}
}
return len;
}
#/* */
EXPORT_DEF size_t mixb_read_upd(struct mixbuffer * mb, size_t len)
{
struct mixstream * stream;
// NOTE: change used, read and also can change write
size_t rv = rb_read_upd(&mb->rb, len);
// all streams has one read but differ used
AST_LIST_TRAVERSE(&mb->streams, stream, entry) {
if(stream->used > len)
stream->used -= len;
else
stream->used = 0;
stream->write = mb->rb.read + stream->used;
if(stream->write >= mb->rb.size)
stream->write -= mb->rb.size;
}
return rv;
}