Revision 0:02467299402e CollidoscopeApp/src
| CollidoscopeApp/src/AudioEngine.cpp | ||
|---|---|---|
| 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 |
|
|
| 23 | 1 |
#include "AudioEngine.h" |
| 24 |
// app.h include not used |
|
| 25 | 2 |
#include "cinder/app/App.h" |
| 3 |
//FIXME remove App.h include |
|
| 26 | 4 |
#include "Log.h" |
| 27 | 5 |
|
| 28 | 6 |
using namespace ci::audio; |
| 29 | 7 |
|
| 30 |
/* Frequency ratios in the chromatic scale */ |
|
| 31 | 8 |
double chromaticRatios[] = {
|
| 32 | 9 |
1, |
| 33 | 10 |
1.0594630943591, |
| ... | ... | |
| 43 | 20 |
1.8877486253586 |
| 44 | 21 |
}; |
| 45 | 22 |
|
| 46 |
|
|
| 47 |
/* |
|
| 48 |
* Calculates the ratio between the frequency of the midi note passed as argument and middle C note ( MIDI value = 60 ). |
|
| 49 |
* This is used for pitch shifting the granular synth output, according to the key pressed by the user. |
|
| 50 |
* The middle C is taken as reference in pitch in the pitch shifting of Collidoscope output. |
|
| 51 |
* That is, with the middle C the output is not pitch shifted at all and is equal in frequency to the recorder sample. |
|
| 52 |
* |
|
| 53 |
*/ |
|
| 54 | 23 |
inline double calculateMidiNoteRatio( int midiNote ) |
| 55 | 24 |
{
|
| 56 | 25 |
int distanceFromCenter = midiNote - 60; // 60 is the central midi note |
| ... | ... | |
| 87 | 56 |
/* audio context */ |
| 88 | 57 |
auto ctx = Context::master(); |
| 89 | 58 |
|
| 90 |
/* audio input device */
|
|
| 59 |
/* audio inpu device */ |
|
| 91 | 60 |
auto inputDeviceNode = ctx->createInputDeviceNode( Device::getDefaultInput() ); |
| 92 | 61 |
|
| 93 | 62 |
|
| ... | ... | |
| 102 | 71 |
/* this prevents the node from recording before record is pressed */ |
| 103 | 72 |
mBufferRecorderNodes[chan]->setAutoEnabled( false ); |
| 104 | 73 |
|
| 105 |
// route the input part of the audio graph. Two channels input goes into one channel route
|
|
| 106 |
// and from one channel route to one channel buffer recorder
|
|
| 74 |
// route the input part of the audio graph. Two channels input goes into |
|
| 75 |
// one channel route and to one channel buffer recorder
|
|
| 107 | 76 |
inputDeviceNode >> mInputRouterNodes[chan]->route( chan, 0, 1 ) >> mBufferRecorderNodes[chan]; |
| 108 | 77 |
|
| 109 | 78 |
|
| 110 | 79 |
// create PGranular loops passing the buffer of the RecorderNode as argument to the contructor |
| 111 |
// use -1 as ID as the loop corresponds to no midi note
|
|
| 80 |
// use -1 as ID |
|
| 112 | 81 |
mPGranularNodes[chan] = ctx->makeNode( new PGranularNode( mBufferRecorderNodes[chan]->getRecorderBuffer(), mCursorTriggerRingBufferPacks[chan]->getBuffer() ) ); |
| 113 | 82 |
|
| 114 | 83 |
// create filter nodes |
| ... | ... | |
| 126 | 95 |
// filter goes to output |
| 127 | 96 |
mLowPassFilterNodes[chan] >> mOutputRouterNodes[chan]->route( 0, chan, 1 ) >> ctx->getOutput(); |
| 128 | 97 |
|
| 129 |
// what goes to output goes to oscilloscope as well
|
|
| 98 |
// what goes to output goes to scope
|
|
| 130 | 99 |
mLowPassFilterNodes[chan] >> mOutputMonitorNodes[chan]; |
| 131 | 100 |
|
| 132 | 101 |
} |
| ... | ... | |
| 205 | 174 |
return mBufferRecorderNodes[waveIdx]->getRingBuffer().getAvailableRead(); |
| 206 | 175 |
} |
| 207 | 176 |
|
| 208 |
|
|
| 209 | 177 |
bool AudioEngine::readRecordWave( size_t waveIdx, RecordWaveMsg* buffer, size_t count ) |
| 210 | 178 |
{
|
| 211 | 179 |
return mBufferRecorderNodes[waveIdx]->getRingBuffer().read( buffer, count ); |
| CollidoscopeApp/src/BufferToWaveRecorderNode.cpp | ||
|---|---|---|
| 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 |
#include "BufferToWaveRecorderNode.h" |
| 47 | 2 |
#include "cinder/audio/Context.h" |
| 48 | 3 |
#include "cinder/audio/Target.h" |
| CollidoscopeApp/src/Chunk.cpp | ||
|---|---|---|
| 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 |
|
|
| 25 | 1 |
#include "Chunk.h" |
| 26 | 2 |
#include "DrawInfo.h" |
| 27 | 3 |
|
| ... | ... | |
| 44 | 20 |
void Chunk::update( const DrawInfo &di ) |
| 45 | 21 |
{
|
| 46 | 22 |
using namespace ci; |
| 47 |
/* if resetting animate the chunks to nicely shrink to 0 size */
|
|
| 23 |
/* if resetting animate the chunks to shrink to 0 size */ |
|
| 48 | 24 |
if ( mResetting ){
|
| 49 | 25 |
if ( mAnimate > 0.0f ){
|
| 50 | 26 |
mAnimate -= 0.1f; |
| ... | ... | |
| 64 | 40 |
} |
| 65 | 41 |
} |
| 66 | 42 |
|
| 67 |
mX = di.flipX( 1 + (mIndex * (2 + kWidth)) ); // FIXME more efficient if it happens only once when resized
|
|
| 43 |
mX = di.flipX( 1 + (mIndex * (2 + kWidth)) ); // FIXME this should happen only once when resized
|
|
| 68 | 44 |
} |
| 69 | 45 |
|
| 70 | 46 |
void Chunk::draw( const DrawInfo& di, ci::gl::BatchRef &batch ){
|
| 71 | 47 |
using namespace ci; |
| 72 |
|
|
| 48 |
|
|
| 73 | 49 |
gl::pushModelMatrix(); |
| 74 | 50 |
|
| 75 | 51 |
const float chunkHeight = mAnimate * mAudioTop * di.getMaxChunkHeight(); |
| 76 | 52 |
|
| 77 |
// place the chunk in the right position brings back the y of chunkHeight/2 so
|
|
| 53 |
// place the chunk in the right position brigns back the y of chunkHeight/2 so
|
|
| 78 | 54 |
// so that after scaling the wave is still centered at the wave center |
| 79 | 55 |
gl::translate( mX, di.getWaveCenterY() - ( chunkHeight / 2 ) - 1 ); |
| 80 | 56 |
|
| 57 |
// FIXME todo use max between top and bottom |
|
| 81 | 58 |
// scale according to audio amplitude |
| 82 | 59 |
gl::scale( 1.0f, chunkHeight ); |
| 83 | 60 |
batch->draw(); |
| ... | ... | |
| 88 | 65 |
|
| 89 | 66 |
|
| 90 | 67 |
void Chunk::drawBar( const DrawInfo& di, ci::gl::BatchRef &batch ){
|
| 91 |
using namespace ci;
|
|
| 68 |
using namespace ci;
|
|
| 92 | 69 |
|
| 93 | 70 |
gl::pushModelMatrix(); |
| 94 | 71 |
|
| ... | ... | |
| 104 | 81 |
|
| 105 | 82 |
|
| 106 | 83 |
const float Chunk::kWidth = 7.0f; |
| 107 |
const float Chunk::kHalfWidth = 3.5f; |
|
| 84 |
const float Chunk::kHalfWidth = 3.5f; |
|
| CollidoscopeApp/src/CollidoscopeApp.cpp | ||
|---|---|---|
| 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 |
|
|
| 23 | 1 |
#include "cinder/app/App.h" |
| 24 | 2 |
#include "cinder/app/RendererGl.h" |
| 25 | 3 |
#include "cinder/gl/gl.h" |
| 26 | 4 |
#include "cinder/Exception.h" |
| 27 |
#include <stdexcept> |
|
| 28 | 5 |
|
| 29 | 6 |
|
| 30 | 7 |
#include "Config.h" |
| ... | ... | |
| 45 | 22 |
class CollidoscopeApp : public App {
|
| 46 | 23 |
public: |
| 47 | 24 |
|
| 48 |
void setup() override;
|
|
| 25 |
void setup() override;
|
|
| 49 | 26 |
void setupGraphics(); |
| 50 | 27 |
|
| 51 |
/** Receives MIDI command messages from MIDI thread */ |
|
| 52 | 28 |
void receiveCommands(); |
| 53 |
/** Prints command line usage */ |
|
| 54 |
void usage(); |
|
| 55 | 29 |
|
| 56 |
void keyDown( KeyEvent event ) override;
|
|
| 57 |
void update() override;
|
|
| 58 |
void draw() override;
|
|
| 30 |
void keyDown( KeyEvent event ) override;
|
|
| 31 |
void update() override;
|
|
| 32 |
void draw() override;
|
|
| 59 | 33 |
void resize() override; |
| 60 | 34 |
|
| 61 |
Config mConfig;
|
|
| 35 |
Config mConfig;
|
|
| 62 | 36 |
collidoscope::MIDI mMIDI; |
| 63 | 37 |
AudioEngine mAudioEngine; |
| 64 |
|
|
| 38 |
|
|
| 65 | 39 |
array< shared_ptr< Wave >, NUM_WAVES > mWaves; |
| 66 | 40 |
array< shared_ptr< DrawInfo >, NUM_WAVES > mDrawInfos; |
| 67 | 41 |
array< shared_ptr< Oscilloscope >, NUM_WAVES > mOscilloscopes; |
| 68 |
// buffer to read the WAVE_* messages as a new wave gets recorded
|
|
| 42 |
// buffers to read the wave messages as a new wave gets recorded
|
|
| 69 | 43 |
array< RecordWaveMsg*, NUM_WAVES> mRecordWaveMessageBuffers; |
| 70 |
//buffer to read the TRIGGER_* messages as the pgranulars play |
|
| 71 | 44 |
array< vector< CursorTriggerMsg >, NUM_WAVES > mCursorTriggerMessagesBuffers; |
| 72 | 45 |
|
| 73 | 46 |
double mSecondsPerChunk; |
| ... | ... | |
| 125 | 98 |
{
|
| 126 | 99 |
char c = event.getChar(); |
| 127 | 100 |
|
| 128 |
const size_t waveIdx = 0; |
|
| 129 |
|
|
| 130 | 101 |
switch (c){
|
| 131 | 102 |
case 'r' : |
| 132 |
mAudioEngine.record( waveIdx ); |
|
| 103 |
mAudioEngine.record( 0 ); |
|
| 104 |
mAudioEngine.record( 1 ); |
|
| 133 | 105 |
break; |
| 134 | 106 |
|
| 135 | 107 |
case 'w': {
|
| 108 |
mWaves[0]->getSelection().setSize(mWaves[0]->getSelection().getSize() + 1); |
|
| 136 | 109 |
|
| 137 |
mWaves[waveIdx]->getSelection().setSize(mWaves[waveIdx]->getSelection().getSize() + 1); |
|
| 138 |
|
|
| 139 |
size_t numSelectionChunks = mWaves[waveIdx]->getSelection().getSize(); |
|
| 110 |
size_t numSelectionChunks = mWaves[0]->getSelection().getSize(); |
|
| 140 | 111 |
// how many samples in one selection ? |
| 141 | 112 |
size_t selectionSize = numSelectionChunks * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()); |
| 142 | 113 |
|
| 143 |
mAudioEngine.setSelectionSize(waveIdx, selectionSize); |
|
| 114 |
mAudioEngine.setSelectionSize(0, selectionSize); |
|
| 115 |
}; |
|
| 116 |
break; |
|
| 117 |
|
|
| 118 |
case 'e': {
|
|
| 119 |
mWaves[1]->getSelection().setSize(mWaves[1]->getSelection().getSize() + 1); |
|
| 120 |
|
|
| 121 |
size_t numSelectionChunks = mWaves[1]->getSelection().getSize(); |
|
| 122 |
// how many samples in one selection ? |
|
| 123 |
size_t selectionSize = numSelectionChunks * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()); |
|
| 124 |
|
|
| 125 |
mAudioEngine.setSelectionSize(1, selectionSize); |
|
| 144 | 126 |
}; |
| 145 | 127 |
break; |
| 146 | 128 |
|
| 147 | 129 |
case 's': {
|
| 148 | 130 |
|
| 149 |
mWaves[waveIdx]->getSelection().setSize( mWaves[waveIdx]->getSelection().getSize() - 1 );
|
|
| 131 |
mWaves[0]->getSelection().setSize( mWaves[0]->getSelection().getSize() - 1 );
|
|
| 150 | 132 |
|
| 151 |
size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() *(mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
|
| 152 |
mAudioEngine.setSelectionSize( waveIdx, selectionSize );
|
|
| 133 |
size_t selectionSize = mWaves[0]->getSelection().getSize() *(mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
|
| 134 |
mAudioEngine.setSelectionSize( 0, selectionSize );
|
|
| 153 | 135 |
}; |
| 154 | 136 |
break; |
| 155 | 137 |
|
| 156 | 138 |
case 'd': {
|
| 157 | 139 |
|
| 158 |
size_t selectionStart = mWaves[waveIdx]->getSelection().getStart(); |
|
| 159 |
mWaves[waveIdx]->getSelection().setStart( selectionStart + 1 ); |
|
| 140 |
for( size_t waveIdx = 0; waveIdx < NUM_WAVES; waveIdx++){
|
|
| 141 |
size_t selectionStart = mWaves[waveIdx]->getSelection().getStart(); |
|
| 142 |
mWaves[waveIdx]->getSelection().setStart( selectionStart + 1 ); |
|
| 160 | 143 |
|
| 161 |
selectionStart = mWaves[waveIdx]->getSelection().getStart(); |
|
| 162 |
mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) ); |
|
| 144 |
selectionStart = mWaves[waveIdx]->getSelection().getStart(); |
|
| 145 |
mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) ); |
|
| 146 |
} |
|
| 163 | 147 |
}; |
| 164 | 148 |
|
| 165 | 149 |
break; |
| 166 | 150 |
|
| 167 | 151 |
case 'a': {
|
| 168 |
size_t selectionStart = mWaves[waveIdx]->getSelection().getStart();
|
|
| 152 |
size_t selectionStart = mWaves[0]->getSelection().getStart();
|
|
| 169 | 153 |
|
| 170 | 154 |
if ( selectionStart == 0 ) |
| 171 | 155 |
return; |
| 172 | 156 |
|
| 173 |
mWaves[waveIdx]->getSelection().setStart( selectionStart - 1 );
|
|
| 157 |
mWaves[0]->getSelection().setStart( selectionStart - 1 );
|
|
| 174 | 158 |
|
| 175 |
selectionStart = mWaves[waveIdx]->getSelection().getStart();
|
|
| 159 |
selectionStart = mWaves[0]->getSelection().getStart();
|
|
| 176 | 160 |
|
| 177 |
mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
|
| 161 |
mAudioEngine.setSelectionStart( 0, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
|
| 178 | 162 |
}; |
| 179 | 163 |
break; |
| 180 | 164 |
|
| 165 |
|
|
| 166 |
case 'p': |
|
| 167 |
|
|
| 168 |
mWaves[0]->setCursorPos( 4, mWaves[0]->getSelection().getStart(), *mDrawInfos[0] ) ; |
|
| 169 |
break; |
|
| 170 |
|
|
| 181 | 171 |
case 'f': |
| 182 | 172 |
setFullScreen( !isFullScreen() ); |
| 183 | 173 |
break; |
| ... | ... | |
| 186 | 176 |
static bool isOn = false; |
| 187 | 177 |
isOn = !isOn; |
| 188 | 178 |
if ( isOn ){
|
| 189 |
mAudioEngine.loopOn( waveIdx ); |
|
| 179 |
mAudioEngine.loopOn( 0 ); |
|
| 180 |
mAudioEngine.loopOn( 1 ); |
|
| 190 | 181 |
} |
| 191 | 182 |
else{
|
| 192 |
mAudioEngine.loopOff( waveIdx ); |
|
| 183 |
mAudioEngine.loopOff( 0 ); |
|
| 184 |
mAudioEngine.loopOff( 1 ); |
|
| 193 | 185 |
} |
| 194 | 186 |
}; |
| 195 | 187 |
break; |
| 196 | 188 |
|
| 189 |
case 'm' : |
|
| 190 |
mAudioEngine.setGrainDurationCoeff(0, 8); |
|
| 191 |
break; |
|
| 192 |
|
|
| 193 |
case 'n': {
|
|
| 194 |
mAudioEngine.setGrainDurationCoeff( 0, 1 ); |
|
| 195 |
}; |
|
| 196 |
break; |
|
| 197 |
|
|
| 197 | 198 |
case '9': {
|
| 198 |
int c = mWaves[waveIdx]->getSelection().getParticleSpread();
|
|
| 199 |
int c = mWaves[0]->getSelection().getParticleSpread();
|
|
| 199 | 200 |
if ( c == 1 ) |
| 200 | 201 |
return; |
| 201 | 202 |
else |
| 202 | 203 |
c -= 1; |
| 203 | 204 |
|
| 204 |
mAudioEngine.setGrainDurationCoeff( waveIdx, c ); |
|
| 205 |
mWaves[waveIdx]->getSelection().setParticleSpread( float( c ) ); |
|
| 206 |
|
|
| 205 |
mAudioEngine.setGrainDurationCoeff( 0, c ); |
|
| 206 |
mWaves[0]->getSelection().setParticleSpread( float( c ) ); |
|
| 207 |
mAudioEngine.setGrainDurationCoeff( 1, c ); |
|
| 208 |
mWaves[1]->getSelection().setParticleSpread( float( c ) ); |
|
| 207 | 209 |
}; break; |
| 208 | 210 |
|
| 209 | 211 |
case '0': {
|
| 210 |
int c = mWaves[waveIdx]->getSelection().getParticleSpread();
|
|
| 212 |
int c = mWaves[0]->getSelection().getParticleSpread();
|
|
| 211 | 213 |
if ( c == 8 ) |
| 212 | 214 |
return; |
| 213 | 215 |
else |
| 214 | 216 |
c += 1; |
| 215 | 217 |
|
| 216 |
mAudioEngine.setGrainDurationCoeff( waveIdx, c );
|
|
| 217 |
mWaves[waveIdx]->getSelection().setParticleSpread( float( c ) );
|
|
| 218 |
mAudioEngine.setGrainDurationCoeff( 0, c );
|
|
| 219 |
mWaves[0]->getSelection().setParticleSpread( float( c ) );
|
|
| 218 | 220 |
}; break; |
| 221 |
|
|
| 219 | 222 |
} |
| 220 | 223 |
|
| 221 | 224 |
} |
| ... | ... | |
| 290 | 293 |
|
| 291 | 294 |
void CollidoscopeApp::draw() |
| 292 | 295 |
{
|
| 293 |
gl::clear( Color( 0, 0, 0 ) );
|
|
| 296 |
gl::clear( Color( 0, 0, 0 ) );
|
|
| 294 | 297 |
|
| 295 | 298 |
for ( int i = 0; i < NUM_WAVES; i++ ){
|
| 296 | 299 |
if ( i == 1 ){
|
| ... | ... | |
| 356 | 359 |
value |= MSB; |
| 357 | 360 |
|
| 358 | 361 |
|
| 359 |
// value ranges from 0 to 149. check boundaries in case sensor gives bad values
|
|
| 360 |
if ( value > 149 ){ // FIXME can use wave.size()
|
|
| 362 |
// value ranges from 0 to 1050. check boundaries in case sensor gives bad values
|
|
| 363 |
if ( value > 149 ){ // FIXME pareametrizer
|
|
| 361 | 364 |
continue; |
| 362 | 365 |
} |
| 363 | 366 |
|
| ... | ... | |
| 385 | 388 |
mWaves[waveIdx]->getSelection().setSize( numSelectionChunks ); |
| 386 | 389 |
|
| 387 | 390 |
// how many samples in one selection ? |
| 388 |
size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
|
| 391 |
size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
|
| 389 | 392 |
mAudioEngine.setSelectionSize( waveIdx, selectionSize ); |
| 390 | 393 |
|
| 391 | 394 |
}; |
| ... | ... | |
| 443 | 446 |
} |
| 444 | 447 |
} |
| 445 | 448 |
|
| 446 |
|
|
| 447 | 449 |
CINDER_APP( CollidoscopeApp, RendererGl, [] ( App::Settings *settings) {
|
| 448 |
|
|
| 449 |
const std::vector< string > args = settings->getCommandLineArgs(); |
|
| 450 |
|
|
| 451 |
int width = 0; |
|
| 452 |
int height = 0; |
|
| 453 |
|
|
| 454 |
try {
|
|
| 455 |
if( args.size() != 3 ) |
|
| 456 |
throw std::invalid_argument("");
|
|
| 457 |
|
|
| 458 |
width = std::stoi( args[1] ); |
|
| 459 |
height = std::stoi( args[2] ); |
|
| 460 |
|
|
| 461 |
} |
|
| 462 |
catch( std::invalid_argument & e ){
|
|
| 463 |
console() << "Error: invalid arguments" << std::endl; |
|
| 464 |
console() << "Usage: ./CollidoscopeApp window_width window_height" << std::endl; |
|
| 465 |
console() << "For example: ./CollidoscopeApp 1024 768 " << std::endl; |
|
| 466 |
|
|
| 467 |
settings->setShouldQuit( true ); |
|
| 468 |
return; |
|
| 469 |
} |
|
| 470 |
|
|
| 471 |
settings->setWindowSize( width, height ); |
|
| 472 |
settings->setMultiTouchEnabled( false ); |
|
| 473 |
settings->disableFrameRate(); |
|
| 450 |
settings->setWindowSize( 1920, 1080 ); |
|
| 451 |
settings->setMultiTouchEnabled( false ); |
|
| 452 |
settings->disableFrameRate(); |
|
| 474 | 453 |
|
| 475 | 454 |
} ) |
| CollidoscopeApp/src/Config.cpp | ||
|---|---|---|
| 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 |
#include "Config.h" |
| 23 | 2 |
|
| 24 | 3 |
|
| ... | ... | |
| 38 | 17 |
|
| 39 | 18 |
} |
| 40 | 19 |
|
| 41 |
// uses Cinder api to parse configuration in XML file |
|
| 20 |
|
|
| 42 | 21 |
void Config::loadFromFile( std::string&& path ) |
| 43 | 22 |
{
|
| 44 | 23 |
try {
|
| CollidoscopeApp/src/Log.cpp | ||
|---|---|---|
| 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 |
|
| 23 | 2 |
#include "cinder/Log.h" |
| 24 | 3 |
|
| CollidoscopeApp/src/MIDI.cpp | ||
|---|---|---|
| 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 |
#include "MIDI.h" |
| 23 | 2 |
#include "Config.h" |
| 24 | 3 |
|
| ... | ... | |
| 152 | 131 |
msg.mData2 = (numBytes == 3 ? (*rtMidiMessage)[2] : 0); |
| 153 | 132 |
|
| 154 | 133 |
return msg; |
| 155 |
} |
|
| 134 |
} |
|
| CollidoscopeApp/src/PGranularNode.cpp | ||
|---|---|---|
| 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 |
#include "PGranularNode.h" |
| 23 | 2 |
|
| 24 | 3 |
#include "cinder/audio/Context.h" |
| ... | ... | |
| 65 | 44 |
{
|
| 66 | 45 |
mTempBuffer = std::make_shared< ci::audio::Buffer >( getFramesPerBlock() ); |
| 67 | 46 |
|
| 68 |
mRandomOffset.reset( new RandomGenerator( getSampleRate() / 100 ) ); // divided by 100 corresponds to multiplied by 0.01 in the time domain
|
|
| 47 |
mRandomOffset.reset( new RandomGenerator( getSampleRate() / 100 ) ); // divided by 100 corresponds to times 0.01 in the time domain
|
|
| 69 | 48 |
|
| 70 | 49 |
/* create the PGranular object for looping */ |
| 71 | 50 |
mPGranularLoop.reset( new collidoscope::PGranular<float, RandomGenerator, PGranularNode>( mGrainBuffer->getData(), mGrainBuffer->getNumFrames(), getSampleRate(), *mRandomOffset, *this, -1 ) ); |
| ... | ... | |
| 80 | 59 |
void PGranularNode::process (ci::audio::Buffer *buffer ) |
| 81 | 60 |
{
|
| 82 | 61 |
// only update PGranular if the atomic value has changed from the previous time |
| 62 |
|
|
| 83 | 63 |
const boost::optional<size_t> selectionSize = mSelectionSize.get(); |
| 84 | 64 |
if ( selectionSize ){
|
| 85 | 65 |
mPGranularLoop->setSelectionSize( *selectionSize ); |
| ... | ... | |
| 132 | 112 |
} |
| 133 | 113 |
} |
| 134 | 114 |
|
| 135 |
// Called back when new PGranular is triggered or turned off. Sends notification message to graphic thread. |
|
| 136 | 115 |
void PGranularNode::operator()( char msgType, int ID ) {
|
| 137 | 116 |
|
| 138 | 117 |
switch ( msgType ){
|
| ... | ... | |
| 167 | 146 |
} |
| 168 | 147 |
|
| 169 | 148 |
if ( !synthFound ){
|
| 170 |
// then look for a free voice
|
|
| 149 |
// then look for a free synth
|
|
| 171 | 150 |
for ( int i = 0; i < kMaxVoices; i++ ){
|
| 172 | 151 |
|
| 173 | 152 |
if ( mMidiNotes[i] == kNoMidiNote ){
|
| CollidoscopeApp/src/ParticleController.cpp | ||
|---|---|---|
| 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 |
#include "ParticleController.h" |
| 25 | 2 |
#include "cinder/Rand.h" |
| 26 | 3 |
|
| ... | ... | |
| 33 | 10 |
mNumParticles( 0 ) |
| 34 | 11 |
|
| 35 | 12 |
{
|
| 36 |
// uses Cinder (and OpenGL) drawing based on virtual buffer object |
|
| 37 |
// see ParticleSphereCPU example in Cinder library |
|
| 38 |
|
|
| 39 | 13 |
mParticles.assign( kMaxParticles, Particle() ); |
| 40 | 14 |
mParticlePositions.assign( kMaxParticles, vec2( -1, -1 ) ); |
| 41 | 15 |
|
| ... | ... | |
| 46 | 20 |
|
| 47 | 21 |
auto mesh = gl::VboMesh::create( mParticlePositions.size(), GL_POINTS, { { particleLayout, mParticleVbo } } );
|
| 48 | 22 |
|
| 49 |
// creates glsl program to run the batch with |
|
| 50 | 23 |
#if ! defined( CINDER_GL_ES ) |
| 51 | 24 |
auto glsl = gl::GlslProg::create( gl::GlslProg::Format() |
| 52 | 25 |
.vertex( CI_GLSL( 150, |
| ... | ... | |
| 97 | 70 |
|
| 98 | 71 |
void ParticleController::updateParticles() |
| 99 | 72 |
{
|
| 100 |
// update the positions of the particles and dispose them if they've reached their timespan |
|
| 101 | 73 |
for ( size_t i = 0; i < mNumParticles; i++ ){
|
| 102 | 74 |
|
| 103 | 75 |
Particle &particle = mParticles[i]; |
| ... | ... | |
| 123 | 95 |
} |
| 124 | 96 |
} |
| 125 | 97 |
|
| 126 |
// Copy particle data onto the GPU. |
|
| 127 |
// Map the GPU memory and write over it. |
|
| 128 | 98 |
void *gpuMem = mParticleVbo->mapReplace(); |
| 129 | 99 |
memcpy( gpuMem, mParticlePositions.data(), mParticlePositions.size() * sizeof( vec2 ) ); |
| 130 | 100 |
mParticleVbo->unmap(); |
| ... | ... | |
| 132 | 102 |
|
| 133 | 103 |
void ParticleController::addParticles(int amount, const vec2 &initialLocation, const float cloudSize) |
| 134 | 104 |
{
|
| 135 |
// reduce the particles linearly to the total number of particles already present |
|
| 136 |
// the more particles aleary present the less particle are added |
|
| 137 | 105 |
int reduction = ci::lmap<int>(mNumParticles, 0, kMaxParticles, 0, kMaxParticleAdd); |
| 138 | 106 |
amount -= reduction; |
| 139 | 107 |
|
| 140 | 108 |
if ( mNumParticles + amount > kMaxParticles ){
|
| 141 |
//a.k.a. return if reached kMaxParticles
|
|
| 109 |
//return;
|
|
| 142 | 110 |
amount = kMaxParticles - mNumParticles; |
| 143 | 111 |
} |
| 144 | 112 |
|
| CollidoscopeApp/src/Wave.cpp | ||
|---|---|---|
| 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 |
#include "Wave.h" |
| 25 | 2 |
#include "DrawInfo.h" |
| 26 | 3 |
|
| ... | ... | |
| 29 | 6 |
|
| 30 | 7 |
Wave::Wave( size_t numChunks, Color selectionColor ): |
| 31 | 8 |
mNumChunks( numChunks ), |
| 32 |
mSelection( this, selectionColor ),
|
|
| 33 |
mColor(Color(0.5f, 0.5f, 0.5f)),
|
|
| 9 |
mSelection( this, selectionColor ),
|
|
| 10 |
mColor(Color(0.5f, 0.5f, 0.5f)),
|
|
| 34 | 11 |
mFilterCoeff( 1.0f ) |
| 35 | 12 |
{
|
| 36 |
mChunks.reserve( numChunks );
|
|
| 13 |
mChunks.reserve( numChunks );
|
|
| 37 | 14 |
|
| 38 |
for ( size_t i = 0; i < numChunks; i++ ){
|
|
| 39 |
mChunks.emplace_back( i );
|
|
| 40 |
}
|
|
| 15 |
for ( size_t i = 0; i < numChunks; i++ ){
|
|
| 16 |
mChunks.emplace_back( i );
|
|
| 17 |
}
|
|
| 41 | 18 |
|
| 42 |
// init cinder batch drawing |
|
| 43 | 19 |
auto lambert = gl::ShaderDef().color(); |
| 44 | 20 |
gl::GlslProgRef shader = gl::getStockShader( lambert ); |
| 45 | 21 |
mChunkBatch = gl::Batch::create( geom::Rect( ci::Rectf( 0, 0, Chunk::kWidth, 1 ) ), shader ); |
| ... | ... | |
| 47 | 23 |
|
| 48 | 24 |
void Wave::reset( bool onlyChunks ) |
| 49 | 25 |
{
|
| 50 |
for (size_t i = 0; i < getSize(); i++){
|
|
| 51 |
mChunks[i].reset();
|
|
| 52 |
}
|
|
| 26 |
for (size_t i = 0; i < getSize(); i++){
|
|
| 27 |
mChunks[i].reset();
|
|
| 28 |
}
|
|
| 53 | 29 |
|
| 54 |
if (onlyChunks)
|
|
| 55 |
return;
|
|
| 30 |
if (onlyChunks)
|
|
| 31 |
return;
|
|
| 56 | 32 |
|
| 57 |
mSelection.setToNull();
|
|
| 33 |
mSelection.setToNull();
|
|
| 58 | 34 |
} |
| 59 | 35 |
|
| 60 | 36 |
|
| 61 | 37 |
void Wave::setChunk(size_t index, float bottom, float top) |
| 62 | 38 |
{
|
| 63 |
Chunk &c = mChunks[index];
|
|
| 64 |
c.setTop(top);
|
|
| 65 |
c.setBottom(bottom);
|
|
| 39 |
Chunk &c = mChunks[index];
|
|
| 40 |
c.setTop(top);
|
|
| 41 |
c.setBottom(bottom);
|
|
| 66 | 42 |
} |
| 67 | 43 |
|
| 68 | 44 |
inline const Chunk & Wave::getChunk(size_t index) |
| 69 | 45 |
{
|
| 70 |
return mChunks[index];
|
|
| 46 |
return mChunks[index];
|
|
| 71 | 47 |
} |
| 72 | 48 |
|
| 73 | 49 |
void Wave::update( double secondsPerChunk, const DrawInfo& di ) {
|
| ... | ... | |
| 87 | 63 |
|
| 88 | 64 |
double elapsed = now - itr->second.lastUpdate; |
| 89 | 65 |
|
| 90 |
// A chunk of audio corresponds to a certain time lenght of audio, according to sample rate. |
|
| 91 |
// Use elapsed time to advance through chunks so that the cursor is animated. |
|
| 92 |
// So it goes from start to end of the selection in the time span of the grain |
|
| 93 | 66 |
itr->second.pos = mSelection.getStart() + int( elapsed / secondsPerChunk ); |
| 94 | 67 |
|
| 95 |
// check we don't go too far off
|
|
| 68 |
/* check we don't go too far off */
|
|
| 96 | 69 |
if (itr->second.pos > mSelection.getEnd()){
|
| 97 | 70 |
itr->second.pos = Cursor::kNoPosition; |
| 98 | 71 |
} |
| ... | ... | |
| 112 | 85 |
void Wave::draw( const DrawInfo& di ){
|
| 113 | 86 |
|
| 114 | 87 |
|
| 115 |
/* ########### draw the particles ########## */
|
|
| 88 |
/* ########### draw the particles ########## */
|
|
| 116 | 89 |
#ifdef USE_PARTICLES |
| 117 |
mParticleController.draw();
|
|
| 90 |
mParticleController.draw();
|
|
| 118 | 91 |
#endif |
| 119 | 92 |
|
| 120 |
/* ########### draw the wave ########## */
|
|
| 121 |
/* scale the wave to fit the window */
|
|
| 122 |
gl::pushModelView();
|
|
| 93 |
/* ########### draw the wave ########## */
|
|
| 94 |
/* scale the wave to fit the window */
|
|
| 95 |
gl::pushModelView();
|
|
| 123 | 96 |
|
| 124 |
|
|
| 125 |
const float wavePixelLen = ( mNumChunks * ( 2 + Chunk::kWidth ) );
|
|
| 126 |
/* scale the x-axis for the wave to fit the window precisely */
|
|
| 127 |
gl::scale( ((float)di.getWindowWidth() ) / wavePixelLen , 1.0f);
|
|
| 128 |
/* draw the chunks */
|
|
| 129 |
if (mSelection.isNull()){
|
|
| 130 |
/* no selection: all chunks the same color */
|
|
| 131 |
gl::color(mColor);
|
|
| 132 |
for (size_t i = 0; i < getSize(); i++){
|
|
| 133 |
mChunks[i].draw( di, mChunkBatch );
|
|
| 134 |
}
|
|
| 135 |
}
|
|
| 97 |
|
|
| 98 |
const float wavePixelLen = ( mNumChunks * ( 2 + Chunk::kWidth ) );
|
|
| 99 |
/* scale the x-axis for the wave to fit the window */
|
|
| 100 |
gl::scale( ((float)di.getWindowWidth() ) / wavePixelLen , 1.0f);
|
|
| 101 |
/* draw the chunks */
|
|
| 102 |
if (mSelection.isNull()){
|
|
| 103 |
/* no selection: all chunks the same color */
|
|
| 104 |
gl::color(mColor);
|
|
| 105 |
for (size_t i = 0; i < getSize(); i++){
|
|
| 106 |
mChunks[i].draw( di, mChunkBatch );
|
|
| 107 |
}
|
|
| 108 |
}
|
|
| 136 | 109 |
else{
|
| 137 | 110 |
// Selection not null |
| 138 |
gl::color(this->mColor);
|
|
| 111 |
gl::color(this->mColor);
|
|
| 139 | 112 |
|
| 140 | 113 |
// update the array with cursor positions |
| 141 | 114 |
mCursorsPos.clear(); |
| ... | ... | |
| 143 | 116 |
mCursorsPos.push_back( cursor.second.pos ); |
| 144 | 117 |
} |
| 145 | 118 |
|
| 146 |
gl::enableAlphaBlending();
|
|
| 119 |
gl::enableAlphaBlending();
|
|
| 147 | 120 |
|
| 148 |
const float selectionAlpha = 0.5f + mFilterCoeff * 0.5f;
|
|
| 121 |
const float selectionAlpha = 0.5f + mFilterCoeff * 0.5f;
|
|
| 149 | 122 |
|
| 150 | 123 |
|
| 151 |
for (size_t i = 0; i < getSize(); i++){
|
|
| 152 |
/* when in selection use selection color */
|
|
| 153 |
|
|
| 154 |
if (i == mSelection.getStart()){
|
|
| 155 |
/* draw the selection bar with a transparent selection color */
|
|
| 156 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
|
|
| 124 |
for (size_t i = 0; i < getSize(); i++){
|
|
| 125 |
/* when in selection use selection color */
|
|
| 126 |
|
|
| 127 |
if (i == mSelection.getStart()){
|
|
| 128 |
/* draw the selection bar with a transparent selection color */
|
|
| 129 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
|
|
| 157 | 130 |
mChunks[i].drawBar( di, mChunkBatch ); |
| 158 | 131 |
|
| 159 |
/* set the color to the selection */
|
|
| 160 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
|
|
| 161 |
}
|
|
| 132 |
/* set the color to the selection */
|
|
| 133 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
|
|
| 134 |
}
|
|
| 162 | 135 |
|
| 163 |
// check if one of the cursors is positioned in this chunk, and draw it white if it is
|
|
| 164 |
if (std::find(mCursorsPos.begin(), mCursorsPos.end(),i) != mCursorsPos.end() ){
|
|
| 165 |
gl::color(CURSOR_CLR);
|
|
| 166 |
mChunks[i].draw( di, mChunkBatch );
|
|
| 167 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
|
|
| 168 |
}
|
|
| 169 |
else{
|
|
| 170 |
/* just draw with current color */
|
|
| 171 |
mChunks[i].draw( di, mChunkBatch );
|
|
| 172 |
}
|
|
| 173 |
|
|
| 174 |
/* exit selection: go back to wave color */
|
|
| 175 |
if (i == mSelection.getEnd()){
|
|
| 176 |
/* draw the selection bar with a transparent selection color */
|
|
| 177 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
|
|
| 136 |
// check if one of the cursors is positioned in this chunk
|
|
| 137 |
if (std::find(mCursorsPos.begin(), mCursorsPos.end(),i) != mCursorsPos.end() ){
|
|
| 138 |
gl::color(CURSOR_CLR);
|
|
| 139 |
mChunks[i].draw( di, mChunkBatch );
|
|
| 140 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
|
|
| 141 |
}
|
|
| 142 |
else{
|
|
| 143 |
/* just draw with current color */
|
|
| 144 |
mChunks[i].draw( di, mChunkBatch );
|
|
| 145 |
}
|
|
| 146 |
|
|
| 147 |
/* exit selection: go back to wave color */
|
|
| 148 |
if (i == mSelection.getEnd()){
|
|
| 149 |
/* draw the selection bar with a transparent selection color */
|
|
| 150 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
|
|
| 178 | 151 |
mChunks[i].drawBar( di, mChunkBatch ); |
| 179 |
/* set the color to the wave */
|
|
| 180 |
gl::color(this->mColor);
|
|
| 181 |
}
|
|
| 182 |
}
|
|
| 183 |
gl::disableAlphaBlending();
|
|
| 184 |
}
|
|
| 185 |
|
|
| 152 |
/* set the colo to the wave */
|
|
| 153 |
gl::color(this->mColor);
|
|
| 154 |
}
|
|
| 155 |
}
|
|
| 156 |
gl::disableAlphaBlending();
|
|
| 157 |
}
|
|
| 158 |
|
|
| 186 | 159 |
|
| 187 |
gl::popModelView();
|
|
| 160 |
gl::popModelView();
|
|
| 188 | 161 |
|
| 189 | 162 |
} |
| 190 | 163 |
|
| ... | ... | |
| 203 | 176 |
|
| 204 | 177 |
void Wave::Selection::setStart(size_t start) {
|
| 205 | 178 |
|
| 206 |
/* deselect the previous */
|
|
| 179 |
/* deselect the previous */
|
|
| 207 | 180 |
mWave->mChunks[mSelectionStart].setAsSelectionStart( false ); |
| 208 |
/* select the next */
|
|
| 181 |
/* select the next */
|
|
| 209 | 182 |
mWave->mChunks[start].setAsSelectionStart( true ); |
| 210 |
|
|
| 211 |
mNull = false;
|
|
| 183 |
|
|
| 184 |
mNull = false;
|
|
| 212 | 185 |
|
| 213 | 186 |
size_t size = getSize(); |
| 214 | 187 |
|
| 215 |
mSelectionStart = start;
|
|
| 188 |
mSelectionStart = start;
|
|
| 216 | 189 |
mSelectionEnd = start + size - 1; |
| 217 | 190 |
if ( mSelectionEnd > mWave->getSize() - 1 ) |
| 218 | 191 |
mSelectionEnd = mWave->getSize() - 1; |
| ... | ... | |
| 233 | 206 |
size = mWave->mNumChunks - mSelectionStart - 1; |
| 234 | 207 |
} |
| 235 | 208 |
|
| 236 |
/* deselect the previous */
|
|
| 209 |
/* deselect the previous */
|
|
| 237 | 210 |
mWave->mChunks[mSelectionEnd].setAsSelectionEnd( false ); |
| 238 | 211 |
|
| 239 | 212 |
mSelectionEnd = mSelectionStart + size; |
| 240 |
/* select the next */
|
|
| 213 |
/* select the next */
|
|
| 241 | 214 |
mWave->mChunks[mSelectionEnd].setAsSelectionEnd( true ); |
| 242 | 215 |
|
| 243 |
mNull = false;
|
|
| 216 |
mNull = false;
|
|
| 244 | 217 |
} |
| 245 | 218 |
|
| 246 | 219 |
|
Also available in: Unified diff