|
- /*
- Copyright (C) 2008 Grame
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
- #if defined(HAVE_CONFIG_H)
- #include "config.h"
- #endif
-
- #include "JackPortAudioAdapter.h"
- #include "JackError.h"
-
- 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;
- 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++ )
- {
- adapter->fPlaybackRingBuffer[i]->SetRatio ( time2, time1 );
- if ( adapter->fPlaybackRingBuffer[i]->ReadResample ( (float*)paBuffer[i], framesPerBuffer ) < framesPerBuffer )
- failure = true;
- }
-
- #ifdef JACK_MONITOR
- adapter->fTable.Write ( time1, time2, double(time1) / double(time2), double(time2) / double(time1),
- adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace() );
- #endif
-
- // Reset all ringbuffers in case of failure
- if ( failure )
- {
- jack_error ( "JackPortAudioAdapter::Render ringbuffer failure... reset" );
- adapter->ResetRingBuffers();
- }
- 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;
-
- fInputDevice = Pa_GetDefaultInputDevice();
- fOutputDevice = Pa_GetDefaultOutputDevice();
-
- for (node = params; node; node = jack_slist_next(node))
- {
- param = (const jack_driver_param_t*) node->data;
-
- switch (param->character)
- {
- case 'i' :
- fCaptureChannels = param->value.ui;
- break;
- case 'o' :
- fPlaybackChannels = param->value.ui;
- break;
- case 'C' :
- if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 )
- {
- jack_error ( "Can't use %s, taking default input device", param->value.str );
- fInputDevice = Pa_GetDefaultInputDevice();
- }
- break;
- case 'P' :
- if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 )
- {
- jack_error ( "Can't use %s, taking default output device", param->value.str );
- fOutputDevice = Pa_GetDefaultOutputDevice();
- }
- break;
- case 'r' :
- SetAdaptedSampleRate ( param->value.ui );
- break;
- case 'p' :
- SetAdaptedBufferSize ( param->value.ui );
- break;
- case 'd' :
- if ( fPaDevices.GetInputDeviceFromName ( param->value.str, fInputDevice, in_max ) < 0 )
- jack_error ( "Can't use %s, taking default input device", param->value.str );
- if ( fPaDevices.GetOutputDeviceFromName ( param->value.str, fOutputDevice, out_max ) < 0 )
- jack_error ( "Can't use %s, taking default output device", param->value.str );
- break;
- case 'l' :
- fPaDevices.DisplayDevicesNames();
- break;
- }
- }
-
- //max channels
- if ( in_max == 0 )
- in_max = fPaDevices.GetDeviceInfo ( fInputDevice )->maxInputChannels;
- if ( out_max == 0 )
- out_max = fPaDevices.GetDeviceInfo ( fOutputDevice )->maxOutputChannels;
-
- //effective channels
- if ( ( fCaptureChannels == 0 ) || ( fCaptureChannels > in_max ) )
- fCaptureChannels = in_max;
- if ( ( fPlaybackChannels == 0 ) || ( fPlaybackChannels > out_max ) )
- fPlaybackChannels = out_max;
-
- //set adapter interface channels
- SetInputs ( fCaptureChannels );
- SetOutputs ( fPlaybackChannels );
- }
-
- 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;
- }
-
- 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;
- }
-
- int JackPortAudioAdapter::Close()
- {
- #ifdef JACK_MONITOR
- fTable.Save();
- #endif
- jack_log ( "JackPortAudioAdapter::Close" );
- Pa_StopStream ( fStream );
- jack_log ( "JackPortAudioAdapter:: Pa_StopStream" );
- Pa_CloseStream ( fStream );
- jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" );
- return JackAudioAdapterInterface::Close();
- }
-
- 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
-
- #ifdef __cplusplus
- extern "C"
- {
- #endif
-
- EXPORT jack_driver_desc_t* jack_get_descriptor()
- {
- jack_driver_desc_t *desc;
- unsigned int i;
- desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
-
- strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
- desc->nparams = 8;
- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
-
- i = 0;
- strcpy(desc->params[i].name, "inchannels");
- desc->params[i].character = 'i';
- desc->params[i].type = JackDriverParamInt;
- desc->params[i].value.ui = 0;
- strcpy(desc->params[i].short_desc, "Maximum number of input channels");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
-
- i++;
- strcpy(desc->params[i].name, "outchannels");
- desc->params[i].character = 'o';
- desc->params[i].type = JackDriverParamInt;
- desc->params[i].value.ui = 0;
- strcpy(desc->params[i].short_desc, "Maximum number of output channels");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
-
- i++;
- strcpy(desc->params[i].name, "capture");
- desc->params[i].character = 'C';
- desc->params[i].type = JackDriverParamString;
- strcpy(desc->params[i].value.str, "default input device");
- strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
-
- i++;
- strcpy(desc->params[i].name, "playback");
- desc->params[i].character = 'P';
- desc->params[i].type = JackDriverParamString;
- strcpy(desc->params[i].value.str, "default output device");
- strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
-
- i++;
- strcpy(desc->params[i].name, "rate");
- desc->params[i].character = 'r';
- desc->params[i].type = JackDriverParamUInt;
- desc->params[i].value.ui = 44100U;
- strcpy(desc->params[i].short_desc, "Sample rate");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
-
- i++;
- strcpy(desc->params[i].name, "periodsize");
- desc->params[i].character = 'p';
- desc->params[i].type = JackDriverParamUInt;
- desc->params[i].value.ui = 512U;
- strcpy(desc->params[i].short_desc, "Period size");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
-
- i++;
- strcpy(desc->params[i].name, "device");
- desc->params[i].character = 'd';
- desc->params[i].type = JackDriverParamString;
- desc->params[i].value.ui = 128U;
- strcpy(desc->params[i].value.str, "default device");
- strcpy(desc->params[i].short_desc, "PortAudio device name");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
-
- i++;
- strcpy(desc->params[i].name, "list-devices");
- desc->params[i].character = 'l';
- desc->params[i].type = JackDriverParamBool;
- desc->params[i].value.i = TRUE;
- strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
-
- return desc;
- }
-
- #ifdef __cplusplus
- }
- #endif
|