<commit_before>#include "utAllocore.h"

SearchPaths searchpaths;
SearchPaths& getSearchPaths() { return searchpaths; }

bool almostEqual(float v1, float v2) {
	return abs(v1 -v2) < 0.00001;
}

int main (int argc, char * const argv[]) {
	searchpaths.addAppPaths(argc, argv);
	searchpaths.addSearchPath(searchpaths.appPath() + "../share");

	// Logical tests; leave uncommented
	// These tests are purely logical, they should not print anything out to
	// the console (as it interferes with assertion error messages) or start any
	// processes that require user intervention to proceed or validate the test.

	// This macro runs the unit test and prints out status info
	// 'Name' should match the name of the unit test, utName.
	#define RUNTEST(Name)\
		printf("%s ", #Name);\
		ut##Name();\
		for(size_t i=0; i<32-strlen(#Name); ++i) printf(".");\
		printf(" pass\n")

	RUNTEST(Math);
	RUNTEST(MathSpherical);
	RUNTEST(Types);
	RUNTEST(TypesConversion);
	RUNTEST(Spatial);
	RUNTEST(System);
	RUNTEST(ProtocolOSC);
	RUNTEST(ProtocolSerialize);

	RUNTEST(IOSocket);
	RUNTEST(File);
	RUNTEST(Thread);

	RUNTEST(GraphicsMesh);

#ifndef ALLOCORE_TESTS_NO_AUDIO
	RUNTEST(IOAudioIO);
	RUNTEST(AudioScene);
#endif

	RUNTEST(Ambisonics);

#ifndef ALLOCORE_TESTS_NO_GUI
	// This test should always be run last since it calls exit()
	// This test will not run on headless machines.
	printf("IOWindow .... (calls exit() internally)\n");
	utIOWindowGL();
#endif

	// Empirical tests; leave commented
	// These are tests that require some kind of observation to validate.

//	utAsset();
//	utGraphicsDraw();

	return 0;
}

<commit_msg>Putting back Ambisonics unit testing for travis. (may break travis build...)<commit_after>#include "utAllocore.h"

SearchPaths searchpaths;
SearchPaths& getSearchPaths() { return searchpaths; }

bool almostEqual(float v1, float v2) {
	return abs(v1 -v2) < 0.00001;
}

int main (int argc, char * const argv[]) {
	searchpaths.addAppPaths(argc, argv);
	searchpaths.addSearchPath(searchpaths.appPath() + "../share");

	// Logical tests; leave uncommented
	// These tests are purely logical, they should not print anything out to
	// the console (as it interferes with assertion error messages) or start any
	// processes that require user intervention to proceed or validate the test.

	// This macro runs the unit test and prints out status info
	// 'Name' should match the name of the unit test, utName.
	#define RUNTEST(Name)\
		printf("%s ", #Name);\
		ut##Name();\
		for(size_t i=0; i<32-strlen(#Name); ++i) printf(".");\
		printf(" pass\n")

	RUNTEST(Math);
	RUNTEST(MathSpherical);
	RUNTEST(Types);
	RUNTEST(TypesConversion);
	RUNTEST(Spatial);
	RUNTEST(System);
	RUNTEST(ProtocolOSC);
	RUNTEST(ProtocolSerialize);

	RUNTEST(IOSocket);
	RUNTEST(File);
	RUNTEST(Thread);

	RUNTEST(GraphicsMesh);

#ifndef ALLOCORE_TESTS_NO_AUDIO
	RUNTEST(IOAudioIO);
#endif

	RUNTEST(AudioScene);
	RUNTEST(Ambisonics);

#ifndef ALLOCORE_TESTS_NO_GUI
	// This test should always be run last since it calls exit()
	// This test will not run on headless machines.
	printf("IOWindow .... (calls exit() internally)\n");
	utIOWindowGL();
#endif

	// Empirical tests; leave commented
	// These are tests that require some kind of observation to validate.

//	utAsset();
//	utGraphicsDraw();

	return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "itkParameterFileParser.h"
#include "elxDefaultConstruct.h"

#include <itksys/SystemTools.hxx>
#include <itksys/RegularExpression.hxx>

#include <fstream>

namespace itk
{

namespace
{
// Uniform way to throw exceptions when the parameter file appears to be invalid.
void
ThrowException(const std::string & line, const std::string & hint)
{
  itkGenericExceptionMacro("ERROR: the following line in your parameter file is invalid: \n\""
                           << line + "\"\n"
                           << hint << "\nPlease correct you parameter file!");

} // end ThrowException()

} // namespace

/**
 * **************** Constructor ***************
 */

ParameterFileParser::ParameterFileParser() = default;

/**
 * **************** Destructor ***************
 */

ParameterFileParser ::~ParameterFileParser() = default;

/**
 * **************** GetParameterMap ***************
 */

const ParameterFileParser::ParameterMapType &
ParameterFileParser::GetParameterMap() const
{
  return this->m_ParameterMap;

} // end GetParameterMap()

/**
 * **************** ReadParameterFile ***************
 */

void
ParameterFileParser::ReadParameterFile()
{
  /** Perform some basic checks. */
  this->BasicFileChecking();

  /** Open the parameter file for reading. */
  std::ifstream parameterFile(this->m_ParameterFileName);

  /** Check if it opened. */
  if (!parameterFile.is_open())
  {
    itkExceptionMacro(<< "ERROR: could not open " << this->m_ParameterFileName << " for reading.");
  }

  /** Clear the map. */
  this->m_ParameterMap.clear();

  /** Loop over the parameter file, line by line. */
  std::string lineIn;
  std::string lineOut;
  while (parameterFile.good())
  {
    /** Extract a line. */
    itksys::SystemTools::GetLineFromStream(parameterFile, lineIn);

    /** Check this line. */
    const bool validLine = this->CheckLine(lineIn, lineOut);

    if (validLine)
    {
      /** Get the parameter name from this line and store it. */
      this->GetParameterFromLine(lineIn, lineOut);
    }
    // Otherwise, we simply ignore this line
  }

} // end ReadParameterFile()

/**
 * **************** BasicFileChecking ***************
 */

void
ParameterFileParser::BasicFileChecking() const
{
  /** Check if the file name is given. */
  if (this->m_ParameterFileName.empty())
  {
    itkExceptionMacro(<< "ERROR: FileName has not been set.");
  }

  /** Basic error checking: existence. */
  const bool exists = itksys::SystemTools::FileExists(this->m_ParameterFileName);
  if (!exists)
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " does not exist.");
  }

  /** Basic error checking: file or directory. */
  const bool isDir = itksys::SystemTools::FileIsDirectory(this->m_ParameterFileName);
  if (isDir)
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " is a directory.");
  }

  /** Check the extension. */
  const std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->m_ParameterFileName);
  if (ext != ".txt")
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " should be a text file (*.txt).");
  }

} // end BasicFileChecking()

/**
 * **************** CheckLine ***************
 */

bool
ParameterFileParser::CheckLine(const std::string & lineIn, std::string & lineOut) const
{
  /** Preprocessing of lineIn:
   * 1) Replace tabs with spaces
   * 2) Remove everything after comment sign //
   * 3) Remove leading spaces
   * 4) Remove trailing spaces
   */
  lineOut = lineIn;
  itksys::SystemTools::ReplaceString(lineOut, "\t", " ");

  itksys::RegularExpression commentPart("//");
  if (commentPart.find(lineOut))
  {
    lineOut = lineOut.substr(0, commentPart.start());
  }

  itksys::RegularExpression leadingSpaces("^[ ]*(.*)");
  leadingSpaces.find(lineOut);
  lineOut = leadingSpaces.match(1);

  itksys::RegularExpression trailingSpaces("[ \t]+$");
  if (trailingSpaces.find(lineOut))
  {
    lineOut = lineOut.substr(0, trailingSpaces.start());
  }

  /**
   * Checks:
   * 1. Empty line -> false
   * 2. Comment (line starts with "//") -> false
   * 3. Line is not between brackets (...) -> exception
   * 4. Line contains less than two words -> exception
   *
   * Otherwise return true.
   */

  /** 1. Check for non-empty lines. */
  itksys::RegularExpression reNonEmptyLine("[^ ]+");
  const bool                match1 = reNonEmptyLine.find(lineOut);
  if (!match1)
  {
    return false;
  }

  /** 2. Check for comments. */
  itksys::RegularExpression reComment("^//");
  const bool                match2 = reComment.find(lineOut);
  if (match2)
  {
    return false;
  }

  /** 3. Check if line is between brackets. */
  if (!itksys::SystemTools::StringStartsWith(lineOut, "(") || !itksys::SystemTools::StringEndsWith(lineOut, ")"))
  {
    const std::string hint = "Line is not between brackets: \"(...)\".";
    ThrowException(lineIn, hint);
  }

  /** Remove brackets. */
  lineOut = lineOut.substr(1, lineOut.size() - 2);

  /** 4. Check: the line should contain at least two words. */
  itksys::RegularExpression reTwoWords("([ ]+)([^ ]+)");
  const bool                match4 = reTwoWords.find(lineOut);
  if (!match4)
  {
    const std::string hint = "Line does not contain a parameter name and value.";
    ThrowException(lineIn, hint);
  }

  /** At this point we know its at least a line containing a parameter.
   * However, this line can still be invalid, for example:
   * (string &^%^*)
   * This will be checked later.
   */

  return true;

} // end CheckLine()

/**
 * **************** GetParameterFromLine ***************
 */

void
ParameterFileParser::GetParameterFromLine(const std::string & fullLine, const std::string & line)
{
  /** A line has a parameter name followed by one or more parameters.
   * They are all separated by one or more spaces (all tabs have been
   * removed previously) or by quotes in case of strings. So,
   * 1) we split the line at the spaces or quotes
   * 2) the first one is the parameter name
   * 3) the other strings that are not a series of spaces, are parameter values
   */

  /** 1) Split the line. */
  std::vector<std::string> splittedLine;
  this->SplitLine(fullLine, line, splittedLine);

  /** 2) Get the parameter name. */
  std::string parameterName = splittedLine[0];
  itksys::SystemTools::ReplaceString(parameterName, " ", "");
  splittedLine.erase(splittedLine.begin());

  /** 3) Get the parameter values. */
  std::vector<std::string> parameterValues;
  for (const auto & value : splittedLine)
  {
    if (!value.empty())
    {
      parameterValues.push_back(value);
    }
  }

  /** 4) Perform some checks on the parameter name. */
  itksys::RegularExpression reInvalidCharacters1("[.,:;!@#$%^&-+|<>?]");
  const bool                match = reInvalidCharacters1.find(parameterName);
  if (match)
  {
    const std::string hint = "The parameter \"" + parameterName + "\" contains invalid characters (.,:;!@#$%^&-+|<>?).";
    ThrowException(fullLine, hint);
  }

  /** 5) Insert this combination in the parameter map. */
  if (this->m_ParameterMap.count(parameterName))
  {
    const std::string hint = "The parameter \"" + parameterName + "\" is specified more than once.";
    ThrowException(fullLine, hint);
  }
  else
  {
    this->m_ParameterMap.insert(make_pair(parameterName, parameterValues));
  }

} // end GetParameterFromLine()

/**
 * **************** SplitLine ***************
 */

void
ParameterFileParser::SplitLine(const std::string &        fullLine,
                               const std::string &        line,
                               std::vector<std::string> & splittedLine) const
{
  splittedLine.clear();
  splittedLine.resize(1);

  /** Count the number of quotes in the line. If it is an odd value, the
   * line contains an error; strings should start and end with a quote, so
   * the total number of quotes is even.
   */
  std::size_t numQuotes = itksys::SystemTools::CountChar(line.c_str(), '"');
  if (numQuotes % 2 == 1)
  {
    /** An invalid parameter line. */
    const std::string hint = "This line has an odd number of quotes (\").";
    ThrowException(fullLine, hint);
  }

  /** Loop over the line. */
  unsigned int index = 0;
  numQuotes = 0;
  for (const char currentChar : line)
  {
    if (currentChar == '"')
    {
      /** Start a new element. */
      splittedLine.push_back("");
      ++index;
      ++numQuotes;
    }
    else if (currentChar == ' ')
    {
      /** Only start a new element if it is not a quote, otherwise just add
       * the space to the string.
       */
      if (numQuotes % 2 == 0)
      {
        splittedLine.push_back("");
        ++index;
      }
      else
      {
        splittedLine[index].push_back(currentChar);
      }
    }
    else
    {
      /** Add this character to the element. */
      splittedLine[index].push_back(currentChar);
    }
  }

} // end SplitLine()

/**
 * **************** ReturnParameterFileAsString ***************
 */

std::string
ParameterFileParser::ReturnParameterFileAsString()
{
  /** Perform some basic checks. */
  this->BasicFileChecking();

  /** Open the parameter file for reading. */
  std::ifstream parameterFile(this->m_ParameterFileName);

  /** Check if it opened. */
  if (!parameterFile.is_open())
  {
    itkExceptionMacro(<< "ERROR: could not open " << this->m_ParameterFileName << " for reading.");
  }

  /** Loop over the parameter file, line by line. */
  std::string line;
  std::string output;
  while (parameterFile.good())
  {
    /** Extract a line. */
    itksys::SystemTools::GetLineFromStream(parameterFile, line); // \todo: returns bool

    output += line + "\n";
  }

  /** Return the string. */
  return output;

} // end ReturnParameterFileAsString()

/**
 * **************** ReadParameterMap ***************
 */

auto
ParameterFileParser::ReadParameterMap(const std::string & fileName) -> ParameterMapType
{
  elastix::DefaultConstruct<ParameterFileParser> parameterFileParser;
  parameterFileParser.m_ParameterFileName = fileName;
  parameterFileParser.ReadParameterFile();

  // Use fast move semantics, because `parameterFileParser` is destructed afterwards anyway.
  return std::move(parameterFileParser.m_ParameterMap);
}

} // end namespace itk
<commit_msg>STYLE: Remove `hint` variables, pass strings directly to ThrowException<commit_after>/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "itkParameterFileParser.h"
#include "elxDefaultConstruct.h"

#include <itksys/SystemTools.hxx>
#include <itksys/RegularExpression.hxx>

#include <fstream>

namespace itk
{

namespace
{
// Uniform way to throw exceptions when the parameter file appears to be invalid.
void
ThrowException(const std::string & line, const std::string & hint)
{
  itkGenericExceptionMacro("ERROR: the following line in your parameter file is invalid: \n\""
                           << line + "\"\n"
                           << hint << "\nPlease correct you parameter file!");

} // end ThrowException()

} // namespace

/**
 * **************** Constructor ***************
 */

ParameterFileParser::ParameterFileParser() = default;

/**
 * **************** Destructor ***************
 */

ParameterFileParser ::~ParameterFileParser() = default;

/**
 * **************** GetParameterMap ***************
 */

const ParameterFileParser::ParameterMapType &
ParameterFileParser::GetParameterMap() const
{
  return this->m_ParameterMap;

} // end GetParameterMap()

/**
 * **************** ReadParameterFile ***************
 */

void
ParameterFileParser::ReadParameterFile()
{
  /** Perform some basic checks. */
  this->BasicFileChecking();

  /** Open the parameter file for reading. */
  std::ifstream parameterFile(this->m_ParameterFileName);

  /** Check if it opened. */
  if (!parameterFile.is_open())
  {
    itkExceptionMacro(<< "ERROR: could not open " << this->m_ParameterFileName << " for reading.");
  }

  /** Clear the map. */
  this->m_ParameterMap.clear();

  /** Loop over the parameter file, line by line. */
  std::string lineIn;
  std::string lineOut;
  while (parameterFile.good())
  {
    /** Extract a line. */
    itksys::SystemTools::GetLineFromStream(parameterFile, lineIn);

    /** Check this line. */
    const bool validLine = this->CheckLine(lineIn, lineOut);

    if (validLine)
    {
      /** Get the parameter name from this line and store it. */
      this->GetParameterFromLine(lineIn, lineOut);
    }
    // Otherwise, we simply ignore this line
  }

} // end ReadParameterFile()

/**
 * **************** BasicFileChecking ***************
 */

void
ParameterFileParser::BasicFileChecking() const
{
  /** Check if the file name is given. */
  if (this->m_ParameterFileName.empty())
  {
    itkExceptionMacro(<< "ERROR: FileName has not been set.");
  }

  /** Basic error checking: existence. */
  const bool exists = itksys::SystemTools::FileExists(this->m_ParameterFileName);
  if (!exists)
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " does not exist.");
  }

  /** Basic error checking: file or directory. */
  const bool isDir = itksys::SystemTools::FileIsDirectory(this->m_ParameterFileName);
  if (isDir)
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " is a directory.");
  }

  /** Check the extension. */
  const std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->m_ParameterFileName);
  if (ext != ".txt")
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " should be a text file (*.txt).");
  }

} // end BasicFileChecking()

/**
 * **************** CheckLine ***************
 */

bool
ParameterFileParser::CheckLine(const std::string & lineIn, std::string & lineOut) const
{
  /** Preprocessing of lineIn:
   * 1) Replace tabs with spaces
   * 2) Remove everything after comment sign //
   * 3) Remove leading spaces
   * 4) Remove trailing spaces
   */
  lineOut = lineIn;
  itksys::SystemTools::ReplaceString(lineOut, "\t", " ");

  itksys::RegularExpression commentPart("//");
  if (commentPart.find(lineOut))
  {
    lineOut = lineOut.substr(0, commentPart.start());
  }

  itksys::RegularExpression leadingSpaces("^[ ]*(.*)");
  leadingSpaces.find(lineOut);
  lineOut = leadingSpaces.match(1);

  itksys::RegularExpression trailingSpaces("[ \t]+$");
  if (trailingSpaces.find(lineOut))
  {
    lineOut = lineOut.substr(0, trailingSpaces.start());
  }

  /**
   * Checks:
   * 1. Empty line -> false
   * 2. Comment (line starts with "//") -> false
   * 3. Line is not between brackets (...) -> exception
   * 4. Line contains less than two words -> exception
   *
   * Otherwise return true.
   */

  /** 1. Check for non-empty lines. */
  itksys::RegularExpression reNonEmptyLine("[^ ]+");
  const bool                match1 = reNonEmptyLine.find(lineOut);
  if (!match1)
  {
    return false;
  }

  /** 2. Check for comments. */
  itksys::RegularExpression reComment("^//");
  const bool                match2 = reComment.find(lineOut);
  if (match2)
  {
    return false;
  }

  /** 3. Check if line is between brackets. */
  if (!itksys::SystemTools::StringStartsWith(lineOut, "(") || !itksys::SystemTools::StringEndsWith(lineOut, ")"))
  {
    ThrowException(lineIn, "Line is not between brackets: \"(...)\".");
  }

  /** Remove brackets. */
  lineOut = lineOut.substr(1, lineOut.size() - 2);

  /** 4. Check: the line should contain at least two words. */
  itksys::RegularExpression reTwoWords("([ ]+)([^ ]+)");
  const bool                match4 = reTwoWords.find(lineOut);
  if (!match4)
  {
    ThrowException(lineIn, "Line does not contain a parameter name and value.");
  }

  /** At this point we know its at least a line containing a parameter.
   * However, this line can still be invalid, for example:
   * (string &^%^*)
   * This will be checked later.
   */

  return true;

} // end CheckLine()

/**
 * **************** GetParameterFromLine ***************
 */

void
ParameterFileParser::GetParameterFromLine(const std::string & fullLine, const std::string & line)
{
  /** A line has a parameter name followed by one or more parameters.
   * They are all separated by one or more spaces (all tabs have been
   * removed previously) or by quotes in case of strings. So,
   * 1) we split the line at the spaces or quotes
   * 2) the first one is the parameter name
   * 3) the other strings that are not a series of spaces, are parameter values
   */

  /** 1) Split the line. */
  std::vector<std::string> splittedLine;
  this->SplitLine(fullLine, line, splittedLine);

  /** 2) Get the parameter name. */
  std::string parameterName = splittedLine[0];
  itksys::SystemTools::ReplaceString(parameterName, " ", "");
  splittedLine.erase(splittedLine.begin());

  /** 3) Get the parameter values. */
  std::vector<std::string> parameterValues;
  for (const auto & value : splittedLine)
  {
    if (!value.empty())
    {
      parameterValues.push_back(value);
    }
  }

  /** 4) Perform some checks on the parameter name. */
  itksys::RegularExpression reInvalidCharacters1("[.,:;!@#$%^&-+|<>?]");
  const bool                match = reInvalidCharacters1.find(parameterName);
  if (match)
  {
    ThrowException(fullLine,
                   "The parameter \"" + parameterName + "\" contains invalid characters (.,:;!@#$%^&-+|<>?).");
  }

  /** 5) Insert this combination in the parameter map. */
  if (this->m_ParameterMap.count(parameterName))
  {
    ThrowException(fullLine, "The parameter \"" + parameterName + "\" is specified more than once.");
  }
  else
  {
    this->m_ParameterMap.insert(make_pair(parameterName, parameterValues));
  }

} // end GetParameterFromLine()

/**
 * **************** SplitLine ***************
 */

void
ParameterFileParser::SplitLine(const std::string &        fullLine,
                               const std::string &        line,
                               std::vector<std::string> & splittedLine) const
{
  splittedLine.clear();
  splittedLine.resize(1);

  /** Count the number of quotes in the line. If it is an odd value, the
   * line contains an error; strings should start and end with a quote, so
   * the total number of quotes is even.
   */
  std::size_t numQuotes = itksys::SystemTools::CountChar(line.c_str(), '"');
  if (numQuotes % 2 == 1)
  {
    /** An invalid parameter line. */
    ThrowException(fullLine, "This line has an odd number of quotes (\").");
  }

  /** Loop over the line. */
  unsigned int index = 0;
  numQuotes = 0;
  for (const char currentChar : line)
  {
    if (currentChar == '"')
    {
      /** Start a new element. */
      splittedLine.push_back("");
      ++index;
      ++numQuotes;
    }
    else if (currentChar == ' ')
    {
      /** Only start a new element if it is not a quote, otherwise just add
       * the space to the string.
       */
      if (numQuotes % 2 == 0)
      {
        splittedLine.push_back("");
        ++index;
      }
      else
      {
        splittedLine[index].push_back(currentChar);
      }
    }
    else
    {
      /** Add this character to the element. */
      splittedLine[index].push_back(currentChar);
    }
  }

} // end SplitLine()

/**
 * **************** ReturnParameterFileAsString ***************
 */

std::string
ParameterFileParser::ReturnParameterFileAsString()
{
  /** Perform some basic checks. */
  this->BasicFileChecking();

  /** Open the parameter file for reading. */
  std::ifstream parameterFile(this->m_ParameterFileName);

  /** Check if it opened. */
  if (!parameterFile.is_open())
  {
    itkExceptionMacro(<< "ERROR: could not open " << this->m_ParameterFileName << " for reading.");
  }

  /** Loop over the parameter file, line by line. */
  std::string line;
  std::string output;
  while (parameterFile.good())
  {
    /** Extract a line. */
    itksys::SystemTools::GetLineFromStream(parameterFile, line); // \todo: returns bool

    output += line + "\n";
  }

  /** Return the string. */
  return output;

} // end ReturnParameterFileAsString()

/**
 * **************** ReadParameterMap ***************
 */

auto
ParameterFileParser::ReadParameterMap(const std::string & fileName) -> ParameterMapType
{
  elastix::DefaultConstruct<ParameterFileParser> parameterFileParser;
  parameterFileParser.m_ParameterFileName = fileName;
  parameterFileParser.ReadParameterFile();

  // Use fast move semantics, because `parameterFileParser` is destructed afterwards anyway.
  return std::move(parameterFileParser.m_ParameterMap);
}

} // end namespace itk
<|endoftext|>


<commit_before>/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "ParticlesSlide.h"

#include "ImGuiLayer.h"
#include "SkParticleAffector.h"
#include "SkParticleDrawable.h"
#include "SkParticleEffect.h"
#include "SkParticleSerialization.h"
#include "SkReflected.h"

#include "imgui.h"

using namespace sk_app;

namespace {

static SkScalar kDragSize = 8.0f;
static SkTArray<SkPoint*> gDragPoints;
int gDragIndex = -1;

}

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

static int InputTextCallback(ImGuiInputTextCallbackData* data) {
    if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
        SkString* s = (SkString*)data->UserData;
        SkASSERT(data->Buf == s->writable_str());
        SkString tmp(data->Buf, data->BufTextLen);
        s->swap(tmp);
        data->Buf = s->writable_str();
    }
    return 0;
}

class SkGuiVisitor : public SkFieldVisitor {
public:
    SkGuiVisitor() {
        fTreeStack.push_back(true);
    }

#define IF_OPEN(WIDGET) if (fTreeStack.back()) { WIDGET; }

    void visit(const char* name, float& f) override {
        IF_OPEN(ImGui::DragFloat(item(name), &f))
    }
    void visit(const char* name, int& i) override {
        IF_OPEN(ImGui::DragInt(item(name), &i))
    }
    void visit(const char* name, bool& b) override {
        IF_OPEN(ImGui::Checkbox(item(name), &b))
    }
    void visit(const char* name, SkString& s) override {
        if (fTreeStack.back()) {
            ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackResize;
            ImGui::InputText(item(name), s.writable_str(), s.size() + 1, flags, InputTextCallback,
                             &s);
        }
    }
    void visit(const char* name, int& i, const EnumStringMapping* map, int count) override {
        if (fTreeStack.back()) {
            const char* curStr = EnumToString(i, map, count);
            if (ImGui::BeginCombo(item(name), curStr ? curStr : "Unknown")) {
                for (int j = 0; j < count; ++j) {
                    if (ImGui::Selectable(map[j].fName, i == map[j].fValue)) {
                        i = map[j].fValue;
                    }
                }
                ImGui::EndCombo();
            }
        }
    }

    void visit(const char* name, SkPoint& p) override {
        if (fTreeStack.back()) {
            ImGui::DragFloat2(item(name), &p.fX);
            gDragPoints.push_back(&p);
        }
    }
    void visit(const char* name, SkColor4f& c) override {
        IF_OPEN(ImGui::ColorEdit4(item(name), c.vec()))
    }

#undef IF_OPEN

    void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
        if (fTreeStack.back()) {
            const SkReflected::Type* curType = e ? e->getType() : nullptr;
            if (ImGui::BeginCombo("Type", curType ? curType->fName : "Null")) {
                auto visitType = [curType,&e](const SkReflected::Type* t) {
                    if (ImGui::Selectable(t->fName, curType == t)) {
                        e = t->fFactory();
                    }
                };
                SkReflected::VisitTypes(visitType, baseType);
                ImGui::EndCombo();
            }
        }
    }

    void enterObject(const char* name) override {
        if (fTreeStack.back()) {
            fTreeStack.push_back(ImGui::TreeNodeEx(item(name),
                                                   ImGuiTreeNodeFlags_AllowItemOverlap));
        } else {
            fTreeStack.push_back(false);
        }
    }
    void exitObject() override {
        if (fTreeStack.back()) {
            ImGui::TreePop();
        }
        fTreeStack.pop_back();
    }

    int enterArray(const char* name, int oldCount) override {
        this->enterObject(item(name));
        fArrayCounterStack.push_back(0);
        fArrayEditStack.push_back();

        int count = oldCount;
        if (fTreeStack.back()) {
            ImGui::SameLine();
            if (ImGui::Button("+")) {
                ++count;
            }
        }
        return count;
    }
    ArrayEdit exitArray() override {
        fArrayCounterStack.pop_back();
        auto edit = fArrayEditStack.back();
        fArrayEditStack.pop_back();
        this->exitObject();
        return edit;
    }

private:
    const char* item(const char* name) {
        if (name) {
            return name;
        }

        // We're in an array. Add extra controls and a dynamic label.
        int index = fArrayCounterStack.back()++;
        ArrayEdit& edit(fArrayEditStack.back());
        fScratchLabel = SkStringPrintf("[%d]", index);

        ImGui::PushID(index);

        if (ImGui::Button("X")) {
            edit.fVerb = ArrayEdit::Verb::kRemove;
            edit.fIndex = index;
        }
        ImGui::SameLine();
        if (ImGui::Button("^")) {
            edit.fVerb = ArrayEdit::Verb::kMoveForward;
            edit.fIndex = index;
        }
        ImGui::SameLine();
        if (ImGui::Button("v")) {
            edit.fVerb = ArrayEdit::Verb::kMoveForward;
            edit.fIndex = index + 1;
        }
        ImGui::SameLine();

        ImGui::PopID();

        return fScratchLabel.c_str();
    }

    SkSTArray<16, bool, true> fTreeStack;
    SkSTArray<16, int, true>  fArrayCounterStack;
    SkSTArray<16, ArrayEdit, true> fArrayEditStack;
    SkString fScratchLabel;
};

static sk_sp<SkParticleEffectParams> LoadEffectParams(const char* filename) {
    sk_sp<SkParticleEffectParams> params(new SkParticleEffectParams());
    if (auto fileData = SkData::MakeFromFileName(filename)) {
        skjson::DOM dom(static_cast<const char*>(fileData->data()), fileData->size());
        SkFromJsonVisitor fromJson(dom.root());
        params->visitFields(&fromJson);
    }
    return params;
}

ParticlesSlide::ParticlesSlide() {
    // Register types for serialization
    REGISTER_REFLECTED(SkReflected);
    SkParticleAffector::RegisterAffectorTypes();
    SkParticleDrawable::RegisterDrawableTypes();
    fName = "Particles";
}

void ParticlesSlide::load(SkScalar winWidth, SkScalar winHeight) {
    fEffect.reset(new SkParticleEffect(LoadEffectParams("resources/particles/default.json"),
                                       fRandom));
}

void ParticlesSlide::draw(SkCanvas* canvas) {
    canvas->clear(0);

    gDragPoints.reset();
    if (ImGui::Begin("Particles", nullptr, ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
        static bool looped = true;
        ImGui::Checkbox("Looped", &looped);
        if (fTimer && ImGui::Button("Play")) {
            fEffect->start(*fTimer, looped);
        }
        static char filename[64] = "resources/particles/default.json";
        ImGui::InputText("Filename", filename, sizeof(filename));
        if (ImGui::Button("Load")) {
            if (auto newParams = LoadEffectParams(filename)) {
                fEffect.reset(new SkParticleEffect(std::move(newParams), fRandom));
            }
        }
        ImGui::SameLine();

        if (ImGui::Button("Save")) {
            SkFILEWStream fileStream(filename);
            if (fileStream.isValid()) {
                SkJSONWriter writer(&fileStream, SkJSONWriter::Mode::kPretty);
                SkToJsonVisitor toJson(writer);
                writer.beginObject();
                fEffect->getParams()->visitFields(&toJson);
                writer.endObject();
                writer.flush();
                fileStream.flush();
            } else {
                SkDebugf("Failed to open file\n");
            }
        }

        SkGuiVisitor gui;
        fEffect->getParams()->visitFields(&gui);
    }
    ImGui::End();

    SkPaint dragPaint;
    dragPaint.setColor(SK_ColorLTGRAY);
    dragPaint.setAntiAlias(true);
    SkPaint dragHighlight;
    dragHighlight.setStyle(SkPaint::kStroke_Style);
    dragHighlight.setColor(SK_ColorGREEN);
    dragHighlight.setStrokeWidth(2);
    dragHighlight.setAntiAlias(true);
    for (int i = 0; i < gDragPoints.count(); ++i) {
        canvas->drawCircle(*gDragPoints[i], kDragSize, dragPaint);
        if (gDragIndex == i) {
            canvas->drawCircle(*gDragPoints[i], kDragSize, dragHighlight);
        }
    }
    fEffect->draw(canvas);
}

bool ParticlesSlide::animate(const SkAnimTimer& timer) {
    fTimer = &timer;
    fEffect->update(timer);
    return true;
}

bool ParticlesSlide::onMouse(SkScalar x, SkScalar y, Window::InputState state, uint32_t modifiers) {
    if (gDragIndex == -1) {
        if (state == Window::kDown_InputState) {
            float bestDistance = kDragSize;
            SkPoint mousePt = { x, y };
            for (int i = 0; i < gDragPoints.count(); ++i) {
                float distance = SkPoint::Distance(*gDragPoints[i], mousePt);
                if (distance < bestDistance) {
                    gDragIndex = i;
                    bestDistance = distance;
                }
            }
            return gDragIndex != -1;
        }
    } else {
        // Currently dragging
        SkASSERT(gDragIndex < gDragPoints.count());
        gDragPoints[gDragIndex]->set(x, y);
        if (state == Window::kUp_InputState) {
            gDragIndex = -1;
        }
        return true;
    }
    return false;
}
<commit_msg>change particleslide to use Resources<commit_after>/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "ParticlesSlide.h"

#include "ImGuiLayer.h"
#include "Resources.h"
#include "SkParticleAffector.h"
#include "SkParticleDrawable.h"
#include "SkParticleEffect.h"
#include "SkParticleSerialization.h"
#include "SkReflected.h"

#include "imgui.h"

using namespace sk_app;

namespace {

static SkScalar kDragSize = 8.0f;
static SkTArray<SkPoint*> gDragPoints;
int gDragIndex = -1;

}

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

static int InputTextCallback(ImGuiInputTextCallbackData* data) {
    if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
        SkString* s = (SkString*)data->UserData;
        SkASSERT(data->Buf == s->writable_str());
        SkString tmp(data->Buf, data->BufTextLen);
        s->swap(tmp);
        data->Buf = s->writable_str();
    }
    return 0;
}

