Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/txshsoundcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelset.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/tproject.h"
Toshihiro Shimizu 890ddd
#include "toonz/sceneproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsoundlevel.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "toutputproperties.h"
Toshihiro Shimizu 890ddd
#include "tsop.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
Jeremy Bullock 6767be
#include <qaudioformat></qaudioformat>
Jeremy Bullock 6767be
#include <qaudiodeviceinfo></qaudiodeviceinfo>
Jeremy Bullock 6767be
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//  ColumnLevel
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class ColumnLevel {
Shinya Kitaoka 120a6e
  TXshSoundLevelP m_soundLevel;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*!Offsets: in frames. Start offset is a positive number.*/
Shinya Kitaoka 120a6e
  int m_startOffset;
Shinya Kitaoka 120a6e
  /*!Offsets: in frames. End offset is a positive number(to subtract to..).*/
Shinya Kitaoka 120a6e
  int m_endOffset;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Starting frame in the timeline
Shinya Kitaoka 120a6e
  int m_startFrame;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! frameRate
Shinya Kitaoka 120a6e
  double m_fps;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ColumnLevel(TXshSoundLevel *soundLevel = 0, int startFrame = -1,
Shinya Kitaoka 120a6e
              int startOffset = -1, int endOffset = -1, double fps = -1);
Shinya Kitaoka 120a6e
  ~ColumnLevel();
Shinya Kitaoka 120a6e
  ColumnLevel *clone() const;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Overridden from TXshLevel
Shinya Kitaoka 120a6e
  TXshSoundLevel *getSoundLevel() const { return m_soundLevel.getPointer(); }
Shinya Kitaoka 120a6e
  void setSoundLevel(TXshSoundLevelP level) { m_soundLevel = level; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void loadData(TIStream &is);
Shinya Kitaoka 120a6e
  void saveData(TOStream &os);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void setStartOffset(int value);
Shinya Kitaoka 120a6e
  int getStartOffset() const { return m_startOffset; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void setEndOffset(int value);
Shinya Kitaoka 120a6e
  int getEndOffset() const { return m_endOffset; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void setOffsets(int startOffset, int endOffset);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Return the starting frame without offsets.
Shinya Kitaoka 120a6e
  void setStartFrame(int frame) { m_startFrame = frame; }
Shinya Kitaoka 120a6e
  int getStartFrame() const { return m_startFrame; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Return the ending frame without offsets.
Shinya Kitaoka 120a6e
  int getEndFrame() const;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Return frame count without offset.
Shinya Kitaoka 120a6e
  int getFrameCount() const;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Return frame count with offset.
Shinya Kitaoka 120a6e
  int getVisibleFrameCount() const;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Return start frame with offset.
Shinya Kitaoka 120a6e
  int getVisibleStartFrame() const;
Shinya Kitaoka 120a6e
  //! Return last frame with offset.
Shinya Kitaoka 120a6e
  int getVisibleEndFrame() const;
Shinya Kitaoka 120a6e
  //! Updates m_startOfset and m_endOffset.
Shinya Kitaoka 120a6e
  void updateFrameRate(double newFrameRate);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void setFrameRate(double fps) { m_fps = fps; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ColumnLevel::ColumnLevel(TXshSoundLevel *soundLevel, int startFrame,
Shinya Kitaoka 120a6e
                         int startOffset, int endOffset, double fps)
Shinya Kitaoka 120a6e
    : m_soundLevel(soundLevel)
Shinya Kitaoka 120a6e
    , m_startOffset(startOffset)
Shinya Kitaoka 120a6e
    , m_endOffset(endOffset)
Shinya Kitaoka 120a6e
    , m_startFrame(startFrame)
Shinya Kitaoka 120a6e
    , m_fps(fps) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ColumnLevel::~ColumnLevel() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ColumnLevel *ColumnLevel::clone() const {
Shinya Kitaoka 120a6e
  ColumnLevel *soundColumnLevel = new ColumnLevel();
Shinya Kitaoka 120a6e
  soundColumnLevel->setSoundLevel(getSoundLevel());
Shinya Kitaoka 120a6e
  soundColumnLevel->setStartFrame(m_startFrame);
Shinya Kitaoka 120a6e
  soundColumnLevel->setStartOffset(m_startOffset);
Shinya Kitaoka 120a6e
  soundColumnLevel->setEndOffset(m_endOffset);
Shinya Kitaoka 120a6e
  soundColumnLevel->setFrameRate(m_fps);
Shinya Kitaoka 120a6e
  return soundColumnLevel;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ColumnLevel::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  std::string tagName;
Shinya Kitaoka 120a6e
  is.openChild(tagName);
Shinya Kitaoka 120a6e
  if (tagName == "SoundCells") {
Shinya Kitaoka 120a6e
    TPersist *p = 0;
Shinya Kitaoka 120a6e
    is >> m_startOffset >> m_endOffset >> m_startFrame >> p;
Shinya Kitaoka 120a6e
    TXshSoundLevel *xshLevel   = dynamic_cast<txshsoundlevel *="">(p);</txshsoundlevel>
Shinya Kitaoka 120a6e
    if (xshLevel) m_soundLevel = xshLevel;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  is.closeChild();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ColumnLevel::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  os.child("SoundCells") << getStartOffset() << getEndOffset()
Shinya Kitaoka 120a6e
                         << getStartFrame() << m_soundLevel.getPointer();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ColumnLevel::setStartOffset(int value) {
Shinya Kitaoka 120a6e
  if (!m_soundLevel) return;
Shinya Kitaoka 120a6e
  if (value < 0 || value > getFrameCount() - getEndOffset() - 1) return;
Shinya Kitaoka 120a6e
  m_startOffset = value;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ColumnLevel::setEndOffset(int value) {
Shinya Kitaoka 120a6e
  if (!m_soundLevel) return;
Shinya Kitaoka 120a6e
  if (value < 0 ||
Shinya Kitaoka 120a6e
      getStartFrame() + getFrameCount() - value <
Shinya Kitaoka 120a6e
          getStartFrame() + getStartOffset() + 1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  m_endOffset = value;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ColumnLevel::setOffsets(int startOffset, int endOffset) {
Shinya Kitaoka 120a6e
  assert(startOffset > 0 && endOffset > 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (startOffset < 0 || startOffset > getFrameCount() - endOffset - 1) return;
Shinya Kitaoka 120a6e
  m_startOffset = startOffset;
Shinya Kitaoka 120a6e
  if (endOffset < 0 ||
Shinya Kitaoka 120a6e
      getStartFrame() + getFrameCount() - endOffset <
Shinya Kitaoka 120a6e
          getStartFrame() + getStartOffset() + 1)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  m_endOffset = endOffset;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ColumnLevel::getEndFrame() const {
Shinya Kitaoka 120a6e
  if (!m_soundLevel) return -1;
Shinya Kitaoka 120a6e
  return getStartFrame() + getFrameCount() - 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ColumnLevel::getFrameCount() const {
Shinya Kitaoka 120a6e
  if (!m_soundLevel) return -1;
Shinya Kitaoka 120a6e
  return m_soundLevel->getFrameCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ColumnLevel::getVisibleFrameCount() const {
Shinya Kitaoka 120a6e
  if (!m_soundLevel) return -1;
Shinya Kitaoka 120a6e
  return getFrameCount() - getStartOffset() - getEndOffset();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ColumnLevel::getVisibleStartFrame() const {
Shinya Kitaoka 120a6e
  if (!m_soundLevel) return -1;
Shinya Kitaoka 120a6e
  return getStartFrame() + getStartOffset();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ColumnLevel::getVisibleEndFrame() const {
Shinya Kitaoka 120a6e
  if (!m_soundLevel) return -1;
Shinya Kitaoka 120a6e
  return getVisibleStartFrame() + getVisibleFrameCount() - 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ColumnLevel::updateFrameRate(double newFrameRate) {
Shinya Kitaoka 120a6e
  if (m_fps == newFrameRate) return;
Shinya Kitaoka 120a6e
  double fact   = (double)newFrameRate / m_fps;
Shinya Kitaoka 120a6e
  m_startFrame  = tround(m_startFrame * fact);
Shinya Kitaoka 120a6e
  m_startOffset = tround(m_startOffset * fact);
Shinya Kitaoka 120a6e
  m_endOffset   = tround(m_endOffset * fact);
Shinya Kitaoka 120a6e
  m_fps         = newFrameRate;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool lessThan(const ColumnLevel *s1, const ColumnLevel *s2) {
Shinya Kitaoka 120a6e
  return s1->getVisibleStartFrame() < s2->getVisibleStartFrame();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TXshSoundColumn::TXshSoundColumn()
Shinya Kitaoka 120a6e
    : m_player(0)
Shinya Kitaoka 120a6e
    , m_volume(0.4)
Shinya Kitaoka 120a6e
    , m_currentPlaySoundTrack(0)
Shinya Kitaoka 120a6e
    , m_isOldVersion(false) {
Shinya Kitaoka 120a6e
  m_timer.setInterval(500);
Shinya Kitaoka 120a6e
  m_timer.setSingleShot(true);
Shinya Kitaoka 120a6e
  m_timer.stop();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimerOut()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshSoundColumn::~TXshSoundColumn() {
Shinya Kitaoka 120a6e
  clear();
Shinya Kitaoka 120a6e
  if (m_timer.isActive()) {
Shinya Kitaoka 120a6e
    m_timer.stop();
Shinya Kitaoka 120a6e
    stop();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshColumn::ColumnType TXshSoundColumn::getColumnType() const {
Shinya Kitaoka 120a6e
  return eSoundType;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshSoundColumn::canSetCell(const TXshCell &cell) const {
Shinya Kitaoka 120a6e
  return cell.isEmpty() || cell.m_level->getSoundLevel() != 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshColumn *TXshSoundColumn::clone() const {
Shinya Kitaoka 120a6e
  TXshSoundColumn *column = new TXshSoundColumn();
Shinya Kitaoka 120a6e
  column->setVolume(m_volume);
Shinya Kitaoka 120a6e
  column->setXsheet(getXsheet());
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < m_levels.size(); i++)
Shinya Kitaoka 120a6e
    column->insertColumnLevel(m_levels.at(i)->clone(), i);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return column;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::assignLevels(const TXshSoundColumn *src) {
Shinya Kitaoka 120a6e
  // Svuoto la lista dei livelli
Shinya Kitaoka 120a6e
  clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int r;
Shinya Kitaoka 120a6e
  for (r = src->getFirstRow(); r <= src->getMaxFrame(); r++) {
Shinya Kitaoka 120a6e
    int r0, r1;
Shinya Kitaoka 120a6e
    if (!src->getLevelRange(r, r0, r1)) continue;
Shinya Kitaoka 120a6e
    TXshCell cell = src->getCell(r);
Shinya Kitaoka 120a6e
    if (cell.isEmpty()) continue;
Shinya Kitaoka 120a6e
    TXshSoundLevel *soundLevel = cell.m_level->getSoundLevel();
Shinya Kitaoka 120a6e
    assert(!!soundLevel);
Shinya Kitaoka 120a6e
    int startOffset = cell.getFrameId().getNumber();
Shinya Kitaoka 120a6e
    int startFrame  = r - startOffset;
Shinya Kitaoka 120a6e
    int endOffset   = startFrame + soundLevel->getFrameCount() - r1 - 1;
Shinya Kitaoka 120a6e
    ColumnLevel *l =
Shinya Kitaoka 120a6e
        new ColumnLevel(soundLevel, startFrame, startOffset, endOffset);
Shinya Kitaoka 120a6e
    insertColumnLevel(l);
Shinya Kitaoka 120a6e
    r = r1;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  VersionNumber tnzVersion = is.getVersion();
Shinya Kitaoka 120a6e
  if (tnzVersion < VersionNumber(1, 17)) {
Shinya Kitaoka 120a6e
    TFilePath path;
Shinya Kitaoka 120a6e
    is >> path;
Shinya Kitaoka 120a6e
    m_isOldVersion = true;
Shinya Kitaoka 120a6e
    int offset     = 0;
Shinya Kitaoka 120a6e
    is >> offset;
Shinya Kitaoka 120a6e
    is >> m_volume;
Shinya Kitaoka 120a6e
    if (!is.eos()) {
Shinya Kitaoka 120a6e
      int status;
Shinya Kitaoka 120a6e
      is >> status;
Shinya Kitaoka 120a6e
      setStatusWord(status);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    TXshSoundLevelP level = new TXshSoundLevel(path.getWideName());
Shinya Kitaoka 120a6e
    level->setPath(path);
Shinya Kitaoka 120a6e
    ColumnLevel *l = new ColumnLevel(level.getPointer(), offset, 0, 0);
Shinya Kitaoka 120a6e
    insertColumnLevel(l);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  is >> m_volume;
Shinya Kitaoka 120a6e
  int levelCount = 0;
Shinya Kitaoka 120a6e
  is >> levelCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < levelCount; i++) {
Shinya Kitaoka 120a6e
    ColumnLevel *sl = new ColumnLevel();
Shinya Kitaoka 120a6e
    sl->loadData(is);
Shinya Kitaoka 120a6e
    insertColumnLevel(sl, i);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!is.eos()) {
Shinya Kitaoka 120a6e
    int status;
Shinya Kitaoka 120a6e
    is >> status;
Shinya Kitaoka 120a6e
    setStatusWord(status);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  os << m_volume;
Shinya Kitaoka 120a6e
  int levelsCount = m_levels.size();
Shinya Kitaoka 120a6e
  os << levelsCount;
Shinya Kitaoka 120a6e
  if (levelsCount == 0) return;
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < levelsCount; i++) m_levels.at(i)->saveData(os);
Shinya Kitaoka 120a6e
  os << getStatusWord();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TXshSoundColumn::getRange(int &r0, int &r1) const {
Shinya Kitaoka 120a6e
  r0 = getFirstRow();
Shinya Kitaoka 120a6e
  r1 = getMaxFrame();
Shinya Kitaoka 120a6e
  return r1 - r0 + 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TXshSoundColumn::getRowCount() const {
Shinya Kitaoka 120a6e
  return getMaxFrame() - getFirstRow();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TXshSoundColumn::getMaxFrame() const {
Shinya Kitaoka 120a6e
  int levelsCount = m_levels.size();
Shinya Kitaoka 120a6e
  if (levelsCount == 0) return -1;
Shinya Kitaoka 120a6e
  return m_levels.at(levelsCount - 1)->getVisibleEndFrame();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TXshSoundColumn::getFirstRow() const {
Shinya Kitaoka 120a6e
  if (m_levels.size() == 0) return -1;
Shinya Kitaoka 120a6e
  return m_levels.at(0)->getVisibleStartFrame();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TXshCell &TXshSoundColumn::getCell(int row) const {
Shinya Kitaoka 120a6e
  static TXshCell emptyCell;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ColumnLevel *l = getColumnLevelByFrame(row);
Shinya Kitaoka 120a6e
  if (row < 0 || row < getFirstRow() || row > getMaxFrame()) {
Shinya Kitaoka 120a6e
    if (l) emptyCell.m_level = l->getSoundLevel();
Shinya Kitaoka 120a6e
    return emptyCell;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!l) return emptyCell;
Shinya Kitaoka 120a6e
  TXshSoundLevel *soundLevel = l->getSoundLevel();
Shinya Kitaoka 120a6e
  TXshCell *cell = new TXshCell(soundLevel, TFrameId(row - l->getStartFrame()));
Shinya Kitaoka 120a6e
  // La nuova cella aggiunge un reference al TXshSoundLevel; poiche' le celle
Shinya Kitaoka 120a6e
  // delle
Shinya Kitaoka 120a6e
  // TXshSoundColumn non sono strutture persistenti ma sono strutture dinamiche
Shinya Kitaoka 120a6e
  // (vengono ricreate ogni volta) devo occuparmi di fare il release altrimenti
Shinya Kitaoka 120a6e
  // il
Shinya Kitaoka 120a6e
  // TXshSoundLevel non viene mai buttato.
Shinya Kitaoka 120a6e
  soundLevel->release();
Shinya Kitaoka 120a6e
  return *cell;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshSoundColumn::isCellEmpty(int row) const {
Shinya Kitaoka 120a6e
  if (m_levels.empty()) return true;
Shinya Kitaoka 120a6e
  ColumnLevel *l = getColumnLevelByFrame(row);
Shinya Kitaoka 120a6e
  if (!l || !l->getSoundLevel()) return true;
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//--- debug only
Shinya Kitaoka 120a6e
void TXshSoundColumn::checkColumn() const {
Toshihiro Shimizu 890ddd
#ifndef NDEBUG
Shinya Kitaoka 120a6e
  int size = m_levels.size();
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < size; i++) {
Shinya Kitaoka 120a6e
    ColumnLevel *level = m_levels.at(i);
Shinya Kitaoka 120a6e
    assert(level);
Shinya Kitaoka 120a6e
    assert(level->getSoundLevel());
Shinya Kitaoka 120a6e
    int start1 = level->getVisibleStartFrame();
Shinya Kitaoka 120a6e
    int end1   = level->getVisibleEndFrame();
Shinya Kitaoka 120a6e
    assert(start1 <= end1);
Shinya Kitaoka 120a6e
    if (i < size - 1) {
Shinya Kitaoka 120a6e
      ColumnLevel *nextLevel = m_levels.at(i + 1);
Shinya Kitaoka 120a6e
      assert(nextLevel);
Shinya Kitaoka 120a6e
      assert(nextLevel->getSoundLevel());
Shinya Kitaoka 120a6e
      int start2 = nextLevel->getVisibleStartFrame();
Shinya Kitaoka 120a6e
      int end2   = nextLevel->getVisibleEndFrame();
Shinya Kitaoka 120a6e
      assert(start2 <= end2);
Shinya Kitaoka 120a6e
      assert(end1 < start2);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::getCells(int row, int rowCount, TXshCell cells[]) {
Shinya Kitaoka 120a6e
  // le celle da settare sono [ra, rb]
Shinya Kitaoka 120a6e
  int ra = row;
Shinya Kitaoka 120a6e
  int rb = row + rowCount - 1;
Shinya Kitaoka 120a6e
  assert(ra <= rb);
Shinya Kitaoka 120a6e
  TXshCell *dstCell = cells;
Shinya Kitaoka 120a6e
  int r;
Shinya Kitaoka 120a6e
  for (r = ra; r <= rb; r++) *cells++ = getCell(r);
Shinya Kitaoka 120a6e
  checkColumn();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::setCellInEmptyFrame(int row, const TXshCell &cell) {
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return;
Shinya Kitaoka 120a6e
  TXshSoundLevel *soundLevel = cell.getSoundLevel();
Shinya Kitaoka 120a6e
  if (!soundLevel) return;
Shinya Kitaoka 120a6e
  int startOffset = cell.getFrameId().getNumber();
Shinya Kitaoka 120a6e
  int startFrame  = row - startOffset;
Shinya Kitaoka 120a6e
  int endOffset   = startFrame + soundLevel->getFrameCount() - 1 - row;
Shinya Kitaoka 120a6e
  insertColumnLevel(
Shinya Kitaoka 120a6e
      new ColumnLevel(soundLevel, startFrame, startOffset, endOffset));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshSoundColumn::setCell(int row, const TXshCell &cell) {
Shinya Kitaoka 120a6e
  return setCell(row, cell, false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshSoundColumn::setCell(int row, const TXshCell &cell,
Shinya Kitaoka 120a6e
                              bool updateSequence) {
Shinya Kitaoka 120a6e
  if (!canSetCell(cell)) return false;
Shinya Kitaoka 120a6e
  assert(row >= 0);
Shinya Kitaoka 120a6e
  ColumnLevel *lBefore = getColumnLevelByFrame(row - 1);
Shinya Kitaoka 120a6e
  ColumnLevel *l       = getColumnLevelByFrame(row);
Shinya Kitaoka 120a6e
  ColumnLevel *lNext   = getColumnLevelByFrame(row + 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Se non devo fare un update della sequenzialita' e la cella e' uguale a
Shinya Kitaoka 120a6e
  // quella gia' esistente ritorno.
Shinya Kitaoka 120a6e
  if (!updateSequence && l && l->getSoundLevel() == cell.getSoundLevel() &&
Shinya Kitaoka 120a6e
      row - l->getStartFrame() == cell.getFrameId().getNumber())
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool isBeforeLevelInSequence =
Shinya Kitaoka 120a6e
      (lBefore && lBefore->getSoundLevel() == cell.getSoundLevel() &&
Shinya Kitaoka 120a6e
       row - lBefore->getStartFrame() == cell.getFrameId().getNumber());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool isNextLevelInSequence =
Shinya Kitaoka 120a6e
      (lNext && lNext->getSoundLevel() == cell.getSoundLevel() &&
Shinya Kitaoka 120a6e
       row - lNext->getStartFrame() == cell.getFrameId().getNumber());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Modifico solo l'endOffset del BeforeLevel
Shinya Kitaoka 120a6e
  if (isBeforeLevelInSequence) {
Shinya Kitaoka 120a6e
    int oldEndOffset = lBefore->getEndOffset();
Shinya Kitaoka 120a6e
    int endOffset    = (lBefore->getVisibleEndFrame() != row) ? oldEndOffset - 1
Shinya Kitaoka 120a6e
                                                           : oldEndOffset;
Shinya Kitaoka 120a6e
    if (isNextLevelInSequence) {
Shinya Kitaoka 120a6e
      endOffset = lNext->getEndOffset();
Shinya Kitaoka 120a6e
      // Se precedente e successivo sono diversi elimino il successivo (caso in
Shinya Kitaoka 120a6e
      // cui inserisci un frame in successione su una cella vuota)
Shinya Kitaoka 120a6e
      if (lNext != lBefore) removeColumnLevel(lNext);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (l && l != lBefore) {
Shinya Kitaoka 120a6e
      if (l->getVisibleFrameCount() == 1)
Shinya Kitaoka 120a6e
        removeColumnLevel(l);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        l->setStartOffset(l->getStartOffset() + 1);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    lBefore->setEndOffset(endOffset);
Shinya Kitaoka 120a6e
    checkColumn();
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // Modifico solo lo startOffset del NextLevel
Shinya Kitaoka 120a6e
  if (isNextLevelInSequence) {
Shinya Kitaoka 120a6e
    int oldStartOffset = lNext->getStartOffset();
Shinya Kitaoka 120a6e
    int startOffset    = (lNext->getVisibleStartFrame() != row)
Shinya Kitaoka 120a6e
                          ? oldStartOffset - 1
Shinya Kitaoka 120a6e
                          : oldStartOffset;
Shinya Kitaoka 120a6e
    if (l && l != lNext) {
Shinya Kitaoka 120a6e
      if (l->getVisibleFrameCount() == 1)
Shinya Kitaoka 120a6e
        removeColumnLevel(l);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        l->setEndOffset(l->getEndOffset() + 1);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    lNext->setStartOffset(startOffset);
Shinya Kitaoka 120a6e
    checkColumn();
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // I Frame non sono in successione quindi devo inserire la cella in frame un
Shinya Kitaoka 120a6e
  // vuoto:
Shinya Kitaoka 120a6e
  clearCells(row, 1);
Shinya Kitaoka 120a6e
  setCellInEmptyFrame(row, cell);
Shinya Kitaoka 120a6e
  checkColumn();
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshSoundColumn::setCells(int row, int rowCount, const TXshCell cells[]) {
Shinya Kitaoka 120a6e
  assert(row >= 0);
Shinya Kitaoka 120a6e
  // le celle da settare sono [ra, rb]
Shinya Kitaoka 120a6e
  int ra = row;
Shinya Kitaoka 120a6e
  int rb = row + rowCount - 1;
Shinya Kitaoka 120a6e
  assert(ra <= rb);
Shinya Kitaoka 120a6e
  bool ret = false;
Shinya Kitaoka 120a6e
  int r;
Shinya Kitaoka 120a6e
  for (r = ra; r <= rb; r++) {
Shinya Kitaoka 120a6e
    bool isOneCellSet     = setCell(r, cells[r - ra]);
Shinya Kitaoka 120a6e
    if (isOneCellSet) ret = isOneCellSet;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::insertEmptyCells(int row, int rowCount) {
Shinya Kitaoka 120a6e
  if (m_levels.isEmpty())
Shinya Kitaoka 120a6e
    return;  // se la colonna e' vuota non devo inserire celle
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int ra = row;
Shinya Kitaoka 120a6e
  int rb = row + rowCount - 1;
Shinya Kitaoka 120a6e
  assert(ra <= rb);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Se il livello nella riga ra inizia prima devo "spezzarlo"
Shinya Kitaoka 120a6e
  ColumnLevel *l = getColumnLevelByFrame(ra);
Shinya Kitaoka 120a6e
  if (l && l->getVisibleStartFrame() < ra) {
Shinya Kitaoka 120a6e
    int oldOffset = l->getEndOffset();
Shinya Kitaoka 120a6e
    l->setEndOffset(oldOffset + l->getVisibleEndFrame() - ra + 1);
Shinya Kitaoka 120a6e
    insertColumnLevel(new ColumnLevel(l->getSoundLevel(), l->getStartFrame(),
Shinya Kitaoka 120a6e
                                      row - l->getStartFrame(), oldOffset));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Sposto il first frame di tutti i livelli successivi ad ra.
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = m_levels.count() - 1; i >= 0; i--) {
Shinya Kitaoka 120a6e
    ColumnLevel *cl = m_levels.at(i);
Shinya Kitaoka 120a6e
    if (cl->getVisibleStartFrame() < ra) continue;
Shinya Kitaoka 120a6e
    cl->setStartFrame(cl->getStartFrame() + rowCount);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  checkColumn();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::removeCells(int row, int rowCount, bool shift) {
Shinya Kitaoka 120a6e
  // le celle da cancellare sono [ra, rb]
Shinya Kitaoka 120a6e
  int ra = row;
Shinya Kitaoka 120a6e
  int rb = row + rowCount - 1;
Shinya Kitaoka 120a6e
  assert(ra <= rb);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = m_levels.size() - 1; i >= 0; i--) {
Shinya Kitaoka 120a6e
    ColumnLevel *l = m_levels.at(i);
Shinya Kitaoka 120a6e
    if (!l) continue;  // Non dovrebbe accadere!
Shinya Kitaoka 120a6e
    int visibleStartFrame = l->getVisibleStartFrame();
Shinya Kitaoka 120a6e
    int visibleEndFrame   = l->getVisibleEndFrame();
Shinya Kitaoka 120a6e
    // Fuori dal range da tagliare.
Shinya Kitaoka 120a6e
    if (visibleStartFrame > rb || visibleEndFrame < ra) continue;
Shinya Kitaoka 120a6e
    int newEndOffset   = l->getEndFrame() - ra + 1;
Shinya Kitaoka 120a6e
    int newStartOffset = rb - l->getStartFrame() + 1;
Shinya Kitaoka 120a6e
    // Il livello contiene il range da cancellare: devo "spezzare" il livello in
Shinya Kitaoka 120a6e
    // due.
Shinya Kitaoka 120a6e
    if (visibleStartFrame < ra && visibleEndFrame > rb) {
Shinya Kitaoka 120a6e
      int oldEndOffset = l->getEndOffset();
Shinya Kitaoka 120a6e
      l->setEndOffset(newEndOffset);
Shinya Kitaoka 120a6e
      insertColumnLevel(new ColumnLevel(l->getSoundLevel(), l->getStartFrame(),
Shinya Kitaoka 120a6e
                                        newStartOffset, oldEndOffset));
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (visibleStartFrame < ra) l->setEndOffset(newEndOffset);
Shinya Kitaoka 120a6e
    if (visibleEndFrame > rb) l->setStartOffset(newStartOffset);
Shinya Kitaoka 120a6e
    // Il livello e' contenuto nel range da cancellare: lo rimuovo.
Shinya Kitaoka 120a6e
    if (visibleStartFrame >= ra && visibleEndFrame <= rb) removeColumnLevel(l);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (shift) {
Shinya Kitaoka 120a6e
    for (i = m_levels.size() - 1; i >= 0; i--) {
Shinya Kitaoka 120a6e
      ColumnLevel *l = m_levels.at(i);
Shinya Kitaoka 120a6e
      if (!l) continue;  // Non dovrebbe accadere!
Shinya Kitaoka 120a6e
      int visibleStartFrame = l->getVisibleStartFrame();
Shinya Kitaoka 120a6e
      int visibleEndFrame   = l->getVisibleEndFrame();
Shinya Kitaoka 120a6e
      if (visibleStartFrame > ra)
Shinya Kitaoka 120a6e
        l->setStartFrame(l->getStartFrame() - rowCount);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Devo controllare se il livello precedente il taglio e quello successivo
Shinya Kitaoka 120a6e
    // sono in sequenza
Shinya Kitaoka 120a6e
    ColumnLevel *beforeL = getColumnLevelByFrame(ra - 1);
Shinya Kitaoka 120a6e
    ColumnLevel *nextL   = getColumnLevelByFrame(ra);
Shinya Kitaoka 120a6e
    if (beforeL && nextL &&
Shinya Kitaoka 120a6e
        beforeL->getSoundLevel() == nextL->getSoundLevel() &&
Shinya Kitaoka 120a6e
        beforeL->getStartFrame() == nextL->getStartFrame()) {
Shinya Kitaoka 120a6e
      beforeL->setEndOffset(nextL->getEndOffset());
Shinya Kitaoka 120a6e
      removeColumnLevel(nextL);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  checkColumn();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::clearCells(int row, int rowCount) {
Shinya Kitaoka 120a6e
  if (rowCount <= 0) return;
Shinya Kitaoka 120a6e
  if (m_levels.isEmpty())
Shinya Kitaoka 120a6e
    return;  // se la colonna e' vuota non devo "sbiancare" celle
Shinya Kitaoka 120a6e
  removeCells(row, rowCount, false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::removeCells(int row, int rowCount) {
Shinya Kitaoka 120a6e
  removeCells(row, rowCount, true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::updateCells(int row, int rowCount) {
Shinya Kitaoka 120a6e
  int r;
Shinya Kitaoka 120a6e
  for (r = row; r < row + rowCount; r++) {
Shinya Kitaoka 120a6e
    TXshCell cell = getCell(r);
Shinya Kitaoka 120a6e
    setCell(row, cell, true);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TXshSoundColumn::modifyCellRange(int row, int delta,
Shinya Kitaoka 120a6e
                                     bool modifyStartValue) {
Shinya Kitaoka 120a6e
  ColumnLevel *l = getColumnLevelByFrame(row);
Shinya Kitaoka 120a6e
  if (!l) return -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int startVisibleFrame = l->getVisibleStartFrame();
Shinya Kitaoka 120a6e
  int endVisibleFrame   = l->getVisibleEndFrame();
Shinya Kitaoka 120a6e
  // Non dovrebbe mai accadere, metto un controllo di sicurezza.
Shinya Kitaoka 120a6e
  if (startVisibleFrame != row && endVisibleFrame != row) return -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int r0 = delta > 0 ? row : row + delta;
Shinya Kitaoka 120a6e
  int r1 = delta > 0 ? row + delta : row;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int r;
Shinya Kitaoka 120a6e
  for (r = r0; r <= r1; r++) {
Shinya Kitaoka 120a6e
    ColumnLevel *oldL = getColumnLevelByFrame(r);
Shinya Kitaoka 120a6e
    if (!oldL || oldL == l) continue;
Shinya Kitaoka 120a6e
    int visibleStartFrame = oldL->getVisibleStartFrame();
Shinya Kitaoka 120a6e
    int visibleEndFrame   = oldL->getVisibleEndFrame();
Shinya Kitaoka 120a6e
    if (visibleStartFrame >= r0 && visibleEndFrame <= r1)
Shinya Kitaoka 120a6e
      removeColumnLevel(oldL);
Shinya Kitaoka 120a6e
    if (visibleStartFrame <= r0)
Shinya Kitaoka 120a6e
      oldL->setEndOffset(oldL->getEndOffset() + visibleEndFrame - r0 + 1);
Shinya Kitaoka 120a6e
    if (visibleEndFrame >= r1)
Shinya Kitaoka 120a6e
      oldL->setStartOffset(oldL->getStartOffset() + r1 - visibleStartFrame + 1);
Shinya Kitaoka 120a6e
    r = visibleEndFrame;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (modifyStartValue) {
Shinya Kitaoka 120a6e
    // Evito che vada oltre il limite infieriore
Shinya Kitaoka 120a6e
    if (endVisibleFrame < startVisibleFrame + delta)
Shinya Kitaoka 120a6e
      delta            = endVisibleFrame - startVisibleFrame;
Shinya Kitaoka 120a6e
    int newStartOffset = l->getStartOffset() + delta;
Shinya Kitaoka 120a6e
    // Evito che vada oltre il limite superiore
Shinya Kitaoka 120a6e
    if (newStartOffset < 0) newStartOffset = 0;
Shinya Kitaoka 120a6e
    l->setStartOffset(newStartOffset);
Shinya Kitaoka 120a6e
    checkColumn();
Shinya Kitaoka 120a6e
    getXsheet()->updateFrameCount();
Shinya Kitaoka 120a6e
    return l->getVisibleStartFrame();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Evito che vada oltre il limite superiore
Shinya Kitaoka 120a6e
  if (startVisibleFrame > endVisibleFrame + delta)
Shinya Kitaoka 120a6e
    delta = startVisibleFrame - endVisibleFrame;
Shinya Kitaoka 120a6e
  // Evito che vada oltre il limite inferiore
Shinya Kitaoka 120a6e
  int newEndOffset                   = l->getEndOffset() - delta;
Shinya Kitaoka 120a6e
  if (newEndOffset < 0) newEndOffset = 0;
Shinya Kitaoka 120a6e
  l->setEndOffset(newEndOffset);
Shinya Kitaoka 120a6e
  checkColumn();
Shinya Kitaoka 120a6e
  getXsheet()->updateFrameCount();
Shinya Kitaoka 120a6e
  return l->getVisibleEndFrame();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshSoundColumn::getLevelRange(int row, int &r0, int &r1) const {
Shinya Kitaoka 120a6e
  ColumnLevel *l = getColumnLevelByFrame(row);
Shinya Kitaoka 120a6e
  if (!l) {
Shinya Kitaoka 120a6e
    r0 = r1 = row;
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  r0 = l->getVisibleStartFrame();
Shinya Kitaoka 120a6e
  r1 = l->getVisibleEndFrame();
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshSoundColumn::getLevelRangeWithoutOffset(int row, int &r0,
Shinya Kitaoka 120a6e
                                                 int &r1) const {
Shinya Kitaoka 120a6e
  ColumnLevel *l = getColumnLevelByFrame(row);
Shinya Kitaoka 120a6e
  if (!l) {
Shinya Kitaoka 120a6e
    r0 = r1 = row;
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  r0 = l->getStartFrame();
Shinya Kitaoka 120a6e
  r1 = l->getEndFrame();
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::setXsheet(TXsheet *xsheet) {
Shinya Kitaoka 120a6e
  TXshColumn::setXsheet(xsheet);
Shinya Kitaoka 120a6e
  ToonzScene *scene = xsheet->getScene();
Shinya Kitaoka 120a6e
  if (!scene || m_levels.empty()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_isOldVersion) {
Shinya Kitaoka 120a6e
    assert(m_levels.size() == 1);
Shinya Kitaoka 120a6e
    scene->getLevelSet()->insertLevel(m_levels.at(0)->getSoundLevel());
Shinya Kitaoka 120a6e
    m_isOldVersion = false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TOutputProperties *properties = scene->getProperties()->getOutputProperties();
Shinya Kitaoka 120a6e
  setFrameRate(properties->getFrameRate());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::setFrameRate(double fps) {
Shinya Kitaoka 120a6e
  if (m_levels.empty()) return;
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < m_levels.size(); i++) {
Shinya Kitaoka 120a6e
    ColumnLevel *column        = m_levels.at(i);
Shinya Kitaoka 120a6e
    TXshSoundLevel *soundLevel = column->getSoundLevel();
Shinya Kitaoka 120a6e
    if (soundLevel->getFrameRate() != fps) soundLevel->setFrameRate(fps);
Shinya Kitaoka 120a6e
    column->setFrameRate(fps);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::updateFrameRate(double fps) {
Shinya Kitaoka 120a6e
  if (m_levels.empty()) return;
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < m_levels.size(); i++) {
Shinya Kitaoka 120a6e
    ColumnLevel *column        = m_levels.at(i);
Shinya Kitaoka 120a6e
    TXshSoundLevel *soundLevel = column->getSoundLevel();
Shinya Kitaoka 120a6e
    double oldFps              = soundLevel->getFrameRate();
Shinya Kitaoka 120a6e
    if (oldFps != fps) soundLevel->setFrameRate(fps);
Shinya Kitaoka 120a6e
    column->updateFrameRate(fps);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::setVolume(double value) {
Shinya Kitaoka 120a6e
  m_volume = tcrop<double>(value, 0.0, 1.0);</double>
Shinya Kitaoka 120a6e
  if (m_player && m_player->isPlaying())
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Shinya Kitaoka 120a6e
    m_player->setVolume(m_volume);
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
    stop();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double TXshSoundColumn::getVolume() const { return m_volume; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::play(TSoundTrackP soundtrack, int s0, int s1, bool loop) {
Shinya Kitaoka 120a6e
  if (!TSoundOutputDevice::installed()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_player) m_player = new TSoundOutputDevice();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_player) {
Shinya Kitaoka 120a6e
    try {
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Jeremy Bullock 6767be
      m_player->prepareVolume(m_volume);
Shinya Kitaoka 120a6e
      TSoundTrackP mixedTrack = soundtrack;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
      TSoundTrackP mixedTrack = TSoundTrack::create(
Shinya Kitaoka 120a6e
          soundtrack->getFormat(), soundtrack->getSampleCount());
Shinya Kitaoka 120a6e
      mixedTrack = TSop::mix(mixedTrack, soundtrack, 1.0, m_volume);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
      m_player->play(mixedTrack, s0, s1, loop);
Shinya Kitaoka 120a6e
      m_currentPlaySoundTrack = mixedTrack;
Toshihiro Shimizu 890ddd
#ifndef MACOSX
Shinya Kitaoka 120a6e
      m_timer.start();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    } catch (TSoundDeviceException &) {
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::play(ColumnLevel *columnLevel, int currentFrame) {
Shinya Kitaoka 120a6e
  assert(columnLevel);
Shinya Kitaoka 120a6e
  TXshSoundLevel *soundLevel = columnLevel->getSoundLevel();
Shinya Kitaoka 120a6e
  int offset                 = 0;
Shinya Kitaoka 120a6e
  int startFrame             = currentFrame - columnLevel->getStartFrame();
Shinya Kitaoka 120a6e
  int endFrame = soundLevel->getFrameCount() - columnLevel->getEndOffset();
Shinya Kitaoka 120a6e
  int spf      = soundLevel->getSamplePerFrame();
Shinya Kitaoka 120a6e
  int s0       = startFrame * spf;
Shinya Kitaoka 120a6e
  int s1       = endFrame * spf;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!soundLevel->getSoundTrack()) return;
Shinya Kitaoka 120a6e
  play(soundLevel->getSoundTrack(), s0, s1, false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::play(int currentFrame) {
Shinya Kitaoka 120a6e
  TSoundTrackP soundTrack = getOverallSoundTrack(currentFrame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!soundTrack) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int spf        = m_levels.at(0)->getSoundLevel()->getSamplePerFrame();
Shinya Kitaoka 120a6e
  int startFrame = (currentFrame - getFirstRow());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int s0 = startFrame * spf;
Shinya Kitaoka 120a6e
  int s1 = getMaxFrame() * spf;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  play(soundTrack, s0, s1, false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::stop() {
Shinya Kitaoka 120a6e
  if (m_player) {
Shinya Kitaoka 120a6e
    m_player->stop();
Shinya Kitaoka 120a6e
    m_player->close();
Shinya Kitaoka 120a6e
    m_player                = 0;
Shinya Kitaoka 120a6e
    m_currentPlaySoundTrack = TSoundTrackP();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshSoundColumn::isPlaying() const {
Shinya Kitaoka 120a6e
  return m_player && m_player->isPlaying();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::insertColumnLevel(ColumnLevel *columnLevel, int index) {
Shinya Kitaoka 120a6e
  if (index == -1) index = m_levels.size();
Shinya Kitaoka 120a6e
  m_levels.insert(index, columnLevel);
Shinya Kitaoka 120a6e
  qSort(m_levels.begin(), m_levels.end(), lessThan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::removeColumnLevel(ColumnLevel *columnLevel) {
Shinya Kitaoka 120a6e
  if (!columnLevel) return;
Shinya Kitaoka 120a6e
  int index = m_levels.indexOf(columnLevel);
Shinya Kitaoka 120a6e
  if (index == -1) return;
Shinya Kitaoka 120a6e
  m_levels.removeAt(index);
Shinya Kitaoka 120a6e
  delete columnLevel;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ColumnLevel *TXshSoundColumn::getColumnLevelByFrame(int frame) const {
Shinya Kitaoka 120a6e
  int levelCount = m_levels.size();
Shinya Kitaoka 120a6e
  for (int i = 0; i < levelCount; i++) {
Shinya Kitaoka 120a6e
    ColumnLevel *l             = m_levels.at(i);
Shinya Kitaoka 120a6e
    TXshSoundLevel *soundLevel = l->getSoundLevel();
Shinya Kitaoka 120a6e
    int startFrame             = l->getStartFrame() + l->getStartOffset();
Shinya Kitaoka 120a6e
    int frameCount =
Shinya Kitaoka 120a6e
        soundLevel->getFrameCount() - l->getStartOffset() - l->getEndOffset();
Shinya Kitaoka 120a6e
    if (startFrame <= frame && startFrame + frameCount > frame) return l;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ColumnLevel *TXshSoundColumn::getColumnLevel(int index) {
Shinya Kitaoka 120a6e
  if (index < 0 || index >= m_levels.count()) return 0;
Shinya Kitaoka 120a6e
  return m_levels.at(index);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TXshSoundColumn::getColumnLevelIndex(ColumnLevel *columnLevel) const {
Shinya Kitaoka 120a6e
  return m_levels.indexOf(columnLevel);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::clear() {
Shinya Kitaoka 120a6e
  int sequenceCount = m_levels.size();
Shinya Kitaoka 120a6e
  for (int i = 0; i < sequenceCount; i++) {
Shinya Kitaoka 120a6e
    ColumnLevel *s = m_levels[i];
Shinya Kitaoka 120a6e
    delete s;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_levels.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::onTimerOut() {
Toshihiro Shimizu 890ddd
#ifndef MACOSX
Shinya Kitaoka 120a6e
  if (m_player && m_player->isAllQueuedItemsPlayed()) stop();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshSoundColumn::scrub(int fromFrame, int toFrame) {
Shinya Kitaoka 120a6e
  if (!isCamstandVisible()) return;
Shinya Kitaoka 120a6e
  TSoundTrackP soundTrack = getOverallSoundTrack(fromFrame, toFrame + 1);
Shinya Kitaoka 120a6e
  if (!soundTrack) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  play(soundTrack, 0, soundTrack->getSampleCount(), false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundTrackP TXshSoundColumn::getOverallSoundTrack(int fromFrame, int toFrame,
Shinya Kitaoka 120a6e
                                                   double fps,
Shinya Kitaoka 120a6e
                                                   TSoundTrackFormat format) {
Shinya Kitaoka 120a6e
  int levelsCount = m_levels.size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (levelsCount == 0) return 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (fps == -1) fps             = m_levels[0]->getSoundLevel()->getFrameRate();
Shinya Kitaoka 120a6e
  if (fromFrame == -1) fromFrame = getFirstRow();
Shinya Kitaoka 120a6e
  if (toFrame == -1) toFrame     = getMaxFrame();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (format.m_sampleRate == 0) {
Shinya Kitaoka 120a6e
    // Found the best format inside the soundsequences
Shinya Kitaoka 120a6e
    int sampleRate    = 0;
Shinya Kitaoka 120a6e
    int bitsPerSample = 8;
Shinya Kitaoka 120a6e
    int channels      = 1;
Shinya Kitaoka 120a6e
    for (int i = 0; i < levelsCount; i++) {
Shinya Kitaoka 120a6e
      TXshSoundLevel *soundLevel = m_levels.at(i)->getSoundLevel();
Shinya Kitaoka 120a6e
      TSoundTrackP soundTrack    = soundLevel->getSoundTrack();
Shinya Kitaoka 120a6e
      if (soundTrack.getPointer() == 0) continue;
Shinya Kitaoka 120a6e
      TSoundTrackFormat f = soundTrack->getFormat();
Shinya Kitaoka 120a6e
      if ((int)f.m_sampleRate > sampleRate) {
Shinya Kitaoka 120a6e
        format.m_sampleRate   = f.m_sampleRate;
Shinya Kitaoka 120a6e
        sampleRate            = f.m_sampleRate;
Shinya Kitaoka 120a6e
        format.m_channelCount = f.m_channelCount;
Shinya Kitaoka 120a6e
        channels              = f.m_channelCount;
Shinya Kitaoka 120a6e
        format.m_signedSample = f.m_signedSample;
Shinya Kitaoka 120a6e
        format.m_bitPerSample = f.m_bitPerSample;
Shinya Kitaoka 120a6e
        bitsPerSample         = f.m_bitPerSample;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (f.m_channelCount > channels) {
Shinya Kitaoka 120a6e
        format.m_channelCount = f.m_channelCount;
Shinya Kitaoka 120a6e
        channels              = f.m_channelCount;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (f.m_bitPerSample > bitsPerSample) {
Shinya Kitaoka 120a6e
        format.m_bitPerSample = f.m_bitPerSample;
Shinya Kitaoka 120a6e
        bitsPerSample         = f.m_bitPerSample;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If there is no soundSequence I use a default format
Shinya Kitaoka 120a6e
  if (levelsCount == 0 || format.m_sampleRate == 0) {
Shinya Kitaoka 120a6e
    format.m_sampleRate   = 44100;
Shinya Kitaoka 120a6e
    format.m_bitPerSample = 16;
Shinya Kitaoka 120a6e
    format.m_channelCount = 1;
Shinya Kitaoka 120a6e
    format.m_signedSample = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Jeremy Bullock 6767be
// We prefer to have 22050 as a maximum sampleRate (to avoid crashes or
Jeremy Bullock 6767be
// another issues)
Jeremy Bullock 6767be
#ifndef MACOSX
Shinya Kitaoka 120a6e
  if (format.m_sampleRate >= 44100) format.m_sampleRate = 22050;
Jeremy Bullock 6767be
#else
Jeremy Bullock 6767be
  QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
Jeremy Bullock 6767be
  QList<int> ssrs = info.supportedSampleRates();</int>
Jeremy Bullock 6767be
  if (!ssrs.contains(format.m_sampleRate)) format.m_sampleRate = 44100;
Jeremy Bullock 6767be
  QAudioFormat qFormat;
Jeremy Bullock 6767be
  qFormat.setSampleRate(format.m_sampleRate);
Jeremy Bullock 6767be
  qFormat.setSampleType(format.m_signedSample ? QAudioFormat::SignedInt
Jeremy Bullock 6767be
                                              : QAudioFormat::UnSignedInt);
Jeremy Bullock 6767be
  qFormat.setSampleSize(format.m_bitPerSample);
Jeremy Bullock 6767be
  qFormat.setCodec("audio/pcm");
Jeremy Bullock 6767be
  qFormat.setChannelCount(format.m_channelCount);
Jeremy Bullock 6767be
  qFormat.setByteOrder(QAudioFormat::LittleEndian);
Jeremy Bullock 6767be
  if (!info.isFormatSupported((qFormat))) {
Jeremy Bullock 6767be
    qFormat               = info.nearestFormat(qFormat);
Jeremy Bullock 6767be
    format.m_bitPerSample = qFormat.sampleSize();
Jeremy Bullock 6767be
    format.m_channelCount = qFormat.channelCount();
Jeremy Bullock 6767be
    format.m_sampleRate   = qFormat.sampleRate();
Jeremy Bullock 6767be
    if (qFormat.sampleType() == QAudioFormat::SignedInt)
Jeremy Bullock 6767be
      format.m_signedSample = true;
Jeremy Bullock 6767be
    else
Jeremy Bullock 6767be
      format.m_signedSample = false;
Jeremy Bullock 6767be
  }
Jeremy Bullock 6767be
#endif
Shinya Kitaoka 120a6e
  // Create the soundTrack
Shinya Kitaoka 120a6e
  double samplePerFrame = format.m_sampleRate / fps;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // In seconds
Shinya Kitaoka 120a6e
  double duration = double(toFrame - fromFrame) / fps;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Seconds to Sample  (it is more accurate than using sampleCount
Shinya Kitaoka 120a6e
  double dsamp = duration * format.m_sampleRate;
Shinya Kitaoka 120a6e
  TINT32 lsamp = (TINT32)dsamp;
Shinya Kitaoka 120a6e
  if ((double)lsamp < dsamp - TConsts::epsilon) lsamp++;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TSoundTrackP overallSoundTrack;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    overallSoundTrack = TSoundTrack::create(format, lsamp);
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &) {
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Blank the whole track
Shinya Kitaoka 120a6e
  overallSoundTrack->blank(0, lsamp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (levelsCount == 0) return overallSoundTrack;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int i = 0; i < levelsCount; i++) {
Shinya Kitaoka 120a6e
    ColumnLevel *l             = m_levels.at(i);
Shinya Kitaoka 120a6e
    TXshSoundLevel *soundLevel = l->getSoundLevel();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Check if the soundtrack is inside the frame Range.
Shinya Kitaoka 120a6e
    int levelStartFrame = l->getStartFrame() + l->getStartOffset();
Shinya Kitaoka 120a6e
    int levelEndFrame   = levelStartFrame + soundLevel->getFrameCount() -
Shinya Kitaoka 120a6e
                        l->getStartOffset() - l->getEndOffset();
Shinya Kitaoka 120a6e
    // If the soundSequence is completely before fromFrame I will skip it
Shinya Kitaoka 120a6e
    if ((levelStartFrame < fromFrame && levelEndFrame < fromFrame)) continue;
Shinya Kitaoka 120a6e
    // If the soundSequence is after toFrame I don't check the others (that
Shinya Kitaoka 120a6e
    // comes later..)
Shinya Kitaoka 120a6e
    if ((levelStartFrame > toFrame && levelEndFrame > toFrame)) break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Extract the right soundTrack (using the offsets)
Shinya Kitaoka 120a6e
    // (pay attention to convert it before)
Shinya Kitaoka 120a6e
    TSoundTrackP s = soundLevel->getSoundTrack();
Shinya Kitaoka 120a6e
    if (!s) continue;
Shinya Kitaoka 120a6e
    TSoundTrackP soundTrack = TSop::convert(s, format);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int s0delta                              = 0;
Shinya Kitaoka 120a6e
    if (fromFrame > levelStartFrame) s0delta = fromFrame - levelStartFrame;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int s0 = (l->getStartOffset() + s0delta) * samplePerFrame;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int s1delta                          = 0;
Shinya Kitaoka 120a6e
    if (toFrame < levelEndFrame) s1delta = levelEndFrame - toFrame;
Shinya Kitaoka 120a6e
    int s1 = (soundLevel->getFrameCount() - l->getEndOffset() - s1delta) *
Shinya Kitaoka 120a6e
             samplePerFrame;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (s1 > 0 && s1 >= s0) {
Shinya Kitaoka 120a6e
      soundTrack = soundTrack->extract(s0, s1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Copy the sound track
Shinya Kitaoka 120a6e
      overallSoundTrack->copy(
Shinya Kitaoka 120a6e
          soundTrack,
Shinya Kitaoka 120a6e
          int((levelStartFrame - fromFrame) *
Shinya Kitaoka 120a6e
              samplePerFrame));  // The int cast is IMPORTANT, since
Shinya Kitaoka 120a6e
    }                            // there are 2 overloads (int & double)
Shinya Kitaoka 120a6e
  }                              // with DIFFERENT SCALES. We mean the
Shinya Kitaoka 120a6e
                                 // SAMPLES-BASED one.
Shinya Kitaoka 120a6e
  return overallSoundTrack;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundTrackP TXshSoundColumn::mixingTogether(
Shinya Kitaoka 120a6e
    const std::vector<txshsoundcolumn *=""> &vect, int fromFrame, int toFrame,</txshsoundcolumn>
Shinya Kitaoka 120a6e
    double fps) {
Shinya Kitaoka 120a6e
  int offset       = 0xffff;
Shinya Kitaoka 120a6e
  long sampleCount = 0;
Shinya Kitaoka 120a6e
  std::vector<tsoundtrackp> tracks;</tsoundtrackp>
Shinya Kitaoka 120a6e
  TSoundTrackP mix;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int size = vect.size(), i = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ColumnLevel *l = vect[0]->getColumnLevel(0);
Shinya Kitaoka 120a6e
  if (!l)        // May happen if the sound level is not
Shinya Kitaoka 120a6e
    return mix;  // correctly loaded from disk
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXshSoundLevel *soundLevel = l->getSoundLevel();
Shinya Kitaoka 120a6e
  assert(soundLevel);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (fps == -1) fps             = soundLevel->getFrameRate();
Shinya Kitaoka 120a6e
  if (fromFrame == -1) fromFrame = 0;
Shinya Kitaoka 120a6e
  if (toFrame == -1) toFrame     = getXsheet()->getFrameCount();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!soundLevel->getSoundTrack()) return mix;
Shinya Kitaoka 120a6e
  TSoundTrackFormat format = soundLevel->getSoundTrack()->getFormat();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXshSoundColumn *c = 0;
Shinya Kitaoka 120a6e
  int j;
Shinya Kitaoka 120a6e
  for (j = 0; j < size; ++j) {
Shinya Kitaoka 120a6e
    TXshSoundColumn *oldC = c;
Shinya Kitaoka 120a6e
    c                     = vect[j];
Shinya Kitaoka 120a6e
    if (j == 0) {
Shinya Kitaoka 120a6e
      mix = c->getOverallSoundTrack(fromFrame, toFrame, fps, format);
Shinya Kitaoka 120a6e
      TSoundTrackP mixedTrack =
Shinya Kitaoka 120a6e
          TSoundTrack::create(mix->getFormat(), mix->getSampleCount());
Shinya Kitaoka 120a6e
      mix = TSop::mix(mixedTrack, mix, 1.0, c->getVolume());
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    assert(oldC);
Shinya Kitaoka 120a6e
    if (c->getVolume() == 0 || c->isEmpty()) {
Shinya Kitaoka 120a6e
      c = oldC;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    mix =
Shinya Kitaoka 120a6e
        TSop::mix(mix, c->getOverallSoundTrack(fromFrame, toFrame, fps, format),
Shinya Kitaoka 120a6e
                  1.0, c->getVolume());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Per ora perche mov vuole solo 16 bit
Shinya Kitaoka 120a6e
  TSoundTrackFormat fmt                            = mix->getFormat();
Shinya Kitaoka 120a6e
  if (fmt.m_bitPerSample != 16) fmt.m_bitPerSample = 16;
Shinya Kitaoka 120a6e
  mix                                              = TSop::convert(mix, fmt);
Shinya Kitaoka 120a6e
  return mix;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PERSIST_IDENTIFIER(TXshSoundColumn, "soundColumn")