Revision 16:4dad0b810f18 CollidoscopeApp/include
| CollidoscopeApp/include/AudioEngine.h | ||
|---|---|---|
| 75 | 75 |
*/ |
| 76 | 76 |
size_t getRecordWaveAvailable( size_t index ); |
| 77 | 77 |
/** |
| 78 |
* Called from the graphic thread. Reads count elements from the wave ring buffer into \a buffer. |
|
| 78 |
* Called from the graphic thread. Reads \a count elements from the wave ring buffer into \a buffer.
|
|
| 79 | 79 |
* The wave ring buffer is used to pass the size of the wave chunks from the audio thread to the graphic thread, |
| 80 | 80 |
* when a new wave is recorded. |
| 81 | 81 |
* |
| ... | ... | |
| 106 | 106 |
// nodes for recording audio input into buffer. Also sends chunks information through |
| 107 | 107 |
// non-blocking queue |
| 108 | 108 |
std::array< BufferToWaveRecorderNodeRef, NUM_WAVES > mBufferRecorderNodes; |
| 109 |
// pgranulars for loop synths
|
|
| 109 |
// pgranulars wrapped in a Cinder::Node
|
|
| 110 | 110 |
std::array< PGranularNodeRef, NUM_WAVES > mPGranularNodes; |
| 111 | 111 |
|
| 112 | 112 |
|
| CollidoscopeApp/include/BufferToWaveRecorderNode.h | ||
|---|---|---|
| 60 | 60 |
/** |
| 61 | 61 |
* A \a Node in the audio graph of the Cinder audio library that records input in a buffer. |
| 62 | 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.
|
|
| 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 | 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 | 66 |
* |
| 67 | 67 |
*/ |
| CollidoscopeApp/include/Chunk.h | ||
|---|---|---|
| 33 | 33 |
* |
| 34 | 34 |
* A chunk of audio in Collidoscope low-fi visual wave. |
| 35 | 35 |
* |
| 36 |
* The visual wave of Collidoscope is made out of a number of bars that mimics in a low-fi fashion the typical waveform based representation of audio.
|
|
| 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 | 37 |
* A Chunk is one of the bars of the visual wave. |
| 38 | 38 |
* |
| 39 | 39 |
*/ |
| ... | ... | |
| 47 | 47 |
const static float kHalfWidth; |
| 48 | 48 |
|
| 49 | 49 |
/** |
| 50 |
* Constructor, takes as argument the index of this chunk in the wave |
|
| 50 |
* Constructor, takes as argument the index of this chunk in the wave that contains it
|
|
| 51 | 51 |
*/ |
| 52 | 52 |
Chunk( size_t index ); |
| 53 | 53 |
|
| ... | ... | |
| 69 | 69 |
float inline getBottom() const { return mAudioBottom; }
|
| 70 | 70 |
|
| 71 | 71 |
/** |
| 72 |
* Reset this chunks. When a chunk is reset it starts shrinking until it disappears.
|
|
| 72 |
* Reset this chunks. When a chunk is reset, it starts shrinking until it disappears or setTop/setBottom are called again
|
|
| 73 | 73 |
* |
| 74 | 74 |
*/ |
| 75 | 75 |
void reset(){
|
| CollidoscopeApp/include/Config.h | ||
|---|---|---|
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 | 68 |
/** |
| 69 |
* Returns wave's selection color
|
|
| 69 |
* Returns wave selection color |
|
| 70 | 70 |
*/ |
| 71 | 71 |
ci::Color getWaveSelectionColor(size_t waveIdx) const |
| 72 | 72 |
{
|
| ... | ... | |
| 123 | 123 |
/** |
| 124 | 124 |
* The value returned is used when creating the oscilloscope. |
| 125 | 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 o audio output buffer / getOscilloscopeNumPointsDivider()
|
|
| 126 |
* audio wave and it's downsampled using the following formula : (number of oscilloscope points) = (size of audio output buffer) / getOscilloscopeNumPointsDivider()
|
|
| 127 | 127 |
*/ |
| 128 | 128 |
size_t getOscilloscopeNumPointsDivider() const |
| 129 | 129 |
{
|
| CollidoscopeApp/include/DrawInfo.h | ||
|---|---|---|
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 | 60 |
/** |
| 61 |
* Maps a value in the audio space [-1.0, 1.0] to a position on the y axis of this DrawInf's bounding area. |
|
| 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 | 62 |
* |
| 63 | 63 |
*/ |
| 64 | 64 |
float audioToHeigt(float audioSample) const {
|
| ... | ... | |
| 99 | 99 |
} |
| 100 | 100 |
|
| 101 | 101 |
/** |
| 102 |
* Flips y according to the index of the wave. It is needed because the second wave in collidoscope is upside down from the orientation oftthe screen.
|
|
| 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 | 103 |
*/ |
| 104 | 104 |
int flipY(int y) const |
| 105 | 105 |
{
|
| ... | ... | |
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 | 112 |
/** |
| 113 |
* Returns x. not used at he moment. |
|
| 113 |
* Returns x. not used at the moment.
|
|
| 114 | 114 |
* |
| 115 | 115 |
*/ |
| 116 | 116 |
int flipX(int x) const |
| CollidoscopeApp/include/EnvASR.h | ||
|---|---|---|
| 1 | 1 |
/* |
| 2 | 2 |
|
| 3 | 3 |
Copyright (C) 2016 Queen Mary University of London |
| 4 |
Author: Fiore Martin |
|
| 4 |
Author: Fiore Martin, based on CCRMA STK ADSR.h (https://ccrma.stanford.edu/software/stk/classstk_1_1ADSR.html)
|
|
| 5 | 5 |
|
| 6 | 6 |
This file is part of Collidoscope. |
| 7 | 7 |
|
| ... | ... | |
| 17 | 17 |
|
| 18 | 18 |
You should have received a copy of the GNU General Public License |
| 19 | 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 |
|
|
| 20 | 51 |
*/ |
| 21 | 52 |
|
| 22 | 53 |
#pragma once |
| CollidoscopeApp/include/MIDI.h | ||
|---|---|---|
| 31 | 31 |
|
| 32 | 32 |
namespace collidoscope {
|
| 33 | 33 |
|
| 34 |
|
|
| 34 |
// Exception thrown by MIDI system |
|
| 35 | 35 |
class MIDIException : public std::exception |
| 36 | 36 |
{
|
| 37 | 37 |
public: |
| ... | ... | |
| 118 | 118 |
// of saving all the messages in mMIDIMessages just save the last received in mPitchBendMessages |
| 119 | 119 |
// and optimize away redundant messages. |
| 120 | 120 |
std::array< MIDIMessage, NUM_WAVES > mPitchBendMessages; |
| 121 |
// Same principle of pitch bend messages
|
|
| 121 |
// Same principle as mPitchBendMessages
|
|
| 122 | 122 |
std::array< MIDIMessage, NUM_WAVES > mFilterMessages; |
| 123 | 123 |
|
| 124 |
// vecotr containing all the MIDI input devices detected.
|
|
| 124 |
// vector containing all the MIDI input devices detected.
|
|
| 125 | 125 |
std::vector< std::unique_ptr <RtMidiIn> > mInputs; |
| 126 | 126 |
// Used for mutual access to the MIDI messages by the MIDI thread and the graphic thread. |
| 127 | 127 |
std::mutex mMutex; |
| CollidoscopeApp/include/Messages.h | ||
|---|---|---|
| 31 | 31 |
// message sent when a new recording starts. The gui resets the wave upon receiving it. |
| 32 | 32 |
WAVE_START, |
| 33 | 33 |
|
| 34 |
// new grain created |
|
| 34 | 35 |
TRIGGER_UPDATE, |
| 36 |
// synth became idle |
|
| 35 | 37 |
TRIGGER_END, |
| 36 | 38 |
|
| 37 | 39 |
NOTE_ON, |
| ... | ... | |
| 43 | 45 |
|
| 44 | 46 |
/** Message sent from the audio thread to the graphic wave when a new wave is recorded. |
| 45 | 47 |
* |
| 46 |
* The graphic thread set the chunks of the wave to reflect the level of the recorded audio. |
|
| 47 |
* The algorithm takes the maximum and minimum value of a group of samples and this becomes the top and bottom of the samples. |
|
| 48 |
* It contains the inde |
|
| 49 |
* the cursor position when the grains are reset. |
|
| 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 |
|
| 50 | 51 |
*/ |
| 51 | 52 |
struct RecordWaveMsg |
| 52 | 53 |
{
|
| CollidoscopeApp/include/Oscilloscope.h | ||
|---|---|---|
| 44 | 44 |
{}
|
| 45 | 45 |
|
| 46 | 46 |
/** |
| 47 |
* Sets the value of a point of the oscilloscope. The value is passed as an audio coordinate [-1.0, 1.0].
|
|
| 48 |
* A reference to DrawInfo is passed to calculate the graphic coordinate of the point based on the audio value passed. |
|
| 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 | 49 |
*/ |
| 50 | 50 |
void setPoint( int index, float audioVal, const DrawInfo &di ){
|
| 51 | 51 |
|
| ... | ... | |
| 66 | 66 |
mLine.getPoints()[index].x = float( di.flipX( int(xRatio) ) ); |
| 67 | 67 |
mLine.getPoints()[index].y = float( di.flipY( int(yRatio) ) ); |
| 68 | 68 |
|
| 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 to the line from n-1 to n is missing
|
|
| 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.
|
|
| 72 | 72 |
if (index == mNumPoints - 1){
|
| 73 | 73 |
xRatio += ( di.getWindowWidth() / mNumPoints ); |
| 74 | 74 |
xRatio = ceil( xRatio ); // ceil because the division might left one pixel out |
| CollidoscopeApp/include/PGranular.h | ||
|---|---|---|
| 1 | 1 |
/* |
| 2 | 2 |
|
| 3 |
Copyright (C) 2002 James McCartney. |
|
| 3 | 4 |
Copyright (C) 2016 Queen Mary University of London |
| 4 |
Author: Fiore Martin |
|
| 5 |
Author: Fiore Martin, based on Supercollider's (http://supercollider.github.io) TGrains code and Ross Bencina's "Implementing Real-Time Granular Synthesis"
|
|
| 5 | 6 |
|
| 6 | 7 |
This file is part of Collidoscope. |
| 7 | 8 |
|
| ... | ... | |
| 33 | 34 |
|
| 34 | 35 |
/** |
| 35 | 36 |
* The very core of the Collidoscope audio engine: the granular synthesizer. |
| 36 |
* Based on SuperCollider's TGrains and Ross Becina's "Implementing Real-Time Granular Synthesis" |
|
| 37 |
* Based on SuperCollider's TGrains and Ross Bencina's "Implementing Real-Time Granular Synthesis"
|
|
| 37 | 38 |
* |
| 38 | 39 |
* It implements Collidoscope's selection-based approach to granular synthesis. |
| 39 | 40 |
* A grain is basically a selection of a recorded sample of audio. |
| 40 |
* Grains are played in a loop: they are retriggered each time they reach the end of the selection. |
|
| 41 |
* However, if the duration coefficient is greater than one, a new grain is re-triggered before the previous one is done.
|
|
| 42 |
* The grains start to overlap with each other and create the typical eerie sound of grnular synthesis.
|
|
| 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.
|
|
| 43 | 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. |
| 44 | 45 |
* |
| 45 | 46 |
* |
| ... | ... | |
| 75 | 76 |
{
|
| 76 | 77 |
double phase; // read pointer to mBuffer of this grain |
| 77 | 78 |
double rate; // rate of the grain. e.g. rate = 2 the grain will play twice as fast |
| 78 |
bool alive; // whether this grain is alive. Not alive means it has been processed and can be replanced by another grain
|
|
| 79 |
bool alive; // whether this grain is alive. Not alive means it has been processed and can be replaced by another grain |
|
| 79 | 80 |
size_t age; // age of this grain in samples |
| 80 | 81 |
size_t duration; // duration of this grain in samples. minimum = 4 |
| 81 | 82 |
|
| ... | ... | |
| 91 | 92 |
* |
| 92 | 93 |
* \param buffer a pointer to an array of T that contains the original sample that will be granulized |
| 93 | 94 |
* \param bufferLen length of buffer in samples |
| 94 |
* \rand function returning of type size_t ()(void) that is called back each time a new grain is generated. The returned value is used
|
|
| 95 |
* \rand function of type size_t ()(void) that is called back each time a new grain is generated. The returned value is used |
|
| 95 | 96 |
* to offset the starting sample of the grain. This adds more colour to the sound especially with small selections. |
| 96 |
* \triggerCallback function of type void ()(char, int) that is called back each time a new grain is triggered.
|
|
| 97 |
* The function is passed the character 't' as first parameter when a new grain is triggered and the characted 't' when the synths becomes idle.
|
|
| 98 |
* \ID id of this PGrain is passed to the triggerCallback function as second parameter to identify this PGranular as the caller.
|
|
| 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.
|
|
| 99 | 100 |
*/ |
| 100 | 101 |
PGranular( const T* buffer, size_t bufferLen, size_t sampleRate, RandOffsetFunc & rand, TriggerCallbackFunc & triggerCallback, int ID ) : |
| 101 | 102 |
mBuffer( buffer ), |
| ... | ... | |
| 204 | 205 |
/** |
| 205 | 206 |
* Runs the granular engine and stores the output in \a audioOut |
| 206 | 207 |
* |
| 207 |
* \param pointer to an array of T. This will be filled with the output of PGranular. It needs to be at least \a numSamples lond
|
|
| 208 |
* \param tempBuffer a temporary buffer used to store the envelope value. It needs to be at leas \a numSamples long |
|
| 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
|
|
| 209 | 210 |
* \param numSamples number of samples to be processed |
| 210 | 211 |
*/ |
| 211 | 212 |
void process( T* audioOut, T* tempBuffer, size_t numSamples ) |
| ... | ... | |
| 318 | 319 |
|
| 319 | 320 |
// synthesize a single grain |
| 320 | 321 |
// audioOut = pointer to audio block to fill |
| 321 |
// numSamples = numpber of samples to process for this block
|
|
| 322 |
// numSamples = number of samples to process for this block |
|
| 322 | 323 |
void synthesizeGrain( PGrain &grain, T* audioOut, T* envelopeValues, size_t numSamples ) |
| 323 | 324 |
{
|
| 324 | 325 |
|
| 325 |
// copy all grain data into local variable for faster porcessing
|
|
| 326 |
// copy all grain data into local variable for faster processing
|
|
| 326 | 327 |
const auto rate = grain.rate; |
| 327 | 328 |
auto phase = grain.phase; |
| 328 | 329 |
auto age = grain.age; |
| ... | ... | |
| 364 | 365 |
} |
| 365 | 366 |
|
| 366 | 367 |
if ( age == duration ){
|
| 367 |
// if it porocessed all the samples left to leave ( numSamplesToOut = duration-age)
|
|
| 368 |
// then the grain is had finished
|
|
| 368 |
// if it processed all the samples left to leave ( numSamplesToOut = duration-age) |
|
| 369 |
// then the grain is finished |
|
| 369 | 370 |
grain.alive = false; |
| 370 | 371 |
} |
| 371 | 372 |
else{
|
| ... | ... | |
| 398 | 399 |
// length of mBuffer in samples |
| 399 | 400 |
const size_t mBufferLen; |
| 400 | 401 |
|
| 401 |
// offset in the buffer where the grains start. a.k.a. seleciton start
|
|
| 402 |
// offset in the buffer where the grains start. a.k.a. selection start
|
|
| 402 | 403 |
size_t mGrainsStart; |
| 403 | 404 |
|
| 404 |
// attenuates signal prevents clipping of grains |
|
| 405 |
// attenuates signal prevents clipping of grains (to some degree)
|
|
| 405 | 406 |
T mAttenuation; |
| 406 | 407 |
|
| 407 | 408 |
// grain duration in samples |
| 408 | 409 |
double mGrainsDurationCoeff; |
| 409 |
// duration of grains is selcection size * duration coeff
|
|
| 410 |
// duration of grains is selection size * duration coeff |
|
| 410 | 411 |
size_t mGrainsDuration; |
| 411 | 412 |
// rate of grain, affects pitch |
| 412 | 413 |
double mGrainsRate; |
| CollidoscopeApp/include/PGranularNode.h | ||
|---|---|---|
| 40 | 40 |
struct RandomGenerator; |
| 41 | 41 |
|
| 42 | 42 |
/* |
| 43 |
A node in the Cinder audio graph that holds a PGranular
|
|
| 43 |
A node in the Cinder audio graph that holds PGranulars for loop and keyboard playing
|
|
| 44 | 44 |
*/ |
| 45 | 45 |
class PGranularNode : public ci::audio::Node |
| 46 | 46 |
{
|
| ... | ... | |
| 82 | 82 |
private: |
| 83 | 83 |
|
| 84 | 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.
|
|
| 85 |
// It is used to avoid calling PGranular setter methods with the same value at each audio callback.
|
|
| 86 | 86 |
template< typename T> |
| 87 | 87 |
class LazyAtomic |
| 88 | 88 |
{
|
| ... | ... | |
| 120 | 120 |
// pointers to PGranular objects |
| 121 | 121 |
std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > > mPGranularLoop; |
| 122 | 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 |
|
| 123 |
// maps midi notes to pgranulars. When a noteOff is received makes sure the right PGranular is turned off
|
|
| 124 | 124 |
std::array<int, kMaxVoices> mMidiNotes; |
| 125 | 125 |
|
| 126 | 126 |
// pointer to the random generator struct passed over to PGranular |
| 127 | 127 |
std::unique_ptr< RandomGenerator > mRandomOffset; |
| 128 | 128 |
|
| 129 |
// buffer containing the recorder audio, to pass to PGranular in initialize()
|
|
| 129 |
// buffer containing the recorded audio, to pass to PGranular in initialize()
|
|
| 130 | 130 |
ci::audio::Buffer *mGrainBuffer; |
| 131 | 131 |
|
| 132 | 132 |
ci::audio::BufferRef mTempBuffer; |
| CollidoscopeApp/include/ParticleController.h | ||
|---|---|---|
| 36 | 36 |
ci::vec2 mCloudCenter; // initial positin of the particle |
| 37 | 37 |
ci::vec2 mVel; // velocity |
| 38 | 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
|
|
| 39 |
// border of the area it gets deflected |
|
| 40 | 40 |
|
| 41 | 41 |
int mAge; // when mAge == mLifeSpan the particle is disposed |
| 42 | 42 |
int mLifespan; // how long a particle lives |
| CollidoscopeApp/include/Wave.h | ||
|---|---|---|
| 88 | 88 |
void setSize( size_t size ); |
| 89 | 89 |
|
| 90 | 90 |
/** The particle spread parameter affects the size of the cloud of particles |
| 91 |
* The cloud is the visual conterpart of the grain duration coefficien in sound.
|
|
| 91 |
* The cloud is the visual counterpart of the grain duration coefficient in sound.
|
|
| 92 | 92 |
* Indeed spread accepts values from 1 to 8, exactly as the duration coefficient |
| 93 | 93 |
*/ |
| 94 | 94 |
void inline setParticleSpread( float spread ){
|
| ... | ... | |
| 148 | 148 |
|
| 149 | 149 |
/* Maps id of the synth to cursor. There is one cursor for each Synth being played */ |
| 150 | 150 |
std::map < SynthID, Cursor > mCursors; |
| 151 |
/** Holds the positions of the cursor, namely on which chunk the cursor is currently */ |
|
| 151 |
/** Holds the positions of the cursor, namely on which chunk the cursor is currently on */
|
|
| 152 | 152 |
std::vector<int> mCursorsPos; |
| 153 | 153 |
|
| 154 | 154 |
public: |
| ... | ... | |
| 156 | 156 |
// value used to identify the loop for cursor position |
| 157 | 157 |
static const int kLoopNote = -1; |
| 158 | 158 |
static const cinder::Color CURSOR_CLR; |
| 159 |
/* must be in sync with supercollider durationFactor ControlSpec max */ |
|
| 160 | 159 |
static const int MAX_DURATION = 8; |
| 161 | 160 |
#ifdef USE_PARTICLES |
| 162 | 161 |
static const int PARTICLESIZE_COEFF = 40; |
| 163 | 162 |
#endif |
| 164 | 163 |
|
| 165 |
/** Resetting a wave makes it shrink until it disappears. Each time a new sample is recorder the wave is reset
|
|
| 164 |
/** Resetting a wave makes it shrink until it disappears. Each time a new sample is recorded, the wave is reset.
|
|
| 166 | 165 |
* \param onlyChunks if false the selection is also set to null, if true only the chunks are reset |
| 167 | 166 |
*/ |
| 168 | 167 |
void reset(bool onlyChunks); |
| ... | ... | |
| 174 | 173 |
|
| 175 | 174 |
const Chunk & getChunk(size_t index); |
| 176 | 175 |
|
| 177 |
/** places the cursor on the wave. Every cursor is associated to a synth voice of the audio engine.
|
|
| 176 |
/** Places the cursor on the wave. Every cursor is associated to a synth voice of the audio engine.
|
|
| 178 | 177 |
* The synth id identifies uniquely the cursor in the internal map of the wave. |
| 179 | 178 |
* If the cursor doesn't exist it is created */ |
| 180 | 179 |
inline void setCursorPos( SynthID id, int pos, const DrawInfo& di ){
|
| ... | ... | |
| 184 | 183 |
cursor.lastUpdate = ci::app::getElapsedSeconds(); |
| 185 | 184 |
|
| 186 | 185 |
#ifdef USE_PARTICLES |
| 187 |
// The idea is that, if the duration is greater than 1.0, the cursor continues in form of particles |
|
| 188 |
// The smaller the selection the more particles; the bigger the duration the more particles |
|
| 186 |
// The idea is that, if the duration is greater than 1.0, the cursor continues in form of particles.
|
|
| 187 |
// The smaller the selection the more particles; the bigger the duration the more particles.
|
|
| 189 | 188 |
if (mSelection.getParticleSpread() > 1.0f){
|
| 190 | 189 |
/* amountCoeff ranges from 1/8 to 1 */ |
| 191 | 190 |
const float amountCoeff = (mSelection.getParticleSpread() / MAX_DURATION); |
| 192 | 191 |
|
| 193 | 192 |
/* get radom point within seleciton as center of the particle */ |
| 194 |
vec2 centrePoint; // was former getRandomPoint
|
|
| 193 |
vec2 centrePoint; |
|
| 195 | 194 |
const int randomChunkIndex = ci::Rand::randInt(mSelection.getStart(), mSelection.getEnd() ); |
| 196 | 195 |
|
| 197 | 196 |
centrePoint.x = di.flipX( 1 + (randomChunkIndex * (2 + Chunk::kWidth)) + Chunk::kWidth / 2 ); |
| ... | ... | |
| 243 | 242 |
|
| 244 | 243 |
cinder::Color mColor; |
| 245 | 244 |
|
| 245 |
// How much filter is applied in audio. It affects the alpha value of the selection color. |
|
| 246 | 246 |
float mFilterCoeff; |
| 247 | 247 |
|
| 248 | 248 |
// cinder gl batch for batch drawing |
Also available in: Unified diff