HOLY FUCK I FIXED THIS BUG

Turns out I was mutiating timeOffset in each loop iteration instead of just pre-computing the pre-pitched timeoffset once before setting it, so these mutations added up,

Also there was something to do with the fact that SynchedSoundStream should be informed of a pitch change *before* asking it to update the streams
This commit is contained in:
Stepland 2022-10-06 00:43:17 +02:00
parent 6555cb168e
commit 68e6eaff32
3 changed files with 28 additions and 15 deletions

View File

@ -70,8 +70,8 @@ void SyncedSoundStreams::change_streams(std::function<void()> callback) {
callback();
reload_sources();
setPlayingOffset(position);
setPitch(pitch);
setPlayingOffset(position);
if (oldStatus == sf::SoundSource::Playing) {
play();
}
@ -215,22 +215,31 @@ sf::SoundSource::Status SyncedSoundStreams::getStatus() const
}
void SyncedSoundStreams::setPlayingOffset(sf::Time timeOffset) {
void SyncedSoundStreams::setPlayingOffset(const sf::Time timeOffset) {
// Get old playing status
auto oldStatus = getStatus();
// Stop the stream
stop();
const auto pre_pitched_time_offset = timeOffset / pitch;
// Let the derived class update the current position
for (auto& [_, s]: streams) {
s.stream->public_seek_callback(timeOffset);
// Restart streaming
if (s.reconstruct_on_pitch_change) {
timeOffset /= pitch;
if (s.bypasses_openal_pitch) {
s.buffers.m_samplesProcessed = time_to_samples(
pre_pitched_time_offset,
s.buffers.m_sampleRate,
s.buffers.m_channelCount
);
} else {
s.buffers.m_samplesProcessed = time_to_samples(
timeOffset,
s.buffers.m_sampleRate,
s.buffers.m_channelCount
);
}
s.buffers.m_samplesProcessed = time_to_samples(timeOffset, s.buffers.m_sampleRate, s.buffers.m_channelCount);
}
if (oldStatus == sf::SoundSource::Stopped) {
@ -259,7 +268,7 @@ sf::Time SyncedSoundStreams::getPlayingOffset(const InternalStream& s) const {
s.buffers.m_sampleRate,
s.buffers.m_channelCount
);
if (s.reconstruct_on_pitch_change) {
if (s.bypasses_openal_pitch) {
return openal_seconds * pitch;
} else {
return openal_seconds;
@ -284,7 +293,7 @@ sf::Time SyncedSoundStreams::getPrecisePlayingOffset(const InternalStream& s) co
void SyncedSoundStreams::setPitch(float new_pitch) {
pitch = new_pitch;
for (auto& [_, s] : streams) {
if (not s.reconstruct_on_pitch_change) {
if (not s.bypasses_openal_pitch) {
s.stream->setPitch(new_pitch);
}
}
@ -309,10 +318,10 @@ void SyncedSoundStreams::display_debug() const {
ImGui::TableHeadersRow();
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted("reconstruct on pitch change");
ImGui::TextUnformatted("bypasses OpenAL Pitch");
for (const auto& [_, s] : streams) {
ImGui::TableNextColumn();
ImGui::TextUnformatted(fmt::format("{}", s.reconstruct_on_pitch_change).c_str());
ImGui::TextUnformatted(fmt::format("{}", s.bypasses_openal_pitch).c_str());
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
@ -358,10 +367,12 @@ void SyncedSoundStreams::display_debug() const {
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted("internal stream pitch");
ImGui::TextUnformatted("AL_PITCH");
for (const auto& [_, s] : streams) {
ImGui::TableNextColumn();
ImGui::TextUnformatted(fmt::format("x{}", s.stream->getPitch()).c_str());
ALfloat pitch;
alCheck(alGetSourcef(s.stream->get_source(), AL_PITCH, &pitch));
ImGui::TextUnformatted(fmt::format("x{}", pitch).c_str());
}
ImGui::TableNextRow();
ImGui::TableNextColumn();

View File

@ -47,7 +47,7 @@ struct NewStream {
struct InternalStream {
std::shared_ptr<PreciseSoundStream> stream;
Buffers buffers;
bool reconstruct_on_pitch_change;
bool bypasses_openal_pitch;
void clear_queue();
};
@ -68,7 +68,7 @@ public:
sf::SoundSource::Status getStatus() const;
void setPlayingOffset(sf::Time timeOffset);
void setPlayingOffset(const sf::Time timeOffset);
sf::Time getPlayingOffset() const;
sf::Time getPrecisePlayingOffset() const;

View File

@ -155,8 +155,10 @@ void EditorState::set_pitch(float pitch) {
beat_ticks = beat_ticks->with_pitch(pitch);
update[beat_tick_stream] = {beat_ticks, true};
}
audio.update_streams(update);
// setPitch has to be called before update_streams to avoid problems in
// the internal call to setPlaybackPosition
audio.setPitch(pitch);
audio.update_streams(update);
}
float EditorState::get_pitch() const {