add AudioInjector class to pull samples from URL and inject

This commit is contained in:
Stephen Birarda 2013-12-19 12:28:37 -08:00
parent 9c39bcba4c
commit eac3b6be65
7 changed files with 118 additions and 37 deletions

View file

@ -458,9 +458,31 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) {
int16_t ringBufferSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO];
_ringBuffer.readSamples(ringBufferSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO);
// add the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL from each QByteArray
// in our _localInjectionByteArrays QVector to the _localInjectedSamples
// add to the output samples whatever is in the _localAudioOutput byte array
// that lets this user hear sound effects and loopback (if enabled)
for (int b = 0; b < _localInjectionByteArrays.size(); b++) {
QByteArray audioByteArray = _localInjectionByteArrays.at(b);
int16_t* byteArraySamples = (int16_t*) audioByteArray.data();
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
_localInjectedSamples[i] = glm::clamp(_localInjectedSamples[i] + byteArraySamples[i],
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
}
// pull out the bytes we just read for outputs
audioByteArray.remove(0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
if (audioByteArray.size() == 0) {
// if there isn't anything left to inject from this byte array, remove it from the vector
_localInjectionByteArrays.remove(b);
}
}
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
ringBufferSamples[i * 2] = glm::clamp(ringBufferSamples[i * 2] + _localInjectedSamples[i],
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
@ -696,6 +718,11 @@ void Audio::startDrumSound(float volume, float frequency, float duration, float
_drumSoundSample = 0;
}
void Audio::handleAudioByteArray(const QByteArray& audioByteArray) {
// add this byte array to our QVector
_localInjectionByteArrays.append(audioByteArray);
}
void Audio::renderToolIcon(int screenHeight) {
_iconBounds = QRect(ICON_LEFT, screenHeight - BOTTOM_PADDING, ICON_SIZE, ICON_SIZE);

View file

@ -15,6 +15,7 @@
#include "InterfaceConfig.h"
#include <QtCore/QObject>
#include <QtCore/QVector>
#include <QtMultimedia/QAudioFormat>
#include <AbstractAudioInterface.h>
@ -31,7 +32,7 @@ class QAudioInput;
class QAudioOutput;
class QIODevice;
class Audio : public QObject, public AbstractAudioInterface {
class Audio : public AbstractAudioInterface {
Q_OBJECT
public:
// setup for audio I/O
@ -51,7 +52,7 @@ public:
virtual void startCollisionSound(float magnitude, float frequency, float noise, float duration, bool flashScreen);
virtual void startDrumSound(float volume, float frequency, float duration, float decay);
float getCollisionSoundMagnitude() { return _collisionSoundMagnitude; }
bool getCollisionFlashesScreen() { return _collisionFlashesScreen; }
@ -65,14 +66,17 @@ public slots:
void handleAudioInput();
void reset();
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
private:
QByteArray firstInputFrame;
QAudioInput* _audioInput;
QAudioFormat _desiredInputFormat;
QAudioFormat _inputFormat;
QIODevice* _inputDevice;
int16_t _localInjectedSamples[NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL];
int _numInputCallbackBytes;
int16_t _localInjectedSamples[NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL];
QVector<QByteArray> _localInjectionByteArrays;
QAudioOutput* _audioOutput;
QAudioFormat _desiredOutputFormat;
QAudioFormat _outputFormat;

View file

@ -10,10 +10,13 @@
#ifndef __hifi__AbstractAudioInterface__
#define __hifi__AbstractAudioInterface__
class AbstractAudioInterface {
class AbstractAudioInterface : public QObject {
Q_OBJECT
public:
virtual void startCollisionSound(float magnitude, float frequency, float noise, float duration, bool flashScreen) = 0;
virtual void startDrumSound(float volume, float frequency, float duration, float decay) = 0;
public slots:
virtual void handleAudioByteArray(const QByteArray& audioByteArray) = 0;
};
#endif /* defined(__hifi__AbstractAudioInterface__) */

View file

@ -1,15 +0,0 @@
//
// AudioInjectionManager.cpp
// hifi
//
// Created by Stephen Birarda on 12/17/2013.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include "AudioInjectionManager.h"
AudioInjectionManager::AudioInjectionManager(QObject* parent) :
QObject(parent)
{
}

View file

@ -1,18 +0,0 @@
//
// AudioInjectionManager.h
// hifi
//
// Created by Stephen Birarda on 12/17/2013.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#ifndef __hifi__AudioInjectionManager__
#define __hifi__AudioInjectionManager__
#include <QtCore/QObject>
class AudioInjectionManager : public QObject {
AudioInjectionManager(QObject* parent = 0);
};
#endif /* defined(__hifi__AudioInjectionManager__) */

View file

@ -0,0 +1,49 @@
//
// AudioInjector.cpp
// hifi
//
// Created by Stephen Birarda on 12/19/2013.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
#include "AbstractAudioInterface.h"
#include "AudioInjector.h"
AudioInjector::AudioInjector(const QUrl& sampleURL, QObject* parent) :
QObject(parent)
{
// assume we have a QApplication or QCoreApplication instance and use the
// QNetworkAccess manager to grab the raw audio file at the given URL
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(sampleURL));
}
void AudioInjector::replyFinished(QNetworkReply* reply) {
// replace our samples array with the downloaded data
_sampleByteArray = reply->readAll();
}
void AudioInjector::injectViaThread(AbstractAudioInterface* localAudioInterface) {
// make sure we actually have samples downloaded to inject
if (_sampleByteArray.size()) {
// give our sample byte array to the local audio interface, if we have it, so it can be handled locally
if (localAudioInterface) {
// assume that localAudioInterface could be on a separate thread
QMetaObject::invokeMethod(localAudioInterface, "handleAudioByteArray",
Qt::QueuedConnection,
Q_ARG(QByteArray, _sampleByteArray));
}
// setup a new thread we can use for the injection
}
}

View file

@ -0,0 +1,31 @@
//
// AudioInjector.h
// hifi
//
// Created by Stephen Birarda on 12/19/2013.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#ifndef __hifi__AudioInjector__
#define __hifi__AudioInjector__
#include <QtCore/QObject>
class AbstractAudioInterface;
class QNetworkReply;
class AudioInjector : public QObject {
Q_OBJECT
public:
AudioInjector(const QUrl& sampleURL, QObject* parent = 0);
~AudioInjector();
void injectViaThread(AbstractAudioInterface* localAudioInterface = NULL);
private:
QByteArray _sampleByteArray;
private slots:
void replyFinished(QNetworkReply* reply);
};
#endif /* defined(__hifi__AudioInjector__) */