utils.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:7k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* flac - Command-line FLAC encoder/decoder
  2.  * Copyright (C) 2002,2003,2004,2005  Josh Coalson
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. #if HAVE_CONFIG_H
  19. #  include <config.h>
  20. #endif
  21. #include "utils.h"
  22. #include "FLAC/assert.h"
  23. #include <math.h>
  24. #include <stdarg.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. int flac__utils_verbosity_ = 2;
  28. static FLAC__bool local__parse_uint64_(const char *s, FLAC__uint64 *value)
  29. {
  30. FLAC__uint64 ret = 0;
  31. char c;
  32. if(*s == '')
  33. return false;
  34. while('' != (c = *s++))
  35. if(c >= '0' && c <= '9')
  36. ret = ret * 10 + (c - '0');
  37. else
  38. return false;
  39. *value = ret;
  40. return true;
  41. }
  42. static FLAC__bool local__parse_timecode_(const char *s, double *value)
  43. {
  44. double ret;
  45. unsigned i;
  46. char c;
  47. /* parse [0-9][0-9]*: */
  48. c = *s++;
  49. if(c >= '0' && c <= '9')
  50. i = (c - '0');
  51. else
  52. return false;
  53. while(':' != (c = *s++)) {
  54. if(c >= '0' && c <= '9')
  55. i = i * 10 + (c - '0');
  56. else
  57. return false;
  58. }
  59. ret = (double)i * 60.;
  60. /* parse [0-9]*[.]?[0-9]* i.e. a sign-less rational number */
  61. if(strspn(s, "1234567890.") != strlen(s))
  62. return false;
  63. {
  64. const char *p = strchr(s, '.');
  65. if(p && 0 != strchr(++p, '.'))
  66. return false;
  67. }
  68. ret += atof(s);
  69. *value = ret;
  70. return true;
  71. }
  72. static FLAC__bool local__parse_cue_(const char *s, const char *end, unsigned *track, unsigned *index)
  73. {
  74. FLAC__bool got_track = false, got_index = false;
  75. unsigned t = 0, i = 0;
  76. char c;
  77. while(end? s < end : *s != '') {
  78. c = *s++;
  79. if(c >= '0' && c <= '9') {
  80. t = t * 10 + (c - '0');
  81. got_track = true;
  82. }
  83. else if(c == '.')
  84. break;
  85. else
  86. return false;
  87. }
  88. while(end? s < end : *s != '') {
  89. c = *s++;
  90. if(c >= '0' && c <= '9') {
  91. i = i * 10 + (c - '0');
  92. got_index = true;
  93. }
  94. else
  95. return false;
  96. }
  97. *track = t;
  98. *index = i;
  99. return got_track && got_index;
  100. }
  101. /*
  102.  * @@@ this only works with sorted cuesheets (the spec strongly recommends but
  103.  * does not require sorted cuesheets).  but if it's not sorted, picking a
  104.  * nearest cue point has no significance.
  105.  */
  106. static FLAC__uint64 local__find_closest_cue_(const FLAC__StreamMetadata_CueSheet *cuesheet, unsigned track, unsigned index, FLAC__uint64 total_samples, FLAC__bool look_forward)
  107. {
  108. int t, i;
  109. if(look_forward) {
  110. for(t = 0; t < (int)cuesheet->num_tracks; t++)
  111. for(i = 0; i < (int)cuesheet->tracks[t].num_indices; i++)
  112. if(cuesheet->tracks[t].number > track || (cuesheet->tracks[t].number == track && cuesheet->tracks[t].indices[i].number >= index))
  113. return cuesheet->tracks[t].offset + cuesheet->tracks[t].indices[i].offset;
  114. return total_samples;
  115. }
  116. else {
  117. for(t = (int)cuesheet->num_tracks - 1; t >= 0; t--)
  118. for(i = (int)cuesheet->tracks[t].num_indices - 1; i >= 0; i--)
  119. if(cuesheet->tracks[t].number < track || (cuesheet->tracks[t].number == track && cuesheet->tracks[t].indices[i].number <= index))
  120. return cuesheet->tracks[t].offset + cuesheet->tracks[t].indices[i].offset;
  121. return 0;
  122. }
  123. }
  124. void flac__utils_printf(FILE *stream, int level, const char *format, ...)
  125. {
  126. if(flac__utils_verbosity_ >= level) {
  127. va_list args;
  128. FLAC__ASSERT(0 != format);
  129. va_start(args, format);
  130. (void) vfprintf(stream, format, args);
  131. va_end(args);
  132. }
  133. }
  134. #ifdef FLAC__VALGRIND_TESTING
  135. size_t flac__utils_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
  136. {
  137. size_t ret = fwrite(ptr, size, nmemb, stream);
  138. if(!ferror(stream))
  139. fflush(stream);
  140. return ret;
  141. }
  142. #endif
  143. FLAC__bool flac__utils_parse_skip_until_specification(const char *s, utils__SkipUntilSpecification *spec)
  144. {
  145. FLAC__uint64 val;
  146. FLAC__bool is_negative = false;
  147. FLAC__ASSERT(0 != spec);
  148. spec->is_relative = false;
  149. spec->value_is_samples = true;
  150. spec->value.samples = 0;
  151. if(0 != s) {
  152. if(s[0] == '-') {
  153. is_negative = true;
  154. spec->is_relative = true;
  155. s++;
  156. }
  157. else if(s[0] == '+') {
  158. spec->is_relative = true;
  159. s++;
  160. }
  161. if(local__parse_uint64_(s, &val)) {
  162. spec->value_is_samples = true;
  163. spec->value.samples = (FLAC__int64)val;
  164. if(is_negative)
  165. spec->value.samples = -(spec->value.samples);
  166. }
  167. else {
  168. double d;
  169. if(!local__parse_timecode_(s, &d))
  170. return false;
  171. spec->value_is_samples = false;
  172. spec->value.seconds = d;
  173. if(is_negative)
  174. spec->value.seconds = -(spec->value.seconds);
  175. }
  176. }
  177. return true;
  178. }
  179. void flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, unsigned sample_rate)
  180. {
  181. FLAC__ASSERT(0 != spec);
  182. if(!spec->value_is_samples) {
  183. spec->value.samples = (FLAC__int64)(spec->value.seconds * (double)sample_rate);
  184. spec->value_is_samples = true;
  185. }
  186. }
  187. FLAC__bool flac__utils_parse_cue_specification(const char *s, utils__CueSpecification *spec)
  188. {
  189. const char *start = s, *end = 0;
  190. FLAC__ASSERT(0 != spec);
  191. spec->has_start_point = spec->has_end_point = false;
  192. s = strchr(s, '-');
  193. if(0 != s) {
  194. if(s == start)
  195. start = 0;
  196. end = s+1;
  197. if(*end == '')
  198. end = 0;
  199. }
  200. if(start) {
  201. if(!local__parse_cue_(start, s, &spec->start_track, &spec->start_index))
  202. return false;
  203. spec->has_start_point = true;
  204. }
  205. if(end) {
  206. if(!local__parse_cue_(end, 0, &spec->end_track, &spec->end_index))
  207. return false;
  208. spec->has_end_point = true;
  209. }
  210. return true;
  211. }
  212. void flac__utils_canonicalize_cue_specification(const utils__CueSpecification *cue_spec, const FLAC__StreamMetadata_CueSheet *cuesheet, FLAC__uint64 total_samples, utils__SkipUntilSpecification *skip_spec, utils__SkipUntilSpecification *until_spec)
  213. {
  214. FLAC__ASSERT(0 != cue_spec);
  215. FLAC__ASSERT(0 != cuesheet);
  216. FLAC__ASSERT(0 != total_samples);
  217. FLAC__ASSERT(0 != skip_spec);
  218. FLAC__ASSERT(0 != until_spec);
  219. skip_spec->is_relative = false;
  220. skip_spec->value_is_samples = true;
  221. until_spec->is_relative = false;
  222. until_spec->value_is_samples = true;
  223. if(cue_spec->has_start_point)
  224. skip_spec->value.samples = local__find_closest_cue_(cuesheet, cue_spec->start_track, cue_spec->start_index, total_samples, /*look_forward=*/false);
  225. else
  226. skip_spec->value.samples = 0;
  227. if(cue_spec->has_end_point)
  228. until_spec->value.samples = local__find_closest_cue_(cuesheet, cue_spec->end_track, cue_spec->end_index, total_samples, /*look_forward=*/true);
  229. else
  230. until_spec->value.samples = total_samples;
  231. }