Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion audio/audio_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ audio_driver_t audio_null = {
NULL,
NULL,
NULL, /* write_avail */
NULL /* buffer_size */
NULL, /* buffer_size */
NULL /* write_raw */
};

audio_driver_t *audio_drivers[] = {
Expand Down Expand Up @@ -456,6 +457,45 @@ static void audio_driver_flush(audio_driver_state_t *audio_st,
? 0.0f
: audio_st->volume_gain;

/* Fast path: if driver handles resampling and no DSP/mixer is active,
* bypass software resampling entirely. */
if (audio_st->current_audio->write_raw
#ifdef HAVE_DSP_FILTER
&& !audio_st->dsp
#endif
#ifdef HAVE_AUDIOMIXER
&& audio_st->mixer_streams_playing == 0
#endif
)
{
size_t frames = samples >> 1;
double rate_adjust = 1.0;
unsigned input_rate = (unsigned)audio_st->input;

/* Rate control for A/V sync */
if (audio_st->flags & AUDIO_FLAG_CONTROL)
{
unsigned write_idx =
audio_st->free_samples_count++ & (AUDIO_BUFFER_FREE_SAMPLES_COUNT - 1);
int avail = (int)audio_st->current_audio->write_avail(
audio_st->context_audio_data);
int half_size = (int)(audio_st->buffer_size / 2);
int delta_mid = avail - half_size;
double direction = (double)delta_mid / half_size;

audio_st->free_samples_buf[write_idx] = avail;
rate_adjust = 1.0 + audio_st->rate_control_delta * direction;
}

if (is_slowmotion)
rate_adjust *= slowmotion_ratio;

/* Note: mute/volume is not applied here - driver must handle or ignore */
audio_st->current_audio->write_raw(audio_st->context_audio_data,
data, frames, input_rate, rate_adjust);
return;
}

src_data.data_out = NULL;
src_data.output_frames = 0;
/* We'll assign a proper output to the resampler later in this function */
Expand Down Expand Up @@ -1121,6 +1161,8 @@ static void audio_mixer_play_stop_cb(
audio_driver_st.mixer_streams[i].stop_cb = NULL;
audio_driver_st.mixer_streams[i].handle = NULL;
audio_driver_st.mixer_streams[i].voice = NULL;
if (audio_driver_st.mixer_streams_playing > 0)
audio_driver_st.mixer_streams_playing--;
}
break;
case AUDIO_MIXER_SOUND_STOPPED:
Expand All @@ -1143,6 +1185,8 @@ static void audio_mixer_menu_stop_cb(
unsigned i = (unsigned)idx;
audio_driver_st.mixer_streams[i].state = AUDIO_STREAM_STATE_STOPPED;
audio_driver_st.mixer_streams[i].volume = 0.0f;
if (audio_driver_st.mixer_streams_playing > 0)
audio_driver_st.mixer_streams_playing--;
}
break;
case AUDIO_MIXER_SOUND_STOPPED:
Expand Down Expand Up @@ -1180,6 +1224,8 @@ static void audio_mixer_play_stop_sequential_cb(
audio_driver_st.mixer_streams[i].stop_cb = NULL;
audio_driver_st.mixer_streams[i].handle = NULL;
audio_driver_st.mixer_streams[i].voice = NULL;
if (audio_driver_st.mixer_streams_playing > 0)
audio_driver_st.mixer_streams_playing--;

i++;

Expand Down Expand Up @@ -1330,6 +1376,11 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
audio_driver_st.mixer_streams[free_slot].volume = params->volume;
audio_driver_st.mixer_streams[free_slot].stop_cb = stop_cb;

if ( params->state == AUDIO_STREAM_STATE_PLAYING
|| params->state == AUDIO_STREAM_STATE_PLAYING_LOOPED
|| params->state == AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL)
audio_driver_st.mixer_streams_playing++;

return true;
}

Expand Down Expand Up @@ -1357,6 +1408,7 @@ static void audio_driver_mixer_play_stream_internal(
audio_driver_st.resampler_quality,
audio_driver_st.mixer_streams[i].stop_cb);
audio_driver_st.mixer_streams[i].state = (enum audio_mixer_state)type;
audio_driver_st.mixer_streams_playing++;
break;
case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED:
Expand Down Expand Up @@ -1591,6 +1643,8 @@ void audio_driver_mixer_stop_stream(unsigned i)
audio_mixer_stop(voice);
audio_driver_st.mixer_streams[i].state = AUDIO_STREAM_STATE_STOPPED;
audio_driver_st.mixer_streams[i].volume = 1.0f;
if (audio_driver_st.mixer_streams_playing > 0)
audio_driver_st.mixer_streams_playing--;
}
break;
case AUDIO_STREAM_STATE_STOPPED:
Expand Down
17 changes: 17 additions & 0 deletions audio/audio_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,22 @@ typedef struct audio_driver
size_t (*write_avail)(void *data);

size_t (*buffer_size)(void *data);

/**
* Optional. Write raw int16 samples with resampling handled by driver.
* If non-NULL, audio_driver will call this instead of doing software
* resampling. The driver is responsible for resampling from input_rate
* to its output rate, applying the rate_adjust factor for A/V sync.
*
* @param data Driver context
* @param samples Interleaved int16 stereo samples (LRLRLR...)
* @param frames Number of frames (pairs of samples)
* @param input_rate Source sample rate in Hz
* @param rate_adjust Rate adjustment multiplier for A/V sync (1.0 = normal)
* @return Number of frames written, or -1 on error
*/
ssize_t (*write_raw)(void *data, const int16_t *samples, size_t frames,
unsigned input_rate, double rate_adjust);
} audio_driver_t;

typedef struct
Expand Down Expand Up @@ -247,6 +263,7 @@ typedef struct
bool mute_enable;
#ifdef HAVE_AUDIOMIXER
bool mixer_mute_enable;
uint8_t mixer_streams_playing; /* Count of currently playing mixer streams */
#endif

/* Sample the flush delta-time when fast forwarding to find the correct ratio. */
Expand Down
1 change: 1 addition & 0 deletions audio/drivers/alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,4 +539,5 @@ audio_driver_t audio_alsa = {
alsa_device_list_free,
alsa_write_avail,
alsa_buffer_size,
NULL /* write_raw */
};
1 change: 1 addition & 0 deletions audio/drivers/alsa_qsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,5 @@ audio_driver_t audio_alsa = {
NULL,
alsa_qsa_write_avail,
alsa_qsa_buffer_size,
NULL /* write_raw */
};
3 changes: 2 additions & 1 deletion audio/drivers/alsathread.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,5 +673,6 @@ audio_driver_t audio_alsathread = {
alsa_device_list_new, /* Reusing these functions from alsa.c */
alsa_device_list_free, /* because they don't use the driver context */
alsa_thread_write_avail,
alsa_thread_buffer_size
alsa_thread_buffer_size,
NULL /* write_raw */
};
1 change: 1 addition & 0 deletions audio/drivers/audioio.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,5 @@ audio_driver_t audio_audioio = {
NULL,
audioio_write_avail,
audioio_buffer_size,
NULL /* write_raw */
};
3 changes: 2 additions & 1 deletion audio/drivers/audioworklet.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,5 +533,6 @@ audio_driver_t audio_audioworklet = {
NULL,
NULL,
audioworklet_write_avail,
audioworklet_buffer_size
audioworklet_buffer_size,
NULL /* write_raw */
};
Loading
Loading