#else
# include <unistd.h>
#endif
+#include <assert.h> /* for FILE */
#include <stdio.h> /* for FILE */
#include <string.h> /* for strcmp() */
#include "FLAC/all.h"
typedef struct {
FILE *fout;
bool abort_flag;
+ bool analysis_mode;
bool test_only;
bool is_wave_out;
bool is_big_endian;
static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
static void print_stats(const stream_info_struct *stream_info);
-int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip)
+int decode_wav(const char *infile, const char *outfile, bool analysis_mode, bool verbose, uint64 skip)
{
bool md5_failure = false;
stream_info_struct stream_info;
decoder = 0;
stream_info.abort_flag = false;
+ stream_info.analysis_mode = analysis_mode;
stream_info.test_only = (outfile == 0);
stream_info.is_wave_out = true;
stream_info.verbose = verbose;
stream_info.samples_processed = 0;
stream_info.frame_counter = 0;
+ assert(!(test_only && analysis_mode));
+
if(!stream_info.test_only) {
if(0 == strcmp(outfile, "-")) {
stream_info.fout = stdout;
return 1;
}
-int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
+int decode_raw(const char *infile, const char *outfile, bool analysis_mode, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
{
bool md5_failure = false;
stream_info_struct stream_info;
decoder = 0;
stream_info.abort_flag = false;
+ stream_info.analysis_mode = analysis_mode;
stream_info.test_only = (outfile == 0);
stream_info.is_wave_out = false;
stream_info.is_big_endian = is_big_endian;
stream_info.samples_processed = 0;
stream_info.frame_counter = 0;
+ assert(!(test_only && analysis_mode));
+
if(!stream_info.test_only) {
if(0 == strcmp(outfile, "-")) {
stream_info.fout = stdout;
if(stream_info->verbose && !(stream_info->frame_counter & 0x1f))
print_stats(stream_info);
- if(!stream_info->test_only) {
+ if(stream_info->analysis_mode) {
+ fprintf(fout, "frame=%u\tblocksize=%u\tsample_rate=%u\tchannels=%u\tchannel_assignment=%s\n", stream_info->frame_counter-1, frame->header.blocksize, frame->header.sample_rate, frame->header.channels, FLAC__ChannelAssignmentString[frame->header.channel_assignment]);
+ for(channel = 0; channel < channels; channel++) {
+ const FLAC__Subframe *subframe = frame->subframes+channel;
+ fprintf(fout, "\tsubframe=%u\ttype=%s", channel, FLAC__SubframeTypeString[subframe->type]);
+ switch(subframe->type) {
+ case FLAC__SUBFRAME_TYPE_CONSTANT:
+ fprintf(fout, "\tvalue=%d\n", subframe->data.constant.value);
+ break;
+ case FLAC__SUBFRAME_TYPE_FIXED:
+ fprintf(fout, "\torder=%u\tpartition_order=%u\n", subframe->data.fixed.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order); /*@@@ assumes method is partitioned-rice */
+ break;
+ case FLAC__SUBFRAME_TYPE_LPC:
+ fprintf(fout, "\torder=%u\tpartition_order=%u\tqlp_coeff_precision=%u\tquantization_level=%d\n", 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); /*@@@ assumes method is partitioned-rice */
+ break;
+ case FLAC__SUBFRAME_TYPE_VERBATIM:
+ fprintf(fout, "\n");
+ break;
+ }
+ }
+ }
+ else if(!stream_info->test_only) {
if(bps == 8) {
if(is_unsigned_samples) {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
}
/* write the WAVE headers if necessary */
- if(!stream_info->test_only && stream_info->is_wave_out) {
+ if(!stream_info->analysis_mode && !stream_info->test_only && stream_info->is_wave_out) {
uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
if(data_size >= 0xFFFFFFDC) {
fprintf(stderr, "ERROR: stream is too big for a wave file\n");
{
if(stream_info->verbose) {
printf("\r%s %u of %u samples, %6.2f%% complete",
- stream_info->test_only? "tested" : "wrote",
+ stream_info->test_only? "tested" : stream_info->analysis_mode? "analyzed" : "wrote",
(unsigned)stream_info->samples_processed,
(unsigned)stream_info->total_samples,
#ifdef _MSC_VER
int main(int argc, char *argv[])
{
int i;
- bool verify = false, verbose = true, lax = false, mode_decode = false, test_only = false;
+ bool verify = false, verbose = true, lax = false, mode_decode = false, test_only = false, analyze = false;
bool do_mid_side = true, do_exhaustive_model_search = false, do_qlp_coeff_prec_search = false;
unsigned max_lpc_order = 8;
unsigned qlp_coeff_precision = 0;
break;
if(0 == strcmp(argv[i], "-d"))
mode_decode = true;
+ else if(0 == strcmp(argv[i], "-a")) {
+ mode_decode = true;
+ analyze = true;
+ }
else if(0 == strcmp(argv[i], "-t")) {
mode_decode = true;
test_only = true;
if(skip > 0)
return usage("ERROR: --skip is not allowed in test mode\n");
}
- else {
+ else if(!analyze) {
if(format_is_wave < 0) {
if(strstr(argv[i+1], ".wav") == argv[i+1] + (strlen(argv[i+1]) - strlen(".wav")))
format_is_wave = true;
if(mode_decode)
if(format_is_wave)
- return decode_wav(argv[i], test_only? 0 : argv[i+1], verbose, skip);
+ return decode_wav(argv[i], test_only? 0 : argv[i+1], analyze, verbose, skip);
else
- return decode_raw(argv[i], test_only? 0 : argv[i+1], verbose, skip, format_is_big_endian, format_is_unsigned_samples);
+ return decode_raw(argv[i], test_only? 0 : argv[i+1], analyze, verbose, skip, format_is_big_endian, format_is_unsigned_samples);
else
if(format_is_wave)
return encode_wav(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision);
printf("For encoding:\n");
printf(" infile may be a PCM RIFF WAVE file or raw samples\n");
printf(" outfile will be in FLAC format\n");
- printf("For decoding, the reverse will be true\n");
+ printf("For decoding, the reverse is be true\n");
printf("\n");
printf("infile may be - for stdin, outfile may be - for stdout\n");
printf("\n");