<commit_before>#include <boost/filesystem.hpp>
#include <boost/ref.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

#include "Renderer.hpp"
#include "AlloShared/StatsUtils.hpp"
#include "AlloShared/to_human_readable_byte_count.hpp"
#include "AlloShared/CommandHandler.hpp"
#include "AlloShared/Console.hpp"
#include "AlloShared/Config.hpp"
#include "AlloShared/CommandLine.hpp"
#include "AlloReceiver/RTSPCubemapSourceClient.hpp"
#include "AlloReceiver/AlloReceiver.h"
#include "AlloReceiver/Stats.hpp"
#include "AlloReceiver/H264CubemapSource.h"

#define DEG_DIV_RAD 57.29577951308233
#define RAD_DIV_DEG  0.01745329251994

const unsigned int DEFAULT_SINK_BUFFER_SIZE = 2000000000;

static Stats         stats;
static Renderer      renderer;
static auto          lastStatsTime    = boost::chrono::steady_clock::now();
static std::string   statsFormat      = AlloReceiver::formatStringMaker();
static bool          noDisplay        = false;
static std::string   url              = "";
static std::string   interfaceAddress = "0.0.0.0";
static unsigned long bufferSize       = DEFAULT_SINK_BUFFER_SIZE;
static bool          matchStereoPairs = false;
static boost::filesystem::path configFilePath;
static bool          robustSyncing    = false;
static size_t        maxFrameMapSize  = 2;
static std::string   logPath          = ".";

StereoCubemap* onNextCubemap(CubemapSource* source, StereoCubemap* cubemap)
{
    for (int i = 0; i < cubemap->getEye(0)->getFacesCount(); i++)
    {
        stats.store(StatsUtils::CubemapFace(i, StatsUtils::CubemapFace::DISPLAYED));
    }
    stats.store(StatsUtils::Cubemap());
    return cubemap;
}

void onReceivedNALU(CubemapSource* source, u_int8_t type, size_t size, int face)
{
    //stats.store(StatsUtils::NALU(type, size, face, StatsUtils::NALU::RECEIVED));
}

void onReceivedFrame(CubemapSource* source, u_int8_t type, size_t size, int face)
{
    //stats.store(StatsUtils::Frame(type, size, face, StatsUtils::Frame::RECEIVED));
}

void onDecodedFrame(CubemapSource* source, u_int8_t type, size_t size, int face)
{
    //stats.store(StatsUtils::Frame(type, size, face, StatsUtils::Frame::DECODED));
}

void onColorConvertedFrame(CubemapSource* source, u_int8_t type, size_t size, int face)
{
    stats.store(StatsUtils::Frame(type, size, face, StatsUtils::Frame::COLOR_CONVERTED));
}

void onAddedFrameToCubemap(CubemapSource* source, int face)
{
    //stats.store(StatsUtils::CubemapFace(face, StatsUtils::CubemapFace::ADDED));
}

void setOnScheduledFrameInCubemap(CubemapSource* source, int face)
{
    stats.store(StatsUtils::CubemapFace(face, StatsUtils::CubemapFace::SCHEDULED));
}

void onDisplayedCubemapFace(Renderer* renderer, int face)
{
    stats.store(StatsUtils::CubemapFace(face, StatsUtils::CubemapFace::DISPLAYED));
}

void onDisplayedFrame(Renderer* renderer)
{
    stats.store(StatsUtils::Cubemap());
}

void onDidConnect(RTSPCubemapSourceClient* client, CubemapSource* cubemapSource)
{
    H264CubemapSource* h264CubemapSource = dynamic_cast<H264CubemapSource*>(cubemapSource);
    if (h264CubemapSource)
    {
        h264CubemapSource->setOnReceivedNALU           (boost::bind(&onReceivedNALU,               _1, _2, _3, _4));
        h264CubemapSource->setOnReceivedFrame          (boost::bind(&onReceivedFrame,              _1, _2, _3, _4));
        h264CubemapSource->setOnDecodedFrame           (boost::bind(&onDecodedFrame,               _1, _2, _3, _4));
        h264CubemapSource->setOnColorConvertedFrame    (boost::bind(&onColorConvertedFrame,        _1, _2, _3, _4));
        h264CubemapSource->setOnAddedFrameToCubemap    (boost::bind(&onAddedFrameToCubemap,        _1, _2));
        h264CubemapSource->setOnScheduledFrameInCubemap(boost::bind(&setOnScheduledFrameInCubemap, _1, _2));
    }

    if (noDisplay)
    {
        cubemapSource->setOnNextCubemap(boost::bind(&onNextCubemap, _1, _2));
    }
    else
    {
        renderer.setCubemapSource(cubemapSource);
    }
}

int main(int argc, char* argv[])
{
    std::initializer_list<CommandHandler::Command> generalCommands =
    {
        {
            "gamma-min",
            {"val"},
            [](const std::vector<std::string>& values)
            {
                renderer.setGammaMin(boost::lexical_cast<float>(values[0]));
            }
        },
        {
            "gamma-max",
            {"val"},
            [](const std::vector<std::string>& values)
            {
                renderer.setGammaMax(boost::lexical_cast<float>(values[0]));
            }
        },
        {
            "gamma-pow",
            {"val"},
            [](const std::vector<std::string>& values)
            {
                renderer.setGammaPow(boost::lexical_cast<float>(values[0]));
            }
        },
        {
            "for-rotation",
            {"α°", "β°", "γ°"},
            [](const std::vector<std::string>& values)
            {
                renderer.setFORRotation(al::Vec3f(boost::lexical_cast<float>(values[0]) * RAD_DIV_DEG,
                                                  boost::lexical_cast<float>(values[1]) * RAD_DIV_DEG,
                                                  boost::lexical_cast<float>(values[2]) * RAD_DIV_DEG));
            }
        },
        {
            "for-angle",
            {"°"},
            [](const std::vector<std::string>& values)
            {
                renderer.setFORAngle(boost::lexical_cast<float>(values[0]) * RAD_DIV_DEG);
            }
        },
        {
            "rotation",
            {"α°", "β°", "γ°"},
            [](const std::vector<std::string>& values)
            {
                renderer.setRotation(al::Vec3f(boost::lexical_cast<float>(values[0]) * RAD_DIV_DEG,
                                               boost::lexical_cast<float>(values[1]) * RAD_DIV_DEG,
                                               boost::lexical_cast<float>(values[2]) * RAD_DIV_DEG));
            }
        },
        {
            "rotation-speed",
            {"val"},
            [](const std::vector<std::string>& values)
            {
                renderer.setRotationSpeed(boost::lexical_cast<float>(values[0]));
            }
        },
        {
            "force-mono",
            {},
            [](const std::vector<std::string>& values)
            {
                renderer.setForceMono(true);
            }
        },
    };

    CommandHandler configCommandHandler({});

    std::initializer_list<CommandHandler::Command> configCommandLineOnlyCommands =
    {
        {
            "config",
            {"file_path"},
            [&configCommandHandler](const std::vector<std::string>& values)
            {
                configFilePath = boost::filesystem::canonical(boost::filesystem::absolute(values[0], configFilePath.parent_path()));

                auto configParseResult = Config::parseConfigFile(configCommandHandler,
                                                                 configFilePath.string());
                if (!configParseResult.first)
                {
                    std::cerr << configParseResult.second << std::endl;
                    std::cerr << configCommandHandler.getCommandHelpString();
                    abort();
                }
            }
        },
        {
            "no-display",
            {},
            [](const std::vector<std::string>& values)
            {
                noDisplay = true;
            }
        },
        {
            "url",
            {"rtsp_url"},
            [](const std::vector<std::string>& values)
            {
                url = values[0];
            }
        },
        {
            "interface-address",
            {"ip"},
            [](const std::vector<std::string>& values)
            {
                interfaceAddress = values[0];
            }
        },
        {
            "buffer-size",
            {"bytes"},
            [](const std::vector<std::string>& values)
            {
                bufferSize = boost::lexical_cast<unsigned long>(values[0]);
            }
        },
        {
            "match-stereo-pairs",
            {},
            [](const std::vector<std::string>& values)
            {
                matchStereoPairs = true;
            }
        },
        {
            "robust-syncing",
            {},
            [](const std::vector<std::string>& values)
            {
                robustSyncing = true;
            }
        },
        {
            "cubemap-queue-size",
            {"size"},
            [](const std::vector<std::string>& values)
            {
                maxFrameMapSize = boost::lexical_cast<size_t>(values[0]);
            }
        }
    };

    std::initializer_list<CommandHandler::Command> consoleOnlyCommands =
    {
        {
            "stats",
            {},
            [](const std::vector<std::string>& values)
            {
                boost::chrono::steady_clock::time_point now = boost::chrono::steady_clock::now();
                std::cout << stats.summary(boost::chrono::duration_cast<boost::chrono::microseconds>(now - lastStatsTime),
                                           AlloReceiver::statValsMaker,
                                           AlloReceiver::postProcessorMaker,
                                           statsFormat);
                lastStatsTime = now;
            }
        },
        {
            "quit",
            {},
            [](const std::vector<std::string>& values)
            {
                exit(0);
            }
        },
        {
            "info",
            {},
            [](const std::vector<std::string>& values)
            {
                al::Vec3f forRotation = renderer.getFORRotation() * DEG_DIV_RAD;
                al::Vec3f rotation    = renderer.getRotation()    * DEG_DIV_RAD;

                std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(1);
                std::cout << "Display:            " << ((noDisplay) ? "no" : "yes") << std::endl;
                std::cout << "RTSP URL:           " << url << std::endl;
                std::cout << "Interface address:  " << interfaceAddress << std::endl;
                std::cout << "Buffer size:        " << to_human_readable_byte_count(bufferSize, false, false) << std::endl;
                std::cout << "Match stereo pairs: " << ((matchStereoPairs) ? "yes" : "no") << std::endl;
                std::cout << "Gamma min:          " << renderer.getGammaMin() << std::endl;
                std::cout << "Gamma max:          " << renderer.getGammaMax() << std::endl;
                std::cout << "Gamma pow:          " << renderer.getGammaPow() << std::endl;
                std::cout << "FOR angle:          " << renderer.getFORAngle() * DEG_DIV_RAD << "°" << std::endl;
                std::cout << "FOR rotation:       " << "α=" << forRotation[0] << "°\t"
                                                    << "β=" << forRotation[1] << "°\t"
                                                    << "γ=" << forRotation[2] << "°" << std::endl;
                std::cout << "Scene rotation:     " << "α=" << rotation[0] << "°\t"
                                                    << "β=" << rotation[1] << "°\t"
                                                    << "γ=" << rotation[2] << "°" << std::endl;
                std::cout << "Rotation speed:     " << renderer.getRotationSpeed() << std::endl;
                std::cout << "Config file:        " << configFilePath << std::endl;
                std::cout << "Face resolutions:   ";
                auto faceResokutions = renderer.getFaceResolutions();
                for (int eye = 0; eye < StereoCubemap::MAX_EYES_COUNT; eye++)
                {
                    for (int face = 0; face < Cubemap::MAX_FACES_COUNT; face++)
                    {
                        auto faceResolution = faceResokutions[eye * Cubemap::MAX_FACES_COUNT + face];
                        std::cout << faceResolution.first << "x" << faceResolution.second << "px ";
                    }
                    std::cout << std::endl << "                    ";
                }
                std::cout << std::endl;
                std::cout << "Robust syncing:     " << ((robustSyncing) ? "yes" : "no") << std::endl;
                std::cout << "Cubemap queue size: " << maxFrameMapSize << std::endl;
                std::cout << "Force mono:         " << ((renderer.getForceMono()) ? "yes" : "no") << std::endl;
            }
        }
    };

    CommandHandler consoleCommandHandler({generalCommands, consoleOnlyCommands});
    configCommandHandler = CommandHandler({generalCommands, configCommandLineOnlyCommands});
    CommandHandler commandLineCommandHandler({generalCommands, configCommandLineOnlyCommands});

    auto commandLineParseResult = CommandLine::parseCommandLine(commandLineCommandHandler,
                                                                argc,
                                                                argv);
    if (!commandLineParseResult.first)
    {
        std::cerr << commandLineParseResult.second << std::endl;
        std::cerr << commandLineCommandHandler.getCommandHelpString();
        abort();
    }

    if (url == "")
    {
        std::cerr << "No URL specified." << std::endl;
        abort();
    }

    Console console(consoleCommandHandler);
    console.start();

    RTSPCubemapSourceClient* rtspClient = RTSPCubemapSourceClient::create(url.c_str(),
                                                                          bufferSize,
                                                                          AV_PIX_FMT_YUV420P,
                                                                          matchStereoPairs,
                                                                          robustSyncing,
                                                                          maxFrameMapSize,
                                                                          interfaceAddress.c_str());
    rtspClient->setOnDidConnect(boost::bind(&onDidConnect, _1, _2));
    rtspClient->connect();

    if (noDisplay)
    {
        std::cout << "network only" << std::endl;
        while(true)
        {
            boost::this_thread::yield();
        }
    }
    else
    {
        renderer.setOnDisplayedCubemapFace(boost::bind(&onDisplayedCubemapFace, _1, _2));
        renderer.setOnDisplayedFrame(boost::bind(&onDisplayedFrame, _1));
        renderer.start(); // does not return
    }
}
<commit_msg>Can activate and deactivate force mono.<commit_after>#include <boost/filesystem.hpp>
#include <boost/ref.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

#include "Renderer.hpp"
#include "AlloShared/StatsUtils.hpp"
#include "AlloShared/to_human_readable_byte_count.hpp"
#include "AlloShared/CommandHandler.hpp"
#include "AlloShared/Console.hpp"
#include "AlloShared/Config.hpp"
#include "AlloShared/CommandLine.hpp"
#include "AlloReceiver/RTSPCubemapSourceClient.hpp"
#include "AlloReceiver/AlloReceiver.h"
#include "AlloReceiver/Stats.hpp"
#include "AlloReceiver/H264CubemapSource.h"

#define DEG_DIV_RAD 57.29577951308233
#define RAD_DIV_DEG  0.01745329251994

const unsigned int DEFAULT_SINK_BUFFER_SIZE = 2000000000;

static Stats         stats;
static Renderer      renderer;
static auto          lastStatsTime    = boost::chrono::steady_clock::now();
static std::string   statsFormat      = AlloReceiver::formatStringMaker();
static bool          noDisplay        = false;
static std::string   url              = "";
static std::string   interfaceAddress = "0.0.0.0";
static unsigned long bufferSize       = DEFAULT_SINK_BUFFER_SIZE;
static bool          matchStereoPairs = false;
static boost::filesystem::path configFilePath;
static bool          robustSyncing    = false;
static size_t        maxFrameMapSize  = 2;
static std::string   logPath          = ".";

StereoCubemap* onNextCubemap(CubemapSource* source, StereoCubemap* cubemap)
{
    for (int i = 0; i < cubemap->getEye(0)->getFacesCount(); i++)
    {
        stats.store(StatsUtils::CubemapFace(i, StatsUtils::CubemapFace::DISPLAYED));
    }
    stats.store(StatsUtils::Cubemap());
    return cubemap;
}

void onReceivedNALU(CubemapSource* source, u_int8_t type, size_t size, int face)
{
    //stats.store(StatsUtils::NALU(type, size, face, StatsUtils::NALU::RECEIVED));
}

void onReceivedFrame(CubemapSource* source, u_int8_t type, size_t size, int face)
{
    //stats.store(StatsUtils::Frame(type, size, face, StatsUtils::Frame::RECEIVED));
}

void onDecodedFrame(CubemapSource* source, u_int8_t type, size_t size, int face)
{
    //stats.store(StatsUtils::Frame(type, size, face, StatsUtils::Frame::DECODED));
}

void onColorConvertedFrame(CubemapSource* source, u_int8_t type, size_t size, int face)
{
    stats.store(StatsUtils::Frame(type, size, face, StatsUtils::Frame::COLOR_CONVERTED));
}

void onAddedFrameToCubemap(CubemapSource* source, int face)
{
    //stats.store(StatsUtils::CubemapFace(face, StatsUtils::CubemapFace::ADDED));
}

void setOnScheduledFrameInCubemap(CubemapSource* source, int face)
{
    stats.store(StatsUtils::CubemapFace(face, StatsUtils::CubemapFace::SCHEDULED));
}

void onDisplayedCubemapFace(Renderer* renderer, int face)
{
    stats.store(StatsUtils::CubemapFace(face, StatsUtils::CubemapFace::DISPLAYED));
}

void onDisplayedFrame(Renderer* renderer)
{
    stats.store(StatsUtils::Cubemap());
}

void onDidConnect(RTSPCubemapSourceClient* client, CubemapSource* cubemapSource)
{
    H264CubemapSource* h264CubemapSource = dynamic_cast<H264CubemapSource*>(cubemapSource);
    if (h264CubemapSource)
    {
        h264CubemapSource->setOnReceivedNALU           (boost::bind(&onReceivedNALU,               _1, _2, _3, _4));
        h264CubemapSource->setOnReceivedFrame          (boost::bind(&onReceivedFrame,              _1, _2, _3, _4));
        h264CubemapSource->setOnDecodedFrame           (boost::bind(&onDecodedFrame,               _1, _2, _3, _4));
        h264CubemapSource->setOnColorConvertedFrame    (boost::bind(&onColorConvertedFrame,        _1, _2, _3, _4));
        h264CubemapSource->setOnAddedFrameToCubemap    (boost::bind(&onAddedFrameToCubemap,        _1, _2));
        h264CubemapSource->setOnScheduledFrameInCubemap(boost::bind(&setOnScheduledFrameInCubemap, _1, _2));
    }

    if (noDisplay)
    {
        cubemapSource->setOnNextCubemap(boost::bind(&onNextCubemap, _1, _2));
    }
    else
    {
        renderer.setCubemapSource(cubemapSource);
    }
}

int main(int argc, char* argv[])
{
    std::initializer_list<CommandHandler::Command> generalCommands =
    {
        {
            "gamma-min",
            {"val"},
            [](const std::vector<std::string>& values)
            {
                renderer.setGammaMin(boost::lexical_cast<float>(values[0]));
            }
        },
        {
            "gamma-max",
            {"val"},
            [](const std::vector<std::string>& values)
            {
                renderer.setGammaMax(boost::lexical_cast<float>(values[0]));
            }
        },
        {
            "gamma-pow",
            {"val"},
            [](const std::vector<std::string>& values)
            {
                renderer.setGammaPow(boost::lexical_cast<float>(values[0]));
            }
        },
        {
            "for-rotation",
            {"α°", "β°", "γ°"},
            [](const std::vector<std::string>& values)
            {
                renderer.setFORRotation(al::Vec3f(boost::lexical_cast<float>(values[0]) * RAD_DIV_DEG,
                                                  boost::lexical_cast<float>(values[1]) * RAD_DIV_DEG,
                                                  boost::lexical_cast<float>(values[2]) * RAD_DIV_DEG));
            }
        },
        {
            "for-angle",
            {"°"},
            [](const std::vector<std::string>& values)
            {
                renderer.setFORAngle(boost::lexical_cast<float>(values[0]) * RAD_DIV_DEG);
            }
        },
        {
            "rotation",
            {"α°", "β°", "γ°"},
            [](const std::vector<std::string>& values)
            {
                renderer.setRotation(al::Vec3f(boost::lexical_cast<float>(values[0]) * RAD_DIV_DEG,
                                               boost::lexical_cast<float>(values[1]) * RAD_DIV_DEG,
                                               boost::lexical_cast<float>(values[2]) * RAD_DIV_DEG));
            }
        },
        {
            "rotation-speed",
            {"val"},
            [](const std::vector<std::string>& values)
            {
                renderer.setRotationSpeed(boost::lexical_cast<float>(values[0]));
            }
        },
        {
            "force-mono",
            {"yes|no"},
            [](const std::vector<std::string>& values)
            {
                if (values[0] == "yes")
                {
                    renderer.setForceMono(true);
                }
                else if (values[0] == "no")
                {
                    renderer.setForceMono(false);
                }
                else
                {
                    throw std::invalid_argument("Only yes or no are valid values");
                }
            }
        },
    };

    CommandHandler configCommandHandler({});

    std::initializer_list<CommandHandler::Command> configCommandLineOnlyCommands =
    {
        {
            "config",
            {"file_path"},
            [&configCommandHandler](const std::vector<std::string>& values)
            {
                configFilePath = boost::filesystem::canonical(boost::filesystem::absolute(values[0], configFilePath.parent_path()));

                auto configParseResult = Config::parseConfigFile(configCommandHandler,
                                                                 configFilePath.string());
                if (!configParseResult.first)
                {
                    std::cerr << configParseResult.second << std::endl;
                    std::cerr << configCommandHandler.getCommandHelpString();
                    abort();
                }
            }
        },
        {
            "no-display",
            {},
            [](const std::vector<std::string>& values)
            {
                noDisplay = true;
            }
        },
        {
            "url",
            {"rtsp_url"},
            [](const std::vector<std::string>& values)
            {
                url = values[0];
            }
        },
        {
            "interface-address",
            {"ip"},
            [](const std::vector<std::string>& values)
            {
                interfaceAddress = values[0];
            }
        },
        {
            "buffer-size",
            {"bytes"},
            [](const std::vector<std::string>& values)
            {
                bufferSize = boost::lexical_cast<unsigned long>(values[0]);
            }
        },
        {
            "match-stereo-pairs",
            {},
            [](const std::vector<std::string>& values)
            {
                matchStereoPairs = true;
            }
        },
        {
            "robust-syncing",
            {},
            [](const std::vector<std::string>& values)
            {
                robustSyncing = true;
            }
        },
        {
            "cubemap-queue-size",
            {"size"},
            [](const std::vector<std::string>& values)
            {
                maxFrameMapSize = boost::lexical_cast<size_t>(values[0]);
            }
        }
    };

    std::initializer_list<CommandHandler::Command> consoleOnlyCommands =
    {
        {
            "stats",
            {},
            [](const std::vector<std::string>& values)
            {
                boost::chrono::steady_clock::time_point now = boost::chrono::steady_clock::now();
                std::cout << stats.summary(boost::chrono::duration_cast<boost::chrono::microseconds>(now - lastStatsTime),
                                           AlloReceiver::statValsMaker,
                                           AlloReceiver::postProcessorMaker,
                                           statsFormat);
                lastStatsTime = now;
            }
        },
        {
            "quit",
            {},
            [](const std::vector<std::string>& values)
            {
                exit(0);
            }
        },
        {
            "info",
            {},
            [](const std::vector<std::string>& values)
            {
                al::Vec3f forRotation = renderer.getFORRotation() * DEG_DIV_RAD;
                al::Vec3f rotation    = renderer.getRotation()    * DEG_DIV_RAD;

                std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(1);
                std::cout << "Display:            " << ((noDisplay) ? "no" : "yes") << std::endl;
                std::cout << "RTSP URL:           " << url << std::endl;
                std::cout << "Interface address:  " << interfaceAddress << std::endl;
                std::cout << "Buffer size:        " << to_human_readable_byte_count(bufferSize, false, false) << std::endl;
                std::cout << "Match stereo pairs: " << ((matchStereoPairs) ? "yes" : "no") << std::endl;
                std::cout << "Gamma min:          " << renderer.getGammaMin() << std::endl;
                std::cout << "Gamma max:          " << renderer.getGammaMax() << std::endl;
                std::cout << "Gamma pow:          " << renderer.getGammaPow() << std::endl;
                std::cout << "FOR angle:          " << renderer.getFORAngle() * DEG_DIV_RAD << "°" << std::endl;
                std::cout << "FOR rotation:       " << "α=" << forRotation[0] << "°\t"
                                                    << "β=" << forRotation[1] << "°\t"
                                                    << "γ=" << forRotation[2] << "°" << std::endl;
                std::cout << "Scene rotation:     " << "α=" << rotation[0] << "°\t"
                                                    << "β=" << rotation[1] << "°\t"
                                                    << "γ=" << rotation[2] << "°" << std::endl;
                std::cout << "Rotation speed:     " << renderer.getRotationSpeed() << std::endl;
                std::cout << "Config file:        " << configFilePath << std::endl;
                std::cout << "Face resolutions:   ";
                auto faceResokutions = renderer.getFaceResolutions();
                for (int eye = 0; eye < StereoCubemap::MAX_EYES_COUNT; eye++)
                {
                    for (int face = 0; face < Cubemap::MAX_FACES_COUNT; face++)
                    {
                        auto faceResolution = faceResokutions[eye * Cubemap::MAX_FACES_COUNT + face];
                        std::cout << faceResolution.first << "x" << faceResolution.second << "px ";
                    }
                    std::cout << std::endl << "                    ";
                }
                std::cout << std::endl;
                std::cout << "Robust syncing:     " << ((robustSyncing) ? "yes" : "no") << std::endl;
                std::cout << "Cubemap queue size: " << maxFrameMapSize << std::endl;
                std::cout << "Force mono:         " << ((renderer.getForceMono()) ? "yes" : "no") << std::endl;
            }
        }
    };

    CommandHandler consoleCommandHandler({generalCommands, consoleOnlyCommands});
    configCommandHandler = CommandHandler({generalCommands, configCommandLineOnlyCommands});
    CommandHandler commandLineCommandHandler({generalCommands, configCommandLineOnlyCommands});

    auto commandLineParseResult = CommandLine::parseCommandLine(commandLineCommandHandler,
                                                                argc,
                                                                argv);
    if (!commandLineParseResult.first)
    {
        std::cerr << commandLineParseResult.second << std::endl;
        std::cerr << commandLineCommandHandler.getCommandHelpString();
        abort();
    }

    if (url == "")
    {
        std::cerr << "No URL specified." << std::endl;
        abort();
    }

    Console console(consoleCommandHandler);
    console.start();

    RTSPCubemapSourceClient* rtspClient = RTSPCubemapSourceClient::create(url.c_str(),
                                                                          bufferSize,
                                                                          AV_PIX_FMT_YUV420P,
                                                                          matchStereoPairs,
                                                                          robustSyncing,
                                                                          maxFrameMapSize,
                                                                          interfaceAddress.c_str());
    rtspClient->setOnDidConnect(boost::bind(&onDidConnect, _1, _2));
    rtspClient->connect();

    if (noDisplay)
    {
        std::cout << "network only" << std::endl;
        while(true)
        {
            boost::this_thread::yield();
        }
    }
    else
    {
        renderer.setOnDisplayedCubemapFace(boost::bind(&onDisplayedCubemapFace, _1, _2));
        renderer.setOnDisplayedFrame(boost::bind(&onDisplayedFrame, _1));
        renderer.start(); // does not return
    }
}
<|endoftext|>


