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 @ 7:a4a336624f5a

History | View | Annotate | Download (4.08 KB)

1
/*
2

3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21

    
22
#pragma once
23

    
24
#include "cinder/Cinder.h"
25
#include "cinder/audio/Node.h"
26
#include "cinder/audio/dsp/RingBuffer.h"
27
#include "boost/optional.hpp"
28
#include "Messages.h"
29
#include "RingBufferPack.h"
30

    
31
#include <memory>
32

    
33
#include "PGranular.h"
34
#include "EnvASR.h"
35

    
36
typedef std::shared_ptr<class PGranularNode> PGranularNodeRef;
37
typedef ci::audio::dsp::RingBufferT<CursorTriggerMsg> CursorTriggerMsgRingBuffer;
38

    
39

    
40
struct RandomGenerator;
41

    
42
/*
43
A node in the Cinder audio graph that holds a PGranular 
44
*/
45
class PGranularNode : public ci::audio::Node
46
{
47
public:
48
    static const size_t kMaxVoices = 6;
49
    static const int kNoMidiNote = -50;
50

    
51
    explicit PGranularNode( ci::audio::Buffer *grainBuffer, CursorTriggerMsgRingBuffer &triggerRingBuffer );
52
    ~PGranularNode();
53

    
54
    /** Set selection size in samples */
55
    void setSelectionSize( size_t size )
56
    {
57
        mSelectionSize.set( size );
58
    }
59

    
60
    /** Set selection start in samples */
61
    void setSelectionStart( size_t start )
62
    {
63
        mSelectionStart.set( start );
64
    }
65

    
66
    void setGrainsDurationCoeff( double coeff )
67
    {
68
        mGrainDurationCoeff.set( coeff );
69
    }
70

    
71
    /* PGranularNode passes itself as trigger callback in PGranular */
72
    void operator()( char msgType, int ID );
73

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

    
76
protected:
77
    
78
    void initialize()                           override;
79

    
80
    void process( ci::audio::Buffer *buffer )   override;
81

    
82
private:
83

    
84
    // Wraps a std::atomic but get() returns a boost::optional that is set to a real value only when the atomic has changed. 
85
    //  It is used to avoid calling PGranulat setter methods with *  the same value at each audio callback.
86
    template< typename T>
87
    class LazyAtomic
88
    {
89
    public:
90
        LazyAtomic( T val ) :
91
            mAtomic( val ),
92
            mPreviousVal( val )
93
        {}
94

    
95
        void set( T val )
96
        {
97
            mAtomic = val;
98
        }
99

    
100
        boost::optional<T> get()
101
        {
102
            const T val = mAtomic;
103
            if ( val != mPreviousVal ){
104
                mPreviousVal = val;
105
                return val;
106
            }
107
            else{
108
                return boost::none;
109
            }
110
        }
111

    
112
    private:
113
        std::atomic<T> mAtomic;
114
        T mPreviousVal;
115
    };
116

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

    
120
    // pointers to PGranular objects 
121
    std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > > mPGranularLoop;
122
    std::array<std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > >, kMaxVoices> mPGranularNotes;
123
    // maps midi notes to pgranulars. When a noteOff is received maks sure the right PGranular is turned off
124
    std::array<int, kMaxVoices> mMidiNotes;
125

    
126
    // pointer to the random generator struct passed over to PGranular 
127
    std::unique_ptr< RandomGenerator > mRandomOffset;
128
    
129
    // buffer containing the recorder audio, to pass to PGranular in initialize()
130
    ci::audio::Buffer *mGrainBuffer;
131

    
132
    ci::audio::BufferRef mTempBuffer;
133

    
134
    CursorTriggerMsgRingBuffer &mTriggerRingBuffer;
135
    RingBufferPack<NoteMsg> mNoteMsgRingBufferPack;
136

    
137
    LazyAtomic<size_t> mSelectionSize;
138
    
139
    LazyAtomic<size_t> mSelectionStart;
140
    
141
    LazyAtomic<double> mGrainDurationCoeff;
142

    
143

    
144
};
145