| #ifndef PRESET_CHOOSER_HPP |
| #define PRESET_CHOOSER_HPP |
| |
| #include "Preset.hpp" |
| |
| #include "PresetLoader.hpp" |
| #include "RandomNumberGenerators.hpp" |
| #include <cassert> |
| #include <memory> |
| #include <iostream> |
| |
| |
| class PresetChooser; |
| |
| /// A simple iterator class to traverse back and forth a preset directory |
| class PresetIterator { |
| |
| public: |
| PresetIterator() {} |
| |
| /// Instantiate a preset iterator at the given starting position |
| PresetIterator(std::size_t start); |
| |
| /// Move iterator forward |
| void operator++(); |
| |
| /// Move iterator backword |
| void operator--() ; |
| |
| /// Not equal comparator |
| bool operator !=(const PresetIterator & presetPos) const ; |
| |
| /// Equality comparator |
| bool operator ==(const PresetIterator & presetPos) const ; |
| |
| /// Returns an integer value representing the iterator position |
| /// @bug might become internal |
| /// \brief Returns the indexing value used by the current iterator. |
| std::size_t operator*() const; |
| |
| /// Allocate a new preset given this iterator's associated preset name |
| /// \param presetInputs the preset inputs to associate with the preset upon construction |
| /// \param presetOutputs the preset outputs to associate with the preset upon construction |
| /// \returns an autopointer of the newly allocated preset |
| std::auto_ptr<Preset> allocate(); |
| |
| /// Set the chooser asocciated with this iterator |
| void setChooser(const PresetChooser & chooser); |
| |
| private: |
| std::size_t _currentIndex; |
| const PresetChooser * _presetChooser; |
| |
| }; |
| |
| /// Provides functions and iterators to select presets. Requires a preset loader upon construction |
| class PresetChooser { |
| |
| public: |
| typedef PresetIterator iterator; |
| |
| /// Initializes a chooser with an established preset loader. |
| /// \param presetLoader an initialized preset loader to choose presets from |
| /// \note The preset loader is refreshed via events or otherwise outside this class's scope |
| PresetChooser(const PresetLoader & presetLoader, bool softCutRatingsEnabled); |
| |
| inline void setSoftCutRatingsEnabled(bool enabled) { |
| _softCutRatingsEnabled = enabled; |
| } |
| |
| /// Choose a preset via the passed in index. Must be between 0 and num valid presets in directory |
| /// \param index An index lying in the interval [0, this->getNumPresets()) |
| /// \param presetInputs the preset inputs to associate with the preset upon construction |
| /// \param presetOutputs the preset outputs to associate with the preset upon construction |
| /// \returns an auto pointer of the newly allocated preset |
| std::auto_ptr<Preset> directoryIndex(std::size_t index) const; |
| |
| /// Gets the number of presets last believed to exist in the preset loader's filename collection |
| /// \returns the number of presets in the collection |
| std::size_t size() const; |
| |
| /// An STL-esque iterator to begin traversing presets from a directory |
| /// \param index the index to begin iterating at. Assumed valid between [0, num presets) |
| /// \returns the position of the first preset in the collection |
| PresetIterator begin(unsigned int index) const; |
| |
| /// An STL-esque iterator to begin traversing presets from a directory |
| /// \returns the position of the first preset in the collection |
| PresetIterator begin(); |
| |
| /// An STL-esque iterator to retrieve an end position from a directory |
| /// \returns the end position of the collection |
| PresetIterator end() const; |
| |
| /// Perform a weighted sample to select a preset (uses preset rating values) |
| /// \returns an iterator to the randomly selected preset |
| iterator weightedRandom(bool hardCut) const; |
| |
| /// True if no presets in directory |
| bool empty() const; |
| |
| |
| inline void nextPreset(PresetIterator & presetPos); |
| inline void previousPreset(PresetIterator & presetPos); |
| |
| private: |
| std::vector<float> sampleWeights; |
| const PresetLoader * _presetLoader; |
| bool _softCutRatingsEnabled; |
| }; |
| |
| |
| inline |
| PresetChooser::PresetChooser ( |
| const PresetLoader &presetLoader, |
| bool softCutRatingsEnabled |
| ) |
| : _presetLoader(&presetLoader), |
| _softCutRatingsEnabled(softCutRatingsEnabled) |
| { |
| |
| } |
| |
| inline std::size_t |
| PresetChooser::size() const |
| { |
| return _presetLoader->size(); |
| } |
| |
| inline void |
| PresetIterator::setChooser(const PresetChooser & chooser) |
| { |
| _presetChooser = &chooser; |
| } |
| |
| inline std::size_t |
| PresetIterator::operator*() const |
| { |
| return _currentIndex; |
| } |
| |
| inline PresetIterator::PresetIterator(std::size_t start):_currentIndex(start) {} |
| |
| inline void |
| PresetIterator::operator++() |
| { |
| assert(_currentIndex < _presetChooser->size()); |
| _currentIndex++; |
| } |
| |
| inline void |
| PresetIterator::operator--() |
| { |
| assert(_currentIndex > 0); |
| _currentIndex--; |
| } |
| |
| inline bool |
| PresetIterator::operator !=(const PresetIterator & presetPos) const |
| { |
| return (*presetPos != **this); |
| } |
| |
| |
| inline bool |
| PresetIterator::operator ==(const PresetIterator & presetPos) const |
| { |
| return (*presetPos == **this); |
| } |
| |
| inline std::auto_ptr<Preset> |
| PresetIterator::allocate() |
| { |
| return _presetChooser->directoryIndex(_currentIndex); |
| } |
| |
| inline void |
| PresetChooser::nextPreset(PresetIterator & presetPos) |
| { |
| if (this->empty()) { |
| return; |
| } |
| // Case: idle preset currently running, selected first preset of chooser |
| else if (presetPos == this->end()) |
| presetPos = this->begin(); |
| else |
| ++(presetPos); |
| |
| // Case: already at last preset, loop to beginning |
| if (((presetPos) == this->end())) { |
| presetPos = this->begin(); |
| } |
| } |
| |
| |
| inline void |
| PresetChooser::previousPreset(PresetIterator & presetPos) |
| { |
| if (this->empty()) |
| return; |
| |
| // Case: idle preset currently running, selected last preset of chooser |
| else if (presetPos == this->end()) { |
| --(presetPos); |
| } |
| else if (presetPos != this->begin()) { |
| --(presetPos); |
| } |
| else { |
| presetPos = this->end(); |
| --(presetPos); |
| } |
| } |
| |
| inline PresetIterator |
| PresetChooser::begin() |
| { |
| PresetIterator pos(0); |
| pos.setChooser(*this); |
| return pos; |
| } |
| |
| inline PresetIterator |
| PresetChooser::begin(unsigned int index) const |
| { |
| PresetIterator pos(index); |
| pos.setChooser(*this); |
| return pos; |
| } |
| |
| inline PresetIterator |
| PresetChooser::end() const |
| { |
| PresetIterator pos(_presetLoader->size()); |
| pos.setChooser(*this); |
| return pos; |
| } |
| |
| |
| inline bool |
| PresetChooser::empty() const |
| { |
| return _presetLoader->size() == 0; |
| } |
| |
| inline std::auto_ptr<Preset> |
| PresetChooser::directoryIndex(std::size_t index) const |
| { |
| return _presetLoader->loadPreset(index); |
| } |
| |
| |
| inline PresetChooser::iterator |
| PresetChooser::weightedRandom(bool hardCut) const |
| { |
| // TODO make a sophisticated function object interface to determine why a certain rating |
| // category is chosen, or weighted distribution thereover. |
| const PresetRatingType ratingType = hardCut || (!_softCutRatingsEnabled) ? |
| HARD_CUT_RATING_TYPE : |
| SOFT_CUT_RATING_TYPE; |
| |
| const std::size_t ratingsTypeIndex = static_cast<std::size_t>(ratingType); |
| |
| const std::vector<int> & weights = _presetLoader->getPresetRatings()[ratingsTypeIndex]; |
| |
| const std::size_t index = RandomNumberGenerators::weightedRandom |
| (weights, |
| _presetLoader->getPresetRatingsSums()[ratingsTypeIndex]); |
| |
| return begin(index); |
| } |
| |
| #endif |