text:
//------------------------------------------------------------------------------
// \file StdTuple_tests.cpp
//------------------------------------------------------------------------------
#include <boost/test/unit_test.hpp>

#include <tuple>

BOOST_AUTO_TEST_SUITE(Cpp)
BOOST_AUTO_TEST_SUITE(Utilities)
BOOST_AUTO_TEST_SUITE(StdTuple_tests)

BOOST_AUTO_TEST_SUITE_END() // StdTuple_tests
BOOST_AUTO_TEST_SUITE_END() // Utilities
BOOST_AUTO_TEST_SUITE_END() // Cpp

max_stars_repo_name: ernestyalumni/HrdwCCppCUDA

max_issues_repo_name: ernestyalumni/HrdwCCppCUDA

max_forks_repo_name: ernestyalumni/HrdwCCppCUDA


text: #include <boost/preprocessor/expr_if.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
// Copyright Stephan T. Lavavej, http://nuwen.net .
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://boost.org/LICENSE_1_0.txt .

#ifndef PHAM_STATIC_ASSERT_PRIVATE_HH
#define PHAM_STATIC_ASSERT_PRIVATE_HH

#include "compiler.hh"

#ifdef NUWEN_PLATFORM_MSVC
    #pragma once
#endif

#include "external_begin.hh"
    #include <boost/static_assert.hpp>
#include "external_end.hh"

#ifdef NUWEN_PLATFORM_GCC
    // Modified from boost/static_assert.hpp RC_1_34_0 20061231, which is Copyright John Maddock.
    // The old-style casts to bool have been removed, as they trigger -Wold-style-cast.
    // static_cast<bool> seems to sometimes cause compilation problems, so
    // PHAM_STATIC_ASSERT simply requires that its argument actually be a bool.

    #ifdef BOOST_SA_GCC_WORKAROUND
        #define PHAM_STATIC_ASSERT(B) \
            typedef char BOOST_JOIN(boost_static_assert_typedef_, __LINE__) \
            [::boost::STATIC_ASSERTION_FAILURE<(B)>::value]
    #else
        #define PHAM_STATIC_ASSERT(B) \
            typedef ::boost::static_assert_test<sizeof(::boost::STATIC_ASSERTION_FAILURE<(B)>)> \
            BOOST_JOIN(boost_static_assert_typedef_, __LINE__)
    #endif
#else
    #define PHAM_STATIC_ASSERT BOOST_STATIC_ASSERT
#endif

#endif // Idempotency

ext: hh

max_stars_repo_name: nurettin/libnuwen

max_issues_repo_name: nurettin/libnuwen

max_forks_repo_name: nurettin/libnuwen


text:
#pragma once

//#include <boost/iostreams/stream.hpp>
//#include <boost/iostreams/stream_buffer.hpp>
//#include <boost/archive/binary_iarchive.hpp>
//#include <boost/archive/binary_oarchive.hpp>

#include <input/linux_structs.h>
#include <input/devices_descriptors.h>
#include <network/client.h>
#include "input/serialization.h"

/*
BOOST_IS_BITWISE_SERIALIZABLE(laprem::input::input_event)
BOOST_IS_BITWISE_SERIALIZABLE(laprem::input::input_driver::SharedEvent)
BOOST_IS_BITWISE_SERIALIZABLE(laprem::input::device_info)
BOOST_IS_BITWISE_SERIALIZABLE(laprem::input::device_descriptor)
*/

namespace laprem::logic {

    typedef enum : uint16_t{
        DEVICE_DESCRIPTOR = 0x1,
        INPUT_EVENT = 0x2
    } message_type;

    template<typename T>
    struct message;

    template<>
    struct message<laprem::input::device_descriptor>{
        inline static message_type type = DEVICE_DESCRIPTOR;
    };

    template<>
    struct message<laprem::input::input_driver::SharedEvent>{
        inline static message_type type = INPUT_EVENT;
    };

    template<typename T>
    void send_message(const network::client& c, const T& data){
        using namespace nlohmann;

        json jdata = data;
        json jmessage;
        jmessage["type"] = message<T>::header;
        jmessage["data"] = jdata;
        std::vector<std::uint8_t> buffy = json::to_msgpack(jmessage);

        c.send_buffer(buffy);
    }

}


text:
#ifndef TRISYCL_SYCL_BUFFER_DETAIL_BUFFER_HPP
#define TRISYCL_SYCL_BUFFER_DETAIL_BUFFER_HPP

/** \file The OpenCL SYCL buffer<> detail implementation

    Ronan at Keryell point FR

    This file is distributed under the University of Illinois Open Source
    License. See LICENSE.TXT for details.
*/

#include <cstddef>
#include <memory>
#include <type_traits>

#include <boost/multi_array.hpp>
// \todo Use C++17 optional when it is mainstream
#include <boost/optional.hpp>

#include "CL/sycl/access.hpp"
#include "CL/sycl/buffer/detail/accessor.hpp"
#include "CL/sycl/buffer/detail/buffer_base.hpp"
#include "CL/sycl/buffer/detail/buffer_waiter.hpp"
#include "CL/sycl/range.hpp"

namespace cl {
namespace sycl {
namespace detail {

/** \addtogroup data Data access and storage in SYCL
    @{
*/

/** A SYCL buffer is a multidimensional variable length array (à la C99
    VLA or even Fortran before) that is used to store data to work on.

    In the case we initialize it from a pointer, for now we just wrap the
    data with boost::multi_array_ref to provide the VLA semantics without
    any storage.
*/
template <typename T,
          int Dimensions = 1>
class buffer : public detail::buffer_base,
               public detail::debug<buffer<T, Dimensions>> {
public:

  // Extension to SYCL: provide pieces of STL container interface
  using element = T;
  using value_type = T;
  /* Even if the buffer is read-only use a non-const type so at
     least the current implementation can copy the data too */
  using non_const_value_type = std::remove_const_t<value_type>;

private:

  // \todo Replace U and D somehow by T and Dimensions
  // To allow allocation access
  template <typename U,
            int D,
            access::mode Mode,
            access::target Target /* = access::global_buffer */>
    friend class detail::accessor;

  /** The allocator to be used when some memory is needed

      \todo Implement user-provided allocator
  */
  std::allocator<non_const_value_type> alloc;

  /** This is the multi-dimensional interface to the data that may point
      to either allocation in the case of storage managed by SYCL itself
      or to some other memory location in the case of host memory or
      storage<> abstraction use
  */
  boost::multi_array_ref<value_type, Dimensions> access;

  /** If some allocation is requested on the host for the buffer
      memory, this is where the memory is attached to.

      Note that this is uninitialized memory, as stated in SYCL
      specification.
  */
  non_const_value_type *allocation = nullptr;

  /* How to copy back data on buffer destruction, can be modified with
     set_final_data( ... )
   */
  boost::optional<std::function<void(void)>> final_write_back;

  // Keep the shared pointer used to create the buffer
  shared_ptr_class<T> input_shared_pointer;

  // Track if the buffer memory is provided as host memory
  bool data_host = false;

  // Track if data should be copied if a modification occurs
  bool copy_if_modified = false;

  // Track if data have been modified
  bool modified = false;

public:

  /// Create a new read-write buffer of size \param r
  buffer(const range<Dimensions> &r) : access { allocate_buffer(r) } {}

  /** Create a new read-write buffer from \param host_data of size
      \param r without further allocation */
  buffer(T *host_data, const range<Dimensions> &r) :
    access { host_data, r },
    data_host { true }
  {}

  /** Create a new read-only buffer from \param host_data of size \param r
      without further allocation

      If the buffer is non const, use a copy-on-write mechanism with
      internal writable memory.

      \todo Clarify the semantics in the spec. What happens if the
      host change the host_data after buffer creation?

      Only enable this constructor if the value type is not constant,
      because if it is constant, the buffer is constant too.
  */
  template <typename Dependent = T,
            typename = std::enable_if_t<!std::is_const<Dependent>::value>>
  buffer(const T *host_data, const range<Dimensions> &r) :
    /* The buffer is read-only, even if the internal multidimensional
       wrapper is not. If a write accessor is requested, there should
       be a copy on write. So this pointer should not be written and
       this const_cast should be acceptable. */
    access { const_cast<T *>(host_data), r },
    data_host { true },
    /* Set copy_if_modified to true, so that if an accessor with write
       access is created, data are copied before to be modified. */
    copy_if_modified { true }
  {}

  /** Create a new buffer with associated memory, using the data in
      host_data

      The ownership of the host_data is shared between the runtime and the
      user. In order to enable both the user application and the SYCL
      runtime to use the same pointer, a cl::sycl::mutex_class is
      used.
  */
  buffer(shared_ptr_class<T> &host_data, const range<Dimensions> &r) :
    access { host_data.get(), r },
    input_shared_pointer { host_data },
    data_host { true }
  {}

  /** Create a new buffer with associated memory, using the data owned in
      a unique pointer

      SYCL's runtime has full ownership of the host_data.
  */
  template<typename Deleter>
  buffer(unique_ptr_class<T, Deleter> &&host_data,
         const range<Dimensions> &r) :
    access { host_data.get(), r },
      /* Use the fact that there is an implicit constructor of a \c
         std::shared_ptr from a \c std::unique_ptr to avoid storing
         the unique pointer. Doing so would need to implement
         ourselves some type erasure on the \c Deleter to avoid it
         leaking out of the \c buffer type and \c accessor type.

         It still works as expected since, if we own a shared pointer,
         the \c Deleter is correctly handled and if we own it and its
         use-count is 1, we are the only owner and we can skip the
         copy-back later.
       */
    input_shared_pointer { std::move(host_data) },
    data_host { true }
  {}

  /// Create a new allocated 1D buffer from the given elements
  template <typename Iterator>
  buffer(Iterator start_iterator, Iterator end_iterator) :
    access { allocate_buffer(std::distance(start_iterator, end_iterator)) }
    {
      /* Then assign allocation since this is the only multi_array
         method with this iterator interface */
      access.assign(start_iterator, end_iterator);
    }

  /** Create a new sub-buffer without allocation to have separate
      accessors later

      \todo To implement and deal with reference counting
  buffer(buffer<T, Dimensions> b,
         index<Dimensions> base_index,
         range<Dimensions> sub_range)
  */

  /// \todo Allow CLHPP objects too?
  ///
  /*
  buffer(cl_mem mem_object,
         queue from_queue,
         event available_event)
  */

  /** The buffer content may be copied back on destruction to some
      final location */
  ~buffer() {
#ifdef TRISYCL_OPENCL
    /* We ensure that the host has the most up-to-date version of the data
       before the buffer is destroyed. This is necessary because we do not
       systematically transfer the data back from a device with
       \c copy_back_cl_buffer any more.
       \todo Optimize for the case the buffer is not based on host memory
    */
    cl::sycl::context ctx;
    auto size = access.num_elements() * sizeof(value_type);
    call_update_buffer_state(ctx, access::mode::read, size, access.data());

#endif
    if (modified && final_write_back)
      (*final_write_back)();
    // Allocate explicitly allocated memory if required
    deallocate_buffer();
  }

  /** Enforce the buffer to be considered as being modified.
      Same as creating an accessor with write access.
   */
  void mark_as_written() {
    modified = true;
  }

  /** This method is to be called whenever an accessor is created

      Its current purpose is to track if an accessor with write access
      is created and acting accordingly.
   */
  template <access::mode Mode,
            access::target Target = access::target::host_buffer>
  void track_access_mode() {
    // test if write access is required
    if (   Mode == access::mode::write
        || Mode == access::mode::read_write
        || Mode == access::mode::discard_write
        || Mode == access::mode::discard_read_write
        || Mode == access::mode::atomic
       ) {
      modified = true;
      if (copy_if_modified) {
        // Implement the allocate & copy-on-write optimization
        copy_if_modified = false;
        data_host = false;
        // Since \c allocate_buffer() changes \c access, keep a copy first
        auto current_access = access;
        /* The range is actually computed from \c access itself, so
           save it */
        auto current_range = get_range();
        allocate_buffer(current_range);
        /* Then move everything to the new place

           \todo Use std::uninitialized_move instead, when we switch
           to full C++17
        */
        std::copy(current_access.begin(),
                  current_access.end(),
                  access.begin());
      }
    }
  }

 /** Return a range object representing the size of the buffer in
      terms of number of elements in each dimension as passed to the
      constructor
  */
  auto get_range() const {
    /* Interpret the shape which is a pointer to the first element as an
       array of Dimensions elements so that the range<Dimensions>
       constructor is happy with this collection

       \todo Add also a constructor in range<> to accept a const
       std::size_t *?
    */
    return range<Dimensions> {
      *(const std::size_t (*)[Dimensions])(access.shape())
        };
  }

  /** Returns the total number of elements in the buffer

      Equal to get_range()[0] * ... * get_range()[Dimensions-1].
  */
  auto get_count() const {
    return access.num_elements();
  }

  /** Returns the size of the buffer storage in bytes

      \todo rename to something else. In
      http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0122r0.pdf
      it is named bytes() for example
  */
  auto get_size() const {
    return get_count()*sizeof(value_type);
  }

  /** Set the weak pointer as destination for write-back on buffer
      destruction
  */
  void set_final_data(std::weak_ptr<T> && final_data) {
    final_write_back = [=] {
      if (auto sptr = final_data.lock()) {
        std::copy_n(access.data(), access.num_elements(), sptr.get());
      }
    };
  }

  /** Provide destination for write-back on buffer destruction as a
      shared pointer.
   */
  void set_final_data(std::shared_ptr<T> && final_data) {
    final_write_back = [=] {
      std::copy_n(access.data(), access.num_elements(), final_data.get());
    };
  }

  /** Disable write-back on buffer destruction as an iterator.
  */
  void set_final_data(std::nullptr_t) {
    final_write_back = boost::none;
  }

  /** Provide destination for write-back on buffer destruction as an
      iterator
  */
  template <typename Iterator>
  void set_final_data(Iterator final_data) {
 /*   using type_ = typename iterator_value_type<Iterator>::value_type;
    static_assert(std::is_same<type_, T>::value, "buffer type mismatch");
    static_assert(!(std::is_const<type_>::value),
                  "const iterator is not allowed");*/
    final_write_back = [=] {
      std::copy_n(access.data(), access.num_elements(), final_data);
    };
  }

private:

  /// Allocate uninitialized buffer memory
  auto allocate_buffer(const range<Dimensions> &r) {
    auto count = r.get_count();
    // Allocate uninitialized memory
    allocation = alloc.allocate(count);
    return boost::multi_array_ref<value_type, Dimensions> { allocation, r };
  }

  /// Deallocate buffer memory if required
  void deallocate_buffer() {
    if (allocation)
      alloc.deallocate(allocation, access.num_elements());
  }

  /** Function pair to work around the fact that T might be a \c const type.
      We call update_buffer_state only if T is not \c const, we have to
      use \c enable_if otherwise the compiler will try to cast \c const
      \c void* to \c void* if we create a buffer with a \c const type

      \todo Use \c if \c constexpr when it is available with C++17
  */
  template <typename BaseType = T, typename DataType>
  void call_update_buffer_state(cl::sycl::context ctx, access::mode mode,
                                size_t size, DataType* data,
                                std::enable_if_t<!std::is_const<BaseType>
                                ::value>* = 0) {
    update_buffer_state(ctx, mode, size, data);
  }

  /** Version of \c call_update_buffer_state that does nothing. It is called if
      the type of the data in the buffer is \c const
   */
  template <typename BaseType = T, typename DataType>
  void call_update_buffer_state(cl::sycl::context ctx, access::mode mode,
                                size_t size, DataType* data,
                                std::enable_if_t<std::is_const<BaseType>
                                ::value>* = 0) { }

public:

  /** Get a \c future to wait from inside the \c cl::sycl::buffer in
      case there is something to copy back to the host

      \return A \c future in the \c optional if there is something to
      wait for, otherwise an empty \c optional
      \todo Make the function private again
  */
  boost::optional<std::future<void>> get_destructor_future() {
    /* If there is only 1 shared_ptr user of the buffer, this is the
       caller of this function, the \c buffer_waiter, so there is no
       need to get a \ future otherwise there will be a dead-lock if
       there is only 1 thread waiting for itself.

       Since \c use_count() is applied to a \c shared_ptr just created
       for this purpose, it actually increase locally the count by 1,
       so check for 1 + 1 use count instead...
    */
    // If the buffer's destruction triggers a write-back, wait
    if ((shared_from_this().use_count() > 2) &&
        modified && (final_write_back || data_host)) {
      // Create a promise to wait for
      notify_buffer_destructor = std::promise<void> {};
      // And return the future to wait for it
      return notify_buffer_destructor->get_future();
    }
    return boost::none;
  }

private:

  // Allow buffer_waiter destructor to access get_destructor_future()
  // friend detail::buffer_waiter<T, Dimensions>::~buffer_waiter();
  /* \todo Work around to Clang bug
     https://llvm.org/bugs/show_bug.cgi?id=28873 cannot use destructor
     here */
  /* \todo solve the fact that get_destructor_future is not accessible
     when private and buffer_waiter uses a custom allocator */
  friend detail::buffer_waiter<T, Dimensions>;

};

/** Proxy function to avoid some circular type recursion

    \return a shared_ptr<task>

    \todo To remove with some refactoring
*/
template <typename BufferDetail>
static std::shared_ptr<detail::task>
buffer_add_to_task(BufferDetail buf,
                   handler *command_group_handler,
                   bool is_write_mode) {
    return buf->add_to_task(command_group_handler, is_write_mode);
  }

/// @} End the data Doxygen group

}
}
}

/*
    # Some Emacs stuff:
    ### Local Variables:
    ### ispell-local-dictionary: "american"
    ### eval: (flyspell-prog-mode)
    ### End:
*/

#endif // TRISYCL_SYCL_BUFFER_DETAIL_BUFFER_HPP

max_stars_repo_name: infinitesnow/InceptionCL

max_issues_repo_name: infinitesnow/InceptionCL

max_forks_repo_name: infinitesnow/InceptionCL


text:
/**
 * @file  eventconverter-opl.cpp
 * @brief EventHandler implementation that produces OPL data from Events.
 *
 * Copyright (C) 2010-2015 Adam Nielsen <malvineous@shikadi.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <sstream>
#include <math.h>
#include <boost/pointer_cast.hpp>
#include <camoto/error.hpp>
#include <camoto/util.hpp>
#include <camoto/gamemusic/eventconverter-opl.hpp>
#include <camoto/gamemusic/eventconverter-midi.hpp>
#include <camoto/gamemusic/util-opl.hpp>
#include <camoto/gamemusic/patch-midi.hpp>

using namespace camoto;
using namespace camoto::gamemusic;

EventConverter_OPL::EventConverter_OPL(OPLWriterCallback *cb,
	ConstMusicPtr music, double fnumConversion, OPLWriteFlags::type flags)
	:	cb(cb),
		music(music),
		fnumConversion(fnumConversion),
		flags(flags),
		cachedDelay(0),
		modeOPL3(false),
		modeRhythm(false)
{
	// Initialise all OPL registers to zero (this is assumed the initial state
	// upon playback)
	memset(this->oplSet, 0x00, sizeof(this->oplSet));
	memset(this->oplState, 0x00, sizeof(this->oplState));
	assert(this->oplSet[0][0] == false);
}

EventConverter_OPL::~EventConverter_OPL()
{
}

void EventConverter_OPL::setBankMIDI(PatchBankPtr bankMIDI)
{
	this->bankMIDI = bankMIDI;
	return;
}

void EventConverter_OPL::handleAllEvents(EventHandler::EventOrder eventOrder)
{
	this->EventHandler::handleAllEvents(eventOrder, this->music);

	// Write out any trailing delay
	OPLEvent oplev;
	oplev.valid = OPLEvent::Delay;
	oplev.delay = this->cachedDelay;
	this->cachedDelay = 0;
	this->cb->writeNextPair(&oplev);
}

void EventConverter_OPL::endOfTrack(unsigned long delay)
{
	return;
}

void EventConverter_OPL::endOfPattern(unsigned long delay)
{
	this->cachedDelay += delay;
	return;
}

void EventConverter_OPL::handleEvent(unsigned long delay,
	unsigned int trackIndex, unsigned int patternIndex, const TempoEvent *ev)
{
	assert(ev->tempo.usPerTick > 0);
	this->cachedDelay += delay;
	OPLEvent oplev;
	oplev.valid = 0;
	if (this->cachedDelay) {
		oplev.valid |= OPLEvent::Delay;
		oplev.delay = this->cachedDelay;
		this->cachedDelay = 0;
	}
	oplev.valid |= OPLEvent::Tempo;
	oplev.tempo = ev->tempo;
	this->cb->writeNextPair(&oplev);
	return;
}

void EventConverter_OPL::handleEvent(unsigned long delay,
	unsigned int trackIndex, unsigned int patternIndex, const NoteOnEvent *ev)
{
	assert(this->music->patches);
	assert(trackIndex < this->music->trackInfo.size());

	// Set the delay as a cached delay, so that it will be written out before the
	// next register write, whenever that happens to be.
	this->cachedDelay += delay;

	if (ev->instrument >= this->music->patches->size()) {
		throw bad_patch(createString("Instrument bank too small - tried to play "
			"note with instrument #" << ev->instrument + 1
			<< " but patch bank only has " << this->music->patches->size()
			<< " instruments."));
	}
	PatchPtr patch = this->music->patches->at(ev->instrument);
	const TrackInfo& ti = this->music->trackInfo[trackIndex];
	if (this->bankMIDI) {
		// We are handling MIDI events
		if (
			(ti.channelType != TrackInfo::MIDIChannel)
			&& (ti.channelType != TrackInfo::AnyChannel)
		) {
			// Not a MIDI track
			return;
		}
		MIDIPatchPtr instMIDI = boost::dynamic_pointer_cast<MIDIPatch>(patch);
		if (!instMIDI) return; // non-MIDI instrument on a MIDI channel, ignore
		unsigned long target = instMIDI->midiPatch;
		if (instMIDI->percussion) {
			target += MIDI_PATCHES;
		}
		if (target < this->bankMIDI->size()) {
			patch = this->bankMIDI->at(target);
		} else {
			// No patch, bank too small
			std::cout << "Dropping MIDI note, no entry in MIDI bank for "
				<< (instMIDI->percussion ? "percussion" : "")
				<< " patch #" << (int)instMIDI->midiPatch << "\n";
			return;
		}
	} else {
		// We are handling OPL events
		if (
			(ti.channelType != TrackInfo::OPLChannel)
			&& (ti.channelType != TrackInfo::OPLPercChannel)
			&& (ti.channelType != TrackInfo::AnyChannel)
		) {
			// Not an OPL track
			return;
		}

		if (
			(ti.channelType == TrackInfo::OPLPercChannel)
			&& (!this->modeRhythm)
		) {
			std::cerr << "OPL: Ignoring rhythm channel in non-rhythm mode" << std::endl;
			return;
		}

		if (
			(ti.channelType == TrackInfo::OPLChannel)
			&& (!this->modeOPL3)
			&& (ti.channelIndex >= 9)
		) {
			std::cerr << "OPL: Ignoring OPL3 channels in OPL2 mode" << std::endl;
			return;
		}
	}
	OPLPatchPtr inst = boost::dynamic_pointer_cast<OPLPatch>(patch);

	// Don't play this note if there's no patch for it
	if (!inst) return;

	unsigned int oplChannel, chipIndex;
	bool mod, car;
	this->getOPLChannel(ti, trackIndex, &oplChannel, &chipIndex, &mod, &car);

	// No free channels
	if (chipIndex == OPL_INVALID_CHIP) return;

	// If the note is already playing, turn it off first before we update the
	// instrument parameters.  This makes a clean note and prevents it from
	// audibly morphing into the new patch.
	if (ti.channelType == TrackInfo::OPLPercChannel) {
		int keyBit = 1 << ti.channelIndex;
		if (this->oplState[chipIndex][0xBD] & keyBit) {
			// Note is already playing, disable
			this->processNextPair(chipIndex, 0xBD,
				this->oplState[chipIndex][0xBD] ^ keyBit
			);
		}
	} else { // normal instrument
		if (this->oplState[chipIndex][0xB0 | oplChannel] & OPLBIT_KEYON) {
			// Note already playing, switch it off first
			this->processNextPair(chipIndex, 0xB0 | oplChannel,
				(this->oplState[chipIndex][0xB0 | oplChannel] & ~OPLBIT_KEYON)
			);
		}
	}

	// We always have to set the patch in case the velocity has changed.
	// Duplicate register writes will be dropped later.

	// Write modulator settings
	if (mod) {
		this->writeOpSettings(chipIndex, oplChannel, 0, inst, ev->velocity);
	}
	// Write carrier settings
	if (car) {
		this->writeOpSettings(chipIndex, oplChannel, 1, inst, ev->velocity);
	}

	unsigned int fnum, block;
	milliHertzToFnum(ev->milliHertz, &fnum, &block, this->fnumConversion);
	assert(block <= 7);

	// Write the rest of the (global) instrument settings.
	if (ti.channelType != TrackInfo::OPLPercChannel) {
		// This register is only used on melodic channels.  It is ignored on
		// percussive channels, so don't bother setting it.
		this->processNextPair(chipIndex, BASE_FEED_CONN | oplChannel,
			(this->modeOPL3 ? 0x30 /* L+R OPL3 panning */ : 0 /* regs aren't on OPL2 */)
			| ((inst->feedback & 7) << 1)
			| (inst->connection ? 1 : 0));
	}

	// Write lower eight bits of note freq
	this->processNextPair(chipIndex, 0xA0 | oplChannel, fnum & 0xFF);

	// Write 0xB0 w/ keyon bit
	this->processNextPair(chipIndex, 0xB0 | oplChannel,
		(ti.channelType != TrackInfo::OPLPercChannel ? OPLBIT_KEYON : 0) // keyon enabled
		| (block << 2) // and the octave
		| ((fnum >> 8) & 0x03) // plus the upper two bits of fnum
	);

	if (ti.channelType == TrackInfo::OPLPercChannel) {
		// Write keyon for correct instrument
		int keyBit = 1 << ti.channelIndex;
		this->processNextPair(chipIndex, 0xBD,
			0x20 |  // enable percussion mode
			this->oplState[chipIndex][0xBD] | keyBit
		);
	}
	return;
}

void EventConverter_OPL::handleEvent(unsigned long delay,
	unsigned int trackIndex, unsigned int patternIndex, const NoteOffEvent *ev)
{
	this->cachedDelay += delay;

	assert(trackIndex < this->music->trackInfo.size());
	const TrackInfo& ti = this->music->trackInfo[trackIndex];
	if (
		(ti.channelType != TrackInfo::OPLChannel)
		&& (ti.channelType != TrackInfo::OPLPercChannel)
		&& (ti.channelType != TrackInfo::AnyChannel)
		&& (
			!this->bankMIDI
			|| (ti.channelType != TrackInfo::MIDIChannel)
		)
	) {
		// This isn't an OPL track, so ignore it
		return;
	}

	if (ti.channelType == TrackInfo::OPLPercChannel) {
		uint8_t keyBit = 1 << ti.channelIndex; // instrument-specific keyon
		this->processNextPair(0, 0xBD,
			(this->oplState[0][0xBD] & ~keyBit)
		);
	} else {
		unsigned int oplChannel, chipIndex;
		bool mod, car;
		this->getOPLChannel(ti, trackIndex, &oplChannel, &chipIndex, &mod, &car);

		// No free channels
		if (chipIndex == OPL_INVALID_CHIP) return;

		// Write 0xB0 w/ keyon bit disabled
		this->processNextPair(chipIndex, 0xB0 | oplChannel,
			(this->oplState[chipIndex][0xB0 | oplChannel] & ~OPLBIT_KEYON)
		);

		this->clearOPLChannel(trackIndex);
	}
	return;
}

