codec_resample.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2011, Digium, Inc.
  5. *
  6. * Russell Bryant <russell@digium.com>
  7. * David Vossel <dvossel@digium.com>
  8. *
  9. * See http://www.asterisk.org for more information about
  10. * the Asterisk project. Please do not directly contact
  11. * any of the maintainers of this project for assistance;
  12. * the project provides a web site, mailing lists and IRC
  13. * channels for your use.
  14. *
  15. * This program is free software, distributed under the terms of
  16. * the GNU General Public License Version 2. See the LICENSE file
  17. * at the top of the source tree.
  18. */
  19. /*!
  20. * \file
  21. *
  22. * \brief Resample slinear audio
  23. *
  24. * \ingroup codecs
  25. */
  26. /*** MODULEINFO
  27. <support_level>core</support_level>
  28. ***/
  29. #include "asterisk.h"
  30. #include "speex/speex_resampler.h"
  31. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  32. #include "asterisk/module.h"
  33. #include "asterisk/translate.h"
  34. #include "asterisk/slin.h"
  35. #define OUTBUF_SAMPLES 11520
  36. static struct ast_translator *translators;
  37. static int trans_size;
  38. static struct ast_codec codec_list[] = {
  39. {
  40. .name = "slin",
  41. .type = AST_MEDIA_TYPE_AUDIO,
  42. .sample_rate = 8000,
  43. },
  44. {
  45. .name = "slin",
  46. .type = AST_MEDIA_TYPE_AUDIO,
  47. .sample_rate = 12000,
  48. },
  49. {
  50. .name = "slin",
  51. .type = AST_MEDIA_TYPE_AUDIO,
  52. .sample_rate = 16000,
  53. },
  54. {
  55. .name = "slin",
  56. .type = AST_MEDIA_TYPE_AUDIO,
  57. .sample_rate = 24000,
  58. },
  59. {
  60. .name = "slin",
  61. .type = AST_MEDIA_TYPE_AUDIO,
  62. .sample_rate = 32000,
  63. },
  64. {
  65. .name = "slin",
  66. .type = AST_MEDIA_TYPE_AUDIO,
  67. .sample_rate = 44100,
  68. },
  69. {
  70. .name = "slin",
  71. .type = AST_MEDIA_TYPE_AUDIO,
  72. .sample_rate = 48000,
  73. },
  74. {
  75. .name = "slin",
  76. .type = AST_MEDIA_TYPE_AUDIO,
  77. .sample_rate = 96000,
  78. },
  79. {
  80. .name = "slin",
  81. .type = AST_MEDIA_TYPE_AUDIO,
  82. .sample_rate = 192000,
  83. },
  84. };
  85. static int resamp_new(struct ast_trans_pvt *pvt)
  86. {
  87. int err;
  88. if (!(pvt->pvt = speex_resampler_init(1, pvt->t->src_codec.sample_rate, pvt->t->dst_codec.sample_rate, 5, &err))) {
  89. return -1;
  90. }
  91. ast_assert(pvt->f.subclass.format == NULL);
  92. pvt->f.subclass.format = ao2_bump(ast_format_cache_get_slin_by_rate(pvt->t->dst_codec.sample_rate));
  93. return 0;
  94. }
  95. static void resamp_destroy(struct ast_trans_pvt *pvt)
  96. {
  97. SpeexResamplerState *resamp_pvt = pvt->pvt;
  98. speex_resampler_destroy(resamp_pvt);
  99. }
  100. static int resamp_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
  101. {
  102. SpeexResamplerState *resamp_pvt = pvt->pvt;
  103. unsigned int out_samples = OUTBUF_SAMPLES - pvt->samples;
  104. unsigned int in_samples;
  105. if (!f->datalen) {
  106. return -1;
  107. }
  108. in_samples = f->datalen / 2;
  109. speex_resampler_process_int(resamp_pvt,
  110. 0,
  111. f->data.ptr,
  112. &in_samples,
  113. pvt->outbuf.i16 + pvt->samples,
  114. &out_samples);
  115. pvt->samples += out_samples;
  116. pvt->datalen += out_samples * 2;
  117. return 0;
  118. }
  119. static int unload_module(void)
  120. {
  121. int res = 0;
  122. int idx;
  123. for (idx = 0; idx < trans_size; idx++) {
  124. res |= ast_unregister_translator(&translators[idx]);
  125. }
  126. ast_free(translators);
  127. return res;
  128. }
  129. static int load_module(void)
  130. {
  131. int res = 0;
  132. int x, y, idx = 0;
  133. trans_size = ARRAY_LEN(codec_list) * (ARRAY_LEN(codec_list) - 1);
  134. if (!(translators = ast_calloc(1, sizeof(struct ast_translator) * trans_size))) {
  135. return AST_MODULE_LOAD_DECLINE;
  136. }
  137. for (x = 0; x < ARRAY_LEN(codec_list); x++) {
  138. for (y = 0; y < ARRAY_LEN(codec_list); y++) {
  139. if (x == y) {
  140. continue;
  141. }
  142. translators[idx].newpvt = resamp_new;
  143. translators[idx].destroy = resamp_destroy;
  144. translators[idx].framein = resamp_framein;
  145. translators[idx].desc_size = 0;
  146. translators[idx].buffer_samples = OUTBUF_SAMPLES;
  147. translators[idx].buf_size = (OUTBUF_SAMPLES * sizeof(int16_t));
  148. memcpy(&translators[idx].src_codec, &codec_list[x], sizeof(struct ast_codec));
  149. memcpy(&translators[idx].dst_codec, &codec_list[y], sizeof(struct ast_codec));
  150. snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %ukhz -> %ukhz",
  151. translators[idx].src_codec.sample_rate, translators[idx].dst_codec.sample_rate);
  152. res |= ast_register_translator(&translators[idx]);
  153. idx++;
  154. }
  155. }
  156. /* in case ast_register_translator() failed, we call unload_module() and
  157. ast_unregister_translator won't fail.*/
  158. if (res) {
  159. unload_module();
  160. return AST_MODULE_LOAD_DECLINE;
  161. }
  162. return AST_MODULE_LOAD_SUCCESS;
  163. }
  164. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec");