static bool flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample, GError **error) { if ( !FLAC__stream_encoder_set_compression_level(encoder->fse, encoder->compression)) { g_set_error(error, flac_encoder_quark(), 0, "error setting flac compression to %d", encoder->compression); return false; } if ( !FLAC__stream_encoder_set_channels(encoder->fse, encoder->audio_format.channels)) { g_set_error(error, flac_encoder_quark(), 0, "error setting flac channels num to %d", encoder->audio_format.channels); return false; } if ( !FLAC__stream_encoder_set_bits_per_sample(encoder->fse, bits_per_sample)) { g_set_error(error, flac_encoder_quark(), 0, "error setting flac bit format to %d", bits_per_sample); return false; } if ( !FLAC__stream_encoder_set_sample_rate(encoder->fse, encoder->audio_format.sample_rate)) { g_set_error(error, flac_encoder_quark(), 0, "error setting flac sample rate to %d", encoder->audio_format.sample_rate); return false; } return true; }
static bool flac_encoder_write(struct encoder *_encoder, const void *data, size_t length, G_GNUC_UNUSED GError **error) { struct flac_encoder *encoder = (struct flac_encoder *)_encoder; unsigned num_frames, num_samples; void *exbuffer; const void *buffer = NULL; /* format conversion */ num_frames = length / audio_format_frame_size(&encoder->audio_format); num_samples = num_frames * encoder->audio_format.channels; switch (encoder->audio_format.format) { case SAMPLE_FORMAT_S8: exbuffer = pcm_buffer_get(&encoder->expand_buffer, length*4); pcm8_to_flac(exbuffer, data, num_samples); buffer = exbuffer; break; case SAMPLE_FORMAT_S16: exbuffer = pcm_buffer_get(&encoder->expand_buffer, length*2); pcm16_to_flac(exbuffer, data, num_samples); buffer = exbuffer; break; case SAMPLE_FORMAT_S24_P32: case SAMPLE_FORMAT_S32: /* nothing need to be done; format is the same for both mpd and libFLAC */ buffer = data; break; } /* feed samples to encoder */ if (!FLAC__stream_encoder_process_interleaved(encoder->fse, buffer, num_frames)) { g_set_error(error, flac_encoder_quark(), 0, "flac encoder process failed"); return false; } return true; }
static bool flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format, GError **error) { struct flac_encoder *encoder = (struct flac_encoder *)_encoder; unsigned bits_per_sample; encoder->audio_format = *audio_format; /* FIXME: flac should support 32bit as well */ switch (audio_format->format) { case SAMPLE_FORMAT_S8: bits_per_sample = 8; break; case SAMPLE_FORMAT_S16: bits_per_sample = 16; break; case SAMPLE_FORMAT_S24_P32: bits_per_sample = 24; break; default: bits_per_sample = 24; audio_format->format = SAMPLE_FORMAT_S24_P32; } /* allocate the encoder */ encoder->fse = FLAC__stream_encoder_new(); if (encoder->fse == NULL) { g_set_error(error, flac_encoder_quark(), 0, "flac_new() failed"); return false; } if (!flac_encoder_setup(encoder, bits_per_sample, error)) { FLAC__stream_encoder_delete(encoder->fse); return false; } encoder->buffer_length = 0; pcm_buffer_init(&encoder->buffer); pcm_buffer_init(&encoder->expand_buffer); /* this immediately outputs data through callback */ #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 { FLAC__StreamEncoderState init_status; FLAC__stream_encoder_set_write_callback(encoder->fse, flac_write_callback); init_status = FLAC__stream_encoder_init(encoder->fse); if (init_status != FLAC__STREAM_ENCODER_OK) { g_set_error(error, flac_encoder_quark(), 0, "failed to initialize encoder: %s\n", FLAC__StreamEncoderStateString[init_status]); flac_encoder_close(_encoder); return false; } } #else { FLAC__StreamEncoderInitStatus init_status; init_status = FLAC__stream_encoder_init_stream(encoder->fse, flac_write_callback, NULL, NULL, NULL, encoder); if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { g_set_error(error, flac_encoder_quark(), 0, "failed to initialize encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]); flac_encoder_close(_encoder); return false; } } #endif return true; }