Mercurial > hg > opencollidoscope
view CollidoscopeApp/include/PGranularNode.h @ 5:75b744078d66
added license
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Wed, 13 Jul 2016 16:06:46 +0200 |
parents | 7fb593d53361 |
children | 4dad0b810f18 |
line wrap: on
line source
/* Copyright (C) 2016 Queen Mary University of London Author: Fiore Martin This file is part of Collidoscope. Collidoscope 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/>. */ #pragma once #include "cinder/Cinder.h" #include "cinder/audio/Node.h" #include "cinder/audio/dsp/RingBuffer.h" #include "boost/optional.hpp" #include "Messages.h" #include "RingBufferPack.h" #include <memory> #include "PGranular.h" #include "EnvASR.h" typedef std::shared_ptr<class PGranularNode> PGranularNodeRef; typedef ci::audio::dsp::RingBufferT<CursorTriggerMsg> CursorTriggerMsgRingBuffer; struct RandomGenerator; /* A node in the Cinder audio graph that holds a PGranular */ class PGranularNode : public ci::audio::Node { public: static const size_t kMaxVoices = 6; static const int kNoMidiNote = -50; explicit PGranularNode( ci::audio::Buffer *grainBuffer, CursorTriggerMsgRingBuffer &triggerRingBuffer ); ~PGranularNode(); /** Set selection size in samples */ void setSelectionSize( size_t size ) { mSelectionSize.set( size ); } /** Set selection start in samples */ void setSelectionStart( size_t start ) { mSelectionStart.set( start ); } void setGrainsDurationCoeff( double coeff ) { mGrainDurationCoeff.set( coeff ); } /* PGranularNode passes itself as trigger callback in PGranular */ void operator()( char msgType, int ID ); ci::audio::dsp::RingBufferT<NoteMsg>& getNoteRingBuffer() { return mNoteMsgRingBufferPack.getBuffer(); } protected: void initialize() override; void process( ci::audio::Buffer *buffer ) override; private: // Wraps a std::atomic but get() returns a boost::optional that is set to a real value only when the atomic has changed. // It is used to avoid calling PGranulat setter methods with * the same value at each audio callback. template< typename T> class LazyAtomic { public: LazyAtomic( T val ) : mAtomic( val ), mPreviousVal( val ) {} void set( T val ) { mAtomic = val; } boost::optional<T> get() { const T val = mAtomic; if ( val != mPreviousVal ){ mPreviousVal = val; return val; } else{ return boost::none; } } private: std::atomic<T> mAtomic; T mPreviousVal; }; // creates or re-start a PGranular and sets the pitch according to the MIDI note passed as argument void handleNoteMsg( const NoteMsg &msg ); // pointers to PGranular objects std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > > mPGranularLoop; std::array<std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > >, kMaxVoices> mPGranularNotes; // maps midi notes to pgranulars. When a noteOff is received maks sure the right PGranular is turned off std::array<int, kMaxVoices> mMidiNotes; // pointer to the random generator struct passed over to PGranular std::unique_ptr< RandomGenerator > mRandomOffset; // buffer containing the recorder audio, to pass to PGranular in initialize() ci::audio::Buffer *mGrainBuffer; ci::audio::BufferRef mTempBuffer; CursorTriggerMsgRingBuffer &mTriggerRingBuffer; RingBufferPack<NoteMsg> mNoteMsgRingBufferPack; LazyAtomic<size_t> mSelectionSize; LazyAtomic<size_t> mSelectionStart; LazyAtomic<double> mGrainDurationCoeff; };