mirror of
https://github.com/vale981/openAV-Luppp
synced 2025-03-05 09:01:39 -05:00
-Added Pitch-Shift code to looper, fixed some issues
This commit is contained in:
parent
8da62b87bf
commit
b45f635a12
4 changed files with 89 additions and 15 deletions
|
@ -7,6 +7,36 @@
|
||||||
|
|
||||||
extern Jack* jack;
|
extern Jack* jack;
|
||||||
|
|
||||||
|
Looper::Looper(int t) :
|
||||||
|
track(t),
|
||||||
|
state(STATE_STOPPED),
|
||||||
|
numBeats (4),
|
||||||
|
playedBeats(0),
|
||||||
|
stopRecordOnBar(false),
|
||||||
|
endPoint (0),
|
||||||
|
playPoint (0),
|
||||||
|
lastWrittenSampleIndex(0)
|
||||||
|
{
|
||||||
|
// init faust pitch shift variables
|
||||||
|
fSamplingFreq = 44100;
|
||||||
|
IOTA = 0;
|
||||||
|
|
||||||
|
int bufferSize = 1024;
|
||||||
|
|
||||||
|
for ( int i = 0; i < bufferSize; i++)
|
||||||
|
tmpBuffer.push_back(0.f);
|
||||||
|
|
||||||
|
for (int i=0; i<65536; i++)
|
||||||
|
fVec0[i] = 0;
|
||||||
|
|
||||||
|
semitoneShift = 0.0f;
|
||||||
|
windowSize = 1000;
|
||||||
|
crossfadeSize = 1000;
|
||||||
|
|
||||||
|
for (int i=0; i<2; i++)
|
||||||
|
fRec0[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Looper::setState(State s)
|
void Looper::setState(State s)
|
||||||
{
|
{
|
||||||
if ( state == STATE_RECORDING )
|
if ( state == STATE_RECORDING )
|
||||||
|
@ -37,7 +67,7 @@ void Looper::process(int nframes, Buffers* buffers)
|
||||||
{
|
{
|
||||||
if ( playPoint < endPoint )
|
if ( playPoint < endPoint )
|
||||||
{
|
{
|
||||||
out[i] += sample[playPoint];
|
tmpBuffer[i] += sample[playPoint];
|
||||||
}
|
}
|
||||||
// always update playPoint, even when not playing sound.
|
// always update playPoint, even when not playing sound.
|
||||||
// it updates the UI of progress
|
// it updates the UI of progress
|
||||||
|
@ -54,7 +84,6 @@ void Looper::process(int nframes, Buffers* buffers)
|
||||||
EventLooperProgress e(track, prog );
|
EventLooperProgress e(track, prog );
|
||||||
writeToGuiRingbuffer( &e );
|
writeToGuiRingbuffer( &e );
|
||||||
}
|
}
|
||||||
|
|
||||||
// stopRecordOnBar ensures we record right up to the bar measure
|
// stopRecordOnBar ensures we record right up to the bar measure
|
||||||
else if ( state == STATE_RECORDING || stopRecordOnBar )
|
else if ( state == STATE_RECORDING || stopRecordOnBar )
|
||||||
{
|
{
|
||||||
|
@ -66,6 +95,11 @@ void Looper::process(int nframes, Buffers* buffers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// not pitch-shift the audio in the buffer
|
||||||
|
pitchShift( nframes, &tmpBuffer[0], out);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,3 +167,34 @@ void Looper::setLoopLength(float l)
|
||||||
EventGuiPrint e( buffer );
|
EventGuiPrint e( buffer );
|
||||||
writeToGuiRingbuffer( &e );
|
writeToGuiRingbuffer( &e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Looper::pitchShift(int count, float* input, float* output)
|
||||||
|
{
|
||||||
|
float fSlow0 = windowSize;
|
||||||
|
float fSlow1 = ((1 + fSlow0) - powf(2,(0.08333333333333333f * semitoneShift)));
|
||||||
|
float fSlow2 = (1.0f / crossfadeSize);
|
||||||
|
float fSlow3 = (fSlow0 - 1);
|
||||||
|
float* input0 = &input[0];
|
||||||
|
float* output0 = &output[0];
|
||||||
|
|
||||||
|
for (int i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
float fTemp0 = (float)input0[i];
|
||||||
|
fVec0[IOTA&65535] = fTemp0;
|
||||||
|
fRec0[0] = fmodf((fRec0[1] + fSlow1),fSlow0);
|
||||||
|
int iTemp1 = int(fRec0[0]);
|
||||||
|
int iTemp2 = (1 + iTemp1);
|
||||||
|
float fTemp3 = min((fSlow2 * fRec0[0]), 1.f );
|
||||||
|
float fTemp4 = (fSlow0 + fRec0[0]);
|
||||||
|
int iTemp5 = int(fTemp4);
|
||||||
|
output0[i] += (float)(((1 - fTemp3) * (((fTemp4 - iTemp5) *
|
||||||
|
fVec0[(IOTA-int((int((1 + iTemp5)) & 65535)))&65535]) + ((0 - ((
|
||||||
|
fRec0[0] + fSlow3) - iTemp5)) * fVec0[(IOTA-int((iTemp5 & 65535)))
|
||||||
|
&65535]))) + (fTemp3 * (((fRec0[0] - iTemp1) * fVec0[(IOTA-int((int(
|
||||||
|
iTemp2) & 65535)))&65535]) + ((iTemp2 - fRec0[0]) * fVec0[(IOTA-int((
|
||||||
|
iTemp1 & 65535)))&65535]))));
|
||||||
|
fRec0[1] = fRec0[0];
|
||||||
|
IOTA = IOTA+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#ifndef LUPPP_LOOPER_H
|
#ifndef LUPPP_LOOPER_H
|
||||||
#define LUPPP_LOOPER_H
|
#define LUPPP_LOOPER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "buffers.hxx"
|
#include "buffers.hxx"
|
||||||
|
@ -21,16 +22,7 @@ class Looper : public Observer // for notifications
|
||||||
STATE_STOP_QUEUED,
|
STATE_STOP_QUEUED,
|
||||||
};
|
};
|
||||||
|
|
||||||
Looper(int t) :
|
Looper(int t);
|
||||||
track(t),
|
|
||||||
state(STATE_STOPPED),
|
|
||||||
numBeats (4),
|
|
||||||
playedBeats(0),
|
|
||||||
stopRecordOnBar(false),
|
|
||||||
endPoint (0),
|
|
||||||
playPoint (0),
|
|
||||||
lastWrittenSampleIndex(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void bar();
|
void bar();
|
||||||
void beat();
|
void beat();
|
||||||
|
@ -53,7 +45,17 @@ class Looper : public Observer // for notifications
|
||||||
|
|
||||||
int endPoint, playPoint, lastWrittenSampleIndex;
|
int endPoint, playPoint, lastWrittenSampleIndex;
|
||||||
float sample[44100*60];
|
float sample[44100*60];
|
||||||
|
|
||||||
|
// Pitch Shifting
|
||||||
|
void pitchShift(int count, float* input, float* output);
|
||||||
|
vector<float> tmpBuffer;
|
||||||
|
int IOTA;
|
||||||
|
float fVec0[65536];
|
||||||
|
float semitoneShift;
|
||||||
|
float windowSize;
|
||||||
|
float fRec0[2];
|
||||||
|
float crossfadeSize;
|
||||||
|
float fSamplingFreq;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LUPPP_LOOPER_H
|
#endif // LUPPP_LOOPER_H
|
||||||
|
|
|
@ -30,6 +30,9 @@ class Metronome : public Observer
|
||||||
beatSample[i]= sin(i*scale);
|
beatSample[i]= sin(i*scale);
|
||||||
barSample [i]= sin(i*scale*1.5);
|
barSample [i]= sin(i*scale*1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't play after creation
|
||||||
|
playPoint = endPoint + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setActive(bool a)
|
void setActive(bool a)
|
||||||
|
|
|
@ -18,7 +18,7 @@ class TimeManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TimeManager():
|
TimeManager():
|
||||||
fpb(120),
|
fpb(22050),
|
||||||
oldBeat(0)
|
oldBeat(0)
|
||||||
{
|
{
|
||||||
tapTempoPos = 0;
|
tapTempoPos = 0;
|
||||||
|
@ -29,11 +29,13 @@ class TimeManager
|
||||||
|
|
||||||
void setBpm(float bpm)
|
void setBpm(float bpm)
|
||||||
{
|
{
|
||||||
|
//cout << "setBpm() " << bpm << endl;
|
||||||
setFpb( 44100 / bpm * 60 );
|
setFpb( 44100 / bpm * 60 );
|
||||||
}
|
}
|
||||||
void setFpb(float f)
|
void setFpb(float f)
|
||||||
{
|
{
|
||||||
fpb = f;
|
fpb = f;
|
||||||
|
//cout << "setFpb() " << fpb << endl;
|
||||||
|
|
||||||
char buffer [50];
|
char buffer [50];
|
||||||
sprintf (buffer, "TM, setFpb() %i", int(f) );
|
sprintf (buffer, "TM, setFpb() %i", int(f) );
|
||||||
|
@ -48,6 +50,7 @@ class TimeManager
|
||||||
|
|
||||||
void registerObserver(Observer* o)
|
void registerObserver(Observer* o)
|
||||||
{
|
{
|
||||||
|
//cout << "registerObserver() " << fpb << endl;
|
||||||
observers.push_back(o);
|
observers.push_back(o);
|
||||||
o->setFpb( fpb );
|
o->setFpb( fpb );
|
||||||
}
|
}
|
||||||
|
@ -66,13 +69,14 @@ class TimeManager
|
||||||
int tapFpb2 = tapTempo[2] - tapTempo[1];
|
int tapFpb2 = tapTempo[2] - tapTempo[1];
|
||||||
|
|
||||||
int average = (tapFpb1 + tapFpb2) / 2;
|
int average = (tapFpb1 + tapFpb2) / 2;
|
||||||
setFpb(average);
|
|
||||||
|
|
||||||
char buffer [50];
|
char buffer [50];
|
||||||
sprintf (buffer, "TM, tap() average = %i", average );
|
sprintf (buffer, "TM, tap() average = %i", average );
|
||||||
EventGuiPrint e( buffer );
|
EventGuiPrint e( buffer );
|
||||||
writeToGuiRingbuffer( &e );
|
writeToGuiRingbuffer( &e );
|
||||||
|
|
||||||
|
setFpb(average);
|
||||||
|
|
||||||
// reset, so next 3 taps restart process
|
// reset, so next 3 taps restart process
|
||||||
tapTempoPos = 0;
|
tapTempoPos = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue