~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjmedia/src/pjmedia/echo_common.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: echo_common.c 3841 2011-10-24 09:28:13Z ming $ */
 
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/echo.h>
 
22
#include <pjmedia/delaybuf.h>
 
23
#include <pjmedia/frame.h>
 
24
#include <pjmedia/errno.h>
 
25
#include <pj/assert.h>
 
26
#include <pj/list.h>
 
27
#include <pj/log.h>
 
28
#include <pj/math.h>
 
29
#include <pj/pool.h>
 
30
#include "echo_internal.h"
 
31
 
 
32
#define THIS_FILE   "echo_common.c"
 
33
 
 
34
typedef struct ec_operations ec_operations;
 
35
 
 
36
struct frame
 
37
{
 
38
    PJ_DECL_LIST_MEMBER(struct frame);
 
39
    short   buf[1];
 
40
};
 
41
 
 
42
struct pjmedia_echo_state
 
43
{
 
44
    pj_pool_t       *pool;
 
45
    char            *obj_name;
 
46
    unsigned         samples_per_frame;
 
47
    void            *state;
 
48
    ec_operations   *op;
 
49
 
 
50
    pj_bool_t        lat_ready;     /* lat_buf has been filled in.          */
 
51
    struct frame     lat_buf;       /* Frame queue for delayed playback     */
 
52
    struct frame     lat_free;      /* Free frame list.                     */
 
53
 
 
54
    pjmedia_delay_buf   *delay_buf;
 
55
    pj_int16_t      *frm_buf;
 
56
};
 
57
 
 
58
 
 
59
struct ec_operations
 
60
{
 
61
    const char *name;
 
62
 
 
63
    pj_status_t (*ec_create)(pj_pool_t *pool,
 
64
                             unsigned clock_rate,
 
65
                             unsigned channel_count,
 
66
                             unsigned samples_per_frame,
 
67
                             unsigned tail_ms,
 
68
                             unsigned options,
 
69
                             void **p_state );
 
70
    pj_status_t (*ec_destroy)(void *state );
 
71
    void        (*ec_reset)(void *state );
 
72
    pj_status_t (*ec_cancel)(void *state,
 
73
                             pj_int16_t *rec_frm,
 
74
                             const pj_int16_t *play_frm,
 
75
                             unsigned options,
 
76
                             void *reserved );
 
77
};
 
78
 
 
79
 
 
80
static struct ec_operations echo_supp_op = 
 
81
{
 
82
    "Echo suppressor",
 
83
    &echo_supp_create,
 
84
    &echo_supp_destroy,
 
85
    &echo_supp_reset,
 
86
    &echo_supp_cancel_echo
 
87
};
 
88
 
 
89
 
 
90
 
 
91
/*
 
92
 * Speex AEC prototypes
 
93
 */
 
94
#if defined(PJMEDIA_HAS_SPEEX_AEC) && PJMEDIA_HAS_SPEEX_AEC!=0
 
95
static struct ec_operations speex_aec_op = 
 
96
{
 
97
    "AEC",
 
98
    &speex_aec_create,
 
99
    &speex_aec_destroy,
 
100
    &speex_aec_reset,
 
101
    &speex_aec_cancel_echo
 
102
};
 
103
#endif
 
104
 
 
105
 
 
106
/*
 
107
 * IPP AEC prototypes
 
108
 */
 
109
#if defined(PJMEDIA_HAS_INTEL_IPP_AEC) && PJMEDIA_HAS_INTEL_IPP_AEC!=0
 
110
static struct ec_operations ipp_aec_op = 
 
111
{
 
112
    "IPP AEC",
 
113
    &ipp_aec_create,
 
114
    &ipp_aec_destroy,
 
115
    &ipp_aec_reset,
 
116
    &ipp_aec_cancel_echo
 
117
};
 
118
#endif
 
119
 
 
120
/*
 
121
 * Create the echo canceller. 
 
122
 */
 
