Пример #1
0
static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
	DecoderInstance *instance = (DecoderInstance*)client_data;

	(void)decoder;

	if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
		instance->bits_per_sample = metadata->data.stream_info.bits_per_sample;
		instance->channels = metadata->data.stream_info.channels;
		instance->sample_rate = metadata->data.stream_info.sample_rate;

		if(instance->channels != 1 && instance->channels != 2) {
			instance->error = true;
			return;
		}

		if(!grabbag__replaygain_is_valid_sample_frequency(instance->sample_rate)) {
			instance->error = true;
			return;
		}
	}
}
Пример #2
0
FLAC__bool do_shorthand_operation__add_replay_gain(char **filenames, unsigned num_files, FLAC__bool preserve_modtime)
{
	FLAC__StreamMetadata streaminfo;
	float *title_gains = 0, *title_peaks = 0;
	float album_gain, album_peak;
	unsigned sample_rate = 0;
	unsigned bits_per_sample = 0;
	unsigned channels = 0;
	unsigned i;
	const char *error;
	FLAC__bool first = true;

	FLAC__ASSERT(num_files > 0);

	for(i = 0; i < num_files; i++) {
		FLAC__ASSERT(0 != filenames[i]);
		if(!FLAC__metadata_get_streaminfo(filenames[i], &streaminfo)) {
			fprintf(stderr, "%s: ERROR: can't open file or get STREAMINFO block\n", filenames[i]);
			return false;
		}
		if(first) {
			first = false;
			sample_rate = streaminfo.data.stream_info.sample_rate;
			bits_per_sample = streaminfo.data.stream_info.bits_per_sample;
			channels = streaminfo.data.stream_info.channels;
		}
		else {
			if(sample_rate != streaminfo.data.stream_info.sample_rate) {
				fprintf(stderr, "%s: ERROR: sample rate of %u Hz does not match previous files' %u Hz\n", filenames[i], streaminfo.data.stream_info.sample_rate, sample_rate);
				return false;
			}
			if(bits_per_sample != streaminfo.data.stream_info.bits_per_sample) {
				fprintf(stderr, "%s: ERROR: resolution of %u bps does not match previous files' %u bps\n", filenames[i], streaminfo.data.stream_info.bits_per_sample, bits_per_sample);
				return false;
			}
			if(channels != streaminfo.data.stream_info.channels) {
				fprintf(stderr, "%s: ERROR: # channels (%u) does not match previous files' (%u)\n", filenames[i], streaminfo.data.stream_info.channels, channels);
				return false;
			}
		}
		if(!grabbag__replaygain_is_valid_sample_frequency(sample_rate)) {
			fprintf(stderr, "%s: ERROR: sample rate of %u Hz is not supported\n", filenames[i], sample_rate);
			return false;
		}
		if(channels != 1 && channels != 2) {
			fprintf(stderr, "%s: ERROR: # of channels (%u) is not supported, must be 1 or 2\n", filenames[i], channels);
			return false;
		}
	}
	FLAC__ASSERT(bits_per_sample >= FLAC__MIN_BITS_PER_SAMPLE && bits_per_sample <= FLAC__MAX_BITS_PER_SAMPLE);

	if(!grabbag__replaygain_init(sample_rate)) {
		FLAC__ASSERT(0);
		/* double protection */
		fprintf(stderr, "internal error\n");
		return false;
	}

	if(
		0 == (title_gains = (float*)malloc(sizeof(float) * num_files)) ||
		0 == (title_peaks = (float*)malloc(sizeof(float) * num_files))
	)
		die("out of memory allocating space for title gains/peaks");

	for(i = 0; i < num_files; i++) {
		if(0 != (error = grabbag__replaygain_analyze_file(filenames[i], title_gains+i, title_peaks+i))) {
			fprintf(stderr, "%s: ERROR: during analysis (%s)\n", filenames[i], error);
			free(title_gains);
			free(title_peaks);
			return false;
		}
	}
	grabbag__replaygain_get_album(&album_gain, &album_peak);

	for(i = 0; i < num_files; i++) {
		if(0 != (error = grabbag__replaygain_store_to_file(filenames[i], album_gain, album_peak, title_gains[i], title_peaks[i], preserve_modtime))) {
			fprintf(stderr, "%s: ERROR: writing tags (%s)\n", filenames[i], error);
			free(title_gains);
			free(title_peaks);
			return false;
		}
	}

	free(title_gains);
	free(title_peaks);
	return true;
}