void EventConverter_OPL::handleEvent(unsigned long delay, unsigned int trackIndex,
	unsigned int patternIndex, const EffectEvent *ev)
{
	this->cachedDelay += delay;

	assert(trackIndex < this->music->trackInfo.size());
	const TrackInfo& ti = this->music->trackInfo[trackIndex];
	if (
		(ti.channelType != TrackInfo::OPLChannel)
		&& (ti.channelType != TrackInfo::OPLPercChannel)
		&& (ti.channelType != TrackInfo::AnyChannel)
		&& (
			!this->bankMIDI
			|| (ti.channelType != TrackInfo::MIDIChannel)
		)
	) {
		// This isn't an OPL track, so ignore it
		return;
	}

	unsigned int oplChannel, chipIndex;
	bool mod, car;
	this->getOPLChannel(ti, trackIndex, &oplChannel, &chipIndex, &mod, &car);

	// No free channels
	if (chipIndex == OPL_INVALID_CHIP) return;

	switch (ev->type) {
		case EffectEvent::PitchbendNote: {
			// Just bend the whole channel because there will only be one note
			// playing anyway, and the bend will be reset on the next note.
			const unsigned int& milliHertz = ev->data;
			unsigned int fnum, block;
			milliHertzToFnum(milliHertz, &fnum, &block, this->fnumConversion);

			// Write lower eight bits of note freq
			this->processNextPair(chipIndex, 0xA0 | oplChannel, fnum & 0xFF);

			// Write 0xB0 w/ keyon bit
			this->processNextPair(chipIndex, 0xB0 | oplChannel,
				// Use whatever keyon bit was set before - this will prevent rhythm
				// instruments from having the keyon bit set erroneously
				(this->oplState[chipIndex][0xB0 | oplChannel] & OPLBIT_KEYON)
				| (block << 2) // and the octave
				| ((fnum >> 8) & 0x03) // plus the upper two bits of fnum
			);
			break;
		}
		case EffectEvent::Volume:
			// ev->data is new velocity/volume value
			// Write carrier settings (modulator output level does not control volume)
			if (car) {
				const unsigned int& volume = ev->data;
				unsigned int op = OPLOFFSET_CAR(oplChannel);
				unsigned int outputLevel = 0x3F - 0x3F * log((float)volume) / log(256.0);

				uint8_t reg = BASE_SCAL_LEVL | op;
				uint8_t val = this->oplState[chipIndex][reg] & ~0x3F;
				this->processNextPair(chipIndex, reg, val | (outputLevel & 0x3F));
			}
			break;
	}
	return;
}

