Ejemplo n.º 1
0
/**
 * Write callback. Called when decoder has decoded a single audio frame.
 *
 * @param decoder       Decoder instance
 * @param frame         Decoded frame
 * @param buffer        Array of pointers to decoded channels of data
 * @param client_data   Client data set at initilisation
 *
 * @return Read status
 */
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame, 
    const FLAC__int32* const buffer[], void* client_data)
{
    //TODO write to I2S

#ifdef TO_PORT
	FILE *f = (FILE*)client_data;
	const FLAC__uint32 total_size = (FLAC__uint32)(total_samples * channels * (bps/8));
	size_t i;

	(void)decoder;

	if(total_samples == 0) {
		fprintf(stderr, "ERROR: this example only works for FLAC files that have a total_samples count in STREAMINFO\n");
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
	}
	if(channels != 2 || bps != 16) {
		fprintf(stderr, "ERROR: this example only supports 16bit stereo streams\n");
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
	}

	/* write WAVE header before we write the first frame */
	if(frame->header.number.sample_number == 0) {
		if(
			fwrite("RIFF", 1, 4, f) < 4 ||
			!write_little_endian_uint32(f, total_size + 36) ||
			fwrite("WAVEfmt ", 1, 8, f) < 8 ||
			!write_little_endian_uint32(f, 16) ||
			!write_little_endian_uint16(f, 1) ||
			!write_little_endian_uint16(f, (FLAC__uint16)channels) ||
			!write_little_endian_uint32(f, sample_rate) ||
			!write_little_endian_uint32(f, sample_rate * channels * (bps/8)) ||
			!write_little_endian_uint16(f, (FLAC__uint16)(channels * (bps/8))) || /* block align */
			!write_little_endian_uint16(f, (FLAC__uint16)bps) ||
			fwrite("data", 1, 4, f) < 4 ||
			!write_little_endian_uint32(f, total_size)
		) {
			fprintf(stderr, "ERROR: write error\n");
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
		}
	}

	/* write decoded PCM samples */
	for(i = 0; i < frame->header.blocksize; i++) {
		if(
			!write_little_endian_int16(f, (FLAC__int16)buffer[0][i]) ||  /* left channel */
			!write_little_endian_int16(f, (FLAC__int16)buffer[1][i])     /* right channel */
		) {
			fprintf(stderr, "ERROR: write error\n");
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
		}
	}
#endif
	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
Ejemplo n.º 2
0
/* @@@ not used (yet) */
static FLAC__bool write_little_endian_int32(FILE *f, FLAC__int32 x)
{
	return write_little_endian_uint32(f, (FLAC__uint32)x);
}
Ejemplo n.º 3
0
static FLAC__bool generate_wav(const char *filename, unsigned sample_rate, unsigned channels, unsigned bps, unsigned samples, FLAC__bool strict)
{
	const FLAC__bool waveformatextensible = strict && (channels > 2 || (bps%8));
	/*                                                                 ^^^^^^^
	 * (bps%8) allows 24 bps which is technically supposed to be WAVEFORMATEXTENSIBLE but we
	 * write 24bps as WAVEFORMATEX since it's unambiguous and matches how flac writes it
	 */
	const unsigned true_size = channels * ((bps+7)/8) * samples;
	const unsigned padded_size = (true_size + 1) & (~1u);
	const unsigned shift = (bps%8)? 8 - (bps%8) : 0;
	FILE *f;
	unsigned i;

	if(0 == (f = fopen(filename, mode)))
		return false;
	if(fwrite("RIFF", 1, 4, f) < 4)
		goto foo;
	if(!write_little_endian_uint32(f, padded_size + (waveformatextensible?60:36)))
		goto foo;
	if(fwrite("WAVEfmt ", 1, 8, f) < 8)
		goto foo;
	if(!write_little_endian_uint32(f, waveformatextensible?40:16))
		goto foo;
	if(!write_little_endian_uint16(f, (FLAC__uint16)(waveformatextensible?65534:1)))
		goto foo;
	if(!write_little_endian_uint16(f, (FLAC__uint16)channels))
		goto foo;
	if(!write_little_endian_uint32(f, sample_rate))
		goto foo;
	if(!write_little_endian_uint32(f, sample_rate * channels * ((bps+7)/8)))
		goto foo;
	if(!write_little_endian_uint16(f, (FLAC__uint16)(channels * ((bps+7)/8)))) /* block align */
		goto foo;
	if(!write_little_endian_uint16(f, (FLAC__uint16)(bps+shift)))
		goto foo;
	if(waveformatextensible) {
		if(!write_little_endian_uint16(f, (FLAC__uint16)22)) /* cbSize */
			goto foo;
		if(!write_little_endian_uint16(f, (FLAC__uint16)bps)) /* validBitsPerSample */
			goto foo;
		if(!write_little_endian_uint32(f, 0)) /* channelMask */
			goto foo;
		/* GUID = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} */
		if(fwrite("\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71", 1, 16, f) != 16)
			goto foo;
	}
	if(fwrite("data", 1, 4, f) < 4)
		goto foo;
	if(!write_little_endian_uint32(f, true_size))
		goto foo;

	for(i = 0; i < true_size; i++)
		if(fputc(GET_RANDOM_BYTE<<shift, f) == EOF)
			goto foo;
	for( ; i < padded_size; i++)
		if(fputc(0, f) == EOF)
			goto foo;

	fclose(f);
	return true;
foo:
	fclose(f);
	return false;
}