| @@ -63,7 +63,8 @@ extern "C" | |||||
| jack_nframes_t buffer_size; | jack_nframes_t buffer_size; | ||||
| jack_nframes_t sample_rate; | jack_nframes_t sample_rate; | ||||
| char master_name[MASTER_NAME_SIZE]; | char master_name[MASTER_NAME_SIZE]; | ||||
| int time_out; | |||||
| int time_out; | |||||
| int partial_cycle; | |||||
| } jack_master_t; | } jack_master_t; | ||||
| @@ -112,6 +113,9 @@ extern "C" | |||||
| LIB_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); | LIB_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); | ||||
| LIB_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer); | LIB_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer); | ||||
| LIB_EXPORT int jack_net_master_recv_slice(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames); | |||||
| LIB_EXPORT int jack_net_master_send_slice(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames); | |||||
| // NetJack adapter API | // NetJack adapter API | ||||
| typedef struct _jack_adapter jack_adapter_t; | typedef struct _jack_adapter jack_adapter_t; | ||||
| @@ -146,6 +150,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| jack_master_t fRequest; | jack_master_t fRequest; | ||||
| int fPacketTimeOut; | int fPacketTimeOut; | ||||
| JackRingBuffer** fRingBuffer; | |||||
| JackNetExtMaster(const char* ip, | JackNetExtMaster(const char* ip, | ||||
| int port, | int port, | ||||
| @@ -161,10 +167,19 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| fRequest.audio_input = request->audio_input; | fRequest.audio_input = request->audio_input; | ||||
| fRequest.audio_output = request->audio_output; | fRequest.audio_output = request->audio_output; | ||||
| fRequest.time_out = request->time_out; | fRequest.time_out = request->time_out; | ||||
| fRequest.partial_cycle = request->partial_cycle; | |||||
| fRingBuffer = NULL; | |||||
| } | } | ||||
| virtual ~JackNetExtMaster() | virtual ~JackNetExtMaster() | ||||
| {} | |||||
| { | |||||
| if (fRingBuffer) { | |||||
| for (int i = 0; i < fParams.fReturnAudioChannels; i++) { | |||||
| delete fRingBuffer[i]; | |||||
| } | |||||
| delete [] fRingBuffer; | |||||
| } | |||||
| } | |||||
| int Open(jack_slave_t* result) | int Open(jack_slave_t* result) | ||||
| { | { | ||||
| @@ -257,6 +272,14 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| result->midi_output = fParams.fReturnMidiChannels; | result->midi_output = fParams.fReturnMidiChannels; | ||||
| result->mtu = fParams.fMtu; | result->mtu = fParams.fMtu; | ||||
| result->latency = fParams.fNetworkLatency; | result->latency = fParams.fNetworkLatency; | ||||
| // Use ringbuffer in case of partial cycle and latency > 0 | |||||
| if (fRequest.partial_cycle && result->latency > 0) { | |||||
| fRingBuffer = new JackRingBuffer*[fParams.fReturnAudioChannels]; | |||||
| for (int i = 0; i < fParams.fReturnAudioChannels; i++) { | |||||
| fRingBuffer[i] = new JackRingBuffer(fRequest.buffer_size * result->latency * 2); | |||||
| } | |||||
| } | |||||
| return 0; | return 0; | ||||
| error: | error: | ||||
| @@ -332,10 +355,13 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | |||||
| int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames) | |||||
| { | { | ||||
| try { | try { | ||||
| if (frames < 0) frames = fParams.fPeriodSize; | |||||
| int cycle_size; | |||||
| assert(audio_input == fParams.fReturnAudioChannels); | assert(audio_input == fParams.fReturnAudioChannels); | ||||
| for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) { | ||||
| @@ -346,18 +372,25 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]); | fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]); | ||||
| } | } | ||||
| int res = SyncRecv(); | |||||
| switch (res) { | |||||
| int res1 = SyncRecv(); | |||||
| switch (res1) { | |||||
| case NET_SYNCHING: | case NET_SYNCHING: | ||||
| // Data will not be received, so cleanup buffers... | // Data will not be received, so cleanup buffers... | ||||
| for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) { | ||||
| memset(audio_input_buffer[audio_port_index], 0, sizeof(float) * fParams.fPeriodSize); | |||||
| memset(audio_input_buffer[audio_port_index], 0, sizeof(float) * fParams.fPeriodSize); | |||||
| } | |||||
| // Possibly use ringbuffer... | |||||
| if (fRingBuffer) { | |||||
| for (int i = 0; i < audio_input; i++) { | |||||
| fRingBuffer[i]->Write(audio_input_buffer[i], fParams.fPeriodSize); | |||||
| fRingBuffer[i]->Read(audio_input_buffer[i], frames); | |||||
| } | |||||
| } | } | ||||
| return res; | |||||
| return res1; | |||||
| case SOCKET_ERROR: | case SOCKET_ERROR: | ||||
| return res; | |||||
| return res1; | |||||
| case SYNC_PACKET_ERROR: | case SYNC_PACKET_ERROR: | ||||
| // since sync packet is incorrect, don't decode it and continue with data | // since sync packet is incorrect, don't decode it and continue with data | ||||
| @@ -365,11 +398,20 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| default: | default: | ||||
| // decode sync | // decode sync | ||||
| DecodeSyncPacket(); | |||||
| cycle_size; | |||||
| DecodeSyncPacket(cycle_size); | |||||
| break; | break; | ||||
| } | } | ||||
| return DataRecv(); | |||||
| int res2 = DataRecv(); | |||||
| // Possibly use ringbuffer... | |||||
| if (res2 == 0 && fRingBuffer) { | |||||
| for (int i = 0; i < audio_input; i++) { | |||||
| fRingBuffer[i]->Write(audio_input_buffer[i], cycle_size); | |||||
| fRingBuffer[i]->Read(audio_input_buffer[i], frames); | |||||
| } | |||||
| } | |||||
| return res2; | |||||
| } catch (JackNetException& e) { | } catch (JackNetException& e) { | ||||
| jack_error("Lost connection"); | jack_error("Lost connection"); | ||||
| @@ -377,9 +419,11 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| } | } | ||||
| } | } | ||||
| int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | |||||
| int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames) | |||||
| { | { | ||||
| try { | try { | ||||
| if (frames < 0) frames = fParams.fPeriodSize; | |||||
| assert(audio_output == fParams.fSendAudioChannels); | assert(audio_output == fParams.fSendAudioChannels); | ||||
| @@ -391,8 +435,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); | fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); | ||||
| } | } | ||||
| EncodeSyncPacket(); | |||||
| EncodeSyncPacket(frames); | |||||
| // send sync | // send sync | ||||
| if (SyncSend() == SOCKET_ERROR) { | if (SyncSend() == SOCKET_ERROR) { | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| @@ -402,7 +446,6 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| if (DataSend() == SOCKET_ERROR) { | if (DataSend() == SOCKET_ERROR) { | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } catch (JackNetException& e) { | } catch (JackNetException& e) { | ||||
| @@ -450,6 +493,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| void* fSampleRateArg; | void* fSampleRateArg; | ||||
| int fConnectTimeOut; | int fConnectTimeOut; | ||||
| int fCycleSize; | |||||
| JackNetExtSlave(const char* ip, | JackNetExtSlave(const char* ip, | ||||
| int port, | int port, | ||||
| @@ -610,8 +654,8 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| // Set result | |||||
| if (result != NULL) { | |||||
| // Set result | |||||
| if (result != NULL) { | |||||
| result->buffer_size = fParams.fPeriodSize; | result->buffer_size = fParams.fPeriodSize; | ||||
| result->sample_rate = fParams.fSampleRate; | result->sample_rate = fParams.fSampleRate; | ||||
| result->audio_input = fParams.fSendAudioChannels; | result->audio_input = fParams.fSendAudioChannels; | ||||
| @@ -620,7 +664,10 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| result->midi_output = fParams.fReturnMidiChannels; | result->midi_output = fParams.fReturnMidiChannels; | ||||
| strcpy(result->master_name, fParams.fMasterNetName); | strcpy(result->master_name, fParams.fMasterNetName); | ||||
| } | } | ||||
| // By default fCycleSize is fPeriodSize | |||||
| fCycleSize = fParams.fPeriodSize; | |||||
| AllocPorts(); | AllocPorts(); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -711,7 +758,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| bool Execute() | bool Execute() | ||||
| { | { | ||||
| try { | |||||
| try { | |||||
| /* | /* | ||||
| Fist cycle use an INT_MAX time out, so that connection | Fist cycle use an INT_MAX time out, so that connection | ||||
| is considered established (with PACKET_TIMEOUT later on) | is considered established (with PACKET_TIMEOUT later on) | ||||
| @@ -758,7 +805,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| default: | default: | ||||
| // decode sync | // decode sync | ||||
| DecodeSyncPacket(); | |||||
| DecodeSyncPacket(fCycleSize); | |||||
| break; | break; | ||||
| } | } | ||||
| @@ -768,11 +815,11 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| } | } | ||||
| return res; | return res; | ||||
| } | } | ||||
| int Write() | int Write() | ||||
| { | { | ||||
| EncodeSyncPacket(); | |||||
| EncodeSyncPacket(fCycleSize); | |||||
| if (SyncSend() == SOCKET_ERROR) { | if (SyncSend() == SOCKET_ERROR) { | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| } | } | ||||
| @@ -798,8 +845,8 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| if (Read() == SOCKET_ERROR) { | if (Read() == SOCKET_ERROR) { | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| } | } | ||||
| fProcessCallback(fParams.fPeriodSize, | |||||
| fProcessCallback(fCycleSize, | |||||
| fParams.fSendAudioChannels, | fParams.fSendAudioChannels, | ||||
| fAudioCaptureBuffer, | fAudioCaptureBuffer, | ||||
| fParams.fSendMidiChannels, | fParams.fSendMidiChannels, | ||||
| @@ -809,7 +856,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| fParams.fReturnMidiChannels, | fParams.fReturnMidiChannels, | ||||
| (void**)fMidiPlaybackBuffer, | (void**)fMidiPlaybackBuffer, | ||||
| fProcessArg); | fProcessArg); | ||||
| // Then write data to network, throw JackNetException in case of network error... | // Then write data to network, throw JackNetException in case of network error... | ||||
| if (Write() == SOCKET_ERROR) { | if (Write() == SOCKET_ERROR) { | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| @@ -1068,13 +1115,25 @@ LIB_EXPORT int jack_net_master_close(jack_net_master_t* net) | |||||
| LIB_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | LIB_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | ||||
| { | { | ||||
| JackNetExtMaster* master = (JackNetExtMaster*)net; | JackNetExtMaster* master = (JackNetExtMaster*)net; | ||||
| return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer); | |||||
| return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer, -1); | |||||
| } | } | ||||
| LIB_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | LIB_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | ||||
| { | { | ||||
| JackNetExtMaster* master = (JackNetExtMaster*)net; | JackNetExtMaster* master = (JackNetExtMaster*)net; | ||||
| return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer); | |||||
| return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer, -1); | |||||
| } | |||||
| LIB_EXPORT int jack_net_master_recv_slice(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames) | |||||
| { | |||||
| JackNetExtMaster* master = (JackNetExtMaster*)net; | |||||
| return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer, frames); | |||||
| } | |||||
| LIB_EXPORT int jack_net_master_send_slice(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames) | |||||
| { | |||||
| JackNetExtMaster* master = (JackNetExtMaster*)net; | |||||
| return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer, frames); | |||||
| } | } | ||||
| // Adapter API | // Adapter API | ||||
| @@ -361,7 +361,8 @@ namespace Jack | |||||
| default: | default: | ||||
| //decode sync | //decode sync | ||||
| DecodeSyncPacket(); | |||||
| int unused_cycle_size; | |||||
| DecodeSyncPacket(unused_cycle_size); | |||||
| break; | break; | ||||
| } | } | ||||
| @@ -575,7 +575,8 @@ namespace Jack | |||||
| default: | default: | ||||
| // decode sync | // decode sync | ||||
| DecodeSyncPacket(); | |||||
| int unused_cycle_size; | |||||
| DecodeSyncPacket(unused_cycle_size); | |||||
| break; | break; | ||||
| } | } | ||||
| @@ -724,8 +725,8 @@ Deactivated for now.. | |||||
| int mtu = DEFAULT_MTU; | int mtu = DEFAULT_MTU; | ||||
| // Desactivated for now... | // Desactivated for now... | ||||
| uint transport_sync = 0; | uint transport_sync = 0; | ||||
| jack_nframes_t period_size = 1024; | |||||
| jack_nframes_t sample_rate = 48000; | |||||
| jack_nframes_t period_size = 1024; // to be used while waiting for master period_size | |||||
| jack_nframes_t sample_rate = 48000; // to be used while waiting for master sample_rate | |||||
| int audio_capture_ports = -1; | int audio_capture_ports = -1; | ||||
| int audio_playback_ports = -1; | int audio_playback_ports = -1; | ||||
| int midi_input_ports = -1; | int midi_input_ports = -1; | ||||
| @@ -544,7 +544,7 @@ namespace Jack | |||||
| return rx_bytes; | return rx_bytes; | ||||
| } | } | ||||
| void JackNetMasterInterface::EncodeSyncPacket() | |||||
| void JackNetMasterInterface::EncodeSyncPacket(int cycle_size) | |||||
| { | { | ||||
| // This method contains every step of sync packet informations coding | // This method contains every step of sync packet informations coding | ||||
| // first of all, clear sync packet | // first of all, clear sync packet | ||||
| @@ -565,9 +565,10 @@ namespace Jack | |||||
| // Write active ports list | // Write active ports list | ||||
| fTxHeader.fActivePorts = (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->ActivePortsToNetwork(fTxData) : 0; | fTxHeader.fActivePorts = (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->ActivePortsToNetwork(fTxData) : 0; | ||||
| fTxHeader.fCycleSize = cycle_size; | |||||
| } | } | ||||
| void JackNetMasterInterface::DecodeSyncPacket() | |||||
| void JackNetMasterInterface::DecodeSyncPacket(int& cycle_size) | |||||
| { | { | ||||
| // This method contains every step of sync packet informations decoding process | // This method contains every step of sync packet informations decoding process | ||||
| @@ -590,6 +591,8 @@ namespace Jack | |||||
| if (fNetAudioCaptureBuffer) { | if (fNetAudioCaptureBuffer) { | ||||
| fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); | fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); | ||||
| } | } | ||||
| cycle_size = rx_head->fCycleSize; | |||||
| } | } | ||||
| // JackNetSlaveInterface ************************************************************************************************ | // JackNetSlaveInterface ************************************************************************************************ | ||||
| @@ -946,7 +949,7 @@ namespace Jack | |||||
| } | } | ||||
| // network sync------------------------------------------------------------------------ | // network sync------------------------------------------------------------------------ | ||||
| void JackNetSlaveInterface::EncodeSyncPacket() | |||||
| void JackNetSlaveInterface::EncodeSyncPacket(int cycle_size) | |||||
| { | { | ||||
| // This method contains every step of sync packet informations coding | // This method contains every step of sync packet informations coding | ||||
| // first of all, clear sync packet | // first of all, clear sync packet | ||||
| @@ -967,9 +970,10 @@ namespace Jack | |||||
| // Write active ports list | // Write active ports list | ||||
| fTxHeader.fActivePorts = (fNetAudioCaptureBuffer) ? fNetAudioCaptureBuffer->ActivePortsToNetwork(fTxData) : 0; | fTxHeader.fActivePorts = (fNetAudioCaptureBuffer) ? fNetAudioCaptureBuffer->ActivePortsToNetwork(fTxData) : 0; | ||||
| fTxHeader.fCycleSize = cycle_size; | |||||
| } | } | ||||
| void JackNetSlaveInterface::DecodeSyncPacket() | |||||
| void JackNetSlaveInterface::DecodeSyncPacket(int& cycle_size) | |||||
| { | { | ||||
| // This method contains every step of sync packet informations decoding process | // This method contains every step of sync packet informations decoding process | ||||
| @@ -992,6 +996,8 @@ namespace Jack | |||||
| if (fNetAudioPlaybackBuffer) { | if (fNetAudioPlaybackBuffer) { | ||||
| fNetAudioPlaybackBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); | fNetAudioPlaybackBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); | ||||
| } | } | ||||
| cycle_size = rx_head->fCycleSize; | |||||
| } | } | ||||
| } | } | ||||
| @@ -92,8 +92,8 @@ namespace Jack | |||||
| virtual void DecodeTransportData() = 0; | virtual void DecodeTransportData() = 0; | ||||
| // sync packet | // sync packet | ||||
| virtual void EncodeSyncPacket() = 0; | |||||
| virtual void DecodeSyncPacket() = 0; | |||||
| virtual void EncodeSyncPacket(int cycle_size = -1) = 0; | |||||
| virtual void DecodeSyncPacket(int& cycle_size) = 0; | |||||
| virtual int SyncRecv() = 0; | virtual int SyncRecv() = 0; | ||||
| virtual int SyncSend() = 0; | virtual int SyncSend() = 0; | ||||
| @@ -160,8 +160,8 @@ namespace Jack | |||||
| int DataSend(); | int DataSend(); | ||||
| // sync packet | // sync packet | ||||
| void EncodeSyncPacket(); | |||||
| void DecodeSyncPacket(); | |||||
| void EncodeSyncPacket(int cycle_size = -1); | |||||
| void DecodeSyncPacket(int& cycle_size); | |||||
| int Send(size_t size, int flags); | int Send(size_t size, int flags); | ||||
| int Recv(size_t size, int flags); | int Recv(size_t size, int flags); | ||||
| @@ -217,8 +217,8 @@ namespace Jack | |||||
| int DataSend(); | int DataSend(); | ||||
| // sync packet | // sync packet | ||||
| void EncodeSyncPacket(); | |||||
| void DecodeSyncPacket(); | |||||
| void EncodeSyncPacket(int cycle_size = -1); | |||||
| void DecodeSyncPacket(int& cycle_size); | |||||
| int Recv(size_t size, int flags); | int Recv(size_t size, int flags); | ||||
| int Send(size_t size, int flags); | int Send(size_t size, int flags); | ||||
| @@ -543,7 +543,8 @@ namespace Jack | |||||
| default: | default: | ||||
| // Decode sync | // Decode sync | ||||
| DecodeSyncPacket(); | |||||
| int unused_cycle_size; | |||||
| DecodeSyncPacket(unused_cycle_size); | |||||
| break; | break; | ||||
| } | } | ||||
| @@ -1216,6 +1216,7 @@ namespace Jack | |||||
| dst_header->fActivePorts = htonl(src_header->fActivePorts); | dst_header->fActivePorts = htonl(src_header->fActivePorts); | ||||
| dst_header->fCycle = htonl(src_header->fCycle); | dst_header->fCycle = htonl(src_header->fCycle); | ||||
| dst_header->fSubCycle = htonl(src_header->fSubCycle); | dst_header->fSubCycle = htonl(src_header->fSubCycle); | ||||
| dst_header->fCycleSize = htonl(src_header->fCycleSize); | |||||
| dst_header->fIsLastPckt = htonl(src_header->fIsLastPckt); | dst_header->fIsLastPckt = htonl(src_header->fIsLastPckt); | ||||
| } | } | ||||
| @@ -1230,6 +1231,7 @@ namespace Jack | |||||
| dst_header->fActivePorts = ntohl(src_header->fActivePorts); | dst_header->fActivePorts = ntohl(src_header->fActivePorts); | ||||
| dst_header->fCycle = ntohl(src_header->fCycle); | dst_header->fCycle = ntohl(src_header->fCycle); | ||||
| dst_header->fSubCycle = ntohl(src_header->fSubCycle); | dst_header->fSubCycle = ntohl(src_header->fSubCycle); | ||||
| dst_header->fCycleSize = ntohl(src_header->fCycleSize); | |||||
| dst_header->fIsLastPckt = ntohl(src_header->fIsLastPckt); | dst_header->fIsLastPckt = ntohl(src_header->fIsLastPckt); | ||||
| } | } | ||||
| @@ -38,7 +38,7 @@ using namespace std; | |||||
| #endif | #endif | ||||
| #endif | #endif | ||||
| #define NETWORK_PROTOCOL 7 | |||||
| #define NETWORK_PROTOCOL 8 | |||||
| #define NET_SYNCHING 0 | #define NET_SYNCHING 0 | ||||
| #define SYNC_PACKET_ERROR -2 | #define SYNC_PACKET_ERROR -2 | ||||
| @@ -180,6 +180,7 @@ namespace Jack | |||||
| uint32_t fActivePorts; //number of active ports | uint32_t fActivePorts; //number of active ports | ||||
| uint32_t fCycle; //process cycle counter | uint32_t fCycle; //process cycle counter | ||||
| uint32_t fSubCycle; //midi/audio subcycle counter | uint32_t fSubCycle; //midi/audio subcycle counter | ||||
| int32_t fCycleSize; //process cycle size in frames | |||||
| uint32_t fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n') | uint32_t fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n') | ||||
| } POST_PACKED_STRUCTURE; | } POST_PACKED_STRUCTURE; | ||||
| @@ -24,45 +24,44 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| JackResampler::JackResampler() | |||||
| :fRatio(1), fRingBufferSize(DEFAULT_RB_SIZE) | |||||
| JackRingBuffer::JackRingBuffer(int size):fRingBufferSize(size) | |||||
| { | { | ||||
| fRingBuffer = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * fRingBufferSize); | fRingBuffer = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * fRingBufferSize); | ||||
| jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize) / 2); | |||||
| Reset(fRingBufferSize); | |||||
| } | } | ||||
| JackResampler::~JackResampler() | |||||
| JackRingBuffer::~JackRingBuffer() | |||||
| { | { | ||||
| if (fRingBuffer) { | if (fRingBuffer) { | ||||
| jack_ringbuffer_free(fRingBuffer); | jack_ringbuffer_free(fRingBuffer); | ||||
| } | } | ||||
| } | } | ||||
| void JackResampler::Reset(unsigned int new_size) | |||||
| void JackRingBuffer::Reset(unsigned int new_size) | |||||
| { | { | ||||
| fRingBufferSize = new_size; | fRingBufferSize = new_size; | ||||
| jack_ringbuffer_reset(fRingBuffer); | jack_ringbuffer_reset(fRingBuffer); | ||||
| jack_ringbuffer_reset_size(fRingBuffer, sizeof(jack_default_audio_sample_t) * fRingBufferSize); | jack_ringbuffer_reset_size(fRingBuffer, sizeof(jack_default_audio_sample_t) * fRingBufferSize); | ||||
| jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize / 2)); | |||||
| jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * new_size/2)); | |||||
| } | } | ||||
| unsigned int JackResampler::ReadSpace() | |||||
| unsigned int JackRingBuffer::ReadSpace() | |||||
| { | { | ||||
| return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(jack_default_audio_sample_t)); | return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(jack_default_audio_sample_t)); | ||||
| } | } | ||||
| unsigned int JackResampler::WriteSpace() | |||||
| unsigned int JackRingBuffer::WriteSpace() | |||||
| { | { | ||||
| return (jack_ringbuffer_write_space(fRingBuffer) / sizeof(jack_default_audio_sample_t)); | return (jack_ringbuffer_write_space(fRingBuffer) / sizeof(jack_default_audio_sample_t)); | ||||
| } | } | ||||
| unsigned int JackResampler::Read(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
| unsigned int JackRingBuffer::Read(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
| { | { | ||||
| size_t len = jack_ringbuffer_read_space(fRingBuffer); | size_t len = jack_ringbuffer_read_space(fRingBuffer); | ||||
| jack_log("JackResampler::Read input available = %ld", len / sizeof(jack_default_audio_sample_t)); | |||||
| jack_log("JackRingBuffer::Read input available = %ld", len / sizeof(jack_default_audio_sample_t)); | |||||
| if (len < frames * sizeof(jack_default_audio_sample_t)) { | if (len < frames * sizeof(jack_default_audio_sample_t)) { | ||||
| jack_error("JackResampler::Read : producer too slow, missing frames = %d", frames); | |||||
| jack_error("JackRingBuffer::Read : producer too slow, missing frames = %d", frames); | |||||
| return 0; | return 0; | ||||
| } else { | } else { | ||||
| jack_ringbuffer_read(fRingBuffer, (char*)buffer, frames * sizeof(jack_default_audio_sample_t)); | jack_ringbuffer_read(fRingBuffer, (char*)buffer, frames * sizeof(jack_default_audio_sample_t)); | ||||
| @@ -70,13 +69,13 @@ unsigned int JackResampler::Read(jack_default_audio_sample_t* buffer, unsigned i | |||||
| } | } | ||||
| } | } | ||||
| unsigned int JackResampler::Write(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
| unsigned int JackRingBuffer::Write(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
| { | { | ||||
| size_t len = jack_ringbuffer_write_space(fRingBuffer); | size_t len = jack_ringbuffer_write_space(fRingBuffer); | ||||
| jack_log("JackResampler::Write output available = %ld", len / sizeof(jack_default_audio_sample_t)); | |||||
| jack_log("JackRingBuffer::Write output available = %ld", len / sizeof(jack_default_audio_sample_t)); | |||||
| if (len < frames * sizeof(jack_default_audio_sample_t)) { | if (len < frames * sizeof(jack_default_audio_sample_t)) { | ||||
| jack_error("JackResampler::Write : consumer too slow, skip frames = %d", frames); | |||||
| jack_error("JackRingBuffer::Write : consumer too slow, skip frames = %d", frames); | |||||
| return 0; | return 0; | ||||
| } else { | } else { | ||||
| jack_ringbuffer_write(fRingBuffer, (char*)buffer, frames * sizeof(jack_default_audio_sample_t)); | jack_ringbuffer_write(fRingBuffer, (char*)buffer, frames * sizeof(jack_default_audio_sample_t)); | ||||
| @@ -84,13 +83,13 @@ unsigned int JackResampler::Write(jack_default_audio_sample_t* buffer, unsigned | |||||
| } | } | ||||
| } | } | ||||
| unsigned int JackResampler::Read(void* buffer, unsigned int bytes) | |||||
| unsigned int JackRingBuffer::Read(void* buffer, unsigned int bytes) | |||||
| { | { | ||||
| size_t len = jack_ringbuffer_read_space(fRingBuffer); | size_t len = jack_ringbuffer_read_space(fRingBuffer); | ||||
| jack_log("JackResampler::Read input available = %ld", len); | |||||
| jack_log("JackRingBuffer::Read input available = %ld", len); | |||||
| if (len < bytes) { | if (len < bytes) { | ||||
| jack_error("JackResampler::Read : producer too slow, missing bytes = %d", bytes); | |||||
| jack_error("JackRingBuffer::Read : producer too slow, missing bytes = %d", bytes); | |||||
| return 0; | return 0; | ||||
| } else { | } else { | ||||
| jack_ringbuffer_read(fRingBuffer, (char*)buffer, bytes); | jack_ringbuffer_read(fRingBuffer, (char*)buffer, bytes); | ||||
| @@ -98,13 +97,13 @@ unsigned int JackResampler::Read(void* buffer, unsigned int bytes) | |||||
| } | } | ||||
| } | } | ||||
| unsigned int JackResampler::Write(void* buffer, unsigned int bytes) | |||||
| unsigned int JackRingBuffer::Write(void* buffer, unsigned int bytes) | |||||
| { | { | ||||
| size_t len = jack_ringbuffer_write_space(fRingBuffer); | size_t len = jack_ringbuffer_write_space(fRingBuffer); | ||||
| jack_log("JackResampler::Write output available = %ld", len); | |||||
| jack_log("JackRingBuffer::Write output available = %ld", len); | |||||
| if (len < bytes) { | if (len < bytes) { | ||||
| jack_error("JackResampler::Write : consumer too slow, skip bytes = %d", bytes); | |||||
| jack_error("JackRingBuffer::Write : consumer too slow, skip bytes = %d", bytes); | |||||
| return 0; | return 0; | ||||
| } else { | } else { | ||||
| jack_ringbuffer_write(fRingBuffer, (char*)buffer, bytes); | jack_ringbuffer_write(fRingBuffer, (char*)buffer, bytes); | ||||
| @@ -35,34 +35,33 @@ inline float Range(float min, float max, float val) | |||||
| } | } | ||||
| /*! | /*! | ||||
| \brief Base class for Resampler. | |||||
| \brief Base class for RingBuffer in frames. | |||||
| */ | */ | ||||
| class JackResampler | |||||
| class JackRingBuffer | |||||
| { | { | ||||
| protected: | protected: | ||||
| jack_ringbuffer_t* fRingBuffer; | jack_ringbuffer_t* fRingBuffer; | ||||
| double fRatio; | |||||
| unsigned int fRingBufferSize; | unsigned int fRingBufferSize; | ||||
| public: | public: | ||||
| JackResampler(); | |||||
| virtual ~JackResampler(); | |||||
| JackRingBuffer(int size = DEFAULT_RB_SIZE); | |||||
| virtual ~JackRingBuffer(); | |||||
| virtual void Reset(unsigned int new_size); | virtual void Reset(unsigned int new_size); | ||||
| virtual unsigned int ReadResample(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
| virtual unsigned int WriteResample(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
| // in frames | |||||
| virtual unsigned int Read(jack_default_audio_sample_t* buffer, unsigned int frames); | virtual unsigned int Read(jack_default_audio_sample_t* buffer, unsigned int frames); | ||||
| virtual unsigned int Write(jack_default_audio_sample_t* buffer, unsigned int frames); | virtual unsigned int Write(jack_default_audio_sample_t* buffer, unsigned int frames); | ||||
| // in bytes | |||||
| virtual unsigned int Read(void* buffer, unsigned int bytes); | virtual unsigned int Read(void* buffer, unsigned int bytes); | ||||
| virtual unsigned int Write(void* buffer, unsigned int bytes); | virtual unsigned int Write(void* buffer, unsigned int bytes); | ||||
| // in frames | |||||
| virtual unsigned int ReadSpace(); | virtual unsigned int ReadSpace(); | ||||
| virtual unsigned int WriteSpace(); | virtual unsigned int WriteSpace(); | ||||
| @@ -71,6 +70,29 @@ class JackResampler | |||||
| return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(float)) - (fRingBufferSize / 2); | return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(float)) - (fRingBufferSize / 2); | ||||
| } | } | ||||
| }; | |||||
| /*! | |||||
| \brief Base class for Resampler. | |||||
| */ | |||||
| class JackResampler : public JackRingBuffer | |||||
| { | |||||
| protected: | |||||
| double fRatio; | |||||
| public: | |||||
| JackResampler():JackRingBuffer(),fRatio(1) | |||||
| {} | |||||
| virtual ~JackResampler() | |||||
| {} | |||||
| virtual unsigned int ReadResample(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
| virtual unsigned int WriteResample(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
| void SetRatio(double ratio) | void SetRatio(double ratio) | ||||
| { | { | ||||
| fRatio = Range(0.25, 4.0, ratio); | fRatio = Range(0.25, 4.0, ratio); | ||||
| @@ -75,6 +75,7 @@ typedef struct { | |||||
| jack_nframes_t sample_rate; // master sample rate | jack_nframes_t sample_rate; // master sample rate | ||||
| char master_name[MASTER_NAME_SIZE]; // master machine name | char master_name[MASTER_NAME_SIZE]; // master machine name | ||||
| int time_out; // in second, -1 means infinite | int time_out; // in second, -1 means infinite | ||||
| int partial_cycle; // if 'true', partial cycle will be used | |||||
| } jack_master_t; | } jack_master_t; | ||||
| @@ -281,7 +282,7 @@ jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* na | |||||
| int jack_net_master_close(jack_net_master_t* net); | int jack_net_master_close(jack_net_master_t* net); | ||||
| /** | /** | ||||
| * Receive sync and data from the network. | |||||
| * Receive sync and data from the network (complete buffer). | |||||
| * @param net the network connection | * @param net the network connection | ||||
| * @param audio_input number of audio inputs | * @param audio_input number of audio inputs | ||||
| * @param audio_input_buffer an array of audio input buffers | * @param audio_input_buffer an array of audio input buffers | ||||
| @@ -293,7 +294,20 @@ int jack_net_master_close(jack_net_master_t* net); | |||||
| int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); | int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); | ||||
| /** | /** | ||||
| * Send sync and data to the network. | |||||
| * Receive sync and data from the network (incomplete buffer). | |||||
| * @param net the network connection | |||||
| * @param audio_input number of audio inputs | |||||
| * @param audio_input_buffer an array of audio input buffers | |||||
| * @param midi_input number of MIDI inputs | |||||
| * @param midi_input_buffer an array of MIDI input buffers | |||||
| * @param frames the number of frames to receive. | |||||
| * | |||||
| * @return zero on success, non-zero on error | |||||
| */ | |||||
| int jack_net_master_recv_slice(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames); | |||||
| /** | |||||
| * Send sync and data to the network (complete buffer). | |||||
| * @param net the network connection | * @param net the network connection | ||||
| * @param audio_output number of audio outputs | * @param audio_output number of audio outputs | ||||
| * @param audio_output_buffer an array of audio output buffers | * @param audio_output_buffer an array of audio output buffers | ||||
| @@ -304,6 +318,19 @@ int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_ | |||||
| */ | */ | ||||
| int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer); | int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer); | ||||
| /** | |||||
| * Send sync and data to the network (incomplete buffer). | |||||
| * @param net the network connection | |||||
| * @param audio_output number of audio outputs | |||||
| * @param audio_output_buffer an array of audio output buffers | |||||
| * @param midi_output number of MIDI ouputs | |||||
| * @param midi_output_buffer an array of MIDI output buffers | |||||
| * @param frames the number of frames to send. | |||||
| * | |||||
| * @return zero on success, non-zero on error | |||||
| */ | |||||
| int jack_net_master_send_slice(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames); | |||||
| // Experimental Adapter API | // Experimental Adapter API | ||||
| /** | /** | ||||
| @@ -101,7 +101,7 @@ main (int argc, char *argv[]) | |||||
| int i; | int i; | ||||
| //jack_master_t request = { 4, 4, -1, -1, buffer_size, sample_rate, "master", -1 }; | //jack_master_t request = { 4, 4, -1, -1, buffer_size, sample_rate, "master", -1 }; | ||||
| jack_master_t request = { -1, -1, -1, -1, buffer_size, sample_rate, "master", 6 }; | |||||
| jack_master_t request = { -1, -1, -1, -1, buffer_size, sample_rate, "master", 6, true }; | |||||
| jack_slave_t result; | jack_slave_t result; | ||||
| float** audio_input_buffer; | float** audio_input_buffer; | ||||
| float** audio_output_buffer; | float** audio_output_buffer; | ||||
| @@ -161,6 +161,7 @@ main (int argc, char *argv[]) | |||||
| memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); | memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); | ||||
| } | } | ||||
| /* | |||||
| if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { | if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { | ||||
| printf("jack_net_master_send failure, exiting\n"); | printf("jack_net_master_send failure, exiting\n"); | ||||
| break; | break; | ||||
| @@ -172,6 +173,19 @@ main (int argc, char *argv[]) | |||||
| printf("jack_net_master_recv failure, exiting\n"); | printf("jack_net_master_recv failure, exiting\n"); | ||||
| break; | break; | ||||
| } | } | ||||
| */ | |||||
| if (jack_net_master_send_slice(net, result.audio_output, audio_output_buffer, 0, NULL, BUFFER_SIZE/2) < 0) { | |||||
| printf("jack_net_master_send failure, exiting\n"); | |||||
| break; | |||||
| } | |||||
| usleep(10000); | |||||
| if (jack_net_master_recv_slice(net, result.audio_input, audio_input_buffer, 0, NULL, BUFFER_SIZE/2) < 0) { | |||||
| printf("jack_net_master_recv failure, exiting\n"); | |||||
| break; | |||||
| } | |||||
| usleep(wait_usec); | usleep(wait_usec); | ||||
| }; | }; | ||||