Use stereo input and stereo audio buffer

This commit is contained in:
coderkun 2017-03-19 12:45:04 +01:00 committed by Harry van Haaren
parent 6e8687592b
commit 59b146f052
11 changed files with 107 additions and 53 deletions

View file

@ -17,6 +17,7 @@
*/
#include "audiobuffer.hxx"
#include "config.hxx"
#include <stdio.h>
@ -31,7 +32,8 @@ AudioBuffer::AudioBuffer(unsigned long size)
// FIXME recorded buffers don't get an ID, using garbage IDs
/// no ID assigned: it *takes* the one from the previous buffer!
init();
buffer.resize(size);
bufferL.resize(size);
bufferR.resize(size);
}
void AudioBuffer::init()
@ -98,18 +100,32 @@ long AudioBuffer::getAudioFrames()
return audioFrames;
}
std::vector<float>& AudioBuffer::getData()
long AudioBuffer::getSize()
{
return buffer;
if(bufferL.size() != bufferR.size()) {
LUPPP_WARN("left and right channels of audio buffer have different size: %i vs %i", bufferL.size(), bufferR.size() );
}
return std::min(bufferL.size(), bufferR.size());
}
void AudioBuffer::nonRtSetSample(std::vector<float>& sample)
std::vector<float>& AudioBuffer::getDataL()
{
buffer.swap(sample);
return bufferL;
}
std::vector<float>& AudioBuffer::getDataR()
{
return bufferR;
}
void AudioBuffer::nonRtSetSample(std::vector<float>& sampleL, std::vector<float>& sampleR)
{
bufferL.swap(sampleL);
bufferR.swap(sampleR);
}
void AudioBuffer::nonRtResize(unsigned long size)
{
buffer.resize(size);
bufferL.resize(size);
bufferR.resize(size);
}
/*

View file

@ -52,9 +52,12 @@ public:
long getAudioFrames();
std::vector<float>& getData();
long getSize();
void nonRtSetSample(std::vector<float>& sample);
std::vector<float>& getDataL();
std::vector<float>& getDataR();
void nonRtSetSample(std::vector<float>& sampleL, std::vector<float>& sampleR);
void nonRtResize(unsigned long size);
@ -72,7 +75,8 @@ protected:
char name[20];
std::vector<float> buffer;
std::vector<float> bufferL;
std::vector<float> bufferR;
};
#endif

View file

@ -28,7 +28,8 @@ public:
enum BUFFER {
// AUDIO
MASTER_INPUT = 0,
MASTER_INPUT_L = 0,
MASTER_INPUT_R,
MASTER_OUT_L,
MASTER_OUT_R,

View file

@ -237,7 +237,8 @@ int DiskReader::loadSample( int track, int scene, string path )
/// create buffer, and set the data
AudioBuffer* ab = new AudioBuffer();
ab->setAudioFrames( buf.size() );
ab->nonRtSetSample( buf );
// TODO right (stereo)
ab->nonRtSetSample( buf, buf );
//cout << "DiskReader::loadSample() " << path << endl;

View file

@ -321,7 +321,8 @@ int DiskWriter::writeAudioBuffer(int track, int scene, AudioBuffer* ab,
// FIXME: the size of the buffer is bigger than the audio contained in it:
// calculate the length that needs saving using getBeats() * framesPerBeat
if ( ab->getAudioFrames() > 0 )
outfile.write( &ab->getData()[0], ab->getAudioFrames() );
// TODO right (stereo)
outfile.write( &ab->getDataL()[0], ab->getAudioFrames() );
else {
LUPPP_WARN("%s","Sample has zero samples");
}

View file

@ -102,7 +102,8 @@ void AudioEditor::show( AudioBuffer* buf, bool modal )
if ( !ab ) {
LUPPP_WARN("called with ab == 0");
} else {
std::vector<float>& tmp = ab->getData();
// TODO right (stereo)
std::vector<float>& tmp = ab->getDataL();
int size = tmp.size();
waveform->setData( &tmp[0], size );

View file

@ -109,11 +109,17 @@ Jack::Jack( std::string name ) :
uiUpdateCounter = buffers.samplerate / 30;
uiUpdateConstant = buffers.samplerate / 30;
masterInput = jack_port_register( client,
"master_in",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsInput,
0 );
masterInputL = jack_port_register( client,
"master_in_left",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsInput,
0 );
masterInputR = jack_port_register( client,
"master_in_right",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsInput,
0 );
masterReturnL = jack_port_register( client,
"master_return_left",
@ -367,7 +373,8 @@ void Jack::unregisterMidiIO( MidiIO* mo )
int Jack::process (jack_nframes_t nframes)
{
/// get buffers
buffers.audio[Buffers::MASTER_INPUT] = (float*)jack_port_get_buffer( masterInput , nframes );
buffers.audio[Buffers::MASTER_INPUT_L] = (float*)jack_port_get_buffer( masterInputL , nframes );
buffers.audio[Buffers::MASTER_INPUT_R] = (float*)jack_port_get_buffer( masterInputR , nframes );
buffers.audio[Buffers::MASTER_RETURN_L] = (float*)jack_port_get_buffer( masterReturnL , nframes );
buffers.audio[Buffers::MASTER_RETURN_R] = (float*)jack_port_get_buffer( masterReturnR , nframes );
buffers.audio[Buffers::HEADPHONES_OUT] = (float*)jack_port_get_buffer( headphonesPort , nframes );
@ -469,7 +476,8 @@ void Jack::processFrames(int nframes)
/// mix input, reverb & post-sidechain in
for(unsigned int i = 0; i < nframes; i++) {
float input= buffers.audio[Buffers::MASTER_INPUT][i] * inputVol;
float inputL = buffers.audio[Buffers::MASTER_INPUT_L][i] * inputVol;
float inputR = buffers.audio[Buffers::MASTER_INPUT_R][i] * inputVol;
float L = buffers.audio[Buffers::MASTER_OUT_L][i];
float R = buffers.audio[Buffers::MASTER_OUT_R][i];
@ -478,19 +486,23 @@ void Jack::processFrames(int nframes)
if ( inputToMixEnable ) {
// if sending to mix, scale by volume *and* by XSide send
float tmp = input * inputToMixVol * (1-inputToXSideVol);
L += tmp;
R += tmp;
float tmpL = inputL * inputToMixVol * (1-inputToXSideVol);
float tmpR = inputR * inputToMixVol * (1-inputToXSideVol);
L += tmpL;
R += tmpR;
}
if ( inputToSendEnable ) {
// post-mix-send amount: hence * inputToMixVol
buffers.audio[Buffers::SEND][i] += input * inputToSendVol * inputToMixVol;
// TODO input r (stereo send)
buffers.audio[Buffers::SEND][i] += inputL * inputToSendVol * inputToMixVol;
}
if ( inputToKeyEnable ) {
buffers.audio[Buffers::SIDECHAIN_KEY][i] += input;
// TODO input r (stereo key)
buffers.audio[Buffers::SIDECHAIN_KEY][i] += inputL;
}
buffers.audio[Buffers::SIDECHAIN_SIGNAL][i] += input * inputToXSideVol;
// TODO input r (stereo sidechain)
buffers.audio[Buffers::SIDECHAIN_SIGNAL][i] += inputL * inputToXSideVol;
//compute master volume lag;
if(fabs(masterVol-masterVolLag)>=fabs(masterVolDiff/10.0))
@ -507,7 +519,7 @@ void Jack::processFrames(int nframes)
/// db meter on master input & output
inputMeter->process( nframes, buffers.audio[Buffers::MASTER_INPUT], buffers.audio[Buffers::MASTER_INPUT]);
inputMeter->process( nframes, buffers.audio[Buffers::MASTER_INPUT_L], buffers.audio[Buffers::MASTER_INPUT_R]);
masterMeter->process(nframes, buffers.audio[Buffers::JACK_MASTER_OUT_L], buffers.audio[Buffers::JACK_MASTER_OUT_R] );
if ( uiUpdateCounter > uiUpdateConstant ) {
@ -541,7 +553,8 @@ void Jack::processFrames(int nframes)
/// update buffers by nframes
if(lastnframes+nframes<buffers.nframes) {
lastnframes=nframes;
buffers.audio[Buffers::MASTER_INPUT] = &buffers.audio[Buffers::MASTER_INPUT] [nframes];
buffers.audio[Buffers::MASTER_INPUT_L] = &buffers.audio[Buffers::MASTER_INPUT_L][nframes];
buffers.audio[Buffers::MASTER_INPUT_R] = &buffers.audio[Buffers::MASTER_INPUT_R][nframes];
buffers.audio[Buffers::MASTER_RETURN_L] = &buffers.audio[Buffers::MASTER_RETURN_L][nframes];
buffers.audio[Buffers::MASTER_RETURN_R] = &buffers.audio[Buffers::MASTER_RETURN_R][nframes];
buffers.audio[Buffers::HEADPHONES_OUT] = &buffers.audio[Buffers::HEADPHONES_OUT] [nframes];

View file

@ -173,7 +173,8 @@ private:
bool clientActive;
int samplerate;
jack_port_t* masterInput;
jack_port_t* masterInputL;
jack_port_t* masterInputR;
jack_port_t* masterOutputL;
jack_port_t* masterOutputR;

View file

@ -118,8 +118,9 @@ void Looper::process(unsigned int nframes, Buffers* buffers)
}
// copy data from input buffer to recording buffer
float* input = buffers->audio[Buffers::MASTER_INPUT];
clips[clip]->record( nframes, input, 0 );
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;
@ -130,11 +131,14 @@ void Looper::process(unsigned int nframes, Buffers* buffers)
playSpeed = float(actualFrames) / targetFrames;
}
// TODO stereo sends
float* out = buffers->audio[Buffers::SEND_TRACK_0 + track];
for(unsigned int i = 0; i < nframes; i++ ) {
// REFACTOR into system that is better than per sample function calls
float tmp = clips[clip]->getSample(playSpeed);
float tmpL = 0;
float tmpR = 0;
clips[clip]->getSample(playSpeed, &tmpL, &tmpR);
float deltaPitch = 12 * log ( playSpeed ) / log (2);
semitoneShift = -deltaPitch;
@ -143,9 +147,13 @@ void Looper::process(unsigned int nframes, Buffers* buffers)
//FIXME: pitchShift adds delay even for playSpeed = 1.0!!
//we should use something better (e.g librubberband)
if(playSpeed!=1.0f)
pitchShift( 1, &tmp, &out[i] );
pitchShift( 1, &tmpL, &out[i] );
// TODO stereo sends
//pitchShift( 1, tmpR, &out[i] );
else
out[i]+=tmp;
// TODO stereo sends
out[i]+=tmpL;
//outR[i]+=tmpR;
}
//printf("Looper %i playing(), speed = %f\n", track, playSpeed );

View file

@ -121,7 +121,7 @@ void LooperClip::load( AudioBuffer* ab )
jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
// set the endpoint to the buffer's size
_recordhead = _buffer->getData().size();
_recordhead = _buffer->getSize();
#ifdef DEBUG_BUFFER
char buffer [50];
@ -134,8 +134,9 @@ void LooperClip::load( AudioBuffer* ab )
void LooperClip::setRequestedBuffer( AudioBuffer* ab )
{
if ( _buffer ) {
size_t size = _buffer->getData().size();
memcpy( &ab->getData().at(0), &_buffer->getData().at(0), sizeof(float)*size);
size_t size = _buffer->getSize();
memcpy( &ab->getDataL().at(0), &_buffer->getDataL().at(0), sizeof(float)*size);
memcpy( &ab->getDataR().at(0), &_buffer->getDataR().at(0), sizeof(float)*size);
ab->setID ( _buffer->getID() );
ab->setBeats( _buffer->getBeats() );
@ -153,10 +154,13 @@ void LooperClip::setRequestedBuffer( AudioBuffer* ab )
void LooperClip::recieveSaveBuffer( AudioBuffer* saveBuffer )
{
if ( saveBuffer->getData().size() >= _buffer->getData().at(0) ) {
if ( saveBuffer->getSize() >= _buffer->getDataL().at(0) ||
saveBuffer->getSize() >= _buffer->getDataR().at(0) ) {
// copy current contents into save buffer,
// getData() contains L and R buffer, so twice the size is needed
size_t framesBySize = _buffer->getAudioFrames();
memcpy( &saveBuffer->getData().at(0), &_buffer->getData().at(0), sizeof(float)*framesBySize);
memcpy( &saveBuffer->getDataL().at(0), &_buffer->getDataL().at(0), sizeof(float)*framesBySize);
memcpy( &saveBuffer->getDataR().at(0), &_buffer->getDataR().at(0), sizeof(float)*framesBySize);
saveBuffer->setID ( _buffer->getID() );
saveBuffer->setBeats( _buffer->getBeats() );
@ -189,11 +193,12 @@ void LooperClip::record(int count, float* L, float* R)
{
// write "count" samples into current buffer.
if ( _buffer ) {
size_t size = _buffer->getData().size();
size_t size = _buffer->getSize();
for(int i = 0; i < count; i++) {
if ( _recordhead < size ) {
_buffer->getData().at( _recordhead ) = *L++;
_buffer->getDataL().at( _recordhead ) = *L++;
_buffer->getDataR().at( _recordhead ) = *R++;
_recordhead++;
} else {
// break: this is *BAD*, audio data is lost but the buffer isn't here
@ -218,7 +223,8 @@ void LooperClip::record(int count, float* L, float* R)
unsigned long LooperClip::recordSpaceAvailable()
{
if ( _buffer )
return _buffer->getData().size() - _recordhead;
// getData() contains L and R buffer, so it is twice the size
return _buffer->getSize() - _recordhead;
return 0;
}
@ -226,7 +232,7 @@ unsigned long LooperClip::recordSpaceAvailable()
size_t LooperClip::audioBufferSize()
{
if ( _buffer ) {
return _buffer->getData().size();
return _buffer->getSize();
}
return 0;
}
@ -410,11 +416,11 @@ bool LooperClip::newBufferInTransit()
return _newBufferInTransit;
}
float LooperClip::getSample(float playSpeed)
void LooperClip::getSample(float playSpeed, float* L, float* R)
{
if ( _buffer && _buffer->getData().size() > 0 ) {
if ( _buffer && (_buffer->getSize() > 0)) {
if ( _playhead >= _recordhead ||
_playhead >= _buffer->getData().size() ||
_playhead >= _buffer->getSize() ||
_playhead < 0 ) {
_playhead = 0;
@ -422,14 +428,16 @@ float LooperClip::getSample(float playSpeed)
//writeToGuiRingbuffer( &e );
}
std::vector<float>& v = _buffer->getData();
float tmp = v.at(_playhead);
std::vector<float>& vL = _buffer->getDataL();
std::vector<float>& vR = _buffer->getDataR();
*L = vL.at(_playhead);
*R = vR.at(_playhead);
_playhead +=playSpeed;
return tmp;
}
return 0.f;
else {
*L = 0.f;
*R = 0.f;
}
}
float LooperClip::getProgress()

View file

@ -55,7 +55,7 @@ public:
void load( AudioBuffer* ab );
/// audio functionality
float getSample(float playSpeed);
void getSample(float playSpeed, float* L, float* R);
void record(int count, float* L, float* R);
/// TimeObserver override