|
Packit Service |
065837 |
/* flac - Command-line FLAC encoder/decoder
|
|
Packit Service |
065837 |
* Copyright (C) 2000-2009 Josh Coalson
|
|
Packit Service |
065837 |
* Copyright (C) 2011-2016 Xiph.Org Foundation
|
|
Packit Service |
065837 |
*
|
|
Packit Service |
065837 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
065837 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
065837 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
065837 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
065837 |
*
|
|
Packit Service |
065837 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
065837 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
065837 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
065837 |
* GNU General Public License for more details.
|
|
Packit Service |
065837 |
*
|
|
Packit Service |
065837 |
* You should have received a copy of the GNU General Public License along
|
|
Packit Service |
065837 |
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit Service |
065837 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit Service |
065837 |
*/
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
065837 |
# include <config.h>
|
|
Packit Service |
065837 |
#endif
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
#include <errno.h>
|
|
Packit Service |
065837 |
#include <math.h>
|
|
Packit Service |
065837 |
#include <stdio.h>
|
|
Packit Service |
065837 |
#include <stdlib.h>
|
|
Packit Service |
065837 |
#include <string.h>
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
#include "FLAC/all.h"
|
|
Packit Service |
065837 |
#include "analyze.h"
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
#include "share/compat.h"
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
typedef struct {
|
|
Packit Service |
065837 |
FLAC__int32 residual;
|
|
Packit Service |
065837 |
unsigned count;
|
|
Packit Service |
065837 |
} pair_t;
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
typedef struct {
|
|
Packit Service |
065837 |
pair_t buckets[FLAC__MAX_BLOCK_SIZE];
|
|
Packit Service |
065837 |
int peak_index;
|
|
Packit Service |
065837 |
unsigned nbuckets;
|
|
Packit Service |
065837 |
unsigned nsamples;
|
|
Packit Service |
065837 |
double sum, sos;
|
|
Packit Service |
065837 |
double variance;
|
|
Packit Service |
065837 |
double mean;
|
|
Packit Service |
065837 |
double stddev;
|
|
Packit Service |
065837 |
} subframe_stats_t;
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
static subframe_stats_t all_;
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
static void init_stats(subframe_stats_t *stats);
|
|
Packit Service |
065837 |
static void update_stats(subframe_stats_t *stats, FLAC__int32 residual, unsigned incr);
|
|
Packit Service |
065837 |
static void compute_stats(subframe_stats_t *stats);
|
|
Packit Service |
065837 |
static FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename);
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
void flac__analyze_init(analysis_options aopts)
|
|
Packit Service |
065837 |
{
|
|
Packit Service |
065837 |
if(aopts.do_residual_gnuplot) {
|
|
Packit Service |
065837 |
init_stats(&all_);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
void flac__analyze_frame(const FLAC__Frame *frame, unsigned frame_number, FLAC__uint64 frame_offset, unsigned frame_bytes, analysis_options aopts, FILE *fout)
|
|
Packit Service |
065837 |
{
|
|
Packit Service |
065837 |
const unsigned channels = frame->header.channels;
|
|
Packit Service |
065837 |
char outfilename[1024];
|
|
Packit Service |
065837 |
subframe_stats_t stats;
|
|
Packit Service |
065837 |
unsigned i, channel, partitions;
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
/* do the human-readable part first */
|
|
Packit Service |
065837 |
fprintf(fout, "frame=%u\toffset=%" PRIu64 "\tbits=%u\tblocksize=%u\tsample_rate=%u\tchannels=%u\tchannel_assignment=%s\n", frame_number, frame_offset, frame_bytes*8, frame->header.blocksize, frame->header.sample_rate, channels, FLAC__ChannelAssignmentString[frame->header.channel_assignment]);
|
|
Packit Service |
065837 |
for(channel = 0; channel < channels; channel++) {
|
|
Packit Service |
065837 |
const FLAC__Subframe *subframe = frame->subframes+channel;
|
|
Packit Service |
065837 |
const FLAC__bool is_rice2 = subframe->data.fixed.entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2;
|
|
Packit Service |
065837 |
const unsigned pesc = is_rice2? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
|
|
Packit Service |
065837 |
fprintf(fout, "\tsubframe=%u\twasted_bits=%u\ttype=%s", channel, subframe->wasted_bits, FLAC__SubframeTypeString[subframe->type]);
|
|
Packit Service |
065837 |
switch(subframe->type) {
|
|
Packit Service |
065837 |
case FLAC__SUBFRAME_TYPE_CONSTANT:
|
|
Packit Service |
065837 |
fprintf(fout, "\tvalue=%d\n", subframe->data.constant.value);
|
|
Packit Service |
065837 |
break;
|
|
Packit Service |
065837 |
case FLAC__SUBFRAME_TYPE_FIXED:
|
|
Packit Service |
065837 |
FLAC__ASSERT(subframe->data.fixed.entropy_coding_method.type <= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2);
|
|
Packit Service |
065837 |
fprintf(fout, "\torder=%u\tresidual_type=%s\tpartition_order=%u\n", subframe->data.fixed.order, is_rice2? "RICE2":"RICE", subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order);
|
|
Packit Service |
065837 |
for(i = 0; i < subframe->data.fixed.order; i++)
|
|
Packit Service |
065837 |
fprintf(fout, "\t\twarmup[%u]=%d\n", i, subframe->data.fixed.warmup[i]);
|
|
Packit Service |
065837 |
partitions = (1u << subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order);
|
|
Packit Service |
065837 |
for(i = 0; i < partitions; i++) {
|
|
Packit Service |
065837 |
unsigned parameter = subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->parameters[i];
|
|
Packit Service |
065837 |
if(parameter == pesc)
|
|
Packit Service |
065837 |
fprintf(fout, "\t\tparameter[%u]=ESCAPE, raw_bits=%u\n", i, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]);
|
|
Packit Service |
065837 |
else
|
|
Packit Service |
065837 |
fprintf(fout, "\t\tparameter[%u]=%u\n", i, parameter);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
if(aopts.do_residual_text) {
|
|
Packit Service |
065837 |
for(i = 0; i < frame->header.blocksize-subframe->data.fixed.order; i++)
|
|
Packit Service |
065837 |
fprintf(fout, "\t\tresidual[%u]=%d\n", i, subframe->data.fixed.residual[i]);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
break;
|
|
Packit Service |
065837 |
case FLAC__SUBFRAME_TYPE_LPC:
|
|
Packit Service |
065837 |
FLAC__ASSERT(subframe->data.lpc.entropy_coding_method.type <= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2);
|
|
Packit Service |
065837 |
fprintf(fout, "\torder=%u\tqlp_coeff_precision=%u\tquantization_level=%d\tresidual_type=%s\tpartition_order=%u\n", subframe->data.lpc.order, subframe->data.lpc.qlp_coeff_precision, subframe->data.lpc.quantization_level, is_rice2? "RICE2":"RICE", subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order);
|
|
Packit Service |
065837 |
for(i = 0; i < subframe->data.lpc.order; i++)
|
|
Packit Service |
065837 |
fprintf(fout, "\t\tqlp_coeff[%u]=%d\n", i, subframe->data.lpc.qlp_coeff[i]);
|
|
Packit Service |
065837 |
for(i = 0; i < subframe->data.lpc.order; i++)
|
|
Packit Service |
065837 |
fprintf(fout, "\t\twarmup[%u]=%d\n", i, subframe->data.lpc.warmup[i]);
|
|
Packit Service |
065837 |
partitions = (1u << subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order);
|
|
Packit Service |
065837 |
for(i = 0; i < partitions; i++) {
|
|
Packit Service |
065837 |
unsigned parameter = subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->parameters[i];
|
|
Packit Service |
065837 |
if(parameter == pesc)
|
|
Packit Service |
065837 |
fprintf(fout, "\t\tparameter[%u]=ESCAPE, raw_bits=%u\n", i, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]);
|
|
Packit Service |
065837 |
else
|
|
Packit Service |
065837 |
fprintf(fout, "\t\tparameter[%u]=%u\n", i, parameter);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
if(aopts.do_residual_text) {
|
|
Packit Service |
065837 |
for(i = 0; i < frame->header.blocksize-subframe->data.lpc.order; i++)
|
|
Packit Service |
065837 |
fprintf(fout, "\t\tresidual[%u]=%d\n", i, subframe->data.lpc.residual[i]);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
break;
|
|
Packit Service |
065837 |
case FLAC__SUBFRAME_TYPE_VERBATIM:
|
|
Packit Service |
065837 |
fprintf(fout, "\n");
|
|
Packit Service |
065837 |
break;
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
/* now do the residual distributions if requested */
|
|
Packit Service |
065837 |
if(aopts.do_residual_gnuplot) {
|
|
Packit Service |
065837 |
for(channel = 0; channel < channels; channel++) {
|
|
Packit Service |
065837 |
const FLAC__Subframe *subframe = frame->subframes+channel;
|
|
Packit Service |
065837 |
unsigned residual_samples;
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
init_stats(&stats);
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
switch(subframe->type) {
|
|
Packit Service |
065837 |
case FLAC__SUBFRAME_TYPE_FIXED:
|
|
Packit Service |
065837 |
residual_samples = frame->header.blocksize - subframe->data.fixed.order;
|
|
Packit Service |
065837 |
for(i = 0; i < residual_samples; i++)
|
|
Packit Service |
065837 |
update_stats(&stats, subframe->data.fixed.residual[i], 1);
|
|
Packit Service |
065837 |
break;
|
|
Packit Service |
065837 |
case FLAC__SUBFRAME_TYPE_LPC:
|
|
Packit Service |
065837 |
residual_samples = frame->header.blocksize - subframe->data.lpc.order;
|
|
Packit Service |
065837 |
for(i = 0; i < residual_samples; i++)
|
|
Packit Service |
065837 |
update_stats(&stats, subframe->data.lpc.residual[i], 1);
|
|
Packit Service |
065837 |
break;
|
|
Packit Service |
065837 |
default:
|
|
Packit Service |
065837 |
break;
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
/* update all_ */
|
|
Packit Service |
065837 |
for(i = 0; i < stats.nbuckets; i++) {
|
|
Packit Service |
065837 |
update_stats(&all_, stats.buckets[i].residual, stats.buckets[i].count);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
/* write the subframe */
|
|
Packit Service |
065837 |
flac_snprintf(outfilename, sizeof (outfilename), "f%06u.s%u.gp", frame_number, channel);
|
|
Packit Service |
065837 |
compute_stats(&stats);
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
(void)dump_stats(&stats, outfilename);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
void flac__analyze_finish(analysis_options aopts)
|
|
Packit Service |
065837 |
{
|
|
Packit Service |
065837 |
if(aopts.do_residual_gnuplot) {
|
|
Packit Service |
065837 |
compute_stats(&all_);
|
|
Packit Service |
065837 |
(void)dump_stats(&all_, "all");
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
void init_stats(subframe_stats_t *stats)
|
|
Packit Service |
065837 |
{
|
|
Packit Service |
065837 |
stats->peak_index = -1;
|
|
Packit Service |
065837 |
stats->nbuckets = 0;
|
|
Packit Service |
065837 |
stats->nsamples = 0;
|
|
Packit Service |
065837 |
stats->sum = 0.0;
|
|
Packit Service |
065837 |
stats->sos = 0.0;
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
void update_stats(subframe_stats_t *stats, FLAC__int32 residual, unsigned incr)
|
|
Packit Service |
065837 |
{
|
|
Packit Service |
065837 |
unsigned i;
|
|
Packit Service |
065837 |
const double r = (double)residual, a = r*incr;
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
stats->nsamples += incr;
|
|
Packit Service |
065837 |
stats->sum += a;
|
|
Packit Service |
065837 |
stats->sos += (a*r);
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
for(i = 0; i < stats->nbuckets; i++) {
|
|
Packit Service |
065837 |
if(stats->buckets[i].residual == residual) {
|
|
Packit Service |
065837 |
stats->buckets[i].count += incr;
|
|
Packit Service |
065837 |
goto find_peak;
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
/* not found, make a new bucket */
|
|
Packit Service |
065837 |
i = stats->nbuckets;
|
|
Packit Service |
065837 |
stats->buckets[i].residual = residual;
|
|
Packit Service |
065837 |
stats->buckets[i].count = incr;
|
|
Packit Service |
065837 |
stats->nbuckets++;
|
|
Packit Service |
065837 |
find_peak:
|
|
Packit Service |
065837 |
if(stats->peak_index < 0 || stats->buckets[i].count > stats->buckets[stats->peak_index].count)
|
|
Packit Service |
065837 |
stats->peak_index = i;
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
void compute_stats(subframe_stats_t *stats)
|
|
Packit Service |
065837 |
{
|
|
Packit Service |
065837 |
stats->mean = stats->sum / (double)stats->nsamples;
|
|
Packit Service |
065837 |
stats->variance = (stats->sos - (stats->sum * stats->sum / stats->nsamples)) / stats->nsamples;
|
|
Packit Service |
065837 |
stats->stddev = sqrt(stats->variance);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename)
|
|
Packit Service |
065837 |
{
|
|
Packit Service |
065837 |
FILE *outfile;
|
|
Packit Service |
065837 |
unsigned i;
|
|
Packit Service |
065837 |
const double m = stats->mean;
|
|
Packit Service |
065837 |
const double s1 = stats->stddev, s2 = s1*2, s3 = s1*3, s4 = s1*4, s5 = s1*5, s6 = s1*6;
|
|
Packit Service |
065837 |
const double p = stats->buckets[stats->peak_index].count;
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
outfile = flac_fopen(filename, "w");
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
if(0 == outfile) {
|
|
Packit Service |
065837 |
fprintf(stderr, "ERROR opening %s: %s\n", filename, strerror(errno));
|
|
Packit Service |
065837 |
return false;
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
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 histeps\n");
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
for(i = 0; i < stats->nbuckets; i++) {
|
|
Packit Service |
065837 |
fprintf(outfile, "%d %u\n", stats->buckets[i].residual, stats->buckets[i].count);
|
|
Packit Service |
065837 |
}
|
|
Packit Service |
065837 |
fprintf(outfile, "e\n");
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
fprintf(outfile, "%f %f\ne\n", stats->mean, p);
|
|
Packit Service |
065837 |
fprintf(outfile, "%f %f\n%f %f\ne\n", m-s1, p*0.8, m+s1, p*0.8);
|
|
Packit Service |
065837 |
fprintf(outfile, "%f %f\n%f %f\ne\n", m-s2, p*0.7, m+s2, p*0.7);
|
|
Packit Service |
065837 |
fprintf(outfile, "%f %f\n%f %f\ne\n", m-s3, p*0.6, m+s3, p*0.6);
|
|
Packit Service |
065837 |
fprintf(outfile, "%f %f\n%f %f\ne\n", m-s4, p*0.5, m+s4, p*0.5);
|
|
Packit Service |
065837 |
fprintf(outfile, "%f %f\n%f %f\ne\n", m-s5, p*0.4, m+s5, p*0.4);
|
|
Packit Service |
065837 |
fprintf(outfile, "%f %f\n%f %f\ne\n", m-s6, p*0.3, m+s6, p*0.3);
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
fprintf(outfile, "pause -1 'waiting...'\n");
|
|
Packit Service |
065837 |
|
|
Packit Service |
065837 |
fclose(outfile);
|
|
Packit Service |
065837 |
return true;
|
|
Packit Service |
065837 |
}
|