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 @ 16:4dad0b810f18

History | View | Annotate | Download (4.11 KB)

1 5:75b744078d66 f
/*
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 0:02467299402e f
#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 16:4dad0b810f18 f
A node in the Cinder audio graph that holds PGranulars for loop and keyboard playing
44 0:02467299402e f
*/
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 3:7fb593d53361 f
    /** Set selection size in samples */
55 0:02467299402e f
    void setSelectionSize( size_t size )
56
    {
57
        mSelectionSize.set( size );
58
    }
59
60 3:7fb593d53361 f
    /** Set selection start in samples */
61 0:02467299402e f
    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 3:7fb593d53361 f
    /* PGranularNode passes itself as trigger callback in PGranular */
72 0:02467299402e f
    void operator()( char msgType, int ID );
73
74
    ci::audio::dsp::RingBufferT<NoteMsg>& getNoteRingBuffer() { return mNoteMsgRingBufferPack.getBuffer(); }
75
76
protected:
77
78 5:75b744078d66 f
    void initialize()                           override;
79 0:02467299402e f
80 5:75b744078d66 f
    void process( ci::audio::Buffer *buffer )   override;
81 0:02467299402e f
82
private:
83
84 3:7fb593d53361 f
    // Wraps a std::atomic but get() returns a boost::optional that is set to a real value only when the atomic has changed.
85 16:4dad0b810f18 f
    //  It is used to avoid calling PGranular setter methods with the same value at each audio callback.
86 0:02467299402e f
    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 3:7fb593d53361 f
    // creates or re-start a PGranular and sets the pitch according to the MIDI note passed as argument
118 0:02467299402e f
    void handleNoteMsg( const NoteMsg &msg );
119
120 3:7fb593d53361 f
    // pointers to PGranular objects
121 0:02467299402e f
    std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > > mPGranularLoop;
122
    std::array<std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > >, kMaxVoices> mPGranularNotes;
123 16:4dad0b810f18 f
    // maps midi notes to pgranulars. When a noteOff is received makes sure the right PGranular is turned off
124 0:02467299402e f
    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 16:4dad0b810f18 f
    // buffer containing the recorded audio, to pass to PGranular in initialize()
130 0:02467299402e f
    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
};