class SkGuiVisitor : public SkFieldVisitor {
public:
    SkGuiVisitor() {
        fTreeStack.push_back(true);
    }

#define IF_OPEN(WIDGET) if (fTreeStack.back()) { WIDGET; }

    void visit(const char* name, float& f) override {
        IF_OPEN(ImGui::DragFloat(item(name), &f))
    }
    void visit(const char* name, int& i) override {
        IF_OPEN(ImGui::DragInt(item(name), &i))
    }
    void visit(const char* name, bool& b) override {
        IF_OPEN(ImGui::Checkbox(item(name), &b))
    }
    void visit(const char* name, SkString& s) override {
        if (fTreeStack.back()) {
            ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackResize;
            ImGui::InputText(item(name), s.writable_str(), s.size() + 1, flags, InputTextCallback,
                             &s);
        }
    }
    void visit(const char* name, int& i, const EnumStringMapping* map, int count) override {
        if (fTreeStack.back()) {
            const char* curStr = EnumToString(i, map, count);
            if (ImGui::BeginCombo(item(name), curStr ? curStr : "Unknown")) {
                for (int j = 0; j < count; ++j) {
                    if (ImGui::Selectable(map[j].fName, i == map[j].fValue)) {
                        i = map[j].fValue;
                    }
                }
                ImGui::EndCombo();
            }
        }
    }

    void visit(const char* name, SkPoint& p) override {
        if (fTreeStack.back()) {
            ImGui::DragFloat2(item(name), &p.fX);
            gDragPoints.push_back(&p);
        }
    }
    void visit(const char* name, SkColor4f& c) override {
        IF_OPEN(ImGui::ColorEdit4(item(name), c.vec()))
    }

#undef IF_OPEN

    void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
        if (fTreeStack.back()) {
            const SkReflected::Type* curType = e ? e->getType() : nullptr;
            if (ImGui::BeginCombo("Type", curType ? curType->fName : "Null")) {
                auto visitType = [curType,&e](const SkReflected::Type* t) {
                    if (ImGui::Selectable(t->fName, curType == t)) {
                        e = t->fFactory();
                    }
                };
                SkReflected::VisitTypes(visitType, baseType);
                ImGui::EndCombo();
            }
        }
    }

    void enterObject(const char* name) override {
        if (fTreeStack.back()) {
            fTreeStack.push_back(ImGui::TreeNodeEx(item(name),
                                                   ImGuiTreeNodeFlags_AllowItemOverlap));
        } else {
            fTreeStack.push_back(false);
        }
    }
    void exitObject() override {
        if (fTreeStack.back()) {
            ImGui::TreePop();
        }
        fTreeStack.pop_back();
    }

    int enterArray(const char* name, int oldCount) override {
        this->enterObject(item(name));
        fArrayCounterStack.push_back(0);
        fArrayEditStack.push_back();

        int count = oldCount;
        if (fTreeStack.back()) {
            ImGui::SameLine();
            if (ImGui::Button("+")) {
                ++count;
            }
        }
        return count;
    }
    ArrayEdit exitArray() override {
        fArrayCounterStack.pop_back();
        auto edit = fArrayEditStack.back();
        fArrayEditStack.pop_back();
        this->exitObject();
        return edit;
    }

private:
    const char* item(const char* name) {
        if (name) {
            return name;
        }

        // We're in an array. Add extra controls and a dynamic label.
        int index = fArrayCounterStack.back()++;
        ArrayEdit& edit(fArrayEditStack.back());
        fScratchLabel = SkStringPrintf("[%d]", index);

        ImGui::PushID(index);

        if (ImGui::Button("X")) {
            edit.fVerb = ArrayEdit::Verb::kRemove;
            edit.fIndex = index;
        }
        ImGui::SameLine();
        if (ImGui::Button("^")) {
            edit.fVerb = ArrayEdit::Verb::kMoveForward;
            edit.fIndex = index;
        }
        ImGui::SameLine();
        if (ImGui::Button("v")) {
            edit.fVerb = ArrayEdit::Verb::kMoveForward;
            edit.fIndex = index + 1;
        }
        ImGui::SameLine();

        ImGui::PopID();

        return fScratchLabel.c_str();
    }

    SkSTArray<16, bool, true> fTreeStack;
    SkSTArray<16, int, true>  fArrayCounterStack;
    SkSTArray<16, ArrayEdit, true> fArrayEditStack;
    SkString fScratchLabel;
};

static sk_sp<SkParticleEffectParams> LoadEffectParams(const char* filename) {
    sk_sp<SkParticleEffectParams> params(new SkParticleEffectParams());
    if (auto fileData = GetResourceAsData(filename)) {
        skjson::DOM dom(static_cast<const char*>(fileData->data()), fileData->size());
        SkFromJsonVisitor fromJson(dom.root());
        params->visitFields(&fromJson);
    }
    return params;
}

ParticlesSlide::ParticlesSlide() {
    // Register types for serialization
    REGISTER_REFLECTED(SkReflected);
    SkParticleAffector::RegisterAffectorTypes();
    SkParticleDrawable::RegisterDrawableTypes();
    fName = "Particles";
}

void ParticlesSlide::load(SkScalar winWidth, SkScalar winHeight) {
    fEffect.reset(new SkParticleEffect(LoadEffectParams("particles/default.json"),
                                       fRandom));
}

void ParticlesSlide::draw(SkCanvas* canvas) {
    canvas->clear(0);

    gDragPoints.reset();
    if (ImGui::Begin("Particles", nullptr, ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
        static bool looped = true;
        ImGui::Checkbox("Looped", &looped);
        if (fTimer && ImGui::Button("Play")) {
            fEffect->start(*fTimer, looped);
        }
        static char filename[64] = "resources/particles/default.json";
        ImGui::InputText("Filename", filename, sizeof(filename));
        if (ImGui::Button("Load")) {
            if (auto newParams = LoadEffectParams(filename)) {
                fEffect.reset(new SkParticleEffect(std::move(newParams), fRandom));
            }
        }
        ImGui::SameLine();

        if (ImGui::Button("Save")) {
            SkFILEWStream fileStream(filename);
            if (fileStream.isValid()) {
                SkJSONWriter writer(&fileStream, SkJSONWriter::Mode::kPretty);
                SkToJsonVisitor toJson(writer);
                writer.beginObject();
                fEffect->getParams()->visitFields(&toJson);
                writer.endObject();
                writer.flush();
                fileStream.flush();
            } else {
                SkDebugf("Failed to open file\n");
            }
        }

        SkGuiVisitor gui;
        fEffect->getParams()->visitFields(&gui);
    }
    ImGui::End();

    SkPaint dragPaint;
    dragPaint.setColor(SK_ColorLTGRAY);
    dragPaint.setAntiAlias(true);
    SkPaint dragHighlight;
    dragHighlight.setStyle(SkPaint::kStroke_Style);
    dragHighlight.setColor(SK_ColorGREEN);
    dragHighlight.setStrokeWidth(2);
    dragHighlight.setAntiAlias(true);
    for (int i = 0; i < gDragPoints.count(); ++i) {
        canvas->drawCircle(*gDragPoints[i], kDragSize, dragPaint);
        if (gDragIndex == i) {
            canvas->drawCircle(*gDragPoints[i], kDragSize, dragHighlight);
        }
    }
    fEffect->draw(canvas);
}

bool ParticlesSlide::animate(const SkAnimTimer& timer) {
    fTimer = &timer;
    fEffect->update(timer);
    return true;
}

bool ParticlesSlide::onMouse(SkScalar x, SkScalar y, Window::InputState state, uint32_t modifiers) {
    if (gDragIndex == -1) {
        if (state == Window::kDown_InputState) {
            float bestDistance = kDragSize;
            SkPoint mousePt = { x, y };
            for (int i = 0; i < gDragPoints.count(); ++i) {
                float distance = SkPoint::Distance(*gDragPoints[i], mousePt);
                if (distance < bestDistance) {
                    gDragIndex = i;
                    bestDistance = distance;
                }
            }
            return gDragIndex != -1;
        }
    } else {
        // Currently dragging
        SkASSERT(gDragIndex < gDragPoints.count());
        gDragPoints[gDragIndex]->set(x, y);
        if (state == Window::kUp_InputState) {
            gDragIndex = -1;
        }
        return true;
    }
    return false;
}
<|endoftext|>


<commit_before>/****************************************************************************
*
* NAME: smbPitchShift.cpp
* VERSION: 1.2
* HOME URL: http://blogs.zynaptiq.com/bernsee
* KNOWN BUGS: none
*
* SYNOPSIS: Routine for doing pitch shifting while maintaining
* duration using the Short Time Fourier Transform.
*
* DESCRIPTION: The routine takes a pitchShift factor value which is between 0.5
* (one octave down) and 2. (one octave up). A value of exactly 1 does not change
* the pitch. numSampsToProcess tells the routine how many samples in indata[0...
* numSampsToProcess-1] should be pitch shifted and moved to outdata[0 ...
* numSampsToProcess-1]. The two buffers can be identical (ie. it can process the
* data in-place). fftFrameSize defines the FFT frame size used for the
* processing. Typical values are 1024, 2048 and 4096. It MUST be a power of 2.
* oversamp is the STFT oversampling factor which also determines the overlap
* between adjacent STFT frames. It should at least be 4 for moderate scaling
* ratios. A value of 32 is recommended for best quality. sampleRate takes the
* sample rate for the signal in unit Hz, ie. 44100 for 44.1 kHz audio. The data
* passed to the routine in indata[] should be in the range [-1.0, 1.0), which is
* also the output range for the data, make sure you scale the data accordingly
* (for 16bit signed integers you would have to divide (and multiply) by 32768).
*
* COPYRIGHT 1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
*
* 						The Wide Open License (WOL)
*
* Permission to use, copy, modify, distribute and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice and this license appear in all source copies.
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
* ANY KIND. See http://www.dspguru.com/wol.htm for more information.
*
*****************************************************************************/

#ifndef SMBPITCHSHIFT_HPP
#define SMBPITCHSHIFT_HPP

#include <algorithm>
#include <cmath>
#include <cstdint>

namespace smb
{
    namespace
    {
        constexpr float pi = 3.14159265358979323846F;

        // Use own implementation because std::complex has a poor performance
        template <class T>
        struct Complex final
        {
            constexpr Complex<T> operator+(const Complex& other) const noexcept
            {
                return Complex{real + other.real, imag + other.imag};
            }

            constexpr Complex<T>& operator+=(const Complex& other)
            {
                real += other.real;
                imag += other.imag;
                return *this;
            }

            constexpr Complex<T> operator-(const Complex& other) const noexcept
            {
                return Complex{real - other.real, imag - other.imag};
            }

            constexpr Complex<T> operator-() const noexcept
            {
                return Complex{-real, -imag};
            }

            constexpr Complex<T>& operator-=(const Complex& other) noexcept
            {
                real -= other.real;
                imag -= other.imag;
                return *this;
            }

            constexpr Complex<T> operator*(const Complex& other) const noexcept
            {
                return Complex{real * other.real - imag * other.imag, real * other.imag + imag * other.real};
            }

            constexpr Complex<T>& operator*=(const Complex& other) noexcept
            {
                float tempReal = real;
                real = real * other.real - imag * other.imag;
                imag = tempReal * other.imag + imag * other.real;
                return *this;
            }

            T magnitude() const noexcept
            {
                return sqrt(real * real + imag * imag);
            }

            T real;
            T imag;
        };

        template <int32_t sign, uint32_t fftFrameSize>
        void fft(Complex<float> fftBuffer[fftFrameSize]) noexcept
        {
            // Bit-reversal permutation applied to a sequence of fftFrameSize items
            for (uint32_t i = 1; i < fftFrameSize - 1; ++i)
            {
                uint32_t j = 0;

                for (uint32_t bitm = 1; bitm < fftFrameSize; bitm <<= 1)
                {
                    if (i & bitm) ++j;
                    j <<= 1;
                }
                j >>= 1;

                if (i < j)
                    std::swap(fftBuffer[i], fftBuffer[j]);
            }

            // Iterative form of Danielson-Lanczos lemma
            uint32_t step = 2;
            for (uint32_t i = 1; i < fftFrameSize; i <<= 1, step <<= 1)
            {
                const uint32_t step2 = step >> 1;
                const float arg = pi / step2;

                const Complex<float> w{std::cos(arg), std::sin(arg) * sign};
                Complex<float> u{1.0F, 0.0F};
                for (uint32_t j = 0; j < step2; ++j)
                {
                    for (uint32_t k = j; k < fftFrameSize; k += step)
                    {
                        const Complex<float> temp = fftBuffer[k + step2] * u;
                        fftBuffer[k + step2] = fftBuffer[k] - temp;
                        fftBuffer[k] += temp;
                    }

                    u *= w;
                }
            }
        }
    }

    template <uint32_t fftFrameSize, uint32_t oversamp>
    class PitchShift final
    {
    public:
        PitchShift() noexcept
        {
            // Hann window
            for (uint32_t k = 0; k < fftFrameSize; ++k)
                window[k] = 0.5F * (1.0F + std::cos(2.0F * pi * static_cast<float>(k) / static_cast<float>(fftFrameSize)));
        }

        /*
            Routine process(). See top of file for explanation
            Purpose: doing pitch shifting while maintaining duration using the Short
            Time Fourier Transform.
            Author: (c)1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
        */
        void process(const float pitchShift, const uint32_t numSampsToProcess,
                     const uint32_t sampleRate, const float* indata, float* outdata) noexcept
        {
            // set up some handy variables
            constexpr auto fftFrameSizeHalf = fftFrameSize / 2;
            constexpr auto stepSize = fftFrameSize / oversamp;
            constexpr auto inFifoLatency = fftFrameSize - stepSize;
            const auto freqPerBin = static_cast<float>(sampleRate) / static_cast<float>(fftFrameSize);
            constexpr float expected = 2.0F * pi * static_cast<float>(stepSize) / static_cast<float>(fftFrameSize);
            if (rover == 0) rover = inFifoLatency;

            // main processing loop
            for (uint32_t i = 0; i < numSampsToProcess; ++i)
            {
                // As long as we have not yet collected enough data just read in
                inFifo[rover] = indata[i];
                outdata[i] = outFifo[rover - inFifoLatency];
                ++rover;

                // now we have enough data for processing
                if (rover >= fftFrameSize)
                {
                    rover = inFifoLatency;

                    // do windowing
                    for (uint32_t k = 0; k < fftFrameSize; ++k)
                        fftWorksp[k] = {inFifo[k] * window[k], 0.0F};

                    // ***************** ANALYSIS *******************
                    // do transform
                    fft<-1, fftFrameSize>(fftWorksp);

                    // this is the analysis step
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; ++k)
                    {
                        const Complex<float>& current = fftWorksp[k];

                        // compute magnitude and phase
                        const float magn = 2.0F * current.magnitude();
                        const float signx = (current.imag > 0.0F) ? 1.0F : -1.0F;
                        const float phase = (current.imag == 0.0F) ? 0.0F :
                            (current.real == 0.0F) ? signx * pi / 2.0F :
                            std::atan2(current.imag, current.real);

                        // compute phase difference
                        float tmp = phase - lastPhase[k];
                        lastPhase[k] = phase;

                        // subtract expected phase difference
                        tmp -= static_cast<float>(k) * expected;

                        // map delta phase into +/- Pi interval
                        int32_t qpd = static_cast<int32_t>(tmp / pi);
                        if (qpd >= 0) qpd += qpd & 1;
                        else qpd -= qpd & 1;
                        tmp -= pi * static_cast<float>(qpd);

                        // get deviation from bin frequency from the +/- Pi interval
                        tmp = oversamp * tmp / (2.0F * pi);

                        // compute the k-th partials' true frequency
                        tmp = static_cast<float>(k) * freqPerBin + tmp * freqPerBin;

                        // store magnitude and true frequency in analysis arrays
                        anaMagn[k] = magn;
                        anaFreq[k] = tmp;
                    }

                    // ***************** PROCESSING *******************
                    // this does the actual pitch shifting
                    std::fill(std::begin(synMagn), std::end(synMagn), 0.0F);
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; ++k)
                    {
                        const uint32_t index = static_cast<uint32_t>(k * pitchShift);
                        if (index > fftFrameSizeHalf) break;
                        synMagn[index] += anaMagn[k];
                        synFreq[index] = anaFreq[k] * pitchShift;
                    }

                    // ***************** SYNTHESIS *******************
                    // this is the synthesis step
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; ++k)
                    {
                        // get magnitude and true frequency from synthesis arrays
                        const float magn = synMagn[k];
                        float tmp = synFreq[k];

                        // subtract bin mid frequency
                        tmp -= static_cast<float>(k) * freqPerBin;

                        // get bin deviation from freq deviation
                        tmp /= freqPerBin;

                        // take oversampling factor into account
                        tmp = 2.0F * pi * tmp / oversamp;

                        // add the overlap phase advance back in
                        tmp += static_cast<float>(k) * expected;

                        // accumulate delta phase to get bin phase
                        sumPhase[k] += tmp;
                        const float phase = sumPhase[k];

                        // get real and imag part and re-interleave
                        fftWorksp[k] = {magn * std::cos(phase), magn * std::sin(phase)};
                    }

                    // zero negative frequencies
                    //for (uint32_t k = fftFrameSizeHalf + 1; k < fftFrameSize; ++k)
                    //    fftWorksp[k] = {0.0F, 0.0F};

                    // do inverse transform
                    fft<1, fftFrameSize>(fftWorksp);

                    // do windowing and add to output accumulator
                    for (uint32_t k = 0; k < fftFrameSize; ++k)
                        outputAccum[k] += 2.0F * window[k] * fftWorksp[k].real / (fftFrameSizeHalf * oversamp);

                    uint32_t k;
                    for (k = 0; k < stepSize; ++k)
                        outFifo[k] = outputAccum[k];
                    // shift accumulator
                    uint32_t j;
                    for (j = 0; k < fftFrameSize; ++k, ++j)
                        outputAccum[j] = outputAccum[k];
                    for (; j < fftFrameSize; ++j)
                        outputAccum[j] = 0.0;

                    // move input FIFO
                    for (k = 0; k < inFifoLatency; ++k)
                        inFifo[k] = inFifo[k + stepSize];
                }
            }
        }

    private:
        float window[fftFrameSize]; // the windowing function
        float inFifo[fftFrameSize]{0.0F};
        float outFifo[fftFrameSize]{0.0F};
        Complex<float> fftWorksp[fftFrameSize]{{0.0F, 0.0F}};
        float lastPhase[fftFrameSize / 2 + 1]{0.0F};
        float sumPhase[fftFrameSize / 2 + 1]{0.0F};
        float outputAccum[2 * fftFrameSize]{0.0F};
        float anaFreq[fftFrameSize / 2 + 1]{0.0F};
        float anaMagn[fftFrameSize / 2 + 1]{0.0F};
        float synFreq[fftFrameSize / 2 + 1]{0.0F};
        float synMagn[fftFrameSize / 2 + 1]{0.0F};
        uint32_t rover = 0;
    };
}

#endif
<commit_msg>Make += operator noexcept<commit_after>/****************************************************************************
*
* NAME: smbPitchShift.cpp
* VERSION: 1.2
* HOME URL: http://blogs.zynaptiq.com/bernsee
* KNOWN BUGS: none
*
* SYNOPSIS: Routine for doing pitch shifting while maintaining
* duration using the Short Time Fourier Transform.
*
* DESCRIPTION: The routine takes a pitchShift factor value which is between 0.5
* (one octave down) and 2. (one octave up). A value of exactly 1 does not change
* the pitch. numSampsToProcess tells the routine how many samples in indata[0...
* numSampsToProcess-1] should be pitch shifted and moved to outdata[0 ...
* numSampsToProcess-1]. The two buffers can be identical (ie. it can process the
* data in-place). fftFrameSize defines the FFT frame size used for the
* processing. Typical values are 1024, 2048 and 4096. It MUST be a power of 2.
* oversamp is the STFT oversampling factor which also determines the overlap
* between adjacent STFT frames. It should at least be 4 for moderate scaling
* ratios. A value of 32 is recommended for best quality. sampleRate takes the
* sample rate for the signal in unit Hz, ie. 44100 for 44.1 kHz audio. The data
* passed to the routine in indata[] should be in the range [-1.0, 1.0), which is
* also the output range for the data, make sure you scale the data accordingly
* (for 16bit signed integers you would have to divide (and multiply) by 32768).
*
* COPYRIGHT 1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
*
* 						The Wide Open License (WOL)
*
* Permission to use, copy, modify, distribute and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice and this license appear in all source copies.
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
* ANY KIND. See http://www.dspguru.com/wol.htm for more information.
*
*****************************************************************************/

#ifndef SMBPITCHSHIFT_HPP
#define SMBPITCHSHIFT_HPP

