| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Based on frompcm.c and topcm.c from the Emiliano MIPL browser/ | 
					
						
							|  |  |  |  * interpreter.  See http://www.bsdtelephony.com.mx
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-01-21 07:06:25 +00:00
										 |  |  |  * Copyright (c) 2001 - 2005 Digium, Inc. | 
					
						
							| 
									
										
										
										
											2004-12-19 21:13:41 +00:00
										 |  |  |  * All rights reserved. | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2004-12-19 21:13:41 +00:00
										 |  |  |  * Karl Sackett <krs@linux-support.net>, 2001-03-21 | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  * \brief codec_adpcm.c - translate between signed linear and Dialogic ADPCM | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  *  | 
					
						
							| 
									
										
										
										
											2005-11-06 15:09:47 +00:00
										 |  |  |  * \ingroup codecs | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-14 20:13:06 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<support_level>core</support_level> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							| 
									
										
										
										
											2006-04-14 14:08:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/lock.h"
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | #include "asterisk/linkedlists.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | #include "asterisk/config.h"
 | 
					
						
							|  |  |  | #include "asterisk/translate.h"
 | 
					
						
							| 
									
										
										
										
											2006-01-21 08:45:39 +00:00
										 |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | /* define NOT_BLI to use a faster but not bit-level identical version */ | 
					
						
							|  |  |  | /* #define NOT_BLI */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | #define BUFFER_SAMPLES   8096	/* size for the translation buffers */
 | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | /* Sample frame data */ | 
					
						
							| 
									
										
										
										
											2008-10-17 21:35:23 +00:00
										 |  |  | #include "asterisk/slin.h"
 | 
					
						
							|  |  |  | #include "ex_adpcm.h"
 | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Step size index shift table  | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Step size table, where stpsz[i]=floor[16*(11/10)^i] | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | static int stpsz[49] = { | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  |   16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, | 
					
						
							|  |  |  |   80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, | 
					
						
							|  |  |  |   307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, | 
					
						
							|  |  |  |   1060, 1166, 1282, 1411, 1552 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Decoder/Encoder state | 
					
						
							|  |  |  |  *   States for both encoder and decoder are synchronized | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | struct adpcm_state { | 
					
						
							|  |  |  | 	int ssindex; | 
					
						
							|  |  |  | 	int signal; | 
					
						
							|  |  |  | 	int zero_count; | 
					
						
							|  |  |  | 	int next_flag; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Decode(encoded) | 
					
						
							|  |  |  |  *  Decodes the encoded nibble from the adpcm file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Results: | 
					
						
							|  |  |  |  *  Returns the encoded difference. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Side effects: | 
					
						
							|  |  |  |  *  Sets the index to the step size table for the next encode. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | static inline short decode(int encoded, struct adpcm_state *state) | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	int diff; | 
					
						
							|  |  |  | 	int step; | 
					
						
							|  |  |  | 	int sign; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	step = stpsz[state->ssindex]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sign = encoded & 0x08; | 
					
						
							|  |  |  | 	encoded &= 0x07; | 
					
						
							|  |  |  | #ifdef NOT_BLI
 | 
					
						
							|  |  |  | 	diff = (((encoded << 1) + 1) * step) >> 3; | 
					
						
							|  |  |  | #else /* BLI code */
 | 
					
						
							|  |  |  | 	diff = step >> 3; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	if (encoded & 4) | 
					
						
							|  |  |  | 		diff += step; | 
					
						
							|  |  |  | 	if (encoded & 2) | 
					
						
							|  |  |  | 		diff += step >> 1; | 
					
						
							|  |  |  | 	if (encoded & 1) | 
					
						
							|  |  |  | 		diff += step >> 2; | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	if ((encoded >> 1) & step & 0x1) | 
					
						
							|  |  |  | 		diff++; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if (sign) | 
					
						
							|  |  |  | 		diff = -diff; | 
					
						
							| 
									
										
										
										
											2003-10-02 23:17:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	if (state->next_flag & 0x1) | 
					
						
							|  |  |  | 		state->signal -= 8; | 
					
						
							|  |  |  | 	else if (state->next_flag & 0x2) | 
					
						
							|  |  |  | 		state->signal += 8; | 
					
						
							| 
									
										
										
										
											2003-10-02 23:17:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	state->signal += diff; | 
					
						
							| 
									
										
										
										
											2003-10-02 23:17:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	if (state->signal > 2047) | 
					
						
							|  |  |  | 		state->signal = 2047; | 
					
						
							|  |  |  | 	else if (state->signal < -2047) | 
					
						
							|  |  |  | 		state->signal = -2047; | 
					
						
							| 
									
										
										
										
											2003-10-02 23:17:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	state->next_flag = 0; | 
					
						
							| 
									
										
										
										
											2004-03-11 20:56:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef AUTO_RETURN
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	if (encoded) | 
					
						
							|  |  |  | 		state->zero_count = 0; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	else if (++(state->zero_count) == 24) { | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 		state->zero_count = 0; | 
					
						
							|  |  |  | 		if (state->signal > 0) | 
					
						
							|  |  |  | 			state->next_flag = 0x1; | 
					
						
							|  |  |  | 		else if (state->signal < 0) | 
					
						
							|  |  |  | 			state->next_flag = 0x2; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-03-11 20:56:26 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-10-02 23:17:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	state->ssindex += indsft[encoded]; | 
					
						
							|  |  |  | 	if (state->ssindex < 0) | 
					
						
							|  |  |  | 		state->ssindex = 0; | 
					
						
							|  |  |  | 	else if (state->ssindex > 48) | 
					
						
							|  |  |  | 		state->ssindex = 48; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return state->signal << 4; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Adpcm | 
					
						
							|  |  |  |  *  Takes a signed linear signal and encodes it as ADPCM | 
					
						
							|  |  |  |  *  For more information see http://support.dialogic.com/appnotes/adpcm.pdf
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Results: | 
					
						
							|  |  |  |  *  Foo. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Side effects: | 
					
						
							|  |  |  |  *  signal gets updated with each pass. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | static inline int adpcm(short csig, struct adpcm_state *state) | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	int diff; | 
					
						
							|  |  |  | 	int step; | 
					
						
							|  |  |  | 	int encoded; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* 
 | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	 * Clip csig if too large or too small | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 	csig >>= 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	step = stpsz[state->ssindex]; | 
					
						
							|  |  |  | 	diff = csig - state->signal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef NOT_BLI
 | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	if (diff < 0) { | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 		encoded = (-diff << 2) / step; | 
					
						
							|  |  |  | 		if (encoded > 7) | 
					
						
							|  |  |  | 			encoded = 7; | 
					
						
							|  |  |  | 		encoded |= 0x08; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 		encoded = (diff << 2) / step; | 
					
						
							|  |  |  | 		if (encoded > 7) | 
					
						
							|  |  |  | 			encoded = 7; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else /* BLI code */
 | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	if (diff < 0) { | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 		encoded = 8; | 
					
						
							|  |  |  | 		diff = -diff; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 		encoded = 0; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	if (diff >= step) { | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 		encoded |= 4; | 
					
						
							|  |  |  | 		diff -= step; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	step >>= 1; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	if (diff >= step) { | 
					
						
							| 
									
										
										
										
											2004-11-15 00:56:53 +00:00
										 |  |  | 		encoded |= 2; | 
					
						
							|  |  |  | 		diff -= step; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	step >>= 1; | 
					
						
							|  |  |  | 	if (diff >= step) | 
					
						
							|  |  |  | 		encoded |= 1; | 
					
						
							|  |  |  | #endif /* NOT_BLI */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* feedback to state */ | 
					
						
							|  |  |  | 	decode(encoded, state); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return encoded; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*----------------- Asterisk-codec glue ------------*/ | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief Workspace for translating signed linear signals to ADPCM. */ | 
					
						
							|  |  |  | struct adpcm_encoder_pvt { | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	struct adpcm_state state; | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	int16_t inbuf[BUFFER_SAMPLES];	/* Unencoded signed linear values */ | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief Workspace for translating ADPCM signals to signed linear. */ | 
					
						
							|  |  |  | struct adpcm_decoder_pvt { | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	struct adpcm_state state; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief decode 4-bit adpcm frame data and store in output buffer */ | 
					
						
							|  |  |  | static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	struct adpcm_decoder_pvt *tmp = pvt->pvt; | 
					
						
							| 
									
										
										
										
											2006-05-20 13:37:11 +00:00
										 |  |  | 	int x = f->datalen; | 
					
						
							| 
									
										
										
										
											2008-05-22 16:29:54 +00:00
										 |  |  | 	unsigned char *src = f->data.ptr; | 
					
						
							| 
									
										
										
										
											2008-06-26 17:06:17 +00:00
										 |  |  | 	int16_t *dst = pvt->outbuf.i16 + pvt->samples; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-20 13:37:11 +00:00
										 |  |  | 	while (x--) { | 
					
						
							|  |  |  | 		*dst++ = decode((*src >> 4) & 0xf, &tmp->state); | 
					
						
							|  |  |  | 		*dst++ = decode(*src++ & 0x0f, &tmp->state); | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	pvt->samples += f->samples; | 
					
						
							|  |  |  | 	pvt->datalen += 2*f->samples; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief fill input buffer with 16-bit signed linear PCM values. */ | 
					
						
							|  |  |  | static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	struct adpcm_encoder_pvt *tmp = pvt->pvt; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-22 16:29:54 +00:00
										 |  |  | 	memcpy(&tmp->inbuf[pvt->samples], f->data.ptr, f->datalen); | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	pvt->samples += f->samples; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief convert inbuf and store into frame */ | 
					
						
							|  |  |  | static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt) | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	struct adpcm_encoder_pvt *tmp = pvt->pvt; | 
					
						
							|  |  |  | 	struct ast_frame *f; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	int samples = pvt->samples;	/* save original number */ | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	if (samples < 2) | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	pvt->samples &= ~1; /* atomic size is 2 samples */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < pvt->samples; i += 2) { | 
					
						
							| 
									
										
										
										
											2008-06-26 17:06:17 +00:00
										 |  |  | 		pvt->outbuf.c[i/2] = | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 			(adpcm(tmp->inbuf[i  ], &tmp->state) << 4) | | 
					
						
							|  |  |  | 			(adpcm(tmp->inbuf[i+1], &tmp->state)     ); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	f = ast_trans_frameout(pvt, pvt->samples/2, 0); | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	 * If there is a left over sample, move it to the beginning | 
					
						
							|  |  |  | 	 * of the input buffer. | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	if (samples & 1) {	/* move the leftover sample at beginning */ | 
					
						
							|  |  |  | 		tmp->inbuf[0] = tmp->inbuf[samples - 1]; | 
					
						
							|  |  |  | 		pvt->samples = 1; | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	return f; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_translator adpcmtolin = { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	.name = "adpcmtolin", | 
					
						
							|  |  |  | 	.srcfmt = AST_FORMAT_ADPCM, | 
					
						
							|  |  |  | 	.dstfmt = AST_FORMAT_SLINEAR, | 
					
						
							|  |  |  | 	.framein = adpcmtolin_framein, | 
					
						
							| 
									
										
										
										
											2008-10-17 21:35:23 +00:00
										 |  |  | 	.sample = adpcm_sample, | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	.desc_size = sizeof(struct adpcm_decoder_pvt), | 
					
						
							|  |  |  | 	.buffer_samples = BUFFER_SAMPLES, | 
					
						
							|  |  |  | 	.buf_size = BUFFER_SAMPLES * 2, | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_translator lintoadpcm = { | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	.name = "lintoadpcm", | 
					
						
							|  |  |  | 	.srcfmt = AST_FORMAT_SLINEAR, | 
					
						
							|  |  |  | 	.dstfmt = AST_FORMAT_ADPCM, | 
					
						
							|  |  |  | 	.framein = lintoadpcm_framein, | 
					
						
							|  |  |  | 	.frameout = lintoadpcm_frameout, | 
					
						
							| 
									
										
										
										
											2008-10-17 21:35:23 +00:00
										 |  |  | 	.sample = slin8_sample, | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	.desc_size = sizeof (struct adpcm_encoder_pvt), | 
					
						
							|  |  |  | 	.buffer_samples = BUFFER_SAMPLES, | 
					
						
							|  |  |  | 	.buf_size = BUFFER_SAMPLES/ 2,	/* 2 samples per byte */ | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | /*! \brief standard module glue */ | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int reload(void) | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-31 19:24:29 +00:00
										 |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2005-03-17 21:30:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	res = ast_unregister_translator(&lintoadpcm); | 
					
						
							| 
									
										
										
										
											2006-04-08 21:40:57 +00:00
										 |  |  | 	res |= ast_unregister_translator(&adpcmtolin); | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	res = ast_register_translator(&adpcmtolin); | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	if (!res) | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 		res = ast_register_translator(&lintoadpcm); | 
					
						
							| 
									
										
										
										
											2006-01-20 23:23:00 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		ast_unregister_translator(&adpcmtolin); | 
					
						
							| 
									
										
										
										
											2007-10-31 19:24:29 +00:00
										 |  |  | 	if (res) | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_FAILURE; | 
					
						
							|  |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2001-03-22 22:25:06 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-04-14 14:08:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder", | 
					
						
							|  |  |  | 		.load = load_module, | 
					
						
							|  |  |  | 		.unload = unload_module, | 
					
						
							|  |  |  | 		.reload = reload, | 
					
						
							|  |  |  | 	       ); |