Browse Source

Merge branch 'netjack2-latency'

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4502 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.9.8
sletz 14 years ago
parent
commit
b7293b8be6
11 changed files with 64 additions and 235 deletions
  1. +3
    -3
      common/JackNetAPI.cpp
  2. +3
    -11
      common/JackNetAdapter.cpp
  3. +13
    -45
      common/JackNetDriver.cpp
  4. +1
    -1
      common/JackNetDriver.h
  5. +6
    -80
      common/JackNetInterface.cpp
  6. +4
    -6
      common/JackNetInterface.h
  7. +5
    -42
      common/JackNetManager.cpp
  8. +3
    -14
      common/JackNetTool.cpp
  9. +1
    -1
      common/JackNetTool.h
  10. +1
    -8
      common/jack/net.h
  11. +24
    -24
      macosx/iphone/main_slave.mm

+ 3
- 3
common/JackNetAPI.cpp View File

@@ -59,7 +59,7 @@ extern "C"
int time_out; // in millisecond, -1 means in infinite
int encoder;
int kbps; // KB per second for CELT encoder
char mode;
int latency;

} jack_slave_t;

@@ -251,7 +251,7 @@ struct JackNetExtMaster : public JackNetMasterInterface {
result->midi_input = fParams.fSendMidiChannels;
result->midi_output = fParams.fReturnMidiChannels;
result->mtu = fParams.fMtu;
result->mode = fParams.fNetworkMode;
result->latency = fParams.fNetworkLatency;
return 0;

error:
@@ -472,7 +472,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf
fParams.fReturnAudioChannels = request->audio_output;
fParams.fSendMidiChannels = request->midi_input;
fParams.fReturnMidiChannels = request->midi_output;
fParams.fNetworkMode = request->mode;
fParams.fNetworkLatency = request->latency;
fParams.fSampleEncoder = request->encoder;
fParams.fKBps = request->kbps;
fParams.fSlaveSyncMode = 1;


+ 3
- 11
common/JackNetAdapter.cpp View File

@@ -49,7 +49,7 @@ namespace Jack
fParams.fSampleRate = sample_rate;
fParams.fPeriodSize = buffer_size;
fParams.fSlaveSyncMode = 1;
fParams.fNetworkMode = 's';
fParams.fNetworkLatency = 2;
fParams.fSampleEncoder = JackFloatEncoder;
fJackClient = jack_client;

@@ -94,16 +94,8 @@ namespace Jack
}
break;
#endif
case 'm' :
if (strcmp(param->value.str, "normal") == 0) {
fParams.fNetworkMode = 'n';
} else if (strcmp(param->value.str, "slow") == 0) {
fParams.fNetworkMode = 's';
} else if (strcmp(param->value.str, "fast") == 0) {
fParams.fNetworkMode = 'f';
} else {
jack_error("Unknown network mode, using 'normal' mode.");
}
case 'l' :
fParams.fNetworkLatency = param->value.i;
break;
case 'q':
fQuality = param->value.ui;


+ 13
- 45
common/JackNetDriver.cpp View File