123
PJ_DEF(pj_status_t) pjmedia_echo_create( pj_pool_t *pool,
 
124
                                         unsigned clock_rate,
 
125
                                         unsigned samples_per_frame,
 
126
                                         unsigned tail_ms,
 
127
                                         unsigned latency_ms,
 
128
                                         unsigned options,
 
129
                                         pjmedia_echo_state **p_echo )
 
130
{
 
131
    return pjmedia_echo_create2(pool, clock_rate, 1, samples_per_frame,
 
132
                                tail_ms, latency_ms, options, p_echo);
 
133
}
 
134
 
 
135
/*
 
136
 * Create the echo canceller. 
 
137
 */
 
138
PJ_DEF(pj_status_t) pjmedia_echo_create2(pj_pool_t *pool,
 
139
                                         unsigned clock_rate,
 
140
                                         unsigned channel_count,
 
141
                                         unsigned samples_per_frame,
 
142
                                         unsigned tail_ms,
 
143
                                         unsigned latency_ms,
 
144
                                         unsigned options,
 
145
                                         pjmedia_echo_state **p_echo )
 
146
{
 
147
    unsigned ptime, lat_cnt;
 
148
    unsigned delay_buf_opt = 0;
 
149
    pjmedia_echo_state *ec;
 
150
    pj_status_t status;
 
151
 
 
152
    /* Create new pool and instantiate and init the EC */
 
153
    pool = pj_pool_create(pool->factory, "ec%p", 256, 256, NULL);
 
154
    ec = PJ_POOL_ZALLOC_T(pool, struct pjmedia_echo_state);
 
155
    ec->pool = pool;
 
156
    ec->obj_name = pool->obj_name;
 
157
    ec->samples_per_frame = samples_per_frame;
 
158
    ec->frm_buf = (pj_int16_t*)pj_pool_alloc(pool, samples_per_frame<<1);
 
159
    pj_list_init(&ec->lat_buf);
 
160
    pj_list_init(&ec->lat_free);
 
161
 
 
162
    /* Select the backend algorithm */
 
163
    if (0) {
 
164
        /* Dummy */
 
165
        ;
 
166
#if defined(PJMEDIA_HAS_SPEEX_AEC) && PJMEDIA_HAS_SPEEX_AEC!=0
 
167
    } else if ((options & PJMEDIA_ECHO_ALGO_MASK) == PJMEDIA_ECHO_SPEEX ||
 
168
               (options & PJMEDIA_ECHO_ALGO_MASK) == PJMEDIA_ECHO_DEFAULT) 
 
169
    {
 
170
        ec->op = &speex_aec_op;
 
171
#endif
 
172
 
 
173
#if defined(PJMEDIA_HAS_INTEL_IPP_AEC) && PJMEDIA_HAS_INTEL_IPP_AEC!=0
 
174
    } else if ((options & PJMEDIA_ECHO_ALGO_MASK) == PJMEDIA_ECHO_IPP ||
 
175
               (options & PJMEDIA_ECHO_ALGO_MASK) == PJMEDIA_ECHO_DEFAULT)
 
176
    {
 
177
        ec->op = &ipp_aec_op;
 
178
 
 
179
#endif
 
180
 
 
181
    } else {
 
182
        ec->op = &echo_supp_op;
 
183
    }
 
184
 
 
185
    PJ_LOG(5,(ec->obj_name, "Creating %s", ec->op->name));
 
186
 
 
187
    /* Instantiate EC object */
 
188
    status = (*ec->op->ec_create)(pool, clock_rate, channel_count, 
 
189
                                  samples_per_frame, tail_ms, 
 
190
                                  options, &ec->state);
 
191
    if (status != PJ_SUCCESS) {
 
192
        pj_pool_release(pool);
 
193
        return status;
 
194
    }
 
195
 
 
196
    /* Create latency buffers */
 
197
    ptime = samples_per_frame * 1000 / clock_rate;
 
198
    if (latency_ms > ptime) {
 
199
        /* Normalize latency with delaybuf/WSOLA latency */
 
200
        latency_ms -= PJ_MIN(ptime, PJMEDIA_WSOLA_DELAY_MSEC);
 
201
    }
 
202
    if (latency_ms < ptime) {
 
203
        /* Give at least one frame delay to simplify programming */
 
204
        latency_ms = ptime;
 
205
    }
 
206
    lat_cnt = latency_ms / ptime;
 
207
    while (lat_cnt--)  {
 
208
        struct frame *frm;
 
209
 
 
210
        frm = (struct frame*) pj_pool_alloc(pool, (samples_per_frame<<1) +
 
211
                                                  sizeof(struct frame));
 
212
        pj_list_push_back(&ec->lat_free, frm);
 
213
    }
 
214
 
 
215
    /* Create delay buffer to compensate drifts */
 
216
    if (options & PJMEDIA_ECHO_USE_SIMPLE_FIFO)
 
217
        delay_buf_opt |= PJMEDIA_DELAY_BUF_SIMPLE_FIFO;
 
218
    status = pjmedia_delay_buf_create(ec->pool, ec->obj_name, clock_rate, 
 
219
                                      samples_per_frame, channel_count,
 
220
                                      (PJMEDIA_SOUND_BUFFER_COUNT+1) * ptime,
 
221
                                      delay_buf_opt, &ec->delay_buf);
 
222
    if (status != PJ_SUCCESS) {
 
223
        pj_pool_release(pool);
 
224
        return status;
 
225
    }
 
226
 
 
227
    PJ_LOG(4,(ec->obj_name, 
 
228
              "%s created, clock_rate=%d, channel=%d, "
 
229
              "samples per frame=%d, tail length=%d ms, "
 
230
              "latency=%d ms", 
 
231
              ec->op->name, clock_rate, channel_count, samples_per_frame,
 
232
              tail_ms, latency_ms));
 
233
 
 
234
    /* Done */
 
235
    *p_echo = ec;
 
236
 
 
237
    return PJ_SUCCESS;
 
238
}
 