<commit_before>#include "Limiter.h"
#include "Testing.h"

#include <iostream>

static auto CurrentTime() { return std::chrono::high_resolution_clock::now(); }
static constexpr auto oneSecond = std::chrono::seconds(1);

std::ostream& operator<<(std::ostream& os, HttpResult::Code code)
{
    const auto str =
        code == HttpResult::Code::Ok ? "Ok (200)" :
        code == HttpResult::Code::TooManyRequests ? "Too many requests (429)" :
        "Unknown code";
    os << str;
    return os;
}

template <typename Clock, typename Duration>
std::string millisecondsSinceStart(std::chrono::time_point<Clock, Duration> timepoint)
{
    const static auto start = timepoint.time_since_epoch().count();
    return std::to_string((timepoint.time_since_epoch().count() - start) / 1'000'000);
}

static auto TestAllRequestsBelowMaxAreAccepted(int maxAllowedRps)
{
    Limiter limiter(maxAllowedRps, 100);
    const auto startTime = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < maxAllowedRps; ++i)
        if (CurrentTime() < startTime + oneSecond)
            ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
}

static auto TestAllRequestsAboveMaxAreDeclined(int maxAllowedRps)
{
    Limiter limiter(maxAllowedRps, 100);
    const auto startTime = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < maxAllowedRps; ++i)
        if (CurrentTime() < startTime + oneSecond)
            limiter.ValidateRequest();

    while (CurrentTime() < startTime + oneSecond)
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);
}

struct TimeStamps
{
    const std::chrono::time_point<std::chrono::high_resolution_clock> firstAcceptedRequest;
    const std::chrono::time_point<std::chrono::high_resolution_clock> lastAcceptedRequest;
};

static auto TestWithPeakLoadAtStart(Limiter& limiter)
{
    // Accepting the requests until we hit the limit.
    const auto firstAcceptedRequestTime = CurrentTime();
    for (int i = 0; i < limiter.maxRPS(); ++i)
    {
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
    }
    const auto lastAcceptedRequestTime = CurrentTime();

    // Not accepting more requests within current second.
    while (CurrentTime() < firstAcceptedRequestTime + oneSecond)
    {
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);
    }

    // Still not accepting requests if less than one second has elapsed after the first request.
    if (CurrentTime() < firstAcceptedRequestTime + oneSecond)
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);

    std::this_thread::sleep_until(firstAcceptedRequestTime + std::chrono::milliseconds(900));
    if (CurrentTime() < firstAcceptedRequestTime + oneSecond)
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);

    return TimeStamps{ firstAcceptedRequestTime, lastAcceptedRequestTime };
}

static auto TestWithPeakLoadAtStart_SingleIteration(int maxAllowedRps)
{
    Limiter limiter(maxAllowedRps, 100);

    const auto timeStamps = TestWithPeakLoadAtStart(limiter);

    // Herewith we ensure that NOT MORE than maxAllowedRps requests are allowed per second.
    // It is possible that the limiter will allow a bit LESS, though, hence this "delta" allowance
    // in the assertion below.
    constexpr auto delayDueToTimerIssueObtainedEmpirically = std::chrono::milliseconds(42);
    std::this_thread::sleep_until(timeStamps.firstAcceptedRequest + oneSecond + delayDueToTimerIssueObtainedEmpirically);
    ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
}

static auto TestWithPeakLoadAtStart_MultipleIterations(int maxAllowedRps, int iterations)
{
    Limiter limiter(maxAllowedRps, 100);

    for (int i = 0; i < iterations; ++i)
    {
        const auto timeStamps = TestWithPeakLoadAtStart(limiter);
        std::this_thread::sleep_until(timeStamps.lastAcceptedRequest + oneSecond);
    }
}

static auto TestWithEvenLoad(int maxAllowedRps)
{
    Limiter limiter(maxAllowedRps, 100);
    const auto intervalBetweenRequests = oneSecond / (2 * maxAllowedRps);

    for (int iterations = 0; iterations < 5; ++iterations)
    {
        int requestsSent = 0;
        const auto startTime = CurrentTime();

        while (requestsSent < maxAllowedRps &&
               CurrentTime() < startTime + oneSecond)
        {
            ++requestsSent;
            const auto result = limiter.ValidateRequest();

            ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
            std::this_thread::sleep_for(intervalBetweenRequests);
        }
        const auto lastValidRequestTime = CurrentTime();

        while (CurrentTime() < startTime + oneSecond)
        {
            ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);
            std::this_thread::sleep_for(intervalBetweenRequests);
        }

        std::this_thread::sleep_until(lastValidRequestTime + oneSecond);
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
    }
}

static auto TestWithAdjacentPeaks(int maxAllowedRps)
{
    const auto startTime = CurrentTime();

    Limiter limiter(maxAllowedRps, 100);

    std::this_thread::sleep_until(startTime + std::chrono::milliseconds(900));
    int requestsSent = 0;
    while (requestsSent < maxAllowedRps * 0.8)
    {
        requestsSent++;
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
    }

    std::this_thread::sleep_until(startTime + std::chrono::milliseconds(1500));
    while (requestsSent < maxAllowedRps)
    {
        requestsSent++;
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
    }

    while (CurrentTime() < startTime + std::chrono::milliseconds(1900))
    {
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);
    }

    std::this_thread::sleep_until(startTime + std::chrono::milliseconds(2000));
    ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
}

namespace LimiterSpecs
{
    static constexpr int minRPS = 1;
    static constexpr int maxRPS = 100'000;
};

int main()
{
    // Failing tests are commented out.
    try
    {
        TestAllRequestsBelowMaxAreAccepted(LimiterSpecs::maxRPS);
        TestAllRequestsAboveMaxAreDeclined(LimiterSpecs::maxRPS);
        TestWithPeakLoadAtStart_SingleIteration(LimiterSpecs::maxRPS);
        //TestWithPeakLoadAtStart_MultipleIterations(LimiterSpecs::maxRPS, 10);
        TestWithAdjacentPeaks(LimiterSpecs::maxRPS);
        TestWithEvenLoad(LimiterSpecs::maxRPS);
        std::cout << "All Tests passed successfully\n";
    }
    catch (AssertionException& e)
    {
        std::cout << "One or more of tests failed: " << e.what() << '\n';
    }
    system("pause");
    return 0;
}
<commit_msg>Remove redundant check in TestWithPeakLoadAtStart<commit_after>#include "Limiter.h"
#include "Testing.h"

#include <iostream>

static auto CurrentTime() { return std::chrono::high_resolution_clock::now(); }
static constexpr auto oneSecond = std::chrono::seconds(1);

std::ostream& operator<<(std::ostream& os, HttpResult::Code code)
{
    const auto str =
        code == HttpResult::Code::Ok ? "Ok (200)" :
        code == HttpResult::Code::TooManyRequests ? "Too many requests (429)" :
        "Unknown code";
    os << str;
    return os;
}

template <typename Clock, typename Duration>
std::string millisecondsSinceStart(std::chrono::time_point<Clock, Duration> timepoint)
{
    const static auto start = timepoint.time_since_epoch().count();
    return std::to_string((timepoint.time_since_epoch().count() - start) / 1'000'000);
}

static auto TestAllRequestsBelowMaxAreAccepted(int maxAllowedRps)
{
    Limiter limiter(maxAllowedRps, 100);
    const auto startTime = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < maxAllowedRps; ++i)
        if (CurrentTime() < startTime + oneSecond)
            ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
}

static auto TestAllRequestsAboveMaxAreDeclined(int maxAllowedRps)
{
    Limiter limiter(maxAllowedRps, 100);
    const auto startTime = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < maxAllowedRps; ++i)
        if (CurrentTime() < startTime + oneSecond)
            limiter.ValidateRequest();

    while (CurrentTime() < startTime + oneSecond)
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);
}

struct TimeStamps
{
    const std::chrono::time_point<std::chrono::high_resolution_clock> firstAcceptedRequest;
    const std::chrono::time_point<std::chrono::high_resolution_clock> lastAcceptedRequest;
};

static auto TestWithPeakLoadAtStart(Limiter& limiter)
{
    // Accepting the requests until we hit the limit.
    const auto firstAcceptedRequestTime = CurrentTime();
    for (int i = 0; i < limiter.maxRPS(); ++i)
    {
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
    }
    const auto lastAcceptedRequestTime = CurrentTime();

    // Do not accept requests if less than one second has elapsed after the first request.
    if (CurrentTime() < firstAcceptedRequestTime + oneSecond)
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);

    std::this_thread::sleep_until(firstAcceptedRequestTime + std::chrono::milliseconds(900));
    if (CurrentTime() < firstAcceptedRequestTime + oneSecond)
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);

    return TimeStamps{ firstAcceptedRequestTime, lastAcceptedRequestTime };
}

static auto TestWithPeakLoadAtStart_SingleIteration(int maxAllowedRps)
{
    Limiter limiter(maxAllowedRps, 100);

    const auto timeStamps = TestWithPeakLoadAtStart(limiter);

    // Herewith we ensure that NOT MORE than maxAllowedRps requests are allowed per second.
    // It is possible that the limiter will allow a bit LESS, though, hence this "delta" allowance
    // in the assertion below.
    constexpr auto delayDueToTimerIssueObtainedEmpirically = std::chrono::milliseconds(42);
    std::this_thread::sleep_until(timeStamps.firstAcceptedRequest + oneSecond + delayDueToTimerIssueObtainedEmpirically);
    ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
}

static auto TestWithPeakLoadAtStart_MultipleIterations(int maxAllowedRps, int iterations)
{
    Limiter limiter(maxAllowedRps, 100);

    for (int i = 0; i < iterations; ++i)
    {
        const auto timeStamps = TestWithPeakLoadAtStart(limiter);
        std::this_thread::sleep_until(timeStamps.lastAcceptedRequest + oneSecond);
    }
}

static auto TestWithEvenLoad(int maxAllowedRps)
{
    Limiter limiter(maxAllowedRps, 100);
    const auto intervalBetweenRequests = oneSecond / (2 * maxAllowedRps);

    for (int iterations = 0; iterations < 5; ++iterations)
    {
        int requestsSent = 0;
        const auto startTime = CurrentTime();

        while (requestsSent < maxAllowedRps &&
               CurrentTime() < startTime + oneSecond)
        {
            ++requestsSent;
            const auto result = limiter.ValidateRequest();

            ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
            std::this_thread::sleep_for(intervalBetweenRequests);
        }
        const auto lastValidRequestTime = CurrentTime();

        while (CurrentTime() < startTime + oneSecond)
        {
            ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);
            std::this_thread::sleep_for(intervalBetweenRequests);
        }

        std::this_thread::sleep_until(lastValidRequestTime + oneSecond);
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
    }
}

static auto TestWithAdjacentPeaks(int maxAllowedRps)
{
    const auto startTime = CurrentTime();

    Limiter limiter(maxAllowedRps, 100);

    std::this_thread::sleep_until(startTime + std::chrono::milliseconds(900));
    int requestsSent = 0;
    while (requestsSent < maxAllowedRps * 0.8)
    {
        requestsSent++;
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
    }

    std::this_thread::sleep_until(startTime + std::chrono::milliseconds(1500));
    while (requestsSent < maxAllowedRps)
    {
        requestsSent++;
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
    }

    while (CurrentTime() < startTime + std::chrono::milliseconds(1900))
    {
        ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::TooManyRequests);
    }

    std::this_thread::sleep_until(startTime + std::chrono::milliseconds(2000));
    ASSERT_EQUAL(limiter.ValidateRequest(), HttpResult::Code::Ok);
}

