~xnox/debian/sid/dahdi-linux/nmu-659818

« back to all changes in this revision

Viewing changes to drivers/dahdi/dahdi_echocan_sec.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell, Tzafrir Cohen, Victor Seva
  • Date: 2009-05-20 07:22:46 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090520072246-y1ba8ofc81ykgf8z
Tags: 1:2.2.0~dfsg~rc4-1
* New upstream release

[ Tzafrir Cohen ]
* NOT RELEASED YET
* Dropped qozap as wcb4xxp provides that functionality.
* New upstream RC.
* Actually build OpenVox drivers.
* opvxa1200.c: rev. 1.4.12.4 (battery fixes and such)
* Fix '${match}' in udev rules file (hardwire).
* no_firmware_download: Disable downloading a binary kernel module at 
  build time.

[ Victor Seva ]
* fix debian/watch. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
67
67
 
68
68
#define NONUPDATE_DWELL_TIME    600     /* 600 samples, or 75ms */
69
69
 
70
 
struct echo_can_state
71
 
{
72
 
    int tx_power;
73
 
    int rx_power;
74
 
    int clean_rx_power;
75
 
 
76
 
    int rx_power_threshold;
77
 
    int nonupdate_dwell;
78
 
 
79
 
    int16_t *tx_history;        /* Last N tx samples */
80
 
    int32_t *fir_taps;          /* Echo FIR taps */
81
 
        int16_t *fir_taps_short;        /* Echo FIR taps, shorts instead of ints */
82
 
 
83
 
    int curr_pos;
84
 
        
85
 
    int taps;
86
 
    int tap_mask;
87
 
    int use_nlp;
88
 
    int use_suppressor;
89
 
    
90
 
    int32_t supp_test1;
91
 
    int32_t supp_test2;
92
 
    int32_t supp1;
93
 
    int32_t supp2;
94
 
 
95
 
    int32_t latest_correction;  /* Indication of the magnitude of the latest
96
 
                                   adaption, or a code to indicate why adaption
97
 
                                   was skipped, for test purposes */
98
 
};
99
 
 
100
70
/* Original parameters : 
101
71
#define MIN_TX_POWER_FOR_ADAPTION   256
102
72
#define MIN_RX_POWER_FOR_ADAPTION   128
110
80
#define MIN_RX_POWER_FOR_ADAPTION   64
111
81
*/
112
82
 
113
 
static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p,
114
 
                           struct echo_can_state **ec)
 
83
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
 
84
                           struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
 
85
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
 
86
static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size);
 
87
static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val);
 
88
static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable);
 
89
 
 
90
static const struct dahdi_echocan_factory my_factory = {
 
91
        .name = "SEC",
 
92
        .owner = THIS_MODULE,
 
93
        .echocan_create = echo_can_create,
 
94
};
 
95
 
 
96
static const struct dahdi_echocan_features my_features = {
 
97
        .NLP_toggle = 1,
 
98
};
 
99
 
 
100
static const struct dahdi_echocan_ops my_ops = {
 
101
        .name = "SEC",
 
102
        .echocan_free = echo_can_free,
 
103
        .echocan_process = echo_can_process,
 
104
        .echocan_traintap = echo_can_traintap,
 
105
        .echocan_NLP_toggle = echocan_NLP_toggle,
 
106
};
 
107
 
 
108
struct ec_pvt {
 
109
        struct dahdi_echocan_state dahdi;
 
110
        int tx_power;
 
111
        int rx_power;
 
112
        int clean_rx_power;
 
113
 
 
114
        int rx_power_threshold;
 
115
        int nonupdate_dwell;
 
116
 
 
117
        int16_t *tx_history;    /* Last N tx samples */
 
118
        int32_t *fir_taps;              /* Echo FIR taps */
 
119
        int16_t *fir_taps_short;        /* Echo FIR taps, shorts instead of ints */
 
120
 
 
121
        int curr_pos;
 
122
 
 
123
        int taps;
 
124
        int tap_mask;
 
125
        int use_nlp;
 
126
        int use_suppressor;
 
127
 
 
128
        int32_t supp_test1;
 
129
        int32_t supp_test2;
 
130
        int32_t supp1;
 
131
        int32_t supp2;
 
132
 
 
133
        int32_t latest_correction;  /* Indication of the magnitude of the latest
 
134
                                       adaption, or a code to indicate why adaption
 
135
                                       was skipped, for test purposes */
 
136
};
 
137
 
 
138
#define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi)
 
139
 
 
140
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
 
141
                           struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec)
115
142
{
 
143
        struct ec_pvt *pvt;
116
144
        size_t size;
117
 
        
 
145
 
118
146
        if (ecp->param_count > 0) {
119
 
                printk(KERN_WARNING "SEC echo canceler does not support parameters; failing request\n");
 
147
                printk(KERN_WARNING "SEC does not support parameters; failing request\n");
120
148
                return -EINVAL;
121
149
        }
122
 
        
123
 
        size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t);
124
 
        
125
 
        if (!(*ec = kmalloc(size, GFP_KERNEL)))
 
150
 
 
151
        size = sizeof(*pvt) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t);
 
152
        
 
153
        pvt = kzalloc(size, GFP_KERNEL);
 
154
        if (!pvt)
126
155
                return -ENOMEM;
127
 
        
128
 
        memset(*ec, 0, size);
129
 
 
130
 
        (*ec)->taps = ecp->tap_length;
131
 
        (*ec)->tap_mask = ecp->tap_length - 1;
132
 
        (*ec)->tx_history = (int16_t *) (*ec + sizeof(**ec));
133
 
        (*ec)->fir_taps = (int32_t *) (*ec + sizeof(**ec) +
134
 
                                       ecp->tap_length * 2 * sizeof(int16_t));
135
 
        (*ec)->fir_taps_short = (int16_t *) (*ec + sizeof(**ec) +
136
 
                                             ecp->tap_length * sizeof(int32_t) +
137
 
                                             ecp->tap_length * 2 * sizeof(int16_t));
138
 
        (*ec)->rx_power_threshold = 10000000;
139
 
        (*ec)->use_suppressor = FALSE;
 
156
 
 
157
        pvt->dahdi.ops = &my_ops;
 
158
        pvt->dahdi.features = my_features;
 
159
 
 
160
        pvt->taps = ecp->tap_length;
 
161
        pvt->tap_mask = ecp->tap_length - 1;
 
162
        pvt->tx_history = (int16_t *) (pvt + sizeof(*pvt));
 
163
        pvt->fir_taps = (int32_t *) (pvt + sizeof(*pvt) +
 
164
                                     ecp->tap_length * 2 * sizeof(int16_t));
 
165
        pvt->fir_taps_short = (int16_t *) (pvt + sizeof(*pvt) +
 
166
                                           ecp->tap_length * sizeof(int32_t) +
 
167
                                           ecp->tap_length * 2 * sizeof(int16_t));
 
168
        pvt->rx_power_threshold = 10000000;
 
169
        pvt->use_suppressor = FALSE;
140
170
        /* Non-linear processor - a fancy way to say "zap small signals, to avoid
141
171
           accumulating noise". */
142
 
        (*ec)->use_nlp = TRUE;
 
172
        pvt->use_nlp = TRUE;
143
173
 
 
174
        *ec = &pvt->dahdi;
144
175
        return 0;
145
176
}
146
 
/*- End of function --------------------------------------------------------*/
147
177
 
148
 
static void echo_can_free(struct echo_can_state *ec)
 
178
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec)
149
179
{
150
 
        kfree(ec);
 
180
        struct ec_pvt *pvt = dahdi_to_pvt(ec);
 
181
 
 
182
        kfree(pvt);
151
183
}
152
 
/*- End of function --------------------------------------------------------*/
153
184
 
154
 
static inline int16_t sample_update(struct echo_can_state *ec, int16_t tx, int16_t rx)
 