239
 
 
240
 
 
241
/*
 
242
 * Destroy the Echo Canceller. 
 
243
 */
 
244
PJ_DEF(pj_status_t) pjmedia_echo_destroy(pjmedia_echo_state *echo )
 
245
{
 
246
    (*echo->op->ec_destroy)(echo->state);
 
247
 
 
248
    if (echo->delay_buf) {
 
249
        pjmedia_delay_buf_destroy(echo->delay_buf);
 
250
        echo->delay_buf = NULL;
 
251
    }
 
252
 
 
253
    pj_pool_release(echo->pool);
 
254
    return PJ_SUCCESS;
 
255
}
 
256
 
 
257
 
 
258
/*
 
259
 * Reset the echo canceller.
 
260
 */
 
261
PJ_DEF(pj_status_t) pjmedia_echo_reset(pjmedia_echo_state *echo )
 
262
{
 
263
    while (!pj_list_empty(&echo->lat_buf)) {
 
264
        struct frame *frm;
 
265
        frm = echo->lat_buf.next;
 
266
        pj_list_erase(frm);
 
267
        pj_list_push_back(&echo->lat_free, frm);
 
268
    }
 
269
    echo->lat_ready = PJ_FALSE;
 
270
    pjmedia_delay_buf_reset(echo->delay_buf);
 
271
    echo->op->ec_reset(echo->state);
 
272
    return PJ_SUCCESS;
 
273
}
 
274
 
 
275
 
 
276
/*
 
277
 * Let the Echo Canceller know that a frame has been played to the speaker.
 
278
 */
 
279
PJ_DEF(pj_status_t) pjmedia_echo_playback( pjmedia_echo_state *echo,
 
280
                                           pj_int16_t *play_frm )
 
