mumble-voip_mumble/src/mumble/AudioOutput.h

159 lines
5.6 KiB
C++

// Copyright 2007-2023 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
#ifndef MUMBLE_MUMBLE_AUDIOOUTPUT_H_
#define MUMBLE_MUMBLE_AUDIOOUTPUT_H_
#include <QtCore/QObject>
#include <QtCore/QThread>
#include <boost/shared_ptr.hpp>
#include "MumbleProtocol.h"
#ifdef USE_MANUAL_PLUGIN
# include "ManualPlugin.h"
#endif
#ifndef SPEAKER_FRONT_LEFT
# define SPEAKER_FRONT_LEFT 0x1
# define SPEAKER_FRONT_RIGHT 0x2
# define SPEAKER_FRONT_CENTER 0x4
# define SPEAKER_LOW_FREQUENCY 0x8
# define SPEAKER_BACK_LEFT 0x10
# define SPEAKER_BACK_RIGHT 0x20
# define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
# define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
# define SPEAKER_BACK_CENTER 0x100
# define SPEAKER_SIDE_LEFT 0x200
# define SPEAKER_SIDE_RIGHT 0x400
# define SPEAKER_TOP_CENTER 0x800
# define SPEAKER_TOP_FRONT_LEFT 0x1000
# define SPEAKER_TOP_FRONT_CENTER 0x2000
# define SPEAKER_TOP_FRONT_RIGHT 0x4000
# define SPEAKER_TOP_BACK_LEFT 0x8000
# define SPEAKER_TOP_BACK_CENTER 0x10000
# define SPEAKER_TOP_BACK_RIGHT 0x20000
#endif
#include "Audio.h"
class AudioOutput;
class ClientUser;
class AudioOutputBuffer;
class AudioOutputToken;
typedef boost::shared_ptr< AudioOutput > AudioOutputPtr;
class AudioOutputRegistrar {
private:
Q_DISABLE_COPY(AudioOutputRegistrar)
public:
static QMap< QString, AudioOutputRegistrar * > *qmNew;
static QString current;
static AudioOutputPtr newFromChoice(QString choice = QString());
const QString name;
int priority;
AudioOutputRegistrar(const QString &n, int priority = 0);
virtual ~AudioOutputRegistrar();
virtual AudioOutput *create() = 0;
virtual const QVariant getDeviceChoice() = 0;
virtual const QList< audioDevice > getDeviceChoices() = 0;
virtual void setDeviceChoice(const QVariant &, Settings &) = 0;
virtual bool canMuteOthers() const;
virtual bool usesOutputDelay() const;
virtual bool canExclusive() const;
};
class AudioOutput : public QThread {
private:
Q_OBJECT
Q_DISABLE_COPY(AudioOutput)
private:
/// Speaker positional vector
float *fSpeakers = nullptr;
float *fSpeakerVolume = nullptr;
bool *bSpeakerPositional = nullptr;
/// Used when panning stereo stream w.r.t. each speaker.
float *fStereoPanningFactor = nullptr;
void removeBuffer(AudioOutputBuffer *);
private slots:
void handleInvalidatedBuffer(AudioOutputBuffer *);
void handlePositionedBuffer(AudioOutputBuffer *, float x, float y, float z);
protected:
enum { SampleShort, SampleFloat } eSampleFormat = SampleFloat;
volatile bool bRunning = true;
unsigned int iFrameSize = SAMPLE_RATE / 100;
volatile unsigned int iMixerFreq = 0;
unsigned int iChannels = 0;
unsigned int iSampleSize = 0;
unsigned int iBufferSize = 0;
QReadWriteLock qrwlOutputs;
QMultiHash< const ClientUser *, AudioOutputBuffer * > qmOutputs;
#ifdef USE_MANUAL_PLUGIN
QHash< unsigned int, Position2D > positions;
#endif
void initializeMixer(const unsigned int *chanmasks, bool forceheadphone = false);
bool mix(void *output, unsigned int frameCount);
public:
void wipe();
/// Construct an AudioOutput.
///
/// This constructor is only ever called by Audio::startOutput(), and is guaranteed
/// to be called on the application's main thread.
AudioOutput();
/// Destroy an AudioOutput.
///
/// This destructor is only ever called by Audio::stopOutput() and Audio::stop(),
/// and is guaranteed to be called on the application's main thread.
~AudioOutput() Q_DECL_OVERRIDE;
void addFrameToBuffer(ClientUser *sender, const Mumble::Protocol::AudioData &audioData);
AudioOutputToken playSample(const QString &filename, float volume, bool loop = false);
void run() Q_DECL_OVERRIDE = 0;
virtual bool isAlive() const;
const float *getSpeakerPos(unsigned int &nspeakers);
static float calcGain(float dotproduct, float distance);
unsigned int getMixerFreq() const;
void setBufferSize(unsigned int bufferSize);
void setBufferPosition(const AudioOutputToken &, float x, float y, float z);
void removeToken(AudioOutputToken &);
void removeUser(const ClientUser *);
signals:
/// Signal emitted whenever an audio source has been fetched
///
/// @param outputPCM The fetched output PCM
/// @param sampleCount The amount of samples in the output
/// @param channelCount The amount of channels in the output
/// @param sampleRate The used sample rate in Hz
/// @param isSpeech Whether the fetched output is considered to be speech
/// @param A pointer to the user that this speech belongs to or nullptr if this isn't speech
void audioSourceFetched(float *outputPCM, unsigned int sampleCount, unsigned int channelCount,
unsigned int sampleRate, bool isSpeech, const ClientUser *user);
/// Signal emitted whenever an audio is about to be played to the user
///
/// @param outputPCM The output PCM that is to be played
/// @param sampleCount The amount of samples in the output
/// @param channelCount The amount of channels in the output
/// @param sampleRate The used sample rate in Hz
/// @param modifiedAudio Pointer to bool if audio has been modified or not and should be played
void audioOutputAboutToPlay(float *outputPCM, unsigned int sampleCount, unsigned int channelCount,
unsigned int sampleRate, bool *modifiedAudio);
void bufferInvalidated(AudioOutputBuffer *);
void bufferPositionChanged(AudioOutputBuffer *, float x, float y, float z);
};
#endif