namespace LimiterSpecs
{
    static constexpr int minRPS = 1;
    static constexpr int maxRPS = 100'000;
};

int main()
{
    // Failing tests are commented out.
    try
    {
        TestAllRequestsBelowMaxAreAccepted(LimiterSpecs::maxRPS);
        TestAllRequestsAboveMaxAreDeclined(LimiterSpecs::maxRPS);
        TestWithPeakLoadAtStart_SingleIteration(LimiterSpecs::maxRPS);
        //TestWithPeakLoadAtStart_MultipleIterations(LimiterSpecs::maxRPS, 10);
        TestWithAdjacentPeaks(LimiterSpecs::maxRPS);
        TestWithEvenLoad(LimiterSpecs::maxRPS);
        std::cout << "All Tests passed successfully\n";
    }
    catch (AssertionException& e)
    {
        std::cout << "One or more of tests failed: " << e.what() << '\n';
    }
    system("pause");
    return 0;
}
<|endoftext|>


<commit_before>#include <nan.h>

using namespace v8;

struct HeapInfo {
	size_t totalHeapSize;
	size_t totalHeapExecutableSize;
	size_t totalPhysicalSize;
	size_t usedHeapSize;
	size_t heapSizeLimit;
};

struct HeapData {
	HeapInfo* before;
	HeapInfo* after;
	uint64_t gcStartTime;
	uint64_t gcEndTime;
};

static Nan::Callback* afterGCCallback;

static HeapStatistics beforeGCStats;
uint64_t gcStartTime;
GCType gctype;

static NAN_GC_CALLBACK(recordBeforeGC) {
	//Docs say that new objects should not be created
	gcStartTime = uv_hrtime();
	Nan::GetHeapStatistics(&beforeGCStats);
}

static void copyHeapStats(HeapStatistics* stats, HeapInfo* info) {
	info->totalHeapSize = stats->total_heap_size();
	info->totalHeapExecutableSize = stats->total_heap_size_executable();
	#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
	info->totalPhysicalSize = stats->total_physical_size();
	#endif
	info->usedHeapSize = stats->used_heap_size();
	info->heapSizeLimit = stats->heap_size_limit();
}

static void formatStats(Local<Object> obj, HeapInfo* info) {
	Nan::Set(obj, Nan::New("totalHeapSize").ToLocalChecked(), Nan::New<Number>(info->totalHeapSize));
	Nan::Set(obj, Nan::New("totalHeapExecutableSize").ToLocalChecked(), Nan::New<Number>(info->totalHeapExecutableSize));
	Nan::Set(obj, Nan::New("usedHeapSize").ToLocalChecked(), Nan::New<Number>(info->usedHeapSize));
	Nan::Set(obj, Nan::New("heapSizeLimit").ToLocalChecked(), Nan::New<Number>(info->heapSizeLimit));
	#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
	Nan::Set(obj, Nan::New("totalPhysicalSize").ToLocalChecked(), Nan::New<Number>(info->totalPhysicalSize));
	#endif
}

static void formatStatDiff(Local<Object> obj, HeapInfo* before, HeapInfo* after) {
	Nan::Set(obj, Nan::New("totalHeapSize").ToLocalChecked(), Nan::New<Number>(
		static_cast<double>(after->totalHeapSize) - static_cast<double>(before->totalHeapSize)));
	Nan::Set(obj, Nan::New("totalHeapExecutableSize").ToLocalChecked(), Nan::New<Number>(
		static_cast<double>(after->totalHeapExecutableSize) - static_cast<double>(before->totalHeapExecutableSize)));
	Nan::Set(obj, Nan::New("usedHeapSize").ToLocalChecked(), Nan::New<Number>(
		static_cast<double>(after->usedHeapSize) - static_cast<double>(before->usedHeapSize)));
	Nan::Set(obj, Nan::New("heapSizeLimit").ToLocalChecked(), Nan::New<Number>(
		static_cast<double>(after->heapSizeLimit) - static_cast<double>(before->heapSizeLimit)));
	#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
	Nan::Set(obj, Nan::New("totalPhysicalSize").ToLocalChecked(), Nan::New<Number>(
		static_cast<double>(after->totalPhysicalSize) - static_cast<double>(before->totalPhysicalSize)));
	#endif
}

static void asyncAfter(uv_work_t* work, int status) {
	Nan::HandleScope scope;

	HeapData* data = static_cast<HeapData*>(work->data);

	Local<Object> obj = Nan::New<Object>();
	Local<Object> beforeGCStats = Nan::New<Object>();
	Local<Object> afterGCStats = Nan::New<Object>();

	formatStats(beforeGCStats, data->before);
	formatStats(afterGCStats, data->after);

	Local<Object> diffStats = Nan::New<Object>();
	formatStatDiff(diffStats, data->before, data->after);

	Nan::Set(obj, Nan::New("pause").ToLocalChecked(),
		Nan::New<Number>(static_cast<double>(data->gcEndTime - data->gcStartTime)));
	Nan::Set(obj, Nan::New("pauseMS").ToLocalChecked(),
		Nan::New<Number>(static_cast<double>((data->gcEndTime - data->gcStartTime) / 1000000)));
	Nan::Set(obj, Nan::New("gctype").ToLocalChecked(), Nan::New<Number>(gctype));
	Nan::Set(obj, Nan::New("before").ToLocalChecked(), beforeGCStats);
	Nan::Set(obj, Nan::New("after").ToLocalChecked(), afterGCStats);
	Nan::Set(obj, Nan::New("diff").ToLocalChecked(), diffStats);

	Local<Value> arguments[] = {obj};

	afterGCCallback->Call(1, arguments);

	delete data->before;
	delete data->after;
	delete data;
	delete work;
}

static void asyncWork(uv_work_t* work) {
	//can't create V8 objects here because this is different thread?
}

NAN_GC_CALLBACK(afterGC) {
	uv_work_t* work = new uv_work_t;

	HeapData* data = new HeapData;
	data->before = new HeapInfo;
	data->after = new HeapInfo;
	gctype = type;
	HeapStatistics stats;

	Nan::GetHeapStatistics(&stats);

	data->gcEndTime = uv_hrtime();
	data->gcStartTime = gcStartTime;

	copyHeapStats(&beforeGCStats, data->before);
	copyHeapStats(&stats, data->after);

	work->data = data;

	uv_queue_work(uv_default_loop(), work, asyncWork, asyncAfter);
}

static NAN_METHOD(AfterGC) {
	if(info.Length() != 1 || !info[0]->IsFunction()) {
		return Nan::ThrowError("Callback is required");
	}

	Local<Function> callbackHandle = info[0].As<Function>();
	afterGCCallback = new Nan::Callback(callbackHandle);

	Nan::AddGCEpilogueCallback(afterGC);
}

NAN_MODULE_INIT(init) {
	Nan::HandleScope scope;
	Nan::AddGCPrologueCallback(recordBeforeGC);

	Nan::Set(target,
		Nan::New("afterGC").ToLocalChecked(),
		Nan::GetFunction(
			Nan::New<FunctionTemplate>(AfterGC)).ToLocalChecked());
}

NODE_MODULE(gcstats, init)
<commit_msg>Use spaces for indention in all spaces<commit_after>#include <nan.h>

using namespace v8;

struct HeapInfo {
  size_t totalHeapSize;
  size_t totalHeapExecutableSize;
  size_t totalPhysicalSize;
  size_t usedHeapSize;
  size_t heapSizeLimit;
};

struct HeapData {
  HeapInfo* before;
  HeapInfo* after;
  uint64_t gcStartTime;
  uint64_t gcEndTime;
};

static Nan::Callback* afterGCCallback;

static HeapStatistics beforeGCStats;
uint64_t gcStartTime;
GCType gctype;

static NAN_GC_CALLBACK(recordBeforeGC) {
  //Docs say that new objects should not be created
  gcStartTime = uv_hrtime();
  Nan::GetHeapStatistics(&beforeGCStats);
}

static void copyHeapStats(HeapStatistics* stats, HeapInfo* info) {
  info->totalHeapSize = stats->total_heap_size();
  info->totalHeapExecutableSize = stats->total_heap_size_executable();
  #if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
  info->totalPhysicalSize = stats->total_physical_size();
  #endif
  info->usedHeapSize = stats->used_heap_size();
  info->heapSizeLimit = stats->heap_size_limit();
}

static void formatStats(Local<Object> obj, HeapInfo* info) {
  Nan::Set(obj, Nan::New("totalHeapSize").ToLocalChecked(), Nan::New<Number>(info->totalHeapSize));
  Nan::Set(obj, Nan::New("totalHeapExecutableSize").ToLocalChecked(), Nan::New<Number>(info->totalHeapExecutableSize));
  Nan::Set(obj, Nan::New("usedHeapSize").ToLocalChecked(), Nan::New<Number>(info->usedHeapSize));
  Nan::Set(obj, Nan::New("heapSizeLimit").ToLocalChecked(), Nan::New<Number>(info->heapSizeLimit));
  #if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
  Nan::Set(obj, Nan::New("totalPhysicalSize").ToLocalChecked(), Nan::New<Number>(info->totalPhysicalSize));
  #endif
}

static void formatStatDiff(Local<Object> obj, HeapInfo* before, HeapInfo* after) {
  Nan::Set(obj, Nan::New("totalHeapSize").ToLocalChecked(), Nan::New<Number>(
    static_cast<double>(after->totalHeapSize) - static_cast<double>(before->totalHeapSize)));
  Nan::Set(obj, Nan::New("totalHeapExecutableSize").ToLocalChecked(), Nan::New<Number>(
    static_cast<double>(after->totalHeapExecutableSize) - static_cast<double>(before->totalHeapExecutableSize)));
  Nan::Set(obj, Nan::New("usedHeapSize").ToLocalChecked(), Nan::New<Number>(
    static_cast<double>(after->usedHeapSize) - static_cast<double>(before->usedHeapSize)));
  Nan::Set(obj, Nan::New("heapSizeLimit").ToLocalChecked(), Nan::New<Number>(
    static_cast<double>(after->heapSizeLimit) - static_cast<double>(before->heapSizeLimit)));
  #if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
  Nan::Set(obj, Nan::New("totalPhysicalSize").ToLocalChecked(), Nan::New<Number>(
    static_cast<double>(after->totalPhysicalSize) - static_cast<double>(before->totalPhysicalSize)));
  #endif
}

static void asyncAfter(uv_work_t* work, int status) {
  Nan::HandleScope scope;

  HeapData* data = static_cast<HeapData*>(work->data);

  Local<Object> obj = Nan::New<Object>();
  Local<Object> beforeGCStats = Nan::New<Object>();
  Local<Object> afterGCStats = Nan::New<Object>();

  formatStats(beforeGCStats, data->before);
  formatStats(afterGCStats, data->after);

  Local<Object> diffStats = Nan::New<Object>();
  formatStatDiff(diffStats, data->before, data->after);

  Nan::Set(obj, Nan::New("pause").ToLocalChecked(),
    Nan::New<Number>(static_cast<double>(data->gcEndTime - data->gcStartTime)));
  Nan::Set(obj, Nan::New("pauseMS").ToLocalChecked(),
    Nan::New<Number>(static_cast<double>((data->gcEndTime - data->gcStartTime) / 1000000)));
  Nan::Set(obj, Nan::New("gctype").ToLocalChecked(), Nan::New<Number>(gctype));
  Nan::Set(obj, Nan::New("before").ToLocalChecked(), beforeGCStats);
  Nan::Set(obj, Nan::New("after").ToLocalChecked(), afterGCStats);
  Nan::Set(obj, Nan::New("diff").ToLocalChecked(), diffStats);

  Local<Value> arguments[] = {obj};

  afterGCCallback->Call(1, arguments);

  delete data->before;
  delete data->after;
  delete data;
  delete work;
}

static void asyncWork(uv_work_t* work) {
  //can't create V8 objects here because this is different thread?
}

NAN_GC_CALLBACK(afterGC) {
  uv_work_t* work = new uv_work_t;

  HeapData* data = new HeapData;
  data->before = new HeapInfo;
  data->after = new HeapInfo;
  gctype = type;
  HeapStatistics stats;

  Nan::GetHeapStatistics(&stats);

  data->gcEndTime = uv_hrtime();
  data->gcStartTime = gcStartTime;

  copyHeapStats(&beforeGCStats, data->before);
  copyHeapStats(&stats, data->after);

  work->data = data;

  uv_queue_work(uv_default_loop(), work, asyncWork, asyncAfter);
}

static NAN_METHOD(AfterGC) {
  if(info.Length() != 1 || !info[0]->IsFunction()) {
    return Nan::ThrowError("Callback is required");
  }

  Local<Function> callbackHandle = info[0].As<Function>();
  afterGCCallback = new Nan::Callback(callbackHandle);

  Nan::AddGCEpilogueCallback(afterGC);
}

NAN_MODULE_INIT(init) {
  Nan::HandleScope scope;
  Nan::AddGCPrologueCallback(recordBeforeGC);

  Nan::Set(target,
    Nan::New("afterGC").ToLocalChecked(),
    Nan::GetFunction(
      Nan::New<FunctionTemplate>(AfterGC)).ToLocalChecked());
}

NODE_MODULE(gcstats, init)
<|endoftext|>


<commit_before>#pragma once

struct Node {
    uint32_t index;
    char name[128];
    uint32_t numInputSlots = 0;
    uint32_t inputIndex[8];
    uint32_t numOutputSlots = 0;
    uint32_t outputIndex[8];
    glm::vec2 pos = glm::vec2(0.0f);
    glm::vec2 size = glm::vec2(250, 100);

    virtual ~Node() {}

    virtual void Save(std::ofstream* file) {
        file->write(reinterpret_cast<char*>(&index), sizeof(uint32_t));
        file->write(reinterpret_cast<char*>(name), 128);
        file->write(reinterpret_cast<char*>(&numInputSlots), sizeof(uint32_t));
    }

    virtual void Load(std::ifstream* file) {
        file->read(reinterpret_cast<char*>(&index), sizeof(uint32_t));
        file->read(reinterpret_cast<char*>(name), 128);
        file->read(reinterpret_cast<char*>(&numInputSlots), sizeof(uint32_t));
    }
};<commit_msg>Node documentation.<commit_after>#pragma once

/// Default node for node editor.
struct Node {
    uint32_t index;
    char name[128];
    uint32_t numInputSlots = 0;
    uint32_t inputIndex[8];
    uint32_t numOutputSlots = 0;
    uint32_t outputIndex[8];
    glm::vec2 pos = glm::vec2(0.0f);
    glm::vec2 size = glm::vec2(250, 100);

    /// Destructor.
    virtual ~Node() {}

    /// Save node data.
    /**
     * @param file File to save to.
     */
    virtual void Save(std::ofstream* file) {
        file->write(reinterpret_cast<char*>(&index), sizeof(uint32_t));
        file->write(reinterpret_cast<char*>(name), 128);
        file->write(reinterpret_cast<char*>(&numInputSlots), sizeof(uint32_t));
    }

    /// Load node data.
    /**
     * @param file File to load from.
     */
    virtual void Load(std::ifstream* file) {
        file->read(reinterpret_cast<char*>(&index), sizeof(uint32_t));
        file->read(reinterpret_cast<char*>(name), 128);
        file->read(reinterpret_cast<char*>(&numInputSlots), sizeof(uint32_t));
    }
};<|endoftext|>


<commit_before>#include "audio.h"
#include <fmod.h>
#include <fmod_errors.h>

#define ERRCHECK(res)	if (res != FMOD_OK){\
	DEBUGOUT("FMOD error! (%d) %s\n", res, FMOD_ErrorString(res));\
    exit(-1);}

#define PITCHSCALE 0.1
#define MAX_PITCH 2
#define ENGINE_SOUND_FILE "assets/audio/engineNoise3.wav"

#define DOPPLER_SCALE 1.0f
#define DISTANCE_FACTOR 1.0f
#define ROLL_OFF_SCALE 1.0f

#define MUSIC_VOLUME 0.03
#define SOUND_EFFECTS_VOLUME 0.1
#define LOW_ENGINE_NOISE_VOLUME 1

Audio::Audio() {

	m_pMailbox = new Events::Mailbox();
	m_pMailbox->request( Events::EventType::Input );
	m_pMailbox->request( Events::EventType::PowerupPickup );

	SetupHardware();

	//// Setup music and sound effects channels
	ERRCHECK(m_system->createChannelGroup("Effects", &m_channelGroupEffects));
	ERRCHECK(m_system->createChannelGroup("Music", &m_channelGroupMusic));

	musicVol = MUSIC_VOLUME;
	sfxVol = SOUND_EFFECTS_VOLUME;

	m_channelGroupMusic->setVolume(musicVol);
	m_channelGroupEffects->setVolume(sfxVol);

	// Load all the sound files
	LoadMusic("assets/audio/BrainDead.mp3");
	playMusic = true;

	Sounds.PowerUp = LoadSound("assets/audio/powerup2.wav");
	Sounds.LowFreqEngine = LoadSound("assets/audio/engineIdleNoise1.wav");
	Sounds.MachineGun = LoadSound("assets/audio/machineGun1.aiff");

	StartMusic();
	//Setup3DEnvironment();
	SetupEngineSounds();
}

Audio::~Audio() {

	m_system->release();

	if(m_pMailbox)
		delete m_pMailbox;
}

int Audio::SetupHardware(){

	FMOD_RESULT result;
	unsigned int version;
	int numdrivers;
	FMOD_SPEAKERMODE speakermode;
	FMOD_CAPS caps;
	char name[256];
	/*
	Create a System object and initialize.
	*/
	result = FMOD::System_Create(&m_system);
	ERRCHECK(result);
	result = m_system->getVersion(&version);
	ERRCHECK(result);
	if (version < FMOD_VERSION)
	{
		printf("Error! You are using an old version of FMOD %08x.  This program requires %08x\n",
			version, FMOD_VERSION);
		return 0;
	}
	result = m_system->getNumDrivers(&numdrivers);
	ERRCHECK(result);
	if (numdrivers == 0)
	{
		result = m_system->setOutput(FMOD_OUTPUTTYPE_NOSOUND);
		ERRCHECK(result);
	}
	else
	{
		result = m_system->getDriverCaps(0, &caps, 0, &speakermode);
		ERRCHECK(result);
		/*
		Set the user selected speaker mode.
		*/
		result = m_system->setSpeakerMode(speakermode);
		ERRCHECK(result);
		if (caps & FMOD_CAPS_HARDWARE_EMULATED)
		{
			/*
			The user has the 'Acceleration' slider set to off! This is really bad
			for latency! You might want to warn the user about this.
			*/
			result = m_system->setDSPBufferSize(1024, 10);
			ERRCHECK(result);
		}
		result = m_system->getDriverInfo(0, name, 256, 0);
		ERRCHECK(result);
		if (strstr(name, "SigmaTel"))
		{
			/*
			Sigmatel sound devices crackle for some reason if the format is PCM 16bit.
			PCM floating point output seems to solve it.
			*/
			result = m_system->setSoftwareFormat(48000, FMOD_SOUND_FORMAT_PCMFLOAT, 0,0,
				FMOD_DSP_RESAMPLER_LINEAR);
			ERRCHECK(result);
		}
	}
	result = m_system->setSoftwareChannels(100);
	ERRCHECK(result);
	result = m_system->setHardwareChannels(64);
	result = m_system->init(100, FMOD_INIT_NORMAL, 0);
	if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)
	{
		/*
		Ok, the speaker mode selected isn't supported by this soundcard. Switch it
		back to stereo...
		*/
		result = m_system->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
		ERRCHECK(result);
		/*
		... and re-init.
		*/
		result = m_system->init(100, FMOD_INIT_NORMAL, 0);
	}
}

void Audio::SetupEngineSounds(){

	for(int i = 0; i < NUM_KARTS; i++)
	{
		FMOD::Sound *engineSound;
		FMOD::Channel *engineNoisechannel;
		FMOD::Channel *idelNoiseChannel;
		FMOD::DSP *dsp;

		ERRCHECK(m_system->createSound(ENGINE_SOUND_FILE, FMOD_3D, 0, &engineSound));

		ERRCHECK(m_system->playSound(FMOD_CHANNEL_FREE, engineSound, true, &engineNoisechannel));
		ERRCHECK(m_system->playSound(FMOD_CHANNEL_FREE, m_SoundList[Sounds.LowFreqEngine], true, &idelNoiseChannel));

		ERRCHECK(m_system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp));
		ERRCHECK(engineNoisechannel->addDSP(dsp, 0));
		ERRCHECK(idelNoiseChannel->addDSP(dsp, 0));

		FMOD_VECTOR *pos = new FMOD_VECTOR();
		pos->x = GetState().Karts[i].vPos.x;
		pos->y = GetState().Karts[i].vPos.y;
		pos->z = GetState().Karts[i].vPos.z;

		ERRCHECK(engineNoisechannel->set3DAttributes(pos, 0));
		ERRCHECK(idelNoiseChannel->set3DAttributes(pos, 0));
		ERRCHECK(engineNoisechannel->setMode(FMOD_LOOP_NORMAL));
		ERRCHECK(idelNoiseChannel->setMode(FMOD_LOOP_NORMAL));

		idelNoiseChannel->setVolume(LOW_ENGINE_NOISE_VOLUME);

		enginePitch[i] = 0;

		m_EngineSoundList.push_back(engineSound);
		m_EngineChannelList.push_back(engineNoisechannel);
		m_IdleNoiseChannelList.push_back(idelNoiseChannel);
		m_KartEngineDSPList.push_back(dsp);

		ERRCHECK(engineNoisechannel->setChannelGroup(m_channelGroupEngineSound));
		ERRCHECK(idelNoiseChannel->setChannelGroup(m_channelGroupEngineSound));

		ERRCHECK(engineNoisechannel->setPaused(false));
		ERRCHECK(idelNoiseChannel->setPaused(false));
	}
}

void Audio::Setup3DEnvironment() {
	ERRCHECK(m_system->set3DSettings(DOPPLER_SCALE, DISTANCE_FACTOR, ROLL_OFF_SCALE));
}

void Audio::OutputMemUsage(){
	float stream;
	float update;
	float total;

	m_system->getCPUUsage(0, &stream, 0, &update, &total);

	DEBUGOUT("Audio CPU usage:  Stream: %lf | Update: %lf | Total: %lf\n", stream, update, total);
}

int Audio::LoadMusic(char* file){
	FMOD_RESULT result;
	FMOD::Sound *newMusic;

	result = m_system->createStream(file, FMOD_DEFAULT, 0, &newMusic);
	ERRCHECK(result);

	m_MusicList.push_back(newMusic);

	return m_MusicList.size() - 1;
}

int Audio::LoadSound(char* file){
	FMOD::Sound *newSound;
	FMOD::Channel *newChannel;

	ERRCHECK(m_system->createSound(file, FMOD_3D, 0, &newSound));

	m_SoundList.push_back(newSound);
	m_SoundsChannelList.push_back(newChannel);

	return m_SoundList.size() - 1;
}

void Audio::StartMusic(){
	FMOD::Channel *musicChannel;
	m_system->playSound(FMOD_CHANNEL_FREE, m_MusicList[0], 0, &musicChannel);
	musicChannel->setChannelGroup(m_channelGroupMusic);
	m_channelGroupMusic->setVolume(MUSIC_VOLUME);
}

void Audio::ToggleMusic(){
	playMusic = !playMusic;
	m_channelGroupMusic->setPaused(playMusic);
}

void Audio::UpdateListenerPos(){

	FMOD_VECTOR position;
	FMOD_VECTOR velocity;
	FMOD_VECTOR forward;
	FMOD_VECTOR up;
	float speed = GetState().Karts[0].vSpeed;

	position.x = GetState().Karts[0].vPos.x;
	position.y = GetState().Karts[0].vPos.y;
	position.z = GetState().Karts[0].vPos.z;

	// Get the Kart's forward vector and remove the y component and then normalize to get unit vector length
	btVector3 temp = GetState().Karts[0].forDirection;
	temp.setY(0);
	temp.normalize();

	velocity.x = GetState().Karts[0].forDirection.x() * speed;
	velocity.y = GetState().Karts[0].forDirection.y() * speed;
	velocity.z = GetState().Karts[0].forDirection.z() * speed;

	forward.x = temp.getX();
	forward.y = temp.getY();
	forward.z = temp.getZ();

	up.x = 0;
	up.y = 1;
	up.z = 0;

	ERRCHECK(m_system->set3DListenerAttributes(0, &position, &velocity, &forward, &up));
}

void Audio::UpdateKartsPos(){
	for(int i = 0; i < NUM_KARTS; i++)
	{
		FMOD_VECTOR *pos = new FMOD_VECTOR();
		pos->x = GetState().Karts[i].vPos.x;
		pos->y = GetState().Karts[i].vPos.y;
		pos->z = GetState().Karts[i].vPos.z;
		ERRCHECK(m_EngineChannelList[i]->set3DAttributes(pos, 0));
		ERRCHECK(m_IdleNoiseChannelList[i]->set3DAttributes(pos, 0));
	}
}

