git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2796 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
@@ -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 | |||
@@ -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 |
@@ -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; | |||
} | |||
}; | |||
@@ -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; | |||
} | |||
@@ -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 | |||
@@ -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(); | |||
}; | |||
} | |||
@@ -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 | |||
@@ -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); | |||
}; | |||
} | |||
@@ -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'; | |||
@@ -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 | |||
} | |||