185
static inline int16_t sample_update(struct ec_pvt *pvt, int16_t tx, int16_t rx)
155
186
{
156
 
    int32_t echo_value;
157
 
    int clean_rx;
158
 
    int nsuppr;
159
 
 
160
 
    ec->tx_history[ec->curr_pos] = tx;
161
 
    ec->tx_history[ec->curr_pos + ec->taps] = tx;
162
 
 
163
 
    /* Evaluate the echo - i.e. apply the FIR filter */
164
 
    /* Assume the gain of the FIR does not exceed unity. Exceeding unity
165
 
       would seem like a rather poor thing for an echo cancellor to do :)
166
 
       This means we can compute the result with a total disregard for
167
 
       overflows. 16bits x 16bits -> 31bits, so no overflow can occur in
168
 
       any multiply. While accumulating we may overflow and underflow the
169
 
       32 bit scale often. However, if the gain does not exceed unity,
170
 
       everything should work itself out, and the final result will be
171
 
       OK, without any saturation logic. */
172
 
    /* Overflow is very much possible here, and we do nothing about it because
173
 
       of the compute costs */
174
 
    /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound
175
 
       bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems
176
 
       best */
 
187
        int32_t echo_value;
 
188
        int clean_rx;
 
189
        int nsuppr;
 
190
 
 
191
        pvt->tx_history[pvt->curr_pos] = tx;
 
192
        pvt->tx_history[pvt->curr_pos + pvt->taps] = tx;
 
193
 
 
194
        /* Evaluate the echo - i.e. apply the FIR filter */
 
195
        /* Assume the gain of the FIR does not exceed unity. Exceeding unity
 
196
           would seem like a rather poor thing for an echo cancellor to do :)
 
197
           This means we can compute the result with a total disregard for
 
198
           overflows. 16bits x 16bits -> 31bits, so no overflow can occur in
 
199
           any multiply. While accumulating we may overflow and underflow the
 
200
           32 bit scale often. However, if the gain does not exceed unity,
 
201
           everything should work itself out, and the final result will be
 
202
           OK, without any saturation logic. */
 
203
        /* Overflow is very much possible here, and we do nothing about it because
 
204
           of the compute costs */
 
205
        /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound
 
206
           bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems
 
207
           best */
177
208
#ifdef USE_SHORTS
178
 
    echo_value = CONVOLVE2(ec->fir_taps_short, ec->tx_history + ec->curr_pos, ec->taps);
 
209
        echo_value = CONVOLVE2(pvt->fir_taps_short, pvt->tx_history + pvt->curr_pos, pvt->taps);
179
210
#else
180
 
    echo_value = CONVOLVE(ec->fir_taps, ec->tx_history + ec->curr_pos, ec->taps);
 
211
        echo_value = CONVOLVE(pvt->fir_taps, pvt->tx_history + pvt->curr_pos, pvt->taps);
181
212
#endif
182
 
    echo_value >>= 16;
183
 
 
184
 
    /* And the answer is..... */
185
 
    clean_rx = rx - echo_value;
186
 
 
187
 
    /* That was the easy part. Now we need to adapt! */
188
 
    if (ec->nonupdate_dwell > 0)
189
 
        ec->nonupdate_dwell--;
190
 
 
191
 
    /* If there is very little being transmitted, any attempt to train is
192
 
       futile. We would either be training on the far end's noise or signal,
193
 
       the channel's own noise, or our noise. Either way, this is hardly good
194
 
       training, so don't do it (avoid trouble). */
195
 
    /* If the received power is very low, either we are sending very little or
196
 
       we are already well adapted. There is little point in trying to improve
197
 
       the adaption under these circumstanceson, so don't do it (reduce the
198
 
       compute load). */
199
 
    if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION
200
 
        &&
201
 
        ec->rx_power > MIN_RX_POWER_FOR_ADAPTION)
