Revision 0:02467299402e CollidoscopeApp

View differences:

CollidoscopeApp/include/AudioEngine.h
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 1
#pragma once
23 2

  
24 3
#include <array>
......
35 14
#include "Config.h"
36 15

  
37 16

  
38
/**
39
 * Audio engine of the application. It uses the Cinder library to process audio in input and output. 
40
 * The audio engine manages both waves. All methods have a waveIndx parameter to address a specific wave.
41
 */ 
42 17
class AudioEngine
43 18
{
44 19
public:
......
51 26
    AudioEngine( const AudioEngine &copy ) = delete;
52 27
    AudioEngine & operator=(const AudioEngine &copy) = delete;
53 28

  
54
    /**
55
    * Set up of the audio engine. 
56
    */
57 29
    void setup( const Config& Config );
58 30

  
59 31
    size_t getSampleRate();
......
68 40

  
69 41
    void noteOff( size_t waveIdx, int note );
70 42

  
71
    /**
72
    * Returns the number of elements available to read in the wave ring buffer.
73
    * The wave ring buffer is used to pass the size of the wave chunks from the audio thread to the graphic thread, 
74
    * when a new wave is recorded.
75
    */ 
76 43
    size_t getRecordWaveAvailable( size_t index );
77
    /**
78
    * Called from the graphic thread. Reads \a count elements from the wave ring buffer into \a buffer.
79
    * The wave ring buffer is used to pass the size of the wave chunks from the audio thread to the graphic thread, 
80
    * when a new wave is recorded.
81
    *
82
    */
83
    bool readRecordWave( size_t waveIdx, RecordWaveMsg* buffer, size_t count );
44

  
45
    bool readRecordWave( size_t waveIdx, RecordWaveMsg*, size_t count );
84 46

  
85 47
    void setSelectionSize( size_t waveIdx, size_t size );
86 48

  
......
92 54

  
93 55
    void checkCursorTriggers( size_t waveIdx, std::vector<CursorTriggerMsg>& cursorTriggers );
94 56

  
95
    /**
96
     * Returns a const reference to the audio output buffer. This is the buffer that is sent off to the audio interface at each audio cycle. 
97
     * It is used in the graphic thread to draw the oscilloscope.
98
     */
99 57
    const ci::audio::Buffer& getAudioOutputBuffer( size_t waveIdx ) const;
100 58

  
101 59

  
......
106 64
    // nodes for recording audio input into buffer. Also sends chunks information through 
107 65
    // non-blocking queue 
108 66
    std::array< BufferToWaveRecorderNodeRef, NUM_WAVES > mBufferRecorderNodes;
109
    // pgranulars wrapped in a Cinder::Node 
67
    // pgranulars for loop synths 
110 68
    std::array< PGranularNodeRef, NUM_WAVES > mPGranularNodes;
111 69

  
112 70

  
......
118 76

  
119 77
    std::array< std::unique_ptr< RingBufferPack<CursorTriggerMsg> >, NUM_WAVES > mCursorTriggerRingBufferPacks;
120 78

  
121
};
79
};
CollidoscopeApp/include/BufferToWaveRecorderNode.h
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
 This file incorporates work covered by the following copyright and permission notice: 
22

  
23
    Copyright (c) 2014, The Cinder Project
24

  
25
    This code is intended to be used with the Cinder C++ library, http://libcinder.org
26

  
27
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that
28
    the following conditions are met:
29

  
30
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
31
    the following disclaimer.
32
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
33
    the following disclaimer in the documentation and/or other materials provided with the distribution.
34

  
35
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
36
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
38
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
39
    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
    POSSIBILITY OF SUCH DAMAGE.
43
 
44
*/
45

  
46 1
#pragma once
47 2

  
48 3
#include "cinder/Cinder.h"
......
53 8

  
54 9
#include "Messages.h"
55 10

  
56
typedef std::shared_ptr<class BufferToWaveRecorderNode> BufferToWaveRecorderNodeRef;
11
typedef std::shared_ptr<class BufferToWaveRecorderNode>	BufferToWaveRecorderNodeRef;
57 12

  
58 13
typedef ci::audio::dsp::RingBufferT<RecordWaveMsg> RecordWaveMsgRingBuffer;
59 14

  
60
/**
61
 * A \a Node in the audio graph of the Cinder audio library that records input in a buffer.
62
 *
63
 * This class is similar to \a cinder::audio::BufferRecorderNode (it's a derivative work of this class indeed) but it has an additional feature:
64
 * when recording, it uses the audio input samples to compute the size values of the visual chunks. 
65
 * The chunks values are stored in a ring buffer and fetched by the graphic thread to paint the wave as it gets recorded.
66
 *
67
 */
15

  
68 16
class BufferToWaveRecorderNode : public ci::audio::SampleRecorderNode {
69 17
public:
70 18

  
......
88 36
    void setNumSeconds(double numSeconds, bool shrinkToFit = false);
89 37

  
90 38
    //! Returns the length of the recording buffer in frames.
91
    size_t      getNumFrames() const    { return mRecorderBuffer.getNumFrames(); }
39
    size_t		getNumFrames() const	{ return mRecorderBuffer.getNumFrames(); }
92 40
    //! Returns the length of the recording buffer in seconds.
93
    double      getNumSeconds() const;
41
    double		getNumSeconds() const;
94 42

  
95 43
    //! \brief Returns a copy of the recored samples, up to the current write position.
96 44
    //!
97 45
    //! This method is non locking, and as such any resizing calls must be performed on the same thread or be otherwise synchronized.
98
    ci::audio::BufferRef    getRecordedCopy() const;
46
    ci::audio::BufferRef	getRecordedCopy() const;
99 47

  
100 48
    //! \brief Writes the currently recorded samples to a file at \a filePath
101 49
    //!
......
106 54
    //! Returns the frame of the last buffer overrun or 0 if none since the last time this method was called. When this happens, it means the recorded buffer probably has skipped some frames.
107 55
    uint64_t getLastOverrun();
108 56

  
109
    //! returns a reference to the ring buffer when the size values of the chunks is stored, when a new wave is recorder
110 57
    RecordWaveMsgRingBuffer& getRingBuffer() { return mRingBuffer; }
111 58

  
112
    //!returns a pointer to the buffer where the audio is recorder. This is used by the PGranular to create the granular synthesis 
113 59
    ci::audio::Buffer* getRecorderBuffer() { return &mRecorderBuffer; }
114 60

  
115 61

  
116 62
protected:
117
    void initialize()               override;
118
    void process(ci::audio::Buffer *buffer) override;
63
    void initialize()				override;
64
    void process(ci::audio::Buffer *buffer)	override;
119 65

  
120 66
    void initBuffers(size_t numFrames);
121 67

  
122 68
    static const float kMinAudioVal; 
123 69
    static const float kMaxAudioVal;
124 70

  
125
    ci::audio::BufferDynamic        mRecorderBuffer;
126
    ci::audio::BufferDynamicRef     mCopiedBuffer;
127
    std::atomic<uint64_t>   mLastOverrun;
71
    ci::audio::BufferDynamic		mRecorderBuffer;
72
    ci::audio::BufferDynamicRef		mCopiedBuffer;
73
    std::atomic<uint64_t>	mLastOverrun;
128 74

  
129 75
    RecordWaveMsgRingBuffer mRingBuffer;
130 76

  
CollidoscopeApp/include/Chunk.h
1
/*
2

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

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

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

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

  
22
*/
23

  
24 1

  
25 2
#pragma once
26 3

  
......
29 6

  
30 7
class DrawInfo;
31 8

  
32
/**
33
 *
34
 * A chunk of audio in Collidoscope low-fi visual wave. 
35
 *
36
 * The visual wave of Collidoscope is made out of a number of bars that mimic, in a low-fi fashion, the typical waveform-based representation of audio.
37
 * A Chunk is one of the bars of the visual wave. 
38
 *
39
 */
40

  
41 9
class Chunk
42 10
{
43 11

  
......
46 14
    const static float kWidth;
47 15
    const static float kHalfWidth;
48 16

  
49
    /**
50
     * Constructor, takes as argument the index of this chunk in the wave that contains it
51
     */ 
52
    Chunk( size_t index );
17
	Chunk( size_t index );
53 18

  
54
    /**
55
     * Sets the top value of this chunk. The value is passed in audio coordinates : [-1.0, 1.0]
56
     */
57 19
    void inline setTop(float t) { mAudioTop = t; mAnimate = 0.0f; mResetting = false; /* startes the animation to crate a chunk */ }
58
    /**
59
     * Sets the bottom value of this chunk. The value is passed in audio coordinates : [-1.0, 1.0]
60
     */
61 20
    void inline setBottom(float b) { mAudioBottom = b; mAnimate = 0.0f; mResetting = false; }
62
    /**
63
     * Get the top value of this chunk. The value is returned in audio coordinates : [-1.0, 1.0]
64
     */
65 21
    float inline getTop() const { return mAudioTop; }
66
    /**
67
     * Get the bottom value of this chunk. The value is returned in audio coordinates : [-1.0, 1.0]
68
     */
69 22
    float inline getBottom() const { return mAudioBottom; }
70 23

  
71
    /**
72
     * Reset this chunks. When a chunk is reset, it starts shrinking until it disappears or setTop/setBottom are called again
73
     *
74
     */ 
75
    void reset(){
76
        mResetting = true;
77
    }
24
	void reset(){
25
		mResetting = true;
26
	}
78 27

  
79
    /**
80
     * Called in the graphic loop. It update this chunk. 
81
     */ 
82 28
    void update( const DrawInfo& di );
83 29

  
84
    /**
85
     * Called in the graphic loop. It draws this chunk. 
86
     */ 
87 30
    void draw( const DrawInfo& di, ci::gl::BatchRef &batch );
88 31

  
89
    /**
90
     * Called in the graphic loop. It draws this chunk all the way to the bottom of the screen. 
91
     * This method is called when the chunk is the first or last in a selection. 
92
     */ 
93 32
    void drawBar( const DrawInfo& di, ci::gl::BatchRef &batch );
94 33

  
95
    /**
96
     * Informs this chunk that it's the first chunk of the selection.
97
     */ 
98
    void setAsSelectionStart(bool start){
99
        isSelectionStart = start;
100
    }
34
	void setAsSelectionStart(bool start){
35
		isSelectionStart = start;
36
	}
101 37

  
102
    /**
103
     * Informs this chunk that it's the last chunk of the selection.
104
     */ 
105
    void setAsSelectionEnd(bool end){
106
        isSelectionEnd = end;
107
    }
38
	void setAsSelectionEnd(bool end){
39
		isSelectionEnd = end;
40
	}
108 41

  
109 42
private:
110 43

  
CollidoscopeApp/include/Config.h
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 1
#pragma once
23 2

  
24 3
#include <string>
......
27 6
#include "cinder/Xml.h"
28 7

  
29 8

  
30
/**
31
 * Configuration class gathers in one place all the values recided at runtime
32
 *
33
 * Reading the configuration from an XML file is partially implemented but not used at the moment
34
 *
35
 */ 
36 9
class Config
37 10
{
38 11
public:
......
48 21

  
49 22
    std::string getInputDeviceKey() const
50 23
    {
51
        return mAudioInputDeviceKey; 
24
        return mAudioInputDeviceKey;  // Komplete 1/2
25
        //return "{0.0.1.00000000}.{a043bc8c-1dd1-4c94-82b4-ad8320cac5a5}"; // Komplete 3/4 
26
        //return "{0.0.1.00000000}.{828b681b-cc0c-44e1-93c9-5f1f46f5926f}"; // Realtek 
52 27
    }
53 28

  
54
    /**
55
     * Returns number of chunks in a wave 
56
     */ 
57 29
    std::size_t getNumChunks() const
58 30
    {
59 31
        return mNumChunks;
60 32
    }
61 33

  
62
    /** returns wave lenght in seconds */
34
    /* return wave lenght in seconds */
63 35
    double getWaveLen() const
64 36
    {
65 37
        return mWaveLen;
66 38
    }
67 39

  
68
    /**
69
     * Returns wave selection color
70
     */ 
71 40
    ci::Color getWaveSelectionColor(size_t waveIdx) const
72 41
    {
73 42
        if (waveIdx == 0){
......
78 47
        }
79 48
    }
80 49

  
81
    /**
82
     * The size of the ring buffer used to trigger a visual cursor from the audio thread when a new grain is created
83
     */ 
84 50
    std::size_t getCursorTriggerMessageBufSize() const
85 51
    {
86 52
        return 512;
87 53
    }
88 54

  
89
    /** returns the index of the wave associated to the MIDI channel passed as argument */
55
    // returns the index of the wave associated to the MIDI channel passed as argument 
90 56
    size_t getWaveForMIDIChannel( unsigned char channelIdx )
91 57
    {
92 58
        return channelIdx;
59
        /*for ( int i = 0; i < NUM_WAVES; i++ ){
60
            if ( channelIdx == mMidiChannels[i] )
61
                return i;
62
        }*/
93 63
    }
94 64

  
95 65
    double getMaxGrainDurationCoeff() const
......
112 82
        return 6;
113 83
    }
114 84

  
115
    /**
116
     * Returns the maximum size of a wave selection in number of chunks.
117
     */ 
118 85
    size_t getMaxSelectionNumChunks() const
119 86
    {
120 87
        return 37;
121 88
    }
122 89

  
123
    /**
124
     * The value returned is used when creating the oscilloscope. 
125
     * The oscilloscope represents the audio output buffer graphically. However it doesn't need to be as refined as the 
126
     * audio wave and it's downsampled using the following formula :  (number of oscilloscope points) = (size of audio output buffer) / getOscilloscopeNumPointsDivider() 
127
     */ 
128 90
    size_t getOscilloscopeNumPointsDivider() const
129 91
    {
130 92
        return 4;
CollidoscopeApp/include/DrawInfo.h
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 1
#pragma once
23 2

  
24 3
#include "cinder/Area.h"
25 4

  
26
/**
27
 * The DrawInfo class holds size information for drawing the waves in the screen. 
28
 * Every time the screen is resized the draw info is updated with the new information about the window size.
29
 *
30
 * Every wave has its own drawInfo.
31
 *
32
 */ 
33 5
class DrawInfo
34 6
{
35 7
public:
36 8

  
37
    /**
38
     * Constructor. Takes the index of the wave as argument.
39
     */ 
40 9
    DrawInfo( size_t waveIndex ):
41 10
        mWaveIndex( waveIndex ),
42 11
        mWindowWidth(0),
......
45 14
        mShrinkFactor(1)
46 15
    {}
47 16

  
48
    /**
49
     * Reset this DrawInfo using the new bounding area for the wave.  \a shrinkFactor 
50
     * makes the wave shrink on the y axis with respect to the area. A factor 1 makes the wave as big as the area, whereas a factor >1 makes it shrink.
51
     */ 
52 17
    void reset( const ci::Area &bounds, float shrinkFactor )
53 18
    {
54 19
        mWindowWidth = bounds.getWidth();
......
57 22
        mShrinkFactor = shrinkFactor;
58 23
    }
59 24

  
60
    /**
61
     * Maps a value in the audio space [-1.0, 1.0] to a position on the y axis of this DrawInfo's bounding area.
62
     *
63
     */ 
64
    float audioToHeigt(float audioSample) const {
25
	float audioToHeigt(float audioSample) const {
65 26
        /* clip into range [-1.1] */
66 27
        if (audioSample < -1.0f) {
67 28
            audioSample = -1.0f;
......
71 32
        }
72 33

  
73 34
        /* map from [-1,1] to [0,1] */
74
        float ratio = (audioSample - (-1.0f)) * 0.5f; // 2 = 1 - (-1) 
35
		float ratio = (audioSample - (-1.0f)) * 0.5f; // 2 = 1 - (-1) 
75 36

  
76
        /* get bottom and add the scaled height */
37
		/* get bottom and add the scaled height */
77 38
        return ratio * mSelectionBarHeight; //remove  bounds.getY1() bound only needed for size of tier
78
    }
39
	}
79 40

  
80 41
    float getMaxChunkHeight() const 
81 42
    {
......
87 48
        return mSelectionBarHeight;
88 49
    }
89 50

  
90
    /**
91
     * Returns the center position on the y axis of this DrawInfo's the bounding area. 
92
     */ 
93 51
    int32_t getWaveCenterY() const
94 52
    {
95 53
        if ( mWaveIndex == 0 )
96
            return mWindowHeight - ( mWindowHeight / ( 2 * NUM_WAVES ) ) + 1;
54
            return mWindowHeight * 0.75f + 1;
97 55
        else
98 56
            return mWindowHeight / (NUM_WAVES * 2);
99 57
    }
100 58

  
101
    /**
102
     * Flips y according to the index of the wave. It is needed because the second wave in collidoscope is drawn upside down in the screen.
103
     */ 
104
    int flipY(int y) const 
59
	int flipY(int y) const 
105 60
    {
106 61
        if ( mWaveIndex == 0)
107
            return mWindowHeight - y;
62
		    return mWindowHeight - y /*+ 24*/;
108 63
        else
109
            return y;
110
    }
64
            return y /*- 24*/;
65
	}
111 66

  
112
    /**
113
     * Returns x. not used at the moment.
114
     *
115
     */ 
116
    int flipX(int x) const
67
	int flipX(int x) const
117 68
    {
118 69
        return x;
119
    }
70
	}
120 71

  
121 72

  
122 73
    // how much the wave is shrunk on the y axis with respect to the wave's tier 
......
135 86
        return mWindowHeight;
136 87
    }
137 88

  
138
    /**
139
     * Draw infos cannot be copied and should be passed as const reference.
140
     */ 
141 89
    DrawInfo( const DrawInfo &original ) = delete;
142 90
    DrawInfo & operator=( const DrawInfo &original ) = delete;
143 91

  
CollidoscopeApp/include/EnvASR.h
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin, based on CCRMA STK ADSR.h (https://ccrma.stanford.edu/software/stk/classstk_1_1ADSR.html) 
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
 This file incorporates work covered by the following copyright and permission notice:
22

  
23
    The Synthesis ToolKit in C++ (STK)
24

  
25
    Copyright (c) 1995--2016 Perry R. Cook and Gary P. Scavone
26

  
27
    Permission is hereby granted, free of charge, to any person obtaining
28
    a copy of this software and associated documentation files (the
29
    "Software"), to deal in the Software without restriction, including
30
    without limitation the rights to use, copy, modify, merge, publish,
31
    distribute, sublicense, and/or sell copies of the Software, and to
32
    permit persons to whom the Software is furnished to do so, subject to
33
    the following conditions:
34

  
35
    The above copyright notice and this permission notice shall be
36
    included in all copies or substantial portions of the Software.
37

  
38
    Any person wishing to distribute modifications to the Software is
39
    asked to send the modifications to the original developer so that they
40
    can be incorporated into the canonical version.  This is, however, not
41
    a binding provision of this license.
42

  
43
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
44
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
45
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
46
    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
47
    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
48
    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
49
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
50

  
51
*/
52

  
53 1
#pragma once 
54 2

  
55 3
namespace collidoscope {
56 4

  
57

  
58
/* 
59
 * An ASR envelope with linear shape. It is modeled after the STK envelope classes.
60
 * The tick() method advances the computation of the envelope one sample and returns the computed sample
61
 * The class is templated for the type of the samples that each tick of the envelope produces. 
62
 *
63
 * Client classes can set/get the current state of the envelope with the
64
 * respective getter/setter methods
65
 *
66
 */
67 5
template <typename T>
68 6
class EnvASR
69 7
{
70 8
public:
71 9

  
72
    /** Possible states of the envelope. Idle means the envelope ouputs 0 */
73 10
    enum class State {
74 11
        eAttack,
75 12
        eSustain,
......
93 30
        mReleaseRate = T( 1.0 ) / (releaseTime * sampleRate);
94 31
    }
95 32

  
96
    /** Produces one sample worth of envelope */
97 33
    T tick()
98 34
    {
99 35

  
......
152 88
};
153 89

  
154 90

  
155
}
91
}
CollidoscopeApp/include/Log.h
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 1
#pragma once 
23 2

  
24 3

  
25
/**
26
 * Utility function to log errors using the cinder::log library.
27
 * Errors are logged to collidoscope_error.log file. 
28
 *
29
 */ 
4

  
30 5
void logError( const std::string &errorMsg );
31 6

  
32 7

  
33
/**
34
 * Utility function to log info using the cinder::log library.
35
 * Errors are logged to the terminal. Used only for debugging.
36
 *
37
 */ 
38
void logInfo( const std::string &infoMsg );
8
void logInfo( const std::string &infoMsg );
CollidoscopeApp/include/MIDI.h
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 1
#pragma once
23 2

  
24 3
#include "RtMidi.h"
......
31 10

  
32 11
namespace collidoscope {
33 12

  
34
// Exception thrown by MIDI system
13

  
35 14
class MIDIException : public std::exception
36 15
{
37 16
public:
......
50 29
    std::string mMessage;
51 30
};
52 31

  
53
/**
54
 * A MIDI message 
55
 */ 
56 32
class MIDIMessage
57 33
{
58 34
    friend class MIDI;
......
64 40

  
65 41
    unsigned char getChannel() { return mChannel; }
66 42

  
67
    /**
68
     * First byte of MIDI data 
69
     */ 
70 43
    unsigned char getData_1() { return mData1; }
71 44

  
72
    /**
73
     * Second byte of MIDI data 
74
     */ 
75 45
    unsigned char getData_2() { return mData2; }
76 46

  
77 47
private:
......
84 54
    
85 55
};
86 56

  
87
/**
88
 * Handles MIDI messages from the keyboards and Teensy. It uses RtMidi library.
89
 *
90
 */ 
57

  
91 58
class MIDI
92 59
{
93 60

  
......
98 65

  
99 66
    void setup( const Config& );
100 67

  
101
    /**
102
     * Check new incoming messages and stores them into the vector passed as argument by reference.
103
     */ 
104 68
    void checkMessages( std::vector< MIDIMessage >&  );
105 69

  
106 70
private:
107 71

  
108
    // callback passed to RtMidi library 
109 72
    static void RtMidiInCallback( double deltatime, std::vector<unsigned char> *message, void *userData );
110 73

  
111
    // parse RtMidi messages and turns them into more readable collidoscope::MIDIMessages
112 74
    MIDIMessage parseRtMidiMessage( std::vector<unsigned char> *message );
113 75

  
114
    // messages to pass to checkMessages caller 
76
    // messages to pass to checkMessages caller
115 77
    std::vector< MIDIMessage > mMIDIMessages;
116
    // use specific variables for pitch bend messages. Pitch bend messages are coming 
117
    // from the strip sensors that are very jerky and send a lot of values. So instead 
118
    // of saving all the messages in mMIDIMessages just save the last received in mPitchBendMessages 
119
    // and optimize away redundant messages.
120 78
    std::array< MIDIMessage, NUM_WAVES > mPitchBendMessages;
121
    // Same principle as mPitchBendMessages
122 79
    std::array< MIDIMessage, NUM_WAVES > mFilterMessages;
123 80

  
124
    // vector containing all the MIDI input devices detected.
81

  
82

  
125 83
    std::vector< std::unique_ptr <RtMidiIn> > mInputs;
126
    // Used for mutual access to the MIDI messages by the MIDI thread and the graphic thread.  
127 84
    std::mutex mMutex;
128 85
};
129 86

  
CollidoscopeApp/include/Messages.h
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 1
#pragma once
23 2

  
24
/**
25
 * Enumeration of all the possible commands exchanged between audio thread and graphic thread.
26
 *
27
 */ 
3

  
28 4
enum class Command {
29 5
    // message carrying info about one chunk of recorder audio. 
30 6
    WAVE_CHUNK,
31 7
    // message sent when a new recording starts. The gui resets the wave upon receiving it. 
32 8
    WAVE_START,
33 9

  
34
    // new grain created 
35 10
    TRIGGER_UPDATE,
36
    // synth became idle
37 11
    TRIGGER_END,
38 12

  
39 13
    NOTE_ON,
......
43 17
    LOOP_OFF
44 18
};
45 19

  
46
/** Message sent from the audio thread to the graphic wave when a new wave is recorded. 
47
 *  
48
 *  The graphic thread sets the chunks of the wave to reflect the level of the recorded audio. 
49
 *  The algorithm takes the maximum and minimum value of a group of samples and this becomes the top and bottom of the chunk.
50
 *  The message carries also the index of the chunk it refers to 
51
 */
20
/* Messages sent from the audio thread to the graphic wave. 
21
   This includes the wave chunks when the audio is recorder in the buffer and 
22
   the cursor position when the grains are reset.
23
*/
52 24
struct RecordWaveMsg
53 25
{
54
    Command cmd; // WAVE_CHUNK or WAVE_START
26
    Command cmd;
55 27
    std::size_t index;
56 28
    float arg1;
57 29
    float arg2;
58 30
};
59 31

  
60
/**
61
 * Utility function to create a new RecordWaveMsg.
62
 */ 
32

  
63 33
inline RecordWaveMsg makeRecordWaveMsg( Command cmd, std::size_t index, float arg1, float arg2 )
64 34
{
65 35
    RecordWaveMsg msg;
......
71 41
    return msg;
72 42
}
73 43

  
74
/**
75
 * Message sent from the audio thread to the graphic thread when a new grain is triggered in the granular synthesizer. 
76
 * This creates a new cursor that travels from the beginning to the end of the selection to graphically represent the evolution of the grain in time. 
77
 *
78
 */ 
44

  
79 45
struct CursorTriggerMsg
80 46
{
81
    Command cmd; // TRIGGER_UPDATE or TRIGGER_END
47
    Command cmd;
82 48
    int synthID;
83 49
};
84 50

  
85
/**
86
 * Utility function to create a new CursorTriggerMsg.
87
 */ 
88 51
inline CursorTriggerMsg makeCursorTriggerMsg( Command cmd, std::uint8_t synthID )
89 52
{
90 53
    CursorTriggerMsg msg;
......
95 58
    return msg;
96 59
}
97 60

  
98
/**
99
 * Message sent from the graphic (main) thread to the audio thread to start a new voice of the granular synthesizer.
100
 */ 
101 61
struct NoteMsg
102 62
{
103
    Command cmd; // NOTE_ON/OFF ot LOOP_ON/OFF 
63
    Command cmd;
104 64
    int midiNote;
105 65
    double rate;
106 66
};
107 67

  
108
/**
109
 * Utility function to create a new NoteMsg.
110
 */ 
111 68
inline NoteMsg makeNoteMsg( Command cmd, int midiNote, double rate )
112 69
{
113 70
    NoteMsg msg;
......
117 74
    msg.rate = rate;
118 75

  
119 76
    return msg;
120
}
77
}
CollidoscopeApp/include/Oscilloscope.h
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 1
#pragma once
23 2

  
24 3
#include "cinder/gl/gl.h"
25 4

  
26 5
#include "DrawInfo.h"
27 6

  
28

  
29

  
30
/**
31
 * The oscilloscope that oscillates when Collidoscope is played 
32
 */ 
33 7
class Oscilloscope
34 8
{
35 9

  
36 10
public:
37 11

  
38
    /**
39
     * Constructor, accepts as argument the number of points that make up the oscilloscope line 
40
     */ 
41 12
    Oscilloscope( size_t numPoints ):
42 13
        mNumPoints( numPoints ),
43 14
        mLine( std::vector<ci::vec2>( numPoints, ci::vec2() ) )
44 15
        {}
45 16

  
46
    /**
47
     * Sets the value of a point of the oscilloscope. The value is passed in audio coordinates [-1.0, 1.0].
48
     * A reference to DrawInfo is passed to calculate the graphic coordinate of the point based on the audio values passed. 
49
     */ 
50 17
    void  setPoint( int index, float audioVal, const DrawInfo &di ){
51 18

  
52 19
        if ( audioVal > 1.0f ){
......
57 24
        }
58 25

  
59 26
        audioVal *= 0.8f;
60
        // map audio val from [-1.0, 1.0] to [0.0, 1.0]
61
        // then map the value obtained to the height of the wave tier ( window height / NUM_WAVES ) 
27
        // this yRatio is for the bottom scope, the top will be drawn with a translation/4
28
        // because it's half of the half of the tier where the wave is drawn  
62 29
        float yRatio = ((1 + audioVal) / 2.0f) * (di.getWindowHeight() / NUM_WAVES );
63 30
        float xRatio = index * (di.getWindowWidth() / (float)mLine.size());
64 31

  
65
        // this flips the coordinates for the second wave 
66 32
        mLine.getPoints()[index].x = float( di.flipX( int(xRatio) ) );
67 33
        mLine.getPoints()[index].y = float( di.flipY( int(yRatio) ) );
68 34

  
69
        // add the missing line to reach the right of the window.
70
        // Indeed, the scope starts from 0 to size-1 and adds xRatio
71
        // to each new point. The line from n-1 to n is therefore missing.
35
        // add the missing line to reach the right of the window
36
        // indeed the scope starts from 0 to size -1 and adds xRatio
37
        // to each new point to the line from n-1 to n is missing 
72 38
        if (index == mNumPoints - 1){
73 39
            xRatio += ( di.getWindowWidth() / mNumPoints );
74 40
            xRatio = ceil( xRatio ); // ceil because the division might left one pixel out
......
79 45

  
80 46
    }
81 47

  
82
    /**
83
     * Draws this oscilloscope as a cinder::PolyLine2f
84
     */ 
85 48
    void draw()
86 49
    {
87 50
        ci::gl::color(1.0f, 1.0f, 1.0f);
CollidoscopeApp/include/PGranular.h
1
/*
2

  
3
 Copyright (C) 2002 James McCartney.
4
 Copyright (C) 2016  Queen Mary University of London 
5
 Author: Fiore Martin, based on Supercollider's (http://supercollider.github.io) TGrains code and Ross Bencina's "Implementing Real-Time Granular Synthesis"
6

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

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

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

  
23 1
#pragma once
24 2

  
25 3
#include <array>
......
32 10

  
33 11
using std::size_t;
34 12

  
35
/**
36
 * The very core of the Collidoscope audio engine: the granular synthesizer.
37
 * Based on SuperCollider's TGrains and Ross Bencina's "Implementing Real-Time Granular Synthesis" 
38
 *
39
 * It implements Collidoscope's selection-based approach to granular synthesis. 
40
 * A grain is basically a selection of a recorded sample of audio. 
41
 * Grains are played in a loop: they are re-triggered each time they reach the end of the selection.
42
 * However, if the duration coefficient is greater than one, a new grain is re-triggered before the previous one is done,
43
 * the grains start to overlap with each other and create the typical eerie sound of grnular synthesis.
44
 * Also every time a new grain is triggered, it is offset of a few samples from the initial position to make the timbre more interesting.
45
 *
46
 *
47
 * PGranular uses a linear ASR envelope with 10 milliseconds attack and 50 milliseconds release.
48
 *
49
 * Note that PGranular is header based and only depends on std library and on "EnvASR.h" (also header based).
50
 * This means you can embedd it in two your project just by copying these two files over.
51
 *
52
 * Template arguments: 
53
 * T: type of the audio samples (normally float or double) 
54
 * RandOffsetFunc: type of the callable passed as argument to the contructor
55
 * TriggerCallbackFunc: type of the callable passed as argument to the contructor
56
 *
57
 */ 
58 13
template <typename T, typename RandOffsetFunc, typename TriggerCallbackFunc>
59 14
class PGranular
60 15
{
......
69 24
        return static_cast<T> ((1 - decimal) * xn + decimal * xn_1);
70 25
    }
71 26

  
72
    /**
73
     * A single grain of the granular synthesis 
74
     */ 
75 27
    struct PGrain
76 28
    {
77 29
        double phase;    // read pointer to mBuffer of this grain 
78 30
        double rate;     // rate of the grain. e.g. rate = 2 the grain will play twice as fast
79
        bool alive;      // whether this grain is alive. Not alive means it has been processed and can be replaced by another grain
31
        bool alive;      // whether this grain is alive. Not alive means it has been processed and can be replanced by another grain
80 32
        size_t age;      // age of this grain in samples 
81 33
        size_t duration; // duration of this grain in samples. minimum = 4
82 34

  
83
        double b1;       // hann envelope from Ross Becina's "Implementing real time Granular Synthesis"
35
        double b1;       // hann envelope from Ross Becina "Implementing real time Granular Synthesis"
84 36
        double y1;
85 37
        double y2;
86 38
    };
87 39

  
88 40

  
89 41

  
90
    /**
91
     * Constructor.
92
     *
93
     * \param buffer a pointer to an array of T that contains the original sample that will be granulized
94
     * \param bufferLen length of buffer in samples 
95
     * \rand function of type size_t ()(void) that is called back each time a new grain is generated. The returned value is used 
96
     * to offset the starting sample of the grain. This adds more colour to the sound especially with small selections. 
97
     * \triggerCallback function of type void ()(char, int) that is called back each time a new grain is generated.
98
     *      The function is passed the character 't' as first parameter when a new grain is triggered and the characted 'e' when the synth becomes idle (no sound).
99
     * \ID id of this PGrain. Passed to the triggerCallback function as second parameter to identify this PGranular as the caller.
100
     */ 
101 42
    PGranular( const T* buffer, size_t bufferLen, size_t sampleRate, RandOffsetFunc & rand, TriggerCallbackFunc & triggerCallback, int ID ) :
102 43
        mBuffer( buffer ),
103 44
        mBufferLen( bufferLen ),
......
130 71

  
131 72
    ~PGranular(){}
132 73

  
133
    /** Sets multiplier of duration of grains in seconds */
74
    /* sets multiplier of duration of grains in seconds */
134 75
    void setGrainsDurationCoeff( double coeff )
135 76
    {
136 77
        mGrainsDurationCoeff = coeff;
137 78

  
138
        mGrainsDuration = std::lround( mTriggerRate * coeff ); 
79
        mGrainsDuration = std::lround( mTriggerRate * coeff ); // FIXME check if right rounding 
139 80

  
140 81
        if ( mGrainsDuration < kMinGrainsDuration )
141 82
            mGrainsDuration = kMinGrainsDuration;
142 83
    }
143 84

  
144
    /** Sets rate of grains. e.g rate = 2 means one octave higer */
85
    /* sets rate of grains. e.g rate = 2 means one octave higer */
145 86
    void setGrainsRate( double rate )
146 87
    {
147 88
        mGrainsRate = rate;
148 89
    }
149 90

  
150
    /** sets the selection start in samples */
91
    // sets trigger rate in samples 
151 92
    void setSelectionStart( size_t start )
152 93
    {
153 94
        mGrainsStart = start;
154 95
    }
155 96

  
156
    /** Sets the selection size ( and therefore the trigger rate) in samples */
157 97
    void setSelectionSize( size_t size )
158 98
    {
159 99

  
......
167 107

  
168 108
    }
169 109

  
170
    /** Sets the attenuation of the grains with respect to the level of the recorded sample
171
     *  attenuation is in amp value and defaule value is 0.25118864315096 (-12dB) */
172 110
    void setAttenuation( T attenuation )
173 111
    {
174 112
        mAttenuation = attenuation;
175 113
    }
176 114

  
177
    /** Starts the synthesis engine */
178 115
    void noteOn( double rate )
179 116
    {
180 117
        if ( mEnvASR.getState() == EnvASR<T>::State::eIdle ){
......
188 125
        }
189 126
    }
190 127

  
191
    /** Stops the synthesis engine */
192 128
    void noteOff()
193 129
    {
194 130
        if ( mEnvASR.getState() != EnvASR<T>::State::eIdle ){
......
196 132
        }
197 133
    }
198 134

  
199
    /** Whether the synthesis engine is active or not. After noteOff is called the synth stays active until the envelope decays to 0 */
200 135
    bool isIdle()
201 136
    {
202 137
        return mEnvASR.getState() == EnvASR<T>::State::eIdle;
203 138
    }
204 139

  
205
    /**
206
     * Runs the granular engine and stores the output in \a audioOut
207
     * 
208
     * \param pointer to an array of T. This will be filled with the output of PGranular. It needs to be at least \a numSamples long
209
     * \param tempBuffer a temporary buffer used to store the envelope value. It needs to be at least \a numSamples long
210
     * \param numSamples number of samples to be processed 
211
     */ 
212 140
    void process( T* audioOut, T* tempBuffer, size_t numSamples )
213 141
    {
214 142
        
......
216 144
        size_t envSamples = 0;
217 145
        bool becameIdle = false;
218 146

  
219
        // process the envelope first and store it in the tempBuffer 
147
        // do the envelope first and store it in the tempBuffer 
220 148
        for ( size_t i = 0; i < numSamples; i++ ){
221 149
            tempBuffer[i] = mEnvASR.tick();
222 150
            envSamples++;
......
228 156
            }
229 157
        }
230 158

  
231
        // does the actual grains processing 
232 159
        processGrains( audioOut, tempBuffer, envSamples );
233 160

  
234
        // becomes idle if the envelope goes to idle state 
235 161
        if ( becameIdle ){
236 162
            mTriggerCallback( 'e', mID );
237 163
            reset();
......
248 174
            synthesizeGrain( mGrains[grainIdx], audioOut, envelopeValues, numSamples );
249 175

  
250 176
            if ( !mGrains[grainIdx].alive ){
251
                // this grain is dead so copy the last of the active grains here 
177
                // this grain is dead so copyu the last of the active grains here 
252 178
                // so as to keep all active grains at the beginning of the array 
253 179
                // don't increment grainIdx so the last active grain is processed next cycle
254 180
                // if this grain is the last active grain then mNumAliveGrains is decremented 
......
317 243
        }
318 244
    }
319 245

  
320
    // synthesize a single grain 
321 246
    // audioOut = pointer to audio block to fill 
322
    // numSamples = number of samples to process for this block
247
    // numSamples = numpber of samples to process for this block
323 248
    void synthesizeGrain( PGrain &grain, T* audioOut, T* envelopeValues, size_t numSamples )
324 249
    {
325 250

  
326
        // copy all grain data into local variable for faster processing
251
        // copy all grain data into local variable for faster porcessing
327 252
        const auto rate = grain.rate;
328 253
        auto phase = grain.phase;
329 254
        auto age = grain.age;
......
365 290
        }
366 291

  
367 292
        if ( age == duration ){
368
            // if it processed all the samples left to leave ( numSamplesToOut = duration-age)
369
            // then the grain is finished 
293
            // if it porocessed all the samples left to leave ( numSamplesToOut = duration-age)
294
            // then the grain is had finished 
370 295
            grain.alive = false;
371 296
        }
372 297
        else{
......
399 324
    // length of mBuffer in samples 
400 325
    const size_t mBufferLen;
401 326

  
402
    // offset in the buffer where the grains start. a.k.a. selection start 
327
    // offset in the buffer where the grains start. a.k.a. seleciton start 
403 328
    size_t mGrainsStart;
404 329

  
405
    // attenuates signal prevents clipping of grains (to some degree)
330
    // attenuates signal prevents clipping of grains 
406 331
    T mAttenuation;
407 332

  
408 333
    // grain duration in samples 
409 334
    double mGrainsDurationCoeff;
410
    // duration of grains is selection size * duration coeff
335
    // duration of grains is selcection size * duration coeff
411 336
    size_t mGrainsDuration;
412 337
    // rate of grain, affects pitch 
413 338
    double mGrainsRate;
CollidoscopeApp/include/PGranularNode.h
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 1
#pragma once
23 2

  
24 3
#include "cinder/Cinder.h"
......
40 19
struct RandomGenerator;
41 20

  
42 21
/*
43
A node in the Cinder audio graph that holds PGranulars for loop and keyboard playing  
22
A node in the Cinder audio graph that holds a PGranular 
44 23
*/
45 24
class PGranularNode : public ci::audio::Node
46 25
{
......
51 30
    explicit PGranularNode( ci::audio::Buffer *grainBuffer, CursorTriggerMsgRingBuffer &triggerRingBuffer );
52 31
    ~PGranularNode();
53 32

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

  
60
    /** Set selection start in samples */
61 39
    void setSelectionStart( size_t start )
62 40
    {
63 41
        mSelectionStart.set( start );
......
68 46
        mGrainDurationCoeff.set( coeff );
69 47
    }
70 48

  
71
    /* PGranularNode passes itself as trigger callback in PGranular */
49
    // used for trigger callback in PGRanular 
72 50
    void operator()( char msgType, int ID );
73 51

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

  
76 54
protected:
77 55
    
78
    void initialize()                           override;
56
    void initialize()							override;
79 57

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

  
82 60
private:
83 61

  
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 PGranular setter methods with the same value at each audio callback.
86 62
    template< typename T>
87 63
    class LazyAtomic
88 64
    {
......
114 90
        T mPreviousVal;
115 91
    };
116 92

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

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

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

  
132 106
    ci::audio::BufferRef mTempBuffer;
CollidoscopeApp/include/ParticleController.h
1
/*
2

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

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

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

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

  
22
*/
23

  
24 1
#pragma once
25 2

  
26 3
#include "cinder/gl/gl.h"
27 4
#include <vector>
28 5

  
29
/**
30
 * The ParticleController creates/updates/draws and destroys particles
31
 */ 
6

  
32 7
class ParticleController {
33 8

  
34 9
    struct Particle {
35 10

  
36
        ci::vec2	mCloudCenter; // initial positin of the particle 
37
        ci::vec2	mVel;         // velocity 
38
        float       mCloudSize;   // how big is the area where particle float around. When a particle hits the 
39
                                  // border of the area it gets deflected 
11
        ci::vec2	mCloudCenter;
12
        ci::vec2	mVel;
13
        float       mCloudSize;
40 14

  
41
        int			mAge;      // when mAge == mLifeSpan the particle is disposed 
42
        int			mLifespan; // how long a particle lives
43
        bool        mFlyOver;  // some particles last longer and fly over the screen and reach the other user
15
        int			mAge;
16
        int			mLifespan;
17
        bool        mFlyOver;
44 18

  
45 19
    };
46 20

  
......
49 23
	std::vector<Particle> mParticles;
50 24
    std::vector< ci::vec2 > mParticlePositions;
51 25

  
52
    // current number of active particles
53 26
    size_t mNumParticles;
54 27

  
55
    ci::gl::VboRef			mParticleVbo;    // virtual buffer object 
28
    ci::gl::VboRef			mParticleVbo;
56 29
    ci::gl::BatchRef		mParticleBatch;
57 30

  
58 31
 public:
59
    /**
60
     * Every time addParticles is run, up to kMaxParticleAdd are added at once
61
     */ 
62 32
    static const int kMaxParticleAdd = 22;
63 33

  
64 34
    ParticleController();
65

  
66
    /**
67
     * Adds \a amount particles and places them in \a initialLocation. 
68
     * \cloudSize determines how far the particles can go
69
     */ 
70 35
	void addParticles(int amount, const ci::vec2 &initialLocation, const float cloudSize);
71 36
	
72
    /**
73
     * Updates position and age of the particles
74
     */ 
75 37
    void updateParticles();
76 38

  
77
    /**
78
     * Draws all the particles
79
     */ 
80 39
    inline void draw()
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff