const int32_t *
pcm_resample_lsr_32(struct pcm_resample_state *state,
		    uint8_t channels,
		    unsigned src_rate,
		    const int32_t *src_buffer, size_t src_size,
		    unsigned dest_rate, size_t *dest_size_r,
		    GError **error_r)
{
	bool success;
	SRC_DATA *data = &state->data;
	size_t data_in_size;
	size_t data_out_size;
	int error;
	int32_t *dest_buffer;

	assert((src_size % (sizeof(*src_buffer) * channels)) == 0);

	success = pcm_resample_set(state, channels, src_rate, dest_rate,
				   error_r);
	if (!success)
		return NULL;

	/* there was an error previously, and nothing has changed */
	if (state->error) {
		g_set_error(error_r, libsamplerate_quark(), state->error,
			    "libsamplerate has failed: %s",
			    src_strerror(state->error));
		return NULL;
	}

	data->input_frames = src_size / sizeof(*src_buffer) / channels;
	data_in_size = data->input_frames * sizeof(float) * channels;
	data->data_in = pcm_buffer_get(&state->in, data_in_size);

	data->output_frames = (src_size * dest_rate + src_rate - 1) / src_rate;
	data_out_size = data->output_frames * sizeof(float) * channels;
	data->data_out = pcm_buffer_get(&state->out, data_out_size);

	src_int_to_float_array(src_buffer, data->data_in,
			       data->input_frames * channels);

	error = src_process(state->state, data);
	if (error) {
		g_set_error(error_r, libsamplerate_quark(), error,
			    "libsamplerate has failed: %s",
			    src_strerror(error));
		state->error = error;
		return NULL;
	}

	*dest_size_r = data->output_frames_gen *
		sizeof(*dest_buffer) * channels;
	dest_buffer = pcm_buffer_get(&state->buffer, *dest_size_r);
	src_float_to_int_array(data->data_out, dest_buffer,
			       data->output_frames_gen * channels);

	return dest_buffer;
}
const int32_t *
pcm_convert_to_32(struct pcm_buffer *buffer,
		  enum sample_format src_format, const void *src,
		  size_t src_size, size_t *dest_size_r)
{
	unsigned num_samples;
	int32_t *dest;

	switch (src_format) {
	case SAMPLE_FORMAT_UNDEFINED:
		break;

	case SAMPLE_FORMAT_S8:
		num_samples = src_size;
		*dest_size_r = src_size * sizeof(*dest);
		dest = pcm_buffer_get(buffer, *dest_size_r);

		pcm_convert_8_to_32(dest, (const int8_t *)src,
				    num_samples);
		return dest;

	case SAMPLE_FORMAT_S16:
		num_samples = src_size / 2;
		*dest_size_r = num_samples * sizeof(*dest);
		dest = pcm_buffer_get(buffer, *dest_size_r);

		pcm_convert_16_to_32(dest, (const int16_t *)src,
				     num_samples);
		return dest;

	case SAMPLE_FORMAT_S24:
		/* convert to S24_P32 first */
		num_samples = src_size / 3;

		dest = pcm_convert_24_to_24p32(buffer, src, num_samples);

		/* convert to 32 bit in-place */
		*dest_size_r = num_samples * sizeof(*dest);
		pcm_convert_24_to_32(dest, dest, num_samples);
		return dest;

	case SAMPLE_FORMAT_S24_P32:
		num_samples = src_size / 4;
		*dest_size_r = num_samples * sizeof(*dest);
		dest = pcm_buffer_get(buffer, *dest_size_r);

		pcm_convert_24_to_32(dest, (const int32_t *)src,
				     num_samples);
		return dest;

	case SAMPLE_FORMAT_S32:
		*dest_size_r = src_size;
		return src;
	}

	return NULL;
}
Esempio n. 3
0
const float *
pcm_dsd_to_float(struct pcm_dsd *dsd, unsigned channels, bool lsbfirst,
		 const uint8_t *src, size_t src_size,
		 size_t *dest_size_r)
{
	assert(dsd != NULL);
	assert(src != NULL);
	assert(src_size > 0);
	assert(src_size % channels == 0);
	assert(channels <= G_N_ELEMENTS(dsd->dsd2pcm));

	const unsigned num_samples = src_size;
	const unsigned num_frames = src_size / channels;

	float *dest;
	const size_t dest_size = num_samples * sizeof(*dest);
	*dest_size_r = dest_size;
	dest = pcm_buffer_get(&dsd->buffer, dest_size);

	for (unsigned c = 0; c < channels; ++c) {
		if (dsd->dsd2pcm[c] == NULL) {
			dsd->dsd2pcm[c] = dsd2pcm_init();
			if (dsd->dsd2pcm[c] == NULL)
				return NULL;
		}

		dsd2pcm_translate(dsd->dsd2pcm[c], num_frames,
				  src + c, channels,
				  lsbfirst, dest + c, channels);
	}

	return dest;
}
const float *
pcm_resample_lsr_float(struct pcm_resample_state *state,
		       unsigned channels,
		       unsigned src_rate,
		       const float *src_buffer, size_t src_size,
		       unsigned dest_rate, size_t *dest_size_r,
		       GError **error_r)
{
	assert((src_size % (sizeof(*src_buffer) * channels)) == 0);

	if (!pcm_resample_set(state, channels, src_rate, dest_rate, error_r))
		return NULL;

	SRC_DATA *data = &state->data;
	data->input_frames = src_size / sizeof(*src_buffer) / channels;
	data->data_in = deconst_float_buffer(src_buffer);

	data->output_frames = (src_size * dest_rate + src_rate - 1) / src_rate;
	size_t data_out_size = data->output_frames * sizeof(float) * channels;
	data->data_out = pcm_buffer_get(&state->out, data_out_size);

	if (!lsr_process(state, error_r))
		return NULL;

	*dest_size_r = data->output_frames_gen *
		sizeof(*data->data_out) * channels;
	return data->data_out;
}
/**
 * Convert to 24 bit packed samples (aka S24_3LE / S24_3BE).
 */
static const void *
pcm_convert_24_packed(struct pcm_convert_state *state,
		      const struct audio_format *src_format,
		      const void *src_buffer, size_t src_size,
		      const struct audio_format *dest_format,
		      size_t *dest_size_r,
		      GError **error_r)
{
	assert(dest_format->format == SAMPLE_FORMAT_S24);

	/* use the normal 24 bit conversion first */

	struct audio_format audio_format;
	audio_format_init(&audio_format, dest_format->sample_rate,
			  SAMPLE_FORMAT_S24_P32, dest_format->channels);

	const int32_t *buffer;
	size_t buffer_size;

	buffer = pcm_convert_24(state, src_format, src_buffer, src_size,
				&audio_format, &buffer_size, error_r);
	if (buffer == NULL)
		return NULL;

	/* now convert to packed 24 bit */

	unsigned num_samples = buffer_size / 4;
	size_t dest_size = num_samples * 3;

	uint8_t *dest = pcm_buffer_get(&state->pack_buffer, dest_size);
	pcm_pack_24(dest, buffer, num_samples, dest_format->reverse_endian);

	*dest_size_r = dest_size;
	return dest;
}
Esempio n. 6
0
const int16_t *
pcm_convert_channels_16(struct pcm_buffer *buffer,
			int8_t dest_channels,
			int8_t src_channels, const int16_t *src,
			size_t src_size, size_t *dest_size_r)
{
	unsigned num_frames = src_size / src_channels / sizeof(*src);
	unsigned dest_size = num_frames * dest_channels * sizeof(*src);
	int16_t *dest = pcm_buffer_get(buffer, dest_size);

	*dest_size_r = dest_size;

	if (src_channels == 1 && dest_channels == 2)
		pcm_convert_channels_16_1_to_2(dest, src, num_frames);
	else if (src_channels == 2 && dest_channels == 1)
		pcm_convert_channels_16_2_to_1(dest, src, num_frames);
	else if (dest_channels == 2)
		pcm_convert_channels_16_n_to_2(dest, src_channels, src,
					       num_frames);
	else {
		g_warning("conversion %u->%u channels is not supported",
			  src_channels, dest_channels);
		return NULL;
	}

	return dest;
}
Esempio n. 7
0
/**
 * Copy data into a buffer, and prepare the wave header.
 */
