Раздели PCM-сессии и исправь частоту и перемотку звука

This commit is contained in:
evgeny committed 2026-10-02 02:00:50 +03:00
1 parent 40b974b29c
commit 217e5795bf
13 files changed
+226 -134

No files matched your search

+19 -17
View File
@@ -29,6 +29,7 @@ MessageDelegate::MessageDelegate(QObject *parent)
: QStyledItemDelegate(parent) {}
struct VoicePlayState {
uint64_t playbackId = 0;
bool loading = false;
bool playing = false;
bool paused = false;
@@ -56,7 +57,7 @@ static void ensureVoiceTimer() {
continue;
}
if (it->paused) { anyActive = true; continue; }
if (!sm->isCurrentPcmPlaying()) {
if (!sm->isPcmPlaying(it->playbackId)) {
it->playing = false;
it->paused = false;
anyActive = true;
@@ -177,16 +178,16 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
/* Start playback then seek */
st.loading = true;
QPersistentModelIndex persistent(index);
VoicePlayer::playOpusFile(filePath, this, [filePath, clickFrac, persistent](float actualDur) {
VoicePlayer::playOpusFile(filePath, this, [filePath, clickFrac, persistent](float actualDur, uint64_t playbackId) {
s_voiceStates[filePath].loading = false;
if (actualDur <= 0) return;
MessageDelegate::startAutoPlay(filePath, actualDur);
MessageDelegate::startAutoPlay(filePath, actualDur, playbackId);
float position = clickFrac * actualDur;
auto& state = s_voiceStates[filePath];
state.startMs -= (qint64)(position * 1000); state.pausedPosSec = position;
state.displayFrac = clickFrac; state.displayElapsed = position;
int rate = SoundManager::instance()->currentPcmSampleRate();
if (rate > 0) SoundManager::instance()->seekCurrentPcm((unsigned long long)(position * rate));
int rate = SoundManager::instance()->pcmSampleRate(playbackId);
if (rate > 0) SoundManager::instance()->seekPcm(playbackId, (unsigned long long)(position * rate));
if (persistent.isValid()) const_cast<QAbstractItemModel*>(persistent.model())->setData(persistent, 1, MsgVoicePlayStateRole);
});
s_voiceTimer->start();
@@ -199,9 +200,9 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
{ st.playing = true; s_voiceTimer->start(); }
st.displayFrac = (targetSec > 0 && dur > 0) ? (targetSec / dur) : 0;
st.displayElapsed = targetSec;
int sr = SoundManager::instance()->currentPcmSampleRate();
int sr = SoundManager::instance()->pcmSampleRate(st.playbackId);
if (sr > 0)
SoundManager::instance()->seekCurrentPcm((unsigned long long)(targetSec * sr));
SoundManager::instance()->seekPcm(st.playbackId, (unsigned long long)(targetSec * sr));
}
return true;
}
@@ -219,7 +220,7 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
st.pausedPosSec = (now - st.startMs) / 1000.0f;
st.playing = false;
st.paused = true;
SoundManager::instance()->pauseCurrentPcm();
SoundManager::instance()->pausePcm(st.playbackId);
model->setData(index, 2, MsgVoicePlayStateRole);
return true;
}
@@ -232,7 +233,7 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
st.startMs = now - (qint64)(st.pausedPosSec * 1000.0);
st.displayFrac = (dur > 0) ? (st.pausedPosSec / dur) : 0;
st.displayElapsed = st.pausedPosSec;
SoundManager::instance()->resumeCurrentPcm();
SoundManager::instance()->resumePcm(st.playbackId);
s_voiceTimer->start();
model->setData(index, 1, MsgVoicePlayStateRole);
return true;
@@ -243,15 +244,15 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
for (auto it = s_voiceStates.begin(); it != s_voiceStates.end(); ++it) {
it->playing = false; it->paused = false;
}
SoundManager::instance()->stopCurrentPcm();
VoicePlayer::stop();
}
st.loading = true;
QPersistentModelIndex persistent(index);
VoicePlayer::playOpusFile(filePath, this, [filePath, persistent](float actualDur) {
VoicePlayer::playOpusFile(filePath, this, [filePath, persistent](float actualDur, uint64_t playbackId) {
s_voiceStates[filePath].loading = false;
if (actualDur <= 0) return;
MessageDelegate::startAutoPlay(filePath, actualDur);
MessageDelegate::startAutoPlay(filePath, actualDur, playbackId);
if (persistent.isValid()) const_cast<QAbstractItemModel*>(persistent.model())->setData(persistent, 1, MsgVoicePlayStateRole);
});
s_voiceTimer->start();
@@ -913,9 +914,9 @@ void MessageDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
elapsed = st->pausedPosSec;
} else if (isPlaying) {
SoundManager* sm = SoundManager::instance();
if (sm->isCurrentPcmPlaying()) {
int sr = sm->currentPcmSampleRate();
if (sr > 0) elapsed = (float)((double)sm->currentPcmCursor() / sr);
if (sm->isPcmPlaying(st->playbackId)) {
int sr = sm->pcmSampleRate(st->playbackId);
if (sr > 0) elapsed = (float)((double)sm->pcmCursor(st->playbackId) / sr);
}
if (elapsed <= 0) {
qint64 now = QDateTime::currentMSecsSinceEpoch();
@@ -1504,10 +1505,11 @@ void MessageDelegate::drawAvatar(QPainter *p, const Layout &L,
p->restore();
}
void MessageDelegate::startAutoPlay(const QString& filePath, float actualDurationSec) {
void MessageDelegate::startAutoPlay(const QString& filePath, float actualDurationSec, uint64_t playbackId) {
if (actualDurationSec <= 0) return;
ensureVoiceTimer();
VoicePlayState& st = s_voiceStates[filePath];
st.playbackId = playbackId;
st.playing = true;
st.paused = false;
st.durationSec = (actualDurationSec > 0) ? actualDurationSec : 1.0f;
@@ -1520,7 +1522,7 @@ void MessageDelegate::startAutoPlay(const QString& filePath, float actualDuratio
}
void MessageDelegate::stopAllAutoPlay() {
VoicePlayer::cancelPending();
VoicePlayer::stop();
for (auto it = s_voiceStates.begin(); it != s_voiceStates.end(); ++it) {
it->playing = false; it->paused = false; it->loading = false;
}