void EventConverter_OPL::handleEvent(unsigned long delay, unsigned int trackIndex,
	unsigned int patternIndex, const GotoEvent *ev)
{
	// We'll do something here when we encounter the first raw OPL format that
	// supports jumps.
	this->cachedDelay += delay;
	return;
}

void EventConverter_OPL::handleEvent(unsigned long delay,
	unsigned int trackIndex, unsigned int patternIndex,
	const ConfigurationEvent *ev)
{
	this->cachedDelay += delay;

	assert(trackIndex < this->music->trackInfo.size());
	const TrackInfo& ti = this->music->trackInfo[trackIndex];
	if (
		(ti.channelType != TrackInfo::OPLChannel)
		&& (ti.channelType != TrackInfo::OPLPercChannel)
		&& (ti.channelType != TrackInfo::AnyChannel)
		&& (
			!this->bankMIDI
			|| (ti.channelType != TrackInfo::MIDIChannel)
		)
	) {
		// This isn't an OPL track, so ignore it
		return;
	}

	switch (ev->configType) {
		case ConfigurationEvent::EmptyEvent:
			break;
		case ConfigurationEvent::EnableOPL3:
			if (
				(this->modeOPL3 && (ev->value == 0)) // on, switching off
				|| (!this->modeOPL3 && (ev->value == 1)) // off, switching on
			) {
				this->processNextPair(1, 0x05, ev->value ? 0x01 : 0x00);
				this->modeOPL3 = ev->value;
			}
			break;
		case ConfigurationEvent::EnableDeepTremolo: {
			unsigned int chipIndex = (ev->value >> 1) & 1;
			uint8_t val;
			if (ev->value & 1) val = this->oplState[chipIndex][0xBD] | 0x80;
			else val = this->oplState[chipIndex][0xBD] & 0x7F;
			this->processNextPair(chipIndex, 0xBD, val);
			break;
		}
		case ConfigurationEvent::EnableDeepVibrato: {
			unsigned int chipIndex = (ev->value >> 1) & 1;
			uint8_t val;
			if (ev->value & 1) val = this->oplState[chipIndex][0xBD] | 0x40;
			else val = this->oplState[chipIndex][0xBD] & 0xBF;
			this->processNextPair(chipIndex, 0xBD, val);
			break;
		}
		case ConfigurationEvent::EnableRhythm:
			// Nothing required, rhythm mode is enabled the first time a rhythm
			// instrument is played.
			if (this->modeRhythm && (ev->value == 0)) {
				// Switching rhythm mode off (incl all rhythm instruments)
				this->processNextPair(0, 0xBD,
					this->oplState[0][0xBD] & ~0x3F
				);
				this->processNextPair(1, 0xBD,
					this->oplState[1][0xBD] & ~0x3F
				);
			}
			this->modeRhythm = ev->value;
			break;
		case ConfigurationEvent::EnableWaveSel:
			this->processNextPair(0, 0x01, ev->value ? 0x20 : 0x00);
			break;
	}
	return;
}

void EventConverter_OPL::processNextPair(uint8_t chipIndex, uint8_t reg,
	uint8_t val)
{
	assert(chipIndex < 2);

	// Don't write anything if the value isn't changing
	if (this->oplSet[chipIndex][reg] && (this->oplState[chipIndex][reg] == val)) return;

	OPLEvent oplev;
	oplev.valid = OPLEvent::Delay | OPLEvent::Regs;
	oplev.reg = reg;
	oplev.val = val;
	oplev.chipIndex = chipIndex;
	oplev.delay = this->cachedDelay;
	this->cachedDelay = 0;

	this->cb->writeNextPair(&oplev);

	this->oplState[chipIndex][reg] = val;
	this->oplSet[chipIndex][reg] = true;
	return;
}

void EventConverter_OPL::writeOpSettings(int chipIndex, int oplChannel,
	int opNum, OPLPatchPtr i, int velocity)
{
	uint8_t op;
	OPLOperator *o;
	int outputLevel;
	if (opNum == 0) {
		op = OPLOFFSET_MOD(oplChannel);
		o = &(i->m);
		outputLevel = o->outputLevel;
		// Note that modulator-only percussive instruments cannot have their volume
		// set, so we don't need to handle that here
	} else {
		op = OPLOFFSET_CAR(oplChannel);
		o = &(i->c);
		outputLevel = o->outputLevel;
		if (velocity != DefaultVelocity) {
			// Not using default velocity
			outputLevel = 63 - lin_velocity_to_log_volume(velocity, 63);
			// Note the CMF reader sets the velocity to -1 to skip this
			// @todo: Use a flag: inst output val is max note vel, or note vel overrides inst output val
		}
	}

	this->processNextPair(chipIndex, BASE_CHAR_MULT | op,
		((o->enableTremolo & 1) << 7) |
		((o->enableVibrato & 1) << 6) |
		((o->enableSustain & 1) << 5) |
		((o->enableKSR     & 1) << 4) |
		 (o->freqMult      & 0x0F)
	);
	this->processNextPair(chipIndex, BASE_SCAL_LEVL | op, (o->scaleLevel << 6) | (outputLevel & 0x3F));
	this->processNextPair(chipIndex, BASE_ATCK_DCAY | op, (o->attackRate << 4) | (o->decayRate & 0x0F));
	this->processNextPair(chipIndex, BASE_SUST_RLSE | op, (o->sustainRate << 4) | (o->releaseRate & 0x0F));
	this->processNextPair(chipIndex, BASE_WAVE      | op,  o->waveSelect & 7);
	return;
}