281
{
 
282
    /* Playing frame should be stored, as it will be used by echo_capture() 
 
283
     * as reference frame, delay buffer is used for storing the playing frames
 
284
     * as in case there was clock drift between mic & speaker.
 
285
     *
 
286
     * Ticket #830:
 
287
     * Note that pjmedia_delay_buf_put() may modify the input frame and those
 
288
     * modified frames may not be smooth, i.e: if there were two or more
 
289
     * consecutive pjmedia_delay_buf_get() before next pjmedia_delay_buf_put(),
 
290
     * so we'll just feed the delay buffer with the copy of playing frame,
 
291
     * instead of the original playing frame. However this will cause the EC 
 
292
     * uses slight 'different' frames (for reference) than actually played 
 
293
     * by the speaker.
 
294
     */
 
295
    pjmedia_copy_samples(echo->frm_buf, play_frm, 
 
296
                         echo->samples_per_frame);
 
297
    pjmedia_delay_buf_put(echo->delay_buf, echo->frm_buf);
 
298
 
 
299
    if (!echo->lat_ready) {
 
300
        /* We've not built enough latency in the buffer, so put this frame
 
301
         * in the latency buffer list.
 
302
         */
 
303
        struct frame *frm;
 
304
 
 
305
        if (pj_list_empty(&echo->lat_free)) {
 
306
            echo->lat_ready = PJ_TRUE;
 
307
            PJ_LOG(5,(echo->obj_name, "Latency bufferring complete"));
 
308
            return PJ_SUCCESS;
 
309
        }
 
310
            
 
311
        frm = echo->lat_free.prev;
 
312
        pj_list_erase(frm);
 
313
 
 
314
        /* Move one frame from delay buffer to the latency buffer. */
 
315
        pjmedia_delay_buf_get(echo->delay_buf, echo->frm_buf);
 
316
        pjmedia_copy_samples(frm->buf, echo->frm_buf, echo->samples_per_frame);
 
317
        pj_list_push_back(&echo->lat_buf, frm);
 
318
    }
 
319
 
 
320
    return PJ_SUCCESS;
 
321
}
 
322
 
 
323
 
 
324
/*
 
325
 * Let the Echo Canceller knows that a frame has been captured from 
 
326
 * the microphone.
 
327
 */
 
328
PJ_DEF(pj_status_t) pjmedia_echo_capture( pjmedia_echo_state *echo,
 
329
                                          pj_int16_t *rec_frm,
 
330
                                          unsigned options )
 
331
{
 
332
    struct frame *oldest_frm;
 
333
    pj_status_t status, rc;
 
334
 
 
335
    if (!echo->lat_ready) {
 
336
        /* Prefetching to fill in the desired latency */
 
337
        PJ_LOG(5,(echo->obj_name, "Prefetching.."));
 
338
        return PJ_SUCCESS;
 
339
    }
 
340
 
 
341
    /* Retrieve oldest frame from the latency buffer */
 
342
    oldest_frm = echo->lat_buf.next;
 
343
    pj_list_erase(oldest_frm);
 
344
 
 
345
    /* Cancel echo using this reference frame */
 
346
    status = pjmedia_echo_cancel(echo, rec_frm, oldest_frm->buf, 
 
347
                                 options, NULL);
 
348
 
 
349
    /* Move one frame from delay buffer to the latency buffer. */
 
350
    rc = pjmedia_delay_buf_get(echo->delay_buf, oldest_frm->buf);
 
351
    if (rc != PJ_SUCCESS) {
 
352
        /* Ooops.. no frame! */
 
353
        PJ_LOG(5,(echo->obj_name, 
 
354
                  "No frame from delay buffer. This will upset EC later"));
 
355
        pjmedia_zero_samples(oldest_frm->buf, echo->samples_per_frame);
 
356
    }
 
357
    pj_list_push_back(&echo->lat_buf, oldest_frm);
 
358
    
 
359
    return status;
 
360
}
 
361
 
 
362
 
 
363
/*
 
364
 * Perform echo cancellation.
 
365
 */
 
366
PJ_DEF(pj_status_t) pjmedia_echo_cancel( pjmedia_echo_state *echo,
 
367
                                         pj_int16_t *rec_frm,
 
368
                                         const pj_int16_t *play_frm,
 
369
                                         unsigned options,
 
370
                                         void *reserved )
 
371
{
 
372
    return (*echo->op->ec_cancel)( echo->state, rec_frm, play_frm, options, 
 
373
                                   reserved);
 
374
}
 
375