Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2023 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "abstractfxresolver.h"
24 :
25 : #include "log.h"
26 :
27 : using namespace muse::audio;
28 : using namespace muse::audio::fx;
29 :
30 0 : std::vector<IFxProcessorPtr> AbstractFxResolver::resolveFxList(const TrackId trackId, const AudioFxChain& fxChain,
31 : const OutputSpec& outputSpec)
32 : {
33 0 : if (fxChain.empty()) {
34 0 : LOGE() << "invalid fx chain for trackId: " << trackId;
35 0 : return {};
36 : }
37 :
38 0 : FxMap& fxMap = m_tracksFxMap[trackId];
39 0 : updateTrackFxMap(fxMap, trackId, fxChain, outputSpec);
40 :
41 0 : return muse::values(fxMap);
42 : }
43 :
44 0 : std::vector<IFxProcessorPtr> AbstractFxResolver::resolveMasterFxList(const AudioFxChain& fxChain, const OutputSpec& outputSpec)
45 : {
46 0 : if (fxChain.empty()) {
47 0 : LOGE() << "invalid master fx params";
48 0 : return {};
49 : }
50 :
51 0 : updateMasterFxMap(fxChain, outputSpec);
52 :
53 0 : return muse::values(m_masterFxMap);
54 : }
55 :
56 0 : void AbstractFxResolver::refresh()
57 : {
58 0 : }
59 :
60 0 : void AbstractFxResolver::clearAllFx()
61 : {
62 0 : m_tracksFxMap.clear();
63 0 : m_masterFxMap.clear();
64 0 : }
65 :
66 0 : void AbstractFxResolver::updateTrackFxMap(FxMap& fxMap, const audio::TrackId trackId, const AudioFxChain& newFxChain,
67 : const OutputSpec& outputSpec)
68 : {
69 0 : AudioFxChain currentFxChain;
70 0 : for (const auto& pair : fxMap) {
71 0 : currentFxChain.emplace(pair.first, pair.second->params());
72 : }
73 :
74 0 : audio::AudioFxChain fxToRemove;
75 0 : fxChainToRemove(currentFxChain, newFxChain, fxToRemove);
76 :
77 0 : for (const auto& pair : fxToRemove) {
78 0 : removeTrackFx(trackId, pair.second.resourceMeta.id, pair.second.chainOrder);
79 :
80 0 : currentFxChain.erase(pair.first);
81 0 : fxMap.erase(pair.first);
82 : }
83 :
84 0 : audio::AudioFxChain fxToCreate;
85 0 : fxChainToCreate(currentFxChain, newFxChain, fxToCreate);
86 :
87 0 : for (const auto& pair : fxToCreate) {
88 0 : IFxProcessorPtr fxPtr = createTrackFx(trackId, pair.second, outputSpec);
89 0 : if (fxPtr) {
90 0 : fxMap.emplace(pair.first, std::move(fxPtr));
91 : }
92 0 : }
93 0 : }
94 :
95 0 : void AbstractFxResolver::updateMasterFxMap(const AudioFxChain& newFxChain, const OutputSpec& outputSpec)
96 : {
97 0 : AudioFxChain currentFxChain;
98 0 : for (const auto& pair : m_masterFxMap) {
99 0 : currentFxChain.emplace(pair.first, pair.second->params());
100 : }
101 :
102 0 : audio::AudioFxChain fxToRemove;
103 0 : fxChainToRemove(currentFxChain, newFxChain, fxToRemove);
104 :
105 0 : for (const auto& pair : fxToRemove) {
106 0 : removeMasterFx(pair.second.resourceMeta.id, pair.second.chainOrder);
107 :
108 0 : currentFxChain.erase(pair.first);
109 0 : m_masterFxMap.erase(pair.first);
110 : }
111 :
112 0 : audio::AudioFxChain fxToCreate;
113 0 : fxChainToCreate(currentFxChain, newFxChain, fxToCreate);
114 :
115 0 : for (const auto& pair : fxToCreate) {
116 0 : IFxProcessorPtr fx = createMasterFx(pair.second, outputSpec);
117 0 : if (fx) {
118 0 : m_masterFxMap.emplace(pair.first, fx);
119 : }
120 0 : }
121 0 : }
122 :
123 0 : void AbstractFxResolver::removeMasterFx(const AudioResourceId&, AudioFxChainOrder)
124 : {
125 0 : }
126 :
127 0 : void AbstractFxResolver::removeTrackFx(const audio::TrackId, const AudioResourceId&, AudioFxChainOrder)
128 : {
129 0 : }
130 :
131 0 : void AbstractFxResolver::fxChainToRemove(const AudioFxChain& currentFxChain,
132 : const AudioFxChain& newFxChain,
133 : AudioFxChain& resultChain)
134 : {
135 0 : for (auto it = currentFxChain.cbegin(); it != currentFxChain.cend(); ++it) {
136 0 : auto newIt = newFxChain.find(it->first);
137 :
138 0 : if (newIt == newFxChain.cend()) {
139 0 : resultChain.insert({ it->first, it->second });
140 0 : continue;
141 : }
142 :
143 0 : if (it->second.resourceMeta != newIt->second.resourceMeta) {
144 0 : resultChain.insert({ it->first, it->second });
145 : }
146 : }
147 0 : }
148 :
149 0 : void AbstractFxResolver::fxChainToCreate(const AudioFxChain& currentFxChain,
150 : const AudioFxChain& newFxChain,
151 : AudioFxChain& resultChain)
152 : {
153 0 : for (auto it = newFxChain.cbegin(); it != newFxChain.cend(); ++it) {
154 0 : if (currentFxChain.find(it->first) != currentFxChain.cend()) {
155 0 : continue;
156 : }
157 :
158 0 : if (it->second.isValid()) {
159 0 : resultChain.insert({ it->first, it->second });
160 : }
161 : }
162 0 : }
|