diff --git a/CHANGES.md b/CHANGES.md index 451fed4d..41a7b4c1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,8 @@ - @voluntas - [FIX] SoraAudioSink.read が timeout を無視して失敗を返すケースがあったので修正する - @enm10k +- [FIX] SoraAudioSink.read が timeout を無視するケースがある問題を修正した結果、 read の実行タイミングによってはクラッシュするようになったので修正する + - @enm10k ## 2024.2.0 diff --git a/src/sora_audio_sink.cpp b/src/sora_audio_sink.cpp index 63de306d..e86a0c88 100644 --- a/src/sora_audio_sink.cpp +++ b/src/sora_audio_sink.cpp @@ -137,14 +137,14 @@ nb::tuple SoraAudioSinkImpl::Read(size_t frames, float timeout) { size_t num_of_samples; if (frames > 0) { // フレーム数のリクエストがある場合はリクエスト分が貯まるまで待つ - num_of_samples = frames * number_of_channels_; if (!buffer_cond_.wait_for( lock, std::chrono::nanoseconds( // Python の流儀に合わせて秒を float で受け取っているので換算 (int64_t)((double)timeout * 1000. * 1000. * 1000.)), [&] { - return buffer_.size() >= num_of_samples || + return (number_of_channels_ > 0 && + buffer_.size() >= frames * number_of_channels_) || PyErr_CheckSignals() != 0; })) { // タイムアウトで返す @@ -154,6 +154,9 @@ nb::tuple SoraAudioSinkImpl::Read(size_t frames, float timeout) { // Signals で wait を抜けた時は返す return nb::make_tuple(false, nb::none()); } + // std::condition_variable::wait_for の待機中に number_of_channels_ が更新される可能性があるため、 + // 起床後に num_of_samples を計算する必要がある + num_of_samples = frames * number_of_channels_; } else { // フレーム数のリクエストがない場合はあるだけ全部出す if (buffer_.empty()) {