codec_resample.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2007, Digium, Inc.
  5. *
  6. * Russell Bryant <russell@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*!
  19. * \file
  20. *
  21. * \brief Resample slinear audio
  22. *
  23. * \note To install libresample, check it out of the following repository:
  24. * <code>$ svn co http://svn.digium.com/svn/thirdparty/libresample/trunk</code>
  25. *
  26. * \ingroup codecs
  27. */
  28. /*** MODULEINFO
  29. <depend>resample</depend>
  30. <support_level>core</support_level>
  31. ***/
  32. #include "asterisk.h"
  33. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  34. /* These are for SHRT_MAX and FLT_MAX -- { */
  35. #if defined(__Darwin__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__CYGWIN__)
  36. #include <float.h>
  37. #else
  38. #include <values.h>
  39. #endif
  40. #include <limits.h>
  41. /* } */
  42. #include <libresample.h>
  43. #include "asterisk/module.h"
  44. #include "asterisk/translate.h"
  45. #include "asterisk/slin.h"
  46. #define RESAMPLER_QUALITY 1
  47. #define OUTBUF_SIZE 8096
  48. struct slin16_to_slin8_pvt {
  49. void *resampler;
  50. float resample_factor;
  51. };
  52. struct slin8_to_slin16_pvt {
  53. void *resampler;
  54. float resample_factor;
  55. };
  56. static int slin16_to_slin8_new(struct ast_trans_pvt *pvt)
  57. {
  58. struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
  59. resamp_pvt->resample_factor = 8000.0 / 16000.0;
  60. if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, resamp_pvt->resample_factor, resamp_pvt->resample_factor)))
  61. return -1;
  62. return 0;
  63. }
  64. static int slin8_to_slin16_new(struct ast_trans_pvt *pvt)
  65. {
  66. struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
  67. resamp_pvt->resample_factor = 16000.0 / 8000.0;
  68. if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, resamp_pvt->resample_factor, resamp_pvt->resample_factor)))
  69. return -1;
  70. return 0;
  71. }
  72. static void slin16_to_slin8_destroy(struct ast_trans_pvt *pvt)
  73. {
  74. struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
  75. if (resamp_pvt->resampler)
  76. resample_close(resamp_pvt->resampler);
  77. }
  78. static void slin8_to_slin16_destroy(struct ast_trans_pvt *pvt)
  79. {
  80. struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
  81. if (resamp_pvt->resampler)
  82. resample_close(resamp_pvt->resampler);
  83. }
  84. static int resample_frame(struct ast_trans_pvt *pvt,
  85. void *resampler, float resample_factor, struct ast_frame *f)
  86. {
  87. int total_in_buf_used = 0;
  88. int total_out_buf_used = 0;
  89. int16_t *in_buf = (int16_t *) f->data.ptr;
  90. int16_t *out_buf = pvt->outbuf.i16 + pvt->samples;
  91. float in_buf_f[f->samples];
  92. float out_buf_f[2048];
  93. int res = 0;
  94. int i;
  95. for (i = 0; i < f->samples; i++)
  96. in_buf_f[i] = in_buf[i] * (FLT_MAX / SHRT_MAX);
  97. while (total_in_buf_used < f->samples) {
  98. int in_buf_used, out_buf_used;
  99. out_buf_used = resample_process(resampler, resample_factor,
  100. &in_buf_f[total_in_buf_used], f->samples - total_in_buf_used,
  101. 0, &in_buf_used,
  102. &out_buf_f[total_out_buf_used], ARRAY_LEN(out_buf_f) - total_out_buf_used);
  103. if (out_buf_used < 0)
  104. break;
  105. total_out_buf_used += out_buf_used;
  106. total_in_buf_used += in_buf_used;
  107. if (total_out_buf_used == ARRAY_LEN(out_buf_f)) {
  108. ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
  109. res = -1;
  110. break;
  111. }
  112. }
  113. for (i = 0; i < total_out_buf_used; i++)
  114. out_buf[i] = out_buf_f[i] * (SHRT_MAX / FLT_MAX);
  115. pvt->samples += total_out_buf_used;
  116. pvt->datalen += (total_out_buf_used * sizeof(int16_t));
  117. return res;
  118. }
  119. static int slin16_to_slin8_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
  120. {
  121. struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
  122. void *resampler = resamp_pvt->resampler;
  123. float resample_factor = resamp_pvt->resample_factor;
  124. return resample_frame(pvt, resampler, resample_factor, f);
  125. }
  126. static int slin8_to_slin16_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
  127. {
  128. struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
  129. void *resampler = resamp_pvt->resampler;
  130. float resample_factor = resamp_pvt->resample_factor;
  131. return resample_frame(pvt, resampler, resample_factor, f);
  132. }
  133. static struct ast_translator slin16_to_slin8 = {
  134. .name = "slin16_to_slin8",
  135. .srcfmt = AST_FORMAT_SLINEAR16,
  136. .dstfmt = AST_FORMAT_SLINEAR,
  137. .newpvt = slin16_to_slin8_new,
  138. .destroy = slin16_to_slin8_destroy,
  139. .framein = slin16_to_slin8_framein,
  140. .sample = slin16_sample,
  141. .desc_size = sizeof(struct slin16_to_slin8_pvt),
  142. .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
  143. .buf_size = OUTBUF_SIZE,
  144. };
  145. static struct ast_translator slin8_to_slin16 = {
  146. .name = "slin8_to_slin16",
  147. .srcfmt = AST_FORMAT_SLINEAR,
  148. .dstfmt = AST_FORMAT_SLINEAR16,
  149. .newpvt = slin8_to_slin16_new,
  150. .destroy = slin8_to_slin16_destroy,
  151. .framein = slin8_to_slin16_framein,
  152. .sample = slin8_sample,
  153. .desc_size = sizeof(struct slin8_to_slin16_pvt),
  154. .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
  155. .buf_size = OUTBUF_SIZE,
  156. };
  157. static int unload_module(void)
  158. {
  159. int res = 0;
  160. res |= ast_unregister_translator(&slin16_to_slin8);
  161. res |= ast_unregister_translator(&slin8_to_slin16);
  162. return res;
  163. }
  164. static int load_module(void)
  165. {
  166. int res = 0;
  167. res |= ast_register_translator(&slin16_to_slin8);
  168. res |= ast_register_translator(&slin8_to_slin16);
  169. return AST_MODULE_LOAD_SUCCESS;
  170. }
  171. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec");