Browse Source

RtAudio: handle buffer size changes in JACK driver

tags/v1.9.11
falkTX 6 years ago
parent
commit
7c16b0db07
3 changed files with 84 additions and 11 deletions
  1. +32
    -3
      source/backend/engine/CarlaEngineRtAudio.cpp
  2. +40
    -6
      source/modules/rtaudio/RtAudio.cpp
  3. +12
    -2
      source/modules/rtaudio/RtAudio.h

+ 32
- 3
source/backend/engine/CarlaEngineRtAudio.cpp View File

@@ -286,7 +286,8 @@ public:
fAudio.openStream(oParams.nChannels > 0 ? &oParams : nullptr,
iParams.nChannels > 0 ? &iParams : nullptr,
RTAUDIO_FLOAT32, pData->options.audioSampleRate, &bufferFrames,
carla_rtaudio_process_callback, this, &rtOptions);
carla_rtaudio_process_callback, this, &rtOptions,
carla_rtaudio_buffer_size_callback);
}
catch (const RtAudioError& e) {
setLastError(e.what());
@@ -592,8 +593,7 @@ protected:
/* */ float* const outsPtr = (float*)outputBuffer;

// assert rtaudio buffers
CARLA_SAFE_ASSERT_RETURN(outputBuffer != nullptr,);
CARLA_SAFE_ASSERT_RETURN(pData->bufferSize == nframes,);
CARLA_SAFE_ASSERT_RETURN(outputBuffer != nullptr,);

// set rtaudio buffers as non-interleaved
const float* inBuf[fAudioInCount];
@@ -601,6 +601,7 @@ protected:

if (fAudioInterleaved)
{
// FIXME - this looks completely wrong!
float* inBuf2[fAudioInCount];

for (uint i=0, count=fAudioInCount; i<count; ++i)
@@ -755,6 +756,28 @@ protected:
(void)streamTime; (void)status;
}

void handleBufferSizeCallback(const uint newBufferSize)
{
carla_stdout("bufferSize callback %u %u", pData->bufferSize, newBufferSize);
if (pData->bufferSize == newBufferSize)
return;

if (fAudioInCount > 0)
{
delete[] fAudioIntBufIn;
fAudioIntBufIn = new float[fAudioInCount*newBufferSize];
}

if (fAudioOutCount > 0)
{
delete[] fAudioIntBufOut;
fAudioIntBufOut = new float[fAudioOutCount*newBufferSize];
}

pData->bufferSize = newBufferSize;
bufferSizeChanged(newBufferSize);
}

void handleMidiCallback(double timeStamp, std::vector<uchar>* const message)
{
const size_t messageSize(message->size());
@@ -1056,6 +1079,12 @@ private:
return 0;
}

static bool carla_rtaudio_buffer_size_callback(unsigned int bufferSize, void* userData)
{
handlePtr->handleBufferSizeCallback(bufferSize);
return true;
}

static void carla_rtmidi_callback(double timeStamp, std::vector<uchar>* message, void* userData)
{
handlePtr->handleMidiCallback(timeStamp, message);


+ 40
- 6
source/modules/rtaudio/RtAudio.cpp View File

@@ -222,11 +222,12 @@ void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters,
unsigned int *bufferFrames,
RtAudioCallback callback, void *userData,
RtAudio::StreamOptions *options,
RtAudioBufferSizeCallback bufSizeCallback,
RtAudioErrorCallback errorCallback )
{
return rtapi_->openStream( outputParameters, inputParameters, format,
sampleRate, bufferFrames, callback,
userData, options, errorCallback );
userData, options, bufSizeCallback, errorCallback );
}

// *************************************************** //
@@ -259,6 +260,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
unsigned int *bufferFrames,
RtAudioCallback callback, void *userData,
RtAudio::StreamOptions *options,
RtAudioBufferSizeCallback bufSizeCallback,
RtAudioErrorCallback errorCallback )
{
if ( stream_.state != STREAM_CLOSED ) {
@@ -340,6 +342,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,

stream_.callbackInfo.callback = (void *) callback;
stream_.callbackInfo.userData = userData;
stream_.callbackInfo.bufSizeCallback = (void *) bufSizeCallback;
stream_.callbackInfo.errorCallback = (void *) errorCallback;

if ( options ) options->numberOfBuffers = stream_.nBuffers;
@@ -1983,6 +1986,16 @@ RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )
return devInfo[device];
}

static int jackBufferSizeHandler( jack_nframes_t nframes, void *infoPointer )
{
CallbackInfo *info = (CallbackInfo *) infoPointer;

RtApiJack *object = (RtApiJack *) info->object;
if ( object->bufferSizeEvent( (unsigned long) nframes ) == false ) return 1;

return 0;
}

static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )
{
CallbackInfo *info = (CallbackInfo *) infoPointer;
@@ -2134,7 +2147,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne

// Allocate necessary internal buffers.
unsigned long bufferBytes;
bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
bufferBytes = stream_.nUserChannels[mode] * 8192 * formatBytes( stream_.userFormat );
stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
if ( stream_.userBuffer[mode] == NULL ) {
errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory.";
@@ -2155,7 +2168,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
}

if ( makeBuffer ) {
bufferBytes *= *bufferSize;
bufferBytes *= 8192;
if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
if ( stream_.deviceBuffer == NULL ) {
@@ -2182,6 +2195,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
stream_.mode = DUPLEX;
else {
stream_.mode = mode;
jackbridge_set_buffer_size_callback( handle->client, jackBufferSizeHandler, (void *) &stream_.callbackInfo );
jackbridge_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo );
jackbridge_set_xrun_callback( handle->client, jackXrun, (void *) &stream_.apiHandle );
jackbridge_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo );
@@ -2419,8 +2433,8 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
error( RtAudioError::WARNING );
return FAILURE;
}
if ( stream_.bufferSize != nframes ) {
errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!";
if ( nframes > 8192 ) {
errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size is too big ... cannot process!";
error( RtAudioError::WARNING );
return FAILURE;
}
@@ -2454,7 +2468,7 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
handle->xrun[1] = false;
}
int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
stream_.bufferSize, streamTime, status, info->userData );
nframes, streamTime, status, info->userData );
if ( cbReturnValue == 2 ) {
stream_.state = STREAM_STOPPING;
handle->drainCounter = 2;
@@ -2524,6 +2538,26 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
RtApi::tickStreamTime();
return SUCCESS;
}

bool RtApiJack :: bufferSizeEvent( unsigned long nframes )
{
if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
if ( stream_.state == STREAM_CLOSED ) {
errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";
error( RtAudioError::WARNING );
return FAILURE;
}
if ( nframes > 8192 ) {
errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size is too big ... cannot process!";
error( RtAudioError::WARNING );
return FAILURE;
}

CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;

RtAudioBufferSizeCallback callback = (RtAudioBufferSizeCallback) info->bufSizeCallback;
return callback( nframes, info->userData );
}
//******************** End of __UNIX_JACK__ *********************//
#endif



+ 12
- 2
source/modules/rtaudio/RtAudio.h View File

@@ -246,6 +246,9 @@ class RTAUDIO_DLL_PUBLIC RtAudioError : public std::runtime_error
*/
typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string &errorText );

//! RtAudio buffer size change callback.
typedef bool (*RtAudioBufferSizeCallback)( unsigned int bufferSize, void* userData );

// **************************************************************** //
//
// RtAudio class declaration.
@@ -494,7 +497,9 @@ class RTAUDIO_DLL_PUBLIC RtAudio
RtAudio::StreamParameters *inputParameters,
RtAudioFormat format, unsigned int sampleRate,
unsigned int *bufferFrames, RtAudioCallback callback,
void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL );
void *userData = NULL, RtAudio::StreamOptions *options = NULL,
RtAudioBufferSizeCallback bufSizeCallback = NULL,
RtAudioErrorCallback errorCallback = NULL );

//! A function that closes a stream and frees any associated stream memory.
/*!
@@ -611,6 +616,7 @@ struct CallbackInfo {
ThreadHandle thread;
void *callback;
void *userData;
void *bufSizeCallback;
void *errorCallback;
void *apiInfo; // void pointer for API specific callback information
bool isRunning;
@@ -619,7 +625,7 @@ struct CallbackInfo {

// Default constructor.
CallbackInfo()
:object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false), priority(0) {}
:object(0), callback(0), userData(0), bufSizeCallback(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false), priority(0) {}
};

// **************************************************************** //
@@ -688,6 +694,7 @@ public:
RtAudioFormat format, unsigned int sampleRate,
unsigned int *bufferFrames, RtAudioCallback callback,
void *userData, RtAudio::StreamOptions *options,
RtAudioBufferSizeCallback bufSizeCallback,
RtAudioErrorCallback errorCallback );
virtual void closeStream( void );
virtual void startStream( void ) = 0;
@@ -909,6 +916,9 @@ public:
// will most likely produce highly undesireable results!
bool callbackEvent( unsigned long nframes );

// Buffer size change callback
bool bufferSizeEvent( unsigned long nframes );

private:

bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,


Loading…
Cancel
Save