static FLAC__bool test_one_picture(const char *prefix, const PictureFile *pf, const PictureResolution * res, FLAC__bool fn_only) { FLAC__StreamMetadata *obj; const char *error; char s[4096]; if(fn_only) flac_snprintf(s, sizeof(s), "pictures/%s", pf->path); else if (res == NULL) flac_snprintf(s, sizeof(s), "%u|%s|%s||pictures/%s", (unsigned)pf->type, pf->mime_type, pf->description, pf->path); else flac_snprintf(s, sizeof(s), "%u|%s|%s|%dx%dx%d/%d|pictures/%s", (unsigned)pf->type, pf->mime_type, pf->description, res->width, res->height, res->depth, res->colors, pf->path); printf("testing grabbag__picture_parse_specification(\"%s\")... ", s); flac_snprintf(s, sizeof(s), "%s/%s", prefix, pf->path); if((obj = grabbag__picture_from_specification(fn_only? FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER : pf->type, pf->mime_type, pf->description, res, s, &error)) == 0) return failed_(error); if(debug_) { printf("\ntype=%u (%s)\nmime_type=%s\ndescription=%s\nwidth=%u\nheight=%u\ndepth=%u\ncolors=%u\ndata_length=%u\n", obj->data.picture.type, obj->data.picture.type < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED? FLAC__StreamMetadata_Picture_TypeString[obj->data.picture.type] : "UNDEFINED", obj->data.picture.mime_type, obj->data.picture.description, obj->data.picture.width, obj->data.picture.height, obj->data.picture.depth, obj->data.picture.colors, obj->data.picture.data_length ); } if(obj->data.picture.type != (fn_only? FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER : pf->type)) return failed_("picture type mismatch"); if(strcmp(obj->data.picture.mime_type, pf->mime_type)) return failed_("picture MIME type mismatch"); if(strcmp((const char *)obj->data.picture.description, (const char *)pf->description)) return failed_("picture description mismatch"); if(obj->data.picture.width != pf->width) return failed_("picture width mismatch"); if(obj->data.picture.height != pf->height) return failed_("picture height mismatch"); if(obj->data.picture.depth != pf->depth) return failed_("picture depth mismatch"); if(obj->data.picture.colors != pf->colors) return failed_("picture colors mismatch"); printf("OK\n"); FLAC__metadata_object_delete(obj); return true; }
FLAC__bool export_cs_to(const char *filename, const FLAC__StreamMetadata *cuesheet, const char *cs_filename) { FILE *f; char *ref = 0; size_t reflen; if(0 == cs_filename || strlen(cs_filename) == 0) { flac_fprintf(stderr, "%s: ERROR: empty export file name\n", filename); return false; } if(0 == strcmp(cs_filename, "-")) f = stdout; else f = flac_fopen(cs_filename, "w"); if(0 == f) { flac_fprintf(stderr, "%s: ERROR: can't open export file %s: %s\n", filename, cs_filename, strerror(errno)); return false; } reflen = strlen(filename) + 7 + 1; if(0 == (ref = malloc(reflen))) { flac_fprintf(stderr, "%s: ERROR: allocating memory\n", filename); if(f != stdout) fclose(f); return false; } flac_snprintf(ref, reflen, "\"%s\" FLAC", filename); grabbag__cuesheet_emit(f, cuesheet, ref); free(ref); if(f != stdout) fclose(f); return true; }
FLAC__bool import_cs_from(const char *filename, FLAC__StreamMetadata **cuesheet, const char *cs_filename, FLAC__bool *needs_write, FLAC__uint64 lead_out_offset, unsigned sample_rate, FLAC__bool is_cdda, Argument_AddSeekpoint *add_seekpoint_link) { FILE *f; const char *error_message; char **seekpoint_specification = add_seekpoint_link? &(add_seekpoint_link->specification) : 0; unsigned last_line_read; if(0 == cs_filename || strlen(cs_filename) == 0) { flac_fprintf(stderr, "%s: ERROR: empty import file name\n", filename); return false; } if(0 == strcmp(cs_filename, "-")) f = stdin; else f = flac_fopen(cs_filename, "r"); if(0 == f) { flac_fprintf(stderr, "%s: ERROR: can't open import file %s: %s\n", filename, cs_filename, strerror(errno)); return false; } *cuesheet = grabbag__cuesheet_parse(f, &error_message, &last_line_read, sample_rate, is_cdda, lead_out_offset); if(f != stdin) fclose(f); if(0 == *cuesheet) { flac_fprintf(stderr, "%s: ERROR: while parsing cuesheet \"%s\" on line %u: %s\n", filename, cs_filename, last_line_read, error_message); return false; } if(!FLAC__format_cuesheet_is_legal(&(*cuesheet)->data.cue_sheet, /*check_cd_da_subset=*/false, &error_message)) { flac_fprintf(stderr, "%s: ERROR parsing cuesheet \"%s\": %s\n", filename, cs_filename, error_message); return false; } /* if we're expecting CDDA, warn about non-compliance */ if(is_cdda && !FLAC__format_cuesheet_is_legal(&(*cuesheet)->data.cue_sheet, /*check_cd_da_subset=*/true, &error_message)) { flac_fprintf(stderr, "%s: WARNING cuesheet \"%s\" is not audio CD compliant: %s\n", filename, cs_filename, error_message); (*cuesheet)->data.cue_sheet.is_cd = false; } /* add seekpoints for each index point if required */ if(0 != seekpoint_specification) { char spec[128]; unsigned track, indx; const FLAC__StreamMetadata_CueSheet *cs = &(*cuesheet)->data.cue_sheet; if(0 == *seekpoint_specification) *seekpoint_specification = local_strdup(""); for(track = 0; track < cs->num_tracks; track++) { const FLAC__StreamMetadata_CueSheet_Track *tr = cs->tracks+track; for(indx = 0; indx < tr->num_indices; indx++) { flac_snprintf(spec, sizeof (spec), "%" PRIu64 ";", (tr->offset + tr->indices[indx].offset)); local_strcat(seekpoint_specification, spec); } } } *needs_write = true; return true; }
int main(int argc, char *argv[]) { int flac_return_val = 0, opt_arg = 1, from_arg = -1, to_arg = -1, flac_level = 5, i; char prog[MAX_PATH], cmdline[MAX_PATH*2], from[MAX_PATH], to[MAX_PATH], macdir[MAX_PATH], options[256], *p; enum { WAVPACK, RKAU, SHORTEN } codec; /* get the directory where MAC external codecs reside */ if(0 != (p = strrchr(argv[0],'\\'))) { safe_strncpy(macdir, argv[0], sizeof(macdir)); *(strrchr(macdir,'\\')+1) = '\0'; } else { safe_strncpy(macdir, "", sizeof(macdir)); } /* determine which codec we were called as and parse the options */ if(p == 0) p = argv[0]; else p++; if(0 == strnicmp(p, "short", 5)) { codec = SHORTEN; } else if(0 == strnicmp(p, "rkau", 4)) { codec = RKAU; if(argv[1][0] == '-' && argv[1][1] == 'l') { opt_arg = 2; switch(argv[1][2]) { case '1': flac_level = 1; break; case '2': flac_level = 5; break; case '3': flac_level = 8; break; } } } else if(0 == strnicmp(p, "wavpack", 7)) { codec = WAVPACK; if(argv[1][0] == '-') { opt_arg = 2; switch(argv[1][1]) { case 'f': flac_level = 1; break; case 'h': flac_level = 8; break; default: opt_arg = 1; } } } else { return -5; } /* figure out which arguments are the source and destination files */ for(i = 1; i < argc; i++) if(argv[i][0] != '-') { from_arg = i++; break; } for( ; i < argc; i++) if(argv[i][0] != '-') { to_arg = i++; break; } if(to_arg < 0) return -4; /* build the command to call flac with */ flac_snprintf(prog, sizeof (prog), "%sflac.exe", macdir); flac_snprintf(options, sizeof (options), "-%d", flac_level); for(i = opt_arg; i < argc; i++) if(argv[i][0] == '-') { safe_strncat(options, " ", sizeof(options)); safe_strncat(options, argv[i], sizeof(options)); } flac_snprintf(cmdline, sizeof (cmdline), "\"%s\" %s -o \"%s\" \"%s\"", prog, options, argv[to_arg], argv[from_arg]); flac_return_val = execit(prog, cmdline); /* * Now that flac has finished, we need to fork a process that will rename * the resulting file with the correct extension once MAC has moved it to * it's final resting place. */ if(0 == flac_return_val) { char *cptr; /* get the destination directory, if any */ if(0 != (p = strchr(argv[to_arg],'\\'))) { safe_strncpy(from, argv[to_arg], sizeof(from)); *(strrchr(from,'\\')+1) = '\0'; } else { safe_strncpy(from, "", sizeof(from)); } /* for the full 'from' and 'to' paths for the renamer process */ p = strrchr(argv[from_arg],'\\'); safe_strncat(from, p? p+1 : argv[from_arg], sizeof(from)); safe_strncpy(to, from, sizeof(to)); cptr = strrchr(from,'.'); if(cptr == NULL) return -3; cptr [0] = 0; switch(codec) { case SHORTEN: safe_strncat(from, ".shn", sizeof (from)); break; case WAVPACK: safe_strncat(from, ".wv", sizeof (from)); break; case RKAU: safe_strncpy(from, ".rka", sizeof (from)); break; default: return -4; } cptr = strrchr(to,'.'); if(cptr == NULL) return -3; cptr [0] = 0; safe_strncat(to, ".flac", sizeof(to)); flac_snprintf(prog, sizeof (prog), "%sflac_ren.exe", macdir); flac_snprintf(cmdline, sizeof (cmdline), "\"%s\" \"%s\" \"%s\"", prog, from, to); flac_return_val = forkit(prog, cmdline); } return flac_return_val; }
void flac__analyze_frame(const FLAC__Frame *frame, unsigned frame_number, FLAC__uint64 frame_offset, unsigned frame_bytes, analysis_options aopts, FILE *fout) { const unsigned channels = frame->header.channels; char outfilename[1024]; subframe_stats_t stats; unsigned i, channel, partitions; /* do the human-readable part first */ 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]); for(channel = 0; channel < channels; channel++) { const FLAC__Subframe *subframe = frame->subframes+channel; const FLAC__bool is_rice2 = subframe->data.fixed.entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2; const unsigned pesc = is_rice2? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; fprintf(fout, "\tsubframe=%u\twasted_bits=%u\ttype=%s", channel, subframe->wasted_bits, 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: FLAC__ASSERT(subframe->data.fixed.entropy_coding_method.type <= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2); 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); for(i = 0; i < subframe->data.fixed.order; i++) fprintf(fout, "\t\twarmup[%u]=%d\n", i, subframe->data.fixed.warmup[i]); partitions = (1u << subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order); for(i = 0; i < partitions; i++) { unsigned parameter = subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->parameters[i]; if(parameter == pesc) fprintf(fout, "\t\tparameter[%u]=ESCAPE, raw_bits=%u\n", i, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]); else fprintf(fout, "\t\tparameter[%u]=%u\n", i, parameter); } if(aopts.do_residual_text) { for(i = 0; i < frame->header.blocksize-subframe->data.fixed.order; i++) fprintf(fout, "\t\tresidual[%u]=%d\n", i, subframe->data.fixed.residual[i]); } break; case FLAC__SUBFRAME_TYPE_LPC: FLAC__ASSERT(subframe->data.lpc.entropy_coding_method.type <= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2); 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); for(i = 0; i < subframe->data.lpc.order; i++) fprintf(fout, "\t\tqlp_coeff[%u]=%d\n", i, subframe->data.lpc.qlp_coeff[i]); for(i = 0; i < subframe->data.lpc.order; i++) fprintf(fout, "\t\twarmup[%u]=%d\n", i, subframe->data.lpc.warmup[i]); partitions = (1u << subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order); for(i = 0; i < partitions; i++) { unsigned parameter = subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->parameters[i]; if(parameter == pesc) fprintf(fout, "\t\tparameter[%u]=ESCAPE, raw_bits=%u\n", i, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]); else fprintf(fout, "\t\tparameter[%u]=%u\n", i, parameter); } if(aopts.do_residual_text) { for(i = 0; i < frame->header.blocksize-subframe->data.lpc.order; i++) fprintf(fout, "\t\tresidual[%u]=%d\n", i, subframe->data.lpc.residual[i]); } break; case FLAC__SUBFRAME_TYPE_VERBATIM: fprintf(fout, "\n"); break; } } /* now do the residual distributions if requested */ if(aopts.do_residual_gnuplot) { for(channel = 0; channel < channels; channel++) { const FLAC__Subframe *subframe = frame->subframes+channel; unsigned residual_samples; init_stats(&stats); switch(subframe->type) { case FLAC__SUBFRAME_TYPE_FIXED: residual_samples = frame->header.blocksize - subframe->data.fixed.order; for(i = 0; i < residual_samples; i++) update_stats(&stats, subframe->data.fixed.residual[i], 1); break; case FLAC__SUBFRAME_TYPE_LPC: residual_samples = frame->header.blocksize - subframe->data.lpc.order; for(i = 0; i < residual_samples; i++) update_stats(&stats, subframe->data.lpc.residual[i], 1); break; default: break; } /* update all_ */ for(i = 0; i < stats.nbuckets; i++) { update_stats(&all_, stats.buckets[i].residual, stats.buckets[i].count); } /* write the subframe */ flac_snprintf(outfilename, sizeof (outfilename), "f%06u.s%u.gp", frame_number, channel); compute_stats(&stats); (void)dump_stats(&stats, outfilename); } } }
static int do_cuesheet(const char *infilename, unsigned sample_rate, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset) { FILE *fin, *fout; const char *error_message, *tmpfilenamebase; char tmpfilename[4096]; unsigned last_line_read; FLAC__StreamMetadata *cuesheet; FLAC__ASSERT(strlen(infilename) + 2 < sizeof(tmpfilename)); /* * pass 1 */ if(0 == strcmp(infilename, "-")) { fin = stdin; } else if(0 == (fin = flac_fopen(infilename, "r"))) { fprintf(stderr, "can't open file %s for reading: %s\n", infilename, strerror(errno)); return 255; } if(0 != (cuesheet = grabbag__cuesheet_parse(fin, &error_message, &last_line_read, sample_rate, is_cdda, lead_out_offset))) { if(fin != stdin) fclose(fin); } else { printf("pass1: parse error, line %u: \"%s\"\n", last_line_read, error_message); if(fin != stdin) fclose(fin); return 1; } if(!FLAC__metadata_object_cuesheet_is_legal(cuesheet, is_cdda, &error_message)) { printf("pass1: illegal cuesheet: \"%s\"\n", error_message); FLAC__metadata_object_delete(cuesheet); return 1; } tmpfilenamebase = strstr(infilename, "cuesheets/"); tmpfilenamebase = tmpfilenamebase == NULL ? infilename : tmpfilenamebase; flac_snprintf(tmpfilename, sizeof (tmpfilename), "%s.1", tmpfilenamebase); if(0 == (fout = flac_fopen(tmpfilename, "w"))) { fprintf(stderr, "can't open file %s for writing: %s\n", tmpfilename, strerror(errno)); FLAC__metadata_object_delete(cuesheet); return 255; } grabbag__cuesheet_emit(fout, cuesheet, "\"dummy.wav\" WAVE"); FLAC__metadata_object_delete(cuesheet); fclose(fout); /* * pass 2 */ if(0 == (fin = flac_fopen(tmpfilename, "r"))) { fprintf(stderr, "can't open file %s for reading: %s\n", tmpfilename, strerror(errno)); return 255; } if(0 != (cuesheet = grabbag__cuesheet_parse(fin, &error_message, &last_line_read, sample_rate, is_cdda, lead_out_offset))) { if(fin != stdin) fclose(fin); } else { printf("pass2: parse error, line %u: \"%s\"\n", last_line_read, error_message); if(fin != stdin) fclose(fin); return 1; } if(!FLAC__metadata_object_cuesheet_is_legal(cuesheet, is_cdda, &error_message)) { printf("pass2: illegal cuesheet: \"%s\"\n", error_message); FLAC__metadata_object_delete(cuesheet); return 1; } flac_snprintf(tmpfilename, sizeof (tmpfilename), "%s.2", tmpfilenamebase); if(0 == (fout = flac_fopen(tmpfilename, "w"))) { fprintf(stderr, "can't open file %s for writing: %s\n", tmpfilename, strerror(errno)); FLAC__metadata_object_delete(cuesheet); return 255; } grabbag__cuesheet_emit(fout, cuesheet, "\"dummy.wav\" WAVE"); FLAC__metadata_object_delete(cuesheet); fclose(fout); return 0; }