123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /*
- * Mixer.h - effect-mixer for LMMS
- *
- * Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
- *
- * This file is part of LMMS - https://lmms.io
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program (see COPYING); if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- */
- #ifndef MIXER_H
- #define MIXER_H
- #include "Model.h"
- #include "EffectChain.h"
- #include "JournallingObject.h"
- #include "ThreadableJob.h"
- #include <atomic>
- #include <QColor>
- class MixerRoute;
- typedef QVector<MixerRoute *> MixerRouteVector;
- class MixerChannel : public ThreadableJob
- {
- public:
- MixerChannel( int idx, Model * _parent );
- virtual ~MixerChannel();
- EffectChain m_fxChain;
- // set to true when input fed from mixToChannel or child channel
- bool m_hasInput;
- // set to true if any effect in the channel is enabled and running
- bool m_stillRunning;
- float m_peakLeft;
- float m_peakRight;
- sampleFrame * m_buffer;
- bool m_muteBeforeSolo;
- BoolModel m_muteModel;
- BoolModel m_soloModel;
- FloatModel m_volumeModel;
- QString m_name;
- QMutex m_lock;
- int m_channelIndex; // what channel index are we
- bool m_queued; // are we queued up for rendering yet?
- bool m_muted; // are we muted? updated per period so we don't have to call m_muteModel.value() twice
- // pointers to other channels that this one sends to
- MixerRouteVector m_sends;
- // pointers to other channels that send to this one
- MixerRouteVector m_receives;
- bool requiresProcessing() const override { return true; }
- void unmuteForSolo();
- void setColor (QColor newColor)
- {
- m_color = newColor;
- m_hasColor = true;
- }
- // TODO C++17 and above: use std::optional instead
- QColor m_color;
- bool m_hasColor;
-
- std::atomic_int m_dependenciesMet;
- void incrementDeps();
- void processed();
-
- private:
- void doProcessing() override;
- };
- class MixerRoute : public QObject
- {
- Q_OBJECT
- public:
- MixerRoute( MixerChannel * from, MixerChannel * to, float amount );
- virtual ~MixerRoute();
-
- mix_ch_t senderIndex() const
- {
- return m_from->m_channelIndex;
- }
-
- mix_ch_t receiverIndex() const
- {
- return m_to->m_channelIndex;
- }
-
- FloatModel * amount()
- {
- return &m_amount;
- }
-
- MixerChannel * sender() const
- {
- return m_from;
- }
-
- MixerChannel * receiver() const
- {
- return m_to;
- }
-
- void updateName();
-
- private:
- MixerChannel * m_from;
- MixerChannel * m_to;
- FloatModel m_amount;
- };
- class LMMS_EXPORT Mixer : public Model, public JournallingObject
- {
- Q_OBJECT
- public:
- Mixer();
- virtual ~Mixer();
- void mixToChannel( const sampleFrame * _buf, mix_ch_t _ch );
- void prepareMasterMix();
- void masterMix( sampleFrame * _buf );
- void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
- void loadSettings( const QDomElement & _this ) override;
- QString nodeName() const override
- {
- return "mixer";
- }
- MixerChannel * mixerChannel( int _ch )
- {
- return m_mixerChannels[_ch];
- }
- // make the output of channel fromChannel go to the input of channel toChannel
- // it is safe to call even if the send already exists
- MixerRoute * createChannelSend(mix_ch_t fromChannel, mix_ch_t toChannel,
- float amount = 1.0f);
- MixerRoute * createRoute( MixerChannel * from, MixerChannel * to, float amount );
- // delete the connection made by createChannelSend
- void deleteChannelSend(mix_ch_t fromChannel, mix_ch_t toChannel);
- void deleteChannelSend( MixerRoute * route );
- // determine if adding a send from sendFrom to
- // sendTo would result in an infinite mixer loop.
- bool isInfiniteLoop(mix_ch_t fromChannel, mix_ch_t toChannel);
- bool checkInfiniteLoop( MixerChannel * from, MixerChannel * to );
- // return the FloatModel of fromChannel sending its output to the input of
- // toChannel. NULL if there is no send.
- FloatModel * channelSendModel(mix_ch_t fromChannel, mix_ch_t toChannel);
- // add a new channel to the mixer.
- // returns the index of the channel that was just added
- int createChannel();
- // delete a channel from the mixer.
- void deleteChannel(int index);
- // delete all the mixer channels except master and remove all effects
- void clear();
- // re-arrange channels
- void moveChannelLeft(int index);
- void moveChannelRight(int index);
- // reset a channel's name, fx, sends, etc
- void clearChannel(mix_ch_t channelIndex);
- // rename channels when moving etc. if they still have their original name
- void validateChannelName( int index, int oldIndex );
- void toggledSolo();
- void activateSolo();
- void deactivateSolo();
- inline mix_ch_t numChannels() const
- {
- return m_mixerChannels.size();
- }
- MixerRouteVector m_mixerRoutes;
- private:
- // the mixer channels in the mixer. index 0 is always master.
- QVector<MixerChannel *> m_mixerChannels;
- // make sure we have at least num channels
- void allocateChannelsTo(int num);
- int m_lastSoloed;
- } ;
- #endif
|