119 lines
3.4 KiB
C
119 lines
3.4 KiB
C
/*
|
|
* BlueALSA - resampler.h
|
|
* SPDX-FileCopyrightText: 2025 BlueALSA developers
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#pragma once
|
|
#ifndef BLUEALSA_APLAY_RESAMPLER_H_
|
|
#define BLUEALSA_APLAY_RESAMPLER_H_
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <time.h>
|
|
|
|
#include <alsa/asoundlib.h>
|
|
#include <samplerate.h>
|
|
|
|
#include "shared/ffb.h"
|
|
|
|
struct resampler {
|
|
|
|
/* The state and configuration data. */
|
|
SRC_STATE *src_state;
|
|
SRC_DATA src_data;
|
|
|
|
/* Internal buffers for converting from
|
|
* integer to float sample formats. */
|
|
float *in_buffer;
|
|
float *out_buffer;
|
|
|
|
/* The number of channels of the stream. */
|
|
unsigned int channels;
|
|
|
|
/* input sample format */
|
|
snd_pcm_format_t in_format;
|
|
/* output sample format */
|
|
snd_pcm_format_t out_format;
|
|
|
|
/* lower bound on the selected target delay */
|
|
snd_pcm_uframes_t min_target;
|
|
/* upper bound on the selected target delay */
|
|
snd_pcm_uframes_t max_target;
|
|
/* conversion ratio assuming zero timer drift */
|
|
double nominal_rate_ratio;
|
|
/* how many steps above or below nominal rate ratio for next processing iteration */
|
|
int rate_ratio_step_count;
|
|
/* current best estimate of step count to give steady delay value */
|
|
int steady_rate_ratio_step_count;
|
|
/* delay value that conversion tries to achieve */
|
|
snd_pcm_uframes_t target_delay;
|
|
/* variation in delay tolerated without changing number of steps */
|
|
snd_pcm_uframes_t delay_tolerance;
|
|
/* difference between delay and target delay at last processing iteration */
|
|
snd_pcm_sframes_t delay_diff;
|
|
/* upper bound on absolute delay difference before automatic reset */
|
|
snd_pcm_uframes_t max_delay_diff;
|
|
/* total number of input frames processed */
|
|
uintmax_t input_frames;
|
|
/* total number of input frames at time of last rate ratio update */
|
|
uintmax_t last_input_frames;
|
|
/* minimum number of input frames between rate ratio updates */
|
|
snd_pcm_uframes_t period;
|
|
/* timestamp of last resampler reset */
|
|
struct timespec reset_ts;
|
|
/* nominal sample rate of the incoming stream */
|
|
unsigned int in_rate;
|
|
|
|
};
|
|
|
|
enum resampler_converter_type {
|
|
RESAMPLER_CONV_NONE = -1,
|
|
RESAMPLER_CONV_SINC_BEST_QUALITY = SRC_SINC_BEST_QUALITY,
|
|
RESAMPLER_CONV_SINC_MEDIUM_QUALITY = SRC_SINC_MEDIUM_QUALITY,
|
|
RESAMPLER_CONV_SINC_FASTEST = SRC_SINC_FASTEST,
|
|
RESAMPLER_CONV_ZERO_ORDER_HOLD = SRC_ZERO_ORDER_HOLD,
|
|
RESAMPLER_CONV_LINEAR = SRC_LINEAR,
|
|
};
|
|
|
|
bool resampler_is_input_format_supported(snd_pcm_format_t format);
|
|
bool resampler_is_output_format_supported(snd_pcm_format_t format);
|
|
|
|
int resampler_init(
|
|
struct resampler *resampler,
|
|
enum resampler_converter_type type,
|
|
unsigned int channels,
|
|
snd_pcm_format_t in_format,
|
|
unsigned int in_rate,
|
|
snd_pcm_format_t out_format,
|
|
unsigned int out_rate,
|
|
snd_pcm_uframes_t min_target,
|
|
snd_pcm_uframes_t max_target);
|
|
|
|
void resampler_free(
|
|
struct resampler *resampler);
|
|
|
|
int resampler_process(
|
|
struct resampler *resampler,
|
|
ffb_t *in,
|
|
ffb_t *out);
|
|
|
|
void resampler_reset(
|
|
struct resampler *resampler);
|
|
|
|
double resampler_current_rate_ratio(
|
|
const struct resampler *resampler);
|
|
|
|
bool resampler_update_rate_ratio(
|
|
struct resampler *resampler,
|
|
snd_pcm_uframes_t frames_read,
|
|
snd_pcm_uframes_t delay);
|
|
|
|
void resampler_convert_to_native_endian_format(
|
|
void *buffer, size_t len, snd_pcm_format_t format);
|
|
|
|
snd_pcm_format_t resampler_native_endian_format(snd_pcm_format_t format);
|
|
snd_pcm_format_t resampler_preferred_output_format(void);
|
|
|
|
#endif
|