void EventConverter_OPL::getOPLChannel(const TrackInfo& ti,
	unsigned int trackIndex, unsigned int *oplChannel, unsigned int *chipIndex,
	bool *mod, bool *car)
{
	*oplChannel = 99;
	if (ti.channelType == TrackInfo::OPLPercChannel) {
		*chipIndex = 0;
		switch (ti.channelIndex) {
			case 4: *oplChannel = 6; *mod = true;  *car = true;  break; // bass drum (mod+car)
			case 3: *oplChannel = 7; *mod = false; *car = true;  break; // snare (car)
			case 2: *oplChannel = 8; *mod = true;  *car = false; break; // tomtom (mod)
			case 1: *oplChannel = 8; *mod = false; *car = true;  break; // top cymbal (car)
			case 0: *oplChannel = 7; *mod = true;  *car = false; break; // hi-hat (mod)
			default:
				throw error(createString("OPL percussion channel out of range: "
					<< (int)ti.channelIndex << " is not in 0 <= x <= 4"));
		}
	} else if (ti.channelType == TrackInfo::OPLChannel) {
		if ((ti.channelIndex == 0) && (this->flags & OPLWriteFlags::ReserveFirstChan)) {
			throw format_limitation("OPL channel 0 cannot be used in this format.  "
				"Please select a different channel.");
		}
		if (ti.channelIndex < 9) {
			*oplChannel = ti.channelIndex;
			*chipIndex = 0;
		} else if ((ti.channelIndex < 18) && !(this->flags & OPLWriteFlags::OPL2Only)) {
			*oplChannel = ti.channelIndex - 9;
			*chipIndex = 1;
		} else {
			throw error(createString("OPL channel " << ti.channelIndex
				<< " is out of range!  This format only supports up to and including "
				"channel " << ((this->flags & OPLWriteFlags::OPL2Only) ? 8 : 17)));
		}
		*mod = true;
		*car = true;
	} else if (ti.channelType == TrackInfo::MIDIChannel) {
		*mod = true;
		*car = true;
		int rawChannel = -1;
		MIDIChannelMap::iterator i = this->midiChannelMap.find(trackIndex);
		if (i != this->midiChannelMap.end()) {
			// Reuse a previous mapping
			rawChannel = i->second;
		} else {
			// Create a new mapping
			bool channelInUse[OPL_MAX_CHANNELS];
			for (unsigned int j = 0; j < OPL_MAX_CHANNELS; j++) channelInUse[j] = false;
			for (MIDIChannelMap::const_iterator
				j = this->midiChannelMap.begin(); j != this->midiChannelMap.end(); j++
			) {
				assert(j->second < (signed int)OPL_MAX_CHANNELS);
				if (j->second >= 0) channelInUse[j->second] = true;
			}
			for (unsigned int j = 0; j < OPL_MAX_CHANNELS; j++) {
				if (!channelInUse[j]) {
					// This is the channel to use
					rawChannel = j;
					this->midiChannelMap[trackIndex] = rawChannel;
					break;
				}
			}
			// This might set the map to -1 if there aren't enough free channels
			if (rawChannel == -1) std::cout << "OPL: All 18 channels are in use for MIDI, dropping a note.\n";
		}
		if (rawChannel < 0) {
			*chipIndex = OPL_INVALID_CHIP;
			*oplChannel = 0;
		} else if (rawChannel >= 9) {
			*chipIndex = 1;
			*oplChannel = rawChannel - 9;
		} else {
			*chipIndex = 0;
			*oplChannel = rawChannel;
		}
	}
	// Should never get this far
	assert(*oplChannel != 99);
	return;
}

void EventConverter_OPL::clearOPLChannel(unsigned int trackIndex)
{
	MIDIChannelMap::iterator i = this->midiChannelMap.find(trackIndex);
	if (i != this->midiChannelMap.end()) {
		this->midiChannelMap.erase(i);
	}
	return;
}

ext: cpp

max_stars_repo_name: pdpdds/sdldualsystem

max_issues_repo_name: pdpdds/sdldualsystem

max_forks_repo_name: pdpdds/sdldualsystem


text:
#ifndef PCP_COMMON_NORMALS_NORMAL_ESTIMATION_HPP
#define PCP_COMMON_NORMALS_NORMAL_ESTIMATION_HPP

/**
 * @file
 * @ingroup common
 */

#include "pcp/common/normals/normal.hpp"
#include "pcp/traits/point_map.hpp"
#include "pcp/traits/point_traits.hpp"

#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <cstdint>
#include <iterator>

namespace pcp {

/**
 * @ingroup common
 * @brief
 * Estimates the normal from a group of points using PCA.
 * @tparam ForwardIter Type of iterator to the points
 * @tparam PointViewMap Type satisfying PointViewMap concept
 * @tparam Normal Type of the normal to return
 * @param it Begin iterator to the points
 * @param end End iterator to the points
 * @param point_map The point view map property map
 * @return
 */
template <class ForwardIter, class PointViewMap, class Normal = pcp::normal_t>
Normal estimate_normal(ForwardIter it, ForwardIter end, PointViewMap const& point_map)
{
    using normal_type = Normal;

    static_assert(
        traits::is_point_view_map_v<PointViewMap, decltype(*it)>,
        "Type of point_map must satisfy PointViewMap concept");

    auto const n = std::distance(it, end);
    Eigen::Matrix3Xf V;
    V.resize(3, n);
    for (auto i = 0; i < n; ++i, ++it)
    {
        auto p              = point_map(*it);
        V.block(0, i, 3, 1) = Eigen::Vector3f(p.x(), p.y(), p.z());
    }

    Eigen::Vector3f const Mu      = V.rowwise().mean();
    Eigen::Matrix3Xf const Vprime = V.colwise() - Mu;
    Eigen::Matrix3f const Cov     = Vprime * Vprime.transpose();
    Eigen::SelfAdjointEigenSolver<decltype(Cov)> A(Cov);
    auto const l  = A.eigenvalues();
    auto const& X = A.eigenvectors();

    normal_type normal;
    // instead of sorting, just use 3 if statements
    // First eigenvalue is smallest
    if (l(0) <= l(1) && l(0) <= l(2))
    {
        normal = {X(0, 0), X(1, 0), X(2, 0)};
    }
    // Second eigenvalue is smallest
    if (l(1) <= l(0) && l(1) <= l(2))
    {
        normal = {X(0, 1), X(1, 1), X(2, 1)};
    }
    // Third eigenvalue is smallest
    if (l(2) <= l(0) && l(2) <= l(1))
    {
        normal = {X(0, 2), X(1, 2), X(2, 2)};
    }

    // normal is already normalized, since Eigen returns
    // normalized eigenvectors
    return normal;
}

} // namespace pcp

#endif // PCP_COMMON_NORMALS_NORMAL_ESTIMATION_HPP

max_stars_repo_name: Q-Minh/octree

max_issues_repo_name: Q-Minh/octree

max_forks_repo_name: Q-Minh/octree