Revision 16:4dad0b810f18 CollidoscopeApp/src
| CollidoscopeApp/src/AudioEngine.cpp | ||
|---|---|---|
| 21 | 21 |
*/ |
| 22 | 22 |
|
| 23 | 23 |
#include "AudioEngine.h" |
| 24 |
// app.h include not used |
|
| 24 | 25 |
#include "cinder/app/App.h" |
| 25 |
//FIXME remove App.h include |
|
| 26 | 26 |
#include "Log.h" |
| 27 | 27 |
|
| 28 | 28 |
using namespace ci::audio; |
| ... | ... | |
| 87 | 87 |
/* audio context */ |
| 88 | 88 |
auto ctx = Context::master(); |
| 89 | 89 |
|
| 90 |
/* audio inpu device */ |
|
| 90 |
/* audio input device */
|
|
| 91 | 91 |
auto inputDeviceNode = ctx->createInputDeviceNode( Device::getDefaultInput() ); |
| 92 | 92 |
|
| 93 | 93 |
|
| ... | ... | |
| 102 | 102 |
/* this prevents the node from recording before record is pressed */ |
| 103 | 103 |
mBufferRecorderNodes[chan]->setAutoEnabled( false ); |
| 104 | 104 |
|
| 105 |
// route the input part of the audio graph. Two channels input goes into |
|
| 106 |
// one channel route and to one channel buffer recorder
|
|
| 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
|
|
| 107 | 107 |
inputDeviceNode >> mInputRouterNodes[chan]->route( chan, 0, 1 ) >> mBufferRecorderNodes[chan]; |
| 108 | 108 |
|
| 109 | 109 |
|
| 110 | 110 |
// create PGranular loops passing the buffer of the RecorderNode as argument to the contructor |
| 111 |
// use -1 as ID |
|
| 111 |
// use -1 as ID as the loop corresponds to no midi note
|
|
| 112 | 112 |
mPGranularNodes[chan] = ctx->makeNode( new PGranularNode( mBufferRecorderNodes[chan]->getRecorderBuffer(), mCursorTriggerRingBufferPacks[chan]->getBuffer() ) ); |
| 113 | 113 |
|
| 114 | 114 |
// create filter nodes |
| ... | ... | |
| 126 | 126 |
// filter goes to output |
| 127 | 127 |
mLowPassFilterNodes[chan] >> mOutputRouterNodes[chan]->route( 0, chan, 1 ) >> ctx->getOutput(); |
| 128 | 128 |
|
| 129 |
// what goes to output goes to scope
|
|
| 129 |
// what goes to output goes to oscilloscope as well
|
|
| 130 | 130 |
mLowPassFilterNodes[chan] >> mOutputMonitorNodes[chan]; |
| 131 | 131 |
|
| 132 | 132 |
} |
| CollidoscopeApp/src/Chunk.cpp | ||
|---|---|---|
| 44 | 44 |
void Chunk::update( const DrawInfo &di ) |
| 45 | 45 |
{
|
| 46 | 46 |
using namespace ci; |
| 47 |
/* if resetting animate the chunks to shrink to 0 size */ |
|
| 47 |
/* if resetting animate the chunks to nicely shrink to 0 size */
|
|
| 48 | 48 |
if ( mResetting ){
|
| 49 | 49 |
if ( mAnimate > 0.0f ){
|
| 50 | 50 |
mAnimate -= 0.1f; |
| ... | ... | |
| 64 | 64 |
} |
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 |
mX = di.flipX( 1 + (mIndex * (2 + kWidth)) ); // FIXME this should happen only once when resized
|
|
| 67 |
mX = di.flipX( 1 + (mIndex * (2 + kWidth)) ); // FIXME more efficient if it happens only once when resized
|
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 | 70 |
void Chunk::draw( const DrawInfo& di, ci::gl::BatchRef &batch ){
|
| ... | ... | |
| 74 | 74 |
|
| 75 | 75 |
const float chunkHeight = mAnimate * mAudioTop * di.getMaxChunkHeight(); |
| 76 | 76 |
|
| 77 |
// place the chunk in the right position brigns back the y of chunkHeight/2 so
|
|
| 77 |
// place the chunk in the right position brings back the y of chunkHeight/2 so
|
|
| 78 | 78 |
// so that after scaling the wave is still centered at the wave center |
| 79 | 79 |
gl::translate( mX, di.getWaveCenterY() - ( chunkHeight / 2 ) - 1 ); |
| 80 | 80 |
|
| 81 |
// FIXME todo use max between top and bottom |
|
| 82 | 81 |
// scale according to audio amplitude |
| 83 | 82 |
gl::scale( 1.0f, chunkHeight ); |
| 84 | 83 |
batch->draw(); |
| CollidoscopeApp/src/CollidoscopeApp.cpp | ||
|---|---|---|
| 65 | 65 |
array< shared_ptr< Wave >, NUM_WAVES > mWaves; |
| 66 | 66 |
array< shared_ptr< DrawInfo >, NUM_WAVES > mDrawInfos; |
| 67 | 67 |
array< shared_ptr< Oscilloscope >, NUM_WAVES > mOscilloscopes; |
| 68 |
// buffers to read the wave messages as a new wave gets recorded
|
|
| 68 |
// buffer to read the WAVE_* messages as a new wave gets recorded
|
|
| 69 | 69 |
array< RecordWaveMsg*, NUM_WAVES> mRecordWaveMessageBuffers; |
| 70 |
//buffer to read the TRIGGER_* messages as the pgranulars play |
|
| 70 | 71 |
array< vector< CursorTriggerMsg >, NUM_WAVES > mCursorTriggerMessagesBuffers; |
| 71 | 72 |
|
| 72 | 73 |
double mSecondsPerChunk; |
| CollidoscopeApp/src/PGranularNode.cpp | ||
|---|---|---|
| 65 | 65 |
{
|
| 66 | 66 |
mTempBuffer = std::make_shared< ci::audio::Buffer >( getFramesPerBlock() ); |
| 67 | 67 |
|
| 68 |
mRandomOffset.reset( new RandomGenerator( getSampleRate() / 100 ) ); // divided by 100 corresponds to times 0.01 in the time domain
|
|
| 68 |
mRandomOffset.reset( new RandomGenerator( getSampleRate() / 100 ) ); // divided by 100 corresponds to multiplied by 0.01 in the time domain
|
|
| 69 | 69 |
|
| 70 | 70 |
/* create the PGranular object for looping */ |
| 71 | 71 |
mPGranularLoop.reset( new collidoscope::PGranular<float, RandomGenerator, PGranularNode>( mGrainBuffer->getData(), mGrainBuffer->getNumFrames(), getSampleRate(), *mRandomOffset, *this, -1 ) ); |
| ... | ... | |
| 132 | 132 |
} |
| 133 | 133 |
} |
| 134 | 134 |
|
| 135 |
// Called back when new grnular is triggered of turned off. Sends notification message to graphic thread.
|
|
| 135 |
// Called back when new PGranular is triggered or turned off. Sends notification message to graphic thread.
|
|
| 136 | 136 |
void PGranularNode::operator()( char msgType, int ID ) {
|
| 137 | 137 |
|
| 138 | 138 |
switch ( msgType ){
|
| ... | ... | |
| 167 | 167 |
} |
| 168 | 168 |
|
| 169 | 169 |
if ( !synthFound ){
|
| 170 |
// then look for a free synth
|
|
| 170 |
// then look for a free voice
|
|
| 171 | 171 |
for ( int i = 0; i < kMaxVoices; i++ ){
|
| 172 | 172 |
|
| 173 | 173 |
if ( mMidiNotes[i] == kNoMidiNote ){
|
| CollidoscopeApp/src/ParticleController.cpp | ||
|---|---|---|
| 33 | 33 |
mNumParticles( 0 ) |
| 34 | 34 |
|
| 35 | 35 |
{
|
| 36 |
// uses Cinder (and OpenGL) virtual buffer object based drawing
|
|
| 36 |
// uses Cinder (and OpenGL) drawing based on virtual buffer object
|
|
| 37 | 37 |
// see ParticleSphereCPU example in Cinder library |
| 38 | 38 |
|
| 39 | 39 |
mParticles.assign( kMaxParticles, Particle() ); |
| ... | ... | |
| 97 | 97 |
|
| 98 | 98 |
void ParticleController::updateParticles() |
| 99 | 99 |
{
|
| 100 |
// update the positions of the particles and dispose them if they're reached their timespan
|
|
| 100 |
// update the positions of the particles and dispose them if they've reached their timespan
|
|
| 101 | 101 |
for ( size_t i = 0; i < mNumParticles; i++ ){
|
| 102 | 102 |
|
| 103 | 103 |
Particle &particle = mParticles[i]; |
| ... | ... | |
| 132 | 132 |
|
| 133 | 133 |
void ParticleController::addParticles(int amount, const vec2 &initialLocation, const float cloudSize) |
| 134 | 134 |
{
|
| 135 |
// reduce the particles liearly to the total number of particles already present |
|
| 135 |
// reduce the particles linearly to the total number of particles already present
|
|
| 136 | 136 |
// the more particles aleary present the less particle are added |
| 137 | 137 |
int reduction = ci::lmap<int>(mNumParticles, 0, kMaxParticles, 0, kMaxParticleAdd); |
| 138 | 138 |
amount -= reduction; |
| CollidoscopeApp/src/Wave.cpp | ||
|---|---|---|
| 87 | 87 |
|
| 88 | 88 |
double elapsed = now - itr->second.lastUpdate; |
| 89 | 89 |
|
| 90 |
// A chunk of audio corresponds to a certain time according to sample rate. |
|
| 91 |
// Use elapsed time to advance through chunks so that the cursor is animated |
|
| 92 |
// and goes from start to end of the seleciton in the time span of the grain
|
|
| 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 | 93 |
itr->second.pos = mSelection.getStart() + int( elapsed / secondsPerChunk ); |
| 94 | 94 |
|
| 95 | 95 |
// check we don't go too far off |
| ... | ... | |
| 160 | 160 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha); |
| 161 | 161 |
} |
| 162 | 162 |
|
| 163 |
// check if one of the cursors is positioned in this chunk
|
|
| 163 |
// check if one of the cursors is positioned in this chunk, and draw it white if it is
|
|
| 164 | 164 |
if (std::find(mCursorsPos.begin(), mCursorsPos.end(),i) != mCursorsPos.end() ){
|
| 165 | 165 |
gl::color(CURSOR_CLR); |
| 166 | 166 |
mChunks[i].draw( di, mChunkBatch ); |
| ... | ... | |
| 176 | 176 |
/* draw the selection bar with a transparent selection color */ |
| 177 | 177 |
gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f); |
| 178 | 178 |
mChunks[i].drawBar( di, mChunkBatch ); |
| 179 |
/* set the colo to the wave */ |
|
| 179 |
/* set the color to the wave */
|
|
| 180 | 180 |
gl::color(this->mColor); |
| 181 | 181 |
} |
| 182 | 182 |
} |
Also available in: Unified diff