blob: 9042ef99272ace151491958762381c582b47d591 [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
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.
10 *
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.
15 *
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
19 */
20
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>
27#include <pj/lock.h>
28#include <pj/log.h>
29#include <pj/math.h>
30#include <pj/pool.h>
31
32
33#if 0
34# define TRACE__(x) PJ_LOG(3,x)
35#else
36# define TRACE__(x)
37#endif
38
39/* Operation types of delay buffer */
40enum OP
41{
42 OP_PUT,
43 OP_GET
44};
45
46/* Specify time for delaybuf to recalculate effective delay, in ms.
47 */
48#define RECALC_TIME 2000
49
50/* Default value of maximum delay, in ms, this value is used when
51 * maximum delay requested is less than ptime (one frame length).
52 */
53#define DEFAULT_MAX_DELAY 400
54
55/* Number of frames to add to learnt level for additional stability.
56 */
57#define SAFE_MARGIN 0
58
59/* This structure describes internal delaybuf settings and states.
60 */
61struct pjmedia_delay_buf
62{
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
70 samples */
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. */
77
78 /* Learning vars */
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 */
83
84 /* Drift handler */
85 pjmedia_wsola *wsola; /**< Drift handler */
86};
87
88
89PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool,
90 const char *name,
91 unsigned clock_rate,
92 unsigned samples_per_frame,
93 unsigned channel_count,
94 unsigned max_delay,
95 unsigned options,
96 pjmedia_delay_buf **p_b)
97{
98 pjmedia_delay_buf *b;
99 pj_status_t status;
100
101 PJ_ASSERT_RETURN(pool && samples_per_frame && clock_rate && channel_count &&
102 p_b, PJ_EINVAL);
103
104 if (!name) {
105 name = "delaybuf";
106 }
107
108 b = PJ_POOL_ZALLOC_T(pool, pjmedia_delay_buf);
109
110 pj_ansi_strncpy(b->obj_name, name, PJ_MAX_OBJ_NAME-1);
111
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);
117
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;
121
122 /* Create circular buffer */
123 status = pjmedia_circ_buf_create(pool, b->max_cnt, &b->circ_buf);
124 if (status != PJ_SUCCESS)
125 return status;
126
127 if (!(options & PJMEDIA_DELAY_BUF_SIMPLE_FIFO)) {
128 /* Create WSOLA */
129 status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1,
130 PJMEDIA_WSOLA_NO_FADING, &b->wsola);
131 if (status != PJ_SUCCESS)
132 return status;
133 PJ_LOG(5, (b->obj_name, "Using delay buffer with WSOLA."));
134 } else {
135 PJ_LOG(5, (b->obj_name, "Using simple FIFO delay buffer."));
136 }
137
138 /* Finally, create mutex */
139 status = pj_lock_create_recursive_mutex(pool, b->obj_name,
140 &b->lock);
141 if (status != PJ_SUCCESS)
142 return status;
143
144 *p_b = b;
145
146 TRACE__((b->obj_name,"Delay buffer created"));
147
148 return PJ_SUCCESS;
149}
150
151PJ_DEF(pj_status_t) pjmedia_delay_buf_destroy(pjmedia_delay_buf *b)
152{
153 pj_status_t status = PJ_SUCCESS;
154
155 PJ_ASSERT_RETURN(b, PJ_EINVAL);
156
157 pj_lock_acquire(b->lock);
158
159 if (b->wsola) {
160 status = pjmedia_wsola_destroy(b->wsola);
161 if (status == PJ_SUCCESS)
162 b->wsola = NULL;
163 }
164
165 pj_lock_release(b->lock);
166
167 pj_lock_destroy(b->lock);
168 b->lock = NULL;
169
170 return status;
171}
172
173/* This function will erase samples from delay buffer.
174 * The number of erased samples is guaranteed to be >= erase_cnt.
175 */
176static void shrink_buffer(pjmedia_delay_buf *b, unsigned erase_cnt)
177{
178 pj_int16_t *buf1, *buf2;
179 unsigned buf1len;
180 unsigned buf2len;
181 pj_status_t status;
182
183 pj_assert(b && erase_cnt && pjmedia_circ_buf_get_len(b->circ_buf));
184
185 pjmedia_circ_buf_get_read_regions(b->circ_buf, &buf1, &buf1len,
186 &buf2, &buf2len);
187 status = pjmedia_wsola_discard(b->wsola, buf1, buf1len, buf2, buf2len,
188 &erase_cnt);
189
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.
194 */
195
196 pjmedia_circ_buf_set_len(b->circ_buf,
197 pjmedia_circ_buf_get_len(b->circ_buf) -
198 erase_cnt);
199
200 PJ_LOG(5,(b->obj_name,"%d samples reduced, buf_cnt=%d",
201 erase_cnt, pjmedia_circ_buf_get_len(b->circ_buf)));
202 }
203}
204
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)
211
212static void update(pjmedia_delay_buf *b, enum OP op)
213{
214 /* Sequential operation */
215 if (op == b->last_op) {
216 ++b->level;
217 return;
218 }
219
220 /* Switching operation */
221 if (b->level > b->max_level)
222 b->max_level = b->level;
223
224 b->recalc_timer -= (b->level * b->ptime) >> 1;
225
226 b->last_op = op;
227 b->level = 1;
228
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;
232
233 /* Smoothening effective count transition */
234 AGC(b->eff_cnt, new_eff_cnt);
235
236 /* Make sure the new effective count is multiplication of
237 * channel_count, so let's round it up.
238 */
239 if (b->eff_cnt % b->channel_count)
240 b->eff_cnt += b->channel_count - (b->eff_cnt % b->channel_count);
241
242 TRACE__((b->obj_name,"Cur eff_cnt=%d", b->eff_cnt));
243
244 b->max_level = 0;
245 b->recalc_timer = RECALC_TIME;
246 }
247
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)
251 {
252 unsigned erase_cnt = b->samples_per_frame >> 1;
253 unsigned old_buf_cnt = pjmedia_circ_buf_get_len(b->circ_buf);
254
255 shrink_buffer(b, erase_cnt);
256 PJ_LOG(4,(b->obj_name,"Buffer size adjusted from %d to %d (eff_cnt=%d)",
257 old_buf_cnt,
258 pjmedia_circ_buf_get_len(b->circ_buf),
259 b->eff_cnt));
260 }
261}
262
263PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
264 pj_int16_t frame[])
265{
266 pj_status_t status;
267
268 PJ_ASSERT_RETURN(b && frame, PJ_EINVAL);
269
270 pj_lock_acquire(b->lock);
271
272 if (b->wsola) {
273 update(b, OP_PUT);
274
275 status = pjmedia_wsola_save(b->wsola, frame, PJ_FALSE);
276 if (status != PJ_SUCCESS) {
277 pj_lock_release(b->lock);
278 return status;
279 }
280 }
281
282 /* Overflow checking */
283 if (pjmedia_circ_buf_get_len(b->circ_buf) + b->samples_per_frame >
284 b->max_cnt)
285 {
286 unsigned erase_cnt;
287
288 if (b->wsola) {
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;
293
294 shrink_buffer(b, erase_cnt);
295 }
296
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.
300 */
301 if (pjmedia_circ_buf_get_len(b->circ_buf) + b->samples_per_frame >
302 b->max_cnt)
303 {
304 erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) +
305 b->samples_per_frame - b->max_cnt;
306
307 pjmedia_circ_buf_adv_read_ptr(b->circ_buf, erase_cnt);
308
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)));
312 }
313 }
314
315 pjmedia_circ_buf_write(b->circ_buf, frame, b->samples_per_frame);
316
317 pj_lock_release(b->lock);
318 return PJ_SUCCESS;
319}
320
321PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b,
322 pj_int16_t frame[])
323{
324 pj_status_t status = PJ_SUCCESS;
325
326 PJ_ASSERT_RETURN(b && frame, PJ_EINVAL);
327
328 pj_lock_acquire(b->lock);
329
330 if (b->wsola)
331 update(b, OP_GET);
332
333 /* Starvation checking */
334 if (pjmedia_circ_buf_get_len(b->circ_buf) < b->samples_per_frame) {
335
336 PJ_LOG(4,(b->obj_name,"Underflow, buf_cnt=%d, will generate 1 frame",
337 pjmedia_circ_buf_get_len(b->circ_buf)));
338
339 if (b->wsola) {
340 status = pjmedia_wsola_generate(b->wsola, frame);
341
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);
346 return PJ_SUCCESS;
347 }
348
349 /* Put generated frame into buffer */
350 pjmedia_circ_buf_write(b->circ_buf, frame,
351 b->samples_per_frame);
352 }
353 }
354
355 if (!b->wsola || status != PJ_SUCCESS) {
356 unsigned buf_len = pjmedia_circ_buf_get_len(b->circ_buf);
357
358 /* Give all what delay buffer has, then pad with zeroes */
359 if (b->wsola)
360 PJ_LOG(4,(b->obj_name,"Error generating frame, status=%d",
361 status));
362
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);
366
367 /* The buffer is empty now, reset it */
368 pjmedia_circ_buf_reset(b->circ_buf);
369
370 pj_lock_release(b->lock);
371
372 return PJ_SUCCESS;
373 }
374 }
375
376 pjmedia_circ_buf_read(b->circ_buf, frame, b->samples_per_frame);
377
378 pj_lock_release(b->lock);
379
380 return PJ_SUCCESS;
381}
382
383
384PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b)
385{
386 PJ_ASSERT_RETURN(b, PJ_EINVAL);
387
388 pj_lock_acquire(b->lock);
389
390 b->recalc_timer = RECALC_TIME;
391
392 /* Reset buffer */
393 pjmedia_circ_buf_reset(b->circ_buf);
394
395 /* Reset WSOLA */
396 if (b->wsola)
397 pjmedia_wsola_reset(b->wsola, 0);
398
399 pj_lock_release(b->lock);
400
401 PJ_LOG(5,(b->obj_name,"Delay buffer is reset"));
402
403 return PJ_SUCCESS;
404}
405