void Audio::Update(Real seconds){

	// Check for keyboard events
	if (GetState().key_map['p']){
		ToggleMusic();
	}
	if (GetState().key_map['-']){
		sfxVol -= Clamp(sfxVol - 0.1f);
		ERRCHECK(m_channelGroupEffects->setVolume(sfxVol));
	}

	// Check for input events
	if( m_pMailbox )
	{
		const std::vector<Events::Event*> aryEvents = m_pMailbox->checkMail();
		for( unsigned int i = 0; i < aryEvents.size(); i++ )
		{
			if(aryEvents[i]->type == Events::EventType::Input)
			{
				// Handle all one-off sound effects
				Events::InputEvent *input = (Events::InputEvent *)aryEvents[i];
				if(input->aPressed)  // Weapon fired
				{
					FMOD_VECTOR pos;
					int KartID = input->kart_index;

					pos.x = GetState().Karts[KartID].vPos.x;
					pos.y = GetState().Karts[KartID].vPos.y;
					pos.z = GetState().Karts[KartID].vPos.z;

					bool isPlaying = false;
					m_SoundsChannelList[KartID]->isPlaying(&isPlaying);

					if(!isPlaying)
					{
						ERRCHECK(m_system->playSound(FMOD_CHANNEL_FREE, m_SoundList[Sounds.MachineGun], true, &m_SoundsChannelList[KartID]));
						m_SoundsChannelList[KartID]->set3DAttributes(&pos, 0);
						m_SoundsChannelList[KartID]->setChannelGroup(m_channelGroupEffects);
						m_SoundsChannelList[KartID]->setPaused(false);
					}
				}
				if(input->bPressed)
				{
					// Play a sound effect
					int x = 0;
				}

				Real lerpAmt = seconds * 2.0f;
				Real newPitch = Lerp(enginePitch[input->kart_index], input->rightTrigger * MAX_PITCH, lerpAmt);

				enginePitch[input->kart_index] = newPitch;

				// Update Kart Engine Sounds
				ERRCHECK(m_KartEngineDSPList[input->kart_index]->setParameter(FMOD_DSP_PITCHSHIFT_PITCH, newPitch));
				//m_EngineChannelList[input->kart_index]->setVolume(newPitch / 2);
				//m_IdleNoiseChannelList[input->kart_index]->setVolume(1 - (newPitch / 2));
			}
			else if(aryEvents[i]->type = (Events::EventType::PowerupPickup))
			{
				Events::PowerupPickupEvent *event = (Events::PowerupPickupEvent *)aryEvents[i];
				FMOD_VECTOR pos;
				int KartID = *event->picker_kart_index;

				pos.x = GetState().Karts[0].vPos.x;
				pos.y = GetState().Karts[0].vPos.y;
				pos.z = GetState().Karts[0].vPos.z;

				FMOD::Channel *channel;

				int PowerUp = Sounds.PowerUp;

				ERRCHECK(m_system->playSound(FMOD_CHANNEL_FREE, m_SoundList[PowerUp], true, &channel));
				channel->setChannelGroup(m_channelGroupEffects);
				channel->set3DAttributes(&pos, 0);
				channel->setPaused(false);
			}
		}
		m_pMailbox->emptyMail();
	}

	UpdateKartsPos();
	UpdateListenerPos();
	ERRCHECK(m_system->update());

	//OutputMemUsage();
}

<commit_msg>Added some memory usage output, it's commented out right now though.<commit_after>#include "audio.h"
#include <fmod.h>
#include <fmod_errors.h>

#define ERRCHECK(res)	if (res != FMOD_OK){\
	DEBUGOUT("FMOD error! (%d) %s\n", res, FMOD_ErrorString(res));\
    exit(-1);}

#define PITCHSCALE 0.1
#define MAX_PITCH 2
#define ENGINE_SOUND_FILE "assets/audio/engineNoise3.wav"

#define DOPPLER_SCALE 1.0f
#define DISTANCE_FACTOR 1.0f
#define ROLL_OFF_SCALE 1.0f

#define MUSIC_VOLUME 0.03
#define SOUND_EFFECTS_VOLUME 0.1
#define LOW_ENGINE_NOISE_VOLUME 1

Audio::Audio() {

	m_pMailbox = new Events::Mailbox();
	m_pMailbox->request( Events::EventType::Input );
	m_pMailbox->request( Events::EventType::PowerupPickup );

	SetupHardware();

	//// Setup music and sound effects channels
	ERRCHECK(m_system->createChannelGroup("Effects", &m_channelGroupEffects));
	ERRCHECK(m_system->createChannelGroup("Music", &m_channelGroupMusic));

	musicVol = MUSIC_VOLUME;
	sfxVol = SOUND_EFFECTS_VOLUME;

	m_channelGroupMusic->setVolume(musicVol);
	m_channelGroupEffects->setVolume(sfxVol);

	// Load all the sound files
	LoadMusic("assets/audio/BrainDead.mp3");
	playMusic = true;

	Sounds.PowerUp = LoadSound("assets/audio/powerup2.wav");
	Sounds.LowFreqEngine = LoadSound("assets/audio/engineIdleNoise1.wav");
	Sounds.MachineGun = LoadSound("assets/audio/machineGun1.aiff");

	StartMusic();
	//Setup3DEnvironment();
	SetupEngineSounds();
}

Audio::~Audio() {

	m_system->release();

	if(m_pMailbox)
		delete m_pMailbox;
}

int Audio::SetupHardware(){

	FMOD_RESULT result;
	unsigned int version;
	int numdrivers;
	FMOD_SPEAKERMODE speakermode;
	FMOD_CAPS caps;
	char name[256];
	/*
	Create a System object and initialize.
	*/
	result = FMOD::System_Create(&m_system);
	ERRCHECK(result);
	result = m_system->getVersion(&version);
	ERRCHECK(result);
	if (version < FMOD_VERSION)
	{
		printf("Error! You are using an old version of FMOD %08x.  This program requires %08x\n",
			version, FMOD_VERSION);
		return 0;
	}
	result = m_system->getNumDrivers(&numdrivers);
	ERRCHECK(result);
	if (numdrivers == 0)
	{
		result = m_system->setOutput(FMOD_OUTPUTTYPE_NOSOUND);
		ERRCHECK(result);
	}
	else
	{
		result = m_system->getDriverCaps(0, &caps, 0, &speakermode);
		ERRCHECK(result);
		/*
		Set the user selected speaker mode.
		*/
		result = m_system->setSpeakerMode(speakermode);
		ERRCHECK(result);
		if (caps & FMOD_CAPS_HARDWARE_EMULATED)
		{
			/*
			The user has the 'Acceleration' slider set to off! This is really bad
			for latency! You might want to warn the user about this.
			*/
			result = m_system->setDSPBufferSize(1024, 10);
			ERRCHECK(result);
		}
		result = m_system->getDriverInfo(0, name, 256, 0);
		ERRCHECK(result);
		if (strstr(name, "SigmaTel"))
		{
			/*
			Sigmatel sound devices crackle for some reason if the format is PCM 16bit.
			PCM floating point output seems to solve it.
			*/
			result = m_system->setSoftwareFormat(48000, FMOD_SOUND_FORMAT_PCMFLOAT, 0,0,
				FMOD_DSP_RESAMPLER_LINEAR);
			ERRCHECK(result);
		}
	}
	result = m_system->setSoftwareChannels(100);
	ERRCHECK(result);
	result = m_system->setHardwareChannels(64);
	result = m_system->init(100, FMOD_INIT_NORMAL, 0);
	if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)
	{
		/*
		Ok, the speaker mode selected isn't supported by this soundcard. Switch it
		back to stereo...
		*/
		result = m_system->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
		ERRCHECK(result);
		/*
		... and re-init.
		*/
		result = m_system->init(100, FMOD_INIT_NORMAL, 0);
	}
}

void Audio::SetupEngineSounds(){

	for(int i = 0; i < NUM_KARTS; i++)
	{
		FMOD::Sound *engineSound;
		FMOD::Channel *engineNoisechannel;
		FMOD::Channel *idelNoiseChannel;
		FMOD::DSP *dsp;

		ERRCHECK(m_system->createSound(ENGINE_SOUND_FILE, FMOD_3D, 0, &engineSound));

		ERRCHECK(m_system->playSound(FMOD_CHANNEL_FREE, engineSound, true, &engineNoisechannel));
		ERRCHECK(m_system->playSound(FMOD_CHANNEL_FREE, m_SoundList[Sounds.LowFreqEngine], true, &idelNoiseChannel));

		ERRCHECK(m_system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp));
		ERRCHECK(engineNoisechannel->addDSP(dsp, 0));
		ERRCHECK(idelNoiseChannel->addDSP(dsp, 0));

		FMOD_VECTOR *pos = new FMOD_VECTOR();
		pos->x = GetState().Karts[i].vPos.x;
		pos->y = GetState().Karts[i].vPos.y;
		pos->z = GetState().Karts[i].vPos.z;

		ERRCHECK(engineNoisechannel->set3DAttributes(pos, 0));
		ERRCHECK(idelNoiseChannel->set3DAttributes(pos, 0));
		ERRCHECK(engineNoisechannel->setMode(FMOD_LOOP_NORMAL));
		ERRCHECK(idelNoiseChannel->setMode(FMOD_LOOP_NORMAL));

		idelNoiseChannel->setVolume(LOW_ENGINE_NOISE_VOLUME);

		enginePitch[i] = 0;

		m_EngineSoundList.push_back(engineSound);
		m_EngineChannelList.push_back(engineNoisechannel);
		m_IdleNoiseChannelList.push_back(idelNoiseChannel);
		m_KartEngineDSPList.push_back(dsp);

		ERRCHECK(engineNoisechannel->setChannelGroup(m_channelGroupEngineSound));
		ERRCHECK(idelNoiseChannel->setChannelGroup(m_channelGroupEngineSound));

		ERRCHECK(engineNoisechannel->setPaused(false));
		ERRCHECK(idelNoiseChannel->setPaused(false));
	}
}

void Audio::Setup3DEnvironment() {
	ERRCHECK(m_system->set3DSettings(DOPPLER_SCALE, DISTANCE_FACTOR, ROLL_OFF_SCALE));
}

void Audio::OutputMemUsage(){
	float stream;
	float update;
	float total;
	//uint32_t memUsage;

	m_system->getCPUUsage(0, &stream, 0, &update, &total);
	//m_system->getMemoryInfo(FMOD_MEMBITS_ALL, FMOD_EVENT_MEMBITS_ALL, &memUsage, 0);

	DEBUGOUT("Audio CPU usage:  Stream: %lf | Update: %lf | Total: %lf\n", stream, update, total);
	//DEBUGOUT("Audio MEM usage:  %d\n", memUsage);
}

int Audio::LoadMusic(char* file){
	FMOD_RESULT result;
	FMOD::Sound *newMusic;

	result = m_system->createStream(file, FMOD_DEFAULT, 0, &newMusic);
	ERRCHECK(result);

	m_MusicList.push_back(newMusic);

	return m_MusicList.size() - 1;
}

int Audio::LoadSound(char* file){
	FMOD::Sound *newSound;
	FMOD::Channel *newChannel;

	ERRCHECK(m_system->createSound(file, FMOD_3D, 0, &newSound));

	m_SoundList.push_back(newSound);
	m_SoundsChannelList.push_back(newChannel);

	return m_SoundList.size() - 1;
}

void Audio::StartMusic(){
	FMOD::Channel *musicChannel;
	m_system->playSound(FMOD_CHANNEL_FREE, m_MusicList[0], 0, &musicChannel);
	musicChannel->setChannelGroup(m_channelGroupMusic);
	m_channelGroupMusic->setVolume(MUSIC_VOLUME);
}

void Audio::ToggleMusic(){
	playMusic = !playMusic;
	m_channelGroupMusic->setPaused(playMusic);
}

void Audio::UpdateListenerPos(){

	FMOD_VECTOR position;
	FMOD_VECTOR velocity;
	FMOD_VECTOR forward;
	FMOD_VECTOR up;
	float speed = GetState().Karts[0].vSpeed;

	position.x = GetState().Karts[0].vPos.x;
	position.y = GetState().Karts[0].vPos.y;
	position.z = GetState().Karts[0].vPos.z;

	// Get the Kart's forward vector and remove the y component and then normalize to get unit vector length
	btVector3 temp = GetState().Karts[0].forDirection;
	temp.setY(0);
	temp.normalize();

	velocity.x = GetState().Karts[0].forDirection.x() * speed;
	velocity.y = GetState().Karts[0].forDirection.y() * speed;
	velocity.z = GetState().Karts[0].forDirection.z() * speed;

	forward.x = temp.getX();
	forward.y = temp.getY();
	forward.z = temp.getZ();

	up.x = 0;
	up.y = 1;
	up.z = 0;

	ERRCHECK(m_system->set3DListenerAttributes(0, &position, &velocity, &forward, &up));
}

