Commit 4c56bcb0 authored by sletz's avatar sletz
Browse files

Merge libjacknet branch.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4327 0c269be4-1314-0410-8aa9-9f06e86f4224
parents 68e5ac74 ad347033
---------------------------
Contributors
---------------------------
Dmitry Baikov
Gabriel M. Beddingfield
Steven Chamberlain
Thom Johansen
Thibault LeMeur
Tom Szilagyi
Andrzej Szombierski
Kjetil S.Matheussen
Pieter Palmers
Tim Blechmann
Marc-Olivier Barre
Nedko Arnaudov
Fernando Lopez-Lezcano
Romain Moret
Florian Faber
Michael Voigt
Torben Hohn
Paul Davis
Peter L Jones
Devin Anderson
Josh Green
Mario Lang
---------------------------
Contributors
---------------------------
Dmitry Baikov
Gabriel M. Beddingfield
Steven Chamberlain
Thom Johansen
Thibault LeMeur
Tom Szilagyi
Andrzej Szombierski
Kjetil S.Matheussen
Pieter Palmers
Tim Blechmann
Marc-Olivier Barre
Nedko Arnaudov
Fernando Lopez-Lezcano
Romain Moret
Florian Faber
Michael Voigt
Torben Hohn
Paul Davis
Peter L Jones
Devin Anderson
Josh Green
Mario Lang
Arnold Krille
Jan Engelhardt
Adrian Knoth
David Garcia Garzon
Valerio Pilo
---------------------------
......@@ -107,7 +106,7 @@ Valerio Pilo
* jack_client_has_session_callback implementation.
* Fix jdelay for new latency API.
* Check requested buffer size and limit to 1..8192 - avoids weird behaviour caused by jack_bufsize foobar.
* Check requested buffer size and limit to 1..8192 - avoids wierd behaviour caused by jack_bufsize foobar.
* jack_port_type_get_buffer_size implementation.
* Stop using alloca and allocate buffer on the heap for alsa_io.
* Rename jdelay to jack_iodelay as per Fons' request.
......@@ -1770,4 +1769,4 @@ Valerio Pilo
2006-09-03 Stephane Letz <letz@grame.fr>
* First import of version 0.58 base code
* First import of version 0.58 base code
......@@ -17,9 +17,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif
#include "JackAudioAdapter.h"
#ifndef MY_TARGET_OS_IPHONE
#include "JackLibSampleRateResampler.h"
#include "JackTime.h"
#endif
#include "JackTime.h"
#include <stdio.h>
namespace Jack
......@@ -66,11 +72,11 @@ namespace Jack
fprintf(file, buffer);
sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
fprintf(file, buffer);
fprintf(file, "\n unset multiplot\n");
fprintf(file, "\n unset multiplot\n");
fprintf(file, "set output 'AdapterTiming1.svg\n");
fprintf(file, "set terminal svg\n");
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"
......@@ -84,9 +90,9 @@ namespace Jack
fprintf(file, buffer);
fprintf(file, "unset multiplot\n");
fprintf(file, "unset output\n");
fclose(file);
// Adapter timing 2
file = fopen("AdapterTiming2.plot", "w");
fprintf(file, "set multiplot\n");
......@@ -100,11 +106,11 @@ namespace Jack
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, "\n unset multiplot\n");
fprintf(file, "set output 'AdapterTiming2.svg\n");
fprintf(file, "set terminal svg\n");
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"
......@@ -118,7 +124,7 @@ namespace Jack
fprintf(file, buffer);
fprintf(file, "unset multiplot\n");
fprintf(file, "unset output\n");
fclose(file);
// Adapter timing 3
......@@ -134,11 +140,11 @@ namespace Jack
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, "\n unset multiplot\n");
fprintf(file, "set output 'AdapterTiming3.svg\n");
fprintf(file, "set terminal svg\n");
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"
......@@ -152,7 +158,7 @@ namespace Jack
fprintf(file, buffer);
fprintf(file, "unset multiplot\n");
fprintf(file, "unset output\n");
fclose(file);
}
......@@ -162,47 +168,51 @@ namespace Jack
{
fRingbufferCurSize *= 2;
}
void JackAudioAdapterInterface::AdaptRingBufferSize()
{
if (fHostBufferSize > fAdaptedBufferSize)
fRingbufferCurSize = 4 * fHostBufferSize;
else
else
fRingbufferCurSize = 4 * fAdaptedBufferSize;
}
void JackAudioAdapterInterface::ResetRingBuffers()
{
if (fRingbufferCurSize > DEFAULT_RB_SIZE)
if (fRingbufferCurSize > DEFAULT_RB_SIZE)
fRingbufferCurSize = DEFAULT_RB_SIZE;
for (int i = 0; i < fCaptureChannels; i++)
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
for (int i = 0; i < fPlaybackChannels; i++)
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
}
void JackAudioAdapterInterface::Reset()
{
ResetRingBuffers();
fRunning = false;
}
#ifdef MY_TARGET_OS_IPHONE
void JackAudioAdapterInterface::Create()
{}
#else
void JackAudioAdapterInterface::Create()
{
//ringbuffers
fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
if (fAdaptative) {
AdaptRingBufferSize();
jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
} else {
if (fRingbufferCurSize > DEFAULT_RB_SIZE)
if (fRingbufferCurSize > DEFAULT_RB_SIZE)
fRingbufferCurSize = DEFAULT_RB_SIZE;
jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
}
for (int i = 0; i < fCaptureChannels; i++ ) {
fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
......@@ -211,12 +221,13 @@ namespace Jack
fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
}
if (fCaptureChannels > 0)
jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
if (fPlaybackChannels > 0)
jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
}
#endif
void JackAudioAdapterInterface::Destroy()
{
......@@ -228,39 +239,45 @@ namespace Jack
delete[] fCaptureRingBuffer;
delete[] fPlaybackRingBuffer;
}
int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
{
bool failure = false;
fRunning = true;
// Finer estimation of the position in the ringbuffer
int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
double ratio = 1;
// TODO : done like this just to avoid crash when input only or output only...
if (fCaptureChannels > 0)
ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
else if (fPlaybackChannels > 0)
ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
#ifdef JACK_MONITOR
if (fCaptureRingBuffer[0] != NULL)
if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL)
fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
#endif
// Push/pull from ringbuffer
for (int i = 0; i < fCaptureChannels; i++) {
fCaptureRingBuffer[i]->SetRatio(ratio);
if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames)
failure = true;
if (inputBuffer[i]) {
if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) {
failure = true;
}
}
}
for (int i = 0; i < fPlaybackChannels; i++) {
fPlaybackRingBuffer[i]->SetRatio(1/ratio);
if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames)
failure = true;
if (outputBuffer[i]) {
if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) {
failure = true;
}
}
}
// Reset all ringbuffers in case of failure
if (failure) {
......@@ -276,26 +293,32 @@ namespace Jack
}
}
int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
{
fPullAndPushTime = GetMicroSeconds();
if (!fRunning)
return 0;
int res = 0;
// Push/pull from ringbuffer
for (int i = 0; i < fCaptureChannels; i++) {
if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames)
res = -1;
if (inputBuffer[i]) {
if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) {
res = -1;
}
}
}
for (int i = 0; i < fPlaybackChannels; i++) {
if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames)
res = -1;
if (outputBuffer[i]) {
if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) {
res = -1;
}
}
}
return res;
}
} // namespace
......@@ -102,7 +102,7 @@ namespace Jack
public:
JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ):
JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE):
fCaptureChannels ( 0 ),
fPlaybackChannels ( 0 ),
fHostBufferSize ( buffer_size ),
......@@ -112,19 +112,37 @@ namespace Jack
fPIControler(sample_rate / sample_rate, 256),
fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL),
fQuality(0),
fRingbufferCurSize(DEFAULT_ADAPTATIVE_SIZE),
fRingbufferCurSize(ring_buffer_size),
fPullAndPushTime(0),
fRunning(false),
fAdaptative(true)
{}
JackAudioAdapterInterface ( jack_nframes_t host_buffer_size,
jack_nframes_t host_sample_rate,
jack_nframes_t adapted_buffer_size,
jack_nframes_t adapted_sample_rate,
jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE ) :
fCaptureChannels ( 0 ),
fPlaybackChannels ( 0 ),
fHostBufferSize ( host_buffer_size ),
fHostSampleRate ( host_sample_rate ),
fAdaptedBufferSize ( adapted_buffer_size),
fAdaptedSampleRate ( adapted_sample_rate ),
fPIControler(host_sample_rate / host_sample_rate, 256),
fQuality(0),
fRingbufferCurSize(ring_buffer_size),
fPullAndPushTime(0),
fRunning(false),
fAdaptative(true)
{}
virtual ~JackAudioAdapterInterface()
{}
virtual void Reset();
void Create();
void Destroy();
virtual void Create();
virtual void Destroy();
virtual int Open()
{
......@@ -194,18 +212,18 @@ namespace Jack
int GetInputs()
{
jack_log ( "JackAudioAdapterInterface::GetInputs %d", fCaptureChannels );
//jack_log("JackAudioAdapterInterface::GetInputs %d", fCaptureChannels);
return fCaptureChannels;
}
int GetOutputs()
{
jack_log ( "JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels );
//jack_log ("JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels);
return fPlaybackChannels;
}
int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int inNumberFrames);
int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int inNumberFrames);
int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames);
int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames);
};
......
......@@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
......@@ -34,7 +34,7 @@ namespace Jack
JackEngineProfiling::JackEngineProfiling():fAudioCycle(0),fMeasuredClient(0)
{
jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024));
// Force memory page in
memset(fProfileTable, 0, sizeof(fProfileTable));
}
......@@ -47,32 +47,32 @@ JackEngineProfiling::~JackEngineProfiling()
if (!fStream.is_open()) {
jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file");
} else {
// For each measured point
for (int i = 2; i < TIME_POINTS; i++) {
// Driver timing values
long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
if (d1 <= 0 || fProfileTable[i].fAudioCycle <= 0)
continue; // Skip non valid cycles
// Print driver delta and end cycle
fStream << d1 << "\t" << d2 << "\t";
// For each measured client
for (unsigned int j = 0; j < fMeasuredClient; j++) {
for (unsigned int j = 0; j < fMeasuredClient; j++) {
int ref = fIntervalTable[j].fRefNum;
// Is valid client cycle
if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) {
// Is valid client cycle
if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) {
long d5 = long(fProfileTable[i].fClientTable[ref].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
long d6 = long(fProfileTable[i].fClientTable[ref].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
long d7 = long(fProfileTable[i].fClientTable[ref].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
fStream << ref << "\t" ;
fStream << ((d5 > 0) ? d5 : 0) << "\t";
fStream << ((d6 > 0) ? d6 : 0) << "\t" ;
......@@ -80,57 +80,57 @@ JackEngineProfiling::~JackEngineProfiling()
fStream << ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0) << "\t" ;
fStream << ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0) << "\t" ;
fStream << fProfileTable[i].fClientTable[ref].fStatus << "\t" ;;
} else { // Print tabs
fStream << "\t \t \t \t \t \t \t";
}
}
// Terminate line
fStream << std::endl;
}
}
// Driver period
std::ofstream fStream1("Timing1.plot", std::ios_base::ate);
if (!fStream1.is_open()) {
jack_error("JackEngineProfiling::Save cannot open Timing1.plot file");
} else {
fStream1 << "set grid\n";
fStream1 << "set title \"Audio driver timing\"\n";
fStream1 << "set xlabel \"audio cycles\"\n";
fStream1 << "set ylabel \"usec\"\n";
fStream1 << "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n";
fStream1 << "set output 'Timing1.svg\n";
fStream1 << "set terminal svg\n";
fStream1 << "set grid\n";
fStream1 << "set title \"Audio driver timing\"\n";
fStream1 << "set xlabel \"audio cycles\"\n";
fStream1 << "set ylabel \"usec\"\n";
fStream1 << "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n";
fStream1 << "unset output\n";
fStream1 << "unset output\n";
}
// Driver end date
std::ofstream fStream2("Timing2.plot", std::ios_base::ate);
if (!fStream2.is_open()) {
jack_error("JackEngineProfiling::Save cannot open Timing2.plot file");
} else {
fStream2 << "set grid\n";
fStream2 << "set title \"Driver end date\"\n";
fStream2 << "set xlabel \"audio cycles\"\n";
fStream2 << "set ylabel \"usec\"\n";
fStream2 << "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n";
fStream2 << "set output 'Timing2.svg\n";
fStream2 << "set terminal svg\n";
fStream2 << "set grid\n";
fStream2 << "set title \"Driver end date\"\n";
fStream2 << "set xlabel \"audio cycles\"\n";
......@@ -138,15 +138,15 @@ JackEngineProfiling::~JackEngineProfiling()
fStream2 << "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n";
fStream2 << "unset output\n";
}
// Clients end date
if (fMeasuredClient > 0) {
std::ofstream fStream3("Timing3.plot", std::ios_base::ate);
if (!fStream3.is_open()) {
jack_error("JackEngineProfiling::Save cannot open Timing3.plot file");
} else {
fStream3 << "set multiplot\n";
fStream3 << "set grid\n";
fStream3 << "set title \"Clients end date\"\n";
......@@ -170,11 +170,11 @@ JackEngineProfiling::~JackEngineProfiling()
fStream3 << "\"JackEngineProfiling.log\" using " << ((i + 1) * 7) - 1 << " title \"" << fIntervalTable[i].fName << "\" with lines,";
}
}
fStream3 << "\n unset multiplot\n";
fStream3 << "\n unset multiplot\n";
fStream3 << "set output 'Timing3.svg\n";
fStream3 << "set terminal svg\n";
fStream3 << "set multiplot\n";
fStream3 << "set grid\n";
fStream3 << "set title \"Clients end date\"\n";
......@@ -206,11 +206,11 @@ JackEngineProfiling::~JackEngineProfiling()
// Clients scheduling
if (fMeasuredClient > 0) {
std::ofstream fStream4("Timing4.plot", std::ios_base::ate);
if (!fStream4.is_open()) {
jack_error("JackEngineProfiling::Save cannot open Timing4.plot file");
} else {
fStream4 << "set multiplot\n";
fStream4 << "set grid\n";
fStream4 << "set title \"Clients scheduling latency\"\n";
......@@ -224,11 +224,11 @@ JackEngineProfiling::~JackEngineProfiling()
fStream4 << "\"JackEngineProfiling.log\" using " << ((i + 1) * 7) << " title \"" << fIntervalTable[i].fName << "\" with lines,";
}
}
fStream4 << "\n unset multiplot\n";
fStream4 << "\n unset multiplot\n";
fStream4 << "set output 'Timing4.svg\n";
fStream4 << "set terminal svg\n";
fStream4 << "set multiplot\n";
fStream4 << "set grid\n";
fStream4 << "set title \"Clients scheduling latency\"\n";
......@@ -246,7 +246,7 @@ JackEngineProfiling::~JackEngineProfiling()
fStream4 << "unset output\n";
}
}
// Clients duration
if (fMeasuredClient > 0) {
std::ofstream fStream5("Timing5.plot", std::ios_base::ate);
......@@ -254,7 +254,7 @@ JackEngineProfiling::~JackEngineProfiling()
if (!fStream5.is_open()) {
jack_error("JackEngineProfiling::Save cannot open Timing5.plot file");
} else {