You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
5.6KB

  1. /*
  2. ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
  3. ** All rights reserved.
  4. **
  5. ** This code is released under 2-clause BSD license. Please see the
  6. ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "config.h"
  12. #include "float_cast.h"
  13. #include "common.h"
  14. static int linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
  15. static void linear_reset (SRC_PRIVATE *psrc) ;
  16. /*========================================================================================
  17. */
  18. #define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r')
  19. #define SRC_DEBUG 0
  20. typedef struct
  21. { int linear_magic_marker ;
  22. int channels ;
  23. int reset ;
  24. long in_count, in_used ;
  25. long out_count, out_gen ;
  26. float last_value [1] ;
  27. } LINEAR_DATA ;
  28. /*----------------------------------------------------------------------------------------
  29. */
  30. static int
  31. linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
  32. { LINEAR_DATA *priv ;
  33. double src_ratio, input_index, rem ;
  34. int ch ;
  35. if (data->input_frames <= 0)
  36. return SRC_ERR_NO_ERROR ;
  37. if (psrc->private_data == NULL)
  38. return SRC_ERR_NO_PRIVATE ;
  39. priv = (LINEAR_DATA*) psrc->private_data ;
  40. if (priv->reset)
  41. { /* If we have just been reset, set the last_value data. */
  42. for (ch = 0 ; ch < priv->channels ; ch++)
  43. priv->last_value [ch] = data->data_in [ch] ;
  44. priv->reset = 0 ;
  45. } ;
  46. priv->in_count = data->input_frames * priv->channels ;
  47. priv->out_count = data->output_frames * priv->channels ;
  48. priv->in_used = priv->out_gen = 0 ;
  49. src_ratio = psrc->last_ratio ;
  50. if (is_bad_src_ratio (src_ratio))
  51. return SRC_ERR_BAD_INTERNAL_STATE ;
  52. input_index = psrc->last_position ;
  53. /* Calculate samples before first sample in input array. */
  54. while (input_index < 1.0 && priv->out_gen < priv->out_count)
  55. {
  56. if (priv->in_used + priv->channels * (1.0 + input_index) >= priv->in_count)
  57. break ;
  58. if (priv->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
  59. src_ratio = psrc->last_ratio + priv->out_gen * (data->src_ratio - psrc->last_ratio) / priv->out_count ;
  60. for (ch = 0 ; ch < priv->channels ; ch++)
  61. { data->data_out [priv->out_gen] = (float) (priv->last_value [ch] + input_index *
  62. (data->data_in [ch] - priv->last_value [ch])) ;
  63. priv->out_gen ++ ;
  64. } ;
  65. /* Figure out the next index. */
  66. input_index += 1.0 / src_ratio ;
  67. } ;
  68. rem = fmod_one (input_index) ;
  69. priv->in_used += priv->channels * lrint (input_index - rem) ;
  70. input_index = rem ;
  71. /* Main processing loop. */
  72. while (priv->out_gen < priv->out_count && priv->in_used + priv->channels * input_index < priv->in_count)
  73. {
  74. if (priv->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
  75. src_ratio = psrc->last_ratio + priv->out_gen * (data->src_ratio - psrc->last_ratio) / priv->out_count ;
  76. if (SRC_DEBUG && priv->in_used < priv->channels && input_index < 1.0)
  77. { printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", priv->in_used, priv->channels, input_index) ;
  78. exit (1) ;
  79. } ;
  80. for (ch = 0 ; ch < priv->channels ; ch++)
  81. { data->data_out [priv->out_gen] = (float) (data->data_in [priv->in_used - priv->channels + ch] + input_index *
  82. (data->data_in [priv->in_used + ch] - data->data_in [priv->in_used - priv->channels + ch])) ;
  83. priv->out_gen ++ ;
  84. } ;
  85. /* Figure out the next index. */
  86. input_index += 1.0 / src_ratio ;
  87. rem = fmod_one (input_index) ;
  88. priv->in_used += priv->channels * lrint (input_index - rem) ;
  89. input_index = rem ;
  90. } ;
  91. if (priv->in_used > priv->in_count)
  92. { input_index += (priv->in_used - priv->in_count) / priv->channels ;
  93. priv->in_used = priv->in_count ;
  94. } ;
  95. psrc->last_position = input_index ;
  96. if (priv->in_used > 0)
  97. for (ch = 0 ; ch < priv->channels ; ch++)
  98. priv->last_value [ch] = data->data_in [priv->in_used - priv->channels + ch] ;
  99. /* Save current ratio rather then target ratio. */
  100. psrc->last_ratio = src_ratio ;
  101. data->input_frames_used = priv->in_used / priv->channels ;
  102. data->output_frames_gen = priv->out_gen / priv->channels ;
  103. return SRC_ERR_NO_ERROR ;
  104. } /* linear_vari_process */
  105. /*------------------------------------------------------------------------------
  106. */
  107. const char*
  108. linear_get_name (int src_enum)
  109. {
  110. if (src_enum == SRC_LINEAR)
  111. return "Linear Interpolator" ;
  112. return NULL ;
  113. } /* linear_get_name */
  114. const char*
  115. linear_get_description (int src_enum)
  116. {
  117. if (src_enum == SRC_LINEAR)
  118. return "Linear interpolator, very fast, poor quality." ;
  119. return NULL ;
  120. } /* linear_get_descrition */
  121. int
  122. linear_set_converter (SRC_PRIVATE *psrc, int src_enum)
  123. { LINEAR_DATA *priv = NULL ;
  124. if (src_enum != SRC_LINEAR)
  125. return SRC_ERR_BAD_CONVERTER ;
  126. if (psrc->private_data != NULL)
  127. { free (psrc->private_data) ;
  128. psrc->private_data = NULL ;
  129. } ;
  130. if (psrc->private_data == NULL)
  131. { priv = calloc (1, sizeof (*priv) + psrc->channels * sizeof (float)) ;
  132. psrc->private_data = priv ;
  133. } ;
  134. if (priv == NULL)
  135. return SRC_ERR_MALLOC_FAILED ;
  136. priv->linear_magic_marker = LINEAR_MAGIC_MARKER ;
  137. priv->channels = psrc->channels ;
  138. psrc->const_process = linear_vari_process ;
  139. psrc->vari_process = linear_vari_process ;
  140. psrc->reset = linear_reset ;
  141. linear_reset (psrc) ;
  142. return SRC_ERR_NO_ERROR ;
  143. } /* linear_set_converter */
  144. /*===================================================================================
  145. */
  146. static void
  147. linear_reset (SRC_PRIVATE *psrc)
  148. { LINEAR_DATA *priv = NULL ;
  149. priv = (LINEAR_DATA*) psrc->private_data ;
  150. if (priv == NULL)
  151. return ;
  152. priv->channels = psrc->channels ;
  153. priv->reset = 1 ;
  154. memset (priv->last_value, 0, sizeof (priv->last_value [0]) * priv->channels) ;
  155. return ;
  156. } /* linear_reset */