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.

222 lines
5.5KB

  1. /* sndplay plays sounds */
  2. #include "mus-config.h"
  3. #include <math.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include "_sndlib.h"
  7. #ifndef _MSC_VER
  8. #include <unistd.h>
  9. #endif
  10. #include <string.h>
  11. #if __APPLE__
  12. #define BUFFER_SIZE 256
  13. #else
  14. #ifdef _MSC_VER
  15. /* this setting from Scott Middleton (actually used 8096) */
  16. #define BUFFER_SIZE 8192
  17. #else
  18. #define BUFFER_SIZE 4096
  19. #endif
  20. #endif
  21. #if __APPLE__
  22. #define OutSample float
  23. #define MUS_CONVERT(samp) (float)(samp)
  24. #else
  25. #define OutSample short
  26. #define MUS_SAMPLE_TO_SHORT(n) ((short)((n) * (1 << 15)))
  27. #define MUS_CONVERT(samp) MUS_SAMPLE_TO_SHORT(samp)
  28. #endif
  29. /* 22-Nov-00: moved alsa support to separate block */
  30. /* 8-Apr-04: added start/end (seconds-based) args */
  31. /* 2-Nov-05: added -volume arg (removed later) */
  32. /* 22-July-08: added -mutable arg */
  33. /* 1-May-12: removed alsa special case */
  34. int main(int argc, char *argv[])
  35. {
  36. int fd, afd, i, j, n, k, chans, srate;
  37. mus_long_t framples, m;
  38. mus_float_t **bufs;
  39. OutSample *obuf;
  40. int buffer_size = BUFFER_SIZE, curframples, sample_size, out_chans, outbytes;
  41. char *name = NULL;
  42. mus_long_t start = 0, end = 0;
  43. double begin_time = 0.0, end_time = 0.0;
  44. int mutate = 1, include_mutate = 0;
  45. if (argc == 1)
  46. {
  47. printf("usage: sndplay file [-start 1.0] [-end 1.0] [-bufsize %d] [-buffers 2x12] [-describe]\n", BUFFER_SIZE);
  48. exit(0);
  49. }
  50. mus_sound_initialize();
  51. for (i = 1; i < argc; i++)
  52. {
  53. if (strcmp(argv[i], "-buffers") == 0)
  54. {
  55. #if (HAVE_OSS || HAVE_ALSA)
  56. static char x_string[2] = {'x','\0'};
  57. char *arg;
  58. int a, b;
  59. arg = strtok(argv[i + 1], x_string);
  60. a = atoi(arg);
  61. arg = strtok(NULL, x_string);
  62. b = atoi(arg);
  63. mus_oss_set_buffers(a, b);
  64. #endif
  65. i++;
  66. }
  67. else
  68. {
  69. if (strcmp(argv[i], "-bufsize") == 0)
  70. {
  71. buffer_size = atoi(argv[i + 1]);
  72. i++;
  73. }
  74. else
  75. {
  76. if (strcmp(argv[i], "-start") == 0)
  77. {
  78. begin_time = atof(argv[i + 1]);
  79. i++;
  80. }
  81. else
  82. {
  83. if (strcmp(argv[i], "-end") == 0)
  84. {
  85. end_time = atof(argv[i + 1]);
  86. i++;
  87. }
  88. else
  89. {
  90. if (strcmp(argv[i], "-mutable") == 0)
  91. {
  92. mutate = atoi(argv[i + 1]);
  93. include_mutate = 1;
  94. i++;
  95. }
  96. else name = argv[i];
  97. }}}}}
  98. if (name == NULL)
  99. {
  100. printf("usage: sndplay file [-start 1.0] [-end 1.0] [-bufsize %d] [-buffers 2x12] [-mutable 1]\n", BUFFER_SIZE);
  101. exit(0);
  102. }
  103. afd = -1;
  104. if (!(mus_is_header_type(mus_sound_header_type(name))))
  105. {
  106. fprintf(stderr, "can't play %s (header type: %s?)\n",
  107. name,
  108. mus_header_type_name(mus_header_type()));
  109. exit(0);
  110. }
  111. if (!(mus_is_sample_type(mus_sound_sample_type(name))))
  112. {
  113. fprintf(stderr, "can't play %s (sample type: %s (%s)?)\n",
  114. name,
  115. mus_sample_type_name(mus_sound_sample_type(name)),
  116. mus_header_original_sample_type_name(mus_sound_original_sample_type(name), mus_sound_header_type(name)));
  117. exit(0);
  118. }
  119. fd = mus_sound_open_input(name);
  120. if (fd != -1)
  121. {
  122. chans = mus_sound_chans(name);
  123. if (chans > 2)
  124. {
  125. int available_chans;
  126. available_chans = mus_audio_device_channels(MUS_AUDIO_DEFAULT);
  127. if (available_chans < chans)
  128. {
  129. fprintf(stderr, "%s has %d channels, but we can only handle %d\n", name, chans, available_chans);
  130. exit(1);
  131. }
  132. }
  133. out_chans = chans;
  134. srate = mus_sound_srate(name);
  135. framples = mus_sound_framples(name);
  136. sample_size = mus_bytes_per_sample(MUS_AUDIO_COMPATIBLE_SAMPLE_TYPE);
  137. start = (mus_long_t)(begin_time * srate);
  138. if (start > 0)
  139. mus_file_seek_frample(fd, start);
  140. if (end_time > 0.0)
  141. end = (mus_long_t)(end_time * srate);
  142. else end = framples;
  143. if ((end - start) < framples)
  144. framples = end - start;
  145. bufs = (mus_float_t **)calloc(chans, sizeof(mus_float_t *));
  146. for (i = 0; i < chans; i++) bufs[i] = (mus_float_t *)calloc(buffer_size, sizeof(mus_float_t));
  147. obuf = (OutSample *)calloc(buffer_size * out_chans, sizeof(OutSample));
  148. outbytes = buffer_size * out_chans * sample_size;
  149. for (m = 0; m < framples; m += buffer_size)
  150. {
  151. if ((m + buffer_size) <= framples)
  152. curframples = buffer_size;
  153. else curframples = framples - m;
  154. mus_file_read(fd, start + m, curframples, chans, bufs);
  155. /* some systems are happier if we read the file before opening the dac */
  156. /* at this point the data is in separate arrays of mus_sample_t's */
  157. if (chans == 1)
  158. {
  159. for (k = 0; k < curframples; k++)
  160. obuf[k] = MUS_CONVERT(bufs[0][k]);
  161. }
  162. else
  163. {
  164. if (chans == 2)
  165. {
  166. for (k = 0, n = 0; k < curframples; k++, n += 2)
  167. {
  168. obuf[n] = MUS_CONVERT(bufs[0][k]);
  169. obuf[n + 1] = MUS_CONVERT(bufs[1][k]);
  170. }
  171. }
  172. else
  173. {
  174. for (k = 0, j = 0; k < curframples; k++, j += chans)
  175. {
  176. for (n = 0; n < chans; n++)
  177. obuf[j + n] = MUS_CONVERT(bufs[n][k]);
  178. }
  179. }
  180. }
  181. #if __APPLE__
  182. if (include_mutate == 1)
  183. mus_audio_output_properties_mutable(mutate);
  184. #endif
  185. if (afd == -1)
  186. {
  187. afd = mus_audio_open_output(MUS_AUDIO_DEFAULT, srate, out_chans, MUS_AUDIO_COMPATIBLE_SAMPLE_TYPE, outbytes);
  188. if (afd == -1) break;
  189. }
  190. outbytes = curframples * out_chans * sample_size;
  191. mus_audio_write(afd, (char *)obuf, outbytes);
  192. }
  193. if (afd != -1) mus_audio_close(afd);
  194. mus_sound_close_input(fd);
  195. for (i = 0; i < chans; i++) free(bufs[i]);
  196. free(bufs);
  197. free(obuf);
  198. }
  199. return(0);
  200. }