#include <algorithm>
#include <cmath>
#include <cstdint>

namespace smb
{
    namespace
    {
        constexpr float pi = 3.14159265358979323846F;

        // Use own implementation because std::complex has a poor performance
        template <class T>
        struct Complex final
        {
            constexpr Complex<T> operator+(const Complex& other) const noexcept
            {
                return Complex{real + other.real, imag + other.imag};
            }

            constexpr Complex<T>& operator+=(const Complex& other) noexcept
            {
                real += other.real;
                imag += other.imag;
                return *this;
            }

            constexpr Complex<T> operator-(const Complex& other) const noexcept
            {
                return Complex{real - other.real, imag - other.imag};
            }

            constexpr Complex<T> operator-() const noexcept
            {
                return Complex{-real, -imag};
            }

            constexpr Complex<T>& operator-=(const Complex& other) noexcept
            {
                real -= other.real;
                imag -= other.imag;
                return *this;
            }

            constexpr Complex<T> operator*(const Complex& other) const noexcept
            {
                return Complex{real * other.real - imag * other.imag, real * other.imag + imag * other.real};
            }

            constexpr Complex<T>& operator*=(const Complex& other) noexcept
            {
                float tempReal = real;
                real = real * other.real - imag * other.imag;
                imag = tempReal * other.imag + imag * other.real;
                return *this;
            }

            T magnitude() const noexcept
            {
                return sqrt(real * real + imag * imag);
            }

            T real;
            T imag;
        };

        template <int32_t sign, uint32_t fftFrameSize>
        void fft(Complex<float> fftBuffer[fftFrameSize]) noexcept
        {
            // Bit-reversal permutation applied to a sequence of fftFrameSize items
            for (uint32_t i = 1; i < fftFrameSize - 1; ++i)
            {
                uint32_t j = 0;

                for (uint32_t bitm = 1; bitm < fftFrameSize; bitm <<= 1)
                {
                    if (i & bitm) ++j;
                    j <<= 1;
                }
                j >>= 1;

                if (i < j)
                    std::swap(fftBuffer[i], fftBuffer[j]);
            }

            // Iterative form of Danielson-Lanczos lemma
            uint32_t step = 2;
            for (uint32_t i = 1; i < fftFrameSize; i <<= 1, step <<= 1)
            {
                const uint32_t step2 = step >> 1;
                const float arg = pi / step2;

                const Complex<float> w{std::cos(arg), std::sin(arg) * sign};
                Complex<float> u{1.0F, 0.0F};
                for (uint32_t j = 0; j < step2; ++j)
                {
                    for (uint32_t k = j; k < fftFrameSize; k += step)
                    {
                        const Complex<float> temp = fftBuffer[k + step2] * u;
                        fftBuffer[k + step2] = fftBuffer[k] - temp;
                        fftBuffer[k] += temp;
                    }

                    u *= w;
                }
            }
        }
    }

    template <uint32_t fftFrameSize, uint32_t oversamp>
    class PitchShift final
    {
    public:
        PitchShift() noexcept
        {
            // Hann window
            for (uint32_t k = 0; k < fftFrameSize; ++k)
                window[k] = 0.5F * (1.0F + std::cos(2.0F * pi * static_cast<float>(k) / static_cast<float>(fftFrameSize)));
        }

        /*
            Routine process(). See top of file for explanation
            Purpose: doing pitch shifting while maintaining duration using the Short
            Time Fourier Transform.
            Author: (c)1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
        */
        void process(const float pitchShift, const uint32_t numSampsToProcess,
                     const uint32_t sampleRate, const float* indata, float* outdata) noexcept
        {
            // set up some handy variables
            constexpr auto fftFrameSizeHalf = fftFrameSize / 2;
            constexpr auto stepSize = fftFrameSize / oversamp;
            constexpr auto inFifoLatency = fftFrameSize - stepSize;
            const auto freqPerBin = static_cast<float>(sampleRate) / static_cast<float>(fftFrameSize);
            constexpr float expected = 2.0F * pi * static_cast<float>(stepSize) / static_cast<float>(fftFrameSize);
            if (rover == 0) rover = inFifoLatency;

            // main processing loop
            for (uint32_t i = 0; i < numSampsToProcess; ++i)
            {
                // As long as we have not yet collected enough data just read in
                inFifo[rover] = indata[i];
                outdata[i] = outFifo[rover - inFifoLatency];
                ++rover;

                // now we have enough data for processing
                if (rover >= fftFrameSize)
                {
                    rover = inFifoLatency;

                    // do windowing
                    for (uint32_t k = 0; k < fftFrameSize; ++k)
                        fftWorksp[k] = {inFifo[k] * window[k], 0.0F};

                    // ***************** ANALYSIS *******************
                    // do transform
                    fft<-1, fftFrameSize>(fftWorksp);

                    // this is the analysis step
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; ++k)
                    {
                        const Complex<float>& current = fftWorksp[k];

                        // compute magnitude and phase
                        const float magn = 2.0F * current.magnitude();
                        const float signx = (current.imag > 0.0F) ? 1.0F : -1.0F;
                        const float phase = (current.imag == 0.0F) ? 0.0F :
                            (current.real == 0.0F) ? signx * pi / 2.0F :
                            std::atan2(current.imag, current.real);

                        // compute phase difference
                        float tmp = phase - lastPhase[k];
                        lastPhase[k] = phase;

                        // subtract expected phase difference
                        tmp -= static_cast<float>(k) * expected;

                        // map delta phase into +/- Pi interval
                        int32_t qpd = static_cast<int32_t>(tmp / pi);
                        if (qpd >= 0) qpd += qpd & 1;
                        else qpd -= qpd & 1;
                        tmp -= pi * static_cast<float>(qpd);

                        // get deviation from bin frequency from the +/- Pi interval
                        tmp = oversamp * tmp / (2.0F * pi);

                        // compute the k-th partials' true frequency
                        tmp = static_cast<float>(k) * freqPerBin + tmp * freqPerBin;

                        // store magnitude and true frequency in analysis arrays
                        anaMagn[k] = magn;
                        anaFreq[k] = tmp;
                    }

                    // ***************** PROCESSING *******************
                    // this does the actual pitch shifting
                    std::fill(std::begin(synMagn), std::end(synMagn), 0.0F);
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; ++k)
                    {
                        const uint32_t index = static_cast<uint32_t>(k * pitchShift);
                        if (index > fftFrameSizeHalf) break;
                        synMagn[index] += anaMagn[k];
                        synFreq[index] = anaFreq[k] * pitchShift;
                    }

                    // ***************** SYNTHESIS *******************
                    // this is the synthesis step
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; ++k)
                    {
                        // get magnitude and true frequency from synthesis arrays
                        const float magn = synMagn[k];
                        float tmp = synFreq[k];

                        // subtract bin mid frequency
                        tmp -= static_cast<float>(k) * freqPerBin;

                        // get bin deviation from freq deviation
                        tmp /= freqPerBin;

                        // take oversampling factor into account
                        tmp = 2.0F * pi * tmp / oversamp;

                        // add the overlap phase advance back in
                        tmp += static_cast<float>(k) * expected;

                        // accumulate delta phase to get bin phase
                        sumPhase[k] += tmp;
                        const float phase = sumPhase[k];

                        // get real and imag part and re-interleave
                        fftWorksp[k] = {magn * std::cos(phase), magn * std::sin(phase)};
                    }

                    // zero negative frequencies
                    //for (uint32_t k = fftFrameSizeHalf + 1; k < fftFrameSize; ++k)
                    //    fftWorksp[k] = {0.0F, 0.0F};

                    // do inverse transform
                    fft<1, fftFrameSize>(fftWorksp);

                    // do windowing and add to output accumulator
                    for (uint32_t k = 0; k < fftFrameSize; ++k)
                        outputAccum[k] += 2.0F * window[k] * fftWorksp[k].real / (fftFrameSizeHalf * oversamp);

                    uint32_t k;
                    for (k = 0; k < stepSize; ++k)
                        outFifo[k] = outputAccum[k];
                    // shift accumulator
                    uint32_t j;
                    for (j = 0; k < fftFrameSize; ++k, ++j)
                        outputAccum[j] = outputAccum[k];
                    for (; j < fftFrameSize; ++j)
                        outputAccum[j] = 0.0;

                    // move input FIFO
                    for (k = 0; k < inFifoLatency; ++k)
                        inFifo[k] = inFifo[k + stepSize];
                }
            }
        }

    private:
        float window[fftFrameSize]; // the windowing function
        float inFifo[fftFrameSize]{0.0F};
        float outFifo[fftFrameSize]{0.0F};
        Complex<float> fftWorksp[fftFrameSize]{{0.0F, 0.0F}};
        float lastPhase[fftFrameSize / 2 + 1]{0.0F};
        float sumPhase[fftFrameSize / 2 + 1]{0.0F};
        float outputAccum[2 * fftFrameSize]{0.0F};
        float anaFreq[fftFrameSize / 2 + 1]{0.0F};
        float anaMagn[fftFrameSize / 2 + 1]{0.0F};
        float synFreq[fftFrameSize / 2 + 1]{0.0F};
        float synMagn[fftFrameSize / 2 + 1]{0.0F};
        uint32_t rover = 0;
    };
}

#endif
<|endoftext|>


