@@ -673,11 +673,44 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
/*
* Soft voice (playback)
*/
+static void audio_pcm_sw_resample_out(SWVoiceOut *sw,
+ size_t frames_in_max, size_t frames_out_max,
+ size_t *total_in, size_t *total_out)
+{
+ HWVoiceOut *hw = sw->hw;
+ struct st_sample *src, *dst;
+ size_t live, wpos, frames_in, frames_out;
+
+ live = sw->total_hw_samples_mixed;
+ wpos = (hw->mix_buf.pos + live) % hw->mix_buf.size;
+
+ /* write to mix_buf from wpos to end of buffer */
+ src = sw->resample_buf.buffer;
+ frames_in = frames_in_max;
+ dst = hw->mix_buf.buffer + wpos;
+ frames_out = MIN(frames_out_max, hw->mix_buf.size - wpos);
+ st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
+ wpos += frames_out;
+ *total_in = frames_in;
+ *total_out = frames_out;
+
+ /* write to mix_buf from start of buffer if there are input frames left */
+ if (frames_in_max - frames_in > 0 && wpos == hw->mix_buf.size) {
+ src += frames_in;
+ frames_in = frames_in_max - frames_in;
+ dst = hw->mix_buf.buffer;
+ frames_out = frames_out_max - frames_out;
+ st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
+ *total_in += frames_in;
+ *total_out += frames_out;
+ }
+}
+
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
{
- size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
+ size_t hwsamples, samples, live, dead;
size_t hw_free;
- size_t ret = 0, pos = 0, total = 0;
+ size_t ret, total;
if (!sw) {
return size;
@@ -698,8 +731,6 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
return 0;
}
- wpos = (sw->hw->mix_buf.pos + live) % hwsamples;
-
dead = hwsamples - live;
hw_free = audio_pcm_hw_get_free(sw->hw);
hw_free = hw_free > live ? hw_free - live : 0;
@@ -713,29 +744,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
}
}
- while (samples) {
- dead = hwsamples - live;
- left = hwsamples - wpos;
- blck = MIN (dead, left);
- if (!blck) {
- break;
- }
- isamp = samples;
- osamp = blck;
- st_rate_flow_mix (
- sw->rate,
- sw->resample_buf.buffer + pos,
- sw->hw->mix_buf.buffer + wpos,
- &isamp,
- &osamp
- );
- ret += isamp;
- samples -= isamp;
- pos += isamp;
- live += osamp;
- wpos = (wpos + osamp) % hwsamples;
- total += osamp;
- }
+ audio_pcm_sw_resample_out(sw, samples, MIN(dead, hw_free), &ret, &total);
sw->total_hw_samples_mixed += total;
sw->empty = sw->total_hw_samples_mixed == 0;