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; | 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); | JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | ||||
adapter->Reset(); | adapter->Reset(); | ||||
adapter->fAudioAdapter->SetBufferSize(buffer_size); | |||||
adapter->fAudioAdapter->SetHostBufferSize ( buffer_size ); | |||||
return 0; | 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); | JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | ||||
adapter->Reset(); | adapter->Reset(); | ||||
adapter->fAudioAdapter->SetSampleRate(sample_rate); | |||||
adapter->fAudioAdapter->SetHostSampleRate(sample_rate); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -104,12 +104,12 @@ namespace Jack | |||||
void JackAudioAdapter::FreePorts() | void JackAudioAdapter::FreePorts() | ||||
{ | { | ||||
int i; | int i; | ||||
for ( i = 0; i < fCaptureChannels; i++ ) | |||||
if ( fCapturePortList[i] ) | |||||
jack_port_unregister ( fJackClient, fCapturePortList[i] ); | |||||
for (i = 0; i < fCaptureChannels; 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[] fCapturePortList; | ||||
delete[] fPlaybackPortList; | delete[] fPlaybackPortList; | ||||
@@ -127,7 +127,7 @@ namespace Jack | |||||
int JackAudioAdapter::Open() | int JackAudioAdapter::Open() | ||||
{ | { | ||||
jack_log("JackAudioAdapter::Open()"); | |||||
jack_log("JackAudioAdapter::Open"); | |||||
int i; | int i; | ||||
char name[32]; | char name[32]; | ||||
@@ -138,15 +138,15 @@ namespace Jack | |||||
//ringbuffers | //ringbuffers | ||||
fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; | fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; | ||||
fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; | fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; | ||||
for (i = 0; i < fCaptureChannels; i++) | |||||
for ( i = 0; i < fCaptureChannels; i++ ) | |||||
fCaptureRingBuffer[i] = new JackLibSampleRateResampler(); | fCaptureRingBuffer[i] = new JackLibSampleRateResampler(); | ||||
for (i = 0; i < fPlaybackChannels; i++) | |||||
for ( i = 0; i < fPlaybackChannels; i++ ) | |||||
fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(); | fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(); | ||||
fAudioAdapter->SetRingBuffers(fCaptureRingBuffer, fPlaybackRingBuffer); | fAudioAdapter->SetRingBuffers(fCaptureRingBuffer, fPlaybackRingBuffer); | ||||
if ( fCaptureChannels ) | if ( fCaptureChannels ) | ||||
jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); | |||||
jack_log ( "ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace() ); | |||||
if ( fPlaybackChannels ) | if ( fPlaybackChannels ) | ||||
jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); | |||||
jack_log ( "WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace() ); | |||||
//jack ports | //jack ports | ||||
fCapturePortList = new jack_port_t* [fCaptureChannels]; | fCapturePortList = new jack_port_t* [fCaptureChannels]; | ||||
@@ -155,25 +155,25 @@ namespace Jack | |||||
for (i = 0; i < fCaptureChannels; i++) | for (i = 0; i < fCaptureChannels; i++) | ||||
{ | { | ||||
sprintf(name, "capture_%d", i+1); | 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; | goto fail; | ||||
} | } | ||||
for (i = 0; i < fPlaybackChannels; i++) | for (i = 0; i < fPlaybackChannels; i++) | ||||
{ | { | ||||
sprintf(name, "playback_%d", i+1); | 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; | goto fail; | ||||
} | } | ||||
//callbacks and activation | //callbacks and activation | ||||
if (jack_set_process_callback(fJackClient, Process, this) < 0) | |||||
if ( jack_set_process_callback ( fJackClient, Process, this ) < 0 ) | |||||
goto fail; | goto fail; | ||||
if (jack_set_buffer_size_callback(fJackClient, BufferSize, this) < 0) | |||||
if ( jack_set_buffer_size_callback ( fJackClient, BufferSize, this ) < 0 ) | |||||
goto fail; | goto fail; | ||||
if (jack_set_sample_rate_callback(fJackClient, SampleRate, this) < 0) | |||||
if ( jack_set_sample_rate_callback ( fJackClient, SampleRate, this ) < 0 ) | |||||
goto fail; | goto fail; | ||||
if (jack_activate(fJackClient) < 0) | |||||
if ( jack_activate ( fJackClient ) < 0 ) | |||||
goto fail; | goto fail; | ||||
//ringbuffers and jack clients are ok, we can now open the adapter driver interface | //ringbuffers and jack clients are ok, we can now open the adapter driver interface | ||||
@@ -25,120 +25,120 @@ namespace Jack | |||||
#ifdef JACK_MONITOR | #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 | #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 | } // namespace |
@@ -72,138 +72,142 @@ namespace Jack | |||||
class JackAudioAdapterInterface | class JackAudioAdapterInterface | ||||
{ | { | ||||
protected: | |||||
protected: | |||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
MeasureTable fTable; | |||||
MeasureTable fTable; | |||||
#endif | #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 ) | int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size ) | ||||
{ | { | ||||
JackAudioAdapterInterface::SetHostBufferSize ( buffer_size ); | |||||
JackAudioAdapterInterface::SetHostBufferSize ( buffer_size ); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -210,7 +210,8 @@ namespace Jack | |||||
} | } | ||||
//set audio adapter parameters | //set audio adapter parameters | ||||
JackAudioAdapterInterface::SetAdaptedBufferSize ( fParams.fPeriodSize ); | |||||
SetAdaptedBufferSize ( fParams.fPeriodSize ); | |||||
SetAdaptedSampleRate ( fParams.fSampleRate ); | |||||
//init done, display parameters | //init done, display parameters | ||||
SessionParamsDisplay ( &fParams ); | SessionParamsDisplay ( &fParams ); | ||||
@@ -278,14 +279,14 @@ namespace Jack | |||||
for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) | for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) | ||||
{ | { | ||||
fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 ); | 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; | failure = true; | ||||
} | } | ||||
//and output data, | //and output data, | ||||
for ( port_index = 0; port_index < fPlaybackChannels; port_index++ ) | for ( port_index = 0; port_index < fPlaybackChannels; port_index++ ) | ||||
{ | { | ||||
fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 ); | 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; | failure = true; | ||||
} | } | ||||
@@ -30,46 +30,50 @@ namespace Jack | |||||
JackAlsaAdapter::JackAlsaAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) | JackAlsaAdapter::JackAlsaAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) | ||||
:JackAudioAdapterInterface(buffer_size, sample_rate) | :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 JSList* node; | ||||
const jack_driver_param_t* param; | const jack_driver_param_t* param; | ||||
fCaptureChannels = 2; | fCaptureChannels = 2; | ||||
fPlaybackChannels = 2; | fPlaybackChannels = 2; | ||||
for (node = params; node; node = jack_slist_next(node)) { | for (node = params; node; node = jack_slist_next(node)) { | ||||
param = (const jack_driver_param_t*) node->data; | param = (const jack_driver_param_t*) node->data; | ||||
switch (param->character) { | switch (param->character) { | ||||
case 'i': | case 'i': | ||||
fCaptureChannels = param->value.ui; | fCaptureChannels = param->value.ui; | ||||
break; | break; | ||||
case 'o': | case 'o': | ||||
fPlaybackChannels = param->value.ui; | fPlaybackChannels = param->value.ui; | ||||
break; | break; | ||||
case 'C': | case 'C': | ||||
break; | break; | ||||
case 'P': | case 'P': | ||||
break; | break; | ||||
case 'D': | case 'D': | ||||
break; | break; | ||||
case 'n': | case 'n': | ||||
fAudioInterface.fPeriod = param->value.ui; | fAudioInterface.fPeriod = param->value.ui; | ||||
break; | break; | ||||
case 'd': | case 'd': | ||||
fAudioInterface.fCardName = strdup(param->value.str); | fAudioInterface.fCardName = strdup(param->value.str); | ||||
break; | break; | ||||
case 'r': | case 'r': | ||||
SetAudioSampleRate(param->value.ui); | |||||
SetAdaptedSampleRate(param->value.ui); | |||||
break; | |||||
case 'p': | |||||
SetAdaptedBufferSize(param->value.ui); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -77,14 +81,14 @@ namespace Jack | |||||
int JackAlsaAdapter::Open() | int JackAlsaAdapter::Open() | ||||
{ | { | ||||
if (fAudioInterface.open() != 0) | |||||
if (fAudioInterface.open() != 0) | |||||
return -1; | return -1; | ||||
if (fThread.StartSync() < 0) { | if (fThread.StartSync() < 0) { | ||||
jack_error("Cannot start audioadapter thread"); | jack_error("Cannot start audioadapter thread"); | ||||
return -1; | return -1; | ||||
} | } | ||||
fAudioInterface.longinfo(); | fAudioInterface.longinfo(); | ||||
fThread.AcquireRealTime(JackServer::fInstance->GetEngineControl()->fPriority); | fThread.AcquireRealTime(JackServer::fInstance->GetEngineControl()->fPriority); | ||||
return 0; | return 0; | ||||
@@ -96,7 +100,7 @@ int JackAlsaAdapter::Close() | |||||
fTable.Save(); | fTable.Save(); | ||||
#endif | #endif | ||||
switch (fThread.GetStatus()) { | switch (fThread.GetStatus()) { | ||||
// Kill the thread in Init phase | // Kill the thread in Init phase | ||||
case JackThread::kStarting: | case JackThread::kStarting: | ||||
case JackThread::kIniting: | case JackThread::kIniting: | ||||
@@ -105,15 +109,15 @@ int JackAlsaAdapter::Close() | |||||
return -1; | return -1; | ||||
} | } | ||||
break; | break; | ||||
// Stop when the thread cycle is finished | // Stop when the thread cycle is finished | ||||
case JackThread::kRunning: | case JackThread::kRunning: | ||||
if (fThread.Stop() < 0) { | if (fThread.Stop() < 0) { | ||||
jack_error("Cannot stop thread"); | |||||
jack_error("Cannot stop thread"); | |||||
return -1; | return -1; | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
@@ -126,25 +130,25 @@ bool JackAlsaAdapter::Init() | |||||
fAudioInterface.write(); | fAudioInterface.write(); | ||||
return true; | return true; | ||||
} | } | ||||
bool JackAlsaAdapter::Execute() | bool JackAlsaAdapter::Execute() | ||||
{ | { | ||||
if (fAudioInterface.read() < 0) | if (fAudioInterface.read() < 0) | ||||
return false; | return false; | ||||
bool failure = false; | bool failure = false; | ||||
jack_nframes_t time1, time2; | |||||
jack_nframes_t time1, time2; | |||||
ResampleFactor(time1, time2); | ResampleFactor(time1, time2); | ||||
for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
fCaptureRingBuffer[i]->SetRatio(time1, time2); | 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; | failure = true; | ||||
} | } | ||||
for (int i = 0; i < fPlaybackChannels; i++) { | for (int i = 0; i < fPlaybackChannels; i++) { | ||||
fPlaybackRingBuffer[i]->SetRatio(time2, time1); | 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; | failure = true; | ||||
} | } | ||||
@@ -152,10 +156,10 @@ bool JackAlsaAdapter::Execute() | |||||
fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1), | fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1), | ||||
fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace()); | fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace()); | ||||
#endif | #endif | ||||
if (fAudioInterface.write() < 0) | if (fAudioInterface.write() < 0) | ||||
return false; | return false; | ||||
// Reset all ringbuffers in case of failure | // Reset all ringbuffers in case of failure | ||||
if (failure) { | if (failure) { | ||||
jack_error("JackAlsaAdapter::Execute ringbuffer failure... reset"); | jack_error("JackAlsaAdapter::Execute ringbuffer failure... reset"); | ||||
@@ -164,13 +168,20 @@ bool JackAlsaAdapter::Execute() | |||||
return true; | 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) | int JackAlsaAdapter::SetBufferSize(jack_nframes_t buffer_size) | ||||
{ | { | ||||
JackAudioAdapterInterface::SetBufferSize(buffer_size); | |||||
JackAudioAdapterInterface::SetHostBufferSize(buffer_size); | |||||
Close(); | Close(); | ||||
return Open(); | return Open(); | ||||
} | } | ||||
} // namespace | } // namespace | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
@@ -183,12 +194,12 @@ extern "C" | |||||
jack_driver_desc_t *desc; | jack_driver_desc_t *desc; | ||||
jack_driver_param_desc_t * params; | jack_driver_param_desc_t * params; | ||||
unsigned int i; | unsigned int i; | ||||
desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); | desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); | ||||
strcpy (desc->name, "alsa-adapter"); | 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)); | params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); | ||||
i = 0; | i = 0; | ||||
strcpy(params[i].name, "capture"); | strcpy(params[i].name, "capture"); | ||||
params[i].character = 'C'; | params[i].character = 'C'; | ||||
@@ -214,7 +225,7 @@ extern "C" | |||||
strcpy(params[i].value.str, "hw:0"); | strcpy(params[i].value.str, "hw:0"); | ||||
strcpy(params[i].short_desc, "ALSA device name"); | strcpy(params[i].short_desc, "ALSA device name"); | ||||
strcpy(params[i].long_desc, params[i].short_desc); | strcpy(params[i].long_desc, params[i].short_desc); | ||||
i++; | i++; | ||||
strcpy (params[i].name, "rate"); | strcpy (params[i].name, "rate"); | ||||
params[i].character = 'r'; | params[i].character = 'r'; | ||||
@@ -223,6 +234,14 @@ extern "C" | |||||
strcpy(params[i].short_desc, "Sample rate"); | strcpy(params[i].short_desc, "Sample rate"); | ||||
strcpy(params[i].long_desc, params[i].short_desc); | 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++; | i++; | ||||
strcpy(params[i].name, "nperiods"); | strcpy(params[i].name, "nperiods"); | ||||
params[i].character = 'n'; | params[i].character = 'n'; | ||||
@@ -261,7 +280,7 @@ extern "C" | |||||
desc->params = params; | desc->params = params; | ||||
return desc; | return desc; | ||||
} | } | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif | ||||
@@ -49,32 +49,32 @@ class AudioParam | |||||
{ | { | ||||
public: | public: | ||||
const char* fCardName; | |||||
const char* fCardName; | |||||
unsigned int fFrequency; | unsigned int fFrequency; | ||||
int fBuffering; | |||||
int fBuffering; | |||||
unsigned int fSoftInputs; | unsigned int fSoftInputs; | ||||
unsigned int fSoftOutputs; | unsigned int fSoftOutputs; | ||||
public: | public: | ||||
AudioParam() : | |||||
AudioParam() : | |||||
fCardName("hw:0"), | fCardName("hw:0"), | ||||
fFrequency(44100), | fFrequency(44100), | ||||
fBuffering(512), | fBuffering(512), | ||||
fSoftInputs(2), | fSoftInputs(2), | ||||
fSoftOutputs(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"), | fCardName("hw:0"), | ||||
fFrequency(sample_rate), | fFrequency(sample_rate), | ||||
fBuffering(buffer_size), | fBuffering(buffer_size), | ||||
fSoftInputs(input), | fSoftInputs(input), | ||||
fSoftOutputs(output) | fSoftOutputs(output) | ||||
{} | {} | ||||
AudioParam& cardName(const char* n) { fCardName = n; return *this; } | AudioParam& cardName(const char* n) { fCardName = n; return *this; } | ||||
AudioParam& frequency(int f) { fFrequency = f; return *this; } | AudioParam& frequency(int f) { fFrequency = f; return *this; } | ||||
AudioParam& buffering(int fpb) { fBuffering = fpb; return *this; } | AudioParam& buffering(int fpb) { fBuffering = fpb; return *this; } | ||||
@@ -89,44 +89,44 @@ class AudioInterface : public AudioParam | |||||
{ | { | ||||
public: | 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* fInputParams; | ||||
snd_pcm_hw_params_t* fOutputParams; | snd_pcm_hw_params_t* fOutputParams; | ||||
snd_pcm_format_t fSampleFormat; | snd_pcm_format_t fSampleFormat; | ||||
snd_pcm_access_t fSampleAccess; | snd_pcm_access_t fSampleAccess; | ||||
unsigned int fCardInputs; | unsigned int fCardInputs; | ||||
unsigned int fCardOutputs; | unsigned int fCardOutputs; | ||||
unsigned int fChanInputs; | unsigned int fChanInputs; | ||||
unsigned int fChanOutputs; | unsigned int fChanOutputs; | ||||
unsigned int fPeriod; | unsigned int fPeriod; | ||||
// interleaved mode audiocard buffers | // interleaved mode audiocard buffers | ||||
void* fInputCardBuffer; | void* fInputCardBuffer; | ||||
void* fOutputCardBuffer; | void* fOutputCardBuffer; | ||||
// non interleaved mode audiocard buffers | // non interleaved mode audiocard buffers | ||||
void* fInputCardChannels[256]; | void* fInputCardChannels[256]; | ||||
void* fOutputCardChannels[256]; | void* fOutputCardChannels[256]; | ||||
// non interleaved mod, floating point software buffers | // non interleaved mod, floating point software buffers | ||||
float* fInputSoftChannels[256]; | float* fInputSoftChannels[256]; | ||||
float* fOutputSoftChannels[256]; | float* fOutputSoftChannels[256]; | ||||
public: | public: | ||||
const char* cardName() { return fCardName; } | const char* cardName() { return fCardName; } | ||||
int frequency() { return fFrequency; } | int frequency() { return fFrequency; } | ||||
int buffering() { return fBuffering; } | int buffering() { return fBuffering; } | ||||
float** inputSoftChannels() { return fInputSoftChannels; } | float** inputSoftChannels() { return fInputSoftChannels; } | ||||
float** outputSoftChannels() { return fOutputSoftChannels; } | float** outputSoftChannels() { return fOutputSoftChannels; } | ||||
AudioInterface(const AudioParam& ap = AudioParam()) : AudioParam(ap) | AudioInterface(const AudioParam& ap = AudioParam()) : AudioParam(ap) | ||||
{ | { | ||||
fInputDevice = 0; | fInputDevice = 0; | ||||
@@ -136,7 +136,7 @@ class AudioInterface : public AudioParam | |||||
fPeriod = 2; | 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) | AudioParam(input, output, buffer_size, sample_rate) | ||||
{ | { | ||||
fInputCardBuffer = 0; | fInputCardBuffer = 0; | ||||
@@ -149,7 +149,7 @@ class AudioInterface : public AudioParam | |||||
fOutputSoftChannels[i] = 0; | fOutputSoftChannels[i] = 0; | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Open the audio interface | * Open the audio interface | ||||
*/ | */ | ||||
@@ -188,7 +188,7 @@ class AudioInterface : public AudioParam | |||||
fOutputCardChannels[i] = aligned_calloc(noninterleavedBufferSize(fOutputParams), 1); | fOutputCardChannels[i] = aligned_calloc(noninterleavedBufferSize(fOutputParams), 1); | ||||
} | } | ||||
} | } | ||||
// allocation of floating point buffers needed by the dsp code | // allocation of floating point buffers needed by the dsp code | ||||
fChanInputs = max(fSoftInputs, fCardInputs); assert (fChanInputs < 256); | fChanInputs = max(fSoftInputs, fCardInputs); assert (fChanInputs < 256); | ||||
fChanOutputs = max(fSoftOutputs, fCardOutputs); assert (fChanOutputs < 256); | fChanOutputs = max(fSoftOutputs, fCardOutputs); assert (fChanOutputs < 256); | ||||
@@ -208,7 +208,7 @@ class AudioInterface : public AudioParam | |||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
int close() | int close() | ||||
{ | { | ||||
snd_pcm_hw_params_free(fInputParams); | snd_pcm_hw_params_free(fInputParams); | ||||
@@ -240,26 +240,26 @@ class AudioInterface : public AudioParam | |||||
free(fInputCardBuffer); | free(fInputCardBuffer); | ||||
if (fOutputCardBuffer) | if (fOutputCardBuffer) | ||||
free(fOutputCardBuffer); | free(fOutputCardBuffer); | ||||
return 0; | return 0; | ||||
} | } | ||||
int setAudioParams(snd_pcm_t* stream, snd_pcm_hw_params_t* params) | int setAudioParams(snd_pcm_t* stream, snd_pcm_hw_params_t* params) | ||||
{ | |||||
{ | |||||
int err; | int err; | ||||
// set params record with initial values | // 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") | check_error_msg(err, "unable to init parameters") | ||||
// set alsa access mode (and fSampleAccess field) either to non interleaved or interleaved | // 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 ); | err = snd_pcm_hw_params_set_access (stream, params, SND_PCM_ACCESS_RW_NONINTERLEAVED ); | ||||
if (err) { | if (err) { | ||||
err = snd_pcm_hw_params_set_access (stream, params, SND_PCM_ACCESS_RW_INTERLEAVED ); | 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"); | 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 | // search for 32-bits or 16-bits format | ||||
err = snd_pcm_hw_params_set_format (stream, params, SND_PCM_FORMAT_S32); | 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); | snd_pcm_hw_params_get_format(params, &fSampleFormat); | ||||
// set sample frequency | // 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) | // 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"); | 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"); | check_error_msg(err, "number of periods not available"); | ||||
return 0; | 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 | * care of interleaved buffers | ||||
*/ | */ | ||||
int read() | int read() | ||||
{ | { | ||||
if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) { | 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"); | 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"); | check_error_msg(err, "preparing input stream"); | ||||
} | } | ||||
if (fSampleFormat == SND_PCM_FORMAT_S16) { | if (fSampleFormat == SND_PCM_FORMAT_S16) { | ||||
short* buffer16b = (short*) fInputCardBuffer; | short* buffer16b = (short*) fInputCardBuffer; | ||||
@@ -330,16 +330,16 @@ class AudioInterface : public AudioParam | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) { | } 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"); | 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"); | check_error_msg(err, "preparing input stream"); | ||||
} | } | ||||
if (fSampleFormat == SND_PCM_FORMAT_S16) { | if (fSampleFormat == SND_PCM_FORMAT_S16) { | ||||
for (unsigned int c = 0; c < fCardInputs; c++) { | for (unsigned int c = 0; c < fCardInputs; c++) { | ||||
@@ -358,7 +358,7 @@ class AudioInterface : public AudioParam | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
check_error_msg(-10000, "unknow access mode"); | 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 | * format and interleaves buffers when needed | ||||
*/ | */ | ||||
int write() | int write() | ||||
{ | { | ||||
recovery: | recovery: | ||||
if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) { | if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) { | ||||
if (fSampleFormat == SND_PCM_FORMAT_S16) { | if (fSampleFormat == SND_PCM_FORMAT_S16) { | ||||
short* buffer16b = (short*) fOutputCardBuffer; | 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"); | check_error_msg(err, "preparing output stream"); | ||||
goto recovery; | goto recovery; | ||||
} | } | ||||
} else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) { | } else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) { | ||||
if (fSampleFormat == SND_PCM_FORMAT_S16) { | if (fSampleFormat == SND_PCM_FORMAT_S16) { | ||||
for (unsigned int c = 0; c < fCardOutputs; c++) { | 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"); | check_error_msg(err, "preparing output stream"); | ||||
goto recovery; | goto recovery; | ||||
} | } | ||||
} else { | } else { | ||||
check_error_msg(-10000, "unknow access mode"); | check_error_msg(-10000, "unknow access mode"); | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
/** | /** | ||||
* print short information on the audio device | * 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); | err = snd_ctl_open(&ctl_handle, fCardName, 0); check_error(err); | ||||
snd_ctl_card_info_alloca(&card_info); | snd_ctl_card_info_alloca(&card_info); | ||||
err = snd_ctl_card_info(ctl_handle, card_info); check_error(err); | 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), | snd_ctl_card_info_get_driver(card_info), | ||||
fCardInputs, fCardOutputs, | fCardInputs, fCardOutputs, | ||||
fFrequency, fBuffering, | fFrequency, fBuffering, | ||||
snd_pcm_format_name((_snd_pcm_format)fSampleFormat)); | snd_pcm_format_name((_snd_pcm_format)fSampleFormat)); | ||||
} | } | ||||
/** | /** | ||||
* print more detailled information on the audio device | * print more detailled information on the audio device | ||||
*/ | */ | ||||
@@ -472,12 +472,12 @@ class AudioInterface : public AudioParam | |||||
snd_ctl_t* ctl_handle; | snd_ctl_t* ctl_handle; | ||||
jack_info("Audio Interface Description :"); | 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); | fFrequency, snd_pcm_format_name((_snd_pcm_format)fSampleFormat), fBuffering, fPeriod); | ||||
jack_info("Software inputs : %2d, Software outputs : %2d", fSoftInputs, fSoftOutputs); | jack_info("Software inputs : %2d, Software outputs : %2d", fSoftInputs, fSoftOutputs); | ||||
jack_info("Hardware inputs : %2d, Hardware outputs : %2d", fCardInputs, fCardOutputs); | jack_info("Hardware inputs : %2d, Hardware outputs : %2d", fCardInputs, fCardOutputs); | ||||
jack_info("Channel inputs : %2d, Channel outputs : %2d", fChanInputs, fChanOutputs); | jack_info("Channel inputs : %2d, Channel outputs : %2d", fChanInputs, fChanOutputs); | ||||
// affichage des infos de la carte | // affichage des infos de la carte | ||||
err = snd_ctl_open (&ctl_handle, fCardName, 0); check_error(err); | err = snd_ctl_open (&ctl_handle, fCardName, 0); check_error(err); | ||||
snd_ctl_card_info_alloca (&card_info); | snd_ctl_card_info_alloca (&card_info); | ||||
@@ -489,7 +489,7 @@ class AudioInterface : public AudioParam | |||||
if (fSoftOutputs > 0) printHWParams(fOutputParams); | if (fSoftOutputs > 0) printHWParams(fOutputParams); | ||||
return 0; | return 0; | ||||
} | } | ||||
void printCardInfo(snd_ctl_card_info_t* ci) | void printCardInfo(snd_ctl_card_info_t* ci) | ||||
{ | { | ||||
jack_info("Card info (address : %p)", ci); | jack_info("Card info (address : %p)", ci); | ||||
@@ -528,24 +528,25 @@ class JackAlsaAdapter : public JackAudioAdapterInterface, public JackRunnableInt | |||||
{ | { | ||||
private: | private: | ||||
JackThread fThread; | JackThread fThread; | ||||
AudioInterface fAudioInterface; | AudioInterface fAudioInterface; | ||||
public: | public: | ||||
JackAlsaAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); | JackAlsaAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); | ||||
~JackAlsaAdapter() | ~JackAlsaAdapter() | ||||
{} | {} | ||||
virtual int Open(); | virtual int Open(); | ||||
virtual int Close(); | virtual int Close(); | ||||
virtual int SetSampleRate(jack_nframes_t sample_rate); | |||||
virtual int SetBufferSize(jack_nframes_t buffer_size); | virtual int SetBufferSize(jack_nframes_t buffer_size); | ||||
virtual bool Init(); | virtual bool Init(); | ||||
virtual bool Execute(); | virtual bool Execute(); | ||||
}; | }; | ||||
} | } | ||||
@@ -116,7 +116,7 @@ OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice, | |||||
return noErr; | return noErr; | ||||
} | } | ||||
OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | ||||
AudioUnitRenderActionFlags *ioActionFlags, | AudioUnitRenderActionFlags *ioActionFlags, | ||||
const AudioTimeStamp *inTimeStamp, | const AudioTimeStamp *inTimeStamp, | ||||
@@ -127,27 +127,27 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | |||||
JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon); | JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon); | ||||
AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); | AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); | ||||
bool failure = false; | bool failure = false; | ||||
jack_nframes_t time1, time2; | |||||
jack_nframes_t time1, time2; | |||||
adapter->ResampleFactor(time1, time2); | adapter->ResampleFactor(time1, time2); | ||||
for (int i = 0; i < adapter->fCaptureChannels; i++) { | for (int i = 0; i < adapter->fCaptureChannels; i++) { | ||||
adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2); | adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2); | ||||
if (adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames) < inNumberFrames) | if (adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames) < inNumberFrames) | ||||
failure = true; | failure = true; | ||||
} | } | ||||
for (int i = 0; i < adapter->fPlaybackChannels; i++) { | for (int i = 0; i < adapter->fPlaybackChannels; i++) { | ||||
adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1); | adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1); | ||||
if (adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames) < inNumberFrames) | if (adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames) < inNumberFrames) | ||||
failure = true; | 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()); | adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace()); | ||||
#endif | #endif | ||||
// Reset all ringbuffers in case of failure | // Reset all ringbuffers in case of failure | ||||
if (failure) { | if (failure) { | ||||
jack_error("JackCoreAudioAdapter::Render ringbuffer failure... reset"); | jack_error("JackCoreAudioAdapter::Render ringbuffer failure... reset"); | ||||
@@ -162,39 +162,42 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | |||||
const JSList* node; | const JSList* node; | ||||
const jack_driver_param_t* param; | const jack_driver_param_t* param; | ||||
fCaptureChannels = 2; | fCaptureChannels = 2; | ||||
fPlaybackChannels = 2; | fPlaybackChannels = 2; | ||||
for (node = params; node; node = jack_slist_next(node)) { | for (node = params; node; node = jack_slist_next(node)) { | ||||
param = (const jack_driver_param_t*) node->data; | param = (const jack_driver_param_t*) node->data; | ||||
switch (param->character) { | switch (param->character) { | ||||
case 'c' : | case 'c' : | ||||
break; | break; | ||||
case 'i': | case 'i': | ||||
fCaptureChannels = param->value.ui; | fCaptureChannels = param->value.ui; | ||||
break; | break; | ||||
case 'o': | case 'o': | ||||
fPlaybackChannels = param->value.ui; | fPlaybackChannels = param->value.ui; | ||||
break; | break; | ||||
case 'C': | case 'C': | ||||
break; | break; | ||||
case 'P': | case 'P': | ||||
break; | break; | ||||
case 'D': | case 'D': | ||||
break; | break; | ||||
case 'r': | case 'r': | ||||
SetAudioSampleRate(param->value.ui); | |||||
SetAdaptedSampleRate(param->value.ui); | |||||
break; | |||||
case 'p': | |||||
SetAdaptedBufferSize(param->value.ui); | |||||
break; | break; | ||||
case 'l': | case 'l': | ||||
break; | break; | ||||
} | } | ||||
@@ -260,7 +263,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||||
jack_error("Cannot open default device"); | jack_error("Cannot open default device"); | ||||
return -1; | return -1; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -273,21 +276,21 @@ int JackCoreAudioAdapter::SetupChannels(bool capturing, | |||||
bool strict) | bool strict) | ||||
{ | { | ||||
OSStatus err = noErr; | OSStatus err = noErr; | ||||
err = GetTotalChannels(fDeviceID, &in_nChannels, true); | err = GetTotalChannels(fDeviceID, &in_nChannels, true); | ||||
if (err != noErr) { | if (err != noErr) { | ||||
jack_error("Cannot get input channel number"); | jack_error("Cannot get input channel number"); | ||||
printError(err); | printError(err); | ||||
return -1; | return -1; | ||||
} | } | ||||
err = GetTotalChannels(fDeviceID, &out_nChannels, false); | err = GetTotalChannels(fDeviceID, &out_nChannels, false); | ||||
if (err != noErr) { | if (err != noErr) { | ||||
jack_error("Cannot get output channel number"); | jack_error("Cannot get output channel number"); | ||||
printError(err); | printError(err); | ||||
return -1; | return -1; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -350,7 +353,7 @@ int JackCoreAudioAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, j | |||||
int JackCoreAudioAdapter::SetupBuffers(int inchannels, int outchannels) | int JackCoreAudioAdapter::SetupBuffers(int inchannels, int outchannels) | ||||
{ | { | ||||
jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld output = %ld", inchannels, outchannels); | jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld output = %ld", inchannels, outchannels); | ||||
// Prepare buffers | // Prepare buffers | ||||
fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer)); | fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer)); | ||||
if (fInputData == 0) { | if (fInputData == 0) { | ||||
@@ -369,7 +372,7 @@ int JackCoreAudioAdapter::SetupBuffers(int inchannels, int outchannels) | |||||
void JackCoreAudioAdapter::DisposeBuffers() | void JackCoreAudioAdapter::DisposeBuffers() | ||||
{ | { | ||||
if (fInputData) { | if (fInputData) { | ||||
for (int i = 0; i < fCaptureChannels; i++) | |||||
for (int i = 0; i < fCaptureChannels; i++) | |||||
free(fInputData->mBuffers[i].mData); | free(fInputData->mBuffers[i].mData); | ||||
free(fInputData); | free(fInputData); | ||||
fInputData = 0; | fInputData = 0; | ||||
@@ -559,13 +562,13 @@ void JackCoreAudioAdapter::CloseAUHAL() | |||||
AudioUnitUninitialize(fAUHAL); | AudioUnitUninitialize(fAUHAL); | ||||
CloseComponent(fAUHAL); | CloseComponent(fAUHAL); | ||||
} | } | ||||
int JackCoreAudioAdapter::Open() | int JackCoreAudioAdapter::Open() | ||||
{ | { | ||||
OSStatus err; | OSStatus err; | ||||
int in_nChannels = 0; | int in_nChannels = 0; | ||||
int out_nChannels = 0; | int out_nChannels = 0; | ||||
if (SetupDevices("", "", "", "") < 0) | if (SetupDevices("", "", "", "") < 0) | ||||
return -1; | return -1; | ||||
@@ -580,11 +583,11 @@ int JackCoreAudioAdapter::Open() | |||||
if (SetupBuffers(fCaptureChannels, fPlaybackChannels) < 0) | if (SetupBuffers(fCaptureChannels, fPlaybackChannels) < 0) | ||||
goto error; | goto error; | ||||
err = AudioOutputUnitStart(fAUHAL); | err = AudioOutputUnitStart(fAUHAL); | ||||
if (err != noErr) | if (err != noErr) | ||||
goto error; | goto error; | ||||
return 0; | return 0; | ||||
error: | error: | ||||
@@ -594,7 +597,7 @@ error: | |||||
int JackCoreAudioAdapter::Close() | int JackCoreAudioAdapter::Close() | ||||
{ | { | ||||
#ifdef JACK_MONITOR | |||||
#ifdef JACK_MONITOR | |||||
fTable.Save(); | fTable.Save(); | ||||
#endif | #endif | ||||
AudioOutputUnitStop(fAUHAL); | AudioOutputUnitStop(fAUHAL); | ||||
@@ -603,9 +606,15 @@ int JackCoreAudioAdapter::Close() | |||||
return 0; | 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(); | Close(); | ||||
return Open(); | return Open(); | ||||
} | } | ||||
@@ -617,14 +626,14 @@ extern "C" | |||||
{ | { | ||||
#endif | #endif | ||||
EXPORT jack_driver_desc_t* jack_get_descriptor() | |||||
EXPORT jack_driver_desc_t* jack_get_descriptor() | |||||
{ | { | ||||
jack_driver_desc_t *desc; | jack_driver_desc_t *desc; | ||||
unsigned int i; | unsigned int i; | ||||
desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); | desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); | ||||
strcpy(desc->name, "coreaudio-adapter"); | 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)); | desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); | ||||
i = 0; | i = 0; | ||||
@@ -666,7 +675,7 @@ extern "C" | |||||
strcpy(desc->params[i].value.str, "will take default CoreAudio output device"); | 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].short_desc, "Provide playback ports. Optionally set CoreAudio device name"); | ||||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | ||||
i++; | i++; | ||||
strcpy(desc->params[i].name, "rate"); | strcpy(desc->params[i].name, "rate"); | ||||
desc->params[i].character = 'r'; | desc->params[i].character = 'r'; | ||||
@@ -675,6 +684,14 @@ extern "C" | |||||
strcpy(desc->params[i].short_desc, "Sample rate"); | strcpy(desc->params[i].short_desc, "Sample rate"); | ||||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | 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++; | i++; | ||||
strcpy(desc->params[i].name, "duplex"); | strcpy(desc->params[i].name, "duplex"); | ||||
desc->params[i].character = 'D'; | desc->params[i].character = 'D'; | ||||
@@ -698,11 +715,11 @@ extern "C" | |||||
desc->params[i].value.i = TRUE; | desc->params[i].value.i = TRUE; | ||||
strcpy(desc->params[i].short_desc, "Display available CoreAudio devices"); | strcpy(desc->params[i].short_desc, "Display available CoreAudio devices"); | ||||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | ||||
return desc; | return desc; | ||||
} | } | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif | ||||
@@ -44,23 +44,23 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface | |||||
{ | { | ||||
private: | private: | ||||
AudioUnit fAUHAL; | AudioUnit fAUHAL; | ||||
AudioBufferList* fInputData; | AudioBufferList* fInputData; | ||||
AudioDeviceID fDeviceID; | AudioDeviceID fDeviceID; | ||||
bool fState; | bool fState; | ||||
AudioUnitRenderActionFlags* fActionFags; | AudioUnitRenderActionFlags* fActionFags; | ||||
AudioTimeStamp* fCurrentTime; | AudioTimeStamp* fCurrentTime; | ||||
static OSStatus Render(void *inRefCon, | static OSStatus Render(void *inRefCon, | ||||
AudioUnitRenderActionFlags *ioActionFlags, | AudioUnitRenderActionFlags *ioActionFlags, | ||||
const AudioTimeStamp *inTimeStamp, | const AudioTimeStamp *inTimeStamp, | ||||
UInt32 inBusNumber, | UInt32 inBusNumber, | ||||
UInt32 inNumberFrames, | UInt32 inNumberFrames, | ||||
AudioBufferList *ioData); | AudioBufferList *ioData); | ||||
static OSStatus SRNotificationCallback(AudioDeviceID inDevice, | static OSStatus SRNotificationCallback(AudioDeviceID inDevice, | ||||
UInt32 inChannel, | UInt32 inChannel, | ||||
Boolean isInput, | Boolean isInput, | ||||
@@ -83,7 +83,7 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface | |||||
int& in_nChannels, | int& in_nChannels, | ||||
int& out_nChannels, | int& out_nChannels, | ||||
bool strict); | bool strict); | ||||
int OpenAUHAL(bool capturing, | int OpenAUHAL(bool capturing, | ||||
bool playing, | bool playing, | ||||
int inchannels, | int inchannels, | ||||
@@ -100,16 +100,17 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface | |||||
void CloseAUHAL(); | void CloseAUHAL(); | ||||
public: | public: | ||||
JackCoreAudioAdapter( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); | JackCoreAudioAdapter( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); | ||||
~JackCoreAudioAdapter() | ~JackCoreAudioAdapter() | ||||
{} | {} | ||||
virtual int Open(); | virtual int Open(); | ||||
virtual int Close(); | virtual int Close(); | ||||
virtual int SetSampleRate(jack_nframes_t sample_rate); | |||||
virtual int SetBufferSize(jack_nframes_t buffer_size); | virtual int SetBufferSize(jack_nframes_t buffer_size); | ||||
}; | }; | ||||
} | } | ||||
@@ -27,196 +27,206 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
namespace Jack | 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 | #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 | #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; | fCaptureChannels = param->value.ui; | ||||
break; | break; | ||||
case 'o': | |||||
case 'o' : | |||||
fPlaybackChannels = param->value.ui; | fPlaybackChannels = param->value.ui; | ||||
break; | 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; | 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; | break; | ||||
case 'r': | |||||
SetAudioSampleRate(param->value.ui); | |||||
case 'r' : | |||||
SetAdaptedSampleRate ( param->value.ui ); | |||||
break; | 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; | 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; | 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 | #ifdef JACK_MONITOR | ||||
fTable.Save(); | |||||
fTable.Save(); | |||||
#endif | #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 | } // namespace | ||||
@@ -232,7 +242,7 @@ extern "C" | |||||
desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); | desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); | ||||
strcpy(desc->name, "portaudio-adapter"); | 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)); | desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); | ||||
i = 0; | i = 0; | ||||
@@ -275,6 +285,14 @@ extern "C" | |||||
strcpy(desc->params[i].short_desc, "Sample rate"); | strcpy(desc->params[i].short_desc, "Sample rate"); | ||||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | 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++; | i++; | ||||
strcpy(desc->params[i].name, "device"); | strcpy(desc->params[i].name, "device"); | ||||
desc->params[i].character = 'd'; | desc->params[i].character = 'd'; | ||||
@@ -27,12 +27,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
/*! | |||||
\brief Audio adapter using PortAudio API. | |||||
*/ | |||||
/*! | |||||
\brief Audio adapter using PortAudio API. | |||||
*/ | |||||
class JackPortAudioAdapter : public JackAudioAdapterInterface | |||||
{ | |||||
class JackPortAudioAdapter : public JackAudioAdapterInterface | |||||
{ | |||||
private: | private: | ||||
@@ -41,24 +41,25 @@ class JackPortAudioAdapter : public JackAudioAdapterInterface | |||||
PaDeviceIndex fInputDevice; | PaDeviceIndex fInputDevice; | ||||
PaDeviceIndex fOutputDevice; | 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: | 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() | ~JackPortAudioAdapter() | ||||
{} | {} | ||||
int Open(); | int Open(); | ||||
int Close(); | 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 "JackExports.h" | ||||
#include "driver_interface.h" | #include "driver_interface.h" | ||||
EXPORT jack_driver_desc_t* jack_get_descriptor(); | |||||
EXPORT jack_driver_desc_t* jack_get_descriptor(); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||