static bool
winmm_set_buffer(struct winmm_output *wo, struct winmm_buffer *buffer,
		 const void *data, size_t size,
		 GError **error_r)
{
	void *dest = pcm_buffer_get(&buffer->buffer, size);
	if (dest == NULL) {
		g_set_error(error_r, winmm_output_quark(), 0,
			    "Out of memory");
		return false;
	}

	memcpy(dest, data, size);

	memset(&buffer->hdr, 0, sizeof(buffer->hdr));
	buffer->hdr.lpData = dest;
	buffer->hdr.dwBufferLength = size;

	MMRESULT result = waveOutPrepareHeader(wo->handle, &buffer->hdr,
					       sizeof(buffer->hdr));
	if (result != MMSYSERR_NOERROR) {
		g_set_error(error_r, winmm_output_quark(), result,
			    "waveOutPrepareHeader() failed");
		return false;
	}

	return true;
}
Esempio n. 8
0
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 int32_t *
pcm_convert_24_to_24p32(struct pcm_buffer *buffer, const uint8_t *src,
			unsigned num_samples)
{
	int32_t *dest = pcm_buffer_get(buffer, num_samples * 4);
	pcm_unpack_24(dest, src, num_samples, false);
	return dest;
}
Esempio n. 10
0
static const void *
route_filter_filter(struct filter *_filter,
		   const void *src, size_t src_size,
		   size_t *dest_size_r, G_GNUC_UNUSED GError **error_r)
{
	struct route_filter *filter = (struct route_filter *)_filter;

	size_t number_of_frames = src_size / filter->input_frame_size;

	size_t bytes_per_frame_per_channel =
		audio_format_sample_size(&filter->input_format);

	// A moving pointer that always refers to channel 0 in the input, at the currently handled frame
	const uint8_t *base_source = src;

	// A moving pointer that always refers to the currently filled channel of the currently handled frame, in the output
	uint8_t *chan_destination;

	// Grow our reusable buffer, if needed, and set the moving pointer
	*dest_size_r = number_of_frames * filter->output_frame_size;
	chan_destination = pcm_buffer_get(&filter->output_buffer, *dest_size_r);


	// Perform our copy operations, with N input channels and M output channels
	for (unsigned int s=0; s<number_of_frames; ++s) {

		// Need to perform one copy per output channel
		for (unsigned int c=0; c<filter->min_output_channels; ++c) {
			if (filter->sources[c] == -1 ||
			    (unsigned)filter->sources[c] >= filter->input_format.channels) {
				// No source for this destination output,
				// give it zeroes as input
				memset(chan_destination,
					0x00,
					bytes_per_frame_per_channel);
			} else {
				// Get the data from channel sources[c]
				// and copy it to the output
				const uint8_t *data = base_source +
					(filter->sources[c] * bytes_per_frame_per_channel);
				memcpy(chan_destination,
					  data,
					  bytes_per_frame_per_channel);
			}
			// Move on to the next output channel
			chan_destination += bytes_per_frame_per_channel;
		}


		// Go on to the next N input samples
		base_source += filter->input_frame_size;
	}

	// Here it is, ladies and gentlemen! Rerouted data!
	return (void *) filter->output_buffer.buffer;
}
const int32_t *
pcm_resample_lsr_32(struct pcm_resample_state *state,
		    unsigned channels,
		    unsigned src_rate,
		    const int32_t *src_buffer, size_t src_size,
		    unsigned dest_rate, size_t *dest_size_r,
		    GError **error_r)
{
	bool success;
	SRC_DATA *data = &state->data;
	size_t data_in_size;
	size_t data_out_size;
	int32_t *dest_buffer;

	assert((src_size % (sizeof(*src_buffer) * channels)) == 0);

	success = pcm_resample_set(state, channels, src_rate, dest_rate,
				   error_r);
	if (!success)
		return NULL;

	data->input_frames = src_size / sizeof(*src_buffer) / channels;
	data_in_size = data->input_frames * sizeof(float) * channels;
	data->data_in = pcm_buffer_get(&state->in, data_in_size);

	data->output_frames = (src_size * dest_rate + src_rate - 1) / src_rate;
	data_out_size = data->output_frames * sizeof(float) * channels;
	data->data_out = pcm_buffer_get(&state->out, data_out_size);

	src_int_to_float_array(src_buffer, data->data_in,
			       data->input_frames * channels);

	if (!lsr_process(state, error_r))
		return NULL;

	*dest_size_r = data->output_frames_gen *
		sizeof(*dest_buffer) * channels;
	dest_buffer = pcm_buffer_get(&state->buffer, *dest_size_r);
	src_float_to_int_array(data->data_out, dest_buffer,
			       data->output_frames_gen * channels);

	return dest_buffer;
}
static bool
null_encoder_write(struct encoder *_encoder,
		   const void *data, size_t length,
		   G_GNUC_UNUSED GError **error)
{
	struct null_encoder *encoder = (struct null_encoder *)_encoder;
	char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length + length);

	memcpy(buffer+encoder->buffer_length, data, length);

	encoder->buffer_length += length;
	return true;
}
Esempio n. 13
0
static const void *
replay_gain_filter_filter(struct filter *_filter,
			  const void *src, size_t src_size,
			  size_t *dest_size_r, GError **error_r)
{
	struct replay_gain_filter *filter =
		(struct replay_gain_filter *)_filter;
	bool success;
	void *dest;
	enum replay_gain_mode rg_mode;

	/* check if the mode has been changed since the last call */
	rg_mode = replay_gain_get_real_mode();

	if (filter->mode != rg_mode) {
		g_debug("replay gain mode has changed %d->%d\n", filter->mode, rg_mode);
		filter->mode = rg_mode;
		replay_gain_filter_update(filter);
	}

	*dest_size_r = src_size;

	if (filter->volume == PCM_VOLUME_1)
		/* optimized special case: 100% volume = no-op */
		return src;

	dest = pcm_buffer_get(&filter->buffer, src_size);

	if (filter->volume <= 0) {
		/* optimized special case: 0% volume = memset(0) */
		/* XXX is this valid for all sample formats? What
		   about floating point? */
		memset(dest, 0, src_size);
		return dest;
	}

	memcpy(dest, src, src_size);

	success = pcm_volume(dest, src_size, &filter->audio_format,
			     filter->volume);
	if (!success) {
		g_set_error(error_r, replay_gain_quark(), 0,
			    "pcm_volume() has failed");
		return NULL;
	}

	return dest;
}
static size_t
null_encoder_read(struct encoder *_encoder, void *dest, size_t length)
{
	struct null_encoder *encoder = (struct null_encoder *)_encoder;
	char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length);

	if (length > encoder->buffer_length)
		length = encoder->buffer_length;

	memcpy(dest, buffer, length);

	encoder->buffer_length -= length;
	memmove(buffer, buffer + length, encoder->buffer_length);

	return length;
}
Esempio n. 15
0
const int32_t *pcm_byteswap_32(struct pcm_buffer *buffer,
			       const int32_t *src, size_t len)
{
	int32_t *buf = pcm_buffer_get(buffer, len);

	assert(buf != NULL);

	const int32_t *src_end = src + len / sizeof(*src);
	int32_t *dest = buf;
	while (src < src_end) {
		const int32_t x = *src++;
		*dest++ = GUINT32_SWAP_LE_BE(x);
	}

	return buf;
}
Esempio n. 16
0
static const void *
normalize_filter_filter(struct filter *_filter,
			const void *src, size_t src_size, size_t *dest_size_r,
			G_GNUC_UNUSED GError **error_r)
{
	struct normalize_filter *filter = (struct normalize_filter *)_filter;
	void *dest;

	dest = pcm_buffer_get(&filter->buffer, src_size);

	memcpy(dest, src, src_size);

	Compressor_Process_int16(filter->compressor, dest, src_size / 2);

	*dest_size_r = src_size;
	return dest;
}
static bool
wave_encoder_open(struct encoder *_encoder,
		  G_GNUC_UNUSED struct audio_format *audio_format,
		  G_GNUC_UNUSED GError **error)
{
	struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
	void *buffer;

	assert(audio_format_valid(audio_format));

	switch (audio_format->format) {
	case SAMPLE_FORMAT_S8:
		encoder->bits = 8;
		break;

	case SAMPLE_FORMAT_S16:
		encoder->bits = 16;
		break;

	case SAMPLE_FORMAT_S24_P32:
		encoder->bits = 24;
		break;

	case SAMPLE_FORMAT_S32:
		encoder->bits = 32;
		break;

	default:
		audio_format->format = SAMPLE_FORMAT_S16;
		encoder->bits = 16;
		break;
	}

	buffer = pcm_buffer_get(&encoder->buffer, sizeof(struct wave_header) );

	/* create PCM wave header in initial buffer */
	fill_wave_header((struct wave_header *) buffer, 
			audio_format->channels,
			 encoder->bits,
			audio_format->sample_rate,
			 (encoder->bits / 8) * audio_format->channels );

	encoder->buffer_length = sizeof(struct wave_header);
	return true;
}
Esempio n. 18
0
FLAC__StreamDecoderWriteStatus
flac_common_write(struct flac_data *data, const FLAC__Frame * frame,
		  const FLAC__int32 *const buf[],
		  FLAC__uint64 nbytes)
{
	enum decoder_command cmd;
	void *buffer;
	unsigned bit_rate;

	if (!data->initialized && !flac_got_first_frame(data, &frame->header))
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;

	size_t buffer_size = frame->header.blocksize * data->frame_size;
	buffer = pcm_buffer_get(&data->buffer, buffer_size);

	flac_convert(buffer, frame->header.channels,
		     data->audio_format.format, buf,
		     0, frame->header.blocksize);

	if (nbytes > 0)
		bit_rate = nbytes * 8 * frame->header.sample_rate /
			(1000 * frame->header.blocksize);
	else
		bit_rate = 0;

	cmd = decoder_data(data->decoder, data->input_stream,
			   buffer, buffer_size,
			   bit_rate);
	data->next_frame += frame->header.blocksize;
	switch (cmd) {
	case DECODE_COMMAND_NONE:
	case DECODE_COMMAND_START:
		break;

	case DECODE_COMMAND_STOP:
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;

	case DECODE_COMMAND_SEEK:
		return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
	}

	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
Esempio n. 19
0
static FLAC__StreamEncoderWriteStatus
flac_write_callback(G_GNUC_UNUSED const FLAC__StreamEncoder *fse,
		    const FLAC__byte data[],
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
		    unsigned bytes,
#else
		    size_t bytes,
#endif
		    G_GNUC_UNUSED unsigned samples,
	G_GNUC_UNUSED unsigned current_frame, void *client_data)
{
	struct flac_encoder *encoder = (struct flac_encoder *) client_data;

	char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length + bytes);

	//transfer data to buffer
	memcpy( buffer + encoder->buffer_length, data, bytes);
	encoder->buffer_length += bytes;

	return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
Esempio n. 20
0
const int32_t *
pcm_resample_fallback_32(struct pcm_resample_state *state,
			 uint8_t channels,
			 unsigned src_rate,
			 const int32_t *src_buffer, size_t src_size,
			 unsigned dest_rate,
			 size_t *dest_size_r)
{
	unsigned src_pos, dest_pos = 0;
	unsigned src_frames = src_size / channels / sizeof(*src_buffer);
	unsigned dest_frames =
		(src_frames * dest_rate + src_rate - 1) / src_rate;
	unsigned dest_samples = dest_frames * channels;
	size_t dest_size = dest_samples * sizeof(*src_buffer);
	int32_t *dest_buffer = pcm_buffer_get(&state->buffer, dest_size);

	assert((src_size % (sizeof(*src_buffer) * channels)) == 0);

	switch (channels) {
	case 1:
		while (dest_pos < dest_samples) {
			src_pos = dest_pos * src_rate / dest_rate;

			dest_buffer[dest_pos++] = src_buffer[src_pos];
		}
		break;
	case 2:
		while (dest_pos < dest_samples) {
			src_pos = dest_pos * src_rate / dest_rate;
			src_pos &= ~1;

			dest_buffer[dest_pos++] = src_buffer[src_pos];
			dest_buffer[dest_pos++] = src_buffer[src_pos + 1];
		}
		break;
	}

	*dest_size_r = dest_size;
	return dest_buffer;
}
Esempio n. 21
0
static const void *
volume_filter_filter(struct filter *_filter, const void *src, size_t src_size,
		     size_t *dest_size_r, GError **error_r)
{
	struct volume_filter *filter = (struct volume_filter *)_filter;
	bool success;
	void *dest;

	*dest_size_r = src_size;

	if (filter->volume >= PCM_VOLUME_1)
		/* optimized special case: 100% volume = no-op */
		return src;

	dest = pcm_buffer_get(&filter->buffer, src_size);

	if (filter->volume <= 0) {
		/* optimized special case: 0% volume = memset(0) */
		/* XXX is this valid for all sample formats? What
		   about floating point? */
		memset(dest, 0, src_size);
		return dest;
	}

	memcpy(dest, src, src_size);

	success = pcm_volume(dest, src_size, filter->audio_format.format,
			     filter->volume);
	if (!success) {
		g_set_error(error_r, volume_quark(), 0,
			    "pcm_volume() has failed");
		return NULL;
	}

	return dest;
}
Esempio n. 22
0
static const char *
ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
                size_t *length_r)
{
    GError *error = NULL;

    size_t length;
    const char *data = ao_chunk_data(ao, chunk, ao->replay_gain_filter,
                                     &ao->replay_gain_serial, &length);
    if (data == NULL)
        return NULL;

    if (length == 0) {
        /* empty chunk, nothing to do */
        *length_r = 0;
        return data;
    }

    /* cross-fade */

    if (chunk->other != NULL) {
        size_t other_length;
        const char *other_data =
            ao_chunk_data(ao, chunk->other,
                          ao->other_replay_gain_filter,
                          &ao->other_replay_gain_serial,
                          &other_length);
        if (other_data == NULL)
            return NULL;

        if (other_length == 0) {
            *length_r = 0;
            return data;
        }

        /* if the "other" chunk is longer, then that trailer
           is used as-is, without mixing; it is part of the
           "next" song being faded in, and if there's a rest,
           it means cross-fading ends here */

        if (length > other_length)
            length = other_length;

        char *dest = pcm_buffer_get(&ao->cross_fade_buffer,
                                    other_length);
        memcpy(dest, other_data, other_length);
        pcm_mix(dest, data, length, &ao->in_audio_format,
                1.0 - chunk->mix_ratio);

        data = dest;
        length = other_length;
    }

    /* apply filter chain */

    data = filter_filter(ao->filter, data, length, &length, &error);
    if (data == NULL) {
        g_warning("\"%s\" [%s] failed to filter: %s",
                  ao->name, ao->plugin->name, error->message);
        g_error_free(error);
        return NULL;
    }

    *length_r = length;
    return data;
}