<commit_before>/*
Copyright 2016 Fixstars Corporation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http ://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <stdlib.h>
#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/version.hpp>
#if CV_MAJOR_VERSION == 2
#include <opencv2/contrib/contrib.hpp>
#endif

#include <libsgm.h>

cv::Mat color_normalized(const cv::Mat& src)
{
	cv::Mat tmp(src.size(), CV_8UC1);
	double min, max;
	cv::minMaxIdx(src, &min, &max);
	double alpha = 255 / max;
	src.convertTo(tmp, CV_8UC1, alpha, -min * alpha);
	cv::Mat dst;
	cv::applyColorMap(tmp, dst, cv::COLORMAP_JET);
	return dst;
}

int main(int argc, char* argv[]) {
	if (argc < 3) {
		std::cerr << "usage: stereosgm left_img right_img [disp_size]" << std::endl;
		std::exit(EXIT_FAILURE);
	}

	cv::Mat left = cv::imread(argv[1], -1);
	cv::Mat right = cv::imread(argv[2], -1);

	int disp_size = 64;
	if (argc >= 4) {
		disp_size = atoi(argv[3]);
	}
	const int out_depth = argc > 4 ? std::stoi(argv[4]) : 8;
	const bool subpixel = argc > 5 ? std::stoi(argv[5]) != 0 : false;

	if (left.size() != right.size() || left.type() != right.type()) {
		std::cerr << "mismatch input image size" << std::endl;
		std::exit(EXIT_FAILURE);
	}

	int bits = 0;

	switch (left.type()) {
	case CV_8UC1: bits = 8; break;
	case CV_16UC1: bits = 16; break;
	default:
		std::cerr << "invalid input image color format" << left.type() << std::endl;
		std::exit(EXIT_FAILURE);
	}

	const sgm::StereoSGM::Parameters params{10, 120, 0.95f, subpixel};

	sgm::StereoSGM ssgm(left.cols, left.rows, disp_size, bits, out_depth, sgm::EXECUTE_INOUT_HOST2HOST, params);

	cv::Mat output(cv::Size(left.cols, left.rows), out_depth == 8 ? CV_8UC1 : CV_16UC1);

	ssgm.execute(left.data, right.data, output.data);
	// show image
	cv::Mat dst;
	if (subpixel) {
		output.convertTo(dst, CV_8UC1, 255. / (disp_size * sgm::StereoSGM::SUBPIXEL_SCALE));
	} else {
		output.convertTo(dst, CV_8UC1, 255. / disp_size);
	}
	cv::imshow("image", dst);

	cv::Mat colored = color_normalized(output);
	int key = cv::waitKey();
	int mode = 0;
	while (key != 27) {
		if (key == 's') {
			mode += 1;
			if (mode >= 3) mode = 0;

			switch (mode) {
			case 0:
				{
					#if CV_MAJOR_VERSION == 3
					cv::setWindowTitle("image", "disparity");
					#endif
					cv::imshow("image", dst);
					break;
				}
			case 1:
				{
					#if CV_MAJOR_VERSION == 3
					cv::setWindowTitle("image", "disparity color");
					#endif
					cv::imshow("image", colored);
					break;
				}
			case 2:
				{
					#if CV_MAJOR_VERSION == 3
					cv::setWindowTitle("image", "input");
					#endif
					cv::imshow("image", left);
					break;
				}
			}
		}
		key = cv::waitKey();
	}
}
<commit_msg>revert image sample<commit_after>/*
Copyright 2016 Fixstars Corporation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http ://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <stdlib.h>
#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/version.hpp>
#if CV_MAJOR_VERSION == 2
#include <opencv2/contrib/contrib.hpp>
#endif

#include <libsgm.h>

int main(int argc, char* argv[]) {
	if (argc < 3) {
		std::cerr << "usage: stereosgm left_img right_img [disp_size]" << std::endl;
		std::exit(EXIT_FAILURE);
	}

	cv::Mat left = cv::imread(argv[1], -1);
	cv::Mat right = cv::imread(argv[2], -1);

	int disp_size = 64;
	if (argc >= 4) {
		disp_size = atoi(argv[3]);
	}

	if (left.size() != right.size() || left.type() != right.type()) {
		std::cerr << "mismatch input image size" << std::endl;
		std::exit(EXIT_FAILURE);
	}

	int bits = 0;

	switch (left.type()) {
	case CV_8UC1: bits = 8; break;
	case CV_16UC1: bits = 16; break;
	default:
		std::cerr << "invalid input image color format" << left.type() << std::endl;
		std::exit(EXIT_FAILURE);
	}

	sgm::StereoSGM ssgm(left.cols, left.rows, disp_size, bits, 8, sgm::EXECUTE_INOUT_HOST2HOST);

	cv::Mat output(cv::Size(left.cols, left.rows), CV_8UC1);

	ssgm.execute(left.data, right.data, output.data);
	// show image
	cv::imshow("image", output * 256 / disp_size);

	int key = cv::waitKey();
	int mode = 0;
	while (key != 27) {
		if (key == 's') {
			mode += 1;
			if (mode >= 3) mode = 0;

			switch (mode) {
			case 0:
				{
					#if CV_MAJOR_VERSION == 3
					cv::setWindowTitle("image", "disparity");
					#endif
					cv::imshow("image", output * 256 / disp_size);
					break;
				}
			case 1:
				{
					cv::Mat m;
					cv::applyColorMap(output * 256 / disp_size, m, cv::COLORMAP_JET);
					#if CV_MAJOR_VERSION == 3
					cv::setWindowTitle("image", "disparity color");
					#endif
					cv::imshow("image", m);
					break;
				}
			case 2:
				{
					#if CV_MAJOR_VERSION == 3
					cv::setWindowTitle("image", "input");
					#endif
					cv::imshow("image", left);
					break;
				}
			}
		}
		key = cv::waitKey();
	}
}
<|endoftext|>


<commit_before>/*! \file CountBasicBlockExecutionPass.cpp
	\date Wednesday October 6, 2010
	\author Naila Farooqui <naila@cc.gatech.edu>
	\brief The source file for the CountBasicBlockExecutionPass class
*/

#ifndef COUNT_BASIC_BLOCK_EXECUTION_PASS_CPP_INCLUDED
#define COUNT_BASIC_BLOCK_EXECUTION_PASS_CPP_INCLUDED

#include <ocelot/analysis/interface/CountBasicBlockExecutionPass.h>
#include <ocelot/ir/interface/Module.h>
#include <ocelot/ir/interface/PTXStatement.h>
#include <ocelot/ir/interface/PTXKernel.h>
#include <ocelot/analysis/interface/DataflowGraph.h>

#include <hydrazine/implementation/debug.h>

#ifdef REPORT_BASE
#undef REPORT_BASE
#endif

#define REPORT_BASE 0

namespace analysis
{
    CountBasicBlockExecutionPass::CountBasicBlockExecutionPass()
		: ModulePass( DataflowGraphAnalysis, "CountBasicBlockExecutionPass" )
	{

	}

    void CountBasicBlockExecutionPass::_runOnBlock( ir::PTXKernel* kernel, DataflowGraph::iterator block, DataflowGraph::RegisterId registerId, unsigned int offset)
	{
        /* Creating an atomic add instruction to atomically
            load, increment, and store back the result into the
            global counter array */
        ir::PTXInstruction atomicAdd(ir::PTXInstruction::Atom);
        atomicAdd.atomicOperation = ir::PTXInstruction::AtomicAdd;
        atomicAdd.addressSpace = ir::PTXInstruction::Global;
        atomicAdd.type = ir::PTXOperand::u64;
        atomicAdd.a.addressMode = ir::PTXOperand::Address;
        atomicAdd.a.identifier = basicBlockCounterName();
        atomicAdd.a.offset = offset;
        atomicAdd.d.reg = registerId;
        atomicAdd.d.addressMode = ir::PTXOperand::Register;
		atomicAdd.d.type = ir::PTXOperand::u64;
        atomicAdd.b.addressMode = ir::PTXOperand::Immediate;
        atomicAdd.b.imm_int = 1;

        /* Need to insert in the beginning of the basic block.
            Since basic blocks usually end with branches, it
            wouldn't make sense to insert it at the end. */
        kernel->dfg()->insert( block, atomicAdd, 0 );

	}

	void CountBasicBlockExecutionPass::runOnModule( ir::Module& m )
	{
		report( "Adding global variable to " << m.path() );

		ir::PTXStatement statement = ir::PTXStatement(ir::PTXStatement::Global);
        statement.name = basicBlockCounterName();
        statement.type = ir::PTXOperand::u64;

        /* Since the global counter array needs to be declared per module, we need to
            traverse through all the kernels in this module and get the total number of
            basic blocks */
        unsigned int basicBlockCount = 0;
        for (ir::Module::KernelMap::const_iterator kernel = m.kernels().begin();
		    kernel != m.kernels().end(); ++kernel) {
            basicBlockCount += (kernel->second)->cfg()->size();
            /* creating a new register per kernel -- the same register can be reused so need to
            only create one per kernel and pass its id along. */
            DataflowGraph::RegisterId registerId = (kernel->second)->dfg()->newRegister();
            /* also need to keep track of the memory offset for the global counter array */
            unsigned int offset = 0;
            for( analysis::DataflowGraph::iterator block = (kernel->second)->dfg()->begin();
			    block != (kernel->second)->dfg()->end(); ++block )
		        {
			        _runOnBlock( (kernel->second), block, registerId, offset);
                    /* incrementing offset by 8 since the counter is a .u64 */
                    offset = offset + 8;
		        }
	    }

        /* creating a global array counter, each index initialized to zero */
        statement.array.stride.push_back(basicBlockCount);
        statement.array.values = ir::PTXStatement::ArrayVector(basicBlockCount);

        /* inserting the global counter array into the module */
        m.insertGlobal(statement);
	}

    void CountBasicBlockExecutionPass::finalize( )
	{

	}

    std::string CountBasicBlockExecutionPass::basicBlockCounterName() const
	{
		return "__ocelot_basic_block_counter";
	}
}

#endif
<commit_msg>Modified CountBasicBlockExecutionPass to choose between u32 and u64 data types and offset values based on size of size_t. This should ensure that the pass works for both 32-bit and 64-bit machines.<commit_after>/*! \file CountBasicBlockExecutionPass.cpp
	\date Wednesday October 6, 2010
	\author Naila Farooqui <naila@cc.gatech.edu>
	\brief The source file for the CountBasicBlockExecutionPass class
*/

#ifndef COUNT_BASIC_BLOCK_EXECUTION_PASS_CPP_INCLUDED
#define COUNT_BASIC_BLOCK_EXECUTION_PASS_CPP_INCLUDED

#include <ocelot/analysis/interface/CountBasicBlockExecutionPass.h>
#include <ocelot/ir/interface/Module.h>
#include <ocelot/ir/interface/PTXStatement.h>
#include <ocelot/ir/interface/PTXKernel.h>
#include <ocelot/analysis/interface/DataflowGraph.h>

#include <hydrazine/implementation/debug.h>

#ifdef REPORT_BASE
#undef REPORT_BASE
#endif

#define REPORT_BASE 0

namespace analysis
{
    CountBasicBlockExecutionPass::CountBasicBlockExecutionPass()
		: ModulePass( DataflowGraphAnalysis, "CountBasicBlockExecutionPass" )
	{

	}

    void CountBasicBlockExecutionPass::_runOnBlock( ir::PTXKernel* kernel, DataflowGraph::iterator block, DataflowGraph::RegisterId registerId, unsigned int offset)
	{
        /* Creating an atomic add instruction to atomically
            load, increment, and store back the result into the
            global counter array */
        ir::PTXInstruction atomicAdd(ir::PTXInstruction::Atom);
        atomicAdd.atomicOperation = ir::PTXInstruction::AtomicAdd;
        atomicAdd.addressSpace = ir::PTXInstruction::Global;
        atomicAdd.type = (sizeof(size_t) == 8 ? ir::PTXOperand::u64: ir::PTXOperand::u32);
        atomicAdd.a.addressMode = ir::PTXOperand::Address;
        atomicAdd.a.identifier = basicBlockCounterName();
        atomicAdd.a.offset = offset;
        atomicAdd.d.reg = registerId;
        atomicAdd.d.addressMode = ir::PTXOperand::Register;
		atomicAdd.d.type = (sizeof(size_t) == 8 ? ir::PTXOperand::u64: ir::PTXOperand::u32);
        atomicAdd.b.addressMode = ir::PTXOperand::Immediate;
        atomicAdd.b.imm_int = 1;

        /* Need to insert in the beginning of the basic block.
            Since basic blocks usually end with branches, it
            wouldn't make sense to insert it at the end. */
        kernel->dfg()->insert( block, atomicAdd, 0 );

	}

