1 #pragma once
2 
3 #ifndef TXSHSOUNDCOLUMN_INCLUDED
4 #define TXSHSOUNDCOLUMN_INCLUDED
5 
6 #include "toonz/txshcolumn.h"
7 #include "toonz/txshcell.h"
8 #include "toonz/txshsoundlevel.h"
9 #include "tsound.h"
10 
11 #include <QList>
12 #include <QTimer>
13 
14 #undef DVAPI
15 #undef DVVAR
16 #ifdef TOONZLIB_EXPORTS
17 #define DVAPI DV_EXPORT_API
18 #define DVVAR DV_EXPORT_VAR
19 #else
20 #define DVAPI DV_IMPORT_API
21 #define DVVAR DV_IMPORT_VAR
22 #endif
23 
24 //=============================================================================
25 // forward declarations
26 class TFilePath;
27 
28 //=============================================================================
29 //  ColumnLevel
30 //=============================================================================
31 
32 class ColumnLevel {
33   TXshSoundLevelP m_soundLevel;
34 
35   /*!Offsets: in frames. Start offset is a positive number.*/
36   int m_startOffset;
37   /*!Offsets: in frames. End offset is a positive number(to subtract to..).*/
38   int m_endOffset;
39 
40   //! Starting frame in the timeline
41   int m_startFrame;
42 
43   //! frameRate
44   double m_fps;
45 
46 public:
47   ColumnLevel(TXshSoundLevel *soundLevel = 0, int startFrame = -1,
48               int startOffset = -1, int endOffset = -1, double fps = -1);
49   ~ColumnLevel();
50   ColumnLevel *clone() const;
51 
52   //! Overridden from TXshLevel
getSoundLevel()53   TXshSoundLevel *getSoundLevel() const { return m_soundLevel.getPointer(); }
setSoundLevel(TXshSoundLevelP level)54   void setSoundLevel(TXshSoundLevelP level) { m_soundLevel = level; }
55 
56   void loadData(TIStream &is);
57   void saveData(TOStream &os);
58 
59   void setStartOffset(int value);
getStartOffset()60   int getStartOffset() const { return m_startOffset; }
61 
62   void setEndOffset(int value);
getEndOffset()63   int getEndOffset() const { return m_endOffset; }
64 
65   void setOffsets(int startOffset, int endOffset);
66 
67   //! Return the starting frame without offsets.
setStartFrame(int frame)68   void setStartFrame(int frame) { m_startFrame = frame; }
getStartFrame()69   int getStartFrame() const { return m_startFrame; }
70 
71   //! Return the ending frame without offsets.
72   int getEndFrame() const;
73 
74   //! Return frame count without offset.
75   int getFrameCount() const;
76 
77   //! Return frame count with offset.
78   int getVisibleFrameCount() const;
79 
80   //! Return start frame with offset.
81   int getVisibleStartFrame() const;
82   //! Return last frame with offset.
83   int getVisibleEndFrame() const;
84   //! Updates m_startOfset and m_endOffset.
85   void updateFrameRate(double newFrameRate);
86 
setFrameRate(double fps)87   void setFrameRate(double fps) { m_fps = fps; }
88 };
89 
90 //=============================================================================
91 //! The TXshSoundColumn class provides a sound column in xsheet and allows its
92 //! management through cell concept.
93 /*!Inherits \b TXshCellColumn. */
94 //=============================================================================
95 
96 class DVAPI TXshSoundColumn final : public QObject, public TXshCellColumn {
97   Q_OBJECT
98 
99   PERSIST_DECLARATION(TXshSoundColumn)
100   TSoundOutputDevice *m_player;
101 
102   QList<ColumnLevel *> m_levels;  // owner
103 
104   /*!Used to menage current playback.*/
105   TSoundTrackP m_currentPlaySoundTrack;
106 
107   //! From 0.0 to 1.0
108   double m_volume;
109   bool m_isOldVersion;
110 
111   QTimer m_timer;
112 
113 public:
114   TXshSoundColumn();
115   ~TXshSoundColumn();
116 
117   TXshColumn::ColumnType getColumnType() const override;
getSoundColumn()118   TXshSoundColumn *getSoundColumn() override { return this; }
119 
120   bool canSetCell(const TXshCell &cell) const override;
121 
122   TXshColumn *clone() const override;
123 
124   /*! Clear column and set src level. */
125   void assignLevels(const TXshSoundColumn *src);
126 
127   void loadData(TIStream &is) override;
128   void saveData(TOStream &os) override;
129 
130   /*! r0 : min row not empty, r1 : max row not empty. Return row count.*/
131   int getRange(int &r0, int &r1) const override;
132   /*! Last not empty row - first not empty row. */
133   int getRowCount() const override;
134   /*! Return max row not empty. */
135   int getMaxFrame() const override;
136   /*! Return min row not empty.*/
137   int getFirstRow() const override;
138 
139   const TXshCell &getCell(int row) const override;
140   TXshCell getSoundCell(int row);
141   void getCells(int row, int rowCount, TXshCell cells[]) override;
142 
143   bool setCell(int row, const TXshCell &cell) override;
144   /*! Return false if cannot set cells.*/
145   bool setCells(int row, int rowCount, const TXshCell cells[]) override;
146 
147   void insertEmptyCells(int row, int rowCount) override;
148 
149   void clearCells(int row, int rowCount) override;
150   void removeCells(int row, int rowCount) override;
151 
152   /*! Check if frames from \b row to \b row+rowCount are in sequence and
153    * collapse level if it is true. */
154   void updateCells(int row, int rowCount);
155 
156   /*! Modify range of level sound in row. Return new range value of the level in
157 row.
158 N.B. Row must be the first or last cell of a sound level. */
159   int modifyCellRange(int row, int delta, bool modifyStartValue);
160 
161   bool isCellEmpty(int row) const override;
162   /*! r0 : min row not empty of level in row, r1 : max row not empty of level in
163 row.
164 Return true if level range is not empty.*/
165   bool getLevelRange(int row, int &r0, int &r1) const override;
166   /*! r0 : min possible (without offset) row of level in row, r1 : max possible
167 (without offset) row of level in row.
168 Return true if level range is not empty.*/
169   bool getLevelRangeWithoutOffset(int row, int &r0, int &r1) const;
170 
171   /*! Only debug. */
172   void checkColumn() const override;
173 
174   void setXsheet(TXsheet *xsheet) override;
175   void setFrameRate(double fps);
176   void updateFrameRate(double fps);
177 
178   //! From 0.0 to 1.0
179   void setVolume(double value);
180   double getVolume() const;
181 
getCurrentPlaySoundTruck()182   TSoundTrackP getCurrentPlaySoundTruck() { return m_currentPlaySoundTrack; }
183 
184   //! s0 and s1 are samples
185   void play(TSoundTrackP soundtrack, int s0, int s1, bool loop);
186   /*! Play the whole soundSequence, currentFrame it is used to compute an offset
187 when the user play a single level and hence the audio behind..*/
188   void play(ColumnLevel *ss, int currentFrame);
189   void play(int currentFrame = 0);
190   void stop();
191 
192   bool isPlaying() const;
193 
194   void scrub(int fromFrame, int toFrame);
195 
196   TSoundTrackP getOverallSoundTrack(
197       int fromFrame = -1, int toFram = -1, double fps = -1,
198       TSoundTrackFormat format = TSoundTrackFormat());
199 
200   TSoundTrackP mixingTogether(const std::vector<TXshSoundColumn *> &vect,
201                               int fromFrame = -1, int toFram = -1,
202                               double fps = -1);
203 
204 protected:
205   bool setCell(int row, const TXshCell &cell, bool updateSequence);
206   void removeCells(int row, int rowCount, bool shift);
207 
208   void setCellInEmptyFrame(int row, const TXshCell &cell);
209 
210   /*! If index == -1 insert soundColumnLevel at last and than order
211    * soundColumnLevel by startFrame. */
212   void insertColumnLevel(ColumnLevel *columnLevel, int index = -1);
213   void removeColumnLevel(ColumnLevel *columnLevel);
214 
215   ColumnLevel *getColumnLevelByFrame(int frame) const;
216   ColumnLevel *getColumnLevel(int index);
217   int getColumnLevelIndex(ColumnLevel *ss) const;
218   void clear();
219 
220 protected slots:
221   void onTimerOut();
222 };
223 
224 #ifdef _WIN32
225 template class DV_EXPORT_API TSmartPointerT<TXshSoundColumn>;
226 #endif
227 typedef TSmartPointerT<TXshSoundColumn> TXshSoundColumnP;
228 
229 #endif
230