1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 /* Copyright (C) Jean-Marc Valin */ /** @file speex_echo.h @brief Echo cancellation */ /* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SPEEX_ECHO_H #define SPEEX_ECHO_H /** @defgroup SpeexEchoState SpeexEchoState: Acoustic echo canceller * This is the acoustic echo canceller module. * @{ */ #include "speex_types.h" #ifdef __cplusplus extern "C" { #endif /** Obtain frame size used by the AEC */ #define SPEEX_ECHO_GET_FRAME_SIZE 3 /** Set sampling rate */ #define SPEEX_ECHO_SET_SAMPLING_RATE 24 /** Get sampling rate */ #define SPEEX_ECHO_GET_SAMPLING_RATE 25 /** Internal echo canceller state. Should never be accessed directly. */ struct SpeexEchoState_; /** @class SpeexEchoState * This holds the state of the echo canceller. You need one per channel. */ /** Internal echo canceller state. Should never be accessed directly. */ typedef struct SpeexEchoState_ SpeexEchoState; /** Creates a new echo canceller state * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) * @return Newly-created echo canceller state */ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length); /** Destroys an echo canceller state * @param st Echo canceller state */ void speex_echo_state_destroy(SpeexEchoState *st); /** Performs echo cancellation a frame, based on the audio sent to the speaker (no delay is added * to playback in this form) * * @param st Echo canceller state * @param rec Signal from the microphone (near end + far end echo) * @param play Signal played to the speaker (received from far end) * @param out Returns near-end signal with echo removed */ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out); /** Performs echo cancellation a frame (deprecated) */ void speex_echo_cancel(SpeexEchoState *st, const/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * New greyscale framework * Scrolling routines * * This is a generic framework to display 129 shades of grey on low-depth * bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. * * Copyright (C) 2008 Jens Arnold * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "plugin.h" #include "grey.h" /*** Scrolling ***/ /* Scroll left */ void grey_scroll_left(int count) { unsigned char *data, *data_end; int length, blank; if ((unsigned)count >= (unsigned)_grey_info.width) return; data = _grey_info.buffer; data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); length = _grey_info.width - count; blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? _grey_info.fg_brightness : _grey_info.bg_brightness; do { _grey_info.rb->memmove(data, data + count, length); data += length; _grey_info.rb->memset(data, blank, count); data += count; } while (data < data_end); } /* Scroll right */ void grey_scroll_right(int count) { unsigned char *data, *data_end; int length, blank; if ((unsigned)count >= (unsigned)_grey_info.width) return; data = _grey_info.buffer; data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); length = _grey_info.width - count; blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? _grey_info.fg_brightness : _grey_info.bg_brightness; do { _grey_info.rb->memmove(data + count, data, length); _grey_info.rb->memset(data, blank, count); data += _grey_info.width; } while (data < data_end); } /* Scroll up */ void grey_scroll_up(int count) { long shift, length; int blank; if ((unsigned)count >= (unsigned)_grey_info.height) return; shift = _GREY_MULUQ(_grey_info.width, count); length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count); blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? _grey_info.fg_brightness : _grey_info.bg_brightness; _grey_info.rb->memmove(_grey_info.buffer, _grey_info.buffer + shift, length); _grey_info.rb->memset(_grey_info.buffer + length, blank, shift); } /* Scroll down */ void grey_scroll_down(int count) { long shift, length; int blank; if ((unsigned)count >= (unsigned)_grey_info.height) return; shift = _GREY_MULUQ(_grey_info.width, count); length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count); blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? _grey_info.fg_brightness : _grey_info.bg_brightness; _grey_info.rb->memmove(_grey_info.buffer + shift, _grey_info.buffer, length); _grey_info.rb->memset(_grey_info.buffer, blank, shift); } /*** Unbuffered scrolling functions ***/ /* Scroll left */ void grey_ub_scroll_left(int count) { unsigned char *data, *data_end; int blank, length; if ((unsigned)count >= (unsigned)_grey_info.width) return; data = _grey_info.values; data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); length = (_grey_info.width - count) << _GREY_BSHIFT; count <<= _GREY_BSHIFT; blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? _grey_info.fg_brightness : _grey_info.bg_brightness]; do { _grey_info.rb->memmove(data, data + count, length); data += length; _grey_info.rb->memset(data, blank, count); data += count; } while (data < data_end); #ifdef SIMULATOR _grey_info.rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y, _grey_info.width, _grey_info.height); #endif } /* Scroll right */ void grey_ub_scroll_right(int count) { unsigned char *data, *data_end; int blank, length; if ((unsigned)count >= (unsigned)_grey_info.width) return; data = _grey_info.values; data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); length = (_grey_info.width - count) << _GREY_BSHIFT; count <<= _GREY_BSHIFT; blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? _grey_info.fg_brightness : _grey_info.bg_brightness]; do { _grey_info.rb->memmove(data + count, data, length); _grey_info.rb->memset(data, blank, count); data += _grey_info.width << _GREY_BSHIFT; } while (data < data_end); #ifdef SIMULATOR _grey_info.rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y, _grey_info.width, _grey_info.height); #endif } /* Scroll up */ void grey_ub_scroll_up(int count) { unsigned char *dst, *end, *src; int blank; if ((unsigned)count >= (unsigned)_grey_info.height) return; dst = _grey_info.values; end = dst + _GREY_MULUQ(_grey_info.height, _grey_info.width); blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? _grey_info.fg_brightness : _grey_info.bg_brightness]; #if (LCD_PIXELFORMAT == VERTICAL_PACKING) \ || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) if (count & _GREY_BMASK) { /* Scrolling by fractional blocks - move pixel wise. */ unsigned char *line_end; int ys, yd; for (ys = count, yd = 0; ys < _grey_info.height; ys++, yd++) { dst = _grey_info.values + _GREY_MULUQ(_grey_info.width, yd & ~_GREY_BMASK) + (~yd & _GREY_BMASK); src = _grey_info.values + _GREY_MULUQ(_grey_info.width, ys & ~_GREY_BMASK) + (~ys & _GREY_BMASK); line_end = dst + _grey_info.width * _GREY_BSIZE; do { *dst = *src; dst += _GREY_BSIZE; src += _GREY_BSIZE; } while (dst < line_end); } for (; yd & _GREY_BMASK; yd++) /* Fill remainder of current block. */ { dst = _grey_info.values + _GREY_MULUQ(_grey_info.width, yd & ~_GREY_BMASK) + (~yd & _GREY_BMASK); line_end = dst + _grey_info.width * _GREY_BSIZE; do { *dst = blank; dst += _GREY_BSIZE; } while (dst < line_end); } } else #endif { int blen = _GREY_MULUQ(_grey_info.height - count, _grey_info.width); src = dst + _GREY_MULUQ(count, _grey_info.width); _grey_info.rb->memmove(dst, src, blen); dst += blen; } _grey_info.rb->memset(dst, blank, end - dst); /* Fill remainder at once. */ #ifdef SIMULATOR _grey_info.rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y, _grey_info.width, _grey_info.height); #endif } /* Scroll down */ void grey_ub_scroll_down(int count) { unsigned char *start, *dst; int blank; if ((unsigned)count >= (unsigned)_grey_info.height) return; start = _grey_info.values; dst = start + _GREY_MULUQ(_grey_info.height, _grey_info.width); blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? _grey_info.fg_brightness : _grey_info.bg_brightness]; #if (LCD_PIXELFORMAT == VERTICAL_PACKING) \ || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) if (count & _GREY_BMASK) { /* Scrolling by fractional blocks - move pixel wise. */ unsigned char *src, *line_end; int ys, yd; yd = _grey_info.height - 1; for (ys = yd - count; ys >= 0; ys--, yd--) { dst = _grey_info.values + _GREY_MULUQ(_grey_info.width, yd & ~_GREY_BMASK) + (~yd & _GREY_BMASK); src = _grey_info.values + _GREY_MULUQ(_grey_info.width, ys & ~_GREY_BMASK) + (~ys & _GREY_BMASK); line_end = dst + _grey_info.width * _GREY_BSIZE; do { *dst = *src; dst += _GREY_BSIZE; src += _GREY_BSIZE; } while (dst < line_end); } for (; ~yd & _GREY_BMASK; yd--) /* Fill remainder of current block. */ { dst = _grey_info.values + _GREY_MULUQ(_grey_info.width, yd & ~_GREY_BMASK) + (~yd & _GREY_BMASK); line_end = dst + _grey_info.width * _GREY_BSIZE; do { line_end -= _GREY_BSIZE; *line_end = blank; } while (dst < line_end); } /* Top pixel in a block has the highest address, but dst must point * to the lowest address in that block for the subsequent fill. */ dst -= _GREY_BMASK; } else #endif { int blen = _GREY_MULUQ(_grey_info.height - count, _grey_info.width); dst -= blen; _grey_info.rb->memmove(dst, start, blen); } _grey_info.rb->memset(start, blank, dst - start); /* Fill remainder at once. */ #ifdef SIMULATOR _grey_info.rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y, _grey_info.width, _grey_info.height); #endif }