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

View File

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

View File

@ -155,8 +155,10 @@ void EditorState::set_pitch(float pitch) {
beat_ticks = beat_ticks->with_pitch(pitch); beat_ticks = beat_ticks->with_pitch(pitch);
update[beat_tick_stream] = {beat_ticks, true}; 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.setPitch(pitch);
audio.update_streams(update);
} }
float EditorState::get_pitch() const { float EditorState::get_pitch() const {