202
 
    {
203
 
        /* This is a really crude piece of decision logic, but it does OK
204
 
           for now. */
205
 
        if (ec->tx_power > ec->rx_power << 1)
206
 
        {
207
 
            /* There is no far-end speech detected */
208
 
            if (ec->nonupdate_dwell == 0)
209
 
            {
210
 
                /* ... and we are not in the dwell time from previous speech. */
211
 
                //nsuppr = saturate((clean_rx << 16)/ec->tx_power);
212
 
                nsuppr = (clean_rx << 16) / ec->tx_power;
213
 
                nsuppr >>= 4;
214
 
                if (nsuppr > 512)
215
 
                        nsuppr = 512;
216
 
                if (nsuppr < -512)
217
 
                        nsuppr = -512;
218
 
 
219
 
                /* Update the FIR taps */
220
 
                ec->latest_correction = 0;
 
213
        echo_value >>= 16;
 
214
 
 
215
        /* And the answer is..... */
 
216
        clean_rx = rx - echo_value;
 
217
 
 
218
        /* That was the easy part. Now we need to adapt! */
 
219
        if (pvt->nonupdate_dwell > 0)
 
220
                pvt->nonupdate_dwell--;
 
221
 
 
222
        /* If there is very little being transmitted, any attempt to train is
 
223
           futile. We would either be training on the far end's noise or signal,
 
224
           the channel's own noise, or our noise. Either way, this is hardly good
 
225
           training, so don't do it (avoid trouble). */
 
226
        /* If the received power is very low, either we are sending very little or
 
227
           we are already well adapted. There is little point in trying to improve
 
228
           the adaption under these circumstanceson, so don't do it (reduce the
 
229
           compute load). */
 
230
        if (pvt->tx_power > MIN_TX_POWER_FOR_ADAPTION && pvt->rx_power > MIN_RX_POWER_FOR_ADAPTION) {
 
231
                /* This is a really crude piece of decision logic, but it does OK
 
232
                   for now. */
 
233
                if (pvt->tx_power > pvt->rx_power << 1) {
 
234
                        /* There is no far-end speech detected */
 
235
                        if (pvt->nonupdate_dwell == 0) {
 
236
                                /* ... and we are not in the dwell time from previous speech. */
 
237
                                /* nsuppr = saturate((clean_rx << 16)/pvt->tx_power); */
 
238
                                nsuppr = (clean_rx << 16) / pvt->tx_power;
 
239
                                nsuppr >>= 4;
 
240
                                if (nsuppr > 512)
 
241
                                        nsuppr = 512;
 
242
                                if (nsuppr < -512)
 
243
                                        nsuppr = -512;
 
244
 
 
245
                                /* Update the FIR taps */
 
246
                                pvt->latest_correction = 0;
221
247
#ifdef USE_SHORTS
222
 
                UPDATE2(ec->fir_taps, ec->fir_taps_short, ec->tx_history + ec->curr_pos, nsuppr, ec->taps);
 
248
                                UPDATE2(pvt->fir_taps, pvt->fir_taps_short, pvt->tx_history + pvt->curr_pos, nsuppr, pvt->taps);
223
249
#else                           
224
 
                UPDATE(ec->fir_taps, ec->fir_taps_short, ec->tx_history + ec->curr_pos, nsuppr, ec->taps);
 
250
                                UPDATE(pvt->fir_taps, pvt->fir_taps_short, pvt->tx_history + pvt->curr_pos, nsuppr, pvt->taps);
225
251
#endif          
226
 
           }  else
227
 
            {
228
 
                ec->latest_correction = -3;
229
 
            }
230
 
        }
231
 
        else
232
 
        {
233
 
            ec->nonupdate_dwell = NONUPDATE_DWELL_TIME;
234
 
            ec->latest_correction = -2;
235
 
        }
236
 
    }
237
 
    else
238
 
    {
239
 
        ec->nonupdate_dwell = 0;
240
 
        ec->latest_correction = -1;
241
 
    }
242
 
    /* Calculate short term power levels using very simple single pole IIRs */
243
 
    /* TODO: Is the nasty modulus approach the fastest, or would a real
244
 
       tx*tx power calculation actually be faster? */
245
 
    ec->tx_power += ((abs(tx) - ec->tx_power) >> 5);
246
 
    ec->rx_power += ((abs(rx) - ec->rx_power) >> 5);
247
 
    ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5);
 
252
                        } else {
 
253
                                pvt->latest_correction = -3;
 
254
                        }
 
255
                } else {
 
256
                        pvt->nonupdate_dwell = NONUPDATE_DWELL_TIME;
 
257
                        pvt->latest_correction = -2;
 
258
                }
 
259
        } else {
 
260
                pvt->nonupdate_dwell = 0;
 
261
                pvt->latest_correction = -1;
 
262
        }
 
263
        /* Calculate short term power levels using very simple single pole IIRs */
 
264
        /* TODO: Is the nasty modulus approach the fastest, or would a real
 
265
           tx*tx power calculation actually be faster? */
 
266
        pvt->tx_power += ((abs(tx) - pvt->tx_power) >> 5);
 
267
        pvt->rx_power += ((abs(rx) - pvt->rx_power) >> 5);
 
268
        pvt->clean_rx_power += ((abs(clean_rx) - pvt->clean_rx_power) >> 5);
248
269
 
249
270
#if defined(XYZZY)
250
 
    if (ec->use_suppressor)
251
 
    {
252
 
        ec->supp_test1 += (ec->tx_history[ec->curr_pos] - ec->tx_history[(ec->curr_pos - 7) & ec->tap_mask]);
253
 
        ec->supp_test2 += (ec->tx_history[(ec->curr_pos - 24) & ec->tap_mask] - ec->tx_history[(ec->curr_pos - 31) & ec->tap_mask]);
254
 
        if (ec->supp_test1 > 42  &&  ec->supp_test2 > 42)
255
 
            supp_change = 25;
256
 
        else
257
 
            supp_change = 50;
258
 
        supp = supp_change + k1*ec->supp1 + k2*ec->supp2;
259
 
        ec->supp2 = ec->supp1;
260
 
        ec->supp1 = supp;
261
 
        clean_rx *= (1 - supp);
262
 
    }
 
