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 | |||
| --------------------------- | |||
| 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> | |||
| * Fix JackNetDriver::Close method. | |||
| * 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> | |||
| @@ -37,7 +48,7 @@ Michael Voigt | |||
| * 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. | |||
| * 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> | |||
| @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "JackAudioAdapter.h" | |||
| #include "JackLibSampleRateResampler.h" | |||
| #include "JackError.h" | |||
| #include "JackCompilerDeps.h" | |||
| #include "JackTools.h" | |||
| @@ -34,40 +33,22 @@ namespace Jack | |||
| { | |||
| //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; | |||
| // 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; | |||
| } | |||
| @@ -91,24 +72,15 @@ namespace Jack | |||
| JackAudioAdapter::~JackAudioAdapter() | |||
| { | |||
| // 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; | |||
| } | |||
| void JackAudioAdapter::FreePorts() | |||
| { | |||
| int i; | |||
| for ( i = 0; i < fCaptureChannels; i++ ) | |||
| for (int i = 0; i < fAudioAdapter->GetInputs(); i++ ) | |||
| if ( 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] ) | |||
| jack_port_unregister ( fJackClient, fPlaybackPortList[i] ); | |||
| @@ -118,52 +90,30 @@ namespace Jack | |||
| 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(); | |||
| } | |||
| int JackAudioAdapter::Open() | |||
| { | |||
| int i; | |||
| 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 | |||
| 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; | |||
| } | |||
| 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; | |||
| } | |||
| @@ -177,17 +127,20 @@ namespace Jack | |||
| if ( jack_activate ( fJackClient ) < 0 ) | |||
| goto fail; | |||
| //ringbuffers and jack clients are ok, we can now open the adapter driver interface | |||
| // Ring buffer are now allocated.. | |||
| return fAudioAdapter->Open(); | |||
| fail: | |||
| FreePorts(); | |||
| fAudioAdapter->Destroy(); | |||
| return -1; | |||
| } | |||
| int JackAudioAdapter::Close() | |||
| { | |||
| return fAudioAdapter->Close(); | |||
| fAudioAdapter->Close(); | |||
| fAudioAdapter->Destroy(); | |||
| return 0; | |||
| } | |||
| } //namespace | |||
| @@ -37,12 +37,6 @@ namespace Jack | |||
| static int BufferSize ( jack_nframes_t buffer_size, 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** fPlaybackPortList; | |||
| @@ -18,6 +18,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "JackAudioAdapter.h" | |||
| #include <TargetConditionals.h> | |||
| #ifndef TARGET_OS_IPHONE | |||
| #include "JackLibSampleRateResampler.h" | |||
| #endif | |||
| #include "JackTime.h" | |||
| #include <stdio.h> | |||
| @@ -37,7 +41,7 @@ namespace Jack | |||
| 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]; | |||
| FILE* file = fopen("JackAudioAdapter.log", "w"); | |||
| @@ -54,6 +58,22 @@ namespace Jack | |||
| // 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: 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 grid\n"); | |||
| fprintf(file, "set title \"Audio adapter timing\"\n"); | |||
| @@ -64,10 +84,27 @@ namespace Jack | |||
| 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: 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 grid\n"); | |||
| fprintf(file, "set title \"Audio adapter timing\"\n"); | |||
| @@ -78,10 +115,27 @@ namespace Jack | |||
| 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: 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 grid\n"); | |||
| fprintf(file, "set title \"Audio adapter timing\"\n"); | |||
| @@ -92,35 +146,32 @@ namespace Jack | |||
| fprintf(file, buffer); | |||
| sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines"); | |||
| fprintf(file, buffer); | |||
| fclose(file); | |||
| } | |||
| #endif | |||
| void JackAudioAdapterInterface::ResetRingBuffers() | |||
| { | |||
| int i; | |||
| for (i = 0; i < fCaptureChannels; i++) | |||
| for (int i = 0; i < fCaptureChannels; i++) | |||
| fCaptureRingBuffer[i]->Reset(); | |||
| for (i = 0; i < fPlaybackChannels; i++) | |||
| for (int i = 0; i < fPlaybackChannels; i++) | |||
| 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(); | |||
| if ( !fRunning ) | |||
| { | |||
| if (!fRunning) { | |||
| // Init DLL | |||
| fRunning = true; | |||
| fHostDLL.Init ( time ); | |||
| fAdaptedDLL.Init ( time ); | |||
| fHostDLL.Init(time); | |||
| fAdaptedDLL.Init(time); | |||
| frame1 = 1; | |||
| frame2 = 1; | |||
| } | |||
| else | |||
| { | |||
| } else { | |||
| // DLL | |||
| fAdaptedDLL.IncFrame(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)); | |||
| } | |||
| } | |||
| 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 | |||
| @@ -51,8 +51,8 @@ namespace Jack | |||
| 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; | |||
| unsigned int fQuality; | |||
| unsigned int fRingbufferSize; | |||
| bool fRunning; | |||
| void ResetRingBuffers(); | |||
| void ResampleFactor ( jack_time_t& frame1, jack_time_t& frame2 ); | |||
| public: | |||
| JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, | |||
| @@ -106,6 +110,7 @@ namespace Jack | |||
| fHostDLL ( host_buffer_size, host_sample_rate ), | |||
| fAdaptedDLL ( host_buffer_size, host_sample_rate ), | |||
| fQuality(0), | |||
| fRingbufferSize(DEFAULT_RB_SIZE), | |||
| fRunning ( false ) | |||
| {} | |||
| JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, | |||
| @@ -121,38 +126,33 @@ namespace Jack | |||
| fHostDLL ( host_buffer_size, host_sample_rate ), | |||
| fAdaptedDLL ( adapted_buffer_size, adapted_sample_rate ), | |||
| fQuality(0), | |||
| fRingbufferSize(DEFAULT_RB_SIZE), | |||
| fRunning ( false ) | |||
| {} | |||
| virtual ~JackAudioAdapterInterface() | |||
| {} | |||
| void SetRingBuffers ( JackResampler** input, JackResampler** output ) | |||
| { | |||
| fCaptureRingBuffer = input; | |||
| fPlaybackRingBuffer = output; | |||
| } | |||
| bool IsRunning() | |||
| { | |||
| 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 ) | |||
| { | |||
| fHostBufferSize = buffer_size; | |||
| @@ -194,14 +194,7 @@ namespace Jack | |||
| 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 ); | |||
| @@ -225,6 +218,9 @@ namespace Jack | |||
| jack_log ( "JackAudioAdapterInterface::GetOutputs %d", 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)); | |||
| } | |||
| JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality) | |||
| :JackResampler(),fRatio(1) | |||
| JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality, unsigned int ringbuffer_size) | |||
| :JackResampler(ringbuffer_size),fRatio(1) | |||
| { | |||
| switch (quality) { | |||
| case 0: | |||
| @@ -46,7 +46,7 @@ class JackLibSampleRateResampler : public JackResampler | |||
| public: | |||
| JackLibSampleRateResampler(); | |||
| JackLibSampleRateResampler(unsigned int quality); | |||
| JackLibSampleRateResampler(unsigned int quality, unsigned int ringbuffer_size); | |||
| virtual ~JackLibSampleRateResampler(); | |||
| unsigned int ReadResample(float* buffer, unsigned int frames); | |||
| @@ -55,7 +55,7 @@ class JackLibSampleRateResampler : public JackResampler | |||
| void SetRatio(unsigned int num, unsigned int 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(); | |||
| @@ -106,18 +106,16 @@ extern "C" | |||
| 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 adapted_buffer_size, | |||
| jack_nframes_t adapted_sample_rate); | |||
| 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 | |||
| } | |||
| #endif | |||
| @@ -734,144 +732,39 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| 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 adapted_buffer_size, | |||
| jack_nframes_t 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 | |||
| 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 adapted_buffer_size, | |||
| 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) | |||
| @@ -982,30 +876,18 @@ SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) | |||
| 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; | |||
| 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; | |||
| 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.. | |||
| //#ifdef TARGET_OS_IPHONE | |||
| @@ -367,7 +367,7 @@ namespace Jack | |||
| return SOCKET_ERROR; | |||
| //get the resample factor, | |||
| jack_nframes_t time1, time2; | |||
| jack_time_t time1, time2; | |||
| ResampleFactor ( time1, time2 ); | |||
| //resample input data, | |||
| @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "JackResampler.h" | |||
| #include <stdio.h> | |||
| namespace Jack | |||
| { | |||
| @@ -28,6 +29,12 @@ JackResampler::JackResampler():fNum(1),fDenom(1) | |||
| 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() | |||
| { | |||
| if (fRingBuffer) | |||
| @@ -36,7 +43,8 @@ JackResampler::~JackResampler() | |||
| 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() | |||
| @@ -40,10 +40,12 @@ class JackResampler | |||
| jack_ringbuffer_t* fRingBuffer; | |||
| unsigned int fNum; | |||
| unsigned int fDenom; | |||
| unsigned int fRingBufferSize; | |||
| public: | |||
| JackResampler(); | |||
| JackResampler(unsigned int ringbuffer_size); | |||
| virtual ~JackResampler(); | |||
| virtual void Reset(); | |||
| @@ -255,7 +255,8 @@ typedef struct _jack_adapter jack_adapter_t; | |||
| * | |||
| * @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 adapted_buffer_size, | |||
| 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); | |||
| /** | |||
| * Push input to ringbuffer | |||
| * Push input to and pull output from ringbuffer | |||
| * | |||
| * @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 | |||
| */ | |||
| 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 | |||
| @@ -182,9 +182,15 @@ def build(bld): | |||
| netlib.includes = includes | |||
| netlib.name = 'netlib' | |||
| netlib.target = 'jacknet' | |||
| netlib.uselib = uselib | |||
| netlib.uselib = 'SAMPLERATE' | |||
| 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']: | |||
| netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../linux/JackLinuxTime.c'] | |||
| @@ -66,14 +66,19 @@ namespace Jack | |||
| fAudioInterface.fCardName = strdup ( param->value.str ); | |||
| break; | |||
| case 'r': | |||
| fAudioInterface.fFrequency = param->value.ui; | |||
| SetAdaptedSampleRate ( param->value.ui ); | |||
| break; | |||
| case 'p': | |||
| fAudioInterface.fBuffering = param->value.ui; | |||
| SetAdaptedBufferSize ( param->value.ui ); | |||
| break; | |||
| case 'q': | |||
| fQuality = param->value.ui; | |||
| break; | |||
| case 'g': | |||
| fRingbufferSize = param->value.ui; | |||
| break; | |||
| } | |||
| } | |||
| @@ -106,7 +111,7 @@ namespace Jack | |||
| int JackAlsaAdapter::Close() | |||
| { | |||
| #ifdef JACK_MONITOR | |||
| fTable.Save(); | |||
| fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); | |||
| #endif | |||
| switch ( fThread.GetStatus() ) | |||
| { | |||
| @@ -147,46 +152,15 @@ namespace Jack | |||
| bool JackAlsaAdapter::Execute() | |||
| { | |||
| //read data from audio interface | |||
| if ( fAudioInterface.read() < 0 ) | |||
| if (fAudioInterface.read() < 0) | |||
| 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 | |||
| if ( fAudioInterface.write() < 0 ) | |||
| if (fAudioInterface.write() < 0) | |||
| return false; | |||
| //reset all ringbuffers in case of failure | |||
| if ( failure ) | |||
| { | |||
| jack_error ( "JackAlsaAdapter::Execute ringbuffer failure... reset" ); | |||
| ResetRingBuffers(); | |||
| } | |||
| return true; | |||
| } | |||
| @@ -220,7 +194,7 @@ extern "C" | |||
| 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 | |||
| desc->nparams = 10; | |||
| desc->nparams = 11; | |||
| desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); | |||
| i = 0; | |||
| @@ -299,7 +273,6 @@ extern "C" | |||
| strcpy ( desc->params[i].short_desc, | |||
| "Number of playback channels (defaults to hardware max)" ); | |||
| strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | |||
| i++; | |||
| strcpy(desc->params[i].name, "quality"); | |||
| @@ -308,6 +281,14 @@ extern "C" | |||
| desc->params[i].value.ui = 0; | |||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | |||
| 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; | |||
| } | |||
| @@ -182,6 +182,17 @@ namespace Jack | |||
| fInputParams = 0; | |||
| fOutputParams = 0; | |||
| 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 ) : | |||
| @@ -369,10 +380,10 @@ namespace Jack | |||
| } | |||
| else // SND_PCM_FORMAT_S32 | |||
| { | |||
| long* buffer32b = ( long* ) fInputCardBuffer; | |||
| int32_t* buffer32b = ( int32_t* ) fInputCardBuffer; | |||
| for ( s = 0; s < fBuffering; s++ ) | |||
| 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; | |||
| case SND_PCM_ACCESS_RW_NONINTERLEAVED : | |||
| @@ -394,12 +405,12 @@ namespace Jack | |||
| } | |||
| else // SND_PCM_FORMAT_S32 | |||
| { | |||
| long* chan32b; | |||
| int32_t* chan32b; | |||
| for ( c = 0; c < fCardInputs; c++ ) | |||
| { | |||
| chan32b = ( long* ) fInputCardChannels[c]; | |||
| chan32b = ( int32_t* ) fInputCardChannels[c]; | |||
| 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; | |||
| @@ -436,13 +447,13 @@ namespace Jack | |||
| } | |||
| else // SND_PCM_FORMAT_S32 | |||
| { | |||
| long* buffer32b = ( long* ) fOutputCardBuffer; | |||
| int32_t* buffer32b = ( int32_t* ) fOutputCardBuffer; | |||
| for ( f = 0; f < fBuffering; f++ ) | |||
| { | |||
| for ( unsigned int c = 0; c < fCardOutputs; c++ ) | |||
| { | |||
| 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++ ) | |||
| { | |||
| long* chan32b = ( long* ) fOutputCardChannels[c]; | |||
| int32_t* chan32b = ( int32_t* ) fOutputCardChannels[c]; | |||
| for ( f = 0; f < fBuffering; 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); | |||
| 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++) { | |||
| 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++) { | |||
| 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; | |||
| } | |||
| 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) | |||
| { | |||
| @@ -392,6 +376,10 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | |||
| case 'q': | |||
| fQuality = param->value.ui; | |||
| break; | |||
| case 'g': | |||
| fRingbufferSize = param->value.ui; | |||
| break; | |||
| } | |||
| } | |||
| @@ -960,7 +948,7 @@ int JackCoreAudioAdapter::Open() | |||
| int JackCoreAudioAdapter::Close() | |||
| { | |||
| #ifdef JACK_MONITOR | |||
| fTable.Save(); | |||
| fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); | |||
| #endif | |||
| AudioOutputUnitStop(fAUHAL); | |||
| DisposeBuffers(); | |||
| @@ -997,7 +985,7 @@ extern "C" | |||
| 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 | |||
| desc->nparams = 11; | |||
| desc->nparams = 12; | |||
| desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); | |||
| i = 0; | |||
| @@ -1087,6 +1075,14 @@ extern "C" | |||
| desc->params[i].value.ui = 0; | |||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | |||
| 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; | |||
| } | |||
| @@ -181,6 +181,10 @@ JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample | |||
| case 'q': | |||
| fQuality = param->value.ui; | |||
| break; | |||
| case 'g': | |||
| fRingbufferSize = param->value.ui; | |||
| break; | |||
| } | |||
| } | |||
| @@ -502,10 +506,9 @@ error: | |||
| int JackOSSAdapter::Close() | |||
| { | |||
| #ifdef DEBUG | |||
| fTable.Save(); | |||
| #ifdef JACK_MONITOR | |||
| fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); | |||
| #endif | |||
| fThread.Stop(); | |||
| CloseAux(); | |||
| return 0; | |||
| @@ -600,38 +603,16 @@ int JackOSSAdapter::Write() | |||
| bool JackOSSAdapter::Execute() | |||
| { | |||
| //read data from audio interface | |||
| if (Read() < 0) | |||
| 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) | |||
| return false; | |||
| // Reset all ringbuffers in case of failure | |||
| if (failure) { | |||
| jack_error("JackOSSAdapter::Execute ringbuffer failure... reset"); | |||
| ResetRingBuffers(); | |||
| } | |||
| return true; | |||
| } | |||
| @@ -756,6 +737,14 @@ extern "C" | |||
| desc->params[i].value.ui = 0; | |||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | |||
| 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; | |||
| } | |||
| @@ -34,7 +34,7 @@ namespace Jack | |||
| 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_FS 48000 | |||
| #define OSS_DRIVER_DEF_BLKSIZE 1024 | |||
| @@ -27,47 +27,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| namespace Jack | |||
| { | |||
| int JackPortAudioAdapter::Render ( const void* inputBuffer, | |||
| void* outputBuffer, | |||
| unsigned long framesPerBuffer, | |||
| const PaStreamCallbackTimeInfo* timeInfo, | |||
| PaStreamCallbackFlags statusFlags, | |||
| void* userData) | |||
| 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(); | |||
| } | |||
| adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, framesPerBuffer); | |||
| return paContinue; | |||
| } | |||
| @@ -128,6 +96,9 @@ namespace Jack | |||
| case 'q': | |||
| fQuality = param->value.ui; | |||
| break; | |||
| case 'g': | |||
| fRingbufferSize = param->value.ui; | |||
| break; | |||
| } | |||
| } | |||
| @@ -207,7 +178,7 @@ namespace Jack | |||
| int JackPortAudioAdapter::Close() | |||
| { | |||
| #ifdef JACK_MONITOR | |||
| fTable.Save(); | |||
| fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); | |||
| #endif | |||
| jack_log ( "JackPortAudioAdapter::Close" ); | |||
| 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->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)); | |||
| i = 0; | |||
| @@ -314,7 +285,7 @@ extern "C" | |||
| 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); | |||
| i++; | |||
| strcpy(desc->params[i].name, "quality"); | |||
| 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].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; | |||
| } | |||