git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4502 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
| @@ -59,7 +59,7 @@ extern "C" | |||||
| int time_out; // in millisecond, -1 means in infinite | int time_out; // in millisecond, -1 means in infinite | ||||
| int encoder; | int encoder; | ||||
| int kbps; // KB per second for CELT encoder | int kbps; // KB per second for CELT encoder | ||||
| char mode; | |||||
| int latency; | |||||
| } jack_slave_t; | } jack_slave_t; | ||||
| @@ -251,7 +251,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| result->midi_input = fParams.fSendMidiChannels; | result->midi_input = fParams.fSendMidiChannels; | ||||
| result->midi_output = fParams.fReturnMidiChannels; | result->midi_output = fParams.fReturnMidiChannels; | ||||
| result->mtu = fParams.fMtu; | result->mtu = fParams.fMtu; | ||||
| result->mode = fParams.fNetworkMode; | |||||
| result->latency = fParams.fNetworkLatency; | |||||
| return 0; | return 0; | ||||
| error: | error: | ||||
| @@ -472,7 +472,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| fParams.fReturnAudioChannels = request->audio_output; | fParams.fReturnAudioChannels = request->audio_output; | ||||
| fParams.fSendMidiChannels = request->midi_input; | fParams.fSendMidiChannels = request->midi_input; | ||||
| fParams.fReturnMidiChannels = request->midi_output; | fParams.fReturnMidiChannels = request->midi_output; | ||||
| fParams.fNetworkMode = request->mode; | |||||
| fParams.fNetworkLatency = request->latency; | |||||
| fParams.fSampleEncoder = request->encoder; | fParams.fSampleEncoder = request->encoder; | ||||
| fParams.fKBps = request->kbps; | fParams.fKBps = request->kbps; | ||||
| fParams.fSlaveSyncMode = 1; | fParams.fSlaveSyncMode = 1; | ||||
| @@ -49,7 +49,7 @@ namespace Jack | |||||
| fParams.fSampleRate = sample_rate; | fParams.fSampleRate = sample_rate; | ||||
| fParams.fPeriodSize = buffer_size; | fParams.fPeriodSize = buffer_size; | ||||
| fParams.fSlaveSyncMode = 1; | fParams.fSlaveSyncMode = 1; | ||||
| fParams.fNetworkMode = 's'; | |||||
| fParams.fNetworkLatency = 2; | |||||
| fParams.fSampleEncoder = JackFloatEncoder; | fParams.fSampleEncoder = JackFloatEncoder; | ||||
| fJackClient = jack_client; | fJackClient = jack_client; | ||||
| @@ -94,16 +94,8 @@ namespace Jack | |||||
| } | } | ||||
| break; | break; | ||||
| #endif | #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; | break; | ||||
| case 'q': | case 'q': | ||||
| fQuality = param->value.ui; | fQuality = param->value.ui; | ||||
| @@ -29,7 +29,7 @@ namespace Jack | |||||
| { | { | ||||
| JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | 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, | 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) | : JackAudioDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) | ||||
| { | { | ||||
| jack_log("JackNetDriver::JackNetDriver ip %s, port %d", 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); | strcpy(fParams.fName, net_name); | ||||
| fSocket.GetName(fParams.fSlaveNetName); | fSocket.GetName(fParams.fSlaveNetName); | ||||
| fParams.fTransportSync = transport_sync; | fParams.fTransportSync = transport_sync; | ||||
| fParams.fNetworkMode = network_mode; | |||||
| fParams.fNetworkLatency = network_latency; | |||||
| fSendTransportData.fState = -1; | fSendTransportData.fState = -1; | ||||
| fReturnTransportData.fState = -1; | fReturnTransportData.fState = -1; | ||||
| fLastTransportState = -1; | fLastTransportState = -1; | ||||
| @@ -185,20 +185,7 @@ namespace Jack | |||||
| plot_name = string(fParams.fName); | plot_name = string(fParams.fName); | ||||
| plot_name += string("_slave"); | plot_name += string("_slave"); | ||||
| plot_name += (fEngineControl->fSyncMode) ? string("_sync") : string("_async"); | 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); | fNetTimeMon = new JackGnuPlotMonitor<float>(128, 5, plot_name); | ||||
| string net_time_mon_fields[] = | string net_time_mon_fields[] = | ||||
| { | { | ||||
| @@ -305,18 +292,7 @@ namespace Jack | |||||
| port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
| port->SetAlias(alias); | port->SetAlias(alias); | ||||
| //port latency | //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); | port->SetLatencyRange(JackPlaybackLatency, &range); | ||||
| fPlaybackPortList[audio_port_index] = port_index; | 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()); | 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 = fGraphManager->GetPort(port_index); | ||||
| //port latency | //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); | port->SetLatencyRange(JackPlaybackLatency, &range); | ||||
| fMidiPlaybackPortList[midi_port_index] = port_index; | 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()); | 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; | value.ui = 1U; | ||||
| jack_driver_descriptor_add_parameter(desc, &filler, "transport_sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); | 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; | return desc; | ||||
| } | } | ||||
| @@ -679,7 +644,7 @@ namespace Jack | |||||
| int midi_output_ports = 0; | int midi_output_ports = 0; | ||||
| int celt_encoding = -1; | int celt_encoding = -1; | ||||
| bool monitor = false; | bool monitor = false; | ||||
| char network_mode = 's'; | |||||
| int network_latency = 2; | |||||
| const JSList* node; | const JSList* node; | ||||
| const jack_driver_param_t* param; | const jack_driver_param_t* param; | ||||
| @@ -732,7 +697,9 @@ namespace Jack | |||||
| case 't' : | case 't' : | ||||
| transport_sync = param->value.ui; | transport_sync = param->value.ui; | ||||
| break; | break; | ||||
| case 'm' : | |||||
| case 'l' : | |||||
| network_latency = param->value.ui; | |||||
| /* | |||||
| if (strcmp(param->value.str, "normal") == 0) | if (strcmp(param->value.str, "normal") == 0) | ||||
| network_mode = 'n'; | network_mode = 'n'; | ||||
| else if (strcmp(param->value.str, "slow") == 0) | else if (strcmp(param->value.str, "slow") == 0) | ||||
| @@ -741,6 +708,7 @@ namespace Jack | |||||
| network_mode = 'f'; | network_mode = 'f'; | ||||
| else | else | ||||
| jack_error("Unknown network mode, using 'normal' mode."); | jack_error("Unknown network mode, using 'normal' mode."); | ||||
| */ | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -751,7 +719,7 @@ namespace Jack | |||||
| new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, | new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, | ||||
| midi_input_ports, midi_output_ports, | midi_input_ports, midi_output_ports, | ||||
| net_name, transport_sync, | 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) { | 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; | return driver; | ||||
| } else { | } else { | ||||
| @@ -72,7 +72,7 @@ namespace Jack | |||||
| JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | 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, | 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(); | ~JackNetDriver(); | ||||
| int Open(jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing, | int Open(jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing, | ||||
| @@ -107,7 +107,7 @@ namespace Jack | |||||
| jack_log("midi_size %f", midi_size); | jack_log("midi_size %f", midi_size); | ||||
| //bufsize = sync + audio + midi | //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); | jack_log("SetNetBufferSize bufsize = %d", bufsize); | ||||
| //tx buffer | //tx buffer | ||||
| @@ -206,28 +206,6 @@ namespace Jack | |||||
| return true; | 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() | int JackNetMasterInterface::SetRxTimeout() | ||||
| { | { | ||||
| jack_log("JackNetMasterInterface::SetRxTimeout"); | jack_log("JackNetMasterInterface::SetRxTimeout"); | ||||
| @@ -405,11 +383,7 @@ namespace Jack | |||||
| bool JackNetMasterInterface::IsSynched() | bool JackNetMasterInterface::IsSynched() | ||||
| { | { | ||||
| if (fParams.fNetworkMode == 's') { | |||||
| return (fCycleOffset < (CYCLE_OFFSET_SLOW + 1)); | |||||
| } else { | |||||
| return true; | |||||
| } | |||||
| return (fCycleOffset <= fMaxCycleOffset); | |||||
| } | } | ||||
| int JackNetMasterInterface::SyncSend() | int JackNetMasterInterface::SyncSend() | ||||
| @@ -487,58 +461,10 @@ namespace Jack | |||||
| if (fNetAudioCaptureBuffer) | if (fNetAudioCaptureBuffer) | ||||
| fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); | 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; | fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | ||||
| @@ -107,6 +107,7 @@ namespace Jack | |||||
| bool fRunning; | bool fRunning; | ||||
| int fCycleOffset; | int fCycleOffset; | ||||
| int fMaxCycleOffset; | |||||
| int fLastfCycleOffset; | int fLastfCycleOffset; | ||||
| bool Init(); | bool Init(); | ||||
| @@ -133,7 +134,7 @@ namespace Jack | |||||
| void FatalError(); | void FatalError(); | ||||
| public: | 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 ) | JackNetMasterInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) | ||||
| : JackNetInterface ( params, socket, multicast_ip ) | : JackNetInterface ( params, socket, multicast_ip ) | ||||
| @@ -223,10 +224,7 @@ namespace Jack | |||||
| #define MASTER_INIT_TIMEOUT 1000000 // in usec | #define MASTER_INIT_TIMEOUT 1000000 // in usec | ||||
| #define SLAVE_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 | #endif | ||||
| @@ -64,18 +64,7 @@ namespace Jack | |||||
| plot_name = string ( fParams.fName ); | plot_name = string ( fParams.fName ); | ||||
| plot_name += string ( "_master" ); | plot_name += string ( "_master" ); | ||||
| plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" ); | 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 ); | fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name ); | ||||
| string net_time_mon_fields[] = | 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 ) | if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) | ||||
| return -1; | return -1; | ||||
| //port latency | //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 | //midi | ||||
| @@ -229,21 +205,8 @@ namespace Jack | |||||
| if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) | if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) | ||||
| return -1; | return -1; | ||||
| //port latency | //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; | return 0; | ||||
| } | } | ||||
| @@ -690,6 +690,7 @@ namespace Jack | |||||
| dst_params->fPeriodSize = htonl(src_params->fPeriodSize); | dst_params->fPeriodSize = htonl(src_params->fPeriodSize); | ||||
| dst_params->fSampleEncoder = htonl(src_params->fSampleEncoder); | dst_params->fSampleEncoder = htonl(src_params->fSampleEncoder); | ||||
| dst_params->fSlaveSyncMode = htonl(src_params->fSlaveSyncMode); | 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) | 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->fPeriodSize = ntohl(src_params->fPeriodSize); | ||||
| dst_params->fSampleEncoder = ntohl(src_params->fSampleEncoder); | dst_params->fSampleEncoder = ntohl(src_params->fSampleEncoder); | ||||
| dst_params->fSlaveSyncMode = ntohl(src_params->fSlaveSyncMode); | dst_params->fSlaveSyncMode = ntohl(src_params->fSlaveSyncMode); | ||||
| dst_params->fNetworkLatency = ntohl(src_params->fNetworkLatency); | |||||
| } | } | ||||
| SERVER_EXPORT void SessionParamsDisplay(session_params_t* params) | SERVER_EXPORT void SessionParamsDisplay(session_params_t* params) | ||||
| @@ -725,19 +727,6 @@ namespace Jack | |||||
| break; | 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("**************** Network parameters ****************"); | ||||
| jack_info("Name : %s", params->fName); | jack_info("Name : %s", params->fName); | ||||
| jack_info("Protocol revision : %d", params->fProtocolVersion); | 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("Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels); | ||||
| jack_info("Sample rate : %u frames per second", params->fSampleRate); | jack_info("Sample rate : %u frames per second", params->fSampleRate); | ||||
| jack_info("Period size : %u frames per period", params->fPeriodSize); | jack_info("Period size : %u frames per period", params->fPeriodSize); | ||||
| jack_info("Network latency : %u cycles", params->fNetworkLatency); | |||||
| switch (params->fSampleEncoder) { | switch (params->fSampleEncoder) { | ||||
| case (JackFloatEncoder): | case (JackFloatEncoder): | ||||
| jack_info("SampleEncoder : %s", "Float"); | jack_info("SampleEncoder : %s", "Float"); | ||||
| @@ -763,7 +753,6 @@ namespace Jack | |||||
| break; | break; | ||||
| }; | }; | ||||
| jack_info("Slave mode : %s", (params->fSlaveSyncMode) ? "sync" : "async"); | jack_info("Slave mode : %s", (params->fSlaveSyncMode) ? "sync" : "async"); | ||||
| jack_info("Network mode : %s", mode); | |||||
| jack_info("****************************************************"); | jack_info("****************************************************"); | ||||
| } | } | ||||
| @@ -101,7 +101,7 @@ namespace Jack | |||||
| uint32_t fSampleEncoder; //samples encoder | uint32_t fSampleEncoder; //samples encoder | ||||
| uint32_t fKBps; //KB per second for CELT encoder | uint32_t fKBps; //KB per second for CELT encoder | ||||
| uint32_t fSlaveSyncMode; //is the slave in sync mode ? | uint32_t fSlaveSyncMode; //is the slave in sync mode ? | ||||
| char fNetworkMode; //fast, normal or slow mode | |||||
| uint32_t fNetworkLatency; //network latency | |||||
| }; | }; | ||||
| //net status ********************************************************************************** | //net status ********************************************************************************** | ||||
| @@ -35,13 +35,6 @@ extern "C" | |||||
| #define SOCKET_ERROR -1 | #define SOCKET_ERROR -1 | ||||
| enum JackNetMode { | |||||
| JackFastMode = 'f', | |||||
| JackNormalMode = 'n', | |||||
| JackSlowMode = 's', | |||||
| }; | |||||
| enum JackNetEncoder { | enum JackNetEncoder { | ||||
| JackFloatEncoder = 0, // Samples are transmitted as float | JackFloatEncoder = 0, // Samples are transmitted as float | ||||
| @@ -59,7 +52,7 @@ typedef struct { | |||||
| int time_out; // in second, -1 means in infinite | int time_out; // in second, -1 means in infinite | ||||
| int encoder; // Encoder type (one of JackNetEncoder) | int encoder; // Encoder type (one of JackNetEncoder) | ||||
| int kbps; // KB per second for CELT encoder | int kbps; // KB per second for CELT encoder | ||||
| char mode; // one of JackNetMode | |||||
| int latency; // network latency | |||||
| } jack_slave_t; | } jack_slave_t; | ||||
| @@ -21,18 +21,18 @@ int buffer_size; | |||||
| int sample_rate; | int sample_rate; | ||||
| static int net_process(jack_nframes_t buffer_size, | 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, | int midi_input, | ||||
| void** midi_input_buffer, | void** midi_input_buffer, | ||||
| int audio_output, | 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) | void* data) | ||||
| { | { | ||||
| jack_adapter_pull_and_push(adapter, audio_output_buffer, audio_input_buffer, buffer_size); | jack_adapter_pull_and_push(adapter, audio_output_buffer, audio_input_buffer, buffer_size); | ||||
| // Process input, produce output | // Process input, produce output | ||||
| if (audio_input == audio_output) { | if (audio_input == audio_output) { | ||||
| // Copy net input to net 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 | #define WIFI_MTU 1500 | ||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||
| NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; | 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; | jack_master_t result; | ||||
| //if ((net = jack_net_slave_open("169.254.112.119", DEFAULT_PORT, "iPhone", &request, &result)) == 0) { | //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"); | printf("jack_net_slave_open error..\n"); | ||||
| return -1; | 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) { | result.sample_rate)) == 0) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| TiPhoneCoreAudioRenderer audio_device(NUM_INPUT, NUM_OUTPUT); | TiPhoneCoreAudioRenderer audio_device(NUM_INPUT, NUM_OUTPUT); | ||||
| jack_set_net_slave_process_callback(net, net_process, NULL); | jack_set_net_slave_process_callback(net, net_process, NULL); | ||||
| jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL); | jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL); | ||||
| if (jack_net_slave_activate(net) != 0) { | if (jack_net_slave_activate(net) != 0) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| if (audio_device.Open(result.buffer_size, result.sample_rate) < 0) { | if (audio_device.Open(result.buffer_size, result.sample_rate) < 0) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| audio_device.SetAudioCallback(SlaveAudioCallback, NULL); | audio_device.SetAudioCallback(SlaveAudioCallback, NULL); | ||||
| if (audio_device.Start() < 0) { | if (audio_device.Start() < 0) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| int retVal = UIApplicationMain(argc, argv, nil, nil); | int retVal = UIApplicationMain(argc, argv, nil, nil); | ||||
| [pool release]; | [pool release]; | ||||
| audio_device.Stop(); | audio_device.Stop(); | ||||
| audio_device.Close(); | audio_device.Close(); | ||||
| // Wait for application end | // Wait for application end | ||||
| jack_net_slave_deactivate(net); | jack_net_slave_deactivate(net); | ||||
| jack_net_slave_close(net); | jack_net_slave_close(net); | ||||