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

Windows CE

开发平台:

C/C++

  1. /* flac - Command-line FLAC encoder/decoder
  2.  * Copyright (C) 2000,2001,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. #include <math.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "FLAC/all.h"
  23. #include "analyze.h"
  24. typedef struct {
  25. FLAC__int32 residual;
  26. unsigned count;
  27. } pair_t;
  28. typedef struct {
  29. pair_t buckets[FLAC__MAX_BLOCK_SIZE];
  30. int peak_index;
  31. unsigned nbuckets;
  32. unsigned nsamples;
  33. double sum, sos;
  34. double variance;
  35. double mean;
  36. double stddev;
  37. } subframe_stats_t;
  38. static subframe_stats_t all_;
  39. static void init_stats(subframe_stats_t *stats);
  40. static void update_stats(subframe_stats_t *stats, FLAC__int32 residual, unsigned incr);
  41. static void compute_stats(subframe_stats_t *stats);
  42. static FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename);
  43. void flac__analyze_init(analysis_options aopts)
  44. {
  45. if(aopts.do_residual_gnuplot) {
  46. init_stats(&all_);
  47. }
  48. }
  49. void flac__analyze_frame(const FLAC__Frame *frame, unsigned frame_number, analysis_options aopts, FILE *fout)
  50. {
  51. const unsigned channels = frame->header.channels;
  52. char outfilename[1024];
  53. subframe_stats_t stats;
  54. unsigned i, channel;
  55. /* do the human-readable part first */
  56. fprintf(fout, "frame=%utblocksize=%utsample_rate=%utchannels=%utchannel_assignment=%sn", frame_number, frame->header.blocksize, frame->header.sample_rate, channels, FLAC__ChannelAssignmentString[frame->header.channel_assignment]);
  57. for(channel = 0; channel < channels; channel++) {
  58. const FLAC__Subframe *subframe = frame->subframes+channel;
  59. fprintf(fout, "tsubframe=%utwasted_bits=%uttype=%s", channel, subframe->wasted_bits, FLAC__SubframeTypeString[subframe->type]);
  60. switch(subframe->type) {
  61. case FLAC__SUBFRAME_TYPE_CONSTANT:
  62. fprintf(fout, "tvalue=%dn", subframe->data.constant.value);
  63. break;
  64. case FLAC__SUBFRAME_TYPE_FIXED:
  65. FLAC__ASSERT(subframe->data.fixed.entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE);
  66. fprintf(fout, "torder=%utpartition_order=%un", subframe->data.fixed.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order);
  67. for(i = 0; i < subframe->data.fixed.order; i++)
  68. fprintf(fout, "ttwarmup[%u]=%dn", i, subframe->data.fixed.warmup[i]);
  69. if(aopts.do_residual_text) {
  70. const unsigned partitions = (1u << subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order);
  71. for(i = 0; i < partitions; i++) {
  72. unsigned parameter = subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->parameters[i];
  73. if(parameter == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
  74. fprintf(fout, "ttparameter[%u]=ESCAPE, raw_bits=%un", i, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]);
  75. else
  76. fprintf(fout, "ttparameter[%u]=%un", i, parameter);
  77. }
  78. for(i = 0; i < frame->header.blocksize-subframe->data.fixed.order; i++)
  79. fprintf(fout, "ttresidual[%u]=%dn", i, subframe->data.fixed.residual[i]);
  80. }
  81. break;
  82. case FLAC__SUBFRAME_TYPE_LPC:
  83. FLAC__ASSERT(subframe->data.lpc.entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE);
  84. fprintf(fout, "torder=%utpartition_order=%utqlp_coeff_precision=%utquantization_level=%dn", subframe->data.lpc.order, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order, subframe->data.lpc.qlp_coeff_precision, subframe->data.lpc.quantization_level);
  85. for(i = 0; i < subframe->data.lpc.order; i++)
  86. fprintf(fout, "ttwarmup[%u]=%dn", i, subframe->data.lpc.warmup[i]);
  87. if(aopts.do_residual_text) {
  88. const unsigned partitions = (1u << subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order);
  89. for(i = 0; i < partitions; i++) {
  90. unsigned parameter = subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->parameters[i];
  91. if(parameter == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
  92. fprintf(fout, "ttparameter[%u]=ESCAPE, raw_bits=%un", i, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]);
  93. else
  94. fprintf(fout, "ttparameter[%u]=%un", i, parameter);
  95. }
  96. for(i = 0; i < frame->header.blocksize-subframe->data.lpc.order; i++)
  97. fprintf(fout, "ttresidual[%u]=%dn", i, subframe->data.lpc.residual[i]);
  98. }
  99. break;
  100. case FLAC__SUBFRAME_TYPE_VERBATIM:
  101. fprintf(fout, "n");
  102. break;
  103. }
  104. }
  105. /* now do the residual distributions if requested */
  106. if(aopts.do_residual_gnuplot) {
  107. for(channel = 0; channel < channels; channel++) {
  108. const FLAC__Subframe *subframe = frame->subframes+channel;
  109. unsigned residual_samples;
  110. init_stats(&stats);
  111. switch(subframe->type) {
  112. case FLAC__SUBFRAME_TYPE_FIXED:
  113. residual_samples = frame->header.blocksize - subframe->data.fixed.order;
  114. for(i = 0; i < residual_samples; i++)
  115. update_stats(&stats, subframe->data.fixed.residual[i], 1);
  116. break;
  117. case FLAC__SUBFRAME_TYPE_LPC:
  118. residual_samples = frame->header.blocksize - subframe->data.lpc.order;
  119. for(i = 0; i < residual_samples; i++)
  120. update_stats(&stats, subframe->data.lpc.residual[i], 1);
  121. break;
  122. default:
  123. break;
  124. }
  125. /* update all_ */
  126. for(i = 0; i < stats.nbuckets; i++) {
  127. update_stats(&all_, stats.buckets[i].residual, stats.buckets[i].count);
  128. }
  129. /* write the subframe */
  130. sprintf(outfilename, "f%06u.s%u.gp", frame_number, channel);
  131. compute_stats(&stats);
  132. (void)dump_stats(&stats, outfilename);
  133. }
  134. }
  135. }
  136. void flac__analyze_finish(analysis_options aopts)
  137. {
  138. if(aopts.do_residual_gnuplot) {
  139. compute_stats(&all_);
  140. (void)dump_stats(&all_, "all");
  141. }
  142. }
  143. void init_stats(subframe_stats_t *stats)
  144. {
  145. stats->peak_index = -1;
  146. stats->nbuckets = 0;
  147. stats->nsamples = 0;
  148. stats->sum = 0.0;
  149. stats->sos = 0.0;
  150. }
  151. void update_stats(subframe_stats_t *stats, FLAC__int32 residual, unsigned incr)
  152. {
  153. unsigned i;
  154. const double r = (double)residual, a = r*incr;
  155. stats->nsamples += incr;
  156. stats->sum += a;
  157. stats->sos += (a*r);
  158. for(i = 0; i < stats->nbuckets; i++) {
  159. if(stats->buckets[i].residual == residual) {
  160. stats->buckets[i].count += incr;
  161. goto find_peak;
  162. }
  163. }
  164. /* not found, make a new bucket */
  165. i = stats->nbuckets;
  166. stats->buckets[i].residual = residual;
  167. stats->buckets[i].count = incr;
  168. stats->nbuckets++;
  169. find_peak:
  170. if(stats->peak_index < 0 || stats->buckets[i].count > stats->buckets[stats->peak_index].count)
  171. stats->peak_index = i;
  172. }
  173. void compute_stats(subframe_stats_t *stats)
  174. {
  175. stats->mean = stats->sum / (double)stats->nsamples;
  176. stats->variance = (stats->sos - (stats->sum * stats->sum / stats->nsamples)) / stats->nsamples;
  177. stats->stddev = sqrt(stats->variance);
  178. }
  179. FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename)
  180. {
  181. FILE *outfile;
  182. unsigned i;
  183. const double m = stats->mean;
  184. const double s1 = stats->stddev, s2 = s1*2, s3 = s1*3, s4 = s1*4, s5 = s1*5, s6 = s1*6;
  185. const double p = stats->buckets[stats->peak_index].count;
  186. outfile = fopen(filename, "w");
  187. if(0 == outfile) {
  188. fprintf(stderr, "ERROR opening %sn", filename);
  189. return false;
  190. }
  191. fprintf(outfile, "plot '-' title 'PDF', '-' title 'mean' with impulses, '-' title '1-stddev' with histeps, '-' title '2-stddev' with histeps, '-' title '3-stddev' with histeps, '-' title '4-stddev' with histeps, '-' title '5-stddev' with histeps, '-' title '6-stddev' with histepsn");
  192. for(i = 0; i < stats->nbuckets; i++) {
  193. fprintf(outfile, "%d %un", stats->buckets[i].residual, stats->buckets[i].count);
  194. }
  195. fprintf(outfile, "en");
  196. fprintf(outfile, "%f %fnen", stats->mean, p);
  197. fprintf(outfile, "%f %fn%f %fnen", m-s1, p*0.8, m+s1, p*0.8);
  198. fprintf(outfile, "%f %fn%f %fnen", m-s2, p*0.7, m+s2, p*0.7);
  199. fprintf(outfile, "%f %fn%f %fnen", m-s3, p*0.6, m+s3, p*0.6);
  200. fprintf(outfile, "%f %fn%f %fnen", m-s4, p*0.5, m+s4, p*0.5);
  201. fprintf(outfile, "%f %fn%f %fnen", m-s5, p*0.4, m+s5, p*0.4);
  202. fprintf(outfile, "%f %fn%f %fnen", m-s6, p*0.3, m+s6, p*0.3);
  203. fprintf(outfile, "pause -1 'waiting...'n");
  204. fclose(outfile);
  205. return true;
  206. }