To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / CollidoscopeApp / include / PGranularNode.h @ 4:ab6db404403a

History | View | Annotate | Download (3.34 KB)

1
#pragma once
2

    
3
#include "cinder/Cinder.h"
4
#include "cinder/audio/Node.h"
5
#include "cinder/audio/dsp/RingBuffer.h"
6
#include "boost/optional.hpp"
7
#include "Messages.h"
8
#include "RingBufferPack.h"
9

    
10
#include <memory>
11

    
12
#include "PGranular.h"
13
#include "EnvASR.h"
14

    
15
typedef std::shared_ptr<class PGranularNode> PGranularNodeRef;
16
typedef ci::audio::dsp::RingBufferT<CursorTriggerMsg> CursorTriggerMsgRingBuffer;
17

    
18

    
19
struct RandomGenerator;
20

    
21
/*
22
A node in the Cinder audio graph that holds a PGranular 
23
*/
24
class PGranularNode : public ci::audio::Node
25
{
26
public:
27
    static const size_t kMaxVoices = 6;
28
    static const int kNoMidiNote = -50;
29

    
30
    explicit PGranularNode( ci::audio::Buffer *grainBuffer, CursorTriggerMsgRingBuffer &triggerRingBuffer );
31
    ~PGranularNode();
32

    
33
    /** Set selection size in samples */
34
    void setSelectionSize( size_t size )
35
    {
36
        mSelectionSize.set( size );
37
    }
38

    
39
    /** Set selection start in samples */
40
    void setSelectionStart( size_t start )
41
    {
42
        mSelectionStart.set( start );
43
    }
44

    
45
    void setGrainsDurationCoeff( double coeff )
46
    {
47
        mGrainDurationCoeff.set( coeff );
48
    }
49

    
50
    /* PGranularNode passes itself as trigger callback in PGranular */
51
    void operator()( char msgType, int ID );
52

    
53
    ci::audio::dsp::RingBufferT<NoteMsg>& getNoteRingBuffer() { return mNoteMsgRingBufferPack.getBuffer(); }
54

    
55
protected:
56
    
57
    void initialize()                                                        override;
58

    
59
    void process( ci::audio::Buffer *buffer )        override;
60

    
61
private:
62

    
63
    // Wraps a std::atomic but get() returns a boost::optional that is set to a real value only when the atomic has changed. 
64
    //  It is used to avoid calling PGranulat setter methods with *  the same value at each audio callback.
65
    template< typename T>
66
    class LazyAtomic
67
    {
68
    public:
69
        LazyAtomic( T val ) :
70
            mAtomic( val ),
71
            mPreviousVal( val )
72
        {}
73

    
74
        void set( T val )
75
        {
76
            mAtomic = val;
77
        }
78

    
79
        boost::optional<T> get()
80
        {
81
            const T val = mAtomic;
82
            if ( val != mPreviousVal ){
83
                mPreviousVal = val;
84
                return val;
85
            }
86
            else{
87
                return boost::none;
88
            }
89
        }
90

    
91
    private:
92
        std::atomic<T> mAtomic;
93
        T mPreviousVal;
94
    };
95

    
96
    // creates or re-start a PGranular and sets the pitch according to the MIDI note passed as argument
97
    void handleNoteMsg( const NoteMsg &msg );
98

    
99
    // pointers to PGranular objects 
100
    std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > > mPGranularLoop;
101
    std::array<std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > >, kMaxVoices> mPGranularNotes;
102
    // maps midi notes to pgranulars. When a noteOff is received maks sure the right PGranular is turned off
103
    std::array<int, kMaxVoices> mMidiNotes;
104

    
105
    // pointer to the random generator struct passed over to PGranular 
106
    std::unique_ptr< RandomGenerator > mRandomOffset;
107
    
108
    // buffer containing the recorder audio, to pass to PGranular in initialize()
109
    ci::audio::Buffer *mGrainBuffer;
110

    
111
    ci::audio::BufferRef mTempBuffer;
112

    
113
    CursorTriggerMsgRingBuffer &mTriggerRingBuffer;
114
    RingBufferPack<NoteMsg> mNoteMsgRingBufferPack;
115

    
116
    LazyAtomic<size_t> mSelectionSize;
117
    
118
    LazyAtomic<size_t> mSelectionStart;
119
    
120
    LazyAtomic<double> mGrainDurationCoeff;
121

    
122

    
123
};
124