@@ -29,7 +29,7 @@ namespace Jack
{
JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports,
char* net_name, uint transport_sync, char network_mode, int celt_encoding)
char* net_name, uint transport_sync, int network_latency, int celt_encoding)
: JackAudioDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port)
{
jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port);
@@ -50,7 +50,7 @@ namespace Jack
strcpy(fParams.fName, net_name);
fSocket.GetName(fParams.fSlaveNetName);
fParams.fTransportSync = transport_sync;
fParams.fNetworkMode = network_mode;
fParams.fNetworkLatency = network_latency;
fSendTransportData.fState = -1;
fReturnTransportData.fState = -1;
fLastTransportState = -1;
@@ -185,20 +185,7 @@ namespace Jack
plot_name = string(fParams.fName);
plot_name += string("_slave");
plot_name += (fEngineControl->fSyncMode) ? string("_sync") : string("_async");
switch (fParams.fNetworkMode)
{
case 's' :
plot_name += string("_slow");
break;

case 'n' :
plot_name += string("_normal");
break;

case 'f' :
plot_name += string("_fast");
break;
}
plot_name += string("_latency");
fNetTimeMon = new JackGnuPlotMonitor<float>(128, 5, plot_name);
string net_time_mon_fields[] =
{
@@ -305,18 +292,7 @@ namespace Jack
port = fGraphManager->GetPort(port_index);
port->SetAlias(alias);
//port latency
switch (fParams.fNetworkMode)
{
case 'f' :
range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize;
break;
case 'n' :
range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
break;
case 's' :
range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
break;
}
range.min = range.max = (fParams.fNetworkLatency * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
port->SetLatencyRange(JackPlaybackLatency, &range);
fPlaybackPortList[audio_port_index] = port_index;
jack_log("JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency());
@@ -354,18 +330,7 @@ namespace Jack
}
port = fGraphManager->GetPort(port_index);
//port latency
switch (fParams.fNetworkMode)
{
case 'f' :
range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize;
break;
case 'n' :
range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
break;
case 's' :
range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
break;
}
range.min = range.max = (fParams.fNetworkLatency * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
port->SetLatencyRange(JackPlaybackLatency, &range);
fMidiPlaybackPortList[midi_port_index] = port_index;
jack_log("JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency());
@@ -658,8 +623,8 @@ namespace Jack
value.ui = 1U;
jack_driver_descriptor_add_parameter(desc, &filler, "transport_sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL);

strcpy(value.str, "slow");
jack_driver_descriptor_add_parameter(desc, &filler, "mode", 'm', JackDriverParamString, &value, NULL, "Slow, Normal or Fast mode.", NULL);
value.ui = 2U;
jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL);

return desc;
}
@@ -679,7 +644,7 @@ namespace Jack
int midi_output_ports = 0;
int celt_encoding = -1;
bool monitor = false;
char network_mode = 's';
int network_latency = 2;
const JSList* node;
const jack_driver_param_t* param;

@@ -732,7 +697,9 @@ namespace Jack
case 't' :
transport_sync = param->value.ui;
break;
case 'm' :
case 'l' :
network_latency = param->value.ui;
/*
if (strcmp(param->value.str, "normal") == 0)
network_mode = 'n';
else if (strcmp(param->value.str, "slow") == 0)
@@ -741,6 +708,7 @@ namespace Jack
network_mode = 'f';
else
jack_error("Unknown network mode, using 'normal' mode.");
*/
break;
}
}
@@ -751,7 +719,7 @@ namespace Jack
new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
midi_input_ports, midi_output_ports,
net_name, transport_sync,
network_mode, celt_encoding));
network_latency, celt_encoding));
if (driver->Open(period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, monitor, "from_master_", "to_master_", 0, 0) == 0) {
return driver;
} else {


+ 1
- 1
common/JackNetDriver.h View File

@@ -72,7 +72,7 @@ namespace Jack

JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
char* net_name, uint transport_sync, char network_master_mode, int celt_encoding);
char* net_name, uint transport_sync, int network_latency, int celt_encoding);
~JackNetDriver();

int Open(jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing,


+ 6
- 80
common/JackNetInterface.cpp View File

@@ -107,7 +107,7 @@ namespace Jack
jack_log("midi_size %f", midi_size);

//bufsize = sync + audio + midi
int bufsize = MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int) midi_size);
int bufsize = NETWORK_MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int) midi_size);
jack_log("SetNetBufferSize bufsize = %d", bufsize);

//tx buffer
@@ -206,28 +206,6 @@ namespace Jack
return true;
}

/*
int JackNetMasterInterface::SetRxTimeout()
{
jack_log("JackNetMasterInterface::SetRxTimeout");

float time = 0;

//slow or normal mode, short timeout on recv (2 audio subcycles)
if ((fParams.fNetworkMode == 's') || (fParams.fNetworkMode == 'n')) {
time = 2000000.f * ((fNetAudioCaptureBuffer)
? fNetAudioCaptureBuffer->GetCycleDuration()
: (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleDuration() : 0);
}
//fast mode, wait for 75% of the entire cycle duration
else if (fParams.fNetworkMode == 'f') {
time = 750000.f * (static_cast<float>(fParams.fPeriodSize) / static_cast<float>(fParams.fSampleRate));
}

return fSocket.SetTimeOut(static_cast<int>(time));
}
*/

int JackNetMasterInterface::SetRxTimeout()
{
jack_log("JackNetMasterInterface::SetRxTimeout");
@@ -405,11 +383,7 @@ namespace Jack

bool JackNetMasterInterface::IsSynched()
{
if (fParams.fNetworkMode == 's') {
return (fCycleOffset < (CYCLE_OFFSET_SLOW + 1));
} else {
return true;
}
return (fCycleOffset <= fMaxCycleOffset);
}

int JackNetMasterInterface::SyncSend()
@@ -487,58 +461,10 @@ namespace Jack
if (fNetAudioCaptureBuffer)
fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts);

switch (fParams.fNetworkMode)
{
case 's' :
//slow mode : allow to use full bandwidth and heavy process on the slave
// - extra latency is set to two cycles, one cycle for send/receive operations + one cycle for heavy process on the slave
// - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master
// - this mode will skip the two first cycles, thus it lets time for data to be processed and queued on the socket rx buffer
//the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process)

if (fCycleOffset < CYCLE_OFFSET_SLOW) {
return 0;
} else {
rx_bytes = Recv(rx_head->fPacketSize, 0);
}

/*
rx_bytes = Recv(rx_head->fPacketSize, 0);

if (fCycleOffset != fLastfCycleOffset)
jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
fLastfCycleOffset = fCycleOffset;
*/

break;

case 'n' :
//normal use of the network :
// - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth
// - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter
// - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it
if (fCycleOffset < CYCLE_OFFSET_NORMAL) {
return 0;
} else {
rx_bytes = Recv(rx_head->fPacketSize, 0);
}

if (fCycleOffset > CYCLE_OFFSET_NORMAL) {
jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
}
break;

case 'f' :
//fast mode suppose the network bandwith is larger than required for the transmission (only a few channels for example)
// - packets can be quickly received, quickly is here relative to the cycle duration
// - here, receive data, we can't keep it queued on the rx buffer,
// - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow
rx_bytes = Recv(rx_head->fPacketSize, 0);

if (fCycleOffset > CYCLE_OFFSET_FAST) {
jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
}
break;
if (fCycleOffset < fMaxCycleOffset) {
return 0;
} else {
rx_bytes = Recv(rx_head->fPacketSize, 0);
}

fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;


+ 4
- 6
common/JackNetInterface.h View File

@@ -107,6 +107,7 @@ namespace Jack

bool fRunning;
int fCycleOffset;
int fMaxCycleOffset;
int fLastfCycleOffset;

bool Init();
@@ -133,7 +134,7 @@ namespace Jack
void FatalError();

public:
JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCycleOffset(0), fLastfCycleOffset(0)
JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCycleOffset(0), fMaxCycleOffset(0), fLastfCycleOffset(0)
{}
JackNetMasterInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip )
: JackNetInterface ( params, socket, multicast_ip )
@@ -223,10 +224,7 @@ namespace Jack
#define MASTER_INIT_TIMEOUT 1000000 // in usec
#define SLAVE_INIT_TIMEOUT 1000000 // in usec

#define CYCLE_OFFSET_FAST 0
#define CYCLE_OFFSET_NORMAL 1
#define CYCLE_OFFSET_SLOW 2
//#define CYCLE_OFFSET_SLOW 30
#define MAX_LATENCY CYCLE_OFFSET_SLOW * 4
#define CYCLE_OFFSET_SLOW 10
#define NETWORK_MAX_LATENCY CYCLE_OFFSET_SLOW

#endif

+ 5
- 42
common/JackNetManager.cpp View File

@@ -64,18 +64,7 @@ namespace Jack
plot_name = string ( fParams.fName );
plot_name += string ( "_master" );
plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" );
switch ( fParams.fNetworkMode )
{
case 's' :
plot_name += string ( "_slow" );
break;
case 'n' :
plot_name += string ( "_normal" );
break;
case 'f' :
plot_name += string ( "_fast" );
break;
}
plot_name += string ( "_latency" );
fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
string net_time_mon_fields[] =
{
@@ -196,21 +185,8 @@ namespace Jack
if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
return -1;
//port latency
switch ( fParams.fNetworkMode )
{
case 'f' :
range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency;
jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
break;
case 'n' :
range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
break;
case 's' :
range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
break;
}
range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
}

//midi
@@ -229,21 +205,8 @@ namespace Jack
if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
return -1;
//port latency
switch ( fParams.fNetworkMode )
{
case 'f' :
range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency;
jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
break;
case 'n' :
range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
break;
case 's' :
range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
break;
}
range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
}
return 0;
}


+ 3
- 14
common/JackNetTool.cpp View File

@@ -690,6 +690,7 @@ namespace Jack
dst_params->fPeriodSize = htonl(src_params->fPeriodSize);
dst_params->fSampleEncoder = htonl(src_params->fSampleEncoder);
dst_params->fSlaveSyncMode = htonl(src_params->fSlaveSyncMode);
dst_params->fNetworkLatency = htonl(src_params->fNetworkLatency);
}

SERVER_EXPORT void SessionParamsNToH(session_params_t* src_params, session_params_t* dst_params)
@@ -707,6 +708,7 @@ namespace Jack
dst_params->fPeriodSize = ntohl(src_params->fPeriodSize);
dst_params->fSampleEncoder = ntohl(src_params->fSampleEncoder);
dst_params->fSlaveSyncMode = ntohl(src_params->fSlaveSyncMode);
dst_params->fNetworkLatency = ntohl(src_params->fNetworkLatency);
}

SERVER_EXPORT void SessionParamsDisplay(session_params_t* params)
@@ -725,19 +727,6 @@ namespace Jack
break;
}

char mode[8];
switch (params->fNetworkMode)
{
case 's' :
strcpy(mode, "slow");
break;
case 'n' :
strcpy(mode, "normal");
break;
case 'f' :
strcpy(mode, "fast");
break;
}
jack_info("**************** Network parameters ****************");
jack_info("Name : %s", params->fName);
jack_info("Protocol revision : %d", params->fProtocolVersion);
@@ -750,6 +739,7 @@ namespace Jack
jack_info("Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels);
jack_info("Sample rate : %u frames per second", params->fSampleRate);
jack_info("Period size : %u frames per period", params->fPeriodSize);
jack_info("Network latency : %u cycles", params->fNetworkLatency);
switch (params->fSampleEncoder) {
case (JackFloatEncoder):
jack_info("SampleEncoder : %s", "Float");
@@ -763,7 +753,6 @@ namespace Jack
break;
};
jack_info("Slave mode : %s", (params->fSlaveSyncMode) ? "sync" : "async");
jack_info("Network mode : %s", mode);
jack_info("****************************************************");
}



+ 1
- 1
common/JackNetTool.h View File

@@ -101,7 +101,7 @@ namespace Jack
uint32_t fSampleEncoder; //samples encoder
uint32_t fKBps; //KB per second for CELT encoder
uint32_t fSlaveSyncMode; //is the slave in sync mode ?
char fNetworkMode; //fast, normal or slow mode
uint32_t fNetworkLatency; //network latency
};

//net status **********************************************************************************


+ 1
- 8
common/jack/net.h View File

@@ -35,13 +35,6 @@ extern "C"

#define SOCKET_ERROR -1

enum JackNetMode {

JackFastMode = 'f',
JackNormalMode = 'n',
JackSlowMode = 's',
};

enum JackNetEncoder {

JackFloatEncoder = 0, // Samples are transmitted as float
@@ -59,7 +52,7 @@ typedef struct {
int time_out; // in second, -1 means in infinite
int encoder; // Encoder type (one of JackNetEncoder)
int kbps; // KB per second for CELT encoder
char mode; // one of JackNetMode
int latency; // network latency

} jack_slave_t;



+ 24
- 24
macosx/iphone/main_slave.mm View File

@@ -21,18 +21,18 @@ int buffer_size;
int sample_rate;

static int net_process(jack_nframes_t buffer_size,
int audio_input,
float** audio_input_buffer,
int audio_input,
float** audio_input_buffer,
int midi_input,
void** midi_input_buffer,
int audio_output,
float** audio_output_buffer,
int midi_output,
void** midi_output_buffer,
float** audio_output_buffer,
int midi_output,
void** midi_output_buffer,
void* data)
{
jack_adapter_pull_and_push(adapter, audio_output_buffer, audio_input_buffer, buffer_size);
// Process input, produce output
if (audio_input == audio_output) {
// Copy net input to net output
@@ -59,10 +59,10 @@ static void SlaveAudioCallback(int frames, float** inputs, float** outputs, void
#define WIFI_MTU 1500

int main(int argc, char *argv[]) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
jack_slave_t request = { NUM_OUTPUT, NUM_INPUT, 0, 0, WIFI_MTU, -1, JackCeltEncoder, 128, JackSlowMode };
jack_slave_t request = { NUM_OUTPUT, NUM_INPUT, 0, 0, WIFI_MTU, -1, JackCeltEncoder, 128, 2 };
jack_master_t result;

//if ((net = jack_net_slave_open("169.254.112.119", DEFAULT_PORT, "iPhone", &request, &result)) == 0) {
@@ -70,41 +70,41 @@ int main(int argc, char *argv[]) {
printf("jack_net_slave_open error..\n");
return -1;
}
if ((adapter = jack_create_adapter(NUM_INPUT,
NUM_OUTPUT,
result.buffer_size,
result.sample_rate,
result.buffer_size,
if ((adapter = jack_create_adapter(NUM_INPUT,
NUM_OUTPUT,
result.buffer_size,
result.sample_rate,
result.buffer_size,
result.sample_rate)) == 0) {
return -1;
}
TiPhoneCoreAudioRenderer audio_device(NUM_INPUT, NUM_OUTPUT);
jack_set_net_slave_process_callback(net, net_process, NULL);
jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL);
if (jack_net_slave_activate(net) != 0) {
return -1;
}
if (audio_device.Open(result.buffer_size, result.sample_rate) < 0) {
return -1;
}
audio_device.SetAudioCallback(SlaveAudioCallback, NULL);
if (audio_device.Start() < 0) {
return -1;
}
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
audio_device.Stop();
audio_device.Close();
// Wait for application end
jack_net_slave_deactivate(net);
jack_net_slave_close(net);


Loading…
Cancel
Save