-Added Pitch-Shift code to looper, fixed some issues

This commit is contained in:
Harry van Haaren 2013-05-17 09:24:24 +01:00
parent 8da62b87bf
commit b45f635a12
4 changed files with 89 additions and 15 deletions

View file

@ -7,6 +7,36 @@
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)
{
if ( state == STATE_RECORDING )
@ -37,7 +67,7 @@ void Looper::process(int nframes, Buffers* buffers)
{
if ( playPoint < endPoint )
{
out[i] += sample[playPoint];
tmpBuffer[i] += sample[playPoint];
}
// always update playPoint, even when not playing sound.
// it updates the UI of progress
@ -54,7 +84,6 @@ void Looper::process(int nframes, Buffers* buffers)
EventLooperProgress e(track, prog );
writeToGuiRingbuffer( &e );
}
// stopRecordOnBar ensures we record right up to the bar measure
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 );
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;
}
}

View file

@ -2,6 +2,7 @@
#ifndef LUPPP_LOOPER_H
#define LUPPP_LOOPER_H
#include <vector>
#include <iostream>
#include "buffers.hxx"
@ -21,16 +22,7 @@ class Looper : public Observer // for notifications
STATE_STOP_QUEUED,
};
Looper(int t) :
track(t),
state(STATE_STOPPED),
numBeats (4),
playedBeats(0),
stopRecordOnBar(false),
endPoint (0),
playPoint (0),
lastWrittenSampleIndex(0)
{}
Looper(int t);
void bar();
void beat();
@ -53,7 +45,17 @@ class Looper : public Observer // for notifications
int endPoint, playPoint, lastWrittenSampleIndex;
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

View file

@ -30,6 +30,9 @@ class Metronome : public Observer
beatSample[i]= sin(i*scale);
barSample [i]= sin(i*scale*1.5);
}
// don't play after creation
playPoint = endPoint + 1;
}
void setActive(bool a)

View file

@ -18,7 +18,7 @@ class TimeManager
{
public:
TimeManager():
fpb(120),
fpb(22050),
oldBeat(0)
{
tapTempoPos = 0;
@ -29,11 +29,13 @@ class TimeManager
void setBpm(float bpm)
{
//cout << "setBpm() " << bpm << endl;
setFpb( 44100 / bpm * 60 );
}
void setFpb(float f)
{
fpb = f;
//cout << "setFpb() " << fpb << endl;
char buffer [50];
sprintf (buffer, "TM, setFpb() %i", int(f) );
@ -48,6 +50,7 @@ class TimeManager
void registerObserver(Observer* o)
{
//cout << "registerObserver() " << fpb << endl;
observers.push_back(o);
o->setFpb( fpb );
}
@ -66,13 +69,14 @@ class TimeManager
int tapFpb2 = tapTempo[2] - tapTempo[1];
int average = (tapFpb1 + tapFpb2) / 2;
setFpb(average);
char buffer [50];
sprintf (buffer, "TM, tap() average = %i", average );
EventGuiPrint e( buffer );
writeToGuiRingbuffer( &e );
setFpb(average);
// reset, so next 3 taps restart process
tapTempoPos = 0;
}