Require AudioStream::mix to return the number of frames successfully mixed
This commit is contained in:
@ -74,11 +74,13 @@ void AudioStreamPlayback::seek(float p_time) {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
if (GDVIRTUAL_CALL(_mix, p_buffer, p_rate_scale, p_frames)) {
|
||||
return;
|
||||
int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
int ret;
|
||||
if (GDVIRTUAL_CALL(_mix, p_buffer, p_rate_scale, p_frames, ret)) {
|
||||
return ret;
|
||||
}
|
||||
WARN_PRINT_ONCE("AudioStreamPlayback::mix unimplemented!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioStreamPlayback::_bind_methods() {
|
||||
@ -103,12 +105,14 @@ void AudioStreamPlaybackResampled::_begin_resample() {
|
||||
mix_offset = 0;
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
float target_rate = AudioServer::get_singleton()->get_mix_rate();
|
||||
float playback_speed_scale = AudioServer::get_singleton()->get_playback_speed_scale();
|
||||
|
||||
uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale * playback_speed_scale) / double(target_rate)) * double(FP_LEN));
|
||||
|
||||
int mixed_frames_total = p_frames;
|
||||
|
||||
for (int i = 0; i < p_frames; i++) {
|
||||
uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS);
|
||||
//standard cubic interpolation (great quality/performance ratio)
|
||||
@ -119,6 +123,11 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
|
||||
AudioFrame y2 = internal_buffer[idx - 1];
|
||||
AudioFrame y3 = internal_buffer[idx - 0];
|
||||
|
||||
if (idx <= internal_buffer_end && idx >= internal_buffer_end && mixed_frames_total == p_frames) {
|
||||
// The internal buffer ends somewhere in this range, and we haven't yet recorded the number of good frames we have.
|
||||
mixed_frames_total = i;
|
||||
}
|
||||
|
||||
float mu2 = mu * mu;
|
||||
AudioFrame a0 = 3 * y1 - 3 * y2 + y3 - y0;
|
||||
AudioFrame a1 = 2 * y0 - 5 * y1 + 4 * y2 - y3;
|
||||
@ -135,7 +144,14 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
|
||||
internal_buffer[2] = internal_buffer[INTERNAL_BUFFER_LEN + 2];
|
||||
internal_buffer[3] = internal_buffer[INTERNAL_BUFFER_LEN + 3];
|
||||
if (is_playing()) {
|
||||
_mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
|
||||
int mixed_frames = _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
|
||||
if (mixed_frames != INTERNAL_BUFFER_LEN) {
|
||||
// internal_buffer[mixed_frames] is the first frame of silence.
|
||||
internal_buffer_end = mixed_frames;
|
||||
} else {
|
||||
// The internal buffer does not contain the first frame of silence.
|
||||
internal_buffer_end = -1;
|
||||
}
|
||||
} else {
|
||||
//fill with silence, not playing
|
||||
for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) {
|
||||
@ -145,6 +161,7 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
|
||||
mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS);
|
||||
}
|
||||
}
|
||||
return mixed_frames_total;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@ -210,7 +227,7 @@ void AudioStreamMicrophone::_bind_methods() {
|
||||
AudioStreamMicrophone::AudioStreamMicrophone() {
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
int AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
AudioDriver::get_singleton()->lock();
|
||||
|
||||
Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer();
|
||||
@ -221,6 +238,8 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
|
||||
unsigned int input_position = AudioDriver::get_singleton()->get_input_position();
|
||||
#endif
|
||||
|
||||
int mixed_frames = p_frames;
|
||||
|
||||
if (playback_delay > input_size) {
|
||||
for (int i = 0; i < p_frames; i++) {
|
||||
p_buffer[i] = AudioFrame(0.0f, 0.0f);
|
||||
@ -240,6 +259,9 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
|
||||
|
||||
p_buffer[i] = AudioFrame(l, r);
|
||||
} else {
|
||||
if (mixed_frames == p_frames) {
|
||||
mixed_frames = i;
|
||||
}
|
||||
p_buffer[i] = AudioFrame(0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
@ -252,10 +274,12 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
|
||||
#endif
|
||||
|
||||
AudioDriver::get_singleton()->unlock();
|
||||
|
||||
return mixed_frames;
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames);
|
||||
int AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
return AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames);
|
||||
}
|
||||
|
||||
float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() {
|
||||
@ -428,13 +452,14 @@ void AudioStreamPlaybackRandomPitch::seek(float p_time) {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
int AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
if (playing.is_valid()) {
|
||||
playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
|
||||
return playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
|
||||
} else {
|
||||
for (int i = 0; i < p_frames; i++) {
|
||||
p_buffer[i] = AudioFrame(0, 0);
|
||||
}
|
||||
return p_frames;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user