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.

231 lines
5.8KB

  1. /*
  2. ** Copyright (c) 2005-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 "config.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <unistd.h>
  12. #include <string.h>
  13. #include <math.h>
  14. #if (HAVE_SNDFILE)
  15. #include <samplerate.h>
  16. #include <sndfile.h>
  17. #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
  18. #define DEFAULT_CONVERTER SRC_SINC_MEDIUM_QUALITY
  19. #define BUFFER_LEN 1024
  20. #define INPUT_STEP_SIZE 8
  21. typedef struct
  22. { sf_count_t index ;
  23. double ratio ;
  24. } TIMEWARP_FACTOR ;
  25. static void usage_exit (const char *progname) ;
  26. static sf_count_t timewarp_convert (SNDFILE *infile, SNDFILE *outfile, int converter, int channels) ;
  27. int
  28. main (int argc, char *argv [])
  29. { SNDFILE *infile, *outfile ;
  30. SF_INFO sfinfo ;
  31. sf_count_t count ;
  32. if (argc != 3)
  33. usage_exit (argv [0]) ;
  34. putchar ('\n') ;
  35. printf ("Input File : %s\n", argv [argc - 2]) ;
  36. if ((infile = sf_open (argv [argc - 2], SFM_READ, &sfinfo)) == NULL)
  37. { printf ("Error : Not able to open input file '%s'\n", argv [argc - 2]) ;
  38. exit (1) ;
  39. } ;
  40. if (INPUT_STEP_SIZE * sfinfo.channels > BUFFER_LEN)
  41. { printf ("\n\nError : INPUT_STEP_SIZE * sfinfo.channels > BUFFER_LEN\n\n") ;
  42. exit (1) ;
  43. } ;
  44. /* Delete the output file length to zero if already exists. */
  45. remove (argv [argc - 1]) ;
  46. if ((outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL)
  47. { printf ("Error : Not able to open output file '%s'\n", argv [argc - 1]) ;
  48. sf_close (infile) ;
  49. exit (1) ;
  50. } ;
  51. sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
  52. printf ("Output file : %s\n", argv [argc - 1]) ;
  53. printf ("Converter : %s\n", src_get_name (DEFAULT_CONVERTER)) ;
  54. count = timewarp_convert (infile, outfile, DEFAULT_CONVERTER, sfinfo.channels) ;
  55. printf ("Output Frames : %ld\n\n", (long) count) ;
  56. sf_close (infile) ;
  57. sf_close (outfile) ;
  58. return 0 ;
  59. } /* main */
  60. /*==============================================================================
  61. */
  62. static TIMEWARP_FACTOR warp [] =
  63. { { 0 , 1.00000001 },
  64. { 20000 , 1.01000000 },
  65. { 20200 , 1.00000001 },
  66. { 40000 , 1.20000000 },
  67. { 40300 , 1.00000001 },
  68. { 60000 , 1.10000000 },
  69. { 60400 , 1.00000001 },
  70. { 80000 , 1.50000000 },
  71. { 81000 , 1.00000001 },
  72. } ;
  73. static sf_count_t
  74. timewarp_convert (SNDFILE *infile, SNDFILE *outfile, int converter, int channels)
  75. { static float input [BUFFER_LEN] ;
  76. static float output [BUFFER_LEN] ;
  77. SRC_STATE *src_state ;
  78. SRC_DATA src_data ;
  79. int error, warp_index = 0 ;
  80. sf_count_t input_count = 0, output_count = 0 ;
  81. sf_seek (infile, 0, SEEK_SET) ;
  82. sf_seek (outfile, 0, SEEK_SET) ;
  83. /* Initialize the sample rate converter. */
  84. if ((src_state = src_new (converter, channels, &error)) == NULL)
  85. { printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ;
  86. exit (1) ;
  87. } ;
  88. src_data.end_of_input = 0 ; /* Set this later. */
  89. /* Start with zero to force load in while loop. */
  90. src_data.input_frames = 0 ;
  91. src_data.data_in = input ;
  92. if (warp [0].index > 0)
  93. src_data.src_ratio = 1.0 ;
  94. else
  95. { src_data.src_ratio = warp [0].ratio ;
  96. warp_index ++ ;
  97. } ;
  98. src_data.data_out = output ;
  99. src_data.output_frames = BUFFER_LEN /channels ;
  100. while (1)
  101. {
  102. if (warp_index < ARRAY_LEN (warp) - 1 && input_count >= warp [warp_index].index)
  103. { src_data.src_ratio = warp [warp_index].ratio ;
  104. warp_index ++ ;
  105. } ;
  106. /* If the input buffer is empty, refill it. */
  107. if (src_data.input_frames == 0)
  108. { src_data.input_frames = sf_readf_float (infile, input, INPUT_STEP_SIZE) ;
  109. input_count += src_data.input_frames ;
  110. src_data.data_in = input ;
  111. /* The last read will not be a full buffer, so snd_of_input. */
  112. if (src_data.input_frames < INPUT_STEP_SIZE)
  113. src_data.end_of_input = SF_TRUE ;
  114. } ;
  115. /* Process current block. */
  116. if ((error = src_process (src_state, &src_data)))
  117. { printf ("\nError : %s\n", src_strerror (error)) ;
  118. exit (1) ;
  119. } ;
  120. /* Terminate if done. */
  121. if (src_data.end_of_input && src_data.output_frames_gen == 0)
  122. break ;
  123. /* Write output. */
  124. sf_writef_float (outfile, output, src_data.output_frames_gen) ;
  125. output_count += src_data.output_frames_gen ;
  126. src_data.data_in += src_data.input_frames_used * channels ;
  127. src_data.input_frames -= src_data.input_frames_used ;
  128. } ;
  129. src_delete (src_state) ;
  130. return output_count ;
  131. } /* timewarp_convert */
  132. /*------------------------------------------------------------------------------
  133. */
  134. static void
  135. usage_exit (const char *progname)
  136. { const char *cptr ;
  137. if ((cptr = strrchr (progname, '/')) != NULL)
  138. progname = cptr + 1 ;
  139. if ((cptr = strrchr (progname, '\\')) != NULL)
  140. progname = cptr + 1 ;
  141. printf ("\n"
  142. " A program demonstrating the time warping capabilities of libsamplerate."
  143. " It uses libsndfile for file I/O and Secret Rabbit Code (aka libsamplerate)"
  144. " for performing the warping.\n"
  145. " It works on any file format supported by libsndfile with any \n"
  146. " number of channels (limited only by host memory).\n"
  147. "\n"
  148. " The warping is dependant on a table hard code into the source code.\n"
  149. "\n"
  150. " libsamplerate version : %s\n"
  151. "\n"
  152. " Usage : \n"
  153. " %s <input file> <output file>\n"
  154. "\n", src_get_version (), progname) ;
  155. puts ("") ;
  156. exit (1) ;
  157. } /* usage_exit */
  158. /*==============================================================================
  159. */
  160. #else /* (HAVE_SNFILE == 0) */
  161. /* Alternative main function when libsndfile is not available. */
  162. int
  163. main (void)
  164. { puts (
  165. "\n"
  166. "****************************************************************\n"
  167. " This example program was compiled without libsndfile \n"
  168. " (http://www.mega-nerd.com/libsndfile/).\n"
  169. " It is therefore completely broken and non-functional.\n"
  170. "****************************************************************\n"
  171. "\n"
  172. ) ;
  173. return 0 ;
  174. } /* main */
  175. #endif