Browse Source

Add host and adapted denomination in audioadapters. Adapters can adapt from/to different period size/sample rate.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2796 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.90
moret 16 years ago
parent
commit
b38a30bcc9
10 changed files with 657 additions and 595 deletions
  1. +20
    -20
      common/JackAudioAdapter.cpp
  2. +107
    -107
      common/JackAudioAdapterInterface.cpp
  3. +132
    -128
      common/JackAudioAdapterInterface.h
  4. +5
    -4
      common/JackNetAdapter.cpp
  5. +54
    -35
      linux/alsa/JackAlsaAdapter.cpp
  6. +78
    -77
      linux/alsa/JackAlsaAdapter.h
  7. +57
    -40
      macosx/JackCoreAudioAdapter.cpp
  8. +10
    -9
      macosx/JackCoreAudioAdapter.h
  9. +179
    -161
      windows/JackPortAudioAdapter.cpp
  10. +15
    -14
      windows/JackPortAudioAdapter.h

+ 20
- 20
common/JackAudioAdapter.cpp View File

@@ -70,19 +70,19 @@ namespace Jack
return 0;
}

int JackAudioAdapter::BufferSize(jack_nframes_t buffer_size, void* arg)
int JackAudioAdapter::BufferSize ( jack_nframes_t buffer_size, void* arg )
{
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
adapter->Reset();
adapter->fAudioAdapter->SetBufferSize(buffer_size);
adapter->fAudioAdapter->SetHostBufferSize ( buffer_size );
return 0;
}

int JackAudioAdapter::SampleRate(jack_nframes_t sample_rate, void* arg)
int JackAudioAdapter::SampleRate ( jack_nframes_t sample_rate, void* arg )
{
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
adapter->Reset();
adapter->fAudioAdapter->SetSampleRate(sample_rate);
adapter->fAudioAdapter->SetHostSampleRate(sample_rate);
return 0;
}

@@ -104,12 +104,12 @@ namespace Jack
void JackAudioAdapter::FreePorts()
{
int i;
for ( i = 0; i < fCaptureChannels; i++ )
if ( fCapturePortList[i] )
jack_port_unregister ( fJackClient, fCapturePortList[i] );
for (i = 0; i < fCaptureChannels; i++)
if (fCapturePortList[i])
jack_port_unregister(fJackClient, fCapturePortList[i]);
for (i = 0; i < fCaptureChannels; i++)
if (fPlaybackPortList[i])
jack_port_unregister(fJackClient, fPlaybackPortList[i]);
if ( fPlaybackPortList[i] )
jack_port_unregister (fJackClient, fPlaybackPortList[i] );

delete[] fCapturePortList;
delete[] fPlaybackPortList;
@@ -127,7 +127,7 @@ namespace Jack

int JackAudioAdapter::Open()
{
jack_log("JackAudioAdapter::Open()");
jack_log("JackAudioAdapter::Open");

int i;
char name[32];
@@ -138,15 +138,15 @@ namespace Jack
//ringbuffers
fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
for (i = 0; i < fCaptureChannels; i++)
for ( i = 0; i < fCaptureChannels; i++ )
fCaptureRingBuffer[i] = new JackLibSampleRateResampler();
for (i = 0; i < fPlaybackChannels; i++)
for ( i = 0; i < fPlaybackChannels; i++ )
fPlaybackRingBuffer[i] = new JackLibSampleRateResampler();
fAudioAdapter->SetRingBuffers(fCaptureRingBuffer, fPlaybackRingBuffer);
if ( fCaptureChannels )
jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
jack_log ( "ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace() );
if ( fPlaybackChannels )
jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
jack_log ( "WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace() );

//jack ports
fCapturePortList = new jack_port_t* [fCaptureChannels];
@@ -155,25 +155,25 @@ namespace Jack
for (i = 0; i < fCaptureChannels; i++)
{
sprintf(name, "capture_%d", i+1);
if ((fCapturePortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL)
if ( ( fCapturePortList[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ) ) == NULL )
goto fail;
}

for (i = 0; i < fPlaybackChannels; i++)
{
sprintf(name, "playback_%d", i+1);
if ((fPlaybackPortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == NULL)
if ( ( fPlaybackPortList[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ) ) == NULL )
goto fail;
}

//callbacks and activation
if (jack_set_process_callback(fJackClient, Process, this) < 0)
if ( jack_set_process_callback ( fJackClient, Process, this ) < 0 )
goto fail;
if (jack_set_buffer_size_callback(fJackClient, BufferSize, this) < 0)
if ( jack_set_buffer_size_callback ( fJackClient, BufferSize, this ) < 0 )
goto fail;
if (jack_set_sample_rate_callback(fJackClient, SampleRate, this) < 0)
if ( jack_set_sample_rate_callback ( fJackClient, SampleRate, this ) < 0 )
goto fail;
if (jack_activate(fJackClient) < 0)
if ( jack_activate ( fJackClient ) < 0 )
goto fail;

//ringbuffers and jack clients are ok, we can now open the adapter driver interface


+ 107
- 107
common/JackAudioAdapterInterface.cpp View File

@@ -25,120 +25,120 @@ namespace Jack

#ifdef JACK_MONITOR

void MeasureTable::Write(int time1, int time2, float r1, float r2, int pos1, int pos2)
{
int pos = (++fCount) % TABLE_MAX;
fTable[pos].time1 = time1;
fTable[pos].time2 = time2;
fTable[pos].r1 = r1;
fTable[pos].r2 = r2;
fTable[pos].pos1 = pos1;
fTable[pos].pos2 = pos2;
}
void MeasureTable::Save()
{
char buffer[1024];
FILE* file = fopen("JackAudioAdapter.log", "w");

int MAX = (fCount) % TABLE_MAX - 1;
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].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
}
fclose(file);
// Adapter timing 1
file = fopen("AdapterTiming1.plot", "w");
fprintf(file, "set multiplot\n");
fprintf(file, "set grid\n");
fprintf(file, "set title \"Audio adapter timing\"\n");
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,");
fprintf(file, buffer);
sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines");
fprintf(file, buffer);
fclose(file);
// Adapter timing 2
file = fopen("AdapterTiming2.plot", "w");
fprintf(file, "set multiplot\n");
fprintf(file, "set grid\n");
fprintf(file, "set title \"Audio adapter timing\"\n");
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"resampling ratio\"\n");
fprintf(file, "plot ");
sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
fprintf(file, buffer);
sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
fprintf(file, buffer);
fclose(file);
// Adapter timing 3
file = fopen("AdapterTiming3.plot", "w");
fprintf(file, "set multiplot\n");
fprintf(file, "set grid\n");
fprintf(file, "set title \"Audio adapter timing\"\n");
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"frames\"\n");
fprintf(file, "plot ");
sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
fprintf(file, buffer);
sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
fprintf(file, buffer);
fclose(file);
}
void MeasureTable::Write(int time1, int time2, float r1, float r2, int pos1, int pos2)
{
int pos = (++fCount) % TABLE_MAX;
fTable[pos].time1 = time1;
fTable[pos].time2 = time2;
fTable[pos].r1 = r1;
fTable[pos].r2 = r2;
fTable[pos].pos1 = pos1;
fTable[pos].pos2 = pos2;
}

void MeasureTable::Save()
{
char buffer[1024];
FILE* file = fopen("JackAudioAdapter.log", "w");

int MAX = (fCount) % TABLE_MAX - 1;
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].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
}
fclose(file);

// Adapter timing 1
file = fopen("AdapterTiming1.plot", "w");
fprintf(file, "set multiplot\n");
fprintf(file, "set grid\n");
fprintf(file, "set title \"Audio adapter timing\"\n");
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,");
fprintf(file, buffer);
sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines");
fprintf(file, buffer);
fclose(file);

// Adapter timing 2
file = fopen("AdapterTiming2.plot", "w");
fprintf(file, "set multiplot\n");
fprintf(file, "set grid\n");
fprintf(file, "set title \"Audio adapter timing\"\n");
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"resampling ratio\"\n");
fprintf(file, "plot ");
sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
fprintf(file, buffer);
sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
fprintf(file, buffer);
fclose(file);

// Adapter timing 3
file = fopen("AdapterTiming3.plot", "w");
fprintf(file, "set multiplot\n");
fprintf(file, "set grid\n");
fprintf(file, "set title \"Audio adapter timing\"\n");
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"frames\"\n");
fprintf(file, "plot ");
sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
fprintf(file, buffer);
sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
fprintf(file, buffer);
fclose(file);
}

#endif

void JackAudioAdapterInterface::ResetRingBuffers()
{
int i;
for (i = 0; i < fCaptureChannels; i++) {
fCaptureRingBuffer[i]->Reset();
void JackAudioAdapterInterface::ResetRingBuffers()
{
int i;
for (i = 0; i < fCaptureChannels; i++)
fCaptureRingBuffer[i]->Reset();
for (i = 0; i < fPlaybackChannels; i++)
fPlaybackRingBuffer[i]->Reset();
}
for (i = 0; i < fPlaybackChannels; i++) {
fPlaybackRingBuffer[i]->Reset();

void JackAudioAdapterInterface::ResampleFactor ( jack_nframes_t& frame1, jack_nframes_t& frame2 )
{
jack_time_t time = jack_get_time();

if ( !fRunning )
{
// Init DLL
fRunning = true;
fHostDLL.Init ( time );
fAdaptedDLL.Init ( time );
frame1 = 1;
frame2 = 1;
}
else
{
// DLL
fAdaptedDLL.IncFrame(time);
jack_nframes_t time1 = fHostDLL.Time2Frames(time);
jack_nframes_t time2 = fAdaptedDLL.Time2Frames(time);
frame1 = time1;
frame2 = time2;
jack_log("JackAudioAdapterInterface::ResampleFactor time1 = %ld time2 = %ld src_ratio_input = %f src_ratio_output = %f",
long(time1), long(time2), double(time1) / double(time2), double(time2) / double(time1));
}
}
}

void JackAudioAdapterInterface::ResampleFactor(jack_nframes_t& frame1, jack_nframes_t& frame2)
{
jack_time_t time = jack_get_time();
if (!fRunning) {
// Init DLL
fRunning = true;
fProducerDLL.Init(time);
fConsumerDLL.Init(time);
frame1 = 1;
frame2 = 1;
} else {
// DLL
fProducerDLL.IncFrame(time);
jack_nframes_t time1 = fConsumerDLL.Time2Frames(time);
jack_nframes_t time2 = fProducerDLL.Time2Frames(time);
frame1 = time1;
frame2 = time2;
jack_log("JackAudioAdapterInterface::ResampleFactor time1 = %ld time2 = %ld src_ratio_input = %f src_ratio_output = %f",
long(time1), long(time2), double(time1) / double(time2), double(time2) / double(time1));
int JackAudioAdapterInterface::Open()
{
return 0;
}
}

int JackAudioAdapterInterface::Open()
{
return 0;
}
int JackAudioAdapterInterface::Close()
{
return 0;
}

int JackAudioAdapterInterface::Close()
{
return 0;
}
} // namespace

+ 132
- 128
common/JackAudioAdapterInterface.h View File

@@ -72,138 +72,142 @@ namespace Jack
class JackAudioAdapterInterface
{

protected:
protected:

#ifdef JACK_MONITOR
MeasureTable fTable;
MeasureTable fTable;
#endif
//channels
int fCaptureChannels;
int fPlaybackChannels;

//host parameters
jack_nframes_t fHostBufferSize;
jack_nframes_t fHostSampleRate;

//adapted parameters
jack_nframes_t fAdaptedBufferSize;
jack_nframes_t fAdaptedSampleRate;

//delay locked loop
JackAtomicDelayLockedLoop fHostDLL;
JackAtomicDelayLockedLoop fAdaptedDLL;

JackResampler** fCaptureRingBuffer;
JackResampler** fPlaybackRingBuffer;

bool fRunning;

public:

JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
fCaptureChannels ( 0 ),
fPlaybackChannels ( 0 ),
fHostBufferSize ( buffer_size ),
fHostSampleRate ( sample_rate ),
fAdaptedBufferSize ( buffer_size),
fAdaptedSampleRate ( sample_rate ),
fHostDLL ( buffer_size, sample_rate ),
fAdaptedDLL ( buffer_size, sample_rate ),
fRunning ( false )
{}

virtual ~JackAudioAdapterInterface()
{}

int fCaptureChannels;
int fPlaybackChannels;

jack_nframes_t fBufferSize;
jack_nframes_t fSampleRate;

// DLL
JackAtomicDelayLockedLoop fProducerDLL;
JackAtomicDelayLockedLoop fConsumerDLL;

JackResampler** fCaptureRingBuffer;
JackResampler** fPlaybackRingBuffer;

bool fRunning;

public:

JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate )
:fCaptureChannels ( 0 ),
fPlaybackChannels ( 0 ),
fBufferSize ( buffer_size ),
fSampleRate ( sample_rate ),
fProducerDLL ( buffer_size, sample_rate ),
fConsumerDLL ( buffer_size, sample_rate ),
fRunning ( false )
{}
virtual ~JackAudioAdapterInterface()
{}

void SetRingBuffers ( JackResampler** input, JackResampler** output )
{
fCaptureRingBuffer = input;
fPlaybackRingBuffer = output;
}

bool IsRunning() {return fRunning;}

virtual void Reset() {fRunning = false;}
void ResetRingBuffers();

virtual int Open();
virtual int Close();

virtual int SetBufferSize ( jack_nframes_t buffer_size )
{
fBufferSize = buffer_size;
fConsumerDLL.Init ( fBufferSize, fSampleRate );
fProducerDLL.Init ( fBufferSize, fSampleRate );
return 0;
}

virtual int SetHostBufferSize ( jack_nframes_t buffer_size )
{
fBufferSize = buffer_size;
fConsumerDLL.Init ( fBufferSize, fSampleRate );
return 0;
}

virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size )
{
fProducerDLL.Init ( buffer_size, fSampleRate );
return 0;
}

//TODO : switch the two next methods to SetHost/AdaptedBufferSize in adapters
virtual int SetSampleRate ( jack_nframes_t sample_rate )
{
fSampleRate = sample_rate;
fConsumerDLL.Init ( fBufferSize, fSampleRate );
// Producer (Audio) keeps the same SR
return 0;
}

virtual int SetAudioSampleRate ( jack_nframes_t sample_rate )
{
fSampleRate = sample_rate;
// Consumer keeps the same SR
fProducerDLL.Init ( fBufferSize, fSampleRate );
return 0;
}

//host = driver that hosts the adapter
virtual int SetHostSampleRate ( jack_nframes_t sample_rate )
{
fSampleRate = sample_rate;
fConsumerDLL.Init ( fBufferSize, fSampleRate );
return 0;
}

//adapted = driver hosted by the adapter
virtual int SetAdaptedSampleRate ( jack_nframes_t sample_rate )
{
fProducerDLL.Init ( fBufferSize, fSampleRate );
return 0;
}

virtual void SetCallbackTime ( jack_time_t callback_usec )
{
fConsumerDLL.IncFrame ( callback_usec );
}

void ResampleFactor ( jack_nframes_t& frame1, jack_nframes_t& frame2 );

void SetInputs ( int inputs )
{
jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs );
fCaptureChannels = inputs;
}

void SetOutputs ( int outputs )
{
jack_log ( "JackAudioAdapterInterface::SetOutputs %d", outputs );
fPlaybackChannels = outputs;
}

int GetInputs()
{
jack_log ( "JackAudioAdapterInterface::GetInputs %d", fCaptureChannels );
return fCaptureChannels;
}

int GetOutputs()
{
jack_log ( "JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels );
return fPlaybackChannels;
}
void SetRingBuffers ( JackResampler** input, JackResampler** output )
{
fCaptureRingBuffer = input;
fPlaybackRingBuffer = output;
}

bool IsRunning()
{
return fRunning;
}

virtual void Reset()
{
fRunning = false;
}

void ResetRingBuffers();

virtual int Open();
virtual int Close();

virtual int SetHostBufferSize ( jack_nframes_t buffer_size )
{
fHostBufferSize = buffer_size;
fHostDLL.Init ( fHostBufferSize, fHostSampleRate );
return 0;
}

virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size )
{
fAdaptedBufferSize = buffer_size;
fAdaptedDLL.Init ( fAdaptedBufferSize, fAdaptedSampleRate );
return 0;
}

virtual int SetBufferSize ( jack_nframes_t buffer_size )
{
SetHostBufferSize ( buffer_size );
SetAdaptedBufferSize ( buffer_size );
return 0;
}

virtual int SetHostSampleRate ( jack_nframes_t sample_rate )
{
fHostSampleRate = sample_rate;
fHostDLL.Init ( fHostBufferSize, fHostSampleRate );
return 0;
}

virtual int SetAdaptedSampleRate ( jack_nframes_t sample_rate )
{
fAdaptedSampleRate = sample_rate;
fAdaptedDLL.Init ( fAdaptedBufferSize, fAdaptedSampleRate );
return 0;
}

virtual int SetSampleRate ( jack_nframes_t sample_rate )
{
SetHostSampleRate ( sample_rate );
SetAdaptedSampleRate ( sample_rate );
return 0;
}

virtual void SetCallbackTime ( jack_time_t callback_usec )
{
fHostDLL.IncFrame ( callback_usec );
}

void ResampleFactor ( jack_nframes_t& frame1, jack_nframes_t& frame2 );

void SetInputs ( int inputs )
{
jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs );
fCaptureChannels = inputs;
}

void SetOutputs ( int outputs )
{
jack_log ( "JackAudioAdapterInterface::SetOutputs %d", outputs );
fPlaybackChannels = outputs;
}

int GetInputs()
{
jack_log ( "JackAudioAdapterInterface::GetInputs %d", fCaptureChannels );
return fCaptureChannels;
}

int GetOutputs()
{
jack_log ( "JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels );
return fPlaybackChannels;
}

};



+ 5
- 4
common/JackNetAdapter.cpp View File

@@ -178,7 +178,7 @@ namespace Jack

int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size )
{
JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
return 0;
}

@@ -210,7 +210,8 @@ namespace Jack
}

//set audio adapter parameters
JackAudioAdapterInterface::SetAdaptedBufferSize ( fParams.fPeriodSize );
SetAdaptedBufferSize ( fParams.fPeriodSize );
SetAdaptedSampleRate ( fParams.fSampleRate );

//init done, display parameters
SessionParamsDisplay ( &fParams );
@@ -278,14 +279,14 @@ namespace Jack
for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
{
fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 );
if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fParams.fPeriodSize ) < fParams.fPeriodSize )
if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fAdaptedBufferSize ) < fAdaptedBufferSize )
failure = true;
}
//and output data,
for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
{
fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 );
if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fParams.fPeriodSize ) < fParams.fPeriodSize )
if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fAdaptedBufferSize ) < fAdaptedBufferSize )
failure = true;
}



+ 54
- 35
linux/alsa/JackAlsaAdapter.cpp View File

@@ -30,46 +30,50 @@ namespace Jack

JackAlsaAdapter::JackAlsaAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
:JackAudioAdapterInterface(buffer_size, sample_rate)
,fThread(this), fAudioInterface(GetInputs(), GetOutputs(), buffer_size, sample_rate)
,fThread(this), fAudioInterface(GetInputs(), GetOutputs(), buffer_size, sample_rate)
{
const JSList* node;
const jack_driver_param_t* param;
fCaptureChannels = 2;
fPlaybackChannels = 2;
for (node = params; node; node = jack_slist_next(node)) {
param = (const jack_driver_param_t*) node->data;
switch (param->character) {
case 'i':
fCaptureChannels = param->value.ui;
break;
case 'o':
fPlaybackChannels = param->value.ui;
break;
case 'C':
break;
case 'P':
break;
case 'D':
break;
case 'n':
fAudioInterface.fPeriod = param->value.ui;
break;
case 'd':
fAudioInterface.fCardName = strdup(param->value.str);
break;
case 'r':
SetAudioSampleRate(param->value.ui);
SetAdaptedSampleRate(param->value.ui);
break;

case 'p':
SetAdaptedBufferSize(param->value.ui);
break;
}
}
@@ -77,14 +81,14 @@ namespace Jack

int JackAlsaAdapter::Open()
{
if (fAudioInterface.open() != 0)
if (fAudioInterface.open() != 0)
return -1;
if (fThread.StartSync() < 0) {
jack_error("Cannot start audioadapter thread");
return -1;
}
fAudioInterface.longinfo();
fThread.AcquireRealTime(JackServer::fInstance->GetEngineControl()->fPriority);
return 0;
@@ -96,7 +100,7 @@ int JackAlsaAdapter::Close()
fTable.Save();
#endif
switch (fThread.GetStatus()) {
// Kill the thread in Init phase
case JackThread::kStarting:
case JackThread::kIniting:
@@ -105,15 +109,15 @@ int JackAlsaAdapter::Close()
return -1;
}
break;
// Stop when the thread cycle is finished
case JackThread::kRunning:
if (fThread.Stop() < 0) {
jack_error("Cannot stop thread");
jack_error("Cannot stop thread");
return -1;
}
break;
default:
break;
}
@@ -126,25 +130,25 @@ bool JackAlsaAdapter::Init()
fAudioInterface.write();
return true;
}
bool JackAlsaAdapter::Execute()
{
if (fAudioInterface.read() < 0)
return false;

bool failure = false;
jack_nframes_t time1, time2;
jack_nframes_t time1, time2;
ResampleFactor(time1, time2);
for (int i = 0; i < fCaptureChannels; i++) {
fCaptureRingBuffer[i]->SetRatio(time1, time2);
if (fCaptureRingBuffer[i]->WriteResample(fAudioInterface.fInputSoftChannels[i], fBufferSize) < fBufferSize)
if (fCaptureRingBuffer[i]->WriteResample(fAudioInterface.fInputSoftChannels[i], fAdaptedBufferSize) < fAdaptedBufferSize)
failure = true;
}
for (int i = 0; i < fPlaybackChannels; i++) {
fPlaybackRingBuffer[i]->SetRatio(time2, time1);
if (fPlaybackRingBuffer[i]->ReadResample(fAudioInterface.fOutputSoftChannels[i], fBufferSize) < fBufferSize)
if (fPlaybackRingBuffer[i]->ReadResample(fAudioInterface.fOutputSoftChannels[i], fAdaptedBufferSize) < fAdaptedBufferSize)
failure = true;
}

@@ -152,10 +156,10 @@ bool JackAlsaAdapter::Execute()
fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace());
#endif
if (fAudioInterface.write() < 0)
return false;
// Reset all ringbuffers in case of failure
if (failure) {
jack_error("JackAlsaAdapter::Execute ringbuffer failure... reset");
@@ -164,13 +168,20 @@ bool JackAlsaAdapter::Execute()
return true;
}

int JackAlsaAdapter::SetSampleRate(jack_nframes_t sample_rate)
{
JackAudioAdapterInterface::SetHostSampleRate(sample_rate);
Close();
return Open();
}

int JackAlsaAdapter::SetBufferSize(jack_nframes_t buffer_size)
{
JackAudioAdapterInterface::SetBufferSize(buffer_size);
JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
Close();
return Open();
}
} // namespace

#ifdef __cplusplus
@@ -183,12 +194,12 @@ extern "C"
jack_driver_desc_t *desc;
jack_driver_param_desc_t * params;
unsigned int i;
desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
strcpy (desc->name, "alsa-adapter");
desc->nparams = 8;
desc->nparams = 9;
params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
i = 0;
strcpy(params[i].name, "capture");
params[i].character = 'C';
@@ -214,7 +225,7 @@ extern "C"
strcpy(params[i].value.str, "hw:0");
strcpy(params[i].short_desc, "ALSA device name");
strcpy(params[i].long_desc, params[i].short_desc);
i++;
strcpy (params[i].name, "rate");
params[i].character = 'r';
@@ -223,6 +234,14 @@ extern "C"
strcpy(params[i].short_desc, "Sample rate");
strcpy(params[i].long_desc, params[i].short_desc);

i++;
strcpy (params[i].name, "periodsize");
params[i].character = 'p';
params[i].type = JackDriverParamUInt;
params[i].value.ui = 512U;
strcpy(params[i].short_desc, "Perdio size");
strcpy(params[i].long_desc, params[i].short_desc);

i++;
strcpy(params[i].name, "nperiods");
params[i].character = 'n';
@@ -261,7 +280,7 @@ extern "C"
desc->params = params;
return desc;
}
#ifdef __cplusplus
}
#endif


+ 78
- 77
linux/alsa/JackAlsaAdapter.h View File

@@ -49,32 +49,32 @@ class AudioParam
{

public:
const char* fCardName;
const char* fCardName;
unsigned int fFrequency;
int fBuffering;
int fBuffering;
unsigned int fSoftInputs;
unsigned int fSoftOutputs;
public:
AudioParam() :
AudioParam() :
fCardName("hw:0"),
fFrequency(44100),
fBuffering(512),
fSoftInputs(2),
fSoftOutputs(2)
{}
AudioParam(int input, int output, jack_nframes_t buffer_size, jack_nframes_t sample_rate) :
AudioParam(int input, int output, jack_nframes_t buffer_size, jack_nframes_t sample_rate) :
fCardName("hw:0"),
fFrequency(sample_rate),
fBuffering(buffer_size),
fSoftInputs(input),
fSoftOutputs(output)
{}
AudioParam& cardName(const char* n) { fCardName = n; return *this; }
AudioParam& frequency(int f) { fFrequency = f; return *this; }
AudioParam& buffering(int fpb) { fBuffering = fpb; return *this; }
@@ -89,44 +89,44 @@ class AudioInterface : public AudioParam
{

public:
snd_pcm_t* fOutputDevice;
snd_pcm_t* fInputDevice;
snd_pcm_t* fOutputDevice;
snd_pcm_t* fInputDevice;
snd_pcm_hw_params_t* fInputParams;
snd_pcm_hw_params_t* fOutputParams;
snd_pcm_format_t fSampleFormat;
snd_pcm_access_t fSampleAccess;
unsigned int fCardInputs;
unsigned int fCardOutputs;
unsigned int fChanInputs;
unsigned int fChanOutputs;

unsigned int fPeriod;
// interleaved mode audiocard buffers
void* fInputCardBuffer;
void* fOutputCardBuffer;
// non interleaved mode audiocard buffers
void* fInputCardChannels[256];
void* fOutputCardChannels[256];
// non interleaved mod, floating point software buffers
float* fInputSoftChannels[256];
float* fOutputSoftChannels[256];

public:
const char* cardName() { return fCardName; }
int frequency() { return fFrequency; }
int buffering() { return fBuffering; }
float** inputSoftChannels() { return fInputSoftChannels; }
float** outputSoftChannels() { return fOutputSoftChannels; }
AudioInterface(const AudioParam& ap = AudioParam()) : AudioParam(ap)
{
fInputDevice = 0;
@@ -136,7 +136,7 @@ class AudioInterface : public AudioParam
fPeriod = 2;
}

AudioInterface(int input, int output, jack_nframes_t buffer_size, jack_nframes_t sample_rate) :
AudioInterface(int input, int output, jack_nframes_t buffer_size, jack_nframes_t sample_rate) :
AudioParam(input, output, buffer_size, sample_rate)
{
fInputCardBuffer = 0;
@@ -149,7 +149,7 @@ class AudioInterface : public AudioParam
fOutputSoftChannels[i] = 0;
}
}
/**
* Open the audio interface
*/
@@ -188,7 +188,7 @@ class AudioInterface : public AudioParam
fOutputCardChannels[i] = aligned_calloc(noninterleavedBufferSize(fOutputParams), 1);
}
}
// allocation of floating point buffers needed by the dsp code
fChanInputs = max(fSoftInputs, fCardInputs); assert (fChanInputs < 256);
fChanOutputs = max(fSoftOutputs, fCardOutputs); assert (fChanOutputs < 256);
@@ -208,7 +208,7 @@ class AudioInterface : public AudioParam
}
return 0;
}
int close()
{
snd_pcm_hw_params_free(fInputParams);
@@ -240,26 +240,26 @@ class AudioInterface : public AudioParam
free(fInputCardBuffer);
if (fOutputCardBuffer)
free(fOutputCardBuffer);
return 0;
}
int setAudioParams(snd_pcm_t* stream, snd_pcm_hw_params_t* params)
{
{
int err;

// set params record with initial values
err = snd_pcm_hw_params_any ( stream, params );
err = snd_pcm_hw_params_any ( stream, params );
check_error_msg(err, "unable to init parameters")

// set alsa access mode (and fSampleAccess field) either to non interleaved or interleaved
err = snd_pcm_hw_params_set_access (stream, params, SND_PCM_ACCESS_RW_NONINTERLEAVED );
if (err) {
err = snd_pcm_hw_params_set_access (stream, params, SND_PCM_ACCESS_RW_INTERLEAVED );
check_error_msg(err, "unable to set access mode neither to non-interleaved or to interleaved");
}
snd_pcm_hw_params_get_access(params, &fSampleAccess);
snd_pcm_hw_params_get_access(params, &fSampleAccess);

// search for 32-bits or 16-bits format
err = snd_pcm_hw_params_set_format (stream, params, SND_PCM_FORMAT_S32);
@@ -269,13 +269,13 @@ class AudioInterface : public AudioParam
}
snd_pcm_hw_params_get_format(params, &fSampleFormat);
// set sample frequency
snd_pcm_hw_params_set_rate_near (stream, params, &fFrequency, 0);
snd_pcm_hw_params_set_rate_near (stream, params, &fFrequency, 0);

// set period and period size (buffering)
err = snd_pcm_hw_params_set_period_size (stream, params, fBuffering, 0);
err = snd_pcm_hw_params_set_period_size (stream, params, fBuffering, 0);
check_error_msg(err, "period size not available");
err = snd_pcm_hw_params_set_periods (stream, params, fPeriod, 0);
err = snd_pcm_hw_params_set_periods (stream, params, fPeriod, 0);
check_error_msg(err, "number of periods not available");
return 0;
}
@@ -298,20 +298,20 @@ class AudioInterface : public AudioParam
}

/**
* Read audio samples from the audio card. Convert samples to floats and take
* Read audio samples from the audio card. Convert samples to floats and take
* care of interleaved buffers
*/
int read()
{
if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) {
int count = snd_pcm_readi(fInputDevice, fInputCardBuffer, fBuffering);
if (count<0) {
int count = snd_pcm_readi(fInputDevice, fInputCardBuffer, fBuffering);
if (count<0) {
display_error_msg(count, "reading samples");
int err = snd_pcm_prepare(fInputDevice);
int err = snd_pcm_prepare(fInputDevice);
check_error_msg(err, "preparing input stream");
}
if (fSampleFormat == SND_PCM_FORMAT_S16) {

short* buffer16b = (short*) fInputCardBuffer;
@@ -330,16 +330,16 @@ class AudioInterface : public AudioParam
}
}
}
} else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
int count = snd_pcm_readn(fInputDevice, fInputCardChannels, fBuffering);
if (count < 0) {
int count = snd_pcm_readn(fInputDevice, fInputCardChannels, fBuffering);
if (count < 0) {
display_error_msg(count, "reading samples");
int err = snd_pcm_prepare(fInputDevice);
int err = snd_pcm_prepare(fInputDevice);
check_error_msg(err, "preparing input stream");
}
if (fSampleFormat == SND_PCM_FORMAT_S16) {

for (unsigned int c = 0; c < fCardInputs; c++) {
@@ -358,7 +358,7 @@ class AudioInterface : public AudioParam
}
}
}
} else {
check_error_msg(-10000, "unknow access mode");
}
@@ -367,15 +367,15 @@ class AudioInterface : public AudioParam
}

/**
* write the output soft channels to the audio card. Convert sample
* write the output soft channels to the audio card. Convert sample
* format and interleaves buffers when needed
*/
int write()
{
recovery:
if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) {
if (fSampleFormat == SND_PCM_FORMAT_S16) {

short* buffer16b = (short*) fOutputCardBuffer;
@@ -397,17 +397,17 @@ class AudioInterface : public AudioParam
}
}

int count = snd_pcm_writei(fOutputDevice, fOutputCardBuffer, fBuffering);
if (count < 0) {
display_error_msg(count, "w3");
int err = snd_pcm_prepare(fOutputDevice);
int count = snd_pcm_writei(fOutputDevice, fOutputCardBuffer, fBuffering);
if (count < 0) {
display_error_msg(count, "w3");
int err = snd_pcm_prepare(fOutputDevice);
check_error_msg(err, "preparing output stream");
goto recovery;
}
} else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
if (fSampleFormat == SND_PCM_FORMAT_S16) {

for (unsigned int c = 0; c < fCardOutputs; c++) {
@@ -429,21 +429,21 @@ class AudioInterface : public AudioParam
}
}

int count = snd_pcm_writen(fOutputDevice, fOutputCardChannels, fBuffering);
if (count<0) {
display_error_msg(count, "w3");
int err = snd_pcm_prepare(fOutputDevice);
int count = snd_pcm_writen(fOutputDevice, fOutputCardChannels, fBuffering);
if (count<0) {
display_error_msg(count, "w3");
int err = snd_pcm_prepare(fOutputDevice);
check_error_msg(err, "preparing output stream");
goto recovery;
}
} else {
check_error_msg(-10000, "unknow access mode");
}

return 0;
}
/**
* print short information on the audio device
*/
@@ -455,13 +455,13 @@ class AudioInterface : public AudioParam
err = snd_ctl_open(&ctl_handle, fCardName, 0); check_error(err);
snd_ctl_card_info_alloca(&card_info);
err = snd_ctl_card_info(ctl_handle, card_info); check_error(err);
jack_info("%s|%d|%d|%d|%d|%s",
jack_info("%s|%d|%d|%d|%d|%s",
snd_ctl_card_info_get_driver(card_info),
fCardInputs, fCardOutputs,
fFrequency, fBuffering,
snd_pcm_format_name((_snd_pcm_format)fSampleFormat));
}
/**
* print more detailled information on the audio device
*/
@@ -472,12 +472,12 @@ class AudioInterface : public AudioParam
snd_ctl_t* ctl_handle;

jack_info("Audio Interface Description :");
jack_info("Sampling Frequency : %d, Sample Format : %s, buffering : %d nperiod : %d",
jack_info("Sampling Frequency : %d, Sample Format : %s, buffering : %d nperiod : %d",
fFrequency, snd_pcm_format_name((_snd_pcm_format)fSampleFormat), fBuffering, fPeriod);
jack_info("Software inputs : %2d, Software outputs : %2d", fSoftInputs, fSoftOutputs);
jack_info("Hardware inputs : %2d, Hardware outputs : %2d", fCardInputs, fCardOutputs);
jack_info("Channel inputs : %2d, Channel outputs : %2d", fChanInputs, fChanOutputs);
// affichage des infos de la carte
err = snd_ctl_open (&ctl_handle, fCardName, 0); check_error(err);
snd_ctl_card_info_alloca (&card_info);
@@ -489,7 +489,7 @@ class AudioInterface : public AudioParam
if (fSoftOutputs > 0) printHWParams(fOutputParams);
return 0;
}
void printCardInfo(snd_ctl_card_info_t* ci)
{
jack_info("Card info (address : %p)", ci);
@@ -528,24 +528,25 @@ class JackAlsaAdapter : public JackAudioAdapterInterface, public JackRunnableInt
{

private:
JackThread fThread;
AudioInterface fAudioInterface;
public:
JackAlsaAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params);
~JackAlsaAdapter()
{}
virtual int Open();
virtual int Close();

virtual int SetSampleRate(jack_nframes_t sample_rate);
virtual int SetBufferSize(jack_nframes_t buffer_size);
virtual bool Init();
virtual bool Execute();
};

}


+ 57
- 40
macosx/JackCoreAudioAdapter.cpp View File

@@ -116,7 +116,7 @@ OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice,

return noErr;
}
OSStatus JackCoreAudioAdapter::Render(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
@@ -127,27 +127,27 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon,
JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon);
AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
bool failure = false;
jack_nframes_t time1, time2;
jack_nframes_t time1, time2;
adapter->ResampleFactor(time1, time2);
for (int i = 0; i < adapter->fCaptureChannels; i++) {
adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
if (adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames) < inNumberFrames)
failure = true;
}
for (int i = 0; i < adapter->fPlaybackChannels; i++) {
adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
if (adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames) < inNumberFrames)
failure = true;
}
#ifdef JACK_MONITOR
adapter->fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
#ifdef JACK_MONITOR
adapter->fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace());
#endif
// Reset all ringbuffers in case of failure
if (failure) {
jack_error("JackCoreAudioAdapter::Render ringbuffer failure... reset");
@@ -162,39 +162,42 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon,

const JSList* node;
const jack_driver_param_t* param;
fCaptureChannels = 2;
fPlaybackChannels = 2;
for (node = params; node; node = jack_slist_next(node)) {
param = (const jack_driver_param_t*) node->data;
switch (param->character) {
case 'c' :
break;
case 'i':
fCaptureChannels = param->value.ui;
break;
case 'o':
fPlaybackChannels = param->value.ui;
break;
case 'C':
break;
case 'P':
break;
case 'D':
break;
case 'r':
SetAudioSampleRate(param->value.ui);
SetAdaptedSampleRate(param->value.ui);
break;

case 'p':
SetAdaptedBufferSize(param->value.ui);
break;
case 'l':
break;
}
@@ -260,7 +263,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
jack_error("Cannot open default device");
return -1;
}
return 0;
}

@@ -273,21 +276,21 @@ int JackCoreAudioAdapter::SetupChannels(bool capturing,
bool strict)
{
OSStatus err = noErr;
err = GetTotalChannels(fDeviceID, &in_nChannels, true);
if (err != noErr) {
jack_error("Cannot get input channel number");
printError(err);
return -1;
}
err = GetTotalChannels(fDeviceID, &out_nChannels, false);
if (err != noErr) {
jack_error("Cannot get output channel number");
printError(err);
return -1;
}
return 0;
}

@@ -350,7 +353,7 @@ int JackCoreAudioAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, j
int JackCoreAudioAdapter::SetupBuffers(int inchannels, int outchannels)
{
jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld output = %ld", inchannels, outchannels);
// Prepare buffers
fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
if (fInputData == 0) {
@@ -369,7 +372,7 @@ int JackCoreAudioAdapter::SetupBuffers(int inchannels, int outchannels)
void JackCoreAudioAdapter::DisposeBuffers()
{
if (fInputData) {
for (int i = 0; i < fCaptureChannels; i++)
for (int i = 0; i < fCaptureChannels; i++)
free(fInputData->mBuffers[i].mData);
free(fInputData);
fInputData = 0;
@@ -559,13 +562,13 @@ void JackCoreAudioAdapter::CloseAUHAL()
AudioUnitUninitialize(fAUHAL);
CloseComponent(fAUHAL);
}
int JackCoreAudioAdapter::Open()
{
OSStatus err;
int in_nChannels = 0;
int out_nChannels = 0;
if (SetupDevices("", "", "", "") < 0)
return -1;

@@ -580,11 +583,11 @@ int JackCoreAudioAdapter::Open()

if (SetupBuffers(fCaptureChannels, fPlaybackChannels) < 0)
goto error;
err = AudioOutputUnitStart(fAUHAL);
if (err != noErr)
goto error;
return 0;

error:
@@ -594,7 +597,7 @@ error:

int JackCoreAudioAdapter::Close()
{
#ifdef JACK_MONITOR
#ifdef JACK_MONITOR
fTable.Save();
#endif
AudioOutputUnitStop(fAUHAL);
@@ -603,9 +606,15 @@ int JackCoreAudioAdapter::Close()
return 0;
}

int JackCoreAudioAdapter::SetBufferSize(jack_nframes_t buffer_size)
{
JackAudioAdapterInterface::SetBufferSize(buffer_size);

int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) {
JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
Close();
return Open();
}

int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) {
JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
Close();
return Open();
}
@@ -617,14 +626,14 @@ extern "C"
{
#endif

EXPORT jack_driver_desc_t* jack_get_descriptor()
EXPORT jack_driver_desc_t* jack_get_descriptor()
{
jack_driver_desc_t *desc;
unsigned int i;
desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));

strcpy(desc->name, "coreaudio-adapter");
desc->nparams = 9;
desc->nparams = 10;
desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));

i = 0;
@@ -666,7 +675,7 @@ extern "C"
strcpy(desc->params[i].value.str, "will take default CoreAudio output device");
strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
i++;
strcpy(desc->params[i].name, "rate");
desc->params[i].character = 'r';
@@ -675,6 +684,14 @@ extern "C"
strcpy(desc->params[i].short_desc, "Sample rate");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);

i++;
strcpy(desc->params[i].name, "periodsize");
desc->params[i].character = 'p';
desc->params[i].type = JackDriverParamUInt;
desc->params[i].value.ui = 512U;
strcpy(desc->params[i].short_desc, "Period size");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);

i++;
strcpy(desc->params[i].name, "duplex");
desc->params[i].character = 'D';
@@ -698,11 +715,11 @@ extern "C"
desc->params[i].value.i = TRUE;
strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
return desc;
}

#ifdef __cplusplus
}
#endif


+ 10
- 9
macosx/JackCoreAudioAdapter.h View File

@@ -44,23 +44,23 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface
{

private:
AudioUnit fAUHAL;
AudioBufferList* fInputData;
AudioDeviceID fDeviceID;
bool fState;

AudioUnitRenderActionFlags* fActionFags;
AudioTimeStamp* fCurrentTime;
static OSStatus Render(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData);
static OSStatus SRNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel,
Boolean isInput,
@@ -83,7 +83,7 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface
int& in_nChannels,
int& out_nChannels,
bool strict);
int OpenAUHAL(bool capturing,
bool playing,
int inchannels,
@@ -100,16 +100,17 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface
void CloseAUHAL();

public:
JackCoreAudioAdapter( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params);
~JackCoreAudioAdapter()
{}
virtual int Open();
virtual int Close();

virtual int SetSampleRate(jack_nframes_t sample_rate);
virtual int SetBufferSize(jack_nframes_t buffer_size);
};
}



+ 179
- 161
windows/JackPortAudioAdapter.cpp View File

@@ -27,196 +27,206 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack
{

int JackPortAudioAdapter::Render(const void* inputBuffer, void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData)
{
JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData);
float** paBuffer;
float* buffer;
bool failure = false;
jack_nframes_t time1, time2;
adapter->ResampleFactor(time1, time2);
paBuffer = (float**)inputBuffer;
for (int i = 0; i < adapter->fCaptureChannels; i++) {
buffer = (float*)paBuffer[i];
adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
if (adapter->fCaptureRingBuffer[i]->WriteResample(buffer, framesPerBuffer) < framesPerBuffer)
failure = true;
}
int JackPortAudioAdapter::Render ( const void* inputBuffer,
void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData)
{
JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData);
float** paBuffer;
bool failure = false;
jack_nframes_t time1, time2;
adapter->ResampleFactor ( time1, time2 );
paBuffer = (float**)inputBuffer;
for ( int i = 0; i < adapter->fCaptureChannels; i++ )
{
adapter->fCaptureRingBuffer[i]->SetRatio ( time1, time2 );
if (adapter->fCaptureRingBuffer[i]->WriteResample ( (float*)paBuffer[i], framesPerBuffer ) < framesPerBuffer )
failure = true;
}

paBuffer = (float**)outputBuffer;
for (int i = 0; i < adapter->fPlaybackChannels; i++) {
buffer = (float*)paBuffer[i];
adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
if (adapter->fPlaybackRingBuffer[i]->ReadResample(buffer, framesPerBuffer) < framesPerBuffer)
failure = true;
}
paBuffer = (float**)outputBuffer;
for ( int i = 0; i < adapter->fPlaybackChannels; i++ )
{
adapter->fPlaybackRingBuffer[i]->SetRatio ( time2, time1 );
if ( adapter->fPlaybackRingBuffer[i]->ReadResample ( (float*)paBuffer[i], framesPerBuffer ) < framesPerBuffer )
failure = true;
}

#ifdef JACK_MONITOR
adapter->fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace());
adapter->fTable.Write ( time1, time2, double(time1) / double(time2), double(time2) / double(time1),
adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace() );
#endif

// Reset all ringbuffers in case of failure
if (failure) {
jack_error("JackPortAudioAdapter::Render ringbuffer failure... reset");
adapter->ResetRingBuffers();
// Reset all ringbuffers in case of failure
if ( failure )
{
jack_error ( "JackPortAudioAdapter::Render ringbuffer failure... reset" );
adapter->ResetRingBuffers();
}
return paContinue;
}
return paContinue;
}

JackPortAudioAdapter::JackPortAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
:JackAudioAdapterInterface(buffer_size, sample_rate)
{
jack_log ( "JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate );

const JSList* node;
const jack_driver_param_t* param;
int in_max = 0;
int out_max = 0;

fCaptureChannels = 0;
fPlaybackChannels = 0;
JackPortAudioAdapter::JackPortAudioAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
: JackAudioAdapterInterface ( buffer_size, sample_rate )
{
jack_log ( "JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate );

fInputDevice = Pa_GetDefaultInputDevice();
fOutputDevice = Pa_GetDefaultOutputDevice();
const JSList* node;
const jack_driver_param_t* param;
int in_max = 0;
int out_max = 0;

for (node = params; node; node = jack_slist_next(node)) {
param = (const jack_driver_param_t*) node->data;
fInputDevice = Pa_GetDefaultInputDevice();
fOutputDevice = Pa_GetDefaultOutputDevice();

switch (param->character) {
for (node = params; node; node = jack_slist_next(node))
{
param = (const jack_driver_param_t*) node->data;

case 'i':
switch (param->character)
{
case 'i' :
fCaptureChannels = param->value.ui;
break;

case 'o':
case 'o' :
fPlaybackChannels = param->value.ui;
break;
case 'C':
if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 ) {
jack_error ( "Can't use %s, taking default input device", param->value.str );
fInputDevice = Pa_GetDefaultInputDevice();
}
case 'C' :
if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 )
{
jack_error ( "Can't use %s, taking default input device", param->value.str );
fInputDevice = Pa_GetDefaultInputDevice();
}
break;

case 'P':
if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 ) {
jack_error ( "Can't use %s, taking default output device", param->value.str );
fOutputDevice = Pa_GetDefaultOutputDevice();
}

case 'P' :
if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 )
{
jack_error ( "Can't use %s, taking default output device", param->value.str );
fOutputDevice = Pa_GetDefaultOutputDevice();
}
break;

case 'r':
SetAudioSampleRate(param->value.ui);
case 'r' :
SetAdaptedSampleRate ( param->value.ui );
break;

case 'd':
if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 ) {
jack_error ( "Can't use %s, taking default input device", param->value.str );
}
if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 ) {
jack_error ( "Can't use %s, taking default output device", param->value.str );
}
case 'p' :
SetAdaptedBufferSize ( param->value.ui );
break;

case 'l':
fPaDevices.DisplayDevicesNames();
case 'd' :
if ( fPaDevices.GetInputDeviceFromName ( param->value.str, fInputDevice, in_max ) < 0 )
jack_error ( "Can't use %s, taking default input device", param->value.str );
if ( fPaDevices.GetOutputDeviceFromName ( param->value.str, fOutputDevice, out_max ) < 0 )
jack_error ( "Can't use %s, taking default output device", param->value.str );
break;
case 'l' :
fPaDevices.DisplayDevicesNames();
break;
}
}

//max channels
if ( in_max == 0 )
in_max = fPaDevices.GetDeviceInfo ( fInputDevice )->maxInputChannels;
if ( out_max == 0 )
out_max = fPaDevices.GetDeviceInfo ( fOutputDevice )->maxOutputChannels;

//effective channels
if ( ( fCaptureChannels == 0 ) || ( fCaptureChannels > in_max ) )
fCaptureChannels = in_max;
if ( ( fPlaybackChannels == 0 ) || ( fPlaybackChannels > out_max ) )
fPlaybackChannels = out_max;

//set adapter interface channels
SetInputs ( fCaptureChannels );
SetOutputs ( fPlaybackChannels );
}

//max channels
if ( in_max == 0 )
in_max = fPaDevices.GetDeviceInfo(fInputDevice)->maxInputChannels;
if ( out_max == 0 )
out_max = fPaDevices.GetDeviceInfo(fOutputDevice)->maxOutputChannels;

//effective channels
if ( ( fCaptureChannels == 0 ) || ( fCaptureChannels > in_max ) )
fCaptureChannels = in_max;
if ( ( fPlaybackChannels == 0 ) || ( fPlaybackChannels > out_max ) )
fPlaybackChannels = out_max;
}
int JackPortAudioAdapter::Open()
{
PaError err;
PaStreamParameters inputParameters;
PaStreamParameters outputParameters;

if ( JackAudioAdapterInterface::Open() < 0 )
return -1;

jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str());
jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str());
jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate);

inputParameters.device = fInputDevice;
inputParameters.channelCount = fCaptureChannels;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
inputParameters.suggestedLatency = ( fInputDevice != paNoDevice ) // TODO: check how to setup this on ASIO
? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency
: 0;
inputParameters.hostApiSpecificStreamInfo = NULL;

outputParameters.device = fOutputDevice;
outputParameters.channelCount = fPlaybackChannels;
outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
outputParameters.suggestedLatency = ( fOutputDevice != paNoDevice ) // TODO: check how to setup this on ASIO
? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
: 0;
outputParameters.hostApiSpecificStreamInfo = NULL;

err = Pa_OpenStream( &fStream,
( fInputDevice == paNoDevice ) ? 0 : &inputParameters,
( fOutputDevice == paNoDevice ) ? 0 : &outputParameters,
fAdaptedSampleRate,
fAdaptedBufferSize,
paNoFlag, // Clipping is on...
Render,
this );

if ( err != paNoError )
{
jack_error ( "Pa_OpenStream error = %s", Pa_GetErrorText ( err ) );
return -1;
}

int JackPortAudioAdapter::Open()
{
PaError err;
PaStreamParameters inputParameters;
PaStreamParameters outputParameters;

if (JackAudioAdapterInterface::Open() < 0)
return -1;

jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str());
jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str());
jack_log("JackPortAudioAdapter::Open fBufferSize = %u fSampleRate %u", fBufferSize, fSampleRate);

inputParameters.device = fInputDevice;
inputParameters.channelCount = fCaptureChannels;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO
? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency
: 0;
inputParameters.hostApiSpecificStreamInfo = NULL;

outputParameters.device = fOutputDevice;
outputParameters.channelCount = fPlaybackChannels;
outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO
? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
: 0;
outputParameters.hostApiSpecificStreamInfo = NULL;

err = Pa_OpenStream(&fStream,
(fInputDevice == paNoDevice) ? 0 : &inputParameters,
(fOutputDevice == paNoDevice) ? 0 : &outputParameters,
fSampleRate,
fBufferSize,
paNoFlag, // Clipping is on...
Render,
this);
if (err != paNoError) {
jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
return -1;
}
err = Pa_StartStream ( fStream );

err = Pa_StartStream(fStream);
if (err != paNoError) {
jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err));
return -1;
}
jack_log("JackPortAudioAdapter::Open OK");
return 0;
if ( err != paNoError )
{
jack_error ( "Pa_StartStream error = %s", Pa_GetErrorText ( err ) );
return -1;
}

}
jack_log ( "JackPortAudioAdapter::Open OK" );
return 0;
}

int JackPortAudioAdapter::Close()
{
int JackPortAudioAdapter::Close()
{
#ifdef JACK_MONITOR
fTable.Save();
fTable.Save();
#endif
jack_log("JackPortAudioAdapter::Close");
Pa_StopStream(fStream);
jack_log("JackPortAudioAdapter:: Pa_StopStream");
Pa_CloseStream(fStream);
jack_log("JackPortAudioAdapter:: Pa_CloseStream");
return JackAudioAdapterInterface::Close();
}
jack_log ( "JackPortAudioAdapter::Close" );
Pa_StopStream ( fStream );
jack_log ( "JackPortAudioAdapter:: Pa_StopStream" );
Pa_CloseStream ( fStream );
jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" );
return JackAudioAdapterInterface::Close();
}

int JackPortAudioAdapter::SetBufferSize(jack_nframes_t buffer_size)
{
JackAudioAdapterInterface::SetBufferSize(buffer_size);
Close();
return Open();
}
int JackPortAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate )
{
JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
Close();
return Open();
}

int JackPortAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size )
{
JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
Close();
return Open();
}

} // namespace

@@ -232,7 +242,7 @@ extern "C"
desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));

strcpy(desc->name, "portaudio-adapter");
desc->nparams = 7;
desc->nparams = 8;
desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));

i = 0;
@@ -275,6 +285,14 @@ extern "C"
strcpy(desc->params[i].short_desc, "Sample rate");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);

i++;
strcpy(desc->params[i].name, "periodsize");
desc->params[i].character = 'p';
desc->params[i].type = JackDriverParamUInt;
desc->params[i].value.ui = 512U;
strcpy(desc->params[i].short_desc, "Period size");
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);

i++;
strcpy(desc->params[i].name, "device");
desc->params[i].character = 'd';


+ 15
- 14
windows/JackPortAudioAdapter.h View File

@@ -27,12 +27,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack
{

/*!
\brief Audio adapter using PortAudio API.
*/
/*!
\brief Audio adapter using PortAudio API.
*/

class JackPortAudioAdapter : public JackAudioAdapterInterface
{
class JackPortAudioAdapter : public JackAudioAdapterInterface
{

private:

@@ -41,24 +41,25 @@ class JackPortAudioAdapter : public JackAudioAdapterInterface
PaDeviceIndex fInputDevice;
PaDeviceIndex fOutputDevice;

static int Render(const void* inputBuffer, void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData);
static int Render ( const void* inputBuffer, void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData );

public:

JackPortAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params);
JackPortAudioAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params );
~JackPortAudioAdapter()
{}

int Open();
int Close();

int SetBufferSize(jack_nframes_t buffer_size);
int SetSampleRate ( jack_nframes_t sample_rate );
int SetBufferSize ( jack_nframes_t buffer_size );

};
};

}

@@ -70,7 +71,7 @@ extern "C"
#include "JackExports.h"
#include "driver_interface.h"

EXPORT jack_driver_desc_t* jack_get_descriptor();
EXPORT jack_driver_desc_t* jack_get_descriptor();

#ifdef __cplusplus
}


Loading…
Cancel
Save