|
@@ -731,16 +731,21 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
|
|
hw_free = hw_free > live ? hw_free - live : 0;
|
|
hw_free = hw_free > live ? hw_free - live : 0;
|
|
frames_out_max = MIN(dead, hw_free);
|
|
frames_out_max = MIN(dead, hw_free);
|
|
sw_max = st_rate_frames_in(sw->rate, frames_out_max);
|
|
sw_max = st_rate_frames_in(sw->rate, frames_out_max);
|
|
- fe_max = MIN(buf_len / sw->info.bytes_per_frame, sw->resample_buf.size);
|
|
|
|
|
|
+ fe_max = MIN(buf_len / sw->info.bytes_per_frame + sw->resample_buf.pos,
|
|
|
|
+ sw->resample_buf.size);
|
|
frames_in_max = MIN(sw_max, fe_max);
|
|
frames_in_max = MIN(sw_max, fe_max);
|
|
|
|
|
|
if (!frames_in_max) {
|
|
if (!frames_in_max) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- sw->conv(sw->resample_buf.buffer, buf, frames_in_max);
|
|
|
|
- if (!sw->hw->pcm_ops->volume_out) {
|
|
|
|
- mixeng_volume(sw->resample_buf.buffer, frames_in_max, &sw->vol);
|
|
|
|
|
|
+ if (frames_in_max > sw->resample_buf.pos) {
|
|
|
|
+ sw->conv(sw->resample_buf.buffer + sw->resample_buf.pos,
|
|
|
|
+ buf, frames_in_max - sw->resample_buf.pos);
|
|
|
|
+ if (!sw->hw->pcm_ops->volume_out) {
|
|
|
|
+ mixeng_volume(sw->resample_buf.buffer + sw->resample_buf.pos,
|
|
|
|
+ frames_in_max - sw->resample_buf.pos, &sw->vol);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max,
|
|
audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max,
|
|
@@ -749,6 +754,22 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
|
|
sw->total_hw_samples_mixed += total_out;
|
|
sw->total_hw_samples_mixed += total_out;
|
|
sw->empty = sw->total_hw_samples_mixed == 0;
|
|
sw->empty = sw->total_hw_samples_mixed == 0;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Upsampling may leave one audio frame in the resample buffer. Decrement
|
|
|
|
+ * total_in by one if there was a leftover frame from the previous resample
|
|
|
|
+ * pass in the resample buffer. Increment total_in by one if the current
|
|
|
|
+ * resample pass left one frame in the resample buffer.
|
|
|
|
+ */
|
|
|
|
+ if (frames_in_max - total_in == 1) {
|
|
|
|
+ /* copy one leftover audio frame to the beginning of the buffer */
|
|
|
|
+ *sw->resample_buf.buffer = *(sw->resample_buf.buffer + total_in);
|
|
|
|
+ total_in += 1 - sw->resample_buf.pos;
|
|
|
|
+ sw->resample_buf.pos = 1;
|
|
|
|
+ } else if (total_in >= sw->resample_buf.pos) {
|
|
|
|
+ total_in -= sw->resample_buf.pos;
|
|
|
|
+ sw->resample_buf.pos = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
#ifdef DEBUG_OUT
|
|
#ifdef DEBUG_OUT
|
|
dolog (
|
|
dolog (
|
|
"%s: write size %zu written %zu total mixed %zu\n",
|
|
"%s: write size %zu written %zu total mixed %zu\n",
|
|
@@ -1155,8 +1176,9 @@ static void audio_run_out (AudioState *s)
|
|
} else {
|
|
} else {
|
|
free = 0;
|
|
free = 0;
|
|
}
|
|
}
|
|
- if (free > 0) {
|
|
|
|
- free = MIN(free, sw->resample_buf.size);
|
|
|
|
|
|
+ if (free > sw->resample_buf.pos) {
|
|
|
|
+ free = MIN(free, sw->resample_buf.size)
|
|
|
|
+ - sw->resample_buf.pos;
|
|
sw->callback.fn(sw->callback.opaque,
|
|
sw->callback.fn(sw->callback.opaque,
|
|
free * sw->info.bytes_per_frame);
|
|
free * sw->info.bytes_per_frame);
|
|
}
|
|
}
|