00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #if defined(HAVE_CONFIG_H)
00021 #include "config.h"
00022 #endif
00023
00024 #include "JackPortAudioAdapter.h"
00025 #include "JackError.h"
00026
00027 namespace Jack
00028 {
00029
00030 int JackPortAudioAdapter::Render ( const void* inputBuffer,
00031 void* outputBuffer,
00032 unsigned long framesPerBuffer,
00033 const PaStreamCallbackTimeInfo* timeInfo,
00034 PaStreamCallbackFlags statusFlags,
00035 void* userData)
00036 {
00037 JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData);
00038 float** paBuffer;
00039 bool failure = false;
00040
00041 jack_nframes_t time1, time2;
00042 adapter->ResampleFactor ( time1, time2 );
00043
00044 paBuffer = (float**)inputBuffer;
00045 for ( int i = 0; i < adapter->fCaptureChannels; i++ )
00046 {
00047 adapter->fCaptureRingBuffer[i]->SetRatio ( time1, time2 );
00048 if (adapter->fCaptureRingBuffer[i]->WriteResample ( (float*)paBuffer[i], framesPerBuffer ) < framesPerBuffer )
00049 failure = true;
00050 }
00051
00052 paBuffer = (float**)outputBuffer;
00053 for ( int i = 0; i < adapter->fPlaybackChannels; i++ )
00054 {
00055 adapter->fPlaybackRingBuffer[i]->SetRatio ( time2, time1 );
00056 if ( adapter->fPlaybackRingBuffer[i]->ReadResample ( (float*)paBuffer[i], framesPerBuffer ) < framesPerBuffer )
00057 failure = true;
00058 }
00059
00060 #ifdef JACK_MONITOR
00061 adapter->fTable.Write ( time1, time2, double(time1) / double(time2), double(time2) / double(time1),
00062 adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace() );
00063 #endif
00064
00065
00066 if ( failure )
00067 {
00068 jack_error ( "JackPortAudioAdapter::Render ringbuffer failure... reset" );
00069 adapter->ResetRingBuffers();
00070 }
00071 return paContinue;
00072 }
00073
00074 JackPortAudioAdapter::JackPortAudioAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
00075 : JackAudioAdapterInterface ( buffer_size, sample_rate )
00076 {
00077 jack_log ( "JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate );
00078
00079 const JSList* node;
00080 const jack_driver_param_t* param;
00081 int in_max = 0;
00082 int out_max = 0;
00083
00084 fInputDevice = Pa_GetDefaultInputDevice();
00085 fOutputDevice = Pa_GetDefaultOutputDevice();
00086
00087 for (node = params; node; node = jack_slist_next(node))
00088 {
00089 param = (const jack_driver_param_t*) node->data;
00090
00091 switch (param->character)
00092 {
00093 case 'i' :
00094 fCaptureChannels = param->value.ui;
00095 break;
00096 case 'o' :
00097 fPlaybackChannels = param->value.ui;
00098 break;
00099 case 'C' :
00100 if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 )
00101 {
00102 jack_error ( "Can't use %s, taking default input device", param->value.str );
00103 fInputDevice = Pa_GetDefaultInputDevice();
00104 }
00105 break;
00106 case 'P' :
00107 if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 )
00108 {
00109 jack_error ( "Can't use %s, taking default output device", param->value.str );
00110 fOutputDevice = Pa_GetDefaultOutputDevice();
00111 }
00112 break;
00113 case 'r' :
00114 SetAdaptedSampleRate ( param->value.ui );
00115 break;
00116 case 'p' :
00117 SetAdaptedBufferSize ( param->value.ui );
00118 break;
00119 case 'd' :
00120 if ( fPaDevices.GetInputDeviceFromName ( param->value.str, fInputDevice, in_max ) < 0 )
00121 jack_error ( "Can't use %s, taking default input device", param->value.str );
00122 if ( fPaDevices.GetOutputDeviceFromName ( param->value.str, fOutputDevice, out_max ) < 0 )
00123 jack_error ( "Can't use %s, taking default output device", param->value.str );
00124 break;
00125 case 'l' :
00126 fPaDevices.DisplayDevicesNames();
00127 break;
00128 case 'q':
00129 fQuality = param->value.ui;
00130 break;
00131 }
00132 }
00133
00134
00135 if ( in_max == 0 )
00136 in_max = fPaDevices.GetDeviceInfo ( fInputDevice )->maxInputChannels;
00137 if ( out_max == 0 )
00138 out_max = fPaDevices.GetDeviceInfo ( fOutputDevice )->maxOutputChannels;
00139
00140
00141 if ( ( fCaptureChannels == 0 ) || ( fCaptureChannels > in_max ) )
00142 fCaptureChannels = in_max;
00143 if ( ( fPlaybackChannels == 0 ) || ( fPlaybackChannels > out_max ) )
00144 fPlaybackChannels = out_max;
00145
00146
00147 SetInputs ( fCaptureChannels );
00148 SetOutputs ( fPlaybackChannels );
00149 }
00150
00151 int JackPortAudioAdapter::Open()
00152 {
00153 PaError err;
00154 PaStreamParameters inputParameters;
00155 PaStreamParameters outputParameters;
00156
00157 if ( JackAudioAdapterInterface::Open() < 0 )
00158 return -1;
00159
00160 jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str());
00161 jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str());
00162 jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate);
00163
00164 inputParameters.device = fInputDevice;
00165 inputParameters.channelCount = fCaptureChannels;
00166 inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00167 inputParameters.suggestedLatency = ( fInputDevice != paNoDevice )
00168 ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency
00169 : 0;
00170 inputParameters.hostApiSpecificStreamInfo = NULL;
00171
00172 outputParameters.device = fOutputDevice;
00173 outputParameters.channelCount = fPlaybackChannels;
00174 outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00175 outputParameters.suggestedLatency = ( fOutputDevice != paNoDevice )
00176 ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
00177 : 0;
00178 outputParameters.hostApiSpecificStreamInfo = NULL;
00179
00180 err = Pa_OpenStream( &fStream,
00181 ( fInputDevice == paNoDevice ) ? 0 : &inputParameters,
00182 ( fOutputDevice == paNoDevice ) ? 0 : &outputParameters,
00183 fAdaptedSampleRate,
00184 fAdaptedBufferSize,
00185 paNoFlag,
00186 Render,
00187 this );
00188
00189 if ( err != paNoError )
00190 {
00191 jack_error ( "Pa_OpenStream error = %s", Pa_GetErrorText ( err ) );
00192 return -1;
00193 }
00194
00195 err = Pa_StartStream ( fStream );
00196
00197 if ( err != paNoError )
00198 {
00199 jack_error ( "Pa_StartStream error = %s", Pa_GetErrorText ( err ) );
00200 return -1;
00201 }
00202
00203 jack_log ( "JackPortAudioAdapter::Open OK" );
00204 return 0;
00205 }
00206
00207 int JackPortAudioAdapter::Close()
00208 {
00209 #ifdef JACK_MONITOR
00210 fTable.Save();
00211 #endif
00212 jack_log ( "JackPortAudioAdapter::Close" );
00213 Pa_StopStream ( fStream );
00214 jack_log ( "JackPortAudioAdapter:: Pa_StopStream" );
00215 Pa_CloseStream ( fStream );
00216 jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" );
00217 return JackAudioAdapterInterface::Close();
00218 }
00219
00220 int JackPortAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate )
00221 {
00222 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
00223 Close();
00224 return Open();
00225 }
00226
00227 int JackPortAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size )
00228 {
00229 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
00230 Close();
00231 return Open();
00232 }
00233
00234 }
00235
00236 #ifdef __cplusplus
00237 extern "C"
00238 {
00239 #endif
00240
00241 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00242 {
00243 jack_driver_desc_t *desc;
00244 unsigned int i;
00245 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00246
00247 strcpy(desc->name, "audioadapter");
00248 strcpy(desc->desc, "netjack audio <==> net backend adapter");
00249
00250 desc->nparams = 9;
00251 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
00252
00253 i = 0;
00254 strcpy(desc->params[i].name, "inchannels");
00255 desc->params[i].character = 'i';
00256 desc->params[i].type = JackDriverParamInt;
00257 desc->params[i].value.ui = 0;
00258 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
00259 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00260
00261 i++;
00262 strcpy(desc->params[i].name, "outchannels");
00263 desc->params[i].character = 'o';
00264 desc->params[i].type = JackDriverParamInt;
00265 desc->params[i].value.ui = 0;
00266 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
00267 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00268
00269 i++;
00270 strcpy(desc->params[i].name, "capture");
00271 desc->params[i].character = 'C';
00272 desc->params[i].type = JackDriverParamString;
00273 strcpy(desc->params[i].value.str, "default input device");
00274 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
00275 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00276
00277 i++;
00278 strcpy(desc->params[i].name, "playback");
00279 desc->params[i].character = 'P';
00280 desc->params[i].type = JackDriverParamString;
00281 strcpy(desc->params[i].value.str, "default output device");
00282 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
00283 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00284
00285 i++;
00286 strcpy(desc->params[i].name, "rate");
00287 desc->params[i].character = 'r';
00288 desc->params[i].type = JackDriverParamUInt;
00289 desc->params[i].value.ui = 44100U;
00290 strcpy(desc->params[i].short_desc, "Sample rate");
00291 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00292
00293 i++;
00294 strcpy(desc->params[i].name, "periodsize");
00295 desc->params[i].character = 'p';
00296 desc->params[i].type = JackDriverParamUInt;
00297 desc->params[i].value.ui = 512U;
00298 strcpy(desc->params[i].short_desc, "Period size");
00299 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00300
00301 i++;
00302 strcpy(desc->params[i].name, "device");
00303 desc->params[i].character = 'd';
00304 desc->params[i].type = JackDriverParamString;
00305 desc->params[i].value.ui = 128U;
00306 strcpy(desc->params[i].value.str, "default device");
00307 strcpy(desc->params[i].short_desc, "PortAudio device name");
00308 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00309
00310 i++;
00311 strcpy(desc->params[i].name, "list-devices");
00312 desc->params[i].character = 'l';
00313 desc->params[i].type = JackDriverParamBool;
00314 desc->params[i].value.i = TRUE;
00315 strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
00316 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00317
00318 i++;
00319 strcpy(desc->params[i].name, "quality");
00320 desc->params[i].character = 'q';
00321 desc->params[i].type = JackDriverParamInt;
00322 desc->params[i].value.ui = 0;
00323 strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
00324 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00325
00326 return desc;
00327 }
00328
00329 #ifdef __cplusplus
00330 }
00331 #endif