159 lines
5.6 KiB
C++
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
|