Require AudioStream::mix to return the number of frames successfully mixed
This commit is contained in:
parent
460e0ce314
commit
53843ba872
11 changed files with 68 additions and 29 deletions
|
@ -26,7 +26,7 @@
|
|||
</description>
|
||||
</method>
|
||||
<method name="_mix" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<return type="int" />
|
||||
<argument index="0" name="buffer" type="AudioFrame*" />
|
||||
<argument index="1" name="rate_scale" type="float" />
|
||||
<argument index="2" name="frames" type="int" />
|
||||
|
|
|
@ -37,11 +37,13 @@
|
|||
|
||||
#include "core/io/file_access.h"
|
||||
|
||||
void AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
ERR_FAIL_COND(!active);
|
||||
int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
ERR_FAIL_COND_V(!active, 0);
|
||||
|
||||
int todo = p_frames;
|
||||
|
||||
int frames_mixed_this_step = p_frames;
|
||||
|
||||
while (todo && active) {
|
||||
mp3dec_frame_info_t frame_info;
|
||||
mp3d_sample_t *buf_frame = nullptr;
|
||||
|
@ -60,6 +62,7 @@ void AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
|||
seek(mp3_stream->loop_offset);
|
||||
loops++;
|
||||
} else {
|
||||
frames_mixed_this_step = p_frames - todo;
|
||||
//fill remainder with silence
|
||||
for (int i = p_frames - todo; i < p_frames; i++) {
|
||||
p_buffer[i] = AudioFrame(0, 0);
|
||||
|
@ -69,6 +72,7 @@ void AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return frames_mixed_this_step;
|
||||
}
|
||||
|
||||
float AudioStreamPlaybackMP3::get_stream_sampling_rate() {
|
||||
|
|
|
@ -51,7 +51,7 @@ class AudioStreamPlaybackMP3 : public AudioStreamPlaybackResampled {
|
|||
Ref<AudioStreamMP3> mp3_stream;
|
||||
|
||||
protected:
|
||||
virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) override;
|
||||
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
|
||||
virtual float get_stream_sampling_rate() override;
|
||||
|
||||
public:
|
||||
|
|
|
@ -32,13 +32,15 @@
|
|||
|
||||
#include "core/io/file_access.h"
|
||||
|
||||
void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
ERR_FAIL_COND(!active);
|
||||
int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
ERR_FAIL_COND_V(!active, 0);
|
||||
|
||||
int todo = p_frames;
|
||||
|
||||
int start_buffer = 0;
|
||||
|
||||
int frames_mixed_this_step = p_frames;
|
||||
|
||||
while (todo && active) {
|
||||
float *buffer = (float *)p_buffer;
|
||||
if (start_buffer > 0) {
|
||||
|
@ -64,6 +66,7 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra
|
|||
// we still have buffer to fill, start from this element in the next iteration.
|
||||
start_buffer = p_frames - todo;
|
||||
} else {
|
||||
frames_mixed_this_step = p_frames - todo;
|
||||
for (int i = p_frames - todo; i < p_frames; i++) {
|
||||
p_buffer[i] = AudioFrame(0, 0);
|
||||
}
|
||||
|
@ -72,6 +75,7 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra
|
|||
}
|
||||
}
|
||||
}
|
||||
return frames_mixed_this_step;
|
||||
}
|
||||
|
||||
float AudioStreamPlaybackOGGVorbis::get_stream_sampling_rate() {
|
||||
|
|
|
@ -52,7 +52,7 @@ class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled {
|
|||
Ref<AudioStreamOGGVorbis> vorbis_stream;
|
||||
|
||||
protected:
|
||||
virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) override;
|
||||
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
|
||||
virtual float get_stream_sampling_rate() override;
|
||||
|
||||
public:
|
||||
|
|
|
@ -221,12 +221,12 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds
|
|||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
if (!base->data || !active) {
|
||||
for (int i = 0; i < p_frames; i++) {
|
||||
p_buffer[i] = AudioFrame(0, 0);
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len = base->data_bytes;
|
||||
|
@ -395,12 +395,15 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in
|
|||
}
|
||||
|
||||
if (todo) {
|
||||
int mixed_frames = p_frames - todo;
|
||||
//bit was missing from mix
|
||||
int todo_ofs = p_frames - todo;
|
||||
for (int i = todo_ofs; i < p_frames; i++) {
|
||||
p_buffer[i] = AudioFrame(0, 0);
|
||||
}
|
||||
return mixed_frames;
|
||||
}
|
||||
return p_frames;
|
||||
}
|
||||
|
||||
AudioStreamPlaybackSample::AudioStreamPlaybackSample() {}
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
virtual float get_playback_position() const override;
|
||||
virtual void seek(float p_time) override;
|
||||
|
||||
virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
|
||||
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
|
||||
|
||||
AudioStreamPlaybackSample();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ protected:
|
|||
GDVIRTUAL0RC(int, _get_loop_count)
|
||||
GDVIRTUAL0RC(float, _get_playback_position)
|
||||
GDVIRTUAL1(_seek, float)
|
||||
GDVIRTUAL3(_mix, GDNativePtr<AudioFrame>, float, int)
|
||||
GDVIRTUAL3R(int, _mix, GDNativePtr<AudioFrame>, float, int)
|
||||
public:
|
||||
virtual void start(float p_from_pos = 0.0);
|
||||
virtual void stop();
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
virtual float get_playback_position() const;
|
||||
virtual void seek(float p_time);
|
||||
|
||||
virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
|
||||
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
|
||||
};
|
||||
|
||||
class AudioStreamPlaybackResampled : public AudioStreamPlayback {
|
||||
|
@ -77,15 +77,17 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback {
|
|||
};
|
||||
|
||||
AudioFrame internal_buffer[INTERNAL_BUFFER_LEN + CUBIC_INTERP_HISTORY];
|
||||
unsigned int internal_buffer_end = -1;
|
||||
uint64_t mix_offset;
|
||||
|
||||
protected:
|
||||
void _begin_resample();
|
||||
virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) = 0;
|
||||
// Returns the number of frames that were mixed.
|
||||
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) = 0;
|
||||
virtual float get_stream_sampling_rate() = 0;
|
||||
|
||||
public:
|
||||
virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
|
||||
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
|
||||
|
||||
AudioStreamPlaybackResampled() { mix_offset = 0; }
|
||||
};
|
||||
|
@ -140,11 +142,11 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
|
|||
Ref<AudioStreamMicrophone> microphone;
|
||||
|
||||
protected:
|
||||
virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) override;
|
||||
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
|
||||
virtual float get_stream_sampling_rate() override;
|
||||
|
||||
public:
|
||||
virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
|
||||
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
|
||||
|
||||
virtual void start(float p_from_pos = 0.0) override;
|
||||
virtual void stop() override;
|
||||
|
@ -208,7 +210,7 @@ public:
|
|||
virtual float get_playback_position() const override;
|
||||
virtual void seek(float p_time) override;
|
||||
|
||||
virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
|
||||
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
|
||||
|
||||
~AudioStreamPlaybackRandomPitch();
|
||||
};
|
||||
|
|
|
@ -138,7 +138,7 @@ void AudioStreamGeneratorPlayback::clear_buffer() {
|
|||
mixed = 0;
|
||||
}
|
||||
|
||||
void AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
int AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
int read_amount = buffer.data_left();
|
||||
if (p_frames < read_amount) {
|
||||
read_amount = p_frames;
|
||||
|
@ -156,6 +156,7 @@ void AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_fra
|
|||
}
|
||||
|
||||
mixed += p_frames / generator->get_mix_rate();
|
||||
return read_amount < p_frames ? read_amount : p_frames;
|
||||
}
|
||||
|
||||
float AudioStreamGeneratorPlayback::get_stream_sampling_rate() {
|
||||
|
|
|
@ -67,7 +67,7 @@ class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled {
|
|||
AudioStreamGenerator *generator;
|
||||
|
||||
protected:
|
||||
virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) override;
|
||||
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
|
||||
virtual float get_stream_sampling_rate() override;
|
||||
|
||||
static void _bind_methods();
|
||||
|
|
Loading…
Reference in a new issue