📄 encode.c
字号:
return EncoderSession_finish_error(&encoder_session); } bps = x; if(bps * channels != block_align * 8) { flac__utils_printf(stderr, 1, "%s: ERROR: unsupported block alignment (%u), for bits-per-sample=%u, channels=%u\n", encoder_session.inbasefilename, block_align, bps, channels); return EncoderSession_finish_error(&encoder_session); } is_unsigned_samples = (x == 8); /* skip any extra data in the fmt sub-chunk */ data_bytes -= 16; if(data_bytes > 0) { unsigned left, need; for(left = data_bytes; left > 0; ) { need = min(left, CHUNK_OF_SAMPLES); if(fread(ucbuffer_, 1U, need, infile) < need) { flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } left -= need; } } /* * now that we know the sample rate, canonicalize the * --skip string to a number of samples: */ flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, sample_rate); FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); got_fmt_chunk = true; } else if(xx == 0x61746164 && !got_data_chunk && got_fmt_chunk) { /* "data" */ FLAC__uint64 total_samples_in_input, trim = 0; FLAC__bool pad = false; /* data size */ if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); data_bytes = xx; pad = (data_bytes & 1U) ? true : false; bytes_per_wide_sample = channels * (bps >> 3); /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); total_samples_in_input = data_bytes / bytes_per_wide_sample + *options.common.align_reservoir_samples; /* * now that we know the input size, canonicalize the * --until string to an absolute sample number: */ if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, sample_rate, encoder_session.skip, total_samples_in_input)) return EncoderSession_finish_error(&encoder_session); encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); if(encoder_session.skip > 0) { if(!fskip_ahead(infile, encoder_session.skip * bytes_per_wide_sample)) { flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } data_bytes -= (unsigned)encoder_session.skip * bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */ encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; if(encoder_session.until > 0) { trim = total_samples_in_input - encoder_session.until; FLAC__ASSERT(total_samples_in_input > 0); FLAC__ASSERT(!options.common.sector_align); data_bytes -= (unsigned int)trim * bytes_per_wide_sample; encoder_session.total_samples_to_encode -= trim; } if(options.common.sector_align) { align_remainder = (unsigned)(encoder_session.total_samples_to_encode % 588); if(options.common.is_last_file) encoder_session.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */ else encoder_session.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */ } /* +44 for the size of the WAV headers; this is just an estimate for the progress indicator and doesn't need to be exact */ encoder_session.unencoded_size = encoder_session.total_samples_to_encode * bytes_per_wide_sample + 44; if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate)) return EncoderSession_finish_error(&encoder_session); /* * first do any samples in the reservoir */ if(options.common.sector_align && *options.common.align_reservoir_samples > 0) { if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) { print_error_with_state(&encoder_session, "ERROR during encoding"); return EncoderSession_finish_error(&encoder_session); } } /* * decrement the data_bytes counter if we need to align the file */ if(options.common.sector_align) { if(options.common.is_last_file) { *options.common.align_reservoir_samples = 0; } else { *options.common.align_reservoir_samples = align_remainder; data_bytes -= (*options.common.align_reservoir_samples) * bytes_per_wide_sample; } } /* * now do from the file */ while(data_bytes > 0) { bytes_read = fread(ucbuffer_, sizeof(unsigned char), min(data_bytes, CHUNK_OF_SAMPLES * bytes_per_wide_sample), infile); if(bytes_read == 0) { if(ferror(infile)) { flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else if(feof(infile)) { flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); data_bytes = 0; } } else { if(bytes_read % bytes_per_wide_sample != 0) { flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else { unsigned wide_samples = bytes_read / bytes_per_wide_sample; format_input(input_, wide_samples, false, is_unsigned_samples, channels, bps); if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { print_error_with_state(&encoder_session, "ERROR during encoding"); return EncoderSession_finish_error(&encoder_session); } data_bytes -= bytes_read; } } } if(trim > 0) { FLAC__ASSERT(!options.common.sector_align); if(!fskip_ahead(infile, trim * bytes_per_wide_sample)) { flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } /* * now read unaligned samples into reservoir or pad with zeroes if necessary */ if(options.common.sector_align) { if(options.common.is_last_file) { unsigned wide_samples = 588 - align_remainder; if(wide_samples < 588) { unsigned channel; info_align_zero = wide_samples; data_bytes = wide_samples * (bps >> 3); for(channel = 0; channel < channels; channel++) memset(input_[channel], 0, data_bytes); if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { print_error_with_state(&encoder_session, "ERROR during encoding"); return EncoderSession_finish_error(&encoder_session); } } } else { if(*options.common.align_reservoir_samples > 0) { FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile); if(bytes_read == 0 && ferror(infile)) { flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) { flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); data_bytes = 0; } else { info_align_carry = *options.common.align_reservoir_samples; format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, is_unsigned_samples, channels, bps); } } } } if(pad == true) { unsigned char tmp; if(fread(&tmp, 1U, 1U, infile) < 1U) { flac__utils_printf(stderr, 1, "%s: ERROR during read of data pad byte\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } got_data_chunk = true; } else { if(xx == 0x20746d66 && got_fmt_chunk) { /* "fmt " */ flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'fmt ' sub-chunk\n", encoder_session.inbasefilename); } else if(xx == 0x61746164) { /* "data" */ if(got_data_chunk) { flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'data' sub-chunk\n", encoder_session.inbasefilename); } else if(!got_fmt_chunk) { flac__utils_printf(stderr, 1, "%s: ERROR: got 'data' sub-chunk before 'fmt' sub-chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else { FLAC__ASSERT(0); } } else { flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown sub-chunk '%c%c%c%c'\n", encoder_session.inbasefilename, (char)(xx&255), (char)((xx>>8)&255), (char)((xx>>16)&255), (char)(xx>>24)); } /* sub-chunk size */ if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); else { unsigned long skip = xx+(xx & 1U); FLAC__ASSERT(skip<=LONG_MAX); if(!fskip_ahead(infile, skip)) { flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping unsupported sub-chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } } } return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero);}int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options){ EncoderSession encoder_session; size_t bytes_read; const size_t bytes_per_wide_sample = options.channels * (options.bps >> 3); unsigned align_remainder = 0; int info_align_carry = -1, info_align_zero = -1; FLAC__uint64 total_samples_in_input = 0;; FLAC__ASSERT(!options.common.sector_align || options.channels == 2); FLAC__ASSERT(!options.common.sector_align || options.bps == 16); FLAC__ASSERT(!options.common.sector_align || options.sample_rate == 44100); FLAC__ASSERT(!options.common.sector_align || infilesize >= 0); FLAC__ASSERT(!options.common.replay_gain || options.channels <= 2); FLAC__ASSERT(!options.common.replay_gain || grabbag__replaygain_is_valid_sample_frequency(options.sample_rate)); if(! EncoderSession_construct( &encoder_session,#ifdef FLAC__HAS_OGG options.common.use_ogg,#else /*use_ogg=*/false,#endif options.common.verify, infile, infilename, outfilename ) ) return 1; /* * now that we know the sample rate, canonicalize the * --skip string to a number of samples: */ flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, options.sample_rate); FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); if(infilesize < 0) total_samples_in_input = 0; else { /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); total_samples_in_input = (unsigned)infilesize / bytes_per_wide_sample + *options.common.align_reservoir_samples; } /* * now that we know the input size, canonicalize the * --until strings to a number of samples: */ if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, options.sample_rate, encoder_session.skip, total_samples_in_input)) return EncoderSession_finish_error(&encoder_session); encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; if(encoder_session.until > 0) { const FLAC__uint64 trim = total_samples_in_input - encoder_session.until; FLAC__ASSERT(total_samples_in_input > 0); FLAC__ASSERT(!options.common.sector_align); encoder_session.total_samples_to_encode -= trim; } if(infilesize >= 0 && options.common.sector_align) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -