Browse Source

Possibility to calculate resampe ratio per channel in adapter to avoid delay buildup

pull/859/head
uraura00 3 years ago
parent
commit
8c9235528f
10 changed files with 163 additions and 114 deletions
  1. +98
    -28
      common/JackAudioAdapterInterface.cpp
  2. +12
    -7
      common/JackAudioAdapterInterface.h
  3. +6
    -78
      common/JackFilters.h
  4. +6
    -0
      common/JackNetAPI.cpp
  5. +7
    -0
      common/JackNetAdapter.cpp
  6. +5
    -1
      common/JackResampler.h
  7. +6
    -0
      linux/alsa/JackAlsaAdapter.cpp
  8. +8
    -0
      macosx/coreaudio/JackCoreAudioAdapter.mm
  9. +8
    -0
      solaris/oss/JackOSSAdapter.cpp
  10. +7
    -0
      windows/portaudio/JackPortAudioAdapter.cpp

+ 98
- 28
common/JackAudioAdapterInterface.cpp View File

@@ -67,8 +67,8 @@ namespace Jack
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"frames\"\n");
fprintf(file, "plot ");
fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with dots,");
fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with dots");

fprintf(file, "\n unset multiplot\n");
fprintf(file, "set output 'AdapterTiming1.svg\n");
@@ -81,8 +81,8 @@ namespace Jack
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"frames\"\n");
fprintf(file, "plot ");
fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines\n");
fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with dots,");
fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with dots\n");
fprintf(file, "unset multiplot\n");
fprintf(file, "unset output\n");

@@ -97,8 +97,8 @@ namespace Jack
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"resampling ratio\"\n");
fprintf(file, "plot ");
fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with dots,");
fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with dots");

fprintf(file, "\n unset multiplot\n");
fprintf(file, "set output 'AdapterTiming2.svg\n");
@@ -111,8 +111,8 @@ namespace Jack
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"resampling ratio\"\n");
fprintf(file, "plot ");
fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines\n");
fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with dots,");
fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with dots\n");
fprintf(file, "unset multiplot\n");
fprintf(file, "unset output\n");

@@ -127,8 +127,8 @@ namespace Jack
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"frames\"\n");
fprintf(file, "plot ");
fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with dots,");
fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with dots");

fprintf(file, "\n unset multiplot\n");
fprintf(file, "set output 'AdapterTiming3.svg\n");
@@ -141,8 +141,8 @@ namespace Jack
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"frames\"\n");
fprintf(file, "plot ");
fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines\n");
fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with dots,");
fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with dots\n");
fprintf(file, "unset multiplot\n");
fprintf(file, "unset output\n");

@@ -173,9 +173,11 @@ namespace Jack

for (int i = 0; i < fCaptureChannels; i++) {
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
fPIControllerCapture[i]->Reset();
}
for (int i = 0; i < fPlaybackChannels; i++) {
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
fPIControllerPlayback[i]->Reset();
}
}

@@ -191,9 +193,11 @@ namespace Jack
#else
void JackAudioAdapterInterface::Create()
{
//ringbuffers
fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
fPIControllerCapture = new JackPIController*[fCaptureChannels];

fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
fPIControllerPlayback = new JackPIController*[fPlaybackChannels];

if (fAdaptative) {
AdaptRingBufferSize();
@@ -205,13 +209,22 @@ namespace Jack
jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
}

if (fResampleRatioPerChannel){
jack_info("Resample ratio tracked independently for each capture and playback channel");
} else {
jack_info("Shared resample ratio tracking for all capture and playback channels");
}


for (int i = 0; i < fCaptureChannels; i++ ) {
fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
fPIControllerCapture[i] = new JackPIController(double(fHostSampleRate) / double(fAdaptedSampleRate));
}
for (int i = 0; i < fPlaybackChannels; i++ ) {
fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
fPIControllerPlayback[i] = new JackPIController(double(fHostSampleRate) / double(fAdaptedSampleRate));
}

if (fCaptureChannels > 0) {
@@ -227,40 +240,79 @@ namespace Jack
{
for (int i = 0; i < fCaptureChannels; i++) {
delete(fCaptureRingBuffer[i]);
delete(fPIControllerCapture[i]);
}
for (int i = 0; i < fPlaybackChannels; i++) {
delete (fPlaybackRingBuffer[i]);
delete(fPIControllerPlayback[i]);
}

delete[] fCaptureRingBuffer;
delete [] fPIControllerCapture;
delete[] fPlaybackRingBuffer;
delete [] fPIControllerPlayback;
}

double JackAudioAdapterInterface::GetSharedRatio(int delta_frames)
{
if (0 < fCaptureChannels) {
return fPIControllerCapture[0]->GetRatio(fCaptureRingBuffer[0]->GetReadBalance() - delta_frames);
}
else if (0 < fPlaybackChannels) {
return fPIControllerPlayback[0]->GetRatio(fPlaybackRingBuffer[0]->GetReadBalance() - delta_frames);
}
return 1;
}

int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
{
// Most of the time we can use a shared ratio calculated on a single input or output channel ringbuffer and apply this ratio also to all other channels.
// In some situations we see that there is a drift between the channels coming from or going to the same device.
// On those devices we need to activate the fResampleRatioPerChannel option so that every channel will calculate and keep track of its own resample ratio
// in order to keep his ringbuffer in a good balance which is half used for reading and half used for writing.
// Not using this option when it is needed will result in buffer errors followed by resets for all the buffers.
// cfr. https://github.com/jackaudio/jack2/issues/534

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 = 1;

// TODO : done like this just to avoid crash when input only or output only...
if (fCaptureChannels > 0) {
ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
} else if (fPlaybackChannels > 0) {
ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
double ratioC[fCaptureChannels];
double ratioP[fPlaybackChannels];
if(!fResampleRatioPerChannel) {
double shared_ratio = GetSharedRatio(delta_frames);
for (int i = 0; i < fCaptureChannels; i++) {
ratioC[i] = shared_ratio;
}
for (int i = 0; i < fPlaybackChannels; i++) {
ratioP[i] = shared_ratio;
}
#ifdef JACK_MONITOR
if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL) {
fTable.Write(fCaptureRingBuffer[0]->GetReadBalance(), fCaptureRingBuffer[0]->GetReadBalance() - delta_frames, shared_ratio, 1/shared_ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
}
#endif // JACK_MONITOR
}
else {
for (int i = 0; i < fCaptureChannels; i++) {
ratioC[i] = fPIControllerCapture[i]->GetRatio(fCaptureRingBuffer[i]->GetReadBalance() - delta_frames);
}
for (int i = 0; i < fPlaybackChannels; i++) {
ratioP[i] = fPIControllerPlayback[i]->GetRatio(fPlaybackRingBuffer[i]->GetWriteBalance() + delta_frames);
}
#ifdef JACK_MONITOR
if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL) {
fTable.Write(fCaptureRingBuffer[0]->GetReadBalance(), fCaptureRingBuffer[0]->GetReadBalance() - delta_frames, ratioC[0], 1/ratioC[0], fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
}
#endif // JACK_MONITOR
}

#ifdef JACK_MONITOR
if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL)
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++) {
fCaptureRingBuffer[i]->SetRatio(ratio);
fCaptureRingBuffer[i]->SetRatio(ratioC[i]);
if (inputBuffer[i]) {
if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) {
failure = true;
@@ -269,7 +321,7 @@ namespace Jack
}

for (int i = 0; i < fPlaybackChannels; i++) {
fPlaybackRingBuffer[i]->SetRatio(1/ratio);
fPlaybackRingBuffer[i]->SetRatio(1 / ratioP[i]);
if (outputBuffer[i]) {
if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) {
failure = true;
@@ -347,14 +399,32 @@ namespace Jack
int JackAudioAdapterInterface::SetHostSampleRate(jack_nframes_t sample_rate)
{
fHostSampleRate = sample_rate;
fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
if (NULL != fPIControllerCapture) {
for (int i = 0; i < fCaptureChannels; i++) {
fPIControllerCapture[i]->Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
}
}
if (NULL != fPIControllerPlayback) {
for (int i = 0; i < fPlaybackChannels; i++) {
fPIControllerPlayback[i]->Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
}
}
return 0;
}

int JackAudioAdapterInterface::SetAdaptedSampleRate(jack_nframes_t sample_rate)
{
fAdaptedSampleRate = sample_rate;
fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
if (NULL != fPIControllerCapture) {
for (int i = 0; i < fCaptureChannels; i++) {
fPIControllerCapture[i]->Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
}
}
if (NULL != fPIControllerPlayback) {
for (int i = 0; i < fPlaybackChannels; i++ ) {
fPIControllerPlayback[i]->Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
}
}
return 0;
}



+ 12
- 7
common/JackAudioAdapterInterface.h View File

@@ -82,9 +82,9 @@ namespace Jack
jack_nframes_t fAdaptedBufferSize;
jack_nframes_t fAdaptedSampleRate;

//PI controller
JackPIControler fPIControler;
//PI controler
JackPIController** fPIControllerCapture;
JackPIController** fPIControllerPlayback;
JackResampler** fCaptureRingBuffer;
JackResampler** fPlaybackRingBuffer;

@@ -94,6 +94,7 @@ namespace Jack

bool fRunning;
bool fAdaptative;
bool fResampleRatioPerChannel;

void ResetRingBuffers();
void AdaptRingBufferSize();
@@ -108,13 +109,14 @@ namespace Jack
fHostSampleRate(sample_rate),
fAdaptedBufferSize(buffer_size),
fAdaptedSampleRate(sample_rate),
fPIControler(sample_rate / sample_rate, 256),
fPIControllerCapture(NULL), fPIControllerPlayback(NULL),
fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL),
fQuality(0),
fRingbufferCurSize(ring_buffer_size),
fPullAndPushTime(0),
fRunning(false),
fAdaptative(true)
fAdaptative(true),
fResampleRatioPerChannel(false)
{}

JackAudioAdapterInterface(jack_nframes_t host_buffer_size,
@@ -128,12 +130,14 @@ namespace Jack
fHostSampleRate(host_sample_rate),
fAdaptedBufferSize(adapted_buffer_size),
fAdaptedSampleRate(adapted_sample_rate),
fPIControler(host_sample_rate / host_sample_rate, 256),
fPIControllerCapture(NULL), fPIControllerPlayback(NULL),
fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL),
fQuality(0),
fRingbufferCurSize(ring_buffer_size),
fPullAndPushTime(0),
fRunning(false),
fAdaptative(true)
fAdaptative(true),
fResampleRatioPerChannel(false)
{}

virtual ~JackAudioAdapterInterface()
@@ -168,6 +172,7 @@ namespace Jack
virtual int GetInputLatency(int port_index) { return 0; }
virtual int GetOutputLatency(int port_index) { return 0; }

double GetSharedRatio(int delta_frames);
int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames);
int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames);



+ 6
- 78
common/JackFilters.h View File

@@ -220,102 +220,44 @@ namespace Jack
#endif

/*
Torben Hohn PI controller from JACK1
Torben Hohn PI controler from JACK1
*/

struct JackPIControler {
struct JackPIController {

double resample_mean;
double static_resample_factor;

double* offset_array;
double* window_array;
int offset_differential_index;

double offset_integral;

double catch_factor;
double catch_factor2;
double pclamp;
double controlquant;
int smooth_size;

double hann(double x)
{
return 0.5 * (1.0 - cos(2 * M_PI * x));
}

JackPIControler(double resample_factor, int fir_size)
JackPIController(double resample_factor)
{
resample_mean = resample_factor;
static_resample_factor = resample_factor;
offset_array = new double[fir_size];
window_array = new double[fir_size];
offset_differential_index = 0;
offset_integral = 0.0;
smooth_size = fir_size;

for (int i = 0; i < fir_size; i++) {
offset_array[i] = 0.0;
window_array[i] = hann(double(i) / (double(fir_size) - 1.0));
}

// These values could be configurable
catch_factor = 100000;
catch_factor2 = 10000;
pclamp = 15.0;
controlquant = 10000.0;
}

~JackPIControler()
~JackPIController()
{
delete[] offset_array;
delete[] window_array;
}

void Init(double resample_factor)
{
resample_mean = resample_factor;
static_resample_factor = resample_factor;
}

/*
double GetRatio(int fill_level)
void Reset()
{
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;

// Clamp offset : the smooth offset still contains unwanted noise which would go straight onto the resample coeff.
// 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 doesn't hurt.
current_resample_factor = floor((current_resample_factor - resample_mean) * controlquant + 0.5) / controlquant + resample_mean;

// Calculate resample_mean so we can init ourselves to saner values.
resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
return current_resample_factor;
offset_integral = 0.0;
}
*/

double GetRatio(int error)
{
@@ -329,20 +271,6 @@ namespace Jack
// 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()
{
int i;
// Set the resample_rate... we need to adjust the offset integral, to do this.
// first look at the PI controller, this code is just a special case, which should never execute once
// everything is swung in.
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
// Also clear the array. we are beginning a new control cycle.
for (i = 0; i < smooth_size; i++) {
offset_array[i] = 0.0;
}
}

};

}


+ 6
- 0
common/JackNetAPI.cpp View File

@@ -995,9 +995,11 @@ struct JackNetAdapter : public JackAudioAdapterInterface {

if (fCaptureChannels > 0) {
fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
fPIControllerCapture = new JackPIController*[fCaptureChannels];
}
if (fPlaybackChannels > 0) {
fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
fPIControllerPlayback = new JackPIController*[fPlaybackChannels];
}

if (fAdaptative) {
@@ -1013,10 +1015,12 @@ struct JackNetAdapter : public JackAudioAdapterInterface {
for (int i = 0; i < fCaptureChannels; i++ ) {
fCaptureRingBuffer[i] = new JackResampler();
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
fPIControllerCapture[i] = new JackPIController(double(fHostSampleRate) / double(fAdaptedSampleRate));
}
for (int i = 0; i < fPlaybackChannels; i++ ) {
fPlaybackRingBuffer[i] = new JackResampler();
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
fPIControllerPlayback[i] = new JackPIController(double(fHostSampleRate) / double(fAdaptedSampleRate));
}

if (fCaptureChannels > 0) {
@@ -1036,9 +1040,11 @@ struct JackNetAdapter : public JackAudioAdapterInterface {
{
for (int i = 0; i < fCaptureChannels; i++ ) {
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
fPIControllerCapture[i]->Reset();
}
for (int i = 0; i < fPlaybackChannels; i++ ) {
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
fPIControllerPlayback[i]->Reset();
}
}



+ 7
- 0
common/JackNetAdapter.cpp View File

@@ -124,6 +124,9 @@ namespace Jack
fRingbufferCurSize = param->value.ui;
fAdaptative = false;
break;
case 'R':
fResampleRatioPerChannel = true;
break;
}
}

@@ -462,6 +465,10 @@ extern "C"
value.i = false;
jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netadapter to system ports", NULL);

value.i = false;
jack_driver_descriptor_add_parameter(desc, &filler, "multi-ratios", 'R', JackDriverParamBool, &value, NULL, "Calculate resample ratio per channel"
, "Calculate resample ratio per channel in case of repeated ringbuffer errors because of clock drift between the channels from the same device.");

return desc;
}



+ 5
- 1
common/JackResampler.h View File

@@ -65,10 +65,14 @@ class JackRingBuffer
virtual unsigned int ReadSpace();
virtual unsigned int WriteSpace();

unsigned int GetError()
unsigned int GetReadBalance()
{
return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(float)) - (fRingBufferSize / 2);
}
unsigned int GetWriteBalance()
{
return (jack_ringbuffer_write_space(fRingBuffer) / sizeof(float)) - (fRingBufferSize / 2);
}

};



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

@@ -86,6 +86,9 @@ namespace Jack
fRingbufferCurSize = param->value.ui;
fAdaptative = false;
break;
case 'R':
fResampleRatioPerChannel = true;
break;
}
}

@@ -228,6 +231,9 @@ extern "C"
value.ui = 32768;
jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamUInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");

value.i = false;
jack_driver_descriptor_add_parameter(desc, &filler, "multi-ratios", 'R', JackDriverParamBool, &value, NULL, "Calculate resample ratio per channel"
, "Calculate resample ratio per channel in case of repeated ringbuffer errors because of clock drift between the channels from the same device.");
return desc;
}



+ 8
- 0
macosx/coreaudio/JackCoreAudioAdapter.mm View File

@@ -409,6 +409,10 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra
case 's':
fClockDriftCompensate = true;
break;

case 'R':
fResampleRatioPerChannel = true;
break;
}
}

@@ -1745,6 +1749,10 @@ extern "C"
value.i = false;
jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect audioadapter to system ports", NULL);

value.i = false;
jack_driver_descriptor_add_parameter(desc, &filler, "multi-ratios", 'R', JackDriverParamBool, &value, NULL, "Calculate resample ratio per channel"
, "Calculate resample ratio per channel in case of repeated ringbuffer errors because of clock drift between the channels from the same device.");

return desc;
}



+ 8
- 0
solaris/oss/JackOSSAdapter.cpp View File

@@ -187,6 +187,10 @@ JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample
fAdaptative = false;
break;

case 'R':
fResampleRatioPerChannel = true;
break;

}
}

@@ -674,6 +678,10 @@ extern "C"
value.i = 32768;
jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");

value.i = false;
jack_driver_descriptor_add_parameter(desc, &filler, "multi-ratios", 'R', JackDriverParamBool, &value, NULL, "Calculate resample ratio per channel"
, "Calculate resample ratio per channel in case of repeated ringbuffer errors because of clock drift between the channels from the same device.");

return desc;
}



+ 7
- 0
windows/portaudio/JackPortAudioAdapter.cpp View File

@@ -92,6 +92,9 @@ namespace Jack
fRingbufferCurSize = param->value.ui;
fAdaptative = false;
break;
case 'R':
fResampleRatioPerChannel = true;
break;
}
}

@@ -235,6 +238,10 @@ extern "C"
value.ui = 32768;
jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamUInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");

value.i = false;
jack_driver_descriptor_add_parameter(desc, &filler, "multi-ratios", 'R', JackDriverParamBool, &value, NULL, "Calculate resample ratio per channel"
, "Calculate resample ratio per channel in case of repeated ringbuffer errors because of clock drift between the channels from the same device.");

return desc;
}



Loading…
Cancel
Save