1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Rosegarden
5 A MIDI and audio sequencer and musical notation editor.
6 Copyright 2000-2021 the Rosegarden development team.
7
8 Other copyrights also apply to some parts of this work. Please
9 see the AUTHORS file and individual file headers for details.
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version. See the file
15 COPYING included with this distribution for more information.
16 */
17
18
19 #include "AudioSegmentRescaleCommand.h"
20
21 #include "misc/AppendLabel.h"
22 #include "misc/Strings.h"
23 #include "misc/Debug.h"
24 #include "base/Event.h"
25 #include "base/Composition.h"
26 #include "base/NotationTypes.h"
27 #include "base/Segment.h"
28 #include "document/RosegardenDocument.h"
29 #include "sound/AudioFileTimeStretcher.h"
30 #include "sound/AudioFileManager.h"
31 #include <QString>
32
33
34 namespace Rosegarden
35 {
36
AudioSegmentRescaleCommand(RosegardenDocument * doc,Segment * s,float ratio)37 AudioSegmentRescaleCommand::AudioSegmentRescaleCommand(RosegardenDocument *doc,
38 Segment *s,
39 float ratio) :
40 NamedCommand(getGlobalName()),
41 m_afm(&doc->getAudioFileManager()),
42 m_stretcher(new AudioFileTimeStretcher(m_afm)),
43 m_segment(s),
44 m_newSegment(nullptr),
45 m_timesGiven(false),
46 m_startTime(0),
47 m_endMarkerTime(0),
48 m_fid(-1),
49 m_ratio(ratio),
50 m_detached(false)
51 {
52 // nothing
53 }
54
AudioSegmentRescaleCommand(RosegardenDocument * doc,Segment * s,float ratio,timeT st,timeT emt)55 AudioSegmentRescaleCommand::AudioSegmentRescaleCommand(RosegardenDocument *doc,
56 Segment *s,
57 float ratio,
58 timeT st,
59 timeT emt) :
60 NamedCommand(getGlobalName()),
61 m_afm(&doc->getAudioFileManager()),
62 m_stretcher(new AudioFileTimeStretcher(m_afm)),
63 m_segment(s),
64 m_newSegment(nullptr),
65 m_timesGiven(true),
66 m_startTime(st),
67 m_endMarkerTime(emt),
68 m_fid(-1),
69 m_ratio(ratio),
70 m_detached(false)
71 {
72 // nothing
73 }
74
~AudioSegmentRescaleCommand()75 AudioSegmentRescaleCommand::~AudioSegmentRescaleCommand()
76 {
77 delete m_stretcher;
78
79 if (m_detached) {
80 delete m_segment;
81 } else {
82 delete m_newSegment;
83 }
84 }
85
86 void
setProgressDialog(QPointer<QProgressDialog> progressDialog)87 AudioSegmentRescaleCommand::setProgressDialog(
88 QPointer<QProgressDialog> progressDialog)
89 {
90 if (m_stretcher)
91 m_stretcher->setProgressDialog(progressDialog);
92 }
93
94 void
execute()95 AudioSegmentRescaleCommand::execute()
96 {
97 // Audio segments only.
98 if (m_segment->getType() != Segment::Audio) {
99 RG_WARNING << "WARNING: execute() called with a non-audio segment.";
100 return;
101 }
102
103 // If we don't have the rescaled segment yet, create it.
104 if (!m_newSegment) {
105
106 // Rescale the audio file.
107
108 AudioFileId sourceFileId = m_segment->getAudioFileId();
109 float absoluteRatio = m_ratio;
110
111 RG_DEBUG << "AudioSegmentRescaleCommand: segment file id " << sourceFileId << ", given ratio " << m_ratio;
112
113 if (m_segment->getStretchRatio() != 1.f &&
114 m_segment->getStretchRatio() != 0.f) {
115 sourceFileId = m_segment->getUnstretchedFileId();
116 absoluteRatio *= m_segment->getStretchRatio();
117 RG_DEBUG << "AudioSegmentRescaleCommand: unstretched file id " << sourceFileId << ", prev ratio " << m_segment->getStretchRatio() << ", resulting ratio " << absoluteRatio;
118 }
119
120 if (!m_timesGiven) {
121 m_endMarkerTime = m_segment->getStartTime() +
122 (m_segment->getEndMarkerTime() - m_segment->getStartTime()) * m_ratio;
123 }
124
125 m_fid = m_stretcher->getStretchedAudioFile(sourceFileId,
126 absoluteRatio);
127 // If the stretch failed, bail.
128 if (m_fid < 0)
129 return;
130
131 // Audio file was rescaled successfully. Create the new Segment.
132
133 m_newSegment = m_segment->clone(false);
134
135 std::string label = m_newSegment->getLabel();
136 m_newSegment->setLabel(appendLabel(label, qstrtostr(tr("(rescaled)"))));
137
138 m_newSegment->setAudioFileId(m_fid);
139 m_newSegment->setUnstretchedFileId(sourceFileId);
140 m_newSegment->setStretchRatio(absoluteRatio);
141 m_newSegment->setAudioStartTime(m_segment->getAudioStartTime() *
142 m_ratio);
143 if (m_timesGiven) {
144 m_newSegment->setStartTime(m_startTime);
145 m_newSegment->setAudioEndTime(m_segment->getAudioEndTime() *
146 m_ratio);
147 m_newSegment->setEndMarkerTime(m_endMarkerTime);
148 } else {
149 m_newSegment->setEndMarkerTime(m_endMarkerTime);
150 m_newSegment->setAudioEndTime(m_segment->getAudioEndTime() *
151 m_ratio);
152 }
153 }
154
155 m_segment->getComposition()->addSegment(m_newSegment);
156 m_segment->getComposition()->detachSegment(m_segment);
157
158 // m_newSegment->setEndMarkerTime
159 // (startTime + rescale(m_segment->getEndMarkerTime() - startTime));
160
161 m_detached = true;
162 }
163
164 void
unexecute()165 AudioSegmentRescaleCommand::unexecute()
166 {
167 if (m_newSegment) {
168 m_newSegment->getComposition()->addSegment(m_segment);
169 m_newSegment->getComposition()->detachSegment(m_newSegment);
170 m_detached = false;
171 }
172 }
173
174 }
175