From 1b48cf7f5ad98b625b8e2ff3a96515c359f4cde7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 14:54:20 -0800 Subject: [PATCH 01/65] use DependencyManager for AddressManager --- interface/src/Application.cpp | 35 +++++++------------ interface/src/Menu.cpp | 12 +++---- interface/src/Menu.h | 2 -- interface/src/avatar/MyAvatar.cpp | 2 +- .../scripting/LocationScriptingInterface.cpp | 6 ++-- interface/src/ui/AddressBarDialog.cpp | 6 ++-- interface/src/ui/ChatWindow.cpp | 2 +- interface/src/ui/DataWebPage.cpp | 2 +- libraries/networking/src/AddressManager.cpp | 26 +++++++++++--- libraries/networking/src/AddressManager.h | 15 +++++--- 10 files changed, 58 insertions(+), 50 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 766424ef4b..dc60f91db7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -304,17 +304,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // once the event loop has started, check and signal for an access token QMetaObject::invokeMethod(&accountManager, "checkAndSignalForAccessToken", Qt::QueuedConnection); - AddressManager& addressManager = AddressManager::getInstance(); + AddressManager* addressManager = DependencyManager::get(); // use our MyAvatar position and quat for address manager path - addressManager.setPositionGetter(getPositionForPath); - addressManager.setOrientationGetter(getOrientationForPath); + addressManager->setPositionGetter(getPositionForPath); + addressManager->setOrientationGetter(getOrientationForPath); // handle domain change signals from AddressManager - connect(&addressManager, &AddressManager::possibleDomainChangeRequiredToHostname, + connect(addressManager, &AddressManager::possibleDomainChangeRequiredToHostname, this, &Application::changeDomainHostname); - connect(&addressManager, &AddressManager::possibleDomainChangeRequiredViaICEForID, + connect(addressManager, &AddressManager::possibleDomainChangeRequiredViaICEForID, &domainHandler, &DomainHandler::setIceServerHostnameAndID); _settings = new QSettings(this); @@ -841,7 +841,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); if (!fileEvent->url().isEmpty()) { - AddressManager::getInstance().handleLookupString(fileEvent->url().toString()); + DependencyManager::get()->handleLookupString(fileEvent->url().toString()); } return false; @@ -1953,22 +1953,13 @@ void Application::init() { // when --url in command line, teleport to location const QString HIFI_URL_COMMAND_LINE_KEY = "--url"; int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY); + QString addressLookupString; if (urlIndex != -1) { - AddressManager::getInstance().handleLookupString(arguments().value(urlIndex + 1)); - } else { - // check if we have a URL in settings to load to jump back to - // we load this separate from the other settings so we don't double lookup a URL - QSettings* interfaceSettings = lockSettings(); - QVariant addressVariant = interfaceSettings->value(SETTINGS_ADDRESS_KEY); - - QString addressString = addressVariant.isNull() - ? DEFAULT_HIFI_ADDRESS : addressVariant.toUrl().toString(); - - unlockSettings(); - - AddressManager::getInstance().handleLookupString(addressString); + addressLookupString = arguments().value(urlIndex + 1); } + DependencyManager::get()->loadSettings(addressLookupString); + qDebug() << "Loaded settings"; #ifdef __APPLE__ @@ -3615,7 +3606,7 @@ void Application::updateWindowTitle(){ QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) "; QString username = AccountManager::getInstance().getAccountInfo().getUsername(); QString title = QString() + (!username.isEmpty() ? username + " @ " : QString()) - + AddressManager::getInstance().getCurrentDomain() + connectionStatus + buildVersion; + + DependencyManager::get()->getCurrentDomain() + connectionStatus + buildVersion; AccountManager& accountManager = AccountManager::getInstance(); if (accountManager.getAccountInfo().hasBalance()) { @@ -3646,7 +3637,7 @@ void Application::updateLocationInServer() { QJsonObject locationObject; - QString pathString = AddressManager::getInstance().currentPath(); + QString pathString = DependencyManager::get()->currentPath(); const QString LOCATION_KEY_IN_ROOT = "location"; const QString PATH_KEY_IN_LOCATION = "path"; @@ -4189,7 +4180,7 @@ void Application::uploadAttachment() { void Application::openUrl(const QUrl& url) { if (!url.isEmpty()) { if (url.scheme() == HIFI_URL_SCHEME) { - AddressManager::getInstance().handleLookupString(url.toString()); + DependencyManager::get()->handleLookupString(url.toString()); } else { // address manager did not handle - ask QDesktopServices to handle QDesktopServices::openUrl(url); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6c2c3966fc..eacd9ee419 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -155,9 +155,9 @@ Menu::Menu() : connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem); // connect to signal of account manager so we can tell user when the user/place they looked at is offline - AddressManager& addressManager = AddressManager::getInstance(); - connect(&addressManager, &AddressManager::lookupResultIsOffline, this, &Menu::displayAddressOfflineMessage); - connect(&addressManager, &AddressManager::lookupResultIsNotFound, this, &Menu::displayAddressNotFoundMessage); + AddressManager* addressManager = DependencyManager::get(); + connect(addressManager, &AddressManager::lookupResultIsOffline, this, &Menu::displayAddressOfflineMessage); + connect(addressManager, &AddressManager::lookupResultIsNotFound, this, &Menu::displayAddressNotFoundMessage); addDisabledActionAndSeparator(fileMenu, "Scripts"); addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadDialog())); @@ -763,8 +763,6 @@ void Menu::saveSettings(QSettings* settings) { scanMenuBar(&saveAction, settings); Application::getInstance()->getAvatar()->saveData(settings); - - settings->setValue(SETTINGS_ADDRESS_KEY, AddressManager::getInstance().currentAddress()); if (lockedSettings) { Application::getInstance()->unlockSettings(); @@ -1198,7 +1196,7 @@ void Menu::displayNameLocationResponse(const QString& errorString) { void Menu::toggleLocationList() { if (!_userLocationsDialog) { JavascriptObjectMap locationObjectMap; - locationObjectMap.insert("InterfaceLocation", &AddressManager::getInstance()); + locationObjectMap.insert("InterfaceLocation", DependencyManager::get()); _userLocationsDialog = DataWebDialog::dialogForPath("/user/locations", locationObjectMap); } @@ -1242,7 +1240,7 @@ void Menu::nameLocation() { if (!_newLocationDialog) { JavascriptObjectMap locationObjectMap; - locationObjectMap.insert("InterfaceLocation", &AddressManager::getInstance()); + locationObjectMap.insert("InterfaceLocation", DependencyManager::get()); _newLocationDialog = DataWebDialog::dialogForPath("/user/locations/new", locationObjectMap); } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index e2c687fff1..6a89fbc92d 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -51,8 +51,6 @@ const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f; const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f; -const QString SETTINGS_ADDRESS_KEY = "address"; - enum FrustumDrawMode { FRUSTUM_DRAW_MODE_ALL, FRUSTUM_DRAW_MODE_VECTORS, diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 057b1f1fc6..1534e9ea5a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -102,7 +102,7 @@ MyAvatar::MyAvatar() : _skeletonModel.buildRagdoll(); // connect to AddressManager signal for location jumps - connect(&AddressManager::getInstance(), &AddressManager::locationChangeRequired, this, &MyAvatar::goToLocation); + connect(DependencyManager::get(), &AddressManager::locationChangeRequired, this, &MyAvatar::goToLocation); } MyAvatar::~MyAvatar() { diff --git a/interface/src/scripting/LocationScriptingInterface.cpp b/interface/src/scripting/LocationScriptingInterface.cpp index 5ead0100e2..cd732218a5 100644 --- a/interface/src/scripting/LocationScriptingInterface.cpp +++ b/interface/src/scripting/LocationScriptingInterface.cpp @@ -19,7 +19,7 @@ LocationScriptingInterface* LocationScriptingInterface::getInstance() { } QScriptValue LocationScriptingInterface::locationGetter(QScriptContext* context, QScriptEngine* engine) { - return engine->newQObject(&AddressManager::getInstance()); + return engine->newQObject(DependencyManager::get()); } QScriptValue LocationScriptingInterface::locationSetter(QScriptContext* context, QScriptEngine* engine) { @@ -28,11 +28,11 @@ QScriptValue LocationScriptingInterface::locationSetter(QScriptContext* context, if (argumentVariant.canConvert(QMetaType::QVariantMap)) { // this argument is a variant map, so we'll assume it's an address map - QMetaObject::invokeMethod(&AddressManager::getInstance(), "goToAddressFromObject", + QMetaObject::invokeMethod(DependencyManager::get(), "goToAddressFromObject", Q_ARG(const QVariantMap&, argumentVariant.toMap())); } else { // just try and convert the argument to a string, should be a hifi:// address - QMetaObject::invokeMethod(&AddressManager::getInstance(), "handleLookupString", + QMetaObject::invokeMethod(DependencyManager::get(), "handleLookupString", Q_ARG(const QString&, argumentVariant.toString())); } diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index dbc29be71a..6a53e4c76b 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -121,8 +121,8 @@ void AddressBarDialog::showEvent(QShowEvent* event) { void AddressBarDialog::accept() { if (!_addressLineEdit->text().isEmpty()) { _goButton->setIcon(QIcon(Application::resourcesPath() + ADDRESSBAR_GO_BUTTON_ACTIVE_ICON)); - AddressManager& addressManager = AddressManager::getInstance(); - connect(&addressManager, &AddressManager::lookupResultsFinished, this, &QDialog::hide); - addressManager.handleLookupString(_addressLineEdit->text()); + AddressManager* addressManager = DependencyManager::get(); + connect(addressManager, &AddressManager::lookupResultsFinished, this, &QDialog::hide); + addressManager->handleLookupString(_addressLineEdit->text()); } } \ No newline at end of file diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 747b4ae68d..14cc10ec35 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -171,7 +171,7 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { } else if (event->type() == QEvent::MouseButtonRelease) { QVariant userVar = sender->property("user"); if (userVar.isValid()) { - AddressManager::getInstance().goToUser(userVar.toString()); + DependencyManager::get()->goToUser(userVar.toString()); return true; } } diff --git a/interface/src/ui/DataWebPage.cpp b/interface/src/ui/DataWebPage.cpp index b8b6649276..75c86cd617 100644 --- a/interface/src/ui/DataWebPage.cpp +++ b/interface/src/ui/DataWebPage.cpp @@ -36,7 +36,7 @@ bool DataWebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkReques return true; } else { // this is a hifi URL - have the AddressManager handle it - QMetaObject::invokeMethod(&AddressManager::getInstance(), "handleLookupString", + QMetaObject::invokeMethod(DependencyManager::get(), "handleLookupString", Qt::AutoConnection, Q_ARG(const QString&, request.url().toString())); return false; } diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 81b3a1328b..dc5f606333 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -21,11 +21,6 @@ #include "AddressManager.h" -AddressManager& AddressManager::getInstance() { - static AddressManager sharedInstance; - return sharedInstance; -} - AddressManager::AddressManager() : _currentDomain(), _positionGetter(NULL), @@ -48,6 +43,27 @@ const QUrl AddressManager::currentAddress() const { return hifiURL; } +const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager"; +const QString SETTINGS_CURRENT_ADDRESS_KEY = "address"; + +void AddressManager::loadSettings(const QString& lookupString) { + if (lookupString.isEmpty()) { + QSettings settings; + settings.beginGroup(ADDRESS_MANAGER_SETTINGS_GROUP); + handleLookupString(settings.value(SETTINGS_CURRENT_ADDRESS_KEY).toString()); + } else { + handleLookupString(lookupString); + } +} + +void AddressManager::storeCurrentAddress() { + QSettings settings; + + settings.beginGroup(ADDRESS_MANAGER_SETTINGS_GROUP); + settings.setValue(SETTINGS_CURRENT_ADDRESS_KEY, currentAddress()); + settings.endGroup(); +} + const QString AddressManager::currentPath(bool withOrientation) const { if (_positionGetter) { diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index cfdaaa7d41..33939c6325 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -17,6 +17,8 @@ #include #include +#include + #include "AccountManager.h" const QString HIFI_URL_SCHEME = "hifi"; @@ -25,7 +27,7 @@ const QString DEFAULT_HIFI_ADDRESS = "hifi://sandbox"; typedef const glm::vec3& (*PositionGetter)(); typedef glm::quat (*OrientationGetter)(); -class AddressManager : public QObject { +class AddressManager : public QObject, public DependencyManager::Dependency { Q_OBJECT Q_PROPERTY(bool isConnected READ isConnected) Q_PROPERTY(QUrl href READ currentAddress) @@ -34,8 +36,6 @@ class AddressManager : public QObject { Q_PROPERTY(QString pathname READ currentPath) Q_PROPERTY(QString domainID READ getDomainID) public: - static AddressManager& getInstance(); - bool isConnected(); const QString& getProtocol() { return HIFI_URL_SCHEME; }; @@ -50,6 +50,10 @@ public: void setPositionGetter(PositionGetter positionGetter) { _positionGetter = positionGetter; } void setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; } + void loadSettings(const QString& lookupString = QString()); + + friend class DependencyManager; + public slots: void handleLookupString(const QString& lookupString); void goToUser(const QString& username); @@ -64,12 +68,13 @@ signals: void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::quat& newOrientation, bool shouldFaceLocation); +protected: + AddressManager(); private slots: void handleAPIResponse(QNetworkReply& requestReply); void handleAPIError(QNetworkReply& errorReply); + void storeCurrentAddress(); private: - AddressManager(); - void setDomainHostnameAndName(const QString& hostname, const QString& domainName = QString()); const JSONCallbackParameters& apiCallbackParameters(); From 78edb94963f70a0926abdbf4e58e59d4dcd617ac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 10:12:25 -0800 Subject: [PATCH 02/65] move address lookup errors to AddressBarDialog --- interface/src/Menu.cpp | 15 --------------- interface/src/Menu.h | 2 -- interface/src/ui/AddressBarDialog.cpp | 17 +++++++++++++++++ interface/src/ui/AddressBarDialog.h | 3 ++- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index eacd9ee419..45ac2ae023 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -153,11 +153,6 @@ Menu::Menu() : // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item connect(&accountManager, &AccountManager::profileChanged, this, &Menu::toggleLoginMenuItem); connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem); - - // connect to signal of account manager so we can tell user when the user/place they looked at is offline - AddressManager* addressManager = DependencyManager::get(); - connect(addressManager, &AddressManager::lookupResultIsOffline, this, &Menu::displayAddressOfflineMessage); - connect(addressManager, &AddressManager::lookupResultIsNotFound, this, &Menu::displayAddressNotFoundMessage); addDisabledActionAndSeparator(fileMenu, "Scripts"); addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadDialog())); @@ -1146,16 +1141,6 @@ void Menu::toggleAddressBar() { } } -void Menu::displayAddressOfflineMessage() { - QMessageBox::information(Application::getInstance()->getWindow(), "Address offline", - "That user or place is currently offline."); -} - -void Menu::displayAddressNotFoundMessage() { - QMessageBox::information(Application::getInstance()->getWindow(), "Address not found", - "There is no address information for that user or place."); -} - void Menu::muteEnvironment() { int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6a89fbc92d..e5ac80918d 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -229,8 +229,6 @@ private slots: void toggleChat(); void audioMuteToggled(); void displayNameLocationResponse(const QString& errorString); - void displayAddressOfflineMessage(); - void displayAddressNotFoundMessage(); void muteEnvironment(); void changeVSync(); diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 6a53e4c76b..58182af9f0 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "AddressBarDialog.h" #include "AddressManager.h" #include "Application.h" @@ -21,6 +23,11 @@ AddressBarDialog::AddressBarDialog() : { setAttribute(Qt::WA_DeleteOnClose, false); setupUI(); + + AddressManager* addressManager = DependencyManager::get(); + + connect(addressManager, &AddressManager::lookupResultIsOffline, this, &AddressBarDialog::displayAddressOfflineMessage); + connect(addressManager, &AddressManager::lookupResultIsNotFound, this, &AddressBarDialog::displayAddressNotFoundMessage); } void AddressBarDialog::setupUI() { @@ -125,4 +132,14 @@ void AddressBarDialog::accept() { connect(addressManager, &AddressManager::lookupResultsFinished, this, &QDialog::hide); addressManager->handleLookupString(_addressLineEdit->text()); } +} + +void AddressBarDialog::displayAddressOfflineMessage() { + QMessageBox::information(Application::getInstance()->getWindow(), "Address offline", + "That user or place is currently offline."); +} + +void AddressBarDialog::displayAddressNotFoundMessage() { + QMessageBox::information(Application::getInstance()->getWindow(), "Address not found", + "There is no address information for that user or place."); } \ No newline at end of file diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index 8f2cf2d7b8..e1d1d33089 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -40,7 +40,8 @@ private: private slots: void accept(); - + void displayAddressOfflineMessage(); + void displayAddressNotFoundMessage(); }; #endif // hifi_AddressBarDialog_h From aeb273a882519ba45d43e9f40ce52cd6844f8fd3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 10:46:24 -0800 Subject: [PATCH 03/65] move environment mute to Audio --- interface/src/Audio.cpp | 19 +++++++++++++++++++ interface/src/Audio.h | 1 + interface/src/Menu.cpp | 29 ++--------------------------- interface/src/Menu.h | 1 - 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 101d16d3ba..d3eceabf77 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -992,6 +992,25 @@ void Audio::processReceivedSamples(const QByteArray& inputBuffer, QByteArray& ou } } +void Audio::sendMuteEnvironmentPacket() { + QByteArray mutePacket = byteArrayWithPopulatedHeader(PacketTypeMuteEnvironment); + QDataStream mutePacketStream(&mutePacket, QIODevice::Append); + + const float MUTE_RADIUS = 50; + + mutePacketStream.writeBytes(reinterpret_cast(&Application::getInstance()->getAvatar()->getPosition()), + sizeof(glm::vec3)); + mutePacketStream.writeBytes(reinterpret_cast(&MUTE_RADIUS), sizeof(float)); + + // grab our audio mixer from the NodeList, if it exists + SharedNodePointer audioMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AudioMixer); + + if (audioMixer) { + // send off this mute packet + NodeList::getInstance()->writeDatagram(mutePacket, audioMixer); + } +} + void Audio::addReceivedAudioToStream(const QByteArray& audioByteArray) { if (_audioOutput) { // Audio output must exist and be correctly set up if we're going to process received audio diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 47fe00a84c..0d6b8482a5 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -150,6 +150,7 @@ public slots: void addLastFrameRepeatedWithFadeToScope(int samplesPerChannel); void addStereoSamplesToScope(const QByteArray& samples); void processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer); + void sendMuteEnvironmentPacket(); virtual bool outputLocalInjector(bool isStereo, qreal volume, AudioInjector* injector); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 45ac2ae023..f0a11a6265 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -80,7 +80,6 @@ const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost"; const float DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER = 1.0f; const int ONE_SECOND_OF_FRAMES = 60; const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES; -const float MUTE_RADIUS = 50; const QString CONSOLE_TITLE = "Scripting Console"; const float CONSOLE_WINDOW_OPACITY = 0.95f; @@ -546,8 +545,8 @@ Menu::Menu() : addActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteEnvironment, 0, - this, - SLOT(muteEnvironment())); + appInstance->getAudio(), + SLOT(sendMuteEnvironmentPacket())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioSourceInject, 0, @@ -1141,30 +1140,6 @@ void Menu::toggleAddressBar() { } } -void Menu::muteEnvironment() { - int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); - int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float); - - glm::vec3 position = Application::getInstance()->getAvatar()->getPosition(); - - char* packet = (char*)malloc(packetSize); - populatePacketHeader(packet, PacketTypeMuteEnvironment); - memcpy(packet + headerSize, &position, sizeof(glm::vec3)); - memcpy(packet + headerSize + sizeof(glm::vec3), &MUTE_RADIUS, sizeof(float)); - - QByteArray mutePacket(packet, packetSize); - - // grab our audio mixer from the NodeList, if it exists - SharedNodePointer audioMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AudioMixer); - - if (audioMixer) { - // send off this mute packet - NodeList::getInstance()->writeDatagram(mutePacket, audioMixer); - } - - free(packet); -} - void Menu::changeVSync() { Application::getInstance()->setVSyncEnabled(isOptionChecked(MenuOption::RenderTargetFramerateVSyncOn)); } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index e5ac80918d..28c33b9386 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -229,7 +229,6 @@ private slots: void toggleChat(); void audioMuteToggled(); void displayNameLocationResponse(const QString& errorString); - void muteEnvironment(); void changeVSync(); private: From c734bc89a32082e7a4fcdfa222b7798dd64f7dcf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 11:54:59 -0800 Subject: [PATCH 04/65] move the audio scope into its own class --- interface/src/Audio.cpp | 375 +++--------------- interface/src/Audio.h | 52 +-- interface/src/audio/AudioScope.cpp | 300 ++++++++++++++ interface/src/audio/AudioScope.h | 68 ++++ interface/src/ui/ApplicationOverlay.cpp | 5 +- libraries/audio/src/AudioConstants.cpp | 13 + libraries/audio/src/AudioConstants.h | 34 ++ libraries/audio/src/AudioFormat.h | 8 +- libraries/audio/src/AudioInjector.cpp | 4 +- libraries/audio/src/AudioRingBuffer.h | 13 +- libraries/audio/src/AudioSourceTone.cpp | 4 +- libraries/audio/src/InjectedAudioStream.cpp | 4 +- .../audio/src/MixedProcessedAudioStream.cpp | 8 +- libraries/audio/src/PositionalAudioStream.cpp | 4 +- libraries/avatars/src/Player.cpp | 2 +- libraries/avatars/src/Recording.cpp | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 4 +- 17 files changed, 505 insertions(+), 395 deletions(-) create mode 100644 interface/src/audio/AudioScope.cpp create mode 100644 interface/src/audio/AudioScope.h create mode 100644 libraries/audio/src/AudioConstants.cpp create mode 100644 libraries/audio/src/AudioConstants.h diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 861f0dc112..89c33aed79 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -27,6 +27,8 @@ #include #endif +#include + #include #include #include @@ -47,12 +49,10 @@ #include "Audio.h" -static const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float)SAMPLE_RATE * 1000.0; - static const int NUMBER_OF_NOISE_SAMPLE_FRAMES = 300; static const int FRAMES_AVAILABLE_STATS_WINDOW_SECONDS = 10; -static const int APPROXIMATELY_30_SECONDS_OF_AUDIO_PACKETS = (int)(30.0f * 1000.0f / AUDIO_CALLBACK_MSECS); +static const int APPROXIMATELY_30_SECONDS_OF_AUDIO_PACKETS = (int)(30.0f * 1000.0f / AudioConstants::NETWORK_FRAME_MSECS); // Mute icon configration static const int MUTE_ICON_SIZE = 24; @@ -103,22 +103,12 @@ Audio::Audio(QObject* parent) : _gverb(NULL), _iconColor(1.0f), _iconPulseTimeReference(usecTimestampNow()), - _scopeEnabled(false), - _scopeEnabledPause(false), - _scopeInputOffset(0), - _scopeOutputOffset(0), - _framesPerScope(DEFAULT_FRAMES_PER_SCOPE), - _samplesPerScope(NETWORK_SAMPLES_PER_FRAME * _framesPerScope), _noiseSourceEnabled(false), _toneSourceEnabled(true), - _scopeInput(0), - _scopeOutputLeft(0), - _scopeOutputRight(0), - _scopeLastFrame(), _statsEnabled(false), _statsShowInjectedStreams(false), _outgoingAvatarAudioSequenceNumber(0), - _audioInputMsecsReadStats(MSECS_PER_SECOND / (float)AUDIO_CALLBACK_MSECS * CALLBACK_ACCELERATOR_RATIO, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), + _audioInputMsecsReadStats(MSECS_PER_SECOND / (float)AudioConstants::NETWORK_FRAME_MSECS * CALLBACK_ACCELERATOR_RATIO, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), _inputRingBufferMsecsAvailableStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), _audioOutputMsecsUnplayedStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), _lastSentAudioPacket(0), @@ -126,13 +116,13 @@ Audio::Audio(QObject* parent) : _audioOutputIODevice(_receivedAudioStream) { // clear the array of locally injected samples - memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); + memset(_localProceduralSamples, 0, AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL); // Create the noise sample array _noiseSampleFrames = new float[NUMBER_OF_NOISE_SAMPLE_FRAMES]; - connect(&_receivedAudioStream, &MixedProcessedAudioStream::addedSilence, this, &Audio::addStereoSilenceToScope, Qt::DirectConnection); - connect(&_receivedAudioStream, &MixedProcessedAudioStream::addedLastFrameRepeatedWithFade, this, &Audio::addLastFrameRepeatedWithFadeToScope, Qt::DirectConnection); - connect(&_receivedAudioStream, &MixedProcessedAudioStream::addedStereoSamples, this, &Audio::addStereoSamplesToScope, Qt::DirectConnection); +// connect(&_receivedAudioStream, &MixedProcessedAudioStream::addedSilence, this, &Audio::addStereoSilenceToScope, Qt::DirectConnection); +// connect(&_receivedAudioStream, &MixedProcessedAudioStream::addedLastFrameRepeatedWithFade, this, &Audio::addLastFrameRepeatedWithFadeToScope, Qt::DirectConnection); +// connect(&_receivedAudioStream, &MixedProcessedAudioStream::addedStereoSamples, this, &Audio::addStereoSamplesToScope, Qt::DirectConnection); connect(&_receivedAudioStream, &MixedProcessedAudioStream::processSamples, this, &Audio::processReceivedSamples, Qt::DirectConnection); // Initialize GVerb @@ -324,10 +314,10 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, } } - if (audioDevice.supportedSampleRates().contains(SAMPLE_RATE * 2)) { + if (audioDevice.supportedSampleRates().contains(AudioConstants::SAMPLE_RATE * 2)) { // use 48, which is a sample downsample, upsample adjustedAudioFormat = desiredAudioFormat; - adjustedAudioFormat.setSampleRate(SAMPLE_RATE * 2); + adjustedAudioFormat.setSampleRate(AudioConstants::SAMPLE_RATE * 2); // return the nearest in case it needs 2 channels adjustedAudioFormat = audioDevice.nearestFormat(adjustedAudioFormat); @@ -425,7 +415,7 @@ void linearResampling(const int16_t* sourceSamples, int16_t* destinationSamples, void Audio::start() { // set up the desired audio format - _desiredInputFormat.setSampleRate(SAMPLE_RATE); + _desiredInputFormat.setSampleRate(AudioConstants::SAMPLE_RATE); _desiredInputFormat.setSampleSize(16); _desiredInputFormat.setCodec("audio/pcm"); _desiredInputFormat.setSampleType(QAudioFormat::SignedInt); @@ -654,7 +644,7 @@ void Audio::handleAudioInput() { float inputToNetworkInputRatio = calculateDeviceToNetworkInputRatio(_numInputCallbackBytes); - int inputSamplesRequired = (int)((float)NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * inputToNetworkInputRatio); + int inputSamplesRequired = (int)((float)AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * inputToNetworkInputRatio); QByteArray inputByteArray = _inputDevice->readAll(); @@ -694,8 +684,12 @@ void Audio::handleAudioInput() { int16_t* inputAudioSamples = new int16_t[inputSamplesRequired]; _inputRingBuffer.readSamples(inputAudioSamples, inputSamplesRequired); - const int numNetworkBytes = _isStereoInput ? NETWORK_BUFFER_LENGTH_BYTES_STEREO : NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL; - const int numNetworkSamples = _isStereoInput ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + const int numNetworkBytes = _isStereoInput + ? AudioConstants::NETWORK_FRAME_BYTES_STEREO + : AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL; + const int numNetworkSamples = _isStereoInput + ? AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + : AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; // zero out the monoAudioSamples array and the locally injected audio memset(networkAudioSamples, 0, numNetworkBytes); @@ -745,10 +739,11 @@ void Audio::handleAudioInput() { float measuredDcOffset = 0.0f; // Increment the time since the last clip if (_timeSinceLastClip >= 0.0f) { - _timeSinceLastClip += (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float) SAMPLE_RATE; + _timeSinceLastClip += (float) AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL + / (float) AudioConstants::SAMPLE_RATE; } - for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { + for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) { measuredDcOffset += networkAudioSamples[i]; networkAudioSamples[i] -= (int16_t) _dcOffset; thisSample = fabsf(networkAudioSamples[i]); @@ -762,7 +757,7 @@ void Audio::handleAudioInput() { } } - measuredDcOffset /= NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + measuredDcOffset /= AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; if (_dcOffset == 0.0f) { // On first frame, copy over measured offset _dcOffset = measuredDcOffset; @@ -770,7 +765,7 @@ void Audio::handleAudioInput() { _dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.0f - DC_OFFSET_AVERAGING) * measuredDcOffset; } - _lastInputLoudness = fabs(loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _lastInputLoudness = fabs(loudness / AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); if (_quietestFrame > _lastInputLoudness) { _quietestFrame = _lastInputLoudness; @@ -818,18 +813,18 @@ void Audio::handleAudioInput() { } } if (!_noiseGateOpen) { - memset(networkAudioSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); + memset(networkAudioSamples, 0, AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL); _lastInputLoudness = 0; } } } else { float loudness = 0.0f; - for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; i++) { + for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; i++) { loudness += fabsf(networkAudioSamples[i]); } - _lastInputLoudness = fabs(loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _lastInputLoudness = fabs(loudness / AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); } } else { // our input loudness is 0, since we're muted @@ -837,14 +832,14 @@ void Audio::handleAudioInput() { } if (!_isStereoInput && _proceduralAudioOutput) { - processProceduralAudio(networkAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + processProceduralAudio(networkAudioSamples, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); } - if (!_isStereoInput && _scopeEnabled && !_scopeEnabledPause) { - unsigned int numMonoAudioChannels = 1; - unsigned int monoAudioChannel = 0; - _scopeInputOffset = addBufferToScope(_scopeInput, _scopeInputOffset, networkAudioSamples, NETWORK_SAMPLES_PER_FRAME, monoAudioChannel, numMonoAudioChannels); - } +// if (!_isStereoInput && _scopeEnabled && !_scopeEnabledPause) { +// unsigned int numMonoAudioChannels = 1; +// unsigned int monoAudioChannel = 0; +// _scopeInputOffset = addBufferToScope(_scopeInput, _scopeInputOffset, networkAudioSamples, NETWORK_SAMPLES_PER_FRAME, monoAudioChannel, numMonoAudioChannels); +// } NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); @@ -928,45 +923,6 @@ void Audio::handleAudioInput() { } } -const int STEREO_FACTOR = 2; - -void Audio::addStereoSilenceToScope(int silentSamplesPerChannel) { - if (!_scopeEnabled || _scopeEnabledPause) { - return; - } - addSilenceToScope(_scopeOutputLeft, _scopeOutputOffset, silentSamplesPerChannel); - _scopeOutputOffset = addSilenceToScope(_scopeOutputRight, _scopeOutputOffset, silentSamplesPerChannel); -} - -void Audio::addStereoSamplesToScope(const QByteArray& samples) { - if (!_scopeEnabled || _scopeEnabledPause) { - return; - } - const int16_t* samplesData = reinterpret_cast(samples.data()); - int samplesPerChannel = samples.size() / sizeof(int16_t) / STEREO_FACTOR; - - addBufferToScope(_scopeOutputLeft, _scopeOutputOffset, samplesData, samplesPerChannel, 0, STEREO_FACTOR); - _scopeOutputOffset = addBufferToScope(_scopeOutputRight, _scopeOutputOffset, samplesData, samplesPerChannel, 1, STEREO_FACTOR); - - _scopeLastFrame = samples.right(NETWORK_BUFFER_LENGTH_BYTES_STEREO); -} - -void Audio::addLastFrameRepeatedWithFadeToScope(int samplesPerChannel) { - const int16_t* lastFrameData = reinterpret_cast(_scopeLastFrame.data()); - - int samplesRemaining = samplesPerChannel; - int indexOfRepeat = 0; - do { - int samplesToWriteThisIteration = std::min(samplesRemaining, (int)NETWORK_SAMPLES_PER_FRAME); - float fade = calculateRepeatedFrameFadeFactor(indexOfRepeat); - addBufferToScope(_scopeOutputLeft, _scopeOutputOffset, lastFrameData, samplesToWriteThisIteration, 0, STEREO_FACTOR, fade); - _scopeOutputOffset = addBufferToScope(_scopeOutputRight, _scopeOutputOffset, lastFrameData, samplesToWriteThisIteration, 1, STEREO_FACTOR, fade); - - samplesRemaining -= samplesToWriteThisIteration; - indexOfRepeat++; - } while (samplesRemaining > 0); -} - void Audio::processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer) { const int numNetworkOutputSamples = inputBuffer.size() / sizeof(int16_t); const int numDeviceOutputSamples = numNetworkOutputSamples * (_outputFormat.sampleRate() * _outputFormat.channelCount()) @@ -1150,9 +1106,9 @@ void Audio::processProceduralAudio(int16_t* monoInput, int numSamples) { // zero out the locally injected audio in preparation for audio procedural sounds // This is correlated to numSamples, so it really needs to be numSamples * sizeof(sample) - memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); + memset(_localProceduralSamples, 0, AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL); // add procedural effects to the appropriate input samples - addProceduralSounds(monoInput, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + addProceduralSounds(monoInput, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); if (!_proceduralOutputDevice) { _proceduralOutputDevice = _proceduralAudioOutput->start(); @@ -1160,13 +1116,13 @@ void Audio::processProceduralAudio(int16_t* monoInput, int numSamples) { // send whatever procedural sounds we want to locally loop back to the _proceduralOutputDevice QByteArray proceduralOutput; - proceduralOutput.resize(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * _outputFormat.sampleRate() * + proceduralOutput.resize(AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * _outputFormat.sampleRate() * _outputFormat.channelCount() * sizeof(int16_t) / (_desiredInputFormat.sampleRate() * _desiredInputFormat.channelCount())); linearResampling(_localProceduralSamples, reinterpret_cast(proceduralOutput.data()), - NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL, + AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL, proceduralOutput.size() / sizeof(int16_t), _desiredInputFormat, _outputFormat); @@ -1230,7 +1186,7 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { const float MAX_DURATION = 2.0f; const float MIN_AUDIBLE_VOLUME = 0.001f; const float NOISE_MAGNITUDE = 0.02f; - float frequency = (_drumSoundFrequency / SAMPLE_RATE) * TWO_PI; + float frequency = (_drumSoundFrequency / AudioConstants::SAMPLE_RATE) * TWO_PI; if (_drumSoundVolume > 0.0f) { for (int i = 0; i < numSamples; i++) { t = (float) _drumSoundSample + (float) i; @@ -1254,7 +1210,7 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { _drumSoundVolume *= (1.0f - _drumSoundDecay); } _drumSoundSample += numSamples; - _drumSoundDuration = glm::clamp(_drumSoundDuration - (AUDIO_CALLBACK_MSECS / 1000.0f), 0.0f, MAX_DURATION); + _drumSoundDuration = glm::clamp(_drumSoundDuration - (AudioConstants::NETWORK_FRAME_MSECS / 1000.0f), 0.0f, MAX_DURATION); if (_drumSoundDuration == 0.0f || (_drumSoundVolume < MIN_AUDIBLE_VOLUME)) { _drumSoundVolume = 0.0f; } @@ -1382,19 +1338,6 @@ void Audio::renderToolBox(int x, int y, bool boxed) { glDisable(GL_TEXTURE_2D); } -void Audio::toggleScope() { - _scopeEnabled = !_scopeEnabled; - if (_scopeEnabled) { - allocateScope(); - } else { - freeScope(); - } -} - -void Audio::toggleScopePause() { - _scopeEnabledPause = !_scopeEnabledPause; -} - void Audio::toggleStats() { _statsEnabled = !_statsEnabled; } @@ -1403,101 +1346,6 @@ void Audio::toggleStatsShowInjectedStreams() { _statsShowInjectedStreams = !_statsShowInjectedStreams; } -void Audio::selectAudioScopeFiveFrames() { - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioScopeFiveFrames)) { - reallocateScope(5); - } -} - -void Audio::selectAudioScopeTwentyFrames() { - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioScopeTwentyFrames)) { - reallocateScope(20); - } -} - -void Audio::selectAudioScopeFiftyFrames() { - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioScopeFiftyFrames)) { - reallocateScope(50); - } -} - -void Audio::allocateScope() { - _scopeInputOffset = 0; - _scopeOutputOffset = 0; - int num = _samplesPerScope * sizeof(int16_t); - _scopeInput = new QByteArray(num, 0); - _scopeOutputLeft = new QByteArray(num, 0); - _scopeOutputRight = new QByteArray(num, 0); -} - -void Audio::reallocateScope(int frames) { - if (_framesPerScope != frames) { - _framesPerScope = frames; - _samplesPerScope = NETWORK_SAMPLES_PER_FRAME * _framesPerScope; - QMutexLocker lock(&_guard); - freeScope(); - allocateScope(); - } -} - -void Audio::freeScope() { - if (_scopeInput) { - delete _scopeInput; - _scopeInput = 0; - } - if (_scopeOutputLeft) { - delete _scopeOutputLeft; - _scopeOutputLeft = 0; - } - if (_scopeOutputRight) { - delete _scopeOutputRight; - _scopeOutputRight = 0; - } -} - -int Audio::addBufferToScope(QByteArray* byteArray, int frameOffset, const int16_t* source, int sourceSamplesPerChannel, - unsigned int sourceChannel, unsigned int sourceNumberOfChannels, float fade) { - if (!_scopeEnabled || _scopeEnabledPause) { - return 0; - } - - // Temporary variable receives sample value - float sample; - - QMutexLocker lock(&_guard); - // Short int pointer to mapped samples in byte array - int16_t* destination = (int16_t*) byteArray->data(); - - for (int i = 0; i < sourceSamplesPerChannel; i++) { - sample = (float)source[i * sourceNumberOfChannels + sourceChannel]; - destination[frameOffset] = sample / (float) MAX_16_BIT_AUDIO_SAMPLE * (float)SCOPE_HEIGHT / 2.0f; - frameOffset = (frameOffset == _samplesPerScope - 1) ? 0 : frameOffset + 1; - } - return frameOffset; -} - -int Audio::addSilenceToScope(QByteArray* byteArray, int frameOffset, int silentSamples) { - - QMutexLocker lock(&_guard); - // Short int pointer to mapped samples in byte array - int16_t* destination = (int16_t*)byteArray->data(); - - if (silentSamples >= _samplesPerScope) { - memset(destination, 0, byteArray->size()); - return frameOffset; - } - - int samplesToBufferEnd = _samplesPerScope - frameOffset; - if (silentSamples > samplesToBufferEnd) { - memset(destination + frameOffset, 0, samplesToBufferEnd * sizeof(int16_t)); - memset(destination, 0, silentSamples - samplesToBufferEnd * sizeof(int16_t)); - } else { - memset(destination + frameOffset, 0, silentSamples * sizeof(int16_t)); - } - - return (frameOffset + silentSamples) % _samplesPerScope; -} - void Audio::renderStats(const float* color, int width, int height) { if (!_statsEnabled) { return; @@ -1514,10 +1362,18 @@ void Audio::renderStats(const float* color, int width, int height) { int x = std::max((width - (int)STATS_WIDTH) / 2, 0); int y = std::max((height - CENTERED_BACKGROUND_HEIGHT) / 2, 0); - int w = STATS_WIDTH; - int h = statsHeight; - renderBackground(backgroundColor, x, y, w, h); - + int backgroundHeight = statsHeight; + + glColor4fv(backgroundColor); + glBegin(GL_QUADS); + + glVertex2i(x, y); + glVertex2i(x + STATS_WIDTH, y); + glVertex2i(x + STATS_WIDTH, y + backgroundHeight); + glVertex2i(x , y + backgroundHeight); + + glEnd(); + glColor4f(1, 1, 1, 1); int horizontalOffset = x + 5; int verticalOffset = y; @@ -1689,132 +1545,9 @@ void Audio::renderAudioStreamStats(const AudioStreamStats& streamStats, int hori drawText(horizontalOffset, verticalOffset, scale, rotation, font, stringBuffer, color); } - -void Audio::renderScope(int width, int height) { - - if (!_scopeEnabled) - return; - - static const float backgroundColor[4] = { 0.4f, 0.4f, 0.4f, 0.6f }; - static const float gridColor[4] = { 0.7f, 0.7f, 0.7f, 1.0f }; - static const float inputColor[4] = { 0.3f, 1.0f, 0.3f, 1.0f }; - static const float outputLeftColor[4] = { 1.0f, 0.3f, 0.3f, 1.0f }; - static const float outputRightColor[4] = { 0.3f, 0.3f, 1.0f, 1.0f }; - static const int gridRows = 2; - int gridCols = _framesPerScope; - - int x = (width - (int)SCOPE_WIDTH) / 2; - int y = (height - (int)SCOPE_HEIGHT) / 2; - int w = (int)SCOPE_WIDTH; - int h = (int)SCOPE_HEIGHT; - - renderBackground(backgroundColor, x, y, w, h); - renderGrid(gridColor, x, y, w, h, gridRows, gridCols); - - QMutexLocker lock(&_guard); - renderLineStrip(inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput); - renderLineStrip(outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft); - renderLineStrip(outputRightColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputRight); -} - -void Audio::renderBackground(const float* color, int x, int y, int width, int height) { - - glColor4fv(color); - glBegin(GL_QUADS); - - glVertex2i(x, y); - glVertex2i(x + width, y); - glVertex2i(x + width, y + height); - glVertex2i(x , y + height); - - glEnd(); - glColor4f(1, 1, 1, 1); -} - -void Audio::renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols) { - - glColor4fv(color); - glBegin(GL_LINES); - - int dx = width / cols; - int dy = height / rows; - int tx = x; - int ty = y; - - // Draw horizontal grid lines - for (int i = rows + 1; --i >= 0; ) { - glVertex2i(x, ty); - glVertex2i(x + width, ty); - ty += dy; - } - // Draw vertical grid lines - for (int i = cols + 1; --i >= 0; ) { - glVertex2i(tx, y); - glVertex2i(tx, y + height); - tx += dx; - } - glEnd(); - glColor4f(1, 1, 1, 1); -} - -void Audio::renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray* byteArray) { - - glColor4fv(color); - glBegin(GL_LINE_STRIP); - - int16_t sample; - int16_t* samples = ((int16_t*) byteArray->data()) + offset; - int numSamplesToAverage = _framesPerScope / DEFAULT_FRAMES_PER_SCOPE; - int count = (n - offset) / numSamplesToAverage; - int remainder = (n - offset) % numSamplesToAverage; - y += SCOPE_HEIGHT / 2; - - // Compute and draw the sample averages from the offset position - for (int i = count; --i >= 0; ) { - sample = 0; - for (int j = numSamplesToAverage; --j >= 0; ) { - sample += *samples++; - } - sample /= numSamplesToAverage; - glVertex2i(x++, y - sample); - } - - // Compute and draw the sample average across the wrap boundary - if (remainder != 0) { - sample = 0; - for (int j = remainder; --j >= 0; ) { - sample += *samples++; - } - - samples = (int16_t*) byteArray->data(); - - for (int j = numSamplesToAverage - remainder; --j >= 0; ) { - sample += *samples++; - } - sample /= numSamplesToAverage; - glVertex2i(x++, y - sample); - } else { - samples = (int16_t*) byteArray->data(); - } - - // Compute and draw the sample average from the beginning to the offset - count = (offset - remainder) / numSamplesToAverage; - for (int i = count; --i >= 0; ) { - sample = 0; - for (int j = numSamplesToAverage; --j >= 0; ) { - sample += *samples++; - } - sample /= numSamplesToAverage; - glVertex2i(x++, y - sample); - } - glEnd(); - glColor4f(1, 1, 1, 1); -} - - void Audio::outputFormatChanged() { int outputFormatChannelCountTimesSampleRate = _outputFormat.channelCount() * _outputFormat.sampleRate(); - _outputFrameSize = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * outputFormatChannelCountTimesSampleRate / _desiredOutputFormat.sampleRate(); + _outputFrameSize = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * outputFormatChannelCountTimesSampleRate / _desiredOutputFormat.sampleRate(); _receivedAudioStream.outputFormatChanged(outputFormatChannelCountTimesSampleRate); } @@ -1934,9 +1667,9 @@ const float Audio::CALLBACK_ACCELERATOR_RATIO = 2.0f; #endif int Audio::calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const { - int numInputCallbackBytes = (int)(((NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + int numInputCallbackBytes = (int)(((AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL * format.channelCount() - * (format.sampleRate() / SAMPLE_RATE)) + * (format.sampleRate() / AudioConstants::SAMPLE_RATE)) / CALLBACK_ACCELERATOR_RATIO) + 0.5f); return numInputCallbackBytes; @@ -1945,7 +1678,7 @@ int Audio::calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const float Audio::calculateDeviceToNetworkInputRatio(int numBytes) const { float inputToNetworkInputRatio = (int)((_numInputCallbackBytes * CALLBACK_ACCELERATOR_RATIO - / NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL) + 0.5f); + / AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL) + 0.5f); return inputToNetworkInputRatio; } diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 0d6b8482a5..4bca3d9390 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -109,11 +109,7 @@ public: bool mousePressEvent(int x, int y); void renderToolBox(int x, int y, bool boxed); - void renderScope(int width, int height); void renderStats(const float* color, int width, int height); - - int getNetworkSampleRate() { return SAMPLE_RATE; } - int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; } float getInputRingBufferMsecsAvailable() const; float getInputRingBufferAverageMsecsAvailable() const { return (float)_inputRingBufferMsecsAvailableStats.getWindowAverage(); } @@ -138,17 +134,11 @@ public slots: void toggleAudioSourceInject(); void selectAudioSourcePinkNoise(); void selectAudioSourceSine440(); - void toggleScope(); - void toggleScopePause(); + void toggleStats(); void toggleStatsShowInjectedStreams(); void toggleStereoInput(); - void selectAudioScopeFiveFrames(); - void selectAudioScopeTwentyFrames(); - void selectAudioScopeFiftyFrames(); - void addStereoSilenceToScope(int silentSamplesPerChannel); - void addLastFrameRepeatedWithFadeToScope(int samplesPerChannel); - void addStereoSamplesToScope(const QByteArray& samples); + void processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer); void sendMuteEnvironmentPacket(); @@ -185,12 +175,12 @@ private: QAudioFormat _inputFormat; QIODevice* _inputDevice; int _numInputCallbackBytes; - int16_t _localProceduralSamples[NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL]; + int16_t _localProceduralSamples[AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL]; QAudioOutput* _audioOutput; QAudioFormat _desiredOutputFormat; QAudioFormat _outputFormat; int _outputFrameSize; - int16_t _outputProcessingBuffer[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO]; + int16_t _outputProcessingBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO]; int _numOutputCallbackBytes; QAudioOutput* _loopbackAudioOutput; QIODevice* _loopbackOutputDevice; @@ -275,37 +265,9 @@ private: int calculateNumberOfFrameSamples(int numBytes) const; float calculateDeviceToNetworkInputRatio(int numBytes) const; - // Audio scope methods for allocation/deallocation - void allocateScope(); - void freeScope(); - void reallocateScope(int frames); - - // Audio scope methods for data acquisition - int addBufferToScope(QByteArray* byteArray, int frameOffset, const int16_t* source, int sourceSamples, - unsigned int sourceChannel, unsigned int sourceNumberOfChannels, float fade = 1.0f); - int addSilenceToScope(QByteArray* byteArray, int frameOffset, int silentSamples); - - // Audio scope methods for rendering - void renderBackground(const float* color, int x, int y, int width, int height); - void renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols); - void renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray* byteArray); - // audio stats methods for rendering void renderAudioStreamStats(const AudioStreamStats& streamStats, int horizontalOffset, int& verticalOffset, float scale, float rotation, int font, const float* color, bool isDownstreamStats = false); - - // Audio scope data - static const unsigned int NETWORK_SAMPLES_PER_FRAME = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; - static const unsigned int DEFAULT_FRAMES_PER_SCOPE = 5; - static const unsigned int SCOPE_WIDTH = NETWORK_SAMPLES_PER_FRAME * DEFAULT_FRAMES_PER_SCOPE; - static const unsigned int MULTIPLIER_SCOPE_HEIGHT = 20; - static const unsigned int SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT; - bool _scopeEnabled; - bool _scopeEnabledPause; - int _scopeInputOffset; - int _scopeOutputOffset; - int _framesPerScope; - int _samplesPerScope; // Input framebuffer AudioBufferFloat32 _inputFrameBuffer; @@ -324,12 +286,6 @@ private: bool _toneSourceEnabled; AudioSourceTone _toneSource; - - QMutex _guard; - QByteArray* _scopeInput; - QByteArray* _scopeOutputLeft; - QByteArray* _scopeOutputRight; - QByteArray _scopeLastFrame; #ifdef _WIN32 static const unsigned int STATS_WIDTH = 1500; #else diff --git a/interface/src/audio/AudioScope.cpp b/interface/src/audio/AudioScope.cpp new file mode 100644 index 0000000000..8374c6fdb8 --- /dev/null +++ b/interface/src/audio/AudioScope.cpp @@ -0,0 +1,300 @@ +// +// AudioScope.cpp +// interface/src/audio +// +// Created by Stephen Birarda on 2014-12-16. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include + +#include "AudioScope.h" + +static const unsigned int DEFAULT_FRAMES_PER_SCOPE = 5; +static const unsigned int SCOPE_WIDTH = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * DEFAULT_FRAMES_PER_SCOPE; +static const unsigned int MULTIPLIER_SCOPE_HEIGHT = 20; +static const unsigned int SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT; + +AudioScope::AudioScope() : + _scopeEnabled(false), + _scopeEnabledPause(false), + _scopeInputOffset(0), + _scopeOutputOffset(0), + _framesPerScope(DEFAULT_FRAMES_PER_SCOPE), + _samplesPerScope(AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * _framesPerScope), + _scopeInput(NULL), + _scopeOutputLeft(NULL), + _scopeOutputRight(NULL), + _scopeLastFrame() +{ + +} + +void AudioScope::toggleScope() { + _scopeEnabled = !_scopeEnabled; + if (_scopeEnabled) { + allocateScope(); + } else { + freeScope(); + } +} + +void AudioScope::toggleScopePause() { + _scopeEnabledPause = !_scopeEnabledPause; +} + +void AudioScope::selectAudioScopeFiveFrames() { + reallocateScope(5); +} + +void AudioScope::selectAudioScopeTwentyFrames() { + reallocateScope(20); +} + +void AudioScope::selectAudioScopeFiftyFrames() { + reallocateScope(50); +} + +void AudioScope::allocateScope() { + _scopeInputOffset = 0; + _scopeOutputOffset = 0; + int num = _samplesPerScope * sizeof(int16_t); + _scopeInput = new QByteArray(num, 0); + _scopeOutputLeft = new QByteArray(num, 0); + _scopeOutputRight = new QByteArray(num, 0); +} + +void AudioScope::reallocateScope(int frames) { + if (_framesPerScope != frames) { + _framesPerScope = frames; + _samplesPerScope = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * _framesPerScope; + QMutexLocker lock(&_guard); + freeScope(); + allocateScope(); + } +} + +void AudioScope::freeScope() { + if (_scopeInput) { + delete _scopeInput; + _scopeInput = 0; + } + if (_scopeOutputLeft) { + delete _scopeOutputLeft; + _scopeOutputLeft = 0; + } + if (_scopeOutputRight) { + delete _scopeOutputRight; + _scopeOutputRight = 0; + } +} + +void AudioScope::render(int width, int height) { + + if (!_scopeEnabled) + return; + + static const float backgroundColor[4] = { 0.4f, 0.4f, 0.4f, 0.6f }; + static const float gridColor[4] = { 0.7f, 0.7f, 0.7f, 1.0f }; + static const float inputColor[4] = { 0.3f, 1.0f, 0.3f, 1.0f }; + static const float outputLeftColor[4] = { 1.0f, 0.3f, 0.3f, 1.0f }; + static const float outputRightColor[4] = { 0.3f, 0.3f, 1.0f, 1.0f }; + static const int gridRows = 2; + int gridCols = _framesPerScope; + + int x = (width - (int)SCOPE_WIDTH) / 2; + int y = (height - (int)SCOPE_HEIGHT) / 2; + int w = (int)SCOPE_WIDTH; + int h = (int)SCOPE_HEIGHT; + + renderBackground(backgroundColor, x, y, w, h); + renderGrid(gridColor, x, y, w, h, gridRows, gridCols); + + QMutexLocker lock(&_guard); + renderLineStrip(inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput); + renderLineStrip(outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft); + renderLineStrip(outputRightColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputRight); +} + +void AudioScope::renderBackground(const float* color, int x, int y, int width, int height) { + glColor4fv(color); + glBegin(GL_QUADS); + + glVertex2i(x, y); + glVertex2i(x + width, y); + glVertex2i(x + width, y + height); + glVertex2i(x , y + height); + + glEnd(); + glColor4f(1, 1, 1, 1); +} + +void AudioScope::renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols) { + + glColor4fv(color); + glBegin(GL_LINES); + + int dx = width / cols; + int dy = height / rows; + int tx = x; + int ty = y; + + // Draw horizontal grid lines + for (int i = rows + 1; --i >= 0; ) { + glVertex2i(x, ty); + glVertex2i(x + width, ty); + ty += dy; + } + // Draw vertical grid lines + for (int i = cols + 1; --i >= 0; ) { + glVertex2i(tx, y); + glVertex2i(tx, y + height); + tx += dx; + } + glEnd(); + glColor4f(1, 1, 1, 1); +} + +void AudioScope::renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray* byteArray) { + + glColor4fv(color); + glBegin(GL_LINE_STRIP); + + int16_t sample; + int16_t* samples = ((int16_t*) byteArray->data()) + offset; + int numSamplesToAverage = _framesPerScope / DEFAULT_FRAMES_PER_SCOPE; + int count = (n - offset) / numSamplesToAverage; + int remainder = (n - offset) % numSamplesToAverage; + y += SCOPE_HEIGHT / 2; + + // Compute and draw the sample averages from the offset position + for (int i = count; --i >= 0; ) { + sample = 0; + for (int j = numSamplesToAverage; --j >= 0; ) { + sample += *samples++; + } + sample /= numSamplesToAverage; + glVertex2i(x++, y - sample); + } + + // Compute and draw the sample average across the wrap boundary + if (remainder != 0) { + sample = 0; + for (int j = remainder; --j >= 0; ) { + sample += *samples++; + } + + samples = (int16_t*) byteArray->data(); + + for (int j = numSamplesToAverage - remainder; --j >= 0; ) { + sample += *samples++; + } + sample /= numSamplesToAverage; + glVertex2i(x++, y - sample); + } else { + samples = (int16_t*) byteArray->data(); + } + + // Compute and draw the sample average from the beginning to the offset + count = (offset - remainder) / numSamplesToAverage; + for (int i = count; --i >= 0; ) { + sample = 0; + for (int j = numSamplesToAverage; --j >= 0; ) { + sample += *samples++; + } + sample /= numSamplesToAverage; + glVertex2i(x++, y - sample); + } + glEnd(); + glColor4f(1, 1, 1, 1); +} + +int AudioScope::addBufferToScope(QByteArray* byteArray, int frameOffset, const int16_t* source, int sourceSamplesPerChannel, + unsigned int sourceChannel, unsigned int sourceNumberOfChannels, float fade) { + if (!_scopeEnabled || _scopeEnabledPause) { + return 0; + } + + // Temporary variable receives sample value + float sample; + + QMutexLocker lock(&_guard); + // Short int pointer to mapped samples in byte array + int16_t* destination = (int16_t*) byteArray->data(); + + for (int i = 0; i < sourceSamplesPerChannel; i++) { + sample = (float)source[i * sourceNumberOfChannels + sourceChannel]; + destination[frameOffset] = sample / (float) AudioConstants::MAX_SAMPLE_VALUE * (float)SCOPE_HEIGHT / 2.0f; + frameOffset = (frameOffset == _samplesPerScope - 1) ? 0 : frameOffset + 1; + } + return frameOffset; +} + +int AudioScope::addSilenceToScope(QByteArray* byteArray, int frameOffset, int silentSamples) { + + QMutexLocker lock(&_guard); + // Short int pointer to mapped samples in byte array + int16_t* destination = (int16_t*)byteArray->data(); + + if (silentSamples >= _samplesPerScope) { + memset(destination, 0, byteArray->size()); + return frameOffset; + } + + int samplesToBufferEnd = _samplesPerScope - frameOffset; + if (silentSamples > samplesToBufferEnd) { + memset(destination + frameOffset, 0, samplesToBufferEnd * sizeof(int16_t)); + memset(destination, 0, silentSamples - samplesToBufferEnd * sizeof(int16_t)); + } else { + memset(destination + frameOffset, 0, silentSamples * sizeof(int16_t)); + } + + return (frameOffset + silentSamples) % _samplesPerScope; +} + + +const int STEREO_FACTOR = 2; + +void AudioScope::addStereoSilenceToScope(int silentSamplesPerChannel) { + if (!_scopeEnabled || _scopeEnabledPause) { + return; + } + addSilenceToScope(_scopeOutputLeft, _scopeOutputOffset, silentSamplesPerChannel); + _scopeOutputOffset = addSilenceToScope(_scopeOutputRight, _scopeOutputOffset, silentSamplesPerChannel); +} + +void AudioScope::addStereoSamplesToScope(const QByteArray& samples) { + if (!_scopeEnabled || _scopeEnabledPause) { + return; + } + const int16_t* samplesData = reinterpret_cast(samples.data()); + int samplesPerChannel = samples.size() / sizeof(int16_t) / STEREO_FACTOR; + + addBufferToScope(_scopeOutputLeft, _scopeOutputOffset, samplesData, samplesPerChannel, 0, STEREO_FACTOR); + _scopeOutputOffset = addBufferToScope(_scopeOutputRight, _scopeOutputOffset, samplesData, samplesPerChannel, 1, STEREO_FACTOR); + + _scopeLastFrame = samples.right(AudioConstants::NETWORK_FRAME_BYTES_STEREO); +} + +void AudioScope::addLastFrameRepeatedWithFadeToScope(int samplesPerChannel) { + const int16_t* lastFrameData = reinterpret_cast(_scopeLastFrame.data()); + + int samplesRemaining = samplesPerChannel; + int indexOfRepeat = 0; + do { + int samplesToWriteThisIteration = std::min(samplesRemaining, (int) AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); +// float fade = calculateRepeatedFrameFadeFactor(indexOfRepeat); +// addBufferToScope(_scopeOutputLeft, _scopeOutputOffset, lastFrameData, samplesToWriteThisIteration, 0, STEREO_FACTOR, fade); +// _scopeOutputOffset = addBufferToScope(_scopeOutputRight, _scopeOutputOffset, lastFrameData, samplesToWriteThisIteration, 1, STEREO_FACTOR, fade); +// + samplesRemaining -= samplesToWriteThisIteration; + indexOfRepeat++; + } while (samplesRemaining > 0); +} diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h new file mode 100644 index 0000000000..0b1d608658 --- /dev/null +++ b/interface/src/audio/AudioScope.h @@ -0,0 +1,68 @@ +// +// AudioScope.h +// interace/src/audio +// +// Created by Stephen Birarda on 2014-12-16. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AudioScope_h +#define hifi_AudioScope_h + +#include + +#include +#include + +class AudioScope : public QObject, public DependencyManager::Dependency { + Q_OBJECT +public: + // Audio scope methods for data acquisition + int addBufferToScope(QByteArray* byteArray, int frameOffset, const int16_t* source, int sourceSamples, + unsigned int sourceChannel, unsigned int sourceNumberOfChannels, float fade = 1.0f); + int addSilenceToScope(QByteArray* byteArray, int frameOffset, int silentSamples); + + // Audio scope methods for rendering + static void renderBackground(const float* color, int x, int y, int width, int height); + void renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols); + void renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray* byteArray); + + // Audio scope methods for allocation/deallocation + void allocateScope(); + void freeScope(); + void reallocateScope(int frames); + + void render(int width, int height); + + friend class DependencyManager; + +public slots: + void toggleScope(); + void toggleScopePause(); + void selectAudioScopeFiveFrames(); + void selectAudioScopeTwentyFrames(); + void selectAudioScopeFiftyFrames(); + void addStereoSilenceToScope(int silentSamplesPerChannel); + void addLastFrameRepeatedWithFadeToScope(int samplesPerChannel); + void addStereoSamplesToScope(const QByteArray& samples); + +protected: + AudioScope(); +private: + bool _scopeEnabled; + bool _scopeEnabledPause; + int _scopeInputOffset; + int _scopeOutputOffset; + int _framesPerScope; + int _samplesPerScope; + QByteArray* _scopeInput; + QByteArray* _scopeOutputLeft; + QByteArray* _scopeOutputRight; + QByteArray _scopeLastFrame; + QMutex _guard; +}; + +#endif // hifi_AudioScope_h \ No newline at end of file diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f4e0c9769d..7389c9971b 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -14,6 +14,7 @@ #include #include +#include "audio/AudioScope.h" #include "Application.h" #include "ApplicationOverlay.h" #include "devices/OculusManager.h" @@ -827,8 +828,8 @@ void ApplicationOverlay::renderAudioMeter() { } audio->renderToolBox(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, boxed); - - audio->renderScope(glWidget->width(), glWidget->height()); + + DependencyManager::get()->render(glWidget->width(), glWidget->height()); audio->renderStats(WHITE_TEXT, glWidget->width(), glWidget->height()); diff --git a/libraries/audio/src/AudioConstants.cpp b/libraries/audio/src/AudioConstants.cpp new file mode 100644 index 0000000000..edfcdc25a1 --- /dev/null +++ b/libraries/audio/src/AudioConstants.cpp @@ -0,0 +1,13 @@ +// +// AudioConstants.cpp +// libraries/audio/src +// +// Created by Stephen Birarda on 2014-12-16. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AudioConstants.h" + diff --git a/libraries/audio/src/AudioConstants.h b/libraries/audio/src/AudioConstants.h new file mode 100644 index 0000000000..9989593f7c --- /dev/null +++ b/libraries/audio/src/AudioConstants.h @@ -0,0 +1,34 @@ +// +// AudioConstants.h +// libraries/audio/src +// +// Created by Stephen Birarda on 2014-12-16. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AudioConstants_h +#define hifi_AudioConstants_h + +#include +#include + +namespace AudioConstants { + const int SAMPLE_RATE = 2400; + + typedef int16_t AudioSample; + + const int NETWORK_FRAME_BYTES_STEREO = 1024; + const int NETWORK_FRAME_SAMPLES_STEREO = NETWORK_FRAME_BYTES_STEREO / sizeof(AudioSample); + const int NETWORK_FRAME_BYTES_PER_CHANNEL = 512; + const int NETWORK_FRAME_SAMPLES_PER_CHANNEL = NETWORK_FRAME_BYTES_PER_CHANNEL / sizeof(AudioSample); + const float NETWORK_FRAME_MSECS = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL + / (float) AudioConstants::SAMPLE_RATE) * 1000.0; + const int MIN_SAMPLE_VALUE = std::numeric_limits::min(); + const int MAX_SAMPLE_VALUE = std::numeric_limits::max(); +} + + +#endif // hifi_AudioConstants_h \ No newline at end of file diff --git a/libraries/audio/src/AudioFormat.h b/libraries/audio/src/AudioFormat.h index 9548138f58..8ab227c77f 100644 --- a/libraries/audio/src/AudioFormat.h +++ b/libraries/audio/src/AudioFormat.h @@ -1,6 +1,6 @@ // // AudioFormat.h -// hifi +// libraries/audio/src // // Created by Craig Hansen-Sturm on 8/28/14. // Copyright 2014 High Fidelity, Inc. @@ -22,6 +22,8 @@ typedef float float32_t; typedef double float64_t; #endif +#include "AudioConstants.h" + // // Audio format structure (currently for uncompressed streams only) // @@ -63,7 +65,7 @@ struct AudioFormat { void setCanonicalFloat32(uint32_t channels) { assert(channels > 0 && channels <= 2); - _sampleRate = SAMPLE_RATE; // todo: create audio constants header + _sampleRate = AudioConstants::SAMPLE_RATE; _bitsPerChannel = sizeof(float32_t) * 8; _channelsPerFrame = channels; _bytesPerFrame = _channelsPerFrame * _bitsPerChannel / 8; @@ -73,7 +75,7 @@ struct AudioFormat { void setCanonicalInt16(uint32_t channels) { assert(channels > 0 && channels <= 2); - _sampleRate = SAMPLE_RATE; // todo: create audio constants header + _sampleRate = AudioConstants::SAMPLE_RATE; _bitsPerChannel = sizeof(int16_t) * 8; _channelsPerFrame = channels; _bytesPerFrame = _channelsPerFrame * _bitsPerChannel / 8; diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index d31ab83976..371ce505d1 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -83,7 +83,7 @@ void AudioInjector::injectAudio() { if (_options.secondOffset > 0.0f) { // convert the offset into a number of bytes - int byteOffset = (int) floorf(SAMPLE_RATE * _options.secondOffset * (_options.stereo ? 2.0f : 1.0f)); + int byteOffset = (int) floorf(AudioConstants::SAMPLE_RATE * _options.secondOffset * (_options.stereo ? 2.0f : 1.0f)); byteOffset *= sizeof(int16_t); _currentSendPosition = byteOffset; @@ -197,7 +197,7 @@ void AudioInjector::injectToMixer() { quint16 outgoingInjectedAudioSequenceNumber = 0; while (_currentSendPosition < _audioData.size() && !_shouldStop) { - int bytesToCopy = std::min(((_options.stereo) ? 2 : 1) * NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, + int bytesToCopy = std::min(((_options.stereo) ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL, _audioData.size() - _currentSendPosition); // Measure the loudness of this frame diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 9239527df3..60640fcb31 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -15,20 +15,15 @@ #include #include +#include "AudioConstants.h" + #include #include #include -const int SAMPLE_RATE = 24000; - -const int NETWORK_BUFFER_LENGTH_BYTES_STEREO = 1024; -const int NETWORK_BUFFER_LENGTH_SAMPLES_STEREO = NETWORK_BUFFER_LENGTH_BYTES_STEREO / sizeof(int16_t); -const int NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL = 512; -const int NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL = NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL / sizeof(int16_t); - -const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL - / (float)SAMPLE_RATE) * USECS_PER_SECOND); +const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL + / (float)AudioConstants::SAMPLE_RATE) * USECS_PER_SECOND); const int MAX_SAMPLE_VALUE = std::numeric_limits::max(); const int MIN_SAMPLE_VALUE = std::numeric_limits::min(); diff --git a/libraries/audio/src/AudioSourceTone.cpp b/libraries/audio/src/AudioSourceTone.cpp index d1cd14be96..c28e40ad1d 100644 --- a/libraries/audio/src/AudioSourceTone.cpp +++ b/libraries/audio/src/AudioSourceTone.cpp @@ -1,6 +1,6 @@ // // AudioSourceTone.cpp -// hifi +// libraries/audio/src // // Created by Craig Hansen-Sturm on 8/10/14. // Copyright 2014 High Fidelity, Inc. @@ -41,7 +41,7 @@ void AudioSourceTone::updateCoefficients() { void AudioSourceTone::initialize() { const float32_t FREQUENCY_220_HZ = 220.0f; const float32_t GAIN_MINUS_6DB = 0.501f; - setParameters(SAMPLE_RATE, FREQUENCY_220_HZ, GAIN_MINUS_6DB); + setParameters(AudioConstants::SAMPLE_RATE, FREQUENCY_220_HZ, GAIN_MINUS_6DB); } void AudioSourceTone::setParameters(const float32_t sampleRate, const float32_t frequency, const float32_t amplitude) { diff --git a/libraries/audio/src/InjectedAudioStream.cpp b/libraries/audio/src/InjectedAudioStream.cpp index 2811e857db..b405e30df7 100644 --- a/libraries/audio/src/InjectedAudioStream.cpp +++ b/libraries/audio/src/InjectedAudioStream.cpp @@ -45,7 +45,9 @@ int InjectedAudioStream::parseStreamProperties(PacketType type, // if isStereo value has changed, restart the ring buffer with new frame size if (isStereo != _isStereo) { - _ringBuffer.resizeForFrameSize(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _ringBuffer.resizeForFrameSize(isStereo + ? AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + : AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); _isStereo = isStereo; } diff --git a/libraries/audio/src/MixedProcessedAudioStream.cpp b/libraries/audio/src/MixedProcessedAudioStream.cpp index 844adf36b3..d236ac7aad 100644 --- a/libraries/audio/src/MixedProcessedAudioStream.cpp +++ b/libraries/audio/src/MixedProcessedAudioStream.cpp @@ -20,7 +20,7 @@ MixedProcessedAudioStream::MixedProcessedAudioStream(int numFrameSamples, int nu void MixedProcessedAudioStream::outputFormatChanged(int outputFormatChannelCountTimesSampleRate) { _outputFormatChannelsTimesSampleRate = outputFormatChannelCountTimesSampleRate; - int deviceOutputFrameSize = networkToDeviceSamples(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO); + int deviceOutputFrameSize = networkToDeviceSamples(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO); _ringBuffer.resizeForFrameSize(deviceOutputFrameSize); } @@ -55,9 +55,11 @@ int MixedProcessedAudioStream::parseAudioData(PacketType type, const QByteArray& } int MixedProcessedAudioStream::networkToDeviceSamples(int networkSamples) { - return (quint64)networkSamples * (quint64)_outputFormatChannelsTimesSampleRate / (quint64)(STEREO_FACTOR * SAMPLE_RATE); + return (quint64)networkSamples * (quint64)_outputFormatChannelsTimesSampleRate / (quint64)(STEREO_FACTOR + * AudioConstants::SAMPLE_RATE); } int MixedProcessedAudioStream::deviceToNetworkSamples(int deviceSamples) { - return (quint64)deviceSamples * (quint64)(STEREO_FACTOR * SAMPLE_RATE) / (quint64)_outputFormatChannelsTimesSampleRate; + return (quint64)deviceSamples * (quint64)(STEREO_FACTOR * AudioConstants::SAMPLE_RATE) + / (quint64)_outputFormatChannelsTimesSampleRate; } diff --git a/libraries/audio/src/PositionalAudioStream.cpp b/libraries/audio/src/PositionalAudioStream.cpp index c315c04026..7ca18db540 100644 --- a/libraries/audio/src/PositionalAudioStream.cpp +++ b/libraries/audio/src/PositionalAudioStream.cpp @@ -22,7 +22,9 @@ #include PositionalAudioStream::PositionalAudioStream(PositionalAudioStream::Type type, bool isStereo, const InboundAudioStream::Settings& settings) : - InboundAudioStream(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL, + InboundAudioStream(isStereo + ? AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + : AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL, AUDIOMIXER_INBOUND_RING_BUFFER_FRAME_CAPACITY, settings), _type(type), _position(0.0f, 0.0f, 0.0f), diff --git a/libraries/avatars/src/Player.cpp b/libraries/avatars/src/Player.cpp index 9f01e98730..4fc01e50ff 100644 --- a/libraries/avatars/src/Player.cpp +++ b/libraries/avatars/src/Player.cpp @@ -376,7 +376,7 @@ void Player::setAudionInjectorPosition() { int SAMPLE_SIZE = 2; // 16 bits int CHANNEL_COUNT = 1; int FRAME_SIZE = SAMPLE_SIZE * CHANNEL_COUNT; - int currentAudioFrame = elapsed() * FRAME_SIZE * (SAMPLE_RATE / MSEC_PER_SEC); + int currentAudioFrame = elapsed() * FRAME_SIZE * (AudioConstants::SAMPLE_RATE / MSEC_PER_SEC); _injector->setCurrentSendPosition(currentAudioFrame); } diff --git a/libraries/avatars/src/Recording.cpp b/libraries/avatars/src/Recording.cpp index b39421d03a..70624227b0 100644 --- a/libraries/avatars/src/Recording.cpp +++ b/libraries/avatars/src/Recording.cpp @@ -771,7 +771,7 @@ RecordingPointer readRecordingFromRecFile(RecordingPointer recording, const QStr // Cut down audio if necessary int SAMPLE_SIZE = 2; // 16 bits int MSEC_PER_SEC = 1000; - int audioLength = recording->getLength() * SAMPLE_SIZE * (SAMPLE_RATE / MSEC_PER_SEC); + int audioLength = recording->getLength() * SAMPLE_SIZE * (AudioConstants::SAMPLE_RATE / MSEC_PER_SEC); audioArray.chop(audioArray.size() - audioLength); recording->addAudioPacket(audioArray); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 70c536e116..73f02a552d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -402,7 +403,8 @@ void ScriptEngine::run() { if (_isAvatar && _avatarData) { - const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * SAMPLE_RATE) / (1000 * 1000)) + 0.5); + const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * AudioConstants::SAMPLE_RATE) + / (1000 * 1000)) + 0.5); const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t); QByteArray avatarPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarData); From bb77986f1aab5962ad56af2d1749314dfc909f38 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 11:56:56 -0800 Subject: [PATCH 05/65] use new AudioConstants in AudioMixer classes --- assignment-client/src/Agent.cpp | 2 +- assignment-client/src/audio/AudioMixer.cpp | 20 +++++++++---------- assignment-client/src/audio/AudioMixer.h | 4 ++-- .../src/audio/AudioMixerClientData.h | 2 +- .../src/audio/AvatarAudioStream.cpp | 4 +++- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f3efccf31a..2350d745ef 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -39,7 +39,7 @@ Agent::Agent(const QByteArray& packet) : ThreadedAssignment(packet), _voxelEditSender(), _entityEditSender(), - _receivedAudioStream(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, + _receivedAudioStream(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, InboundAudioStream::Settings(0, false, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, false, DEFAULT_WINDOW_STARVE_THRESHOLD, DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES, DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION, false)), diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index c3ec321c77..d9b2a8ea9b 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -273,8 +273,8 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l // Mono input to stereo output (item 1 above) int OUTPUT_SAMPLES_PER_INPUT_SAMPLE = 2; - int inputSampleCount = NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / OUTPUT_SAMPLES_PER_INPUT_SAMPLE; - int maxOutputIndex = NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; + int inputSampleCount = AudioConstants::NETWORK_FRAME_SAMPLES_STEREO / OUTPUT_SAMPLES_PER_INPUT_SAMPLE; + int maxOutputIndex = AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; // attenuation and fade applied to all samples (item 2 above) float attenuationAndFade = attenuationCoefficient * repeatedFrameFadeFactor; @@ -352,7 +352,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l float attenuationAndFade = attenuationCoefficient * repeatedFrameFadeFactor; - for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s++) { + for (int s = 0; s < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; s++) { _preMixSamples[s] = glm::clamp(_preMixSamples[s] + (int)(streamPopOutput[s / stereoDivider] * attenuationAndFade), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); } @@ -416,13 +416,13 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l AudioFilterHSF1s& penumbraFilter = listenerNodeData->getListenerSourcePairData(streamUUID)->getPenumbraFilter(); // set the gain on both filter channels - penumbraFilter.setParameters(0, 0, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope); - penumbraFilter.setParameters(0, 1, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope); - penumbraFilter.render(_preMixSamples, _preMixSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2); + penumbraFilter.setParameters(0, 0, AudioConstants::SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope); + penumbraFilter.setParameters(0, 1, AudioConstants::SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope); + penumbraFilter.render(_preMixSamples, _preMixSamples, AudioConstants::NETWORK_FRAME_SAMPLES_STEREO / 2); } // Actually mix the _preMixSamples into the _mixSamples here. - for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s++) { + for (int s = 0; s < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; s++) { _mixSamples[s] = glm::clamp(_mixSamples[s] + _preMixSamples[s], MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); } @@ -797,8 +797,8 @@ void AudioMixer::run() { mixDataAt += sizeof(quint16); // pack mixed audio samples - memcpy(mixDataAt, _mixSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); - mixDataAt += NETWORK_BUFFER_LENGTH_BYTES_STEREO; + memcpy(mixDataAt, _mixSamples, AudioConstants::NETWORK_FRAME_BYTES_STEREO); + mixDataAt += AudioConstants::NETWORK_FRAME_BYTES_STEREO; } else { // pack header int numBytesPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame); @@ -810,7 +810,7 @@ void AudioMixer::run() { mixDataAt += sizeof(quint16); // pack number of silent audio samples - quint16 numSilentSamples = NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; + quint16 numSilentSamples = AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; memcpy(mixDataAt, &numSilentSamples, sizeof(quint16)); mixDataAt += sizeof(quint16); } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index cc88e368b2..6cee557ff9 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -55,11 +55,11 @@ private: // used on a per stream basis to run the filter on before mixing, large enough to handle the historical // data from a phase delay as well as an entire network buffer - int16_t _preMixSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; + int16_t _preMixSamples[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; // client samples capacity is larger than what will be sent to optimize mixing // we are MMX adding 4 samples at a time so we need client samples to have an extra 4 - int16_t _mixSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; + int16_t _mixSamples[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; void perSecondActions(); diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index ce43229286..322c7057da 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -24,7 +24,7 @@ class PerListenerSourcePairData { public: PerListenerSourcePairData() { - _penumbraFilter.initialize(SAMPLE_RATE, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2); + _penumbraFilter.initialize(AudioConstants::SAMPLE_RATE, AudioConstants::NETWORK_FRAME_SAMPLES_STEREO / 2); }; AudioFilterHSF1s& getPenumbraFilter() { return _penumbraFilter; } diff --git a/assignment-client/src/audio/AvatarAudioStream.cpp b/assignment-client/src/audio/AvatarAudioStream.cpp index 90dcefa09d..87581a637c 100644 --- a/assignment-client/src/audio/AvatarAudioStream.cpp +++ b/assignment-client/src/audio/AvatarAudioStream.cpp @@ -40,7 +40,9 @@ int AvatarAudioStream::parseStreamProperties(PacketType type, const QByteArray& // if isStereo value has changed, restart the ring buffer with new frame size if (isStereo != _isStereo) { - _ringBuffer.resizeForFrameSize(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _ringBuffer.resizeForFrameSize(isStereo + ? AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + : AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); _isStereo = isStereo; } From 4077a76e46f0b0bc3b962d6e14d7a02f8af4e9ca Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 11:58:12 -0800 Subject: [PATCH 06/65] remove AudioRingBuffer include where not needed --- assignment-client/src/Agent.cpp | 1 - libraries/avatars/src/Player.cpp | 2 +- libraries/avatars/src/Recording.cpp | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 2350d745ef..c08a6c9f78 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/libraries/avatars/src/Player.cpp b/libraries/avatars/src/Player.cpp index 4fc01e50ff..dfb786cbc4 100644 --- a/libraries/avatars/src/Player.cpp +++ b/libraries/avatars/src/Player.cpp @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include #include #include #include diff --git a/libraries/avatars/src/Recording.cpp b/libraries/avatars/src/Recording.cpp index 70624227b0..0ba396eaa9 100644 --- a/libraries/avatars/src/Recording.cpp +++ b/libraries/avatars/src/Recording.cpp @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include #include #include #include diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 73f02a552d..e74b27d5b1 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include From 7f2baa056e85b2d2de7d51741ff8d77c69ff9113 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 12:02:10 -0800 Subject: [PATCH 07/65] some cleanup in audio library --- libraries/audio/src/AudioBuffer.h | 16 +++++++++------- libraries/audio/src/AudioFilterBank.cpp | 3 +-- libraries/audio/src/AudioFilterBank.h | 2 +- libraries/audio/src/AudioGain.cpp | 6 +++--- libraries/audio/src/AudioGain.h | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/libraries/audio/src/AudioBuffer.h b/libraries/audio/src/AudioBuffer.h index c489c169a7..e24f53be77 100644 --- a/libraries/audio/src/AudioBuffer.h +++ b/libraries/audio/src/AudioBuffer.h @@ -14,6 +14,8 @@ #include +#include + template< typename T > class AudioFrameBuffer { @@ -150,13 +152,13 @@ inline void AudioFrameBuffer< T >::copyFrames(uint32_t channelCount, const uint3 _channelCount = channelCount; } else { qDebug() << "Audio framing error: _channelCount=" - << _channelCount - << "channelCountMax=" - << _channelCountMax - << "_frameCount=" - << _frameCount - << "frameCountMax=" - << _frameCountMax; + << _channelCount + << "channelCountMax=" + << _channelCountMax + << "_frameCount=" + << _frameCount + << "frameCountMax=" + << _frameCountMax; _channelCount = std::min(_channelCount,_channelCountMax); _frameCount = std::min(_frameCount,_frameCountMax); diff --git a/libraries/audio/src/AudioFilterBank.cpp b/libraries/audio/src/AudioFilterBank.cpp index 6599b29a01..d5792ae97c 100644 --- a/libraries/audio/src/AudioFilterBank.cpp +++ b/libraries/audio/src/AudioFilterBank.cpp @@ -1,6 +1,6 @@ // // AudioFilterBank.cpp -// hifi +// libraries/audio/src // // Created by Craig Hansen-Sturm on 8/10/14. // Copyright 2014 High Fidelity, Inc. @@ -12,7 +12,6 @@ #include #include #include -#include "AudioRingBuffer.h" #include "AudioFormat.h" #include "AudioBuffer.h" #include "AudioFilter.h" diff --git a/libraries/audio/src/AudioFilterBank.h b/libraries/audio/src/AudioFilterBank.h index 41b2985cbe..c5f0c4c171 100644 --- a/libraries/audio/src/AudioFilterBank.h +++ b/libraries/audio/src/AudioFilterBank.h @@ -1,6 +1,6 @@ // // AudioFilterBank.h -// hifi +// libraries/audio/src // // Created by Craig Hansen-Sturm on 8/23/14. // Copyright 2014 High Fidelity, Inc. diff --git a/libraries/audio/src/AudioGain.cpp b/libraries/audio/src/AudioGain.cpp index 8bd2b5b7a3..217a4d3791 100644 --- a/libraries/audio/src/AudioGain.cpp +++ b/libraries/audio/src/AudioGain.cpp @@ -1,6 +1,6 @@ // // AudioGain.cpp -// hifi +// libraries/audio/src // // Created by Craig Hansen-Sturm on 9/10/14. // Copyright 2014 High Fidelity, Inc. @@ -10,9 +10,9 @@ // #include +#include #include -#include -#include "AudioRingBuffer.h" + #include "AudioFormat.h" #include "AudioBuffer.h" #include "AudioGain.h" diff --git a/libraries/audio/src/AudioGain.h b/libraries/audio/src/AudioGain.h index 1d54d76f7f..3bf7b0d4dd 100644 --- a/libraries/audio/src/AudioGain.h +++ b/libraries/audio/src/AudioGain.h @@ -1,6 +1,6 @@ // // AudioGain.h -// hifi +// libraries/audio/src // // Created by Craig Hansen-Sturm on 9/1/14. // Copyright 2014 High Fidelity, Inc. From fba256692f25187a8b23e05d781b9ca0c10fd74d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 12:04:26 -0800 Subject: [PATCH 08/65] rename variables in AudioScope --- interface/src/audio/AudioScope.cpp | 21 +++++++++------------ interface/src/audio/AudioScope.h | 6 +++--- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/interface/src/audio/AudioScope.cpp b/interface/src/audio/AudioScope.cpp index 8374c6fdb8..134ee4ed8d 100644 --- a/interface/src/audio/AudioScope.cpp +++ b/interface/src/audio/AudioScope.cpp @@ -23,8 +23,8 @@ static const unsigned int MULTIPLIER_SCOPE_HEIGHT = 20; static const unsigned int SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT; AudioScope::AudioScope() : - _scopeEnabled(false), - _scopeEnabledPause(false), + _isEnabled(false), + _isPaused(false), _scopeInputOffset(0), _scopeOutputOffset(0), _framesPerScope(DEFAULT_FRAMES_PER_SCOPE), @@ -38,18 +38,14 @@ AudioScope::AudioScope() : } void AudioScope::toggleScope() { - _scopeEnabled = !_scopeEnabled; - if (_scopeEnabled) { + _isEnabled = !_isEnabled; + if (_isEnabled) { allocateScope(); } else { freeScope(); } } -void AudioScope::toggleScopePause() { - _scopeEnabledPause = !_scopeEnabledPause; -} - void AudioScope::selectAudioScopeFiveFrames() { reallocateScope(5); } @@ -98,8 +94,9 @@ void AudioScope::freeScope() { void AudioScope::render(int width, int height) { - if (!_scopeEnabled) + if (!_isEnabled) { return; + } static const float backgroundColor[4] = { 0.4f, 0.4f, 0.4f, 0.6f }; static const float gridColor[4] = { 0.7f, 0.7f, 0.7f, 1.0f }; @@ -218,7 +215,7 @@ void AudioScope::renderLineStrip(const float* color, int x, int y, int n, int of int AudioScope::addBufferToScope(QByteArray* byteArray, int frameOffset, const int16_t* source, int sourceSamplesPerChannel, unsigned int sourceChannel, unsigned int sourceNumberOfChannels, float fade) { - if (!_scopeEnabled || _scopeEnabledPause) { + if (!_isEnabled || _isPaused) { return 0; } @@ -263,7 +260,7 @@ int AudioScope::addSilenceToScope(QByteArray* byteArray, int frameOffset, int si const int STEREO_FACTOR = 2; void AudioScope::addStereoSilenceToScope(int silentSamplesPerChannel) { - if (!_scopeEnabled || _scopeEnabledPause) { + if (!_isEnabled || _isPaused) { return; } addSilenceToScope(_scopeOutputLeft, _scopeOutputOffset, silentSamplesPerChannel); @@ -271,7 +268,7 @@ void AudioScope::addStereoSilenceToScope(int silentSamplesPerChannel) { } void AudioScope::addStereoSamplesToScope(const QByteArray& samples) { - if (!_scopeEnabled || _scopeEnabledPause) { + if (!_isEnabled || _isPaused) { return; } const int16_t* samplesData = reinterpret_cast(samples.data()); diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h index 0b1d608658..37a8a35a28 100644 --- a/interface/src/audio/AudioScope.h +++ b/interface/src/audio/AudioScope.h @@ -41,7 +41,7 @@ public: public slots: void toggleScope(); - void toggleScopePause(); + void toggleScopePause() { _isPaused = !_isPaused; } void selectAudioScopeFiveFrames(); void selectAudioScopeTwentyFrames(); void selectAudioScopeFiftyFrames(); @@ -52,8 +52,8 @@ public slots: protected: AudioScope(); private: - bool _scopeEnabled; - bool _scopeEnabledPause; + bool _isEnabled; + bool _isPaused; int _scopeInputOffset; int _scopeOutputOffset; int _framesPerScope; From 6fd55e6f427a4217750f7e940f1ccda76464102b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 12:31:01 -0800 Subject: [PATCH 09/65] make Audio class use DependencyManager --- interface/src/Application.cpp | 42 ++++++++--------- interface/src/Application.h | 3 -- interface/src/Audio.cpp | 4 +- interface/src/Audio.h | 45 ++++++++++--------- interface/src/audio/AudioScope.cpp | 6 +-- interface/src/audio/AudioScope.h | 1 - .../AudioDeviceScriptingInterface.cpp | 34 ++++++++------ .../scripting/AudioDeviceScriptingInterface.h | 4 +- interface/src/ui/PreferencesDialog.cpp | 2 +- .../entities/src/EntityCollisionSystem.cpp | 5 +-- .../entities/src/EntityCollisionSystem.h | 3 +- 11 files changed, 75 insertions(+), 74 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dc60f91db7..0090ad7833 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -177,7 +177,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _touchAvgY(0.0f), _isTouchPressed(false), _mousePressed(false), - _audio(), _enableProcessVoxelsThread(true), _octreeProcessor(), _voxelHideShowThread(&_voxels), @@ -249,9 +248,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // put the audio processing on a separate thread QThread* audioThread = new QThread(this); - - _audio.moveToThread(audioThread); - connect(audioThread, SIGNAL(started()), &_audio, SLOT(start())); + + Audio* audioIO = DependencyManager::get