271
        if (pvt->use_suppressor) {
 
272
                pvt->supp_test1 += (pvt->tx_history[pvt->curr_pos] - pvt->tx_history[(pvt->curr_pos - 7) & pvt->tap_mask]);
 
273
                pvt->supp_test2 += (pvt->tx_history[(pvt->curr_pos - 24) & pvt->tap_mask] - pvt->tx_history[(pvt->curr_pos - 31) & pvt->tap_mask]);
 
274
                if (pvt->supp_test1 > 42  &&  pvt->supp_test2 > 42)
 
275
                        supp_change = 25;
 
276
                else
 
277
                        supp_change = 50;
 
278
                supp = supp_change + k1*pvt->supp1 + k2*pvt->supp2;
 
279
                pvt->supp2 = pvt->supp1;
 
280
                pvt->supp1 = supp;
 
281
                clean_rx *= (1 - supp);
 
282
        }
263
283
#endif
264
284
 
265
 
    if (ec->use_nlp  &&  ec->rx_power < 32)
266
 
        clean_rx = 0;
267
 
 
268
 
    /* Roll around the rolling buffer */
269
 
    ec->curr_pos = (ec->curr_pos - 1) & ec->tap_mask;
270
 
 
271
 
    return clean_rx;
 
285
        if (pvt->use_nlp && pvt->rx_power < 32)
 
286
                clean_rx = 0;
 
287
 
 
288
        /* Roll around the rolling buffer */
 
289
        pvt->curr_pos = (pvt->curr_pos - 1) & pvt->tap_mask;
 
290
 
 
291
        return clean_rx;
272
292
}
273
 
/*- End of function --------------------------------------------------------*/
274
293
 
275
 
static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig)
 
294
static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size)
276
295
{
277
 
        unsigned int x;
 
296
        struct ec_pvt *pvt = dahdi_to_pvt(ec);
 
297
        u32 x;
278
298
        short result;
279
299
 
280
 
        for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
281
 
                result = sample_update(ec, *iref, *isig);
 
300
        for (x = 0; x < size; x++) {
 
301
                result = sample_update(pvt, *iref, *isig);
282
302
                *isig++ = result;
283
303
                ++iref;
284
304
        }
285
305
}
286
 
/*- End of function --------------------------------------------------------*/
287
306
 
288
 
static int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
 
307
static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val)
289
308
{
 
309
        struct ec_pvt *pvt = dahdi_to_pvt(ec);
 
310
 
290
311
        /* Reset hang counter to avoid adjustments after
291
312
           initial forced training */
292
 
        ec->nonupdate_dwell = ec->taps << 1;
293
 
        if (pos >= ec->taps)
294
 
                return 1;
295
 
        ec->fir_taps[pos] = val << 17;
296
 
        ec->fir_taps_short[pos] = val << 1;
297
 
        if (++pos >= ec->taps)
298
 
                return 1;
299
 
        return 0;
300
 
}
301
 
/*- End of function --------------------------------------------------------*/
302
 
 
303
 
static const struct dahdi_echocan me = {
304
 
        .name = "SEC",
305
 
        .owner = THIS_MODULE,
306
 
        .echo_can_create = echo_can_create,
307
 
        .echo_can_free = echo_can_free,
308
 
        .echo_can_array_update = echo_can_update,
309
 
        .echo_can_traintap = echo_can_traintap,
310
 
};
 
313
        pvt->nonupdate_dwell = pvt->taps << 1;
 
314
        if (pos >= pvt->taps)
 
315
                return 1;
 
316
        pvt->fir_taps[pos] = val << 17;
 
317
        pvt->fir_taps_short[pos] = val << 1;
 
318
        if (++pos >= pvt->taps)
 
319
                return 1;
 
320
        else
 
321
                return 0;
 
322
}
 
323
 
 
324
static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable)
 
325
{
 
326
        struct ec_pvt *pvt = dahdi_to_pvt(ec);
 
327
 
 
328
        pvt->use_nlp = enable ? 1 : 0;
 
329
}
311
330
 
312
331
static int __init mod_init(void)
313
332
{
314
 
        if (dahdi_register_echocan(&me)) {
 
333
        if (dahdi_register_echocan_factory(&my_factory)) {
315
334
                module_printk(KERN_ERR, "could not register with DAHDI core\n");
316
335
 
317
336
                return -EPERM;
318
337
        }
319
338
 
320
 
        module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name);
 
339
        module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name);
321
340
 
322
341
        return 0;
323
342
}
324
343
 
325
344
static void __exit mod_exit(void)
326
345
{
327
 
        dahdi_unregister_echocan(&me);
 
346
        dahdi_unregister_echocan_factory(&my_factory);
328
347
}
329
348
 
330
349
module_param(debug, int, S_IRUGO | S_IWUSR);