1
/* $Id: delaybuf.c 3841 2011-10-24 09:28:13Z ming $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include <pjmedia/delaybuf.h>
22
#include <pjmedia/circbuf.h>
23
#include <pjmedia/errno.h>
24
#include <pjmedia/frame.h>
25
#include <pjmedia/wsola.h>
26
#include <pj/assert.h>
34
# define TRACE__(x) PJ_LOG(3,x)
39
/* Operation types of delay buffer */
46
/* Specify time for delaybuf to recalculate effective delay, in ms.
48
#define RECALC_TIME 2000
50
/* Default value of maximum delay, in ms, this value is used when
51
* maximum delay requested is less than ptime (one frame length).
53
#define DEFAULT_MAX_DELAY 400
55
/* Number of frames to add to learnt level for additional stability.
59
/* This structure describes internal delaybuf settings and states.
61
struct pjmedia_delay_buf
63
/* Properties and configuration */
64
char obj_name[PJ_MAX_OBJ_NAME];
65
pj_lock_t *lock; /**< Lock object. */
66
unsigned samples_per_frame; /**< Number of samples in one frame */
67
unsigned ptime; /**< Frame time, in ms */
68
unsigned channel_count; /**< Channel count, in ms */
69
pjmedia_circ_buf *circ_buf; /**< Circular buffer to store audio
71
unsigned max_cnt; /**< Maximum samples to be buffered */
72
unsigned eff_cnt; /**< Effective count of buffered
73
samples to keep the optimum
74
balance between delay and
75
stability. This is calculated
76
based on burst level. */
79
unsigned level; /**< Burst level counter */
80
enum OP last_op; /**< Last op (GET or PUT) of learning*/
81
int recalc_timer; /**< Timer for recalculating max_level*/
82
unsigned max_level; /**< Current max burst level */
85
pjmedia_wsola *wsola; /**< Drift handler */
89
PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool,
92
unsigned samples_per_frame,
93
unsigned channel_count,
96
pjmedia_delay_buf **p_b)
101
PJ_ASSERT_RETURN(pool && samples_per_frame && clock_rate && channel_count &&
108
b = PJ_POOL_ZALLOC_T(pool, pjmedia_delay_buf);
110
pj_ansi_strncpy(b->obj_name, name, PJ_MAX_OBJ_NAME-1);
112
b->samples_per_frame = samples_per_frame;
113
b->channel_count = channel_count;
114
b->ptime = samples_per_frame * 1000 / clock_rate / channel_count;
115
if (max_delay < b->ptime)
116
max_delay = PJ_MAX(DEFAULT_MAX_DELAY, b->ptime);
118
b->max_cnt = samples_per_frame * max_delay / b->ptime;
119
b->eff_cnt = b->max_cnt >> 1;
120
b->recalc_timer = RECALC_TIME;
122
/* Create circular buffer */
123
status = pjmedia_circ_buf_create(pool, b->max_cnt, &b->circ_buf);
124
if (status != PJ_SUCCESS)
127
if (!(options & PJMEDIA_DELAY_BUF_SIMPLE_FIFO)) {
129
status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1,
130
PJMEDIA_WSOLA_NO_FADING, &b->wsola);
131
if (status != PJ_SUCCESS)
133
PJ_LOG(5, (b->obj_name, "Using delay buffer with WSOLA."));
135
PJ_LOG(5, (b->obj_name, "Using simple FIFO delay buffer."));
138
/* Finally, create mutex */
139
status = pj_lock_create_recursive_mutex(pool, b->obj_name,
141
if (status != PJ_SUCCESS)
146
TRACE__((b->obj_name,"Delay buffer created"));
151
PJ_DEF(pj_status_t) pjmedia_delay_buf_destroy(pjmedia_delay_buf *b)
153
pj_status_t status = PJ_SUCCESS;
155
PJ_ASSERT_RETURN(b, PJ_EINVAL);
157
pj_lock_acquire(b->lock);
160
status = pjmedia_wsola_destroy(b->wsola);
161
if (status == PJ_SUCCESS)
165
pj_lock_release(b->lock);
167
pj_lock_destroy(b->lock);
173
/* This function will erase samples from delay buffer.
174
* The number of erased samples is guaranteed to be >= erase_cnt.
176
static void shrink_buffer(pjmedia_delay_buf *b, unsigned erase_cnt)
178
pj_int16_t *buf1, *buf2;
183
pj_assert(b && erase_cnt && pjmedia_circ_buf_get_len(b->circ_buf));
185
pjmedia_circ_buf_get_read_regions(b->circ_buf, &buf1, &buf1len,
187
status = pjmedia_wsola_discard(b->wsola, buf1, buf1len, buf2, buf2len,
190
if ((status == PJ_SUCCESS) && (erase_cnt > 0)) {
191
/* WSOLA discard will manage the first buffer to be full, unless
192
* erase_cnt is greater than second buffer length. So it is safe
193
* to just set the circular buffer length.
196
pjmedia_circ_buf_set_len(b->circ_buf,
197
pjmedia_circ_buf_get_len(b->circ_buf) -
200
PJ_LOG(5,(b->obj_name,"%d samples reduced, buf_cnt=%d",
201
erase_cnt, pjmedia_circ_buf_get_len(b->circ_buf)));
205
/* Fast increase, slow decrease */
206
#define AGC_UP(cur, target) cur = (cur + target*3) >> 2
207
#define AGC_DOWN(cur, target) cur = (cur*3 + target) >> 2
208
#define AGC(cur, target) \
209
if (cur < target) AGC_UP(cur, target); \
210
else AGC_DOWN(cur, target)
212
static void update(pjmedia_delay_buf *b, enum OP op)
214
/* Sequential operation */
215
if (op == b->last_op) {
220
/* Switching operation */
221
if (b->level > b->max_level)
222
b->max_level = b->level;
224
b->recalc_timer -= (b->level * b->ptime) >> 1;
229
/* Recalculate effective count based on max_level */
230
if (b->recalc_timer <= 0) {
231
unsigned new_eff_cnt = (b->max_level+SAFE_MARGIN)*b->samples_per_frame;
233
/* Smoothening effective count transition */
234
AGC(b->eff_cnt, new_eff_cnt);
236
/* Make sure the new effective count is multiplication of
237
* channel_count, so let's round it up.
239
if (b->eff_cnt % b->channel_count)
240
b->eff_cnt += b->channel_count - (b->eff_cnt % b->channel_count);
242
TRACE__((b->obj_name,"Cur eff_cnt=%d", b->eff_cnt));
245
b->recalc_timer = RECALC_TIME;
248
/* See if we need to shrink the buffer to reduce delay */
249
if (op == OP_PUT && pjmedia_circ_buf_get_len(b->circ_buf) >
250
b->samples_per_frame + b->eff_cnt)
252
unsigned erase_cnt = b->samples_per_frame >> 1;
253
unsigned old_buf_cnt = pjmedia_circ_buf_get_len(b->circ_buf);
255
shrink_buffer(b, erase_cnt);
256
PJ_LOG(4,(b->obj_name,"Buffer size adjusted from %d to %d (eff_cnt=%d)",
258
pjmedia_circ_buf_get_len(b->circ_buf),
263
PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
268
PJ_ASSERT_RETURN(b && frame, PJ_EINVAL);
270
pj_lock_acquire(b->lock);
275
status = pjmedia_wsola_save(b->wsola, frame, PJ_FALSE);
276
if (status != PJ_SUCCESS) {
277
pj_lock_release(b->lock);
282
/* Overflow checking */
283
if (pjmedia_circ_buf_get_len(b->circ_buf) + b->samples_per_frame >
289
/* shrink one frame or just the diff? */
290
//erase_cnt = b->samples_per_frame;
291
erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) +
292
b->samples_per_frame - b->max_cnt;
294
shrink_buffer(b, erase_cnt);
297
/* Check if shrinking failed or erased count is less than requested,
298
* delaybuf needs to drop eldest samples, this is bad since the voice
299
* samples get rough transition which may produce tick noise.
301
if (pjmedia_circ_buf_get_len(b->circ_buf) + b->samples_per_frame >
304
erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) +
305
b->samples_per_frame - b->max_cnt;
307
pjmedia_circ_buf_adv_read_ptr(b->circ_buf, erase_cnt);
309
PJ_LOG(4,(b->obj_name,"%sDropping %d eldest samples, buf_cnt=%d",
310
(b->wsola? "Shrinking failed or insufficient. ": ""),
311
erase_cnt, pjmedia_circ_buf_get_len(b->circ_buf)));
315
pjmedia_circ_buf_write(b->circ_buf, frame, b->samples_per_frame);
317
pj_lock_release(b->lock);
321
PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b,
324
pj_status_t status = PJ_SUCCESS;
326
PJ_ASSERT_RETURN(b && frame, PJ_EINVAL);
328
pj_lock_acquire(b->lock);
333
/* Starvation checking */
334
if (pjmedia_circ_buf_get_len(b->circ_buf) < b->samples_per_frame) {
336
PJ_LOG(4,(b->obj_name,"Underflow, buf_cnt=%d, will generate 1 frame",
337
pjmedia_circ_buf_get_len(b->circ_buf)));
340
status = pjmedia_wsola_generate(b->wsola, frame);
342
if (status == PJ_SUCCESS) {
343
TRACE__((b->obj_name,"Successfully generate 1 frame"));
344
if (pjmedia_circ_buf_get_len(b->circ_buf) == 0) {
345
pj_lock_release(b->lock);
349
/* Put generated frame into buffer */
350
pjmedia_circ_buf_write(b->circ_buf, frame,
351
b->samples_per_frame);
355
if (!b->wsola || status != PJ_SUCCESS) {
356
unsigned buf_len = pjmedia_circ_buf_get_len(b->circ_buf);
358
/* Give all what delay buffer has, then pad with zeroes */
360
PJ_LOG(4,(b->obj_name,"Error generating frame, status=%d",
363
pjmedia_circ_buf_read(b->circ_buf, frame, buf_len);
364
pjmedia_zero_samples(&frame[buf_len],
365
b->samples_per_frame - buf_len);
367
/* The buffer is empty now, reset it */
368
pjmedia_circ_buf_reset(b->circ_buf);
370
pj_lock_release(b->lock);
376
pjmedia_circ_buf_read(b->circ_buf, frame, b->samples_per_frame);
378
pj_lock_release(b->lock);
384
PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b)
386
PJ_ASSERT_RETURN(b, PJ_EINVAL);
388
pj_lock_acquire(b->lock);
390
b->recalc_timer = RECALC_TIME;
393
pjmedia_circ_buf_reset(b->circ_buf);
397
pjmedia_wsola_reset(b->wsola, 0);
399
pj_lock_release(b->lock);
401
PJ_LOG(5,(b->obj_name,"Delay buffer is reset"));