git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3368 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
| @@ -22,11 +22,22 @@ Michael Voigt | |||||
| --------------------------- | --------------------------- | ||||
| Jackdmp changes log | Jackdmp changes log | ||||
| --------------------------- | --------------------------- | ||||
| 2009-02-27 Stephane Letz <letz@grame.fr> | |||||
| * Improve generated gnuplot files for adapting code. | |||||
| 2009-02-25 Stephane Letz <letz@grame.fr> | |||||
| * Major cleanup in adapter code. | |||||
| 2009-02-25 Stephane Letz <letz@grame.fr> | 2009-02-25 Stephane Letz <letz@grame.fr> | ||||
| * Fix JackNetDriver::Close method. | * Fix JackNetDriver::Close method. | ||||
| * For audio device reservation, add card_to_num function. | * For audio device reservation, add card_to_num function. | ||||
| * Fix buffer size and sample rate handling in JackAlsaAdapter. | |||||
| * Add control for adapter ringbuffer size. | |||||
| * Fix JackAlsaAdapter.h for 64 bits compilation. | |||||
| 2009-02-24 Stephane Letz <letz@grame.fr> | 2009-02-24 Stephane Letz <letz@grame.fr> | ||||
| @@ -37,7 +48,7 @@ Michael Voigt | |||||
| * Another fix in systemdeps.h and types.h: jack_time_t now uniquely defined in types.h. | * Another fix in systemdeps.h and types.h: jack_time_t now uniquely defined in types.h. | ||||
| * Move generic code and data in JackNetInterface and JackNetMasterInterface classes. | * Move generic code and data in JackNetInterface and JackNetMasterInterface classes. | ||||
| * First version of D-Bus based audio device rerservation. | |||||
| * First version of D-Bus based audio device reservation. | |||||
| 2009-02-20 Stephane Letz <letz@grame.fr> | 2009-02-20 Stephane Letz <letz@grame.fr> | ||||
| @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| */ | */ | ||||
| #include "JackAudioAdapter.h" | #include "JackAudioAdapter.h" | ||||
| #include "JackLibSampleRateResampler.h" | |||||
| #include "JackError.h" | #include "JackError.h" | ||||
| #include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
| #include "JackTools.h" | #include "JackTools.h" | ||||
| @@ -34,40 +33,22 @@ namespace Jack | |||||
| { | { | ||||
| //static methods *********************************************************** | //static methods *********************************************************** | ||||
| int JackAudioAdapter::Process ( jack_nframes_t frames, void* arg ) | |||||
| int JackAudioAdapter::Process (jack_nframes_t frames, void* arg) | |||||
| { | { | ||||
| JackAudioAdapter* adapter = static_cast<JackAudioAdapter*> ( arg ); | |||||
| float* buffer; | |||||
| bool failure = false; | |||||
| int i; | |||||
| if ( !adapter->fAudioAdapter->IsRunning() ) | |||||
| JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | |||||
| if (!adapter->fAudioAdapter->IsRunning()) | |||||
| return 0; | return 0; | ||||
| // DLL | |||||
| adapter->fAudioAdapter->SetCallbackTime (GetMicroSeconds()); | |||||
| // Push/pull from ringbuffer | |||||
| for ( i = 0; i < adapter->fCaptureChannels; i++ ) | |||||
| { | |||||
| buffer = static_cast<float*> ( jack_port_get_buffer ( adapter->fCapturePortList[i], frames ) ); | |||||
| if ( adapter->fCaptureRingBuffer[i]->Read ( buffer, frames ) < frames ) | |||||
| failure = true; | |||||
| float* inputBuffer[adapter->fAudioAdapter->GetInputs()]; | |||||
| float* outputBuffer[adapter->fAudioAdapter->GetOutputs()]; | |||||
| for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { | |||||
| inputBuffer[i] = (float*)jack_port_get_buffer(adapter->fCapturePortList[i], frames); | |||||
| } | } | ||||
| for ( i = 0; i < adapter->fPlaybackChannels; i++ ) | |||||
| { | |||||
| buffer = static_cast<float*> ( jack_port_get_buffer ( adapter->fPlaybackPortList[i], frames ) ); | |||||
| if ( adapter->fPlaybackRingBuffer[i]->Write ( buffer, frames ) < frames ) | |||||
| failure = true; | |||||
| } | |||||
| // Reset all ringbuffers in case of failure | |||||
| if ( failure ) | |||||
| { | |||||
| jack_error ( "JackCallbackAudioAdapter::Process ringbuffer failure... reset" ); | |||||
| adapter->Reset(); | |||||
| for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { | |||||
| outputBuffer[i] = (float*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); | |||||
| } | } | ||||
| adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -91,24 +72,15 @@ namespace Jack | |||||
| JackAudioAdapter::~JackAudioAdapter() | JackAudioAdapter::~JackAudioAdapter() | ||||
| { | { | ||||
| // When called, Close has already been used for the client, thus ports are already unregistered. | // When called, Close has already been used for the client, thus ports are already unregistered. | ||||
| int i; | |||||
| for ( i = 0; i < fCaptureChannels; i++ ) | |||||
| delete ( fCaptureRingBuffer[i] ); | |||||
| for ( i = 0; i < fPlaybackChannels; i++ ) | |||||
| delete ( fPlaybackRingBuffer[i] ); | |||||
| delete[] fCaptureRingBuffer; | |||||
| delete[] fPlaybackRingBuffer; | |||||
| delete fAudioAdapter; | delete fAudioAdapter; | ||||
| } | } | ||||
| void JackAudioAdapter::FreePorts() | void JackAudioAdapter::FreePorts() | ||||
| { | { | ||||
| int i; | |||||
| for ( i = 0; i < fCaptureChannels; i++ ) | |||||
| for (int i = 0; i < fAudioAdapter->GetInputs(); i++ ) | |||||
| if ( fCapturePortList[i] ) | if ( fCapturePortList[i] ) | ||||
| jack_port_unregister ( fJackClient, fCapturePortList[i] ); | jack_port_unregister ( fJackClient, fCapturePortList[i] ); | ||||
| for ( i = 0; i < fCaptureChannels; i++ ) | |||||
| for (int i = 0; i < fAudioAdapter->GetOutputs(); i++ ) | |||||
| if ( fPlaybackPortList[i] ) | if ( fPlaybackPortList[i] ) | ||||
| jack_port_unregister ( fJackClient, fPlaybackPortList[i] ); | jack_port_unregister ( fJackClient, fPlaybackPortList[i] ); | ||||
| @@ -118,52 +90,30 @@ namespace Jack | |||||
| void JackAudioAdapter::Reset() | void JackAudioAdapter::Reset() | ||||
| { | { | ||||
| int i; | |||||
| for ( i = 0; i < fCaptureChannels; i++ ) | |||||
| fCaptureRingBuffer[i]->Reset(); | |||||
| for ( i = 0; i < fPlaybackChannels; i++ ) | |||||
| fPlaybackRingBuffer[i]->Reset(); | |||||
| fAudioAdapter->Reset(); | fAudioAdapter->Reset(); | ||||
| } | } | ||||
| int JackAudioAdapter::Open() | int JackAudioAdapter::Open() | ||||
| { | { | ||||
| int i; | |||||
| char name[32]; | char name[32]; | ||||
| fCaptureChannels = fAudioAdapter->GetInputs(); | |||||
| fPlaybackChannels = fAudioAdapter->GetOutputs(); | |||||
| jack_log ( "JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fCaptureChannels, fPlaybackChannels ); | |||||
| //ringbuffers | |||||
| fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; | |||||
| fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; | |||||
| for ( i = 0; i < fCaptureChannels; i++ ) | |||||
| fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fAudioAdapter->GetQuality()); | |||||
| for ( i = 0; i < fPlaybackChannels; i++ ) | |||||
| fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fAudioAdapter->GetQuality()); | |||||
| fAudioAdapter->SetRingBuffers ( fCaptureRingBuffer, fPlaybackRingBuffer ); | |||||
| if (fCaptureChannels > 0) | |||||
| jack_log ( "ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace() ); | |||||
| if (fPlaybackChannels > 0) | |||||
| jack_log ( "WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace() ); | |||||
| jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs()); | |||||
| fAudioAdapter->Create(); | |||||
| //jack ports | //jack ports | ||||
| fCapturePortList = new jack_port_t* [fCaptureChannels]; | |||||
| fPlaybackPortList = new jack_port_t* [fPlaybackChannels]; | |||||
| fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()]; | |||||
| fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()]; | |||||
| for ( i = 0; i < fCaptureChannels; i++ ) | |||||
| for (int i = 0; i < fAudioAdapter->GetInputs(); i++) | |||||
| { | { | ||||
| sprintf ( name, "capture_%d", i+1 ); | |||||
| if ( ( fCapturePortList[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ) ) == NULL ) | |||||
| sprintf(name, "capture_%d", i + 1); | |||||
| 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 (int i = 0; i < fAudioAdapter->GetOutputs(); i++) | |||||
| { | { | ||||
| sprintf ( name, "playback_%d", i+1 ); | |||||
| if ( ( fPlaybackPortList[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ) ) == NULL ) | |||||
| sprintf(name, "playback_%d", i + 1); | |||||
| if ((fPlaybackPortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 )) == NULL) | |||||
| goto fail; | goto fail; | ||||
| } | } | ||||
| @@ -177,17 +127,20 @@ namespace Jack | |||||
| 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 | |||||
| // Ring buffer are now allocated.. | |||||
| return fAudioAdapter->Open(); | return fAudioAdapter->Open(); | ||||
| fail: | fail: | ||||
| FreePorts(); | FreePorts(); | ||||
| fAudioAdapter->Destroy(); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| int JackAudioAdapter::Close() | int JackAudioAdapter::Close() | ||||
| { | { | ||||
| return fAudioAdapter->Close(); | |||||
| fAudioAdapter->Close(); | |||||
| fAudioAdapter->Destroy(); | |||||
| return 0; | |||||
| } | } | ||||
| } //namespace | } //namespace | ||||
| @@ -37,12 +37,6 @@ namespace Jack | |||||
| static int BufferSize ( jack_nframes_t buffer_size, void *arg ); | static int BufferSize ( jack_nframes_t buffer_size, void *arg ); | ||||
| static int SampleRate ( jack_nframes_t sample_rate, void *arg ); | static int SampleRate ( jack_nframes_t sample_rate, void *arg ); | ||||
| int fCaptureChannels; | |||||
| int fPlaybackChannels; | |||||
| JackResampler** fCaptureRingBuffer; | |||||
| JackResampler** fPlaybackRingBuffer; | |||||
| jack_port_t** fCapturePortList; | jack_port_t** fCapturePortList; | ||||
| jack_port_t** fPlaybackPortList; | jack_port_t** fPlaybackPortList; | ||||
| @@ -18,6 +18,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| */ | */ | ||||
| #include "JackAudioAdapter.h" | #include "JackAudioAdapter.h" | ||||
| #include <TargetConditionals.h> | |||||
| #ifndef TARGET_OS_IPHONE | |||||
| #include "JackLibSampleRateResampler.h" | |||||
| #endif | |||||
| #include "JackTime.h" | #include "JackTime.h" | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| @@ -37,7 +41,7 @@ namespace Jack | |||||
| fTable[pos].pos2 = pos2; | fTable[pos].pos2 = pos2; | ||||
| } | } | ||||
| void MeasureTable::Save() | |||||
| void MeasureTable::Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize) | |||||
| { | { | ||||
| char buffer[1024]; | char buffer[1024]; | ||||
| FILE* file = fopen("JackAudioAdapter.log", "w"); | FILE* file = fopen("JackAudioAdapter.log", "w"); | ||||
| @@ -54,6 +58,22 @@ namespace Jack | |||||
| // Adapter timing 1 | // Adapter timing 1 | ||||
| file = fopen("AdapterTiming1.plot", "w"); | file = fopen("AdapterTiming1.plot", "w"); | ||||
| fprintf(file, "set multiplot\n"); | |||||
| fprintf(file, "set grid\n"); | |||||
| fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" | |||||
| ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize); | |||||
| 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); | |||||
| fprintf(file, "\n unset multiplot\n"); | |||||
| fprintf(file, "set output 'AdapterTiming1.pdf\n"); | |||||
| fprintf(file, "set terminal pdf\n"); | |||||
| fprintf(file, "set multiplot\n"); | fprintf(file, "set multiplot\n"); | ||||
| fprintf(file, "set grid\n"); | fprintf(file, "set grid\n"); | ||||
| fprintf(file, "set title \"Audio adapter timing\"\n"); | fprintf(file, "set title \"Audio adapter timing\"\n"); | ||||
| @@ -64,10 +84,27 @@ namespace Jack | |||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines"); | sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines"); | ||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| fclose(file); | fclose(file); | ||||
| // Adapter timing 2 | // Adapter timing 2 | ||||
| file = fopen("AdapterTiming2.plot", "w"); | file = fopen("AdapterTiming2.plot", "w"); | ||||
| fprintf(file, "set multiplot\n"); | |||||
| fprintf(file, "set grid\n"); | |||||
| fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" | |||||
| ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize); | |||||
| 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); | |||||
| fprintf(file, "\n unset multiplot\n"); | |||||
| fprintf(file, "set output 'AdapterTiming2.pdf\n"); | |||||
| fprintf(file, "set terminal pdf\n"); | |||||
| fprintf(file, "set multiplot\n"); | fprintf(file, "set multiplot\n"); | ||||
| fprintf(file, "set grid\n"); | fprintf(file, "set grid\n"); | ||||
| fprintf(file, "set title \"Audio adapter timing\"\n"); | fprintf(file, "set title \"Audio adapter timing\"\n"); | ||||
| @@ -78,10 +115,27 @@ namespace Jack | |||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines"); | sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines"); | ||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| fclose(file); | fclose(file); | ||||
| // Adapter timing 3 | // Adapter timing 3 | ||||
| file = fopen("AdapterTiming3.plot", "w"); | file = fopen("AdapterTiming3.plot", "w"); | ||||
| fprintf(file, "set multiplot\n"); | |||||
| fprintf(file, "set grid\n"); | |||||
| fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" | |||||
| ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize); | |||||
| 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); | |||||
| fprintf(file, "\n unset multiplot\n"); | |||||
| fprintf(file, "set output 'AdapterTiming3.pdf\n"); | |||||
| fprintf(file, "set terminal pdf\n"); | |||||
| fprintf(file, "set multiplot\n"); | fprintf(file, "set multiplot\n"); | ||||
| fprintf(file, "set grid\n"); | fprintf(file, "set grid\n"); | ||||
| fprintf(file, "set title \"Audio adapter timing\"\n"); | fprintf(file, "set title \"Audio adapter timing\"\n"); | ||||
| @@ -92,35 +146,32 @@ namespace Jack | |||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines"); | sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines"); | ||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| fclose(file); | fclose(file); | ||||
| } | } | ||||
| #endif | #endif | ||||
| void JackAudioAdapterInterface::ResetRingBuffers() | void JackAudioAdapterInterface::ResetRingBuffers() | ||||
| { | { | ||||
| int i; | |||||
| for (i = 0; i < fCaptureChannels; i++) | |||||
| for (int i = 0; i < fCaptureChannels; i++) | |||||
| fCaptureRingBuffer[i]->Reset(); | fCaptureRingBuffer[i]->Reset(); | ||||
| for (i = 0; i < fPlaybackChannels; i++) | |||||
| for (int i = 0; i < fPlaybackChannels; i++) | |||||
| fPlaybackRingBuffer[i]->Reset(); | fPlaybackRingBuffer[i]->Reset(); | ||||
| } | } | ||||
| void JackAudioAdapterInterface::ResampleFactor ( jack_nframes_t& frame1, jack_nframes_t& frame2 ) | |||||
| void JackAudioAdapterInterface::ResampleFactor ( jack_time_t& frame1, jack_time_t& frame2 ) | |||||
| { | { | ||||
| jack_time_t time = GetMicroSeconds(); | jack_time_t time = GetMicroSeconds(); | ||||
| if ( !fRunning ) | |||||
| { | |||||
| if (!fRunning) { | |||||
| // Init DLL | // Init DLL | ||||
| fRunning = true; | fRunning = true; | ||||
| fHostDLL.Init ( time ); | |||||
| fAdaptedDLL.Init ( time ); | |||||
| fHostDLL.Init(time); | |||||
| fAdaptedDLL.Init(time); | |||||
| frame1 = 1; | frame1 = 1; | ||||
| frame2 = 1; | frame2 = 1; | ||||
| } | |||||
| else | |||||
| { | |||||
| } else { | |||||
| // DLL | // DLL | ||||
| fAdaptedDLL.IncFrame(time); | fAdaptedDLL.IncFrame(time); | ||||
| jack_nframes_t time1 = fHostDLL.Time2Frames(time); | jack_nframes_t time1 = fHostDLL.Time2Frames(time); | ||||
| @@ -131,15 +182,103 @@ namespace Jack | |||||
| long(time1), long(time2), double(time1) / double(time2), double(time2) / double(time1)); | long(time1), long(time2), double(time1) / double(time2), double(time2) / double(time1)); | ||||
| } | } | ||||
| } | } | ||||
| void JackAudioAdapterInterface::Reset() | |||||
| { | |||||
| ResetRingBuffers(); | |||||
| fRunning = false; | |||||
| } | |||||
| #ifdef TARGET_OS_IPHONE | |||||
| void JackAudioAdapterInterface::Create() | |||||
| {} | |||||
| #else | |||||
| void JackAudioAdapterInterface::Create() | |||||
| { | |||||
| //ringbuffers | |||||
| fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; | |||||
| fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; | |||||
| for (int i = 0; i < fCaptureChannels; i++ ) | |||||
| fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality, fRingbufferSize); | |||||
| for (int i = 0; i < fPlaybackChannels; i++ ) | |||||
| fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality, fRingbufferSize); | |||||
| if (fCaptureChannels > 0) | |||||
| jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); | |||||
| if (fPlaybackChannels > 0) | |||||
| jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); | |||||
| } | |||||
| #endif | |||||
| void JackAudioAdapterInterface::Destroy() | |||||
| { | |||||
| for (int i = 0; i < fCaptureChannels; i++ ) | |||||
| delete ( fCaptureRingBuffer[i] ); | |||||
| for (int i = 0; i < fPlaybackChannels; i++ ) | |||||
| delete ( fPlaybackRingBuffer[i] ); | |||||
| int JackAudioAdapterInterface::Open() | |||||
| delete[] fCaptureRingBuffer; | |||||
| delete[] fPlaybackRingBuffer; | |||||
| } | |||||
| int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames) | |||||
| { | { | ||||
| return 0; | |||||
| bool failure = false; | |||||
| jack_time_t time1, time2; | |||||
| ResampleFactor(time1, time2); | |||||
| // Push/pull from ringbuffer | |||||
| for (int i = 0; i < fCaptureChannels; i++) { | |||||
| fCaptureRingBuffer[i]->SetRatio(time1, time2); | |||||
| if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) | |||||
| failure = true; | |||||
| } | |||||
| for (int i = 0; i < fPlaybackChannels; i++) { | |||||
| fPlaybackRingBuffer[i]->SetRatio(time2, time1); | |||||
| if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) | |||||
| failure = true; | |||||
| } | |||||
| #ifdef JACK_MONITOR | |||||
| fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1), | |||||
| fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace()); | |||||
| #endif | |||||
| // Reset all ringbuffers in case of failure | |||||
| if (failure) { | |||||
| jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset"); | |||||
| ResetRingBuffers(); | |||||
| return -1; | |||||
| } else { | |||||
| return 0; | |||||
| } | |||||
| } | } | ||||
| int JackAudioAdapterInterface::Close() | |||||
| int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames) | |||||
| { | { | ||||
| return 0; | |||||
| bool failure = false; | |||||
| fHostDLL.IncFrame(GetMicroSeconds()); | |||||
| // Push/pull from ringbuffer | |||||
| for (int i = 0; i < fCaptureChannels; i++) { | |||||
| if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) | |||||
| failure = true; | |||||
| } | |||||
| for (int i = 0; i < fPlaybackChannels; i++) { | |||||
| if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) | |||||
| failure = true; | |||||
| } | |||||
| // Reset all ringbuffers in case of failure | |||||
| if (failure) { | |||||
| jack_error("JackCallbackAudioAdapter::PullAndPush ringbuffer failure... reset"); | |||||
| Reset(); | |||||
| return -1; | |||||
| } else { | |||||
| return 0; | |||||
| } | |||||
| } | } | ||||
| } // namespace | } // namespace | ||||
| @@ -51,8 +51,8 @@ namespace Jack | |||||
| MeasureTable() :fCount ( 0 ) | MeasureTable() :fCount ( 0 ) | ||||
| {} | {} | ||||
| void Write ( int time1, int time2, float r1, float r2, int pos1, int pos2 ); | |||||
| void Save(); | |||||
| void Write(int time1, int time2, float r1, float r2, int pos1, int pos2); | |||||
| void Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize); | |||||
| }; | }; | ||||
| @@ -90,9 +90,13 @@ namespace Jack | |||||
| JackResampler** fPlaybackRingBuffer; | JackResampler** fPlaybackRingBuffer; | ||||
| unsigned int fQuality; | unsigned int fQuality; | ||||
| unsigned int fRingbufferSize; | |||||
| bool fRunning; | bool fRunning; | ||||
| void ResetRingBuffers(); | |||||
| void ResampleFactor ( jack_time_t& frame1, jack_time_t& frame2 ); | |||||
| public: | public: | ||||
| JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, | JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, | ||||
| @@ -106,6 +110,7 @@ namespace Jack | |||||
| fHostDLL ( host_buffer_size, host_sample_rate ), | fHostDLL ( host_buffer_size, host_sample_rate ), | ||||
| fAdaptedDLL ( host_buffer_size, host_sample_rate ), | fAdaptedDLL ( host_buffer_size, host_sample_rate ), | ||||
| fQuality(0), | fQuality(0), | ||||
| fRingbufferSize(DEFAULT_RB_SIZE), | |||||
| fRunning ( false ) | fRunning ( false ) | ||||
| {} | {} | ||||
| JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, | JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, | ||||
| @@ -121,38 +126,33 @@ namespace Jack | |||||
| fHostDLL ( host_buffer_size, host_sample_rate ), | fHostDLL ( host_buffer_size, host_sample_rate ), | ||||
| fAdaptedDLL ( adapted_buffer_size, adapted_sample_rate ), | fAdaptedDLL ( adapted_buffer_size, adapted_sample_rate ), | ||||
| fQuality(0), | fQuality(0), | ||||
| fRingbufferSize(DEFAULT_RB_SIZE), | |||||
| fRunning ( false ) | fRunning ( false ) | ||||
| {} | {} | ||||
| virtual ~JackAudioAdapterInterface() | virtual ~JackAudioAdapterInterface() | ||||
| {} | {} | ||||
| void SetRingBuffers ( JackResampler** input, JackResampler** output ) | |||||
| { | |||||
| fCaptureRingBuffer = input; | |||||
| fPlaybackRingBuffer = output; | |||||
| } | |||||
| bool IsRunning() | bool IsRunning() | ||||
| { | { | ||||
| return fRunning; | return fRunning; | ||||
| } | } | ||||
| virtual void Reset() | |||||
| virtual void Reset(); | |||||
| virtual void Create(); | |||||
| virtual void Destroy(); | |||||
| virtual int Open() | |||||
| { | { | ||||
| fRunning = false; | |||||
| return 0; | |||||
| } | } | ||||
| void ResetRingBuffers(); | |||||
| unsigned int GetQuality() | |||||
| virtual int Close() | |||||
| { | { | ||||
| return fQuality; | |||||
| return 0; | |||||
| } | } | ||||
| virtual int Open(); | |||||
| virtual int Close(); | |||||
| virtual int SetHostBufferSize ( jack_nframes_t buffer_size ) | virtual int SetHostBufferSize ( jack_nframes_t buffer_size ) | ||||
| { | { | ||||
| fHostBufferSize = buffer_size; | fHostBufferSize = buffer_size; | ||||
| @@ -194,14 +194,7 @@ namespace Jack | |||||
| SetAdaptedSampleRate ( sample_rate ); | SetAdaptedSampleRate ( sample_rate ); | ||||
| return 0; | 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 ) | void SetInputs ( int inputs ) | ||||
| { | { | ||||
| jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs ); | jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs ); | ||||
| @@ -225,6 +218,9 @@ namespace Jack | |||||
| jack_log ( "JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels ); | jack_log ( "JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels ); | ||||
| return fPlaybackChannels; | return fPlaybackChannels; | ||||
| } | } | ||||
| int PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames); | |||||
| int PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames); | |||||
| }; | }; | ||||
| @@ -31,8 +31,8 @@ JackLibSampleRateResampler::JackLibSampleRateResampler() | |||||
| jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | ||||
| } | } | ||||
| JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality) | |||||
| :JackResampler(),fRatio(1) | |||||
| JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality, unsigned int ringbuffer_size) | |||||
| :JackResampler(ringbuffer_size),fRatio(1) | |||||
| { | { | ||||
| switch (quality) { | switch (quality) { | ||||
| case 0: | case 0: | ||||
| @@ -46,7 +46,7 @@ class JackLibSampleRateResampler : public JackResampler | |||||
| public: | public: | ||||
| JackLibSampleRateResampler(); | JackLibSampleRateResampler(); | ||||
| JackLibSampleRateResampler(unsigned int quality); | |||||
| JackLibSampleRateResampler(unsigned int quality, unsigned int ringbuffer_size); | |||||
| virtual ~JackLibSampleRateResampler(); | virtual ~JackLibSampleRateResampler(); | ||||
| unsigned int ReadResample(float* buffer, unsigned int frames); | unsigned int ReadResample(float* buffer, unsigned int frames); | ||||
| @@ -55,7 +55,7 @@ class JackLibSampleRateResampler : public JackResampler | |||||
| void SetRatio(unsigned int num, unsigned int denom) | void SetRatio(unsigned int num, unsigned int denom) | ||||
| { | { | ||||
| JackResampler::SetRatio(num, denom); | JackResampler::SetRatio(num, denom); | ||||
| fRatio = Range(0.25f, 4.0f, (double(num) / double(denom))); | |||||
| fRatio = Range(0.25, 4.0, (double(num) / double(denom))); | |||||
| } | } | ||||
| void Reset(); | void Reset(); | ||||
| @@ -106,18 +106,16 @@ extern "C" | |||||
| typedef struct _jack_adapter jack_adapter_t; | typedef struct _jack_adapter jack_adapter_t; | ||||
| SERVER_EXPORT jack_adapter_t* jack_create_adapter(jack_nframes_t host_buffer_size, | |||||
| SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, | |||||
| jack_nframes_t host_buffer_size, | |||||
| jack_nframes_t host_sample_rate, | jack_nframes_t host_sample_rate, | ||||
| jack_nframes_t adapted_buffer_size, | jack_nframes_t adapted_buffer_size, | ||||
| jack_nframes_t adapted_sample_rate); | jack_nframes_t adapted_sample_rate); | ||||
| SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter); | SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter); | ||||
| SERVER_EXPORT int jack_adapter_push_input(jack_adapter_t* adapter, int channels, float** buffers); | |||||
| SERVER_EXPORT int jack_adapter_pull_input(jack_adapter_t* adapter, int channels, float** buffers); | |||||
| SERVER_EXPORT int jack_adapter_push_output(jack_adapter_t* adapter, int channels, float** buffers); | |||||
| SERVER_EXPORT int jack_adapter_pull_output(jack_adapter_t* adapter, int channels, float** buffers); | |||||
| SERVER_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); | |||||
| SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); | |||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| } | } | ||||
| #endif | #endif | ||||
| @@ -734,144 +732,39 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| struct JackNetAdapter : public JackAudioAdapterInterface { | struct JackNetAdapter : public JackAudioAdapterInterface { | ||||
| JackNetAdapter(jack_nframes_t host_buffer_size, | |||||
| JackNetAdapter(int input, int output, | |||||
| jack_nframes_t host_buffer_size, | |||||
| jack_nframes_t host_sample_rate, | jack_nframes_t host_sample_rate, | ||||
| jack_nframes_t adapted_buffer_size, | jack_nframes_t adapted_buffer_size, | ||||
| jack_nframes_t adapted_sample_rate) | jack_nframes_t adapted_sample_rate) | ||||
| :JackAudioAdapterInterface(host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate) | :JackAudioAdapterInterface(host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate) | ||||
| { | { | ||||
| fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; | |||||
| fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; | |||||
| /* | |||||
| for (i = 0; i < fCaptureChannels; i++) | |||||
| fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fAudioAdapter->GetQuality()); | |||||
| for (i = 0; i < fPlaybackChannels; i++) | |||||
| fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fAudioAdapter->GetQuality()); | |||||
| */ | |||||
| int i; | |||||
| for (i = 0; i < fCaptureChannels; i++) | |||||
| fCaptureRingBuffer[i] = new JackResampler(); | |||||
| for (i = 0; i < fPlaybackChannels; i++) | |||||
| fPlaybackRingBuffer[i] = new JackResampler(); | |||||
| } | |||||
| virtual ~JackNetAdapter() | |||||
| { | |||||
| int i; | |||||
| for (i = 0; i < fCaptureChannels; i++) | |||||
| delete (fCaptureRingBuffer[i]); | |||||
| for (i = 0; i < fPlaybackChannels; i++) | |||||
| delete(fPlaybackRingBuffer[i] ); | |||||
| delete[] fCaptureRingBuffer; | |||||
| delete[] fPlaybackRingBuffer; | |||||
| } | |||||
| void Reset() | |||||
| { | |||||
| int i; | |||||
| for (i = 0; i < fCaptureChannels; i++) | |||||
| fCaptureRingBuffer[i]->Reset(); | |||||
| for (i = 0; i < fPlaybackChannels; i++) | |||||
| fPlaybackRingBuffer[i]->Reset(); | |||||
| } | |||||
| int PushInput(int audio_input, float** audio_input_buffer) | |||||
| { | |||||
| bool failure = false; | |||||
| int port_index; | |||||
| // Get the resample factor, | |||||
| jack_nframes_t time1, time2; | |||||
| ResampleFactor(time1, time2); | |||||
| // Resample input data, | |||||
| for (port_index = 0; port_index < audio_input; port_index++) { | |||||
| fCaptureRingBuffer[port_index]->SetRatio(time1, time2); | |||||
| if (fCaptureRingBuffer[port_index]->WriteResample(audio_input_buffer[port_index], fAdaptedBufferSize) < fAdaptedBufferSize) | |||||
| failure = true; | |||||
| } | |||||
| if (failure) { | |||||
| ResetRingBuffers(); | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| fCaptureChannels = input; | |||||
| fPlaybackChannels = output; | |||||
| Create(); | |||||
| } | } | ||||
| int PullInput(int audio_input, float** audio_input_buffer) | |||||
| void JackNetAdapter::Create() | |||||
| { | { | ||||
| bool failure = false; | |||||
| int port_index; | |||||
| // DLL | |||||
| SetCallbackTime(GetMicroSeconds()); | |||||
| // Push/pull from ringbuffer | |||||
| for (port_index = 0; port_index < audio_input; port_index++) { | |||||
| if (fCaptureRingBuffer[port_index]->Read(audio_input_buffer[port_index], fHostBufferSize) < fHostBufferSize) | |||||
| failure = true; | |||||
| } | |||||
| // Reset all ringbuffers in case of failure | |||||
| if (failure) { | |||||
| Reset(); | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| int PushOutput(int audio_input, float** audio_input_buffer) | |||||
| { | |||||
| bool failure = false; | |||||
| int port_index; | |||||
| // DLL | |||||
| SetCallbackTime(GetMicroSeconds()); | |||||
| //ringbuffers | |||||
| fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; | |||||
| fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; | |||||
| for (int i = 0; i < fCaptureChannels; i++ ) | |||||
| fCaptureRingBuffer[i] = new JackResampler(fRingbufferSize); | |||||
| for (int i = 0; i < fPlaybackChannels; i++ ) | |||||
| fPlaybackRingBuffer[i] = new JackResampler(fRingbufferSize); | |||||
| // Push/pull from ringbuffer | |||||
| for (port_index = 0; port_index < audio_input; port_index++) { | |||||
| if (fPlaybackRingBuffer[port_index]->Write(audio_input_buffer[port_index], fHostBufferSize) < fHostBufferSize) | |||||
| failure = true; | |||||
| } | |||||
| // Reset all ringbuffers in case of failure | |||||
| if (failure) { | |||||
| Reset(); | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| if (fCaptureChannels > 0) | |||||
| jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); | |||||
| if (fPlaybackChannels > 0) | |||||
| jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); | |||||
| } | } | ||||
| int PullOutput(int audio_output, float** audio_output_buffer) | |||||
| virtual ~JackNetAdapter() | |||||
| { | { | ||||
| bool failure = false; | |||||
| int port_index; | |||||
| //get the resample factor, | |||||
| jack_nframes_t time1, time2; | |||||
| ResampleFactor(time1, time2); | |||||
| //resample output data, | |||||
| for (port_index = 0; port_index < fPlaybackChannels; port_index++) { | |||||
| fPlaybackRingBuffer[port_index]->SetRatio(time2, time1); | |||||
| if (fPlaybackRingBuffer[port_index]->ReadResample(audio_output_buffer[port_index], fAdaptedBufferSize) < fAdaptedBufferSize) | |||||
| failure = true; | |||||
| } | |||||
| if (failure) { | |||||
| ResetRingBuffers(); | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| Destroy(); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -968,12 +861,13 @@ SERVER_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, | |||||
| // Adapter API | // Adapter API | ||||
| SERVER_EXPORT jack_adapter_t* jack_create_adapter(jack_nframes_t host_buffer_size, | |||||
| SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, | |||||
| jack_nframes_t host_buffer_size, | |||||
| jack_nframes_t host_sample_rate, | jack_nframes_t host_sample_rate, | ||||
| jack_nframes_t adapted_buffer_size, | jack_nframes_t adapted_buffer_size, | ||||
| jack_nframes_t adapted_sample_rate) | jack_nframes_t adapted_sample_rate) | ||||
| { | { | ||||
| return (jack_adapter_t*)new JackNetAdapter(host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate); | |||||
| return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate); | |||||
| } | } | ||||
| SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) | SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) | ||||
| @@ -982,30 +876,18 @@ SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| SERVER_EXPORT int jack_adapter_push_input(jack_adapter_t * adapter, int channels, float** buffers) | |||||
| SERVER_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) | |||||
| { | { | ||||
| JackNetAdapter* slave = (JackNetAdapter*)adapter; | JackNetAdapter* slave = (JackNetAdapter*)adapter; | ||||
| return slave->PushInput(channels, buffers); | |||||
| return slave->PushAndPull(input, output, frames); | |||||
| } | } | ||||
| SERVER_EXPORT int jack_adapter_pull_input(jack_adapter_t * adapter, int channels, float** buffers) | |||||
| SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) | |||||
| { | { | ||||
| JackNetAdapter* slave = (JackNetAdapter*)adapter; | JackNetAdapter* slave = (JackNetAdapter*)adapter; | ||||
| return slave->PullInput(channels, buffers); | |||||
| } | |||||
| SERVER_EXPORT int jack_adapter_push_output(jack_adapter_t * adapter, int channels, float** buffers) | |||||
| { | |||||
| JackNetAdapter* slave = (JackNetAdapter*)adapter; | |||||
| return slave->PushOutput(channels, buffers); | |||||
| return slave->PullAndPush(input, output, frames); | |||||
| } | } | ||||
| SERVER_EXPORT int jack_adapter_pull_output(jack_adapter_t * adapter, int channels, float** buffers) | |||||
| { | |||||
| JackNetAdapter* slave = (JackNetAdapter*)adapter; | |||||
| return slave->PullOutput(channels, buffers); | |||||
| } | |||||
| // Empty code for now.. | // Empty code for now.. | ||||
| //#ifdef TARGET_OS_IPHONE | //#ifdef TARGET_OS_IPHONE | ||||
| @@ -367,7 +367,7 @@ namespace Jack | |||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| //get the resample factor, | //get the resample factor, | ||||
| jack_nframes_t time1, time2; | |||||
| jack_time_t time1, time2; | |||||
| ResampleFactor ( time1, time2 ); | ResampleFactor ( time1, time2 ); | ||||
| //resample input data, | //resample input data, | ||||
| @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| */ | */ | ||||
| #include "JackResampler.h" | #include "JackResampler.h" | ||||
| #include <stdio.h> | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| @@ -28,6 +29,12 @@ JackResampler::JackResampler():fNum(1),fDenom(1) | |||||
| jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * DEFAULT_RB_SIZE) / 2); | jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * DEFAULT_RB_SIZE) / 2); | ||||
| } | } | ||||
| JackResampler::JackResampler(unsigned int ringbuffer_size):fNum(1),fDenom(1),fRingBufferSize(ringbuffer_size) | |||||
| { | |||||
| fRingBuffer = jack_ringbuffer_create(sizeof(float) * fRingBufferSize); | |||||
| jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * fRingBufferSize) / 2); | |||||
| } | |||||
| JackResampler::~JackResampler() | JackResampler::~JackResampler() | ||||
| { | { | ||||
| if (fRingBuffer) | if (fRingBuffer) | ||||
| @@ -36,7 +43,8 @@ JackResampler::~JackResampler() | |||||
| void JackResampler::Reset() | void JackResampler::Reset() | ||||
| { | { | ||||
| jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * DEFAULT_RB_SIZE) / 2); | |||||
| jack_ringbuffer_reset(fRingBuffer); | |||||
| jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * fRingBufferSize) / 2); | |||||
| } | } | ||||
| unsigned int JackResampler::ReadSpace() | unsigned int JackResampler::ReadSpace() | ||||
| @@ -40,10 +40,12 @@ class JackResampler | |||||
| jack_ringbuffer_t* fRingBuffer; | jack_ringbuffer_t* fRingBuffer; | ||||
| unsigned int fNum; | unsigned int fNum; | ||||
| unsigned int fDenom; | unsigned int fDenom; | ||||
| unsigned int fRingBufferSize; | |||||
| public: | public: | ||||
| JackResampler(); | JackResampler(); | ||||
| JackResampler(unsigned int ringbuffer_size); | |||||
| virtual ~JackResampler(); | virtual ~JackResampler(); | ||||
| virtual void Reset(); | virtual void Reset(); | ||||
| @@ -255,7 +255,8 @@ typedef struct _jack_adapter jack_adapter_t; | |||||
| * | * | ||||
| * @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
| */ | */ | ||||
| jack_adapter_t* jack_create_adapter(jack_nframes_t host_buffer_size, | |||||
| jack_adapter_t* jack_create_adapter(int input, int output, | |||||
| jack_nframes_t host_buffer_size, | |||||
| jack_nframes_t host_sample_rate, | jack_nframes_t host_sample_rate, | ||||
| jack_nframes_t adapted_buffer_size, | jack_nframes_t adapted_buffer_size, | ||||
| jack_nframes_t adapted_sample_rate); | jack_nframes_t adapted_sample_rate); | ||||
| @@ -268,32 +269,18 @@ jack_adapter_t* jack_create_adapter(jack_nframes_t host_buffer_size, | |||||
| int jack_destroy_adapter(jack_adapter_t* adapter); | int jack_destroy_adapter(jack_adapter_t* adapter); | ||||
| /** | /** | ||||
| * Push input to ringbuffer | |||||
| * Push input to and pull output from ringbuffer | |||||
| * | * | ||||
| * @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
| */ | */ | ||||
| int jack_adapter_push_input(jack_adapter_t * adapter, int channels, float** buffers); | |||||
| int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); | |||||
| /** | /** | ||||
| * Pull input from ringbuffer | |||||
| * Pull input to and push output from ringbuffer | |||||
| * | * | ||||
| * @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
| */ | */ | ||||
| int jack_adapter_pull_input(jack_adapter_t * adapter, int channels, float** buffers); | |||||
| /** | |||||
| * Push output to ringbuffer | |||||
| * | |||||
| * @return error code. | |||||
| */ | |||||
| int jack_adapter_push_output(jack_adapter_t * adapter, int channels, float** buffers); | |||||
| /** | |||||
| * Pull output from ringbuffer | |||||
| * | |||||
| * @return 0 on success, otherwise a non-zero error code | |||||
| */ | |||||
| int jack_adapter_pull_output(jack_adapter_t * adapter, int channels, float** buffers); | |||||
| int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); | |||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| @@ -182,9 +182,15 @@ def build(bld): | |||||
| netlib.includes = includes | netlib.includes = includes | ||||
| netlib.name = 'netlib' | netlib.name = 'netlib' | ||||
| netlib.target = 'jacknet' | netlib.target = 'jacknet' | ||||
| netlib.uselib = uselib | |||||
| netlib.uselib = 'SAMPLERATE' | |||||
| netlib.install_path = '${LIBDIR}' | netlib.install_path = '${LIBDIR}' | ||||
| netlib.source = ['JackNetAPI.cpp', 'JackNetInterface.cpp', 'JackNetTool.cpp', 'JackAudioAdapterInterface.cpp', 'JackResampler.cpp', 'ringbuffer.c'] | |||||
| netlib.source = ['JackNetAPI.cpp', | |||||
| 'JackNetInterface.cpp', | |||||
| 'JackNetTool.cpp', | |||||
| 'JackAudioAdapterInterface.cpp', | |||||
| 'JackLibSampleRateResampler.cpp', | |||||
| 'JackResampler.cpp', | |||||
| 'ringbuffer.c'] | |||||
| if bld.env['IS_LINUX']: | if bld.env['IS_LINUX']: | ||||
| netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../linux/JackLinuxTime.c'] | netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../linux/JackLinuxTime.c'] | ||||
| @@ -66,14 +66,19 @@ namespace Jack | |||||
| fAudioInterface.fCardName = strdup ( param->value.str ); | fAudioInterface.fCardName = strdup ( param->value.str ); | ||||
| break; | break; | ||||
| case 'r': | case 'r': | ||||
| fAudioInterface.fFrequency = param->value.ui; | |||||
| SetAdaptedSampleRate ( param->value.ui ); | SetAdaptedSampleRate ( param->value.ui ); | ||||
| break; | break; | ||||
| case 'p': | case 'p': | ||||
| fAudioInterface.fBuffering = param->value.ui; | |||||
| SetAdaptedBufferSize ( param->value.ui ); | SetAdaptedBufferSize ( param->value.ui ); | ||||
| break; | break; | ||||
| case 'q': | case 'q': | ||||
| fQuality = param->value.ui; | fQuality = param->value.ui; | ||||
| break; | break; | ||||
| case 'g': | |||||
| fRingbufferSize = param->value.ui; | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| @@ -106,7 +111,7 @@ namespace Jack | |||||
| int JackAlsaAdapter::Close() | int JackAlsaAdapter::Close() | ||||
| { | { | ||||
| #ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
| fTable.Save(); | |||||
| fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); | |||||
| #endif | #endif | ||||
| switch ( fThread.GetStatus() ) | switch ( fThread.GetStatus() ) | ||||
| { | { | ||||
| @@ -147,46 +152,15 @@ namespace Jack | |||||
| bool JackAlsaAdapter::Execute() | bool JackAlsaAdapter::Execute() | ||||
| { | { | ||||
| //read data from audio interface | //read data from audio interface | ||||
| if ( fAudioInterface.read() < 0 ) | |||||
| if (fAudioInterface.read() < 0) | |||||
| return false; | return false; | ||||
| bool failure = false; | |||||
| //compute resampling factor | |||||
| jack_nframes_t time1, time2; | |||||
| ResampleFactor ( time1, time2 ); | |||||
| //resample inputs | |||||
| for ( int i = 0; i < fCaptureChannels; i++ ) | |||||
| { | |||||
| fCaptureRingBuffer[i]->SetRatio ( time1, time2 ); | |||||
| if ( fCaptureRingBuffer[i]->WriteResample ( fAudioInterface.fInputSoftChannels[i], fAdaptedBufferSize ) < fAdaptedBufferSize ) | |||||
| failure = true; | |||||
| } | |||||
| //resample outputs | |||||
| for ( int i = 0; i < fPlaybackChannels; i++ ) | |||||
| { | |||||
| fPlaybackRingBuffer[i]->SetRatio ( time2, time1 ); | |||||
| if ( fPlaybackRingBuffer[i]->ReadResample ( fAudioInterface.fOutputSoftChannels[i], fAdaptedBufferSize ) < fAdaptedBufferSize ) | |||||
| failure = true; | |||||
| } | |||||
| #ifdef JACK_MONITOR | |||||
| fTable.Write ( time1, time2, double ( time1 ) / double ( time2 ), double ( time2 ) / double ( time1 ), | |||||
| fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace() ); | |||||
| #endif | |||||
| PushAndPull(fAudioInterface.fInputSoftChannels, fAudioInterface.fOutputSoftChannels, fAdaptedBufferSize); | |||||
| //write data to audio interface | //write data to audio interface | ||||
| if ( fAudioInterface.write() < 0 ) | |||||
| if (fAudioInterface.write() < 0) | |||||
| return false; | return false; | ||||
| //reset all ringbuffers in case of failure | |||||
| if ( failure ) | |||||
| { | |||||
| jack_error ( "JackAlsaAdapter::Execute ringbuffer failure... reset" ); | |||||
| ResetRingBuffers(); | |||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -220,7 +194,7 @@ extern "C" | |||||
| strcpy ( desc->name, "audioadapter" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | strcpy ( desc->name, "audioadapter" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | ||||
| strcpy ( desc->desc, "netjack audio <==> net backend adapter" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | strcpy ( desc->desc, "netjack audio <==> net backend adapter" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | ||||
| desc->nparams = 10; | |||||
| desc->nparams = 11; | |||||
| 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; | ||||
| @@ -299,7 +273,6 @@ extern "C" | |||||
| strcpy ( desc->params[i].short_desc, | strcpy ( desc->params[i].short_desc, | ||||
| "Number of playback channels (defaults to hardware max)" ); | "Number of playback channels (defaults to hardware max)" ); | ||||
| 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, "quality"); | strcpy(desc->params[i].name, "quality"); | ||||
| @@ -308,6 +281,14 @@ extern "C" | |||||
| desc->params[i].value.ui = 0; | desc->params[i].value.ui = 0; | ||||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | ||||
| 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, "ring-buffer"); | |||||
| desc->params[i].character = 'g'; | |||||
| desc->params[i].type = JackDriverParamInt; | |||||
| desc->params[i].value.ui = 0; | |||||
| strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 32768)"); | |||||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||||
| return desc; | return desc; | ||||
| } | } | ||||
| @@ -182,6 +182,17 @@ namespace Jack | |||||
| fInputParams = 0; | fInputParams = 0; | ||||
| fOutputParams = 0; | fOutputParams = 0; | ||||
| fPeriod = 2; | fPeriod = 2; | ||||
| fInputCardBuffer = 0; | |||||
| fOutputCardBuffer = 0; | |||||
| for ( int i = 0; i < 256; i++ ) | |||||
| { | |||||
| fInputCardChannels[i] = 0; | |||||
| fOutputCardChannels[i] = 0; | |||||
| fInputSoftChannels[i] = 0; | |||||
| fOutputSoftChannels[i] = 0; | |||||
| } | |||||
| } | } | ||||
| AudioInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) : | AudioInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) : | ||||
| @@ -369,10 +380,10 @@ namespace Jack | |||||
| } | } | ||||
| else // SND_PCM_FORMAT_S32 | else // SND_PCM_FORMAT_S32 | ||||
| { | { | ||||
| long* buffer32b = ( long* ) fInputCardBuffer; | |||||
| int32_t* buffer32b = ( int32_t* ) fInputCardBuffer; | |||||
| for ( s = 0; s < fBuffering; s++ ) | for ( s = 0; s < fBuffering; s++ ) | ||||
| for ( c = 0; c < fCardInputs; c++ ) | for ( c = 0; c < fCardInputs; c++ ) | ||||
| fInputSoftChannels[c][s] = float ( buffer32b[c + s*fCardInputs] ) * ( 1.0/float ( LONG_MAX ) ); | |||||
| fInputSoftChannels[c][s] = float ( buffer32b[c + s*fCardInputs] ) * ( 1.0/float ( INT_MAX ) ); | |||||
| } | } | ||||
| break; | break; | ||||
| case SND_PCM_ACCESS_RW_NONINTERLEAVED : | case SND_PCM_ACCESS_RW_NONINTERLEAVED : | ||||
| @@ -394,12 +405,12 @@ namespace Jack | |||||
| } | } | ||||
| else // SND_PCM_FORMAT_S32 | else // SND_PCM_FORMAT_S32 | ||||
| { | { | ||||
| long* chan32b; | |||||
| int32_t* chan32b; | |||||
| for ( c = 0; c < fCardInputs; c++ ) | for ( c = 0; c < fCardInputs; c++ ) | ||||
| { | { | ||||
| chan32b = ( long* ) fInputCardChannels[c]; | |||||
| chan32b = ( int32_t* ) fInputCardChannels[c]; | |||||
| for ( s = 0; s < fBuffering; s++ ) | for ( s = 0; s < fBuffering; s++ ) | ||||
| fInputSoftChannels[c][s] = float ( chan32b[s] ) * ( 1.0/float ( LONG_MAX ) ); | |||||
| fInputSoftChannels[c][s] = float ( chan32b[s] ) * ( 1.0/float ( INT_MAX ) ); | |||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -436,13 +447,13 @@ namespace Jack | |||||
| } | } | ||||
| else // SND_PCM_FORMAT_S32 | else // SND_PCM_FORMAT_S32 | ||||
| { | { | ||||
| long* buffer32b = ( long* ) fOutputCardBuffer; | |||||
| int32_t* buffer32b = ( int32_t* ) fOutputCardBuffer; | |||||
| for ( f = 0; f < fBuffering; f++ ) | for ( f = 0; f < fBuffering; f++ ) | ||||
| { | { | ||||
| for ( unsigned int c = 0; c < fCardOutputs; c++ ) | for ( unsigned int c = 0; c < fCardOutputs; c++ ) | ||||
| { | { | ||||
| float x = fOutputSoftChannels[c][f]; | float x = fOutputSoftChannels[c][f]; | ||||
| buffer32b[c + f * fCardOutputs] = long ( max ( min ( x, 1.0 ), -1.0 ) * float ( LONG_MAX ) ); | |||||
| buffer32b[c + f * fCardOutputs] = int32_t ( max ( min ( x, 1.0 ), -1.0 ) * float ( INT_MAX ) ); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -472,11 +483,11 @@ namespace Jack | |||||
| { | { | ||||
| for ( c = 0; c < fCardOutputs; c++ ) | for ( c = 0; c < fCardOutputs; c++ ) | ||||
| { | { | ||||
| long* chan32b = ( long* ) fOutputCardChannels[c]; | |||||
| int32_t* chan32b = ( int32_t* ) fOutputCardChannels[c]; | |||||
| for ( f = 0; f < fBuffering; f++ ) | for ( f = 0; f < fBuffering; f++ ) | ||||
| { | { | ||||
| float x = fOutputSoftChannels[c][f]; | float x = fOutputSoftChannels[c][f]; | ||||
| chan32b[f] = long ( max ( min ( x,1.0 ),-1.0 ) * float ( LONG_MAX ) ) ; | |||||
| chan32b[f] = int32_t ( max ( min ( x,1.0 ),-1.0 ) * float ( INT_MAX ) ) ; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -293,38 +293,22 @@ 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; | |||||
| jack_nframes_t time1, time2; | |||||
| adapter->ResampleFactor(time1, time2); | |||||
| float* inputBuffer[adapter->fCaptureChannels]; | |||||
| float* outputBuffer[adapter->fPlaybackChannels]; | |||||
| for (int i = 0; i < adapter->fCaptureChannels; i++) { | for (int i = 0; i < adapter->fCaptureChannels; i++) { | ||||
| adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2); | |||||
| if (adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames) < inNumberFrames) | |||||
| failure = true; | |||||
| inputBuffer[i] = (float*)adapter->fInputData->mBuffers[i].mData; | |||||
| } | } | ||||
| for (int i = 0; i < adapter->fPlaybackChannels; i++) { | for (int i = 0; i < adapter->fPlaybackChannels; i++) { | ||||
| adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1); | |||||
| if (adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames) < inNumberFrames) | |||||
| failure = true; | |||||
| } | |||||
| #ifdef JACK_MONITOR | |||||
| adapter->fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1), | |||||
| adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace()); | |||||
| #endif | |||||
| // Reset all ringbuffers in case of failure | |||||
| if (failure) { | |||||
| jack_error("JackCoreAudioAdapter::Render ringbuffer failure... reset"); | |||||
| adapter->ResetRingBuffers(); | |||||
| outputBuffer[i] = (float*)ioData->mBuffers[i].mData; | |||||
| } | } | ||||
| adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, inNumberFrames); | |||||
| return noErr; | return noErr; | ||||
| } | } | ||||
| JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) | |||||
| JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) | |||||
| :JackAudioAdapterInterface(buffer_size, sample_rate), fInputData(0), fCapturing(false), fPlaying(false), fState(false) | :JackAudioAdapterInterface(buffer_size, sample_rate), fInputData(0), fCapturing(false), fPlaying(false), fState(false) | ||||
| { | { | ||||
| @@ -392,6 +376,10 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | |||||
| case 'q': | case 'q': | ||||
| fQuality = param->value.ui; | fQuality = param->value.ui; | ||||
| break; | break; | ||||
| case 'g': | |||||
| fRingbufferSize = param->value.ui; | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| @@ -960,7 +948,7 @@ int JackCoreAudioAdapter::Open() | |||||
| int JackCoreAudioAdapter::Close() | int JackCoreAudioAdapter::Close() | ||||
| { | { | ||||
| #ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
| fTable.Save(); | |||||
| fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); | |||||
| #endif | #endif | ||||
| AudioOutputUnitStop(fAUHAL); | AudioOutputUnitStop(fAUHAL); | ||||
| DisposeBuffers(); | DisposeBuffers(); | ||||
| @@ -997,7 +985,7 @@ extern "C" | |||||
| strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | ||||
| strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | ||||
| desc->nparams = 11; | |||||
| desc->nparams = 12; | |||||
| 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; | ||||
| @@ -1087,6 +1075,14 @@ extern "C" | |||||
| desc->params[i].value.ui = 0; | desc->params[i].value.ui = 0; | ||||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | ||||
| 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, "ring-buffer"); | |||||
| desc->params[i].character = 'g'; | |||||
| desc->params[i].type = JackDriverParamInt; | |||||
| desc->params[i].value.ui = 0; | |||||
| strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 32768)"); | |||||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||||
| return desc; | return desc; | ||||
| } | } | ||||
| @@ -181,6 +181,10 @@ JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample | |||||
| case 'q': | case 'q': | ||||
| fQuality = param->value.ui; | fQuality = param->value.ui; | ||||
| break; | break; | ||||
| case 'g': | |||||
| fRingbufferSize = param->value.ui; | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| @@ -502,10 +506,9 @@ error: | |||||
| int JackOSSAdapter::Close() | int JackOSSAdapter::Close() | ||||
| { | { | ||||
| #ifdef DEBUG | |||||
| fTable.Save(); | |||||
| #ifdef JACK_MONITOR | |||||
| fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); | |||||
| #endif | #endif | ||||
| fThread.Stop(); | fThread.Stop(); | ||||
| CloseAux(); | CloseAux(); | ||||
| return 0; | return 0; | ||||
| @@ -600,38 +603,16 @@ int JackOSSAdapter::Write() | |||||
| bool JackOSSAdapter::Execute() | bool JackOSSAdapter::Execute() | ||||
| { | { | ||||
| //read data from audio interface | |||||
| if (Read() < 0) | if (Read() < 0) | ||||
| return false; | return false; | ||||
| bool failure = false; | |||||
| jack_nframes_t time1, time2; | |||||
| ResampleFactor(time1, time2); | |||||
| for (int i = 0; i < fCaptureChannels; i++) { | |||||
| fCaptureRingBuffer[i]->SetRatio(time1, time2); | |||||
| if (fCaptureRingBuffer[i]->WriteResample(fInputSampleBuffer[i], fAdaptedBufferSize) < fAdaptedBufferSize) | |||||
| failure = true; | |||||
| } | |||||
| for (int i = 0; i < fPlaybackChannels; i++) { | |||||
| fPlaybackRingBuffer[i]->SetRatio(time2, time1); | |||||
| if (fPlaybackRingBuffer[i]->ReadResample(fOutputSampleBuffer[i], fAdaptedBufferSize) < fAdaptedBufferSize) | |||||
| failure = true; | |||||
| } | |||||
| #ifdef DEBUG | |||||
| fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1), | |||||
| fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace()); | |||||
| #endif | |||||
| PushAndPull(fInputSampleBuffer, fOutputSampleBuffer, fAdaptedBufferSize); | |||||
| //write data to audio interface | |||||
| if (Write() < 0) | if (Write() < 0) | ||||
| return false; | return false; | ||||
| // Reset all ringbuffers in case of failure | |||||
| if (failure) { | |||||
| jack_error("JackOSSAdapter::Execute ringbuffer failure... reset"); | |||||
| ResetRingBuffers(); | |||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -756,6 +737,14 @@ extern "C" | |||||
| desc->params[i].value.ui = 0; | desc->params[i].value.ui = 0; | ||||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | ||||
| 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, "ring-buffer"); | |||||
| desc->params[i].character = 'g'; | |||||
| desc->params[i].type = JackDriverParamInt; | |||||
| desc->params[i].value.ui = 0; | |||||
| strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 32768)"); | |||||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||||
| return desc; | return desc; | ||||
| } | } | ||||
| @@ -34,7 +34,7 @@ namespace Jack | |||||
| typedef jack_default_audio_sample_t jack_sample_t; | typedef jack_default_audio_sample_t jack_sample_t; | ||||
| #define OSS_DRIVER_N_PARAMS 12 | |||||
| #define OSS_DRIVER_N_PARAMS 13 | |||||
| #define OSS_DRIVER_DEF_DEV "/dev/dsp" | #define OSS_DRIVER_DEF_DEV "/dev/dsp" | ||||
| #define OSS_DRIVER_DEF_FS 48000 | #define OSS_DRIVER_DEF_FS 48000 | ||||
| #define OSS_DRIVER_DEF_BLKSIZE 1024 | #define OSS_DRIVER_DEF_BLKSIZE 1024 | ||||
| @@ -27,47 +27,15 @@ 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) | |||||
| int JackPortAudioAdapter::Render(const void* inputBuffer, | |||||
| void* outputBuffer, | |||||
| unsigned long framesPerBuffer, | |||||
| const PaStreamCallbackTimeInfo* timeInfo, | |||||
| PaStreamCallbackFlags statusFlags, | |||||
| void* userData) | |||||
| { | { | ||||
| JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(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(); | |||||
| } | |||||
| adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, framesPerBuffer); | |||||
| return paContinue; | return paContinue; | ||||
| } | } | ||||
| @@ -128,6 +96,9 @@ namespace Jack | |||||
| case 'q': | case 'q': | ||||
| fQuality = param->value.ui; | fQuality = param->value.ui; | ||||
| break; | break; | ||||
| case 'g': | |||||
| fRingbufferSize = param->value.ui; | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| @@ -207,7 +178,7 @@ namespace Jack | |||||
| int JackPortAudioAdapter::Close() | int JackPortAudioAdapter::Close() | ||||
| { | { | ||||
| #ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
| fTable.Save(); | |||||
| fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); | |||||
| #endif | #endif | ||||
| jack_log ( "JackPortAudioAdapter::Close" ); | jack_log ( "JackPortAudioAdapter::Close" ); | ||||
| Pa_StopStream ( fStream ); | Pa_StopStream ( fStream ); | ||||
| @@ -246,8 +217,8 @@ extern "C" | |||||
| strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | ||||
| strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | ||||
| 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; | ||||
| @@ -314,7 +285,7 @@ extern "C" | |||||
| desc->params[i].value.i = TRUE; | desc->params[i].value.i = TRUE; | ||||
| strcpy(desc->params[i].short_desc, "Display available PortAudio devices"); | strcpy(desc->params[i].short_desc, "Display available PortAudio devices"); | ||||
| 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, "quality"); | strcpy(desc->params[i].name, "quality"); | ||||
| desc->params[i].character = 'q'; | desc->params[i].character = 'q'; | ||||
| @@ -323,6 +294,14 @@ extern "C" | |||||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | ||||
| 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, "ring-buffer"); | |||||
| desc->params[i].character = 'g'; | |||||
| desc->params[i].type = JackDriverParamInt; | |||||
| desc->params[i].value.ui = 0; | |||||
| strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 32768)"); | |||||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||||
| return desc; | return desc; | ||||
| } | } | ||||