2010-12-08 04:36:10 +01:00
|
|
|
// Copyright (c) 2010, Niels Martin Hansen
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
|
|
// and/or other materials provided with the distribution.
|
|
|
|
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
|
|
// may be used to endorse or promote products derived from this software
|
|
|
|
// without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
//
|
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
|
|
|
/// @file audio_timing.h
|
|
|
|
/// @brief Construction-functions for timing controller objects
|
|
|
|
/// @ingroup audio_ui
|
|
|
|
|
|
|
|
class AssDialogue;
|
2010-12-08 09:10:00 +01:00
|
|
|
class AssFile;
|
2011-09-28 21:44:07 +02:00
|
|
|
class AssKaraoke;
|
2011-11-18 23:56:45 +01:00
|
|
|
class AudioRenderingStyleRanges;
|
2011-09-28 21:44:07 +02:00
|
|
|
namespace agi { struct Context; }
|
2010-12-08 04:36:10 +01:00
|
|
|
|
2012-02-02 00:59:12 +01:00
|
|
|
#include "audio_marker.h"
|
2011-07-15 06:04:13 +02:00
|
|
|
|
2010-12-08 04:36:10 +01:00
|
|
|
/// @class AudioTimingController
|
|
|
|
/// @brief Base class for objects controlling audio timing
|
|
|
|
///
|
2011-01-16 08:14:53 +01:00
|
|
|
/// There is just one active audio timing controller at a time per audio
|
|
|
|
/// controller. The timing controller manages the timing mode and supplies
|
|
|
|
/// markers that can be manipulated to the audio display, as well as the
|
|
|
|
/// current selection.
|
2010-12-08 04:36:10 +01:00
|
|
|
///
|
2011-01-16 08:14:53 +01:00
|
|
|
/// The timing controller must then be sent the marker drag events as well as
|
|
|
|
/// clicks in empty areas of the audio display.
|
2011-09-15 07:16:26 +02:00
|
|
|
class AudioTimingController : public AudioMarkerProvider, public AudioLabelProvider {
|
2010-12-08 09:09:16 +01:00
|
|
|
protected:
|
|
|
|
/// The primary playback range has changed, usually as a result of user interaction.
|
|
|
|
agi::signal::Signal<> AnnounceUpdatedPrimaryRange;
|
|
|
|
|
|
|
|
/// One or more rendering style ranges have changed in the timing controller.
|
|
|
|
agi::signal::Signal<> AnnounceUpdatedStyleRanges;
|
|
|
|
|
Audio/Timing: implement tap-to-time
Tap-to-time provides the user the ability to tap to the lyrics/syllables
of the song in order to time lines or karaoke. It consists of these
extra UI interactions:
- **Indicator**: tap marker: a designated marker that can be moved to
the current audio position; indicated in:
- the audio display by a green arrow underneath a marker
- the karaoke display by a green-colored syllable
- **Control**: tap marker: the tap marker can be changed by selecting
syllables on audio display in karaoke mode, or clicking the markers on
audio display in dialogue mode
- **Control**: ctrl-right-click audio display: starts playing the audio
from that exact position until the end of the file
- **Option**: Timing/Tap To Time: enables the tap marker indicator and
commands
- **Button**: time_opt_tap_to_time: toggles the Timing/Tap To Time option
- **Button**: time_tap_connect (hotkey I): a command that:
- moves the tap marker's position to the current playing audio
position
- sets the next marker to be the tap marker
- if the tap marker is already the last marker AND BOTH autocommit AND
next-line-on-commit is ON, will move onto the next line
- if moved on to the next line, also sets the start marker to the current
audio position, so the two lines are connected, and moves to the
next tap marker (essentially reinvoking time_tap_connect once)
- **Button**: time_tap_no_connect (hotkey O): similar to
time_tap_connect, except it will not set the next line's start
position even if moved to the next line
Expected workflow:
1) User loads song lyrics
2) User splits each line into syllables
3) User turns on tap-to-time, autocommit, and next-line-on-commit
4) User plays audio from beginning, tapping time_tap_connect to each
syllable, occasionally tapping time_tap_no_connect when a break between
lines is desired
5) If user messes up a line, they can set the tap marker to where they
want to restart from, and ctrl-right-click to start the audio a few
seconds before it
6) Syllables can be split/merged at will, and adjustments to timing can
be done using normal karaoke timing controls
2018-10-21 09:42:33 +02:00
|
|
|
/// The tap marker has changed in the timing controller.
|
|
|
|
agi::signal::Signal<> AnnounceUpdatedTapMarker;
|
|
|
|
|
2010-12-08 04:36:10 +01:00
|
|
|
public:
|
|
|
|
/// @brief Get any warning message to show in the audio display
|
|
|
|
/// @return The warning message to show, may be empty if there is none
|
|
|
|
virtual wxString GetWarningMessage() const = 0;
|
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
/// @brief Get the time range the user is most likely to want to see for the current state
|
|
|
|
/// @return A time range
|
2010-12-08 04:36:10 +01:00
|
|
|
///
|
|
|
|
/// This is used for "bring working area into view" operations.
|
2012-02-02 00:58:58 +01:00
|
|
|
virtual TimeRange GetIdealVisibleTimeRange() const = 0;
|
2010-12-08 04:36:10 +01:00
|
|
|
|
|
|
|
/// @brief Get the primary playback range
|
2012-02-02 00:58:58 +01:00
|
|
|
/// @return A time range
|
2010-12-08 04:36:10 +01:00
|
|
|
///
|
2012-02-02 00:58:58 +01:00
|
|
|
/// Get the time range the user is most likely to want to play back
|
2011-01-16 08:14:59 +01:00
|
|
|
/// currently.
|
2012-02-02 00:58:58 +01:00
|
|
|
virtual TimeRange GetPrimaryPlaybackRange() const = 0;
|
2010-12-08 04:36:10 +01:00
|
|
|
|
2012-10-05 01:15:45 +02:00
|
|
|
/// @brief Get the active line's time
|
|
|
|
/// @return A time range
|
|
|
|
///
|
|
|
|
/// Get the time range which the active line would have if any pending
|
|
|
|
/// modifications were committed.
|
|
|
|
virtual TimeRange GetActiveLineRange() const = 0;
|
|
|
|
|
2011-11-18 23:56:45 +01:00
|
|
|
/// @brief Get all rendering style ranges
|
2012-01-08 02:37:12 +01:00
|
|
|
/// @param[out] ranges Rendering ranges will be added to this
|
2011-11-18 23:56:45 +01:00
|
|
|
virtual void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const = 0;
|
|
|
|
|
Audio/Timing: implement tap-to-time
Tap-to-time provides the user the ability to tap to the lyrics/syllables
of the song in order to time lines or karaoke. It consists of these
extra UI interactions:
- **Indicator**: tap marker: a designated marker that can be moved to
the current audio position; indicated in:
- the audio display by a green arrow underneath a marker
- the karaoke display by a green-colored syllable
- **Control**: tap marker: the tap marker can be changed by selecting
syllables on audio display in karaoke mode, or clicking the markers on
audio display in dialogue mode
- **Control**: ctrl-right-click audio display: starts playing the audio
from that exact position until the end of the file
- **Option**: Timing/Tap To Time: enables the tap marker indicator and
commands
- **Button**: time_opt_tap_to_time: toggles the Timing/Tap To Time option
- **Button**: time_tap_connect (hotkey I): a command that:
- moves the tap marker's position to the current playing audio
position
- sets the next marker to be the tap marker
- if the tap marker is already the last marker AND BOTH autocommit AND
next-line-on-commit is ON, will move onto the next line
- if moved on to the next line, also sets the start marker to the current
audio position, so the two lines are connected, and moves to the
next tap marker (essentially reinvoking time_tap_connect once)
- **Button**: time_tap_no_connect (hotkey O): similar to
time_tap_connect, except it will not set the next line's start
position even if moved to the next line
Expected workflow:
1) User loads song lyrics
2) User splits each line into syllables
3) User turns on tap-to-time, autocommit, and next-line-on-commit
4) User plays audio from beginning, tapping time_tap_connect to each
syllable, occasionally tapping time_tap_no_connect when a break between
lines is desired
5) If user messes up a line, they can set the tap marker to where they
want to restart from, and ctrl-right-click to start the audio a few
seconds before it
6) Syllables can be split/merged at will, and adjustments to timing can
be done using normal karaoke timing controls
2018-10-21 09:42:33 +02:00
|
|
|
/// @brief Return the position of the tap marker
|
|
|
|
virtual int GetTapMarkerPosition() const = 0;
|
|
|
|
|
|
|
|
/// @brief Return the index of the tap marker
|
|
|
|
virtual size_t GetTapMarkerIndex() const = 0;
|
|
|
|
|
2012-04-27 21:07:07 +02:00
|
|
|
enum NextMode {
|
|
|
|
/// Advance to the next timing unit, whether it's a line or a sub-part
|
|
|
|
/// of a line such as a karaoke syllable
|
|
|
|
TIMING_UNIT = 0,
|
|
|
|
|
|
|
|
/// @brief Advance to the next line
|
|
|
|
///
|
|
|
|
/// This may create a new line if there are no more lines in the file,
|
|
|
|
/// but should never modify existing lines
|
|
|
|
LINE,
|
|
|
|
|
|
|
|
/// @brief Advance to the next line using default timing
|
|
|
|
///
|
|
|
|
/// This may create new lines when needed, and should discard any
|
|
|
|
/// existing timing data in favor of the defaults
|
|
|
|
LINE_RESET_DEFAULT
|
|
|
|
};
|
|
|
|
|
2010-12-08 04:36:10 +01:00
|
|
|
/// @brief Go to next timing unit
|
2012-04-27 21:07:07 +02:00
|
|
|
/// @param mode What sort of timing unit should be advanced to
|
|
|
|
virtual void Next(NextMode mode) = 0;
|
2010-12-08 04:36:10 +01:00
|
|
|
|
|
|
|
/// @brief Go to the previous timing unit
|
|
|
|
///
|
|
|
|
/// Rewinds the timing controller to the previous timing unit.
|
|
|
|
virtual void Prev() = 0;
|
|
|
|
|
|
|
|
/// @brief Commit all changes
|
|
|
|
///
|
|
|
|
/// Stores all changes permanently.
|
|
|
|
virtual void Commit() = 0;
|
|
|
|
|
|
|
|
/// @brief Revert all changes
|
|
|
|
///
|
|
|
|
/// Revert all changes to the last committed state.
|
|
|
|
virtual void Revert() = 0;
|
|
|
|
|
2012-02-22 23:00:54 +01:00
|
|
|
/// Add lead-in time to the current timing unit
|
|
|
|
virtual void AddLeadIn() = 0;
|
|
|
|
|
|
|
|
/// Add lead-out time to the current timing unit
|
|
|
|
virtual void AddLeadOut() = 0;
|
|
|
|
|
2012-07-14 15:35:15 +02:00
|
|
|
/// Modify the length of the current and possibly following timing units
|
|
|
|
/// @param delta Amount to add in centiseconds
|
|
|
|
/// @param shift_following Should the following things be shifted by delta?
|
|
|
|
virtual void ModifyLength(int delta, bool shift_following) = 0;
|
|
|
|
|
|
|
|
/// Modify the start time of the current timing unit
|
|
|
|
/// @param delta Amount to add in centiseconds
|
|
|
|
virtual void ModifyStart(int delta) = 0;
|
|
|
|
|
Audio/Timing: implement tap-to-time
Tap-to-time provides the user the ability to tap to the lyrics/syllables
of the song in order to time lines or karaoke. It consists of these
extra UI interactions:
- **Indicator**: tap marker: a designated marker that can be moved to
the current audio position; indicated in:
- the audio display by a green arrow underneath a marker
- the karaoke display by a green-colored syllable
- **Control**: tap marker: the tap marker can be changed by selecting
syllables on audio display in karaoke mode, or clicking the markers on
audio display in dialogue mode
- **Control**: ctrl-right-click audio display: starts playing the audio
from that exact position until the end of the file
- **Option**: Timing/Tap To Time: enables the tap marker indicator and
commands
- **Button**: time_opt_tap_to_time: toggles the Timing/Tap To Time option
- **Button**: time_tap_connect (hotkey I): a command that:
- moves the tap marker's position to the current playing audio
position
- sets the next marker to be the tap marker
- if the tap marker is already the last marker AND BOTH autocommit AND
next-line-on-commit is ON, will move onto the next line
- if moved on to the next line, also sets the start marker to the current
audio position, so the two lines are connected, and moves to the
next tap marker (essentially reinvoking time_tap_connect once)
- **Button**: time_tap_no_connect (hotkey O): similar to
time_tap_connect, except it will not set the next line's start
position even if moved to the next line
Expected workflow:
1) User loads song lyrics
2) User splits each line into syllables
3) User turns on tap-to-time, autocommit, and next-line-on-commit
4) User plays audio from beginning, tapping time_tap_connect to each
syllable, occasionally tapping time_tap_no_connect when a break between
lines is desired
5) If user messes up a line, they can set the tap marker to where they
want to restart from, and ctrl-right-click to start the audio a few
seconds before it
6) Syllables can be split/merged at will, and adjustments to timing can
be done using normal karaoke timing controls
2018-10-21 09:42:33 +02:00
|
|
|
/// Move tap marker position to given position
|
|
|
|
/// @param position to move marker to
|
|
|
|
virtual void MoveTapMarker(int ms) = 0;
|
|
|
|
|
|
|
|
/// Go to next tap marker
|
|
|
|
/// @return True if moved to the next marker, False if tap marker is already
|
|
|
|
/// the last marker of the line
|
|
|
|
virtual bool NextTapMarker() = 0;
|
|
|
|
|
2010-12-08 04:36:10 +01:00
|
|
|
/// @brief Determine if a position is close to a draggable marker
|
2012-02-02 00:58:58 +01:00
|
|
|
/// @param ms The time in milliseconds to test
|
|
|
|
/// @param sensitivity Distance in milliseconds to consider markers as nearby
|
|
|
|
/// @return True if a marker is close by the given time, as defined by sensitivity
|
2010-12-08 04:36:10 +01:00
|
|
|
///
|
2011-01-16 08:14:59 +01:00
|
|
|
/// This is solely for hit-testing against draggable markers, for
|
|
|
|
/// controlling the mouse cursor.
|
2014-05-14 15:40:01 +02:00
|
|
|
virtual bool IsNearbyMarker(int ms, int sensitivity, bool alt_down) const = 0;
|
2010-12-08 04:36:10 +01:00
|
|
|
|
2019-09-11 15:55:14 +02:00
|
|
|
/// @brief Return the text of the currently selected syllab
|
|
|
|
virtual std::string GetCurrentSylText() const { return ""; }
|
|
|
|
|
|
|
|
/// @ brief Set the text for the currently selected syllab
|
|
|
|
virtual void SetCurrentSylText(std::string new_text) {}
|
|
|
|
|
2012-02-10 01:04:13 +01:00
|
|
|
/// @brief The user pressed the left mouse button on the audio
|
2012-02-02 00:58:58 +01:00
|
|
|
/// @param ms The time in milliseconds the user clicked
|
2012-02-10 01:04:13 +01:00
|
|
|
/// @param ctrl_down Is the user currently holding the ctrl key down?
|
2018-10-21 09:31:19 +02:00
|
|
|
/// @param alt_down Is the user currently holding the alt key down?
|
2012-02-02 00:58:58 +01:00
|
|
|
/// @param sensitivity Distance in milliseconds to consider existing markers
|
|
|
|
/// @param snap_range Maximum snapping range in milliseconds
|
2012-02-10 01:04:13 +01:00
|
|
|
/// @return All audio markers at the clicked position which are eligible
|
|
|
|
/// to be dragged, if any.
|
2014-05-12 21:07:46 +02:00
|
|
|
virtual std::vector<AudioMarker*> OnLeftClick(int ms, bool ctrl_down, bool alt_down, int sensitivity, int snap_range) = 0;
|
2010-12-08 04:36:10 +01:00
|
|
|
|
2012-02-10 01:04:13 +01:00
|
|
|
/// @brief The user pressed the right mouse button on the audio
|
2012-02-02 00:58:58 +01:00
|
|
|
/// @param ms The time in milliseconds the user clicked
|
2012-02-10 01:04:13 +01:00
|
|
|
/// @param ctrl_down Is the user currently holding the ctrl key down?
|
2012-02-02 00:58:58 +01:00
|
|
|
/// @param sensitivity Distance in milliseconds to consider existing markers
|
|
|
|
/// @param snap_range Maximum snapping range in milliseconds
|
2012-02-10 01:04:13 +01:00
|
|
|
/// @return All audio markers at the clicked position which are eligible
|
|
|
|
/// to be dragged, if any.
|
|
|
|
virtual std::vector<AudioMarker*> OnRightClick(int ms, bool ctrl_down, int sensitivity, int snap_range) = 0;
|
2010-12-08 04:36:10 +01:00
|
|
|
|
2012-02-10 01:04:13 +01:00
|
|
|
/// @brief The user dragged one or more timing markers
|
|
|
|
/// @param marker The markers being dragged. This is guaranteed to be
|
|
|
|
/// a vector returned from OnLeftClick or OnRightClick.
|
2012-02-02 00:58:58 +01:00
|
|
|
/// @param new_position Time position the marker was dragged to
|
2012-02-10 01:04:13 +01:00
|
|
|
/// @param snap_range Maximum snapping range in milliseconds
|
|
|
|
virtual void OnMarkerDrag(std::vector<AudioMarker*> const& marker, int new_position, int snap_range) = 0;
|
2010-12-08 04:36:10 +01:00
|
|
|
|
|
|
|
/// @brief Destructor
|
2014-04-25 19:01:07 +02:00
|
|
|
virtual ~AudioTimingController() = default;
|
2010-12-08 09:09:16 +01:00
|
|
|
|
|
|
|
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedPrimaryRange, AddUpdatedPrimaryRangeListener)
|
|
|
|
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedStyleRanges, AddUpdatedStyleRangesListener)
|
Audio/Timing: implement tap-to-time
Tap-to-time provides the user the ability to tap to the lyrics/syllables
of the song in order to time lines or karaoke. It consists of these
extra UI interactions:
- **Indicator**: tap marker: a designated marker that can be moved to
the current audio position; indicated in:
- the audio display by a green arrow underneath a marker
- the karaoke display by a green-colored syllable
- **Control**: tap marker: the tap marker can be changed by selecting
syllables on audio display in karaoke mode, or clicking the markers on
audio display in dialogue mode
- **Control**: ctrl-right-click audio display: starts playing the audio
from that exact position until the end of the file
- **Option**: Timing/Tap To Time: enables the tap marker indicator and
commands
- **Button**: time_opt_tap_to_time: toggles the Timing/Tap To Time option
- **Button**: time_tap_connect (hotkey I): a command that:
- moves the tap marker's position to the current playing audio
position
- sets the next marker to be the tap marker
- if the tap marker is already the last marker AND BOTH autocommit AND
next-line-on-commit is ON, will move onto the next line
- if moved on to the next line, also sets the start marker to the current
audio position, so the two lines are connected, and moves to the
next tap marker (essentially reinvoking time_tap_connect once)
- **Button**: time_tap_no_connect (hotkey O): similar to
time_tap_connect, except it will not set the next line's start
position even if moved to the next line
Expected workflow:
1) User loads song lyrics
2) User splits each line into syllables
3) User turns on tap-to-time, autocommit, and next-line-on-commit
4) User plays audio from beginning, tapping time_tap_connect to each
syllable, occasionally tapping time_tap_no_connect when a break between
lines is desired
5) If user messes up a line, they can set the tap marker to where they
want to restart from, and ctrl-right-click to start the audio a few
seconds before it
6) Syllables can be split/merged at will, and adjustments to timing can
be done using normal karaoke timing controls
2018-10-21 09:42:33 +02:00
|
|
|
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedTapMarker, AddUpdatedTapMarkerListener)
|
2010-12-08 04:36:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/// @brief Create a standard dialogue audio timing controller
|
2011-09-28 21:44:44 +02:00
|
|
|
/// @param c Project context
|
2014-04-23 01:21:53 +02:00
|
|
|
std::unique_ptr<AudioTimingController> CreateDialogueTimingController(agi::Context *c);
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
/// @brief Create a karaoke audio timing controller
|
|
|
|
/// @param c Project context
|
|
|
|
/// @param kara Karaoke model
|
2014-04-23 01:21:53 +02:00
|
|
|
std::unique_ptr<AudioTimingController> CreateKaraokeTimingController(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed);
|