Fix audio memory leak and fix windows distortion (#402)
* Fix audio memory leak and fix windows distortion * Fix play button resetting
This commit is contained in:
parent
6954f4d14c
commit
c57e297804
12 changed files with 165 additions and 2326 deletions
File diff suppressed because it is too large
Load diff
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "toonz/txshcolumn.h"
|
||||
#include "toonz/txshcell.h"
|
||||
#include "toonz/txshsoundlevel.h"
|
||||
#include "tsound.h"
|
||||
|
||||
#include <QList>
|
||||
|
@ -23,7 +24,69 @@
|
|||
//=============================================================================
|
||||
// forward declarations
|
||||
class TFilePath;
|
||||
class ColumnLevel;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
// ColumnLevel
|
||||
//=============================================================================
|
||||
|
||||
class ColumnLevel {
|
||||
TXshSoundLevelP m_soundLevel;
|
||||
|
||||
/*!Offsets: in frames. Start offset is a positive number.*/
|
||||
int m_startOffset;
|
||||
/*!Offsets: in frames. End offset is a positive number(to subtract to..).*/
|
||||
int m_endOffset;
|
||||
|
||||
//! Starting frame in the timeline
|
||||
int m_startFrame;
|
||||
|
||||
//! frameRate
|
||||
double m_fps;
|
||||
|
||||
public:
|
||||
ColumnLevel(TXshSoundLevel* soundLevel = 0, int startFrame = -1,
|
||||
int startOffset = -1, int endOffset = -1, double fps = -1);
|
||||
~ColumnLevel();
|
||||
ColumnLevel* clone() const;
|
||||
|
||||
//! Overridden from TXshLevel
|
||||
TXshSoundLevel* getSoundLevel() const { return m_soundLevel.getPointer(); }
|
||||
void setSoundLevel(TXshSoundLevelP level) { m_soundLevel = level; }
|
||||
|
||||
void loadData(TIStream& is);
|
||||
void saveData(TOStream& os);
|
||||
|
||||
void setStartOffset(int value);
|
||||
int getStartOffset() const { return m_startOffset; }
|
||||
|
||||
void setEndOffset(int value);
|
||||
int getEndOffset() const { return m_endOffset; }
|
||||
|
||||
void setOffsets(int startOffset, int endOffset);
|
||||
|
||||
//! Return the starting frame without offsets.
|
||||
void setStartFrame(int frame) { m_startFrame = frame; }
|
||||
int getStartFrame() const { return m_startFrame; }
|
||||
|
||||
//! Return the ending frame without offsets.
|
||||
int getEndFrame() const;
|
||||
|
||||
//! Return frame count without offset.
|
||||
int getFrameCount() const;
|
||||
|
||||
//! Return frame count with offset.
|
||||
int getVisibleFrameCount() const;
|
||||
|
||||
//! Return start frame with offset.
|
||||
int getVisibleStartFrame() const;
|
||||
//! Return last frame with offset.
|
||||
int getVisibleEndFrame() const;
|
||||
//! Updates m_startOfset and m_endOffset.
|
||||
void updateFrameRate(double newFrameRate);
|
||||
|
||||
void setFrameRate(double fps) { m_fps = fps; }
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//! The TXshSoundColumn class provides a sound column in xsheet and allows its
|
||||
|
@ -75,6 +138,7 @@ public:
|
|||
int getFirstRow() const override;
|
||||
|
||||
const TXshCell &getCell(int row) const override;
|
||||
TXshCell getSoundCell(int row);
|
||||
void getCells(int row, int rowCount, TXshCell cells[]) override;
|
||||
|
||||
bool setCell(int row, const TXshCell &cell) override;
|
||||
|
|
|
@ -856,17 +856,20 @@ QString TTool::updateEnabled(int rowIndex, int columnIndex) {
|
|||
// find the nearest level before it
|
||||
if (levelType == NO_XSHLEVEL &&
|
||||
!m_application->getCurrentFrame()->isEditingLevel()) {
|
||||
if (!column || (column && !column->getSoundColumn())) {
|
||||
TXshCell cell = xsh->getCell(rowIndex, columnIndex);
|
||||
xl = cell.isEmpty() ? 0 : (TXshLevel*)(&cell.m_level);
|
||||
sl = cell.isEmpty() ? 0 : cell.getSimpleLevel();
|
||||
levelType = cell.isEmpty() ? NO_XSHLEVEL : cell.m_level->getType();
|
||||
}
|
||||
}
|
||||
|
||||
if (Preferences::instance()->isAutoCreateEnabled()) {
|
||||
// If not in Level editor, let's use our current cell from the xsheet to
|
||||
// find the nearest level before it
|
||||
if (levelType == NO_XSHLEVEL &&
|
||||
!m_application->getCurrentFrame()->isEditingLevel()) {
|
||||
if (!column || (column && !column->getSoundColumn())) {
|
||||
int r0, r1;
|
||||
xsh->getCellRange(columnIndex, r0, r1);
|
||||
for (int r = std::min(r1, rowIndex); r > r0; r--) {
|
||||
|
@ -878,6 +881,7 @@ QString TTool::updateEnabled(int rowIndex, int columnIndex) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the current tool does not match the current type, check for
|
||||
// a version of the same tool that does
|
||||
|
|
|
@ -2108,6 +2108,7 @@ void SceneViewer::drawScene() {
|
|||
args.m_osm = &osm;
|
||||
args.m_xsheetLevel = xsheetLevel;
|
||||
args.m_isPlaying = frameHandle->isPlaying();
|
||||
if (app->getCurrentColumn()->getColumn() && !app->getCurrentColumn()->getColumn()->getSoundColumn())
|
||||
args.m_currentFrameId =
|
||||
app->getCurrentXsheet()
|
||||
->getXsheet()
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "toonz/tcamera.h"
|
||||
#include "toonz/preferences.h"
|
||||
#include "toonz/fullcolorpalette.h"
|
||||
#include "toonz/txshsoundcolumn.h"
|
||||
|
||||
#include "toonzqt/tabbar.h"
|
||||
|
||||
|
@ -310,6 +311,8 @@ int TApp::getCurrentImageType() {
|
|||
}
|
||||
|
||||
TXsheet *xsh = getCurrentXsheet()->getXsheet();
|
||||
if (xsh->getColumn(col) && xsh->getColumn(col)->getSoundColumn())
|
||||
return TImage::VECTOR;
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
if (cell.isEmpty()) {
|
||||
int r0, r1;
|
||||
|
@ -357,7 +360,18 @@ void TApp::updateXshLevel() {
|
|||
int column = m_currentColumn->getColumnIndex();
|
||||
TXsheet *xsheet = m_currentXsheet->getXsheet();
|
||||
|
||||
if (xsheet && column >= 0 && frame >= 0 && !xsheet->isColumnEmpty(column)) {
|
||||
bool isSoundColumn = false;
|
||||
if (xsheet->getColumn(column) &&
|
||||
xsheet->getColumn(column)->getSoundColumn()) {
|
||||
isSoundColumn = true;
|
||||
if (xsheet->getColumn(column)->getSoundColumn()->m_levels.size() > 0) {
|
||||
xl = static_cast<TXshLevel *>(xsheet->getColumn(column)
|
||||
->getSoundColumn()
|
||||
->m_levels.at(0)
|
||||
->getSoundLevel());
|
||||
}
|
||||
} else if (xsheet && column >= 0 && frame >= 0 &&
|
||||
!xsheet->isColumnEmpty(column)) {
|
||||
TXshCell cell = xsheet->getCell(frame, column);
|
||||
xl = cell.m_level.getPointer();
|
||||
|
||||
|
|
|
@ -645,7 +645,8 @@ void SceneViewerPanel::changeWindowTitle() {
|
|||
return;
|
||||
}
|
||||
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
|
||||
TXshCell cell = xsh->getCell(frame, col);
|
||||
TXshCell cell;
|
||||
if (app->getCurrentColumn()->getColumn() && !app->getCurrentColumn()->getColumn()->getSoundColumn()) cell = xsh->getCell(frame, col);
|
||||
if (cell.isEmpty()) {
|
||||
if (!m_sceneViewer->is3DView()) {
|
||||
TAffine aff = m_sceneViewer->getViewMatrix() *
|
||||
|
|
|
@ -1415,8 +1415,8 @@ void CellArea::drawSoundCell(QPainter &p, int row, int col, bool isReference) {
|
|||
}
|
||||
|
||||
TXshCell nextCell;
|
||||
nextCell =
|
||||
m_viewer->getXsheet()->getCell(row + 1, col); // cell in next frame
|
||||
nextCell = soundColumn->getSoundCell(row + 1); // cell in next frame
|
||||
bool isNextEmpty = nextCell.getFrameId().getNumber() < 0;
|
||||
|
||||
int frameAdj = m_viewer->getFrameZoomAdjustment();
|
||||
int frameZoomF = m_viewer->getFrameZoomFactor();
|
||||
|
@ -1424,13 +1424,11 @@ void CellArea::drawSoundCell(QPainter &p, int row, int col, bool isReference) {
|
|||
cellRect.adjust(0, 0, -frameAdj, 0);
|
||||
QRect rect = cellRect.adjusted(
|
||||
1, 1,
|
||||
(!m_viewer->orientation()->isVerticalTimeline() && !nextCell.isEmpty()
|
||||
? 2
|
||||
: 0),
|
||||
(!m_viewer->orientation()->isVerticalTimeline() && !isNextEmpty ? 2 : 0),
|
||||
0);
|
||||
int maxNumFrame = soundColumn->getMaxFrame() + 1;
|
||||
int startFrame = soundColumn->getFirstRow();
|
||||
TXshCell cell = soundColumn->getCell(row);
|
||||
TXshCell cell = soundColumn->getSoundCell(row);
|
||||
if (soundColumn->isCellEmpty(row) || cell.isEmpty() || row > maxNumFrame ||
|
||||
row < startFrame) {
|
||||
drawFrameSeparator(p, row, col, true);
|
||||
|
@ -2948,7 +2946,7 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) {
|
|||
->getZeraryColumnFx()
|
||||
->getZeraryFx()
|
||||
->getName());
|
||||
else if ((!xsh->getCell(row, col).isEmpty() && !isSoundColumn) && // x > 6 &&
|
||||
else if ((!isSoundColumn && !xsh->getCell(row, col).isEmpty()) && // x > 6 &&
|
||||
x < (o->cellWidth() - frameAdj)) {
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
TFrameId fid = cell.getFrameId();
|
||||
|
|
|
@ -2282,8 +2282,12 @@ void ColumnArea::mousePressEvent(QMouseEvent *event) {
|
|||
TSoundTrackP sTrack = s->getCurrentPlaySoundTruck();
|
||||
interval = sTrack->getDuration() * 1000 + 300;
|
||||
}
|
||||
if (s->isPlaying() && interval > 0)
|
||||
QTimer::singleShot(interval, this, SLOT(update()));
|
||||
if (s->isPlaying() && interval > 0) {
|
||||
QTimer::singleShot(interval, this, [this, s] {
|
||||
if (s && s->isPlaying()) s->stop();
|
||||
update();
|
||||
});
|
||||
}
|
||||
}
|
||||
update();
|
||||
} else if (!o->flag(PredefinedFlag::CONFIG_AREA_VISIBLE) &&
|
||||
|
|
|
@ -128,10 +128,15 @@ void XsheetViewer::getColumnColor(QColor &color, QColor &sideColor, int index,
|
|||
xsh->getCellRange(index, r0, r1);
|
||||
if (0 <= r0 && r0 <= r1) {
|
||||
// column color depends on the level type in the top-most occupied cell
|
||||
if (xsh->getColumn(index)->getSoundColumn()) {
|
||||
color = m_soundColumnColor;
|
||||
sideColor = m_soundColumnBorderColor;
|
||||
} else {
|
||||
TXshCell cell = xsh->getCell(r0, index);
|
||||
int ltype;
|
||||
getCellTypeAndColors(ltype, color, sideColor, cell);
|
||||
}
|
||||
}
|
||||
if (xsh->getColumn(index)->isMask()) color = QColor(255, 0, 255);
|
||||
}
|
||||
|
||||
|
|
|
@ -677,7 +677,7 @@ void StageBuilder::addFrame(PlayerSet &players, ToonzScene *scene, TXsheet *xsh,
|
|||
}
|
||||
TXshColumn *column = xsh->getColumn(c);
|
||||
bool isMask = false;
|
||||
if (column && !column->isEmpty()) {
|
||||
if (column && !column->isEmpty() && !column->getSoundColumn()) {
|
||||
if (!column->isPreviewVisible() && checkPreviewVisibility) continue;
|
||||
if (column->isCamstandVisible() ||
|
||||
includeUnvisible) // se l'"occhietto" non e' chiuso
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "orientation.h"
|
||||
|
||||
#include "toonz/txsheet.h"
|
||||
#include "toonz/preferences.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -1488,7 +1489,20 @@ void TXsheet::scrub(int frame, bool isPreview) {
|
|||
double samplePerFrame = st->getSampleRate() / fps;
|
||||
|
||||
double s0 = frame * samplePerFrame, s1 = s0 + samplePerFrame;
|
||||
|
||||
// if (m_player && m_player->isPlaying()) {
|
||||
// try {
|
||||
// m_player->stop();
|
||||
// }
|
||||
// catch (const std::runtime_error& e) {
|
||||
// int i = 0;
|
||||
// }
|
||||
// catch (const std::exception& e) {
|
||||
// int i = 0;
|
||||
// }
|
||||
// catch (...) {
|
||||
// int i = 0;
|
||||
// }
|
||||
//}
|
||||
play(st, s0, s1, false);
|
||||
} catch (TSoundDeviceException &e) {
|
||||
if (e.getType() == TSoundDeviceException::NoDevice) {
|
||||
|
|
|
@ -6,78 +6,16 @@
|
|||
#include "toonz/toonzscene.h"
|
||||
#include "toonz/tproject.h"
|
||||
#include "toonz/sceneproperties.h"
|
||||
#include "toonz/txshsoundlevel.h"
|
||||
|
||||
#include "tstream.h"
|
||||
#include "toutputproperties.h"
|
||||
#include "tsop.h"
|
||||
#include "tconvert.h"
|
||||
#include "toonz/preferences.h"
|
||||
|
||||
#include <QAudioFormat>
|
||||
#include <QAudioDeviceInfo>
|
||||
|
||||
//=============================================================================
|
||||
// ColumnLevel
|
||||
//=============================================================================
|
||||
|
||||
class ColumnLevel {
|
||||
TXshSoundLevelP m_soundLevel;
|
||||
|
||||
/*!Offsets: in frames. Start offset is a positive number.*/
|
||||
int m_startOffset;
|
||||
/*!Offsets: in frames. End offset is a positive number(to subtract to..).*/
|
||||
int m_endOffset;
|
||||
|
||||
//! Starting frame in the timeline
|
||||
int m_startFrame;
|
||||
|
||||
//! frameRate
|
||||
double m_fps;
|
||||
|
||||
public:
|
||||
ColumnLevel(TXshSoundLevel *soundLevel = 0, int startFrame = -1,
|
||||
int startOffset = -1, int endOffset = -1, double fps = -1);
|
||||
~ColumnLevel();
|
||||
ColumnLevel *clone() const;
|
||||
|
||||
//! Overridden from TXshLevel
|
||||
TXshSoundLevel *getSoundLevel() const { return m_soundLevel.getPointer(); }
|
||||
void setSoundLevel(TXshSoundLevelP level) { m_soundLevel = level; }
|
||||
|
||||
void loadData(TIStream &is);
|
||||
void saveData(TOStream &os);
|
||||
|
||||
void setStartOffset(int value);
|
||||
int getStartOffset() const { return m_startOffset; }
|
||||
|
||||
void setEndOffset(int value);
|
||||
int getEndOffset() const { return m_endOffset; }
|
||||
|
||||
void setOffsets(int startOffset, int endOffset);
|
||||
|
||||
//! Return the starting frame without offsets.
|
||||
void setStartFrame(int frame) { m_startFrame = frame; }
|
||||
int getStartFrame() const { return m_startFrame; }
|
||||
|
||||
//! Return the ending frame without offsets.
|
||||
int getEndFrame() const;
|
||||
|
||||
//! Return frame count without offset.
|
||||
int getFrameCount() const;
|
||||
|
||||
//! Return frame count with offset.
|
||||
int getVisibleFrameCount() const;
|
||||
|
||||
//! Return start frame with offset.
|
||||
int getVisibleStartFrame() const;
|
||||
//! Return last frame with offset.
|
||||
int getVisibleEndFrame() const;
|
||||
//! Updates m_startOfset and m_endOffset.
|
||||
void updateFrameRate(double newFrameRate);
|
||||
|
||||
void setFrameRate(double fps) { m_fps = fps; }
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
||||
ColumnLevel::ColumnLevel(TXshSoundLevel *soundLevel, int startFrame,
|
||||
|
@ -381,18 +319,34 @@ const TXshCell &TXshSoundColumn::getCell(int row) const {
|
|||
if (!l) return emptyCell;
|
||||
TXshSoundLevel *soundLevel = l->getSoundLevel();
|
||||
TXshCell *cell = new TXshCell(soundLevel, TFrameId(row - l->getStartFrame()));
|
||||
// La nuova cella aggiunge un reference al TXshSoundLevel; poiche' le celle
|
||||
// delle
|
||||
// TXshSoundColumn non sono strutture persistenti ma sono strutture dinamiche
|
||||
// (vengono ricreate ogni volta) devo occuparmi di fare il release altrimenti
|
||||
// il
|
||||
// TXshSoundLevel non viene mai buttato.
|
||||
// The new cell adds a reference to the TXshSoundLevel;
|
||||
// since the cells of the TXshSoundColumn are not persistent structures
|
||||
// but are dynamic structures (they are recreated every time) I have to take
|
||||
// care of making the release otherwise the TXshSoundLevel is never thrown
|
||||
// away.
|
||||
soundLevel->release();
|
||||
return *cell;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TXshCell TXshSoundColumn::getSoundCell(int row) {
|
||||
static TXshCell emptyCell;
|
||||
|
||||
ColumnLevel* l = getColumnLevelByFrame(row);
|
||||
if (row < 0 || row < getFirstRow() || row > getMaxFrame()) {
|
||||
if (l) emptyCell.m_level = l->getSoundLevel();
|
||||
return emptyCell;
|
||||
}
|
||||
|
||||
if (!l) return emptyCell;
|
||||
TXshSoundLevel* soundLevel = l->getSoundLevel();
|
||||
TXshCell cell(soundLevel, TFrameId(row - l->getStartFrame()));
|
||||
return cell;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool TXshSoundColumn::isCellEmpty(int row) const {
|
||||
if (m_levels.empty()) return true;
|
||||
ColumnLevel *l = getColumnLevelByFrame(row);
|
||||
|
@ -978,7 +932,7 @@ TSoundTrackP TXshSoundColumn::getOverallSoundTrack(int fromFrame, int toFrame,
|
|||
if (toFrame == -1) toFrame = getMaxFrame();
|
||||
|
||||
if (format.m_sampleRate == 0) {
|
||||
// Found the best format inside the soundsequences
|
||||
// Find the best format inside the soundsequences
|
||||
int sampleRate = 0;
|
||||
int bitsPerSample = 8;
|
||||
int channels = 1;
|
||||
|
@ -1015,10 +969,8 @@ TSoundTrackP TXshSoundColumn::getOverallSoundTrack(int fromFrame, int toFrame,
|
|||
format.m_signedSample = true;
|
||||
}
|
||||
|
||||
// We prefer to have 22050 as a maximum sampleRate (to avoid crashes or
|
||||
// another issues)
|
||||
#ifdef _WIN32
|
||||
if (format.m_sampleRate >= 44100) format.m_sampleRate = 22050;
|
||||
if (format.m_sampleRate > 44100) format.m_sampleRate = 44100;
|
||||
#else
|
||||
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
|
||||
if (info.deviceName().length() == 0) throw TSoundDeviceException(TSoundDeviceException::NoDevice,
|
||||
|
|
Loading…
Reference in a new issue