	void CountBasicBlockExecutionPass::runOnModule( ir::Module& m )
	{
		report( "Adding global variable to " << m.path() );

		ir::PTXStatement statement = ir::PTXStatement(ir::PTXStatement::Global);
        statement.name = basicBlockCounterName();
        statement.type = ir::PTXOperand::u64;

        /* Since the global counter array needs to be declared per module, we need to
            traverse through all the kernels in this module and get the total number of
            basic blocks */
        unsigned int basicBlockCount = 0;
        for (ir::Module::KernelMap::const_iterator kernel = m.kernels().begin();
		    kernel != m.kernels().end(); ++kernel) {
            basicBlockCount += (kernel->second)->cfg()->size();
            /* creating a new register per kernel -- the same register can be reused so need to
            only create one per kernel and pass its id along. */
            DataflowGraph::RegisterId registerId = (kernel->second)->dfg()->newRegister();
            /* also need to keep track of the memory offset for the global counter array */
            unsigned int offset = 0;
            for( analysis::DataflowGraph::iterator block = (kernel->second)->dfg()->begin();
			    block != (kernel->second)->dfg()->end(); ++block )
		        {
			        _runOnBlock( (kernel->second), block, registerId, offset);
                    /* incrementing offset based on size_t */
                    offset = offset + sizeof(size_t);
		        }
	    }

        /* creating a global array counter, each index initialized to zero */
        statement.array.stride.push_back(basicBlockCount);
        statement.array.values = ir::PTXStatement::ArrayVector(basicBlockCount);

        /* inserting the global counter array into the module */
        m.insertGlobal(statement);
	}

    void CountBasicBlockExecutionPass::finalize( )
	{

	}

    std::string CountBasicBlockExecutionPass::basicBlockCounterName() const
	{
		return "__ocelot_basic_block_counter";
	}
}

#endif
<|endoftext|>


<commit_before>#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "Sk1DPathEffect.h"
#include "SkCornerPathEffect.h"
#include "SkPathMeasure.h"
#include "SkRandom.h"
#include "SkColorPriv.h"
#include "SkPixelXorXfermode.h"

#define CORNER_RADIUS   12
static SkScalar gPhase;

static const int gXY[] = {
    4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
};

static SkPathEffect* make_pe(int flags) {
    if (flags == 1)
        return new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));

    SkPath  path;
    path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
    for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
        path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
    path.close();
    path.offset(SkIntToScalar(-6), 0);

    SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kRotate_Style);

    if (flags == 2)
        return outer;

    SkPathEffect* inner = new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));

    SkPathEffect* pe = new SkComposePathEffect(outer, inner);
    outer->unref();
    inner->unref();
    return pe;
}

static SkPathEffect* make_warp_pe() {
    SkPath  path;
    path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
    for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
        path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
    path.close();
    path.offset(SkIntToScalar(-6), 0);

    SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kMorph_Style);
    SkPathEffect* inner = new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));

    SkPathEffect* pe = new SkComposePathEffect(outer, inner);
    outer->unref();
    inner->unref();
    return pe;
}

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

#include "SkColorFilter.h"
#include "SkLayerRasterizer.h"

class testrast : public SkLayerRasterizer {
public:
    testrast() {
        SkPaint paint;
        paint.setAntiAlias(true);

#if 0
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(SK_Scalar1*4);
        this->addLayer(paint);

        paint.setStrokeWidth(SK_Scalar1*1);
        paint.setXfermode(SkXfermode::kClear_Mode);
        this->addLayer(paint);
#else
        paint.setAlpha(0x66);
        this->addLayer(paint, SkIntToScalar(4), SkIntToScalar(4));

        paint.setAlpha(0xFF);
        this->addLayer(paint);
#endif
    }
};

class PathEffectView : public SkView {
    SkPath  fPath;
    SkPoint fClickPt;
public:
	PathEffectView() {
        SkRandom    rand;
        int         steps = 20;
        SkScalar    dist = SkIntToScalar(400);
        SkScalar    x = SkIntToScalar(20);
        SkScalar    y = SkIntToScalar(50);

        fPath.moveTo(x, y);
        for (int i = 0; i < steps; i++) {
            x += dist/steps;
            SkScalar tmpY = y + SkIntToScalar(rand.nextS() % 25);
            if (i == steps/2) {
                fPath.moveTo(x, tmpY);
            } else {
                fPath.lineTo(x, tmpY);
            }
        }

        {
            SkRect  oval;
            oval.set(SkIntToScalar(20), SkIntToScalar(30),
                     SkIntToScalar(100), SkIntToScalar(60));
            oval.offset(x, 0);
            fPath.addRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8));
        }

        fClickPt.set(SkIntToScalar(200), SkIntToScalar(200));
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "PathEffects");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFFDDDDDD);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        if (false) {
            canvas->drawColor(SK_ColorWHITE);

            SkPixelXorXfermode  mode(SK_ColorWHITE);
            SkPaint             paint;

            paint.setColor(SK_ColorRED);
            paint.setXfermode(&mode);
            paint.setStrokeWidth(SkIntToScalar(8));

            canvas->drawLine(SkIntToScalar(100), SkIntToScalar(100),
                             SkIntToScalar(200), SkIntToScalar(200), paint);
            canvas->drawLine(SkIntToScalar(100), SkIntToScalar(200),
                             SkIntToScalar(200), SkIntToScalar(100), paint);
         //   return;
        }

        gPhase -= SampleCode::GetAnimSecondsDelta() * 40;
        this->inval(NULL);

        SkPaint paint;

#if 0
        paint.setAntiAlias(true);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(SkIntToScalar(5));
        canvas->drawPath(fPath, paint);
        paint.setStrokeWidth(0);

        paint.setColor(SK_ColorWHITE);
        paint.setPathEffect(make_pe(1))->unref();
        canvas->drawPath(fPath, paint);
#endif

        canvas->translate(0, SkIntToScalar(50));

        paint.setColor(SK_ColorBLUE);
        paint.setPathEffect(make_pe(2))->unref();
        canvas->drawPath(fPath, paint);

        canvas->translate(0, SkIntToScalar(50));

        paint.setARGB(0xFF, 0, 0xBB, 0);
        paint.setPathEffect(make_pe(3))->unref();
        canvas->drawPath(fPath, paint);

        canvas->translate(0, SkIntToScalar(50));

        paint.setARGB(0xFF, 0, 0, 0);
        paint.setPathEffect(make_warp_pe())->unref();
        paint.setRasterizer(new testrast)->unref();
        canvas->drawPath(fPath, paint);
    }

private:
    typedef SkView INHERITED;
};

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

static SkView* MyFactory() { return new PathEffectView; }
static SkViewRegister reg(MyFactory);

<commit_msg>inherit from SampleView<commit_after>#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "Sk1DPathEffect.h"
#include "SkCornerPathEffect.h"
#include "SkPathMeasure.h"
#include "SkRandom.h"
#include "SkColorPriv.h"
#include "SkPixelXorXfermode.h"

#define CORNER_RADIUS   12
static SkScalar gPhase;

static const int gXY[] = {
    4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
};

static SkPathEffect* make_pe(int flags) {
    if (flags == 1)
        return new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));

    SkPath  path;
    path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
    for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
        path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
    path.close();
    path.offset(SkIntToScalar(-6), 0);

    SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kRotate_Style);

    if (flags == 2)
        return outer;

    SkPathEffect* inner = new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));

    SkPathEffect* pe = new SkComposePathEffect(outer, inner);
    outer->unref();
    inner->unref();
    return pe;
}

static SkPathEffect* make_warp_pe() {
    SkPath  path;
    path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
    for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
        path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
    path.close();
    path.offset(SkIntToScalar(-6), 0);

    SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kMorph_Style);
    SkPathEffect* inner = new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));

    SkPathEffect* pe = new SkComposePathEffect(outer, inner);
    outer->unref();
    inner->unref();
    return pe;
}

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

#include "SkColorFilter.h"
#include "SkLayerRasterizer.h"

class testrast : public SkLayerRasterizer {
public:
    testrast() {
        SkPaint paint;
        paint.setAntiAlias(true);

#if 0
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(SK_Scalar1*4);
        this->addLayer(paint);

        paint.setStrokeWidth(SK_Scalar1*1);
        paint.setXfermode(SkXfermode::kClear_Mode);
        this->addLayer(paint);
#else
        paint.setAlpha(0x66);
        this->addLayer(paint, SkIntToScalar(4), SkIntToScalar(4));

        paint.setAlpha(0xFF);
        this->addLayer(paint);
#endif
    }
};

class PathEffectView : public SampleView {
    SkPath  fPath;
    SkPoint fClickPt;
public:
	PathEffectView() {
        SkRandom    rand;
        int         steps = 20;
        SkScalar    dist = SkIntToScalar(400);
        SkScalar    x = SkIntToScalar(20);
        SkScalar    y = SkIntToScalar(50);

        fPath.moveTo(x, y);
        for (int i = 0; i < steps; i++) {
            x += dist/steps;
            SkScalar tmpY = y + SkIntToScalar(rand.nextS() % 25);
            if (i == steps/2) {
                fPath.moveTo(x, tmpY);
            } else {
                fPath.lineTo(x, tmpY);
            }
        }

        {
            SkRect  oval;
            oval.set(SkIntToScalar(20), SkIntToScalar(30),
                     SkIntToScalar(100), SkIntToScalar(60));
            oval.offset(x, 0);
            fPath.addRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8));
        }

        fClickPt.set(SkIntToScalar(200), SkIntToScalar(200));

        this->setBGColor(0xFFDDDDDD);
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "PathEffects");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        gPhase -= SampleCode::GetAnimSecondsDelta() * 40;
        this->inval(NULL);

        SkPaint paint;

#if 0
        paint.setAntiAlias(true);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(SkIntToScalar(5));
        canvas->drawPath(fPath, paint);
        paint.setStrokeWidth(0);

        paint.setColor(SK_ColorWHITE);
        paint.setPathEffect(make_pe(1))->unref();
        canvas->drawPath(fPath, paint);
#endif

        canvas->translate(0, SkIntToScalar(50));

        paint.setColor(SK_ColorBLUE);
        paint.setPathEffect(make_pe(2))->unref();
        canvas->drawPath(fPath, paint);

        canvas->translate(0, SkIntToScalar(50));

        paint.setARGB(0xFF, 0, 0xBB, 0);
        paint.setPathEffect(make_pe(3))->unref();
        canvas->drawPath(fPath, paint);

        canvas->translate(0, SkIntToScalar(50));

        paint.setARGB(0xFF, 0, 0, 0);
        paint.setPathEffect(make_warp_pe())->unref();
        paint.setRasterizer(new testrast)->unref();
        canvas->drawPath(fPath, paint);
    }

private:
    typedef SampleView INHERITED;
};

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

static SkView* MyFactory() { return new PathEffectView; }
static SkViewRegister reg(MyFactory);

<|endoftext|>


<commit_before><commit_msg>Fixes gamepads disconnect crash on Android<commit_after><|endoftext|>