| @@ -63,7 +63,8 @@ extern "C" | |||
| jack_nframes_t buffer_size; | |||
| jack_nframes_t sample_rate; | |||
| char master_name[MASTER_NAME_SIZE]; | |||
| int time_out; | |||
| int time_out; | |||
| int partial_cycle; | |||
| } 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_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 | |||
| typedef struct _jack_adapter jack_adapter_t; | |||
| @@ -146,6 +150,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| jack_master_t fRequest; | |||
| int fPacketTimeOut; | |||
| JackRingBuffer** fRingBuffer; | |||
| JackNetExtMaster(const char* ip, | |||
| int port, | |||
| @@ -161,10 +167,19 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| fRequest.audio_input = request->audio_input; | |||
| fRequest.audio_output = request->audio_output; | |||
| fRequest.time_out = request->time_out; | |||
| fRequest.partial_cycle = request->partial_cycle; | |||
| fRingBuffer = NULL; | |||
| } | |||
| virtual ~JackNetExtMaster() | |||
| {} | |||
| { | |||
| if (fRingBuffer) { | |||
| for (int i = 0; i < fParams.fReturnAudioChannels; i++) { | |||
| delete fRingBuffer[i]; | |||
| } | |||
| delete [] fRingBuffer; | |||
| } | |||
| } | |||
| int Open(jack_slave_t* result) | |||
| { | |||
| @@ -257,6 +272,14 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| result->midi_output = fParams.fReturnMidiChannels; | |||
| result->mtu = fParams.fMtu; | |||
| 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; | |||
| error: | |||
| @@ -332,10 +355,13 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| 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 { | |||
| if (frames < 0) frames = fParams.fPeriodSize; | |||
| int cycle_size; | |||
| assert(audio_input == fParams.fReturnAudioChannels); | |||
| 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]); | |||
| } | |||
| int res = SyncRecv(); | |||
| switch (res) { | |||
| int res1 = SyncRecv(); | |||
| switch (res1) { | |||
| case NET_SYNCHING: | |||
| // Data will not be received, so cleanup buffers... | |||
| 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: | |||
| return res; | |||
| return res1; | |||
| case SYNC_PACKET_ERROR: | |||
| // since sync packet is incorrect, don't decode it and continue with data | |||
| @@ -365,11 +398,20 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| default: | |||
| // decode sync | |||
| DecodeSyncPacket(); | |||
| cycle_size; | |||
| DecodeSyncPacket(cycle_size); | |||
| 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) { | |||
| 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 { | |||
| if (frames < 0) frames = fParams.fPeriodSize; | |||
| 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]); | |||
| } | |||
| EncodeSyncPacket(); | |||
| EncodeSyncPacket(frames); | |||
| // send sync | |||
| if (SyncSend() == SOCKET_ERROR) { | |||
| return SOCKET_ERROR; | |||
| @@ -402,7 +446,6 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| if (DataSend() == SOCKET_ERROR) { | |||
| return SOCKET_ERROR; | |||
| } | |||
| return 0; | |||
| } catch (JackNetException& e) { | |||
| @@ -450,6 +493,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| void* fSampleRateArg; | |||
| int fConnectTimeOut; | |||
| int fCycleSize; | |||
| JackNetExtSlave(const char* ip, | |||
| int port, | |||
| @@ -610,8 +654,8 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| return -1; | |||
| } | |||
| // Set result | |||
| if (result != NULL) { | |||
| // Set result | |||
| if (result != NULL) { | |||
| result->buffer_size = fParams.fPeriodSize; | |||
| result->sample_rate = fParams.fSampleRate; | |||
| result->audio_input = fParams.fSendAudioChannels; | |||
| @@ -620,7 +664,10 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| result->midi_output = fParams.fReturnMidiChannels; | |||
| strcpy(result->master_name, fParams.fMasterNetName); | |||
| } | |||
| // By default fCycleSize is fPeriodSize | |||
| fCycleSize = fParams.fPeriodSize; | |||
| AllocPorts(); | |||
| return 0; | |||
| } | |||
| @@ -711,7 +758,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| bool Execute() | |||
| { | |||
| try { | |||
| try { | |||
| /* | |||
| Fist cycle use an INT_MAX time out, so that connection | |||
| is considered established (with PACKET_TIMEOUT later on) | |||
| @@ -758,7 +805,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| default: | |||
| // decode sync | |||
| DecodeSyncPacket(); | |||
| DecodeSyncPacket(fCycleSize); | |||
| break; | |||
| } | |||
| @@ -768,11 +815,11 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| } | |||
| return res; | |||
| } | |||
| int Write() | |||
| { | |||
| EncodeSyncPacket(); | |||
| EncodeSyncPacket(fCycleSize); | |||
| if (SyncSend() == SOCKET_ERROR) { | |||
| return SOCKET_ERROR; | |||
| } | |||
| @@ -798,8 +845,8 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| if (Read() == SOCKET_ERROR) { | |||
| return SOCKET_ERROR; | |||
| } | |||
| fProcessCallback(fParams.fPeriodSize, | |||
| fProcessCallback(fCycleSize, | |||
| fParams.fSendAudioChannels, | |||
| fAudioCaptureBuffer, | |||
| fParams.fSendMidiChannels, | |||
| @@ -809,7 +856,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| fParams.fReturnMidiChannels, | |||
| (void**)fMidiPlaybackBuffer, | |||
| fProcessArg); | |||
| // Then write data to network, throw JackNetException in case of network error... | |||
| if (Write() == 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) | |||
| { | |||
| 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) | |||
| { | |||
| 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 | |||
| @@ -361,7 +361,8 @@ namespace Jack | |||
| default: | |||
| //decode sync | |||
| DecodeSyncPacket(); | |||
| int unused_cycle_size; | |||
| DecodeSyncPacket(unused_cycle_size); | |||
| break; | |||
| } | |||
| @@ -575,7 +575,8 @@ namespace Jack | |||
| default: | |||
| // decode sync | |||
| DecodeSyncPacket(); | |||
| int unused_cycle_size; | |||
| DecodeSyncPacket(unused_cycle_size); | |||
| break; | |||
| } | |||
| @@ -724,8 +725,8 @@ Deactivated for now.. | |||
| int mtu = DEFAULT_MTU; | |||
| // Desactivated for now... | |||
| 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_playback_ports = -1; | |||
| int midi_input_ports = -1; | |||
| @@ -544,7 +544,7 @@ namespace Jack | |||
| return rx_bytes; | |||
| } | |||
| void JackNetMasterInterface::EncodeSyncPacket() | |||
| void JackNetMasterInterface::EncodeSyncPacket(int cycle_size) | |||
| { | |||
| // This method contains every step of sync packet informations coding | |||
| // first of all, clear sync packet | |||
| @@ -565,9 +565,10 @@ namespace Jack | |||
| // Write active ports list | |||
| 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 | |||
| @@ -590,6 +591,8 @@ namespace Jack | |||
| if (fNetAudioCaptureBuffer) { | |||
| fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); | |||
| } | |||
| cycle_size = rx_head->fCycleSize; | |||
| } | |||
| // JackNetSlaveInterface ************************************************************************************************ | |||
| @@ -946,7 +949,7 @@ namespace Jack | |||
| } | |||
| // network sync------------------------------------------------------------------------ | |||
| void JackNetSlaveInterface::EncodeSyncPacket() | |||
| void JackNetSlaveInterface::EncodeSyncPacket(int cycle_size) | |||
| { | |||
| // This method contains every step of sync packet informations coding | |||
| // first of all, clear sync packet | |||
| @@ -967,9 +970,10 @@ namespace Jack | |||
| // Write active ports list | |||
| 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 | |||
| @@ -992,6 +996,8 @@ namespace Jack | |||
| if (fNetAudioPlaybackBuffer) { | |||
| fNetAudioPlaybackBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts); | |||
| } | |||
| cycle_size = rx_head->fCycleSize; | |||
| } | |||
| } | |||
| @@ -92,8 +92,8 @@ namespace Jack | |||
| virtual void DecodeTransportData() = 0; | |||
| // 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 SyncSend() = 0; | |||
| @@ -160,8 +160,8 @@ namespace Jack | |||
| int DataSend(); | |||
| // 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 Recv(size_t size, int flags); | |||
| @@ -217,8 +217,8 @@ namespace Jack | |||
| int DataSend(); | |||
| // 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 Send(size_t size, int flags); | |||
| @@ -543,7 +543,8 @@ namespace Jack | |||
| default: | |||
| // Decode sync | |||
| DecodeSyncPacket(); | |||
| int unused_cycle_size; | |||
| DecodeSyncPacket(unused_cycle_size); | |||
| break; | |||
| } | |||
| @@ -1216,6 +1216,7 @@ namespace Jack | |||
| dst_header->fActivePorts = htonl(src_header->fActivePorts); | |||
| dst_header->fCycle = htonl(src_header->fCycle); | |||
| dst_header->fSubCycle = htonl(src_header->fSubCycle); | |||
| dst_header->fCycleSize = htonl(src_header->fCycleSize); | |||
| dst_header->fIsLastPckt = htonl(src_header->fIsLastPckt); | |||
| } | |||
| @@ -1230,6 +1231,7 @@ namespace Jack | |||
| dst_header->fActivePorts = ntohl(src_header->fActivePorts); | |||
| dst_header->fCycle = ntohl(src_header->fCycle); | |||
| dst_header->fSubCycle = ntohl(src_header->fSubCycle); | |||
| dst_header->fCycleSize = ntohl(src_header->fCycleSize); | |||
| dst_header->fIsLastPckt = ntohl(src_header->fIsLastPckt); | |||
| } | |||
| @@ -38,7 +38,7 @@ using namespace std; | |||
| #endif | |||
| #endif | |||
| #define NETWORK_PROTOCOL 7 | |||
| #define NETWORK_PROTOCOL 8 | |||
| #define NET_SYNCHING 0 | |||
| #define SYNC_PACKET_ERROR -2 | |||
| @@ -180,6 +180,7 @@ namespace Jack | |||
| uint32_t fActivePorts; //number of active ports | |||
| uint32_t fCycle; //process cycle 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') | |||
| } POST_PACKED_STRUCTURE; | |||
| @@ -24,45 +24,44 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| 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); | |||
| jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize) / 2); | |||
| Reset(fRingBufferSize); | |||
| } | |||
| JackResampler::~JackResampler() | |||
| JackRingBuffer::~JackRingBuffer() | |||
| { | |||
| if (fRingBuffer) { | |||
| jack_ringbuffer_free(fRingBuffer); | |||
| } | |||
| } | |||
| void JackResampler::Reset(unsigned int new_size) | |||
| void JackRingBuffer::Reset(unsigned int new_size) | |||
| { | |||
| fRingBufferSize = new_size; | |||
| jack_ringbuffer_reset(fRingBuffer); | |||
| 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)); | |||
| } | |||
| unsigned int JackResampler::WriteSpace() | |||
| unsigned int JackRingBuffer::WriteSpace() | |||
| { | |||
| 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); | |||
| 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)) { | |||
| jack_error("JackResampler::Read : producer too slow, missing frames = %d", frames); | |||
| jack_error("JackRingBuffer::Read : producer too slow, missing frames = %d", frames); | |||
| return 0; | |||
| } else { | |||
| 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); | |||
| 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)) { | |||
| jack_error("JackResampler::Write : consumer too slow, skip frames = %d", frames); | |||
| jack_error("JackRingBuffer::Write : consumer too slow, skip frames = %d", frames); | |||
| return 0; | |||
| } else { | |||
| 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); | |||
| jack_log("JackResampler::Read input available = %ld", len); | |||
| jack_log("JackRingBuffer::Read input available = %ld", len); | |||
| 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; | |||
| } else { | |||
| 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); | |||
| jack_log("JackResampler::Write output available = %ld", len); | |||
| jack_log("JackRingBuffer::Write output available = %ld", len); | |||
| 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; | |||
| } else { | |||
| 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: | |||
| jack_ringbuffer_t* fRingBuffer; | |||
| double fRatio; | |||
| unsigned int fRingBufferSize; | |||
| public: | |||
| JackResampler(); | |||
| virtual ~JackResampler(); | |||
| JackRingBuffer(int size = DEFAULT_RB_SIZE); | |||
| virtual ~JackRingBuffer(); | |||
| 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 Write(jack_default_audio_sample_t* buffer, unsigned int frames); | |||
| // in bytes | |||
| virtual unsigned int Read(void* buffer, unsigned int bytes); | |||
| virtual unsigned int Write(void* buffer, unsigned int bytes); | |||
| // in frames | |||
| virtual unsigned int ReadSpace(); | |||
| virtual unsigned int WriteSpace(); | |||
| @@ -71,6 +70,29 @@ class JackResampler | |||
| 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) | |||
| { | |||
| fRatio = Range(0.25, 4.0, ratio); | |||
| @@ -75,6 +75,7 @@ typedef struct { | |||
| jack_nframes_t sample_rate; // master sample rate | |||
| char master_name[MASTER_NAME_SIZE]; // master machine name | |||
| int time_out; // in second, -1 means infinite | |||
| int partial_cycle; // if 'true', partial cycle will be used | |||
| } 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); | |||
| /** | |||
| * Receive sync and data from the network. | |||
| * Receive sync and data from the network (complete buffer). | |||
| * @param net the network connection | |||
| * @param audio_input number of audio inputs | |||
| * @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); | |||
| /** | |||
| * 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 audio_output number of audio outputs | |||
| * @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); | |||
| /** | |||
| * 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 | |||
| /** | |||
| @@ -101,7 +101,7 @@ main (int argc, char *argv[]) | |||
| int i; | |||
| //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; | |||
| float** audio_input_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)); | |||
| } | |||
| /* | |||
| if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { | |||
| printf("jack_net_master_send failure, exiting\n"); | |||
| break; | |||
| @@ -172,6 +173,19 @@ main (int argc, char *argv[]) | |||
| printf("jack_net_master_recv failure, exiting\n"); | |||
| 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); | |||
| }; | |||