void Audio::UpdateKartsPos(){
	for(int i = 0; i < NUM_KARTS; i++)
	{
		FMOD_VECTOR *pos = new FMOD_VECTOR();
		pos->x = GetState().Karts[i].vPos.x;
		pos->y = GetState().Karts[i].vPos.y;
		pos->z = GetState().Karts[i].vPos.z;
		ERRCHECK(m_EngineChannelList[i]->set3DAttributes(pos, 0));
		ERRCHECK(m_IdleNoiseChannelList[i]->set3DAttributes(pos, 0));
	}
}

void Audio::Update(Real seconds){

	// Check for keyboard events
	if (GetState().key_map['p']){
		ToggleMusic();
	}
	if (GetState().key_map['-']){
		sfxVol -= Clamp(sfxVol - 0.1f);
		ERRCHECK(m_channelGroupEffects->setVolume(sfxVol));
	}

	// Check for input events
	if( m_pMailbox )
	{
		const std::vector<Events::Event*> aryEvents = m_pMailbox->checkMail();
		for( unsigned int i = 0; i < aryEvents.size(); i++ )
		{
			if(aryEvents[i]->type == Events::EventType::Input)
			{
				// Handle all one-off sound effects
				Events::InputEvent *input = (Events::InputEvent *)aryEvents[i];
				if(input->aPressed)  // Weapon fired
				{
					FMOD_VECTOR pos;
					int KartID = input->kart_index;

					pos.x = GetState().Karts[KartID].vPos.x;
					pos.y = GetState().Karts[KartID].vPos.y;
					pos.z = GetState().Karts[KartID].vPos.z;

					bool isPlaying = false;
					m_SoundsChannelList[KartID]->isPlaying(&isPlaying);

					if(!isPlaying)
					{
						ERRCHECK(m_system->playSound(FMOD_CHANNEL_FREE, m_SoundList[Sounds.MachineGun], true, &m_SoundsChannelList[KartID]));
						m_SoundsChannelList[KartID]->set3DAttributes(&pos, 0);
						m_SoundsChannelList[KartID]->setChannelGroup(m_channelGroupEffects);
						m_SoundsChannelList[KartID]->setPaused(false);
					}
				}
				if(input->bPressed)
				{
					// Play a sound effect
					int x = 0;
				}

				Real lerpAmt = seconds * 2.0f;
				Real newPitch = Lerp(enginePitch[input->kart_index], input->rightTrigger * MAX_PITCH, lerpAmt);

				enginePitch[input->kart_index] = newPitch;

				// Update Kart Engine Sounds
				ERRCHECK(m_KartEngineDSPList[input->kart_index]->setParameter(FMOD_DSP_PITCHSHIFT_PITCH, newPitch));
				//m_EngineChannelList[input->kart_index]->setVolume(newPitch / 2);
				//m_IdleNoiseChannelList[input->kart_index]->setVolume(1 - (newPitch / 2));
			}
			else if(aryEvents[i]->type = (Events::EventType::PowerupPickup))
			{
				Events::PowerupPickupEvent *event = (Events::PowerupPickupEvent *)aryEvents[i];
				FMOD_VECTOR pos;
				int KartID = *event->picker_kart_index;

				pos.x = GetState().Karts[0].vPos.x;
				pos.y = GetState().Karts[0].vPos.y;
				pos.z = GetState().Karts[0].vPos.z;

				FMOD::Channel *channel;

				int PowerUp = Sounds.PowerUp;

				ERRCHECK(m_system->playSound(FMOD_CHANNEL_FREE, m_SoundList[PowerUp], true, &channel));
				channel->setChannelGroup(m_channelGroupEffects);
				channel->set3DAttributes(&pos, 0);
				channel->setPaused(false);
			}
		}
		m_pMailbox->emptyMail();
	}

	UpdateKartsPos();
	UpdateListenerPos();
	ERRCHECK(m_system->update());

	//OutputMemUsage();
}

<|endoftext|>


<commit_before> //
 // This file is part of Easylogging++ samples
 // TIMED_BLOCK sample
 //
 // Revision 1.1
 // @author mkhan3189
 //

#include "easylogging++.h"

_INITIALIZE_EASYLOGGINGPP

int main(int argc, char** argv) {

    _START_EASYLOGGINGPP(argc, argv);

    TIMED_BLOCK(t, "my-block") {
        for (long i = 0; i <= 114300; ++i) {
            LOG(INFO) << "This is for-block 1";
        }
        t.timer.checkpoint("checkpoint-1"); // Note t.timer to access el::base::Trackable
        for (int i = 0; i <= 200; ++i) {
            LOG(INFO) << "This is for-block 2";
        }
    }
    LOG(INFO) << "You should get performance result of above scope";

    return 0;
}
<commit_msg>less output<commit_after> //
 // This file is part of Easylogging++ samples
 // TIMED_BLOCK sample
 //
 // Revision 1.1
 // @author mkhan3189
 //

#include "easylogging++.h"

_INITIALIZE_EASYLOGGINGPP

int main(int argc, char** argv) {

    _START_EASYLOGGINGPP(argc, argv);

    TIMED_BLOCK(t, "my-block") {
        for (long i = 0; i <= 300; ++i) {
            LOG(INFO) << "This is for-block 1";
        }
        t.timer.checkpoint("checkpoint-1"); // Note t.timer to access el::base::Trackable
        for (int i = 0; i <= 200; ++i) {
            LOG(INFO) << "This is for-block 2";
        }
    }
    LOG(INFO) << "You should get performance result of above scope";

    return 0;
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: SteepestDescentMinimizer_test.C,v 1.3 2003/02/04 14:27:03 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#include <BALL/MOLMEC/MINIMIZATION/steepestDescent.h>
#include <BALL/MOLMEC/AMBER/amber.h>
#include <BALL/DATATYPE/options.h>
#include <BALL/KERNEL/PTE.h>
///////////////////////////

START_TEST(ConjugateGradienMinimizer, "$Id: SteepestDescentMinimizer_test.C,v 1.3 2003/02/04 14:27:03 oliver Exp $")

using namespace BALL;

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

System S;
AmberFF FF(S);

SteepestDescentMinimizer*	em;
CHECK(SteepestDescentMinimizer::SteepestDescentMinimizer())
	em = new SteepestDescentMinimizer;
	TEST_NOT_EQUAL(em, 0)
RESULT

CHECK(SteepestDescentMinimizer::~SteepestDescentMinimizer())
	delete em;
RESULT

CHECK(SteepestDescentMinimizer::getForceField())
	SteepestDescentMinimizer em;
	TEST_EQUAL(em.getForceField(), 0)
RESULT

CHECK(SteepestDescentMinimizer::SteepestDescentMinimizer(ForceField&))
	TEST_EQUAL(FF.isValid(), true)
	SteepestDescentMinimizer em(FF);
	TEST_EQUAL(em.getForceField(), &FF)
RESULT

CHECK(SteepestDescentMinimizer::SteepestDescentMinimizer(ForceField&, const Options&))
	Options options;
	options.set("ABC", "DEF");
	em = new SteepestDescentMinimizer(FF, options);
	TEST_EQUAL(em->getForceField(), &FF)
	TEST_EQUAL(em->options["ABC"], "DEF")
	delete em;
RESULT

CHECK(SteepestDescentMinimizer::SteepestDescentMinimizer(const SteepestDescentMinimizer&, bool))
	SteepestDescentMinimizer em1;
	SteepestDescentMinimizer em2(em1);
	bool test = (em1 == em2);
	TEST_EQUAL(test, true)
	em1.setup(FF);
	SteepestDescentMinimizer em3(em1);
	test = (em1 == em3);
	TEST_EQUAL(test, true)
	em1.setup(FF);
RESULT

CHECK(SteepestDescentMinimizer::operator = (const SteepestDescentMinimizer&))
	SteepestDescentMinimizer em1;
	SteepestDescentMinimizer em2 = em1;
	bool test = (em1 == em2);
	TEST_EQUAL(test, true)
	em1.setup(FF);
	SteepestDescentMinimizer em3 = em1;
	test = (em1 == em3);
	TEST_EQUAL(test, true)
RESULT

CHECK(SteepestDescentMinimizer::isValid() const)
	em = new SteepestDescentMinimizer;
	TEST_EQUAL(em->isValid(), false)
	delete em;
	em = new SteepestDescentMinimizer(FF);
	TEST_EQUAL(em->isValid(), true)
	delete em;
RESULT

CHECK(SteepestDescentMinimizer::setup(ForceField&))
	SteepestDescentMinimizer e_min(FF);
	TEST_EQUAL(e_min.getForceUpdateCounter(), 0)
	TEST_EQUAL(e_min.getEnergyUpdateCounter(), 0)
	bool test = (e_min.getForceField() == &FF);
	TEST_EQUAL(test, true)
RESULT

CHECK(SteepestDescentMinimizer::setup(ForceField&, const Options&))
	Options options;
	options.setInteger(EnergyMinimizer::Option::ENERGY_OUTPUT_FREQUENCY, 3456);
	SteepestDescentMinimizer e_min(FF, options);
	TEST_EQUAL(e_min.getForceUpdateCounter(), 0)
	TEST_EQUAL(e_min.getEnergyUpdateCounter(), 0)
	bool test = (e_min.getForceField() == &FF);
	TEST_EQUAL(test, true)
	TEST_EQUAL(e_min.getEnergyOutputFrequency(), 3456)
RESULT

CHECK(SteepestDescentMinimizer::specificSetup())
	SteepestDescentMinimizer em(FF);
	TEST_EQUAL(em.specificSetup(), true)
	// specificSetup() shouldn't do anything except returning true
RESULT

CHECK(SteepestDescentMinimizer::getNumberOfIteration() const)
	SteepestDescentMinimizer e_min;
	TEST_EQUAL(e_min.getNumberOfIterations(), 0)
RESULT

CHECK(SteepestDescentMinimizer::setNumberOfIteration(Size))
	SteepestDescentMinimizer e_min;
	e_min.setNumberOfIterations(4);
	TEST_EQUAL(e_min.getNumberOfIterations(), 4)
RESULT

CHECK(SteepestDescentMinimizer::getMaxNumberOfIterations())
	SteepestDescentMinimizer e_min;
	TEST_EQUAL(e_min.getMaxNumberOfIterations(), 0)
RESULT

CHECK(SteepestDescentMinimizer::setMaxNumberOfIterations(Size))
	SteepestDescentMinimizer e_min;
	e_min.setMaxNumberOfIterations(2000);
	TEST_EQUAL(e_min.getMaxNumberOfIterations(), 2000)
RESULT

CHECK(SteepestDescentMinimizer::getEnergyOutputFrequency() const)
	SteepestDescentMinimizer e_min2;
	TEST_EQUAL(e_min2.getEnergyOutputFrequency(), 0)
RESULT

CHECK(SteepestDescentMinimizer::setEnergyOutputFrequency(Size))
	SteepestDescentMinimizer e_min;
	e_min.setEnergyOutputFrequency(8);
	TEST_EQUAL(e_min.getEnergyOutputFrequency(), 8)
RESULT

CHECK(SteepestDescentMinimizer::getEnergyDifferenceBound() const)
	SteepestDescentMinimizer e_min;
	TEST_EQUAL(e_min.getEnergyDifferenceBound(), 0.0)
RESULT

CHECK(SteepestDescentMinimizer::setEnergyDifferenceBound(float))
	SteepestDescentMinimizer e_min;
	e_min.setEnergyDifferenceBound(9.0);
	TEST_EQUAL(e_min.getEnergyDifferenceBound(), 9.0)
RESULT

CHECK(SteepestDescentMinimizer::getMaximumDisplacement() const)
	SteepestDescentMinimizer e_min;
	TEST_EQUAL(e_min.getMaximumDisplacement(), 0.0)
RESULT

CHECK(SteepestDescentMinimizer::setMaximumDisplacement(float))
	SteepestDescentMinimizer e_min;
	e_min.setMaximumDisplacement(56.0);
	TEST_EQUAL(e_min.getMaximumDisplacement(), 56.0)
RESULT

CHECK(SteepestDescentMinimizer::minimize(Size, bool))
	System S;
	Molecule* m = new Molecule;
	Atom* a1 = new Atom;
	Atom* a2 = new Atom;
	S.insert(*m);
	m->insert(*a1);
	m->insert(*a2);
	a1->setPosition(Vector3(-0.5, 0, 0));
	a2->setPosition(Vector3(0.5, 0, 0));
	a1->setElement(PTE[Element::C]);
	a2->setElement(PTE[Element::C]);
	a1->setTypeName("C");
	a2->setTypeName("C");
	a1->setCharge(0.0);
	a2->setCharge(0.0);
	FF.options[AmberFF::Option::ASSIGN_CHARGES] = "false";
	FF.setup(S);
	TEST_EQUAL(FF.isValid(), true)
	PRECISION(1e-4)
	FF.updateEnergy();
	FF.updateForces();
	PRECISION(10)
	TEST_REAL_EQUAL(FF.getEnergy(), 3.42854e+06)
	SteepestDescentMinimizer cgm(FF);
	cgm.setEnergyOutputFrequency(1);
	cgm.setMaxGradient(0.01);
	TEST_EQUAL(cgm.isValid(), true)
	TEST_EQUAL(cgm.minimize(20), true)

	FF.updateEnergy();
	FF.updateForces();

	PRECISION(1e-3)
  TEST_REAL_EQUAL(FF.getEnergy(), -0.359813)
	PRECISION(7e-3)
  TEST_REAL_EQUAL(a1->getPosition().getDistance(a2->getPosition()), 3.81244)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

END_TEST
<commit_msg>added: test case ethan<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: SteepestDescentMinimizer_test.C,v 1.4 2003/04/12 10:06:06 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#include <BALL/MOLMEC/MINIMIZATION/steepestDescent.h>
#include <BALL/MOLMEC/AMBER/amber.h>
#include <BALL/DATATYPE/options.h>
#include <BALL/KERNEL/PTE.h>
#include <BALL/FORMAT/HINFile.h>
#include <BALL/MATHS/analyticalGeometry.h>

///////////////////////////

START_TEST(ConjugateGradienMinimizer, "$Id: SteepestDescentMinimizer_test.C,v 1.4 2003/04/12 10:06:06 oliver Exp $")

using namespace BALL;

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

System S;
AmberFF FF(S);

SteepestDescentMinimizer*	em;
CHECK(SteepestDescentMinimizer::SteepestDescentMinimizer())
	em = new SteepestDescentMinimizer;
	TEST_NOT_EQUAL(em, 0)
RESULT

CHECK(SteepestDescentMinimizer::~SteepestDescentMinimizer())
	delete em;
RESULT

CHECK(SteepestDescentMinimizer::getForceField())
	SteepestDescentMinimizer em;
	TEST_EQUAL(em.getForceField(), 0)
RESULT

CHECK(SteepestDescentMinimizer::SteepestDescentMinimizer(ForceField&))
	TEST_EQUAL(FF.isValid(), true)
	SteepestDescentMinimizer em(FF);
	TEST_EQUAL(em.getForceField(), &FF)
RESULT

CHECK(SteepestDescentMinimizer::SteepestDescentMinimizer(ForceField&, const Options&))
	Options options;
	options.set("ABC", "DEF");
	em = new SteepestDescentMinimizer(FF, options);
	TEST_EQUAL(em->getForceField(), &FF)
	TEST_EQUAL(em->options["ABC"], "DEF")
	delete em;
RESULT

CHECK(SteepestDescentMinimizer::SteepestDescentMinimizer(const SteepestDescentMinimizer&, bool))
	SteepestDescentMinimizer em1;
	SteepestDescentMinimizer em2(em1);
	bool test = (em1 == em2);
	TEST_EQUAL(test, true)
	em1.setup(FF);
	SteepestDescentMinimizer em3(em1);
	test = (em1 == em3);
	TEST_EQUAL(test, true)
	em1.setup(FF);
RESULT

CHECK(SteepestDescentMinimizer::operator = (const SteepestDescentMinimizer&))
	SteepestDescentMinimizer em1;
	SteepestDescentMinimizer em2 = em1;
	bool test = (em1 == em2);
	TEST_EQUAL(test, true)
	em1.setup(FF);
	SteepestDescentMinimizer em3 = em1;
	test = (em1 == em3);
	TEST_EQUAL(test, true)
RESULT

CHECK(SteepestDescentMinimizer::isValid() const)
	em = new SteepestDescentMinimizer;
	TEST_EQUAL(em->isValid(), false)
	delete em;
	em = new SteepestDescentMinimizer(FF);
	TEST_EQUAL(em->isValid(), true)
	delete em;
RESULT

CHECK(SteepestDescentMinimizer::setup(ForceField&))
	SteepestDescentMinimizer e_min(FF);
	TEST_EQUAL(e_min.getForceUpdateCounter(), 0)
	TEST_EQUAL(e_min.getEnergyUpdateCounter(), 0)
	bool test = (e_min.getForceField() == &FF);
	TEST_EQUAL(test, true)
RESULT

CHECK(SteepestDescentMinimizer::setup(ForceField&, const Options&))
	Options options;
	options.setInteger(EnergyMinimizer::Option::ENERGY_OUTPUT_FREQUENCY, 3456);
	SteepestDescentMinimizer e_min(FF, options);
	TEST_EQUAL(e_min.getForceUpdateCounter(), 0)
	TEST_EQUAL(e_min.getEnergyUpdateCounter(), 0)
	bool test = (e_min.getForceField() == &FF);
	TEST_EQUAL(test, true)
	TEST_EQUAL(e_min.getEnergyOutputFrequency(), 3456)
RESULT

CHECK(SteepestDescentMinimizer::specificSetup())
	SteepestDescentMinimizer em(FF);
	TEST_EQUAL(em.specificSetup(), true)
	// specificSetup() shouldn't do anything except returning true
RESULT

CHECK(SteepestDescentMinimizer::getNumberOfIteration() const)
	SteepestDescentMinimizer e_min;
	TEST_EQUAL(e_min.getNumberOfIterations(), 0)
RESULT

CHECK(SteepestDescentMinimizer::setNumberOfIteration(Size))
	SteepestDescentMinimizer e_min;
	e_min.setNumberOfIterations(4);
	TEST_EQUAL(e_min.getNumberOfIterations(), 4)
RESULT

CHECK(SteepestDescentMinimizer::getMaxNumberOfIterations())
	SteepestDescentMinimizer e_min;
	TEST_EQUAL(e_min.getMaxNumberOfIterations(), 0)
RESULT

CHECK(SteepestDescentMinimizer::setMaxNumberOfIterations(Size))
	SteepestDescentMinimizer e_min;
	e_min.setMaxNumberOfIterations(2000);
	TEST_EQUAL(e_min.getMaxNumberOfIterations(), 2000)
RESULT

CHECK(SteepestDescentMinimizer::getEnergyOutputFrequency() const)
	SteepestDescentMinimizer e_min2;
	TEST_EQUAL(e_min2.getEnergyOutputFrequency(), 0)
RESULT

CHECK(SteepestDescentMinimizer::setEnergyOutputFrequency(Size))
	SteepestDescentMinimizer e_min;
	e_min.setEnergyOutputFrequency(8);
	TEST_EQUAL(e_min.getEnergyOutputFrequency(), 8)
RESULT

CHECK(SteepestDescentMinimizer::getEnergyDifferenceBound() const)
	SteepestDescentMinimizer e_min;
	TEST_EQUAL(e_min.getEnergyDifferenceBound(), 0.0)
RESULT

CHECK(SteepestDescentMinimizer::setEnergyDifferenceBound(float))
	SteepestDescentMinimizer e_min;
	e_min.setEnergyDifferenceBound(9.0);
	TEST_EQUAL(e_min.getEnergyDifferenceBound(), 9.0)
RESULT

CHECK(SteepestDescentMinimizer::getMaximumDisplacement() const)
	SteepestDescentMinimizer e_min;
	TEST_EQUAL(e_min.getMaximumDisplacement(), 0.0)
RESULT

CHECK(SteepestDescentMinimizer::setMaximumDisplacement(float))
	SteepestDescentMinimizer e_min;
	e_min.setMaximumDisplacement(56.0);
	TEST_EQUAL(e_min.getMaximumDisplacement(), 56.0)
RESULT

CHECK(SteepestDescentMinimizer::minimize(Size, bool))
	System S;
	Molecule* m = new Molecule;
	Atom* a1 = new Atom;
	Atom* a2 = new Atom;
	S.insert(*m);
	m->insert(*a1);
	m->insert(*a2);
	a1->setPosition(Vector3(-0.5, 0, 0));
	a2->setPosition(Vector3(0.5, 0, 0));
	a1->setElement(PTE[Element::C]);
	a2->setElement(PTE[Element::C]);
	a1->setTypeName("C");
	a2->setTypeName("C");
	a1->setCharge(0.0);
	a2->setCharge(0.0);
	FF.options[AmberFF::Option::ASSIGN_CHARGES] = "false";
	FF.setup(S);
	TEST_EQUAL(FF.isValid(), true)
	PRECISION(1e-4)
	FF.updateEnergy();
	FF.updateForces();
	PRECISION(10)
	TEST_REAL_EQUAL(FF.getEnergy(), 3.42854e+06)
	SteepestDescentMinimizer cgm(FF);
	cgm.setEnergyOutputFrequency(1);
	cgm.setMaxGradient(0.01);
	TEST_EQUAL(cgm.isValid(), true)
	TEST_EQUAL(cgm.minimize(20), true)

	FF.updateEnergy();
	FF.updateForces();

	PRECISION(1e-3)
  TEST_REAL_EQUAL(FF.getEnergy(), -0.359813)
	PRECISION(7e-3)
  TEST_REAL_EQUAL(a1->getPosition().getDistance(a2->getPosition()), 3.81244)
RESULT

CHECK(SteepestDescentMinimizer::minimize(Size, bool) ethan)
  System S;
  HINFile f("data/ethan.hin");
  f >> S;
  FF.options[AmberFF::Option::ASSIGN_CHARGES] = "false";
  FF.setup(S);

  TEST_EQUAL(FF.isValid(), true)
  FF.updateEnergy();
  FF.updateForces();
  PRECISION(1E-4)
  TEST_REAL_EQUAL(FF.getEnergy(), 18.5605)

  SteepestDescentMinimizer sd(FF);

  sd.setEnergyOutputFrequency(5);
  sd.setMaxGradient(0.418);
	sd.setMaxNumberOfIterations(10000);
  sd.setEnergyDifferenceBound(0.00000001);

  TEST_EQUAL(sd.isValid(), true)
  FF.updateEnergy();
  FF.updateForces();
  bool result = sd.minimize(500);

  TEST_EQUAL(result, true)
  float energy = FF.updateEnergy();
  FF.updateForces();

  PRECISION(6E-2)
  TEST_REAL_EQUAL(energy, 5.906)

  AtomIterator atit;
  Vector3 pos[8];
  int i=0;

  for (atit = S.beginAtom(); +atit; ++atit)
  {
    pos[i] = atit->getPosition();
    ++i;
	}

  PRECISION(5E-2)
  Angle torsion;
  torsion = getTorsionAngle(pos[2].x, pos[2].y, pos[2].z, pos[0].x, pos[0].y, pos[0].z, pos[1].x, pos[1].y, pos[1].z, pos[6].x, pos[6].y, pos[6].z);
  TEST_REAL_EQUAL(torsion.toRadian(), 1.047)
  torsion = getTorsionAngle(pos[3].x, pos[3].y, pos[3].z, pos[0].x, pos[0].y, pos[0].z, pos[1].x, pos[1].y, pos[1].z, pos[5].x, pos[5].y, pos[5].z);
  TEST_REAL_EQUAL(torsion.toRadian(), 1.047)
  torsion = getTorsionAngle(pos[4].x, pos[4].y, pos[4].z, pos[0].x, pos[0].y, pos[0].z, pos[1].x, pos[1].y, pos[1].z, pos[7].x, pos[7].y, pos[7].z);
  TEST_REAL_EQUAL(torsion.toRadian(), 1.047)

  PRECISION(1E-2)
  Angle tet;
  tet = (pos[2] - pos[0]).getAngle(pos[3] - pos[0]);
  TEST_REAL_EQUAL(tet.toRadian(), 1.902)
  tet = (pos[2] - pos[0]).getAngle(pos[4] - pos[0]);
  TEST_REAL_EQUAL(tet.toRadian(), 1.902)
  tet = (pos[4] - pos[0]).getAngle(pos[3] - pos[0]);
  TEST_REAL_EQUAL(tet.toRadian(), 1.902)
  tet = (pos[5] - pos[1]).getAngle(pos[6] - pos[1]);
  TEST_REAL_EQUAL(tet.toRadian(), 1.902)
  tet = (pos[5] - pos[1]).getAngle(pos[7] - pos[1]);
  TEST_REAL_EQUAL(tet.toRadian(), 1.902)
  tet = (pos[7] - pos[1]).getAngle(pos[6] - pos[1]);
  TEST_REAL_EQUAL(tet.toRadian(), 1.902)

RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

END_TEST
<|endoftext|>