mirror of
https://github.com/vale981/openAV-Luppp
synced 2025-03-04 16:51:37 -05:00
Some Tweaks again.
This commit is contained in:
parent
888e639c97
commit
b00eee264e
3 changed files with 116 additions and 120 deletions
|
@ -93,7 +93,8 @@ void ClipSelector::clipName(int clip, std::string name)
|
||||||
|
|
||||||
void ClipSelector::setClipBeats(int scene, int beats, bool isBeatsToRecord)
|
void ClipSelector::setClipBeats(int scene, int beats, bool isBeatsToRecord)
|
||||||
{
|
{
|
||||||
clips[scene].setBeats(beats, isBeatsToRecord);
|
clips[scene].setBeats(beats, isBeatsToRecord);
|
||||||
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
double getCairoTextWith(cairo_t * cr, const char * str)
|
double getCairoTextWith(cairo_t * cr, const char * str)
|
||||||
|
@ -286,10 +287,9 @@ void setRecordBarsCb(Fl_Widget *w, void* data)
|
||||||
long bars = (long)data;
|
long bars = (long)data;
|
||||||
if(bars == -2){
|
if(bars == -2){
|
||||||
const char* answer = fl_input("Enter a custom number: ");
|
const char* answer = fl_input("Enter a custom number: ");
|
||||||
bars = atoi(answer);
|
if(!answer || atoi(bars) <= 0|| atoi(bars) > MAX_BARS) {
|
||||||
if(!answer || bars <= 0|| bars > MAX_BARS) {
|
|
||||||
bars = -1;
|
bars = -1;
|
||||||
fl_message("Invalid Input. You may enter a number smaller than %i!", MAX_BARS);
|
fl_message("Please enter value between 1 and %.", MAX_BARS);
|
||||||
} else
|
} else
|
||||||
bars = atoi(answer);
|
bars = atoi(answer);
|
||||||
}
|
}
|
||||||
|
@ -367,7 +367,7 @@ int ClipSelector::handle(int event)
|
||||||
RECORD_BARS_MENU_ITEM(4),
|
RECORD_BARS_MENU_ITEM(4),
|
||||||
RECORD_BARS_MENU_ITEM(6),
|
RECORD_BARS_MENU_ITEM(6),
|
||||||
RECORD_BARS_MENU_ITEM(8),
|
RECORD_BARS_MENU_ITEM(8),
|
||||||
{"Endless", 0, setRecordBarsCb, (void*)-1, FL_MENU_DIVIDER | (clips[clipNum].getBeatsToRecord() <= 0) ? FL_ACTIVATE : 0
|
{"Endless", 0, setRecordBarsCb, (void*)-1, FL_MENU_DIVIDER | FL_MENU_RADIO | ((clips[clipNum].getBeatsToRecord() <= 0) ? FL_ACTIVATE : 0)
|
||||||
| empty ? 0 : FL_MENU_INACTIVE},
|
| empty ? 0 : FL_MENU_INACTIVE},
|
||||||
{"Custom", 0, setRecordBarsCb, (void*)-2, empty ? 0 : FL_MENU_INACTIVE},
|
{"Custom", 0, setRecordBarsCb, (void*)-2, empty ? 0 : FL_MENU_INACTIVE},
|
||||||
{0},
|
{0},
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
#define LUPPP_RETURN_WARNING 1
|
#define LUPPP_RETURN_WARNING 1
|
||||||
#define LUPPP_RETURN_ERROR 2
|
#define LUPPP_RETURN_ERROR 2
|
||||||
|
|
||||||
#define MAX_BARS 100
|
#define MAX_BARS 64
|
||||||
|
|
||||||
/// debug.hxx for printing convienience
|
/// debug.hxx for printing convienience
|
||||||
#include "debug.hxx"
|
#include "debug.hxx"
|
||||||
|
|
224
src/looper.cxx
224
src/looper.cxx
|
@ -31,50 +31,50 @@
|
||||||
extern Jack* jack;
|
extern Jack* jack;
|
||||||
|
|
||||||
Looper::Looper(int t) :
|
Looper::Looper(int t) :
|
||||||
AudioProcessor(),
|
AudioProcessor(),
|
||||||
TimeObserver(),
|
TimeObserver(),
|
||||||
track(t)
|
track(t)
|
||||||
{
|
{
|
||||||
uiUpdateConstant= jack->getSamplerate() / 30.f;
|
uiUpdateConstant= jack->getSamplerate() / 30.f;
|
||||||
uiUpdateCounter = jack->getSamplerate() / 30.f;
|
uiUpdateCounter = jack->getSamplerate() / 30.f;
|
||||||
|
|
||||||
// pre-zero the internal sample
|
// pre-zero the internal sample
|
||||||
//tmpRecordBuffer = (float*)malloc( sizeof(float) * MAX_BUFFER_SIZE );
|
//tmpRecordBuffer = (float*)malloc( sizeof(float) * MAX_BUFFER_SIZE );
|
||||||
//memset( tmpRecordBuffer, 0, sizeof(float) * MAX_BUFFER_SIZE );
|
//memset( tmpRecordBuffer, 0, sizeof(float) * MAX_BUFFER_SIZE );
|
||||||
|
|
||||||
for(int i = 0; i < NSCENES; i++ ) {
|
for(int i = 0; i < NSCENES; i++ ) {
|
||||||
clips[i] = new LooperClip(track, i);
|
clips[i] = new LooperClip(track, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpBuffer.resize( MAX_BUFFER_SIZE );
|
tmpBuffer.resize( MAX_BUFFER_SIZE );
|
||||||
|
|
||||||
fpb = 22050;
|
fpb = 22050;
|
||||||
|
|
||||||
// init faust pitch shift variables
|
// init faust pitch shift variables
|
||||||
fSamplingFreq = jack->getSamplerate();
|
fSamplingFreq = jack->getSamplerate();
|
||||||
IOTA = 0;
|
IOTA = 0;
|
||||||
|
|
||||||
//tmpRecordBuffer.resize(MAX_BUFFER_SIZE);
|
//tmpRecordBuffer.resize(MAX_BUFFER_SIZE);
|
||||||
|
|
||||||
for (int i=0; i<65536; i++)
|
for (int i=0; i<65536; i++)
|
||||||
fVec0[i] = 0;
|
fVec0[i] = 0;
|
||||||
for (int i=0; i<2; i++)
|
for (int i=0; i<2; i++)
|
||||||
fRec0[i] = 0;
|
fRec0[i] = 0;
|
||||||
semitoneShift = 0.0f;
|
semitoneShift = 0.0f;
|
||||||
windowSize = 1000;
|
windowSize = 1000;
|
||||||
crossfadeSize = 1000;
|
crossfadeSize = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
LooperClip* Looper::getClip(int scene)
|
LooperClip* Looper::getClip(int scene)
|
||||||
{
|
{
|
||||||
return clips[scene];
|
return clips[scene];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Looper::beat()
|
void Looper::beat()
|
||||||
{
|
{
|
||||||
//TODO needed?
|
//TODO needed?
|
||||||
//FIXME: Need to keep looperClips in sync when there exists no int N
|
//FIXME: Need to keep looperClips in sync when there exists no int N
|
||||||
// such that playSpeed*N==1
|
// such that playSpeed*N==1
|
||||||
// for(int i=0;i<NSCENES;i++)
|
// for(int i=0;i<NSCENES;i++)
|
||||||
// {
|
// {
|
||||||
// int iph=clips[i]->getPlayhead()+1.0;
|
// int iph=clips[i]->getPlayhead()+1.0;
|
||||||
|
@ -94,119 +94,115 @@ void Looper::beat()
|
||||||
|
|
||||||
void Looper::setRequestedBuffer(int s, AudioBuffer* ab)
|
void Looper::setRequestedBuffer(int s, AudioBuffer* ab)
|
||||||
{
|
{
|
||||||
clips[s]->setRequestedBuffer( ab );
|
clips[s]->setRequestedBuffer( ab );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Looper::setFpb(int f)
|
void Looper::setFpb(int f)
|
||||||
{
|
{
|
||||||
fpb = f;
|
fpb = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Looper::process(unsigned int nframes, Buffers* buffers)
|
void Looper::process(unsigned int nframes, Buffers* buffers)
|
||||||
{
|
{
|
||||||
// process each clip individually: this allows for playback of one clip,
|
// process each clip individually: this allows for playback of one clip,
|
||||||
// while another clip records.
|
// while another clip records.
|
||||||
for ( int clip = 0; clip < NSCENES; clip++ ) {
|
for ( int clip = 0; clip < NSCENES; clip++ ) {
|
||||||
// handle state of clip, and do what needs doing:
|
// handle state of clip, and do what needs doing:
|
||||||
// record into buffer, play from buffer, etc
|
// record into buffer, play from buffer, etc
|
||||||
if ( clips[clip]->recording() ) {
|
if ( clips[clip]->recording() ) {
|
||||||
if(clips[clip]->getBeatsToRecord() > 0 && clips[clip]->getBeats() >= clips[clip]->getBeatsToRecord() - 4)
|
if ( clips[clip]->recordSpaceAvailable() < LOOPER_SAMPLES_BEFORE_REQUEST &&
|
||||||
clips[clip]->queuePlay(true);
|
!clips[clip]->newBufferInTransit() ) {
|
||||||
|
EventLooperClipRequestBuffer e( track, clip, clips[clip]->audioBufferSize() + LOOPER_SAMPLES_UPDATE_SIZE);
|
||||||
|
writeToGuiRingbuffer( &e );
|
||||||
|
clips[clip]->newBufferInTransit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy data from input buffer to recording buffer
|
||||||
|
float* inputL = buffers->audio[Buffers::MASTER_INPUT_L];
|
||||||
|
float* inputR = buffers->audio[Buffers::MASTER_INPUT_R];
|
||||||
|
clips[clip]->record( nframes, inputL, inputR);
|
||||||
|
} else if ( clips[clip]->playing() ) {
|
||||||
|
// copy data into tmpBuffer, then pitch-stretch into track buffer
|
||||||
|
long targetFrames = clips[clip]->getBeats() * fpb;
|
||||||
|
long actualFrames = clips[clip]->getActualAudioLength();//getBufferLenght();
|
||||||
|
float playSpeed = 1.0;
|
||||||
|
|
||||||
if ( clips[clip]->recordSpaceAvailable() < LOOPER_SAMPLES_BEFORE_REQUEST &&
|
if ( targetFrames != 0 && actualFrames != 0 ) {
|
||||||
!clips[clip]->newBufferInTransit() ) {
|
playSpeed = float(actualFrames) / targetFrames;
|
||||||
EventLooperClipRequestBuffer e( track, clip, clips[clip]->audioBufferSize() + LOOPER_SAMPLES_UPDATE_SIZE);
|
}
|
||||||
writeToGuiRingbuffer( &e );
|
|
||||||
clips[clip]->newBufferInTransit(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy data from input buffer to recording buffer
|
float* outL = buffers->audio[Buffers::SEND_TRACK_0_L + track];
|
||||||
float* inputL = buffers->audio[Buffers::MASTER_INPUT_L];
|
float* outR = buffers->audio[Buffers::SEND_TRACK_0_R + track];
|
||||||
float* inputR = buffers->audio[Buffers::MASTER_INPUT_R];
|
|
||||||
clips[clip]->record( nframes, inputL, inputR);
|
|
||||||
} else if ( clips[clip]->playing() ) {
|
|
||||||
// copy data into tmpBuffer, then pitch-stretch into track buffer
|
|
||||||
long targetFrames = clips[clip]->getBeats() * fpb;
|
|
||||||
long actualFrames = clips[clip]->getActualAudioLength();//getBufferLenght();
|
|
||||||
float playSpeed = 1.0;
|
|
||||||
|
|
||||||
if ( targetFrames != 0 && actualFrames != 0 ) {
|
for(unsigned int i = 0; i < nframes; i++ ) {
|
||||||
playSpeed = float(actualFrames) / targetFrames;
|
// REFACTOR into system that is better than per sample function calls
|
||||||
}
|
float tmpL = 0;
|
||||||
|
float tmpR = 0;
|
||||||
|
clips[clip]->getSample(playSpeed, &tmpL, &tmpR);
|
||||||
|
|
||||||
float* outL = buffers->audio[Buffers::SEND_TRACK_0_L + track];
|
float deltaPitch = 12 * log ( playSpeed ) / log (2);
|
||||||
float* outR = buffers->audio[Buffers::SEND_TRACK_0_R + track];
|
semitoneShift = -deltaPitch;
|
||||||
|
|
||||||
for(unsigned int i = 0; i < nframes; i++ ) {
|
// write the pitch-shifted signal to the track buffer
|
||||||
// REFACTOR into system that is better than per sample function calls
|
//FIXME: pitchShift adds delay even for playSpeed = 1.0!!
|
||||||
float tmpL = 0;
|
//we should use something better (e.g librubberband)
|
||||||
float tmpR = 0;
|
if(0) { //playSpeed!=1.0f) {
|
||||||
clips[clip]->getSample(playSpeed, &tmpL, &tmpR);
|
pitchShift( 1, &tmpL, &outL[i] );
|
||||||
|
pitchShift( 1, &tmpR, &outR[i] );
|
||||||
|
} else {
|
||||||
|
outL[i]+=tmpL;
|
||||||
|
outR[i]+=tmpR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float deltaPitch = 12 * log ( playSpeed ) / log (2);
|
//printf("Looper %i playing(), speed = %f\n", track, playSpeed );
|
||||||
semitoneShift = -deltaPitch;
|
|
||||||
|
|
||||||
// write the pitch-shifted signal to the track buffer
|
if ( uiUpdateCounter > uiUpdateConstant ) {
|
||||||
//FIXME: pitchShift adds delay even for playSpeed = 1.0!!
|
jack->getControllerUpdater()->setTrackSceneProgress(track, clip, clips[clip]->getProgress() );
|
||||||
//we should use something better (e.g librubberband)
|
uiUpdateCounter = 0;
|
||||||
if(0) { //playSpeed!=1.0f) {
|
}
|
||||||
pitchShift( 1, &tmpL, &outL[i] );
|
uiUpdateCounter += nframes;
|
||||||
pitchShift( 1, &tmpR, &outR[i] );
|
}
|
||||||
} else {
|
|
||||||
outL[i]+=tmpL;
|
|
||||||
outR[i]+=tmpR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("Looper %i playing(), speed = %f\n", track, playSpeed );
|
}
|
||||||
|
|
||||||
if ( uiUpdateCounter > uiUpdateConstant ) {
|
|
||||||
jack->getControllerUpdater()->setTrackSceneProgress(track, clip, clips[clip]->getProgress() );
|
|
||||||
uiUpdateCounter = 0;
|
|
||||||
}
|
|
||||||
uiUpdateCounter += nframes;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Looper::resetTimeState()
|
void Looper::resetTimeState()
|
||||||
{
|
{
|
||||||
for(int i=0; i<NSCENES; i++)
|
for(int i=0; i<NSCENES; i++)
|
||||||
clips[i]->setPlayHead(0.0);
|
clips[i]->setPlayHead(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Looper::pitchShift(int count, float* input, float* output)
|
void Looper::pitchShift(int count, float* input, float* output)
|
||||||
{
|
{
|
||||||
float fSlow0 = windowSize;
|
float fSlow0 = windowSize;
|
||||||
float fSlow1 = ((1 + fSlow0) - powf(2,(0.08333333333333333f * semitoneShift)));
|
float fSlow1 = ((1 + fSlow0) - powf(2,(0.08333333333333333f * semitoneShift)));
|
||||||
float fSlow2 = (1.0f / crossfadeSize);
|
float fSlow2 = (1.0f / crossfadeSize);
|
||||||
float fSlow3 = (fSlow0 - 1);
|
float fSlow3 = (fSlow0 - 1);
|
||||||
float* input0 = &input[0];
|
float* input0 = &input[0];
|
||||||
//float* output0 = &output[0];
|
//float* output0 = &output[0];
|
||||||
|
|
||||||
for (int i=0; i<count; i++) {
|
for (int i=0; i<count; i++) {
|
||||||
float fTemp0 = (float)input0[i];
|
float fTemp0 = (float)input0[i];
|
||||||
fVec0[IOTA&65535] = fTemp0;
|
fVec0[IOTA&65535] = fTemp0;
|
||||||
fRec0[0] = fmodf((fRec0[1] + fSlow1),fSlow0);
|
fRec0[0] = fmodf((fRec0[1] + fSlow1),fSlow0);
|
||||||
int iTemp1 = int(fRec0[0]);
|
int iTemp1 = int(fRec0[0]);
|
||||||
int iTemp2 = (1 + iTemp1);
|
int iTemp2 = (1 + iTemp1);
|
||||||
float fTemp3 = min((fSlow2 * fRec0[0]), 1.f );
|
float fTemp3 = min((fSlow2 * fRec0[0]), 1.f );
|
||||||
float fTemp4 = (fSlow0 + fRec0[0]);
|
float fTemp4 = (fSlow0 + fRec0[0]);
|
||||||
int iTemp5 = int(fTemp4);
|
int iTemp5 = int(fTemp4);
|
||||||
float out=output[0];
|
float out=output[0];
|
||||||
out += (float)(((1 - fTemp3) * (((fTemp4 - iTemp5) *
|
out += (float)(((1 - fTemp3) * (((fTemp4 - iTemp5) *
|
||||||
fVec0[(IOTA-int((int((1 + iTemp5)) & 65535)))&65535]) + ((0 - ((
|
fVec0[(IOTA-int((int((1 + iTemp5)) & 65535)))&65535]) + ((0 - ((
|
||||||
fRec0[0] + fSlow3) - iTemp5)) * fVec0[(IOTA-int((iTemp5 & 65535)))
|
fRec0[0] + fSlow3) - iTemp5)) * fVec0[(IOTA-int((iTemp5 & 65535)))
|
||||||
&65535]))) + (fTemp3 * (((fRec0[0] - iTemp1) * fVec0[(IOTA-int((int(
|
&65535]))) + (fTemp3 * (((fRec0[0] - iTemp1) * fVec0[(IOTA-int((int(
|
||||||
iTemp2) & 65535)))&65535]) + ((iTemp2 - fRec0[0]) * fVec0[(IOTA-int((
|
iTemp2) & 65535)))&65535]) + ((iTemp2 - fRec0[0]) * fVec0[(IOTA-int((
|
||||||
iTemp1 & 65535)))&65535]))));
|
iTemp1 & 65535)))&65535]))));
|
||||||
|
|
||||||
output[0]=out;
|
output[0]=out;
|
||||||
fRec0[1] = fRec0[0];
|
fRec0[1] = fRec0[0];
|
||||||
IOTA = IOTA+1;
|
IOTA = IOTA+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue