Browse Source

Try automatic adaptative mode in adapters.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3428 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.9.2
sletz 16 years ago
parent
commit
6d3b3633a6
12 changed files with 135 additions and 105 deletions
  1. +5
    -1
      ChangeLog
  2. +12
    -9
      common/JackAudioAdapter.cpp
  3. +40
    -42
      common/JackAudioAdapterInterface.cpp
  4. +17
    -5
      common/JackAudioAdapterInterface.h
  5. +20
    -4
      common/JackFilters.h
  6. +16
    -19
      common/JackNetAdapter.cpp
  7. +1
    -1
      common/JackResampler.h
  8. +1
    -1
      common/JackWaitThreadedDriver.cpp
  9. +6
    -6
      linux/alsa/JackAlsaAdapter.cpp
  10. +5
    -5
      macosx/coreaudio/JackCoreAudioAdapter.cpp
  11. +6
    -6
      solaris/oss/JackOSSAdapter.cpp
  12. +6
    -6
      windows/portaudio/JackPortAudioAdapter.cpp

+ 5
- 1
ChangeLog View File

@@ -23,10 +23,14 @@ Torben Hohn
---------------------------
Jackdmp changes log
---------------------------

2009-03-12 Stephane Letz <letz@grame.fr>
* Try automatic adaptative mode in adapters.
2009-03-11 Stephane Letz <letz@grame.fr>
* Client incorrect re-naming fixed: now done at socket level also.
* Client incorrect re-naming fixed : now done at socket level also.
2009-03-10 Stephane Letz <letz@grame.fr>


+ 12
- 9
common/JackAudioAdapter.cpp View File

@@ -36,19 +36,22 @@ namespace Jack
int JackAudioAdapter::Process (jack_nframes_t frames, void* arg)
{
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
if (!adapter->fAudioAdapter->IsRunning())
return 0;
float* inputBuffer[adapter->fAudioAdapter->GetInputs()];
float* outputBuffer[adapter->fAudioAdapter->GetOutputs()];
// Always clear output
for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
inputBuffer[i] = (float*)jack_port_get_buffer(adapter->fCapturePortList[i], frames);
memset(inputBuffer[i], 0, frames * sizeof(float));
}
for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
outputBuffer[i] = (float*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames);
}
adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames);
if (adapter->fAudioAdapter->IsRunning()) {
for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
outputBuffer[i] = (float*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames);
}
adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames);
}
return 0;
}

@@ -81,7 +84,7 @@ namespace Jack
param = (const jack_driver_param_t*) node->data;
switch (param->character) {
case 'c':
fAutoConnect = param->value.i;
fAutoConnect = true;
break;
}
}


+ 40
- 42
common/JackAudioAdapterInterface.cpp View File

@@ -47,13 +47,12 @@ namespace Jack
for (int i = 1; i < max; i++)
{
fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n",
fTable[i].delta, fTable[i+1].time1 - fTable[i].time1,
fTable[i+1].time2 - fTable[i].time2,
fTable[i].delta, fTable[i].time1, fTable[i].time2,
fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
}
fclose(file);

/* No used for now
// No used for now
// Adapter timing 1
file = fopen("AdapterTiming1.plot", "w");
fprintf(file, "set multiplot\n");
@@ -63,9 +62,9 @@ namespace Jack
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"frames\"\n");
fprintf(file, "plot ");
sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
fprintf(file, buffer);
sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines");
sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
fprintf(file, buffer);
fprintf(file, "\n unset multiplot\n");
@@ -84,8 +83,7 @@ namespace Jack
fprintf(file, buffer);
fclose(file);
*/

// Adapter timing 2
file = fopen("AdapterTiming2.plot", "w");
fprintf(file, "set multiplot\n");
@@ -150,22 +148,32 @@ namespace Jack
}

#endif

void JackAudioAdapterInterface::GrowRingBufferSize()
{
fRingbufferCurSize *= 2;
}
void JackAudioAdapterInterface::AdaptRingBufferSize()
{
if (fHostBufferSize > fAdaptedBufferSize)
fRingbufferCurSize = 4 * fHostBufferSize;
else
fRingbufferCurSize = 4 * fAdaptedBufferSize;
}
void JackAudioAdapterInterface::ResetRingBuffers()
{
if (fRingbufferSize == 0) {
fRingbufferCurSize *= 2;
if (fRingbufferCurSize > DEFAULT_RB_SIZE)
fRingbufferCurSize = DEFAULT_RB_SIZE;
}
if (fRingbufferCurSize > DEFAULT_RB_SIZE)
fRingbufferCurSize = DEFAULT_RB_SIZE;
for (int i = 0; i < fCaptureChannels; i++)
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
for (int i = 0; i < fPlaybackChannels; i++)
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
}
void JackAudioAdapterInterface::Reset()
void JackAudioAdapterInterface::Reset()
{
ResetRingBuffers();
fRunning = false;
@@ -177,10 +185,11 @@ namespace Jack
fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
fRingbufferCurSize = (fRingbufferSize == 0) ? DEFAULT_ADAPTATIVE_SIZE : DEFAULT_RB_SIZE;
if (fRingbufferSize == 0) {
if (fAdaptative) {
jack_info("Ringbuffer automatic adaptative mode");
} else {
fRingbufferCurSize = DEFAULT_RB_SIZE;
jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
}
for (int i = 0; i < fCaptureChannels; i++ ) {
@@ -213,14 +222,14 @@ namespace Jack
{
bool failure = false;
fRunning = true;
// Finer estimation of the position in the ringbuffer
int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
/*
Finer estimation of the position in the ringbuffer ??
int delta_frames = (int)(float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f;
double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetOffset() - delta_frames);
*/
double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetOffset());
#ifdef JACK_MONITOR
fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
#endif
// Push/pull from ringbuffer
for (int i = 0; i < fCaptureChannels; i++) {
@@ -234,14 +243,10 @@ namespace Jack
if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames)
failure = true;
}

#ifdef JACK_MONITOR
fTable.Write(0, 0, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace());
#endif

// Reset all ringbuffers in case of failure
if (failure) {
jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset");
GrowRingBufferSize();
ResetRingBuffers();
return -1;
} else {
@@ -251,28 +256,21 @@ namespace Jack

int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
{
bool failure = false;
int res = 0;
fPullAndPushTime = GetMicroSeconds();
// Push/pull from ringbuffer
for (int i = 0; i < fCaptureChannels; i++) {
if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames)
failure = true;
res = -1;
}

for (int i = 0; i < fPlaybackChannels; i++) {
if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames)
failure = true;
}

// Reset all ringbuffers in case of failure
if (failure) {
jack_error("JackCallbackAudioAdapter::PullAndPush ringbuffer failure... reset");
Reset();
return -1;
} else {
return 0;
res = -1;
}
return res;
}

} // namespace

+ 17
- 5
common/JackAudioAdapterInterface.h View File

@@ -23,6 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackResampler.h"
#include "JackFilters.h"
#include "JackConstants.h"
#include <stdio.h>

namespace Jack
{
@@ -89,13 +90,15 @@ namespace Jack
JackResampler** fPlaybackRingBuffer;
unsigned int fQuality;
unsigned int fRingbufferSize;
unsigned int fRingbufferCurSize;
jack_time_t fPullAndPushTime;
bool fRunning;
bool fAdaptative;
void ResetRingBuffers();
void AdaptRingBufferSize();
void GrowRingBufferSize();
public:

@@ -108,10 +111,11 @@ namespace Jack
fAdaptedSampleRate ( sample_rate ),
fPIControler(sample_rate / sample_rate, 256),
fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL),
fQuality(0), fRingbufferSize(DEFAULT_RB_SIZE),
fRingbufferCurSize(0),
fQuality(0),
fRingbufferCurSize(DEFAULT_ADAPTATIVE_SIZE),
fPullAndPushTime(0),
fRunning(false)
fRunning(false),
fAdaptative(true)
{}

virtual ~JackAudioAdapterInterface()
@@ -140,12 +144,20 @@ namespace Jack
virtual int SetHostBufferSize ( jack_nframes_t buffer_size )
{
fHostBufferSize = buffer_size;
if (fAdaptative) {
AdaptRingBufferSize();
ResetRingBuffers();
}
return 0;
}

virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size )
{
fAdaptedBufferSize = buffer_size;
if (fAdaptative) {
AdaptRingBufferSize();
ResetRingBuffers();
}
return 0;
}

@@ -203,7 +215,7 @@ namespace Jack
int PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int inNumberFrames);
int PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int inNumberFrames);
};

}


+ 20
- 4
common/JackFilters.h View File

@@ -263,20 +263,21 @@ namespace Jack
static_resample_factor = resample_factor;
}
/*
double GetRatio(int fill_level)
{
double offset = fill_level;

// Save offset.
offset_array[(offset_differential_index++) % smooth_size] = offset;
// Build the mean of the windowed offset array basically fir lowpassing.
double smooth_offset = 0.0;
for (int i = 0; i < smooth_size; i++) {
smooth_offset += offset_array[(i + offset_differential_index - 1) % smooth_size] * window_array[i];
}
smooth_offset /= double(smooth_size);
// This is the integral of the smoothed_offset
offset_integral += smooth_offset;

@@ -284,13 +285,13 @@ namespace Jack
// It only used in the P component and the I component is used for the fine tuning anyways.
if (fabs(smooth_offset) < pclamp)
smooth_offset = 0.0;
// Ok, now this is the PI controller.
// u(t) = K * (e(t) + 1/T \int e(t') dt')
// Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
double current_resample_factor
= static_resample_factor - smooth_offset / catch_factor - offset_integral / catch_factor / catch_factor2;
// Now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt.
current_resample_factor = floor((current_resample_factor - resample_mean) * controlquant + 0.5) / controlquant + resample_mean;

@@ -298,6 +299,21 @@ namespace Jack
resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
return current_resample_factor;
}
*/

double GetRatio(int error)
{
double smooth_offset = error;

// This is the integral of the smoothed_offset
offset_integral += smooth_offset;

// Ok, now this is the PI controller.
// u(t) = K * (e(t) + 1/T \int e(t') dt')
// Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
return static_resample_factor - smooth_offset/catch_factor - offset_integral/catch_factor/catch_factor2;
}
void OurOfBounds()
{


+ 16
- 19
common/JackNetAdapter.cpp View File

@@ -96,7 +96,7 @@ namespace Jack
fQuality = param->value.ui;
break;
case 'g':
fRingbufferSize = param->value.ui;
fAdaptative = false;
break;
}
}
@@ -242,27 +242,24 @@ namespace Jack

bool JackNetAdapter::Execute()
{
try
{
try {
// Keep running even in case of error
while ( fThread.GetStatus() == JackThread::kRunning )
if ( Process() == SOCKET_ERROR )
while (fThread.GetStatus() == JackThread::kRunning)
if (Process() == SOCKET_ERROR)
return false;
return false;
}
catch ( JackNetException& e )
{
} catch (JackNetException& e) {
e.PrintMessage();
jack_log ( "NetAdapter is restarted." );
jack_info("NetAdapter is restarted.");
Reset();
fThread.DropRealTime();
fThread.SetStatus ( JackThread::kIniting );
if ( Init() )
{
fThread.SetStatus ( JackThread::kRunning );
fThread.SetStatus(JackThread::kIniting);
if (Init()) {
fThread.SetStatus(JackThread::kRunning);
return true;
}
else
} else {
return false;
}
}
}

@@ -471,10 +468,10 @@ extern "C"
i++;
strcpy(desc->params[i].name, "ring-buffer");
desc->params[i].character = 'g';
desc->params[i].type = JackDriverParamInt;
desc->params[i].value.ui = 32768;
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames");
strcpy(desc->params[i].long_desc, "Resampling ringbuffer size in frames (default = 32768, 0 for automatic mode)");
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = false;
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (false = automatic adaptative)");
i++;
strcpy ( desc->params[i].name, "auto-connect" );


+ 1
- 1
common/JackResampler.h View File

@@ -63,7 +63,7 @@ class JackResampler
virtual unsigned int ReadSpace();
virtual unsigned int WriteSpace();
unsigned int GetOffset()
unsigned int GetError()
{
return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(float)) - (fRingBufferSize / 2);
}


+ 1
- 1
common/JackWaitThreadedDriver.cpp View File

@@ -61,7 +61,7 @@ bool JackWaitThreadedDriver::Execute()
return false;
} catch (JackNetException& e) {
e.PrintMessage();
jack_log("Driver is restarted");
jack_info("Driver is restarted");
fThread.DropRealTime();
// Thread in kIniting status again...
fThread.SetStatus(JackThread::kIniting);


+ 6
- 6
linux/alsa/JackAlsaAdapter.cpp View File

@@ -77,7 +77,7 @@ namespace Jack
fQuality = param->value.ui;
break;
case 'g':
fRingbufferSize = param->value.ui;
fAdaptative = false;
break;
}
}
@@ -251,7 +251,7 @@ extern "C"
strcpy ( desc->params[i].name, "duplex" );
desc->params[i].character = 'D';
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = 1;
desc->params[i].value.i = true;
strcpy ( desc->params[i].short_desc,
"Provide both capture and playback ports" );
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
@@ -285,10 +285,10 @@ extern "C"
i++;
strcpy(desc->params[i].name, "ring-buffer");
desc->params[i].character = 'g';
desc->params[i].type = JackDriverParamInt;
desc->params[i].value.ui = 32768;
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames");
strcpy(desc->params[i].long_desc, "Resampling ringbuffer size in frames (default = 32768, 0 for automatic mode)");
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = false;
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (false = automatic adaptative)");

return desc;
}


+ 5
- 5
macosx/coreaudio/JackCoreAudioAdapter.cpp View File

@@ -378,7 +378,7 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra
break;
case 'g':
fRingbufferSize = param->value.ui;
fAdaptative = false;
break;
}
}
@@ -1079,10 +1079,10 @@ extern "C"
i++;
strcpy(desc->params[i].name, "ring-buffer");
desc->params[i].character = 'g';
desc->params[i].type = JackDriverParamInt;
desc->params[i].value.ui = 32768;
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames");
strcpy(desc->params[i].long_desc, "Resampling ringbuffer size in frames (default = 32768, 0 for automatic mode)");
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = false;
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (false = automatic adaptative)");

return desc;
}


+ 6
- 6
solaris/oss/JackOSSAdapter.cpp View File

@@ -183,7 +183,7 @@ JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample
break;
case 'g':
fRingbufferSize = param->value.ui;
fAdaptative = false;
break;

}
@@ -741,11 +741,11 @@ extern "C"
i++;
strcpy(desc->params[i].name, "ring-buffer");
desc->params[i].character = 'g';
desc->params[i].type = JackDriverParamInt;
desc->params[i].value.ui = 32768;
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 32768, 0 for automatic mode)");
strcpy(desc->params[i].long_desc, "Resampling ringbuffer size in frames (default = 32768, 0 for automatic mode)");
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = false;
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (false = automatic adaptative)");
return desc;
}


+ 6
- 6
windows/portaudio/JackPortAudioAdapter.cpp View File

@@ -97,7 +97,7 @@ namespace Jack
fQuality = param->value.ui;
break;
case 'g':
fRingbufferSize = param->value.ui;
fAdaptative = false;
break;
}
}
@@ -282,7 +282,7 @@ extern "C"
strcpy(desc->params[i].name, "list-devices");
desc->params[i].character = 'l';
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = TRUE;
desc->params[i].value.i = true;
strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);

@@ -297,10 +297,10 @@ extern "C"
i++;
strcpy(desc->params[i].name, "ring-buffer");
desc->params[i].character = 'g';
desc->params[i].type = JackDriverParamInt;
desc->params[i].value.ui = 32768;
strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames");
strcpy(desc->params[i].long_desc, "Resampling ringbuffer size in frames (default = 32768, 0 for automatic mode)");
desc->params[i].type = JackDriverParamBool;
desc->params[i].value.i = false;
strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (false = automatic adaptative)");

return desc;
}


Loading…
Cancel
Save