-Refactored LooperClip and TrackOutput
parent
f7fce45d4a
commit
ad74c72fea
|
@ -0,0 +1,154 @@
|
||||||
|
|
||||||
|
#include "looperclip.hxx"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "config.hxx"
|
||||||
|
#include "event.hxx"
|
||||||
|
#include "eventhandler.hxx"
|
||||||
|
#include "audiobuffer.hxx"
|
||||||
|
|
||||||
|
LooperClip::LooperClip()
|
||||||
|
{
|
||||||
|
_loaded = false;
|
||||||
|
_playing = false;
|
||||||
|
_recording = false;
|
||||||
|
|
||||||
|
_buffer = 0; //new AudioBuffer(44100);
|
||||||
|
_newBufferInTransit = false;
|
||||||
|
|
||||||
|
_playhead = 0;
|
||||||
|
_recordhead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// loads a sample: eg from disk, unloading current sample if necessary
|
||||||
|
void LooperClip::load( AudioBuffer* ab )
|
||||||
|
{
|
||||||
|
_loaded = true;
|
||||||
|
|
||||||
|
if ( _buffer )
|
||||||
|
{
|
||||||
|
EventDeallocateBuffer e( _buffer );
|
||||||
|
writeToGuiRingbuffer( &e );
|
||||||
|
}
|
||||||
|
|
||||||
|
_buffer = ab;
|
||||||
|
|
||||||
|
_playhead = 0;
|
||||||
|
|
||||||
|
// set the endpoint to the buffer's size
|
||||||
|
_recordhead = _buffer->getData().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LooperClip::setRequestedBuffer( AudioBuffer* ab )
|
||||||
|
{
|
||||||
|
if ( _buffer )
|
||||||
|
{
|
||||||
|
size_t size = _buffer->getData().size();
|
||||||
|
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
ab->getData().at(i) = _buffer->getData().at( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
EventDeallocateBuffer e( _buffer );
|
||||||
|
writeToGuiRingbuffer( &e );
|
||||||
|
}
|
||||||
|
|
||||||
|
_buffer = ab;
|
||||||
|
|
||||||
|
_newBufferInTransit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LooperClip::record(int count, float* L, float* R)
|
||||||
|
{
|
||||||
|
// write "count" samples into current buffer.
|
||||||
|
if ( _buffer )
|
||||||
|
{
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
_buffer->getData().at( _recordhead ) = *L++;
|
||||||
|
_recordhead++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long LooperClip::recordSpaceAvailable()
|
||||||
|
{
|
||||||
|
if ( _buffer )
|
||||||
|
return _buffer->getData().size() - _recordhead;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t LooperClip::audioBufferSize()
|
||||||
|
{
|
||||||
|
if ( _buffer )
|
||||||
|
{
|
||||||
|
return _buffer->getData().size();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LooperClip::setBeats(int beats)
|
||||||
|
{
|
||||||
|
if ( _buffer )
|
||||||
|
{
|
||||||
|
_buffer->setBeats( beats );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int LooperClip::getBeats()
|
||||||
|
{
|
||||||
|
if ( _buffer )
|
||||||
|
return _buffer->getBeats();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long LooperClip::getBufferLenght()
|
||||||
|
{
|
||||||
|
return _recordhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LooperClip::loaded(){return _loaded;}
|
||||||
|
void LooperClip::playing(bool p){_playing = p; _playhead = 0; }
|
||||||
|
bool LooperClip::playing(){return _playing;}
|
||||||
|
bool LooperClip::recording(){return _recording;}
|
||||||
|
void LooperClip::recording(bool r) {_recording = r;}
|
||||||
|
|
||||||
|
void LooperClip::newBufferInTransit(bool n){_newBufferInTransit = n;}
|
||||||
|
bool LooperClip::newBufferInTransit(){return _newBufferInTransit;}
|
||||||
|
|
||||||
|
float LooperClip::getSample(float playSpeed)
|
||||||
|
{
|
||||||
|
if ( _buffer )
|
||||||
|
{
|
||||||
|
if ( _playhead >= _recordhead ||
|
||||||
|
_playhead >= _buffer->getData().size() ||
|
||||||
|
_playhead < 0 )
|
||||||
|
{
|
||||||
|
_playhead = 0;
|
||||||
|
printf("looper resetting playhead\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float>& v = _buffer->getData();
|
||||||
|
float tmp = v.at(_playhead);
|
||||||
|
_playhead += playSpeed;
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float LooperClip::getProgress()
|
||||||
|
{
|
||||||
|
if ( _buffer && _playing )
|
||||||
|
{
|
||||||
|
float p = float(_playhead) / _recordhead;
|
||||||
|
//printf("LooperClip progress %f\n", p );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return 0.f;
|
||||||
|
}
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "config.hxx"
|
#include "config.hxx"
|
||||||
#include "eventhandler.hxx"
|
|
||||||
#include "audiobuffer.hxx"
|
class AudioBuffer;
|
||||||
|
|
||||||
/** LooperClip
|
/** LooperClip
|
||||||
* Represents each clip that a looper can playback. The core of the audio
|
* Represents each clip that a looper can playback. The core of the audio
|
||||||
|
@ -26,154 +26,40 @@
|
||||||
class LooperClip
|
class LooperClip
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LooperClip()
|
LooperClip();
|
||||||
{
|
|
||||||
_loaded = false;
|
|
||||||
_playing = false;
|
|
||||||
_recording = false;
|
|
||||||
|
|
||||||
_buffer = 0; //new AudioBuffer(44100);
|
|
||||||
_newBufferInTransit = false;
|
|
||||||
|
|
||||||
_playhead = 0;
|
|
||||||
_recordhead = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// loads a sample: eg from disk, unloading current sample if necessary
|
/// loads a sample: eg from disk, unloading current sample if necessary
|
||||||
void load( AudioBuffer* ab )
|
void load( AudioBuffer* ab );
|
||||||
{
|
|
||||||
_loaded = true;
|
|
||||||
|
|
||||||
if ( _buffer )
|
|
||||||
{
|
|
||||||
EventDeallocateBuffer e( _buffer );
|
|
||||||
writeToGuiRingbuffer( &e );
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer = ab;
|
|
||||||
|
|
||||||
_playhead = 0;
|
|
||||||
|
|
||||||
// set the endpoint to the buffer's size
|
|
||||||
_recordhead = _buffer->getData().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// used to update the size of the buffer for this looperclip. The current
|
/// used to update the size of the buffer for this looperclip. The current
|
||||||
/// data is copied into the new buffer, then the smaller buffer is sent
|
/// data is copied into the new buffer, then the smaller buffer is sent
|
||||||
/// for de-allocation
|
/// for de-allocation
|
||||||
void setRequestedBuffer( AudioBuffer* ab )
|
void setRequestedBuffer( AudioBuffer* ab );
|
||||||
{
|
|
||||||
if ( _buffer )
|
|
||||||
{
|
|
||||||
size_t size = _buffer->getData().size();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
ab->getData().at(i) = _buffer->getData().at( i );
|
|
||||||
}
|
|
||||||
|
|
||||||
EventDeallocateBuffer e( _buffer );
|
|
||||||
writeToGuiRingbuffer( &e );
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer = ab;
|
|
||||||
|
|
||||||
_newBufferInTransit = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void record(int count, float* L, float* R)
|
void record(int count, float* L, float* R);
|
||||||
{
|
|
||||||
// write "count" samples into current buffer.
|
|
||||||
if ( _buffer )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
_buffer->getData().at( _recordhead ) = *L++;
|
|
||||||
_recordhead++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long recordSpaceAvailable()
|
unsigned long recordSpaceAvailable();
|
||||||
{
|
|
||||||
if ( _buffer )
|
|
||||||
return _buffer->getData().size() - _recordhead;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t audioBufferSize()
|
size_t audioBufferSize();
|
||||||
{
|
|
||||||
if ( _buffer )
|
|
||||||
{
|
|
||||||
return _buffer->getData().size();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBeats(int beats)
|
void setBeats(int beats);
|
||||||
{
|
|
||||||
if ( _buffer )
|
|
||||||
{
|
|
||||||
_buffer->setBeats( beats );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int getBeats()
|
int getBeats();
|
||||||
{
|
|
||||||
if ( _buffer )
|
|
||||||
return _buffer->getBeats();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getBufferLenght()
|
long getBufferLenght();
|
||||||
{
|
|
||||||
return _recordhead;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool loaded(){return _loaded;}
|
bool loaded();
|
||||||
void playing(bool p){_playing = p; _playhead = 0; }
|
void playing(bool p);
|
||||||
bool playing(){return _playing;}
|
bool playing();
|
||||||
bool recording(){return _recording;}
|
bool recording();
|
||||||
void recording(bool r) {_recording = r;}
|
void recording(bool r);
|
||||||
|
|
||||||
void newBufferInTransit(bool n){_newBufferInTransit = n;}
|
void newBufferInTransit(bool n);
|
||||||
bool newBufferInTransit(){return _newBufferInTransit;}
|
bool newBufferInTransit();
|
||||||
|
|
||||||
float getSample(float playSpeed)
|
float getSample(float playSpeed);
|
||||||
{
|
|
||||||
if ( _buffer )
|
|
||||||
{
|
|
||||||
if ( _playhead >= _recordhead ||
|
|
||||||
_playhead >= _buffer->getData().size() ||
|
|
||||||
_playhead < 0 )
|
|
||||||
{
|
|
||||||
_playhead = 0;
|
|
||||||
printf("looper resetting playhead\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<float>& v = _buffer->getData();
|
|
||||||
float tmp = v.at(_playhead);
|
|
||||||
_playhead += playSpeed;
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getProgress()
|
float getProgress();
|
||||||
{
|
|
||||||
if ( _buffer && _playing )
|
|
||||||
{
|
|
||||||
float p = float(_playhead) / _recordhead;
|
|
||||||
//printf("LooperClip progress %f\n", p );
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _loaded;
|
bool _loaded;
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
|
||||||
|
#include "trackoutput.hxx"
|
||||||
|
|
||||||
|
TrackOutput::TrackOutput(int t, AudioProcessor* ap) :
|
||||||
|
AudioProcessor(),
|
||||||
|
track(t),
|
||||||
|
previousInChain(ap),
|
||||||
|
dbMeter(44100)
|
||||||
|
{
|
||||||
|
//printf("trackOutput ID: %i, ap = ", track );
|
||||||
|
//std::cout << ap << std::endl;
|
||||||
|
|
||||||
|
//_trackBuffer.resize( MAX_BUFFER_SIZE );
|
||||||
|
|
||||||
|
// UI update
|
||||||
|
uiUpdateConstant = 44100 / 30;
|
||||||
|
uiUpdateCounter = 44100 / 30;
|
||||||
|
|
||||||
|
_toReverb = 0.0;
|
||||||
|
_toMaster = 0.8;
|
||||||
|
_toSidechain = 0.0;
|
||||||
|
_toPostSidechain = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TrackOutput::setMaster(float value)
|
||||||
|
{
|
||||||
|
_toMaster = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float TrackOutput::getMaster()
|
||||||
|
{
|
||||||
|
return _toMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TrackOutput::setSend( int send, float value )
|
||||||
|
{
|
||||||
|
switch( send )
|
||||||
|
{
|
||||||
|
case SEND_REV:
|
||||||
|
_toReverb = value;
|
||||||
|
break;
|
||||||
|
case SEND_SIDE:
|
||||||
|
_toSidechain = value;
|
||||||
|
break;
|
||||||
|
case SEND_POST:
|
||||||
|
_toPostSidechain = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackOutput::process(int nframes, Buffers* buffers)
|
||||||
|
{
|
||||||
|
// zero track buffer
|
||||||
|
memset( &_trackBuffer[0], 0, nframes );
|
||||||
|
|
||||||
|
buffers->audio[Buffers::TRACK_0 + track] = &_trackBuffer[0];
|
||||||
|
previousInChain->process( nframes, buffers );
|
||||||
|
|
||||||
|
|
||||||
|
// run the meter
|
||||||
|
float* buf = &_trackBuffer[0];
|
||||||
|
dbMeter.process( nframes, buf, buf );
|
||||||
|
|
||||||
|
if (uiUpdateCounter > uiUpdateConstant )
|
||||||
|
{
|
||||||
|
// FIXME: should be using ControllerUpdater
|
||||||
|
EventTrackSignalLevel e( track, dbMeter.getLeftDB() * _toMaster, dbMeter.getRightDB() * _toMaster );
|
||||||
|
writeToGuiRingbuffer( &e );
|
||||||
|
uiUpdateCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiUpdateCounter += nframes;
|
||||||
|
|
||||||
|
|
||||||
|
// copy audio data into reverb / sidechain / master buffers
|
||||||
|
float* reverb = buffers->audio[Buffers::REVERB];
|
||||||
|
float* sidechain = buffers->audio[Buffers::SIDECHAIN];
|
||||||
|
float* postSidechain = buffers->audio[Buffers::POST_SIDECHAIN];
|
||||||
|
|
||||||
|
float* masterL = buffers->audio[Buffers::MASTER_OUT_L];
|
||||||
|
float* masterR = buffers->audio[Buffers::MASTER_OUT_R];
|
||||||
|
|
||||||
|
for(int i = 0; i < nframes; i++)
|
||||||
|
{
|
||||||
|
float tmp = _trackBuffer[i];
|
||||||
|
|
||||||
|
masterL[i] += tmp * _toMaster;
|
||||||
|
masterR[i] += tmp * _toMaster;
|
||||||
|
|
||||||
|
masterL++;
|
||||||
|
masterR++;
|
||||||
|
|
||||||
|
*reverb++ += tmp * _toReverb;
|
||||||
|
*sidechain++ += tmp * _toSidechain;
|
||||||
|
*postSidechain++ += tmp * _toPostSidechain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackOutput::~TrackOutput()
|
||||||
|
{
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "buffers.hxx"
|
||||||
#include "config.hxx"
|
#include "config.hxx"
|
||||||
#include "audioprocessor.hxx"
|
#include "audioprocessor.hxx"
|
||||||
|
|
||||||
|
@ -14,102 +15,20 @@
|
||||||
class TrackOutput : public AudioProcessor
|
class TrackOutput : public AudioProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TrackOutput(int t, AudioProcessor* ap) :
|
TrackOutput(int t, AudioProcessor* ap);
|
||||||
AudioProcessor(),
|
|
||||||
track(t),
|
|
||||||
_trackBuffer( MAX_BUFFER_SIZE, 0.f ),
|
|
||||||
previousInChain(ap),
|
|
||||||
dbMeter(44100)
|
|
||||||
{
|
|
||||||
printf("trackOutput ID: %i, ap = ", track );
|
|
||||||
std::cout << ap << std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
// UI update
|
|
||||||
uiUpdateConstant = 44100 / 30;
|
|
||||||
uiUpdateCounter = 44100 / 30;
|
|
||||||
|
|
||||||
_toReverb = 0.0;
|
|
||||||
_toMaster = 0.8;
|
|
||||||
_toSidechain = 0.0;
|
|
||||||
_toPostSidechain = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// set main mix, 0-1
|
/// set main mix, 0-1
|
||||||
void setMaster(float value)
|
void setMaster(float value);
|
||||||
{
|
|
||||||
_toMaster = value;
|
float getMaster();
|
||||||
}
|
|
||||||
|
|
||||||
/// set send
|
/// set send
|
||||||
void setSend( int send, float value )
|
void setSend( int send, float value );
|
||||||
{
|
|
||||||
switch( send )
|
|
||||||
{
|
|
||||||
case SEND_REV:
|
|
||||||
_toReverb = value;
|
|
||||||
break;
|
|
||||||
case SEND_SIDE:
|
|
||||||
_toSidechain = value;
|
|
||||||
break;
|
|
||||||
case SEND_POST:
|
|
||||||
_toPostSidechain = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// copies the track output to master buffer, sidechain & post-side buffer
|
/// copies the track output to master buffer, sidechain & post-side buffer
|
||||||
void process(int nframes, Buffers* buffers)
|
void process(int nframes, Buffers* buffers);
|
||||||
{
|
|
||||||
// zero track buffer
|
|
||||||
memset( &_trackBuffer[0], 0, nframes );
|
|
||||||
|
|
||||||
buffers->audio[Buffers::TRACK_0 + track] = &_trackBuffer[0];
|
|
||||||
previousInChain->process( nframes, buffers );
|
|
||||||
|
|
||||||
|
|
||||||
// run the meter
|
|
||||||
float* buf = &_trackBuffer[0];
|
|
||||||
dbMeter.process( nframes, buf, buf );
|
|
||||||
|
|
||||||
if (uiUpdateCounter > uiUpdateConstant )
|
|
||||||
{
|
|
||||||
// FIXME: should be using ControllerUpdater
|
|
||||||
EventTrackSignalLevel e( track, dbMeter.getLeftDB() * _toMaster, dbMeter.getRightDB() * _toMaster );
|
|
||||||
writeToGuiRingbuffer( &e );
|
|
||||||
uiUpdateCounter = 0;
|
|
||||||
}
|
|
||||||
uiUpdateCounter += nframes;
|
|
||||||
|
|
||||||
|
|
||||||
/// copy audio data into reverb / sidechain / master buffers
|
|
||||||
float* reverb = buffers->audio[Buffers::REVERB];
|
|
||||||
float* sidechain = buffers->audio[Buffers::SIDECHAIN];
|
|
||||||
float* postSidechain = buffers->audio[Buffers::POST_SIDECHAIN];
|
|
||||||
|
|
||||||
float* masterL = buffers->audio[Buffers::MASTER_OUT_L];
|
|
||||||
float* masterR = buffers->audio[Buffers::MASTER_OUT_R];
|
|
||||||
|
|
||||||
for(int i = 0; i < nframes; i++)
|
|
||||||
{
|
|
||||||
float tmp = _trackBuffer[i];
|
|
||||||
|
|
||||||
masterL[i] += tmp * _toMaster;
|
|
||||||
masterR[i] += tmp * _toMaster;
|
|
||||||
|
|
||||||
masterL++;
|
|
||||||
masterR++;
|
|
||||||
|
|
||||||
*reverb++ += tmp * _toReverb;
|
|
||||||
*sidechain++ += tmp * _toSidechain;
|
|
||||||
*postSidechain++ += tmp * _toPostSidechain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~TrackOutput()
|
~TrackOutput();
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int track;
|
int track;
|
||||||
|
|
Loading…
Reference in New Issue