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; }
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; }
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; }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }