git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3932 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
| @@ -115,6 +115,7 @@ namespace Jack | |||||
| fParams.fPeriodSize * sizeof(sample_t) / PACKET_AVAILABLE_SIZE); | fParams.fPeriodSize * sizeof(sample_t) / PACKET_AVAILABLE_SIZE); | ||||
| //bufsize = sync + audio + midi | //bufsize = sync + audio + midi | ||||
| bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size); | bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size); | ||||
| jack_info("SetNetBufferSize bufsize = %d", bufsize); | |||||
| //tx buffer | //tx buffer | ||||
| if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR ) | if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR ) | ||||
| @@ -298,8 +299,12 @@ namespace Jack | |||||
| assert ( fNetMidiPlaybackBuffer ); | assert ( fNetMidiPlaybackBuffer ); | ||||
| //audio net buffers | //audio net buffers | ||||
| fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData ); | |||||
| fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData ); | |||||
| fNetAudioCaptureBuffer = new NetSingleAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData ); | |||||
| fNetAudioPlaybackBuffer = new NetSingleAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData ); | |||||
| //fNetAudioCaptureBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData ); | |||||
| //fNetAudioPlaybackBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData ); | |||||
| assert ( fNetAudioCaptureBuffer ); | assert ( fNetAudioCaptureBuffer ); | ||||
| assert ( fNetAudioPlaybackBuffer ); | assert ( fNetAudioPlaybackBuffer ); | ||||
| @@ -387,7 +392,7 @@ namespace Jack | |||||
| bool JackNetMasterInterface::IsSynched() | bool JackNetMasterInterface::IsSynched() | ||||
| { | { | ||||
| if (fParams.fNetworkMode == 's') { | if (fParams.fNetworkMode == 's') { | ||||
| return (fCycleOffset < 3); | |||||
| return (fCycleOffset < (CYCLE_OFFSET_SLOW + 1)); | |||||
| } else { | } else { | ||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -464,13 +469,13 @@ namespace Jack | |||||
| // - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master | // - 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 | // - 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) | //the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process) | ||||
| if (fCycleOffset < 2) { | |||||
| if (fCycleOffset < CYCLE_OFFSET_SLOW) { | |||||
| return 0; | return 0; | ||||
| } else { | } else { | ||||
| rx_bytes = Recv ( rx_head->fPacketSize, 0 ); | rx_bytes = Recv ( rx_head->fPacketSize, 0 ); | ||||
| } | } | ||||
| if (fCycleOffset > 2) { | |||||
| if (fCycleOffset > CYCLE_OFFSET_SLOW) { | |||||
| jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); | jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -514,6 +519,8 @@ namespace Jack | |||||
| uint jumpcnt = 0; | uint jumpcnt = 0; | ||||
| uint recvd_midi_pckt = 0; | uint recvd_midi_pckt = 0; | ||||
| uint recvd_audio_pckt = 0; | uint recvd_audio_pckt = 0; | ||||
| int last_cycle = 0; | |||||
| packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer ); | packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer ); | ||||
| while ( !fRxHeader.fIsLastPckt ) | while ( !fRxHeader.fIsLastPckt ) | ||||
| @@ -553,16 +560,22 @@ namespace Jack | |||||
| fRxHeader.fCycle = rx_head->fCycle; | fRxHeader.fCycle = rx_head->fCycle; | ||||
| fRxHeader.fSubCycle = rx_head->fSubCycle; | fRxHeader.fSubCycle = rx_head->fSubCycle; | ||||
| fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | ||||
| fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle ); | |||||
| fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fCycle, rx_head->fSubCycle); | |||||
| jumpcnt = 0; | jumpcnt = 0; | ||||
| last_cycle = rx_head->fCycle; | |||||
| break; | break; | ||||
| case 's': //sync | case 's': //sync | ||||
| jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName); | jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName); | ||||
| // Finish rendering (copy to JACK ports) | |||||
| fNetAudioPlaybackBuffer->FinishRenderToJackPorts(last_cycle); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| // Finish rendering (copy to JACK ports) | |||||
| fNetAudioPlaybackBuffer->FinishRenderToJackPorts(last_cycle); | |||||
| return rx_bytes; | return rx_bytes; | ||||
| } | } | ||||
| @@ -790,8 +803,11 @@ namespace Jack | |||||
| fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData ); | fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData ); | ||||
| //audio net buffers | //audio net buffers | ||||
| fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData ); | |||||
| fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData ); | |||||
| fNetAudioCaptureBuffer = new NetSingleAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData ); | |||||
| fNetAudioPlaybackBuffer = new NetSingleAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData ); | |||||
| //fNetAudioCaptureBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData ); | |||||
| //fNetAudioPlaybackBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData ); | |||||
| //audio netbuffer length | //audio netbuffer length | ||||
| fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize(); | fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize(); | ||||
| @@ -867,6 +883,8 @@ namespace Jack | |||||
| uint recvd_midi_pckt = 0; | uint recvd_midi_pckt = 0; | ||||
| uint recvd_audio_pckt = 0; | uint recvd_audio_pckt = 0; | ||||
| int rx_bytes = 0; | int rx_bytes = 0; | ||||
| int last_cycle = 0; | |||||
| packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer ); | packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer ); | ||||
| while ( !fRxHeader.fIsLastPckt ) | while ( !fRxHeader.fIsLastPckt ) | ||||
| @@ -893,21 +911,26 @@ namespace Jack | |||||
| case 'a': //audio | case 'a': //audio | ||||
| rx_bytes = Recv ( rx_head->fPacketSize, 0 ); | rx_bytes = Recv ( rx_head->fPacketSize, 0 ); | ||||
| if (recvd_audio_pckt++ != rx_head->fSubCycle) { | if (recvd_audio_pckt++ != rx_head->fSubCycle) { | ||||
| //jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName); | |||||
| jack_error("Packet(s) missing from '%s'... %d %d %d", fParams.fMasterNetName, rx_head->fCycle, recvd_audio_pckt, rx_head->fSubCycle); | |||||
| jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName); | |||||
| } | } | ||||
| fRxHeader.fCycle = rx_head->fCycle; | fRxHeader.fCycle = rx_head->fCycle; | ||||
| fRxHeader.fSubCycle = rx_head->fSubCycle; | fRxHeader.fSubCycle = rx_head->fSubCycle; | ||||
| fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | ||||
| fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle ); | |||||
| fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fCycle, rx_head->fSubCycle); | |||||
| last_cycle = rx_head->fCycle; | |||||
| break; | break; | ||||
| case 's': //sync | case 's': //sync | ||||
| jack_info ( "NetSlave : overloaded, skipping receive." ); | jack_info ( "NetSlave : overloaded, skipping receive." ); | ||||
| // Finish rendering (copy to JACK ports) | |||||
| fNetAudioCaptureBuffer->FinishRenderToJackPorts(last_cycle); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| // Finish rendering (copy to JACK ports) | |||||
| fNetAudioCaptureBuffer->FinishRenderToJackPorts(last_cycle); | |||||
| fRxHeader.fCycle = rx_head->fCycle; | fRxHeader.fCycle = rx_head->fCycle; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -212,6 +212,7 @@ namespace Jack | |||||
| #define MASTER_INIT_TIMEOUT 1000000 // in usec | #define MASTER_INIT_TIMEOUT 1000000 // in usec | ||||
| #define SLAVE_INIT_TIMEOUT 2000000 // in usec | #define SLAVE_INIT_TIMEOUT 2000000 // in usec | ||||
| #define MAX_LATENCY 6 | |||||
| #define CYCLE_OFFSET_SLOW 2 | |||||
| #define MAX_LATENCY CYCLE_OFFSET_SLOW * 4 | |||||
| #endif | #endif | ||||
| @@ -127,93 +127,93 @@ namespace Jack | |||||
| // net audio buffer ********************************************************************************* | // net audio buffer ********************************************************************************* | ||||
| NetAudioBuffer::NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) | |||||
| NetSingleAudioBuffer::NetSingleAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) | |||||
| : fPortBuffer(params, nports), fNetBuffer(net_buffer) | |||||
| {} | |||||
| NetSingleAudioBuffer::~NetSingleAudioBuffer() | |||||
| {} | |||||
| size_t NetSingleAudioBuffer::GetSize() | |||||
| { | { | ||||
| fNPorts = nports; | |||||
| fPeriodSize = params->fPeriodSize; | |||||
| fSubPeriodSize = params->fFramesPerPacket; | |||||
| fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); | |||||
| fPortBuffer = new sample_t* [fNPorts]; | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| fPortBuffer[port_index] = NULL; | |||||
| fNetBuffer = net_buffer; | |||||
| return fPortBuffer.GetSize(); | |||||
| } | } | ||||
| NetAudioBuffer::~NetAudioBuffer() | |||||
| void NetSingleAudioBuffer::SetBuffer ( int index, sample_t* buffer ) | |||||
| { | { | ||||
| delete[] fPortBuffer; | |||||
| fPortBuffer.SetBuffer(index, buffer); | |||||
| } | } | ||||
| size_t NetAudioBuffer::GetSize() | |||||
| sample_t* NetSingleAudioBuffer::GetBuffer ( int index ) | |||||
| { | { | ||||
| return fNPorts * fSubPeriodBytesSize; | |||||
| return fPortBuffer.GetBuffer(index); | |||||
| } | } | ||||
| void NetAudioBuffer::SetBuffer ( int index, sample_t* buffer ) | |||||
| void NetSingleAudioBuffer::RenderFromJackPorts (int subcycle) | |||||
| { | { | ||||
| fPortBuffer[index] = buffer; | |||||
| fPortBuffer.RenderFromJackPorts(fNetBuffer, subcycle); | |||||
| } | } | ||||
| sample_t* NetAudioBuffer::GetBuffer ( int index ) | |||||
| void NetSingleAudioBuffer::RenderToJackPorts (int cycle, int subcycle) | |||||
| { | { | ||||
| return fPortBuffer[index]; | |||||
| fPortBuffer.RenderToJackPorts(fNetBuffer, subcycle); | |||||
| } | } | ||||
| #ifdef __BIG_ENDIAN__ | |||||
| // Buffered | |||||
| static inline float SwapFloat(float f) | |||||
| NetBufferedAudioBuffer::NetBufferedAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) | |||||
| { | { | ||||
| union | |||||
| { | |||||
| float f; | |||||
| unsigned char b[4]; | |||||
| } dat1, dat2; | |||||
| fMaxCycle = 0; | |||||
| fNetBuffer = net_buffer; | |||||
| for (int i = 0; i < AUDIO_BUFFER_SIZE; i++) { | |||||
| fPortBuffer[i].Init(params, nports); | |||||
| } | |||||
| fJackPortBuffer = new sample_t* [nports]; | |||||
| for ( int port_index = 0; port_index < nports; port_index++ ) | |||||
| fJackPortBuffer[port_index] = NULL; | |||||
| } | |||||
| dat1.f = f; | |||||
| dat2.b[0] = dat1.b[3]; | |||||
| dat2.b[1] = dat1.b[2]; | |||||
| dat2.b[2] = dat1.b[1]; | |||||
| dat2.b[3] = dat1.b[0]; | |||||
| return dat2.f; | |||||
| NetBufferedAudioBuffer::~NetBufferedAudioBuffer() | |||||
| { | |||||
| delete [] fJackPortBuffer; | |||||
| } | } | ||||
| void NetAudioBuffer::RenderFromJackPorts ( int subcycle ) | |||||
| size_t NetBufferedAudioBuffer::GetSize() | |||||
| { | { | ||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) { | |||||
| float* src = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); | |||||
| float* dst = (float*)(fNetBuffer + port_index * fSubPeriodBytesSize); | |||||
| for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { | |||||
| dst[sample] = SwapFloat(src[sample]); | |||||
| } | |||||
| } | |||||
| return fPortBuffer[0].GetSize(); | |||||
| } | } | ||||
| void NetAudioBuffer::RenderToJackPorts ( int subcycle ) | |||||
| void NetBufferedAudioBuffer::SetBuffer ( int index, sample_t* buffer ) | |||||
| { | { | ||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) { | |||||
| float* src = (float*)(fNetBuffer + port_index * fSubPeriodBytesSize); | |||||
| float* dst = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); | |||||
| for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { | |||||
| dst[sample] = SwapFloat(src[sample]); | |||||
| } | |||||
| } | |||||
| fJackPortBuffer[index] = buffer; | |||||
| } | } | ||||
| #else | |||||
| void NetAudioBuffer::RenderFromJackPorts ( int subcycle ) | |||||
| sample_t* NetBufferedAudioBuffer::GetBuffer ( int index ) | |||||
| { | { | ||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| memcpy ( fNetBuffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize ); | |||||
| return fJackPortBuffer[index]; | |||||
| } | |||||
| void NetBufferedAudioBuffer::RenderFromJackPorts (int subcycle ) | |||||
| { | |||||
| fPortBuffer[0].RenderFromJackPorts(fNetBuffer, subcycle); // Always use first buffer... | |||||
| } | } | ||||
| void NetAudioBuffer::RenderToJackPorts ( int subcycle ) | |||||
| void NetBufferedAudioBuffer::RenderToJackPorts (int cycle, int subcycle) | |||||
| { | { | ||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize ); | |||||
| if (cycle < fMaxCycle) { | |||||
| jack_info("Wrong order fCycle %d subcycle %d fMaxCycle %d", cycle, subcycle, fMaxCycle); | |||||
| } | |||||
| fPortBuffer[cycle % AUDIO_BUFFER_SIZE].RenderToJackPorts(fNetBuffer, subcycle); | |||||
| } | } | ||||
| #endif | |||||
| void NetBufferedAudioBuffer::FinishRenderToJackPorts (int cycle) | |||||
| { | |||||
| fMaxCycle = std::max(fMaxCycle, cycle); | |||||
| fPortBuffer[(cycle + 1) % AUDIO_BUFFER_SIZE].Copy(fJackPortBuffer); // Copy internal buffer in JACK ports | |||||
| } | |||||
| // SessionParams ************************************************************************************ | // SessionParams ************************************************************************************ | ||||
| @@ -248,6 +248,25 @@ namespace Jack | |||||
| // audio data ********************************************************************************* | // audio data ********************************************************************************* | ||||
| class SERVER_EXPORT NetAudioBuffer | |||||
| { | |||||
| public: | |||||
| NetAudioBuffer () | |||||
| {} | |||||
| ~NetAudioBuffer() | |||||
| {} | |||||
| virtual size_t GetSize() = 0; | |||||
| //jack<->buffer | |||||
| virtual void RenderFromJackPorts (int subcycle ) = 0; | |||||
| virtual void RenderToJackPorts ( int cycle, int subcycle) = 0; | |||||
| virtual void FinishRenderToJackPorts (int cycle) = 0; | |||||
| virtual void SetBuffer ( int index, sample_t* buffer ) = 0; | |||||
| virtual sample_t* GetBuffer ( int index ) = 0; | |||||
| }; | |||||
| /** | /** | ||||
| \Brief Audio buffer and operations class | \Brief Audio buffer and operations class | ||||
| @@ -257,24 +276,191 @@ namespace Jack | |||||
| So there is no need of an intermediate buffer as in NetMidiBuffer. | So there is no need of an intermediate buffer as in NetMidiBuffer. | ||||
| */ | */ | ||||
| struct JackPortList { | |||||
| jack_nframes_t fPeriodSize; | |||||
| jack_nframes_t fSubPeriodSize; | |||||
| size_t fSubPeriodBytesSize; | |||||
| sample_t** fPortBuffer; | |||||
| int fNPorts; | |||||
| JackPortList(session_params_t* params, uint32_t nports) | |||||
| { | |||||
| fNPorts = nports; | |||||
| fPeriodSize = params->fPeriodSize; | |||||
| fSubPeriodSize = params->fFramesPerPacket; | |||||
| fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); | |||||
| fPortBuffer = new sample_t* [fNPorts]; | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| fPortBuffer[port_index] = NULL; | |||||
| } | |||||
| JackPortList() | |||||
| { | |||||
| fNPorts = 0; | |||||
| fPeriodSize = 0; | |||||
| fSubPeriodSize = 0; | |||||
| fSubPeriodBytesSize = 0; | |||||
| fPortBuffer = 0; | |||||
| } | |||||
| ~JackPortList() | |||||
| { | |||||
| delete [] fPortBuffer; | |||||
| } | |||||
| void SetBuffer( int index, sample_t* buffer ) | |||||
| { | |||||
| fPortBuffer[index] = buffer; | |||||
| } | |||||
| sample_t* GetBuffer ( int index ) | |||||
| { | |||||
| return fPortBuffer[index]; | |||||
| } | |||||
| void Copy(sample_t** buffers) | |||||
| { | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| memcpy(buffers[port_index], fPortBuffer[port_index], fPeriodSize * sizeof(float)); | |||||
| } | |||||
| size_t GetSize() | |||||
| { | |||||
| return fNPorts * fSubPeriodBytesSize; | |||||
| } | |||||
| #ifdef __BIG_ENDIAN__ | |||||
| static inline float SwapFloat(float f) | |||||
| { | |||||
| union | |||||
| { | |||||
| float f; | |||||
| unsigned char b[4]; | |||||
| } dat1, dat2; | |||||
| dat1.f = f; | |||||
| dat2.b[0] = dat1.b[3]; | |||||
| dat2.b[1] = dat1.b[2]; | |||||
| dat2.b[2] = dat1.b[1]; | |||||
| dat2.b[3] = dat1.b[0]; | |||||
| return dat2.f; | |||||
| } | |||||
| void RenderFromJackPorts (char* net_buffer, int subcycle ) | |||||
| { | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) { | |||||
| float* src = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); | |||||
| float* dst = (float*)(net_buffer + port_index * fSubPeriodBytesSize); | |||||
| for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { | |||||
| dst[sample] = SwapFloat(src[sample]); | |||||
| } | |||||
| } | |||||
| } | |||||
| void RenderToJackPorts (char* net_buffer, int subcycle) | |||||
| { | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) { | |||||
| float* src = (float*)(net_buffer + port_index * fSubPeriodBytesSize); | |||||
| float* dst = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); | |||||
| for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { | |||||
| dst[sample] = SwapFloat(src[sample]); | |||||
| } | |||||
| } | |||||
| } | |||||
| #else | |||||
| void RenderFromJackPorts (char* net_buffer, int subcycle ) | |||||
| { | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| memcpy ( net_buffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize ); | |||||
| } | |||||
| void RenderToJackPorts (char* net_buffer, int subcycle) | |||||
| { | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, net_buffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize ); | |||||
| } | |||||
| #endif | |||||
| }; | |||||
| struct JackPortListAllocate : public JackPortList { | |||||
| JackPortListAllocate() | |||||
| { | |||||
| fNPorts = 0; | |||||
| fPeriodSize = 0; | |||||
| fSubPeriodSize = 0; | |||||
| fSubPeriodBytesSize = 0; | |||||
| fPortBuffer = 0; | |||||
| } | |||||
| ~JackPortListAllocate() | |||||
| { | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| delete [] fPortBuffer[port_index]; | |||||
| delete [] fPortBuffer; | |||||
| } | |||||
| void Init(session_params_t* params, uint32_t nports) | |||||
| { | |||||
| fNPorts = nports; | |||||
| fPeriodSize = params->fPeriodSize; | |||||
| fSubPeriodSize = params->fFramesPerPacket; | |||||
| fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); | |||||
| fPortBuffer = new sample_t* [fNPorts]; | |||||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||||
| fPortBuffer[port_index] = new sample_t[fPeriodSize]; | |||||
| } | |||||
| }; | |||||
| class SERVER_EXPORT NetAudioBuffer | |||||
| class SERVER_EXPORT NetSingleAudioBuffer : public NetAudioBuffer | |||||
| { | { | ||||
| private: | private: | ||||
| int fNPorts; | |||||
| jack_nframes_t fPeriodSize; | |||||
| jack_nframes_t fSubPeriodSize; | |||||
| size_t fSubPeriodBytesSize; | |||||
| JackPortList fPortBuffer; | |||||
| char* fNetBuffer; | |||||
| public: | |||||
| NetSingleAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); | |||||
| ~NetSingleAudioBuffer(); | |||||
| size_t GetSize(); | |||||
| //jack<->buffer | |||||
| void RenderFromJackPorts (int subcycle ); | |||||
| void RenderToJackPorts (int cycle, int subcycle); | |||||
| void SetBuffer ( int index, sample_t* buffer ); | |||||
| sample_t* GetBuffer ( int index ); | |||||
| void FinishRenderToJackPorts (int cycle) {} | |||||
| }; | |||||
| #define AUDIO_BUFFER_SIZE 8 | |||||
| class SERVER_EXPORT NetBufferedAudioBuffer : public NetAudioBuffer | |||||
| { | |||||
| private: | |||||
| char* fNetBuffer; | char* fNetBuffer; | ||||
| sample_t** fPortBuffer; | |||||
| JackPortListAllocate fPortBuffer[AUDIO_BUFFER_SIZE]; | |||||
| sample_t** fJackPortBuffer; | |||||
| int fMaxCycle; | |||||
| public: | public: | ||||
| NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); | |||||
| ~NetAudioBuffer(); | |||||
| NetBufferedAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); | |||||
| ~NetBufferedAudioBuffer(); | |||||
| size_t GetSize(); | size_t GetSize(); | ||||
| //jack<->buffer | //jack<->buffer | ||||
| void RenderFromJackPorts ( int subcycle ); | |||||
| void RenderToJackPorts ( int subcycle ); | |||||
| void RenderFromJackPorts (int subcycle ); | |||||
| void RenderToJackPorts ( int cycle, int subcycle); | |||||
| void FinishRenderToJackPorts (int cycle); | |||||
| void SetBuffer ( int index, sample_t* buffer ); | void SetBuffer ( int index, sample_t* buffer ); | ||||
| sample_t* GetBuffer ( int index ); | sample_t* GetBuffer ( int index ); | ||||
| @@ -137,7 +137,7 @@ namespace Jack | |||||
| T Add ( T measure_point ) | T Add ( T measure_point ) | ||||
| { | { | ||||
| return fCurrentMeasure[fMeasureId++] = measure_point; | |||||
| return fCurrentMeasure[fMeasureId++] = measure_point; | |||||
| } | } | ||||
| uint32_t AddLast ( T measure_point ) | uint32_t AddLast ( T measure_point ) | ||||
| @@ -118,14 +118,14 @@ void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData, UInt32 i | |||||
| } | } | ||||
| } | } | ||||
| int TiPhoneCoreAudioRenderer::OpenDefault(int bufferSize, int samplerate) | |||||
| int TiPhoneCoreAudioRenderer::Open(int bufferSize, int samplerate) | |||||
| { | { | ||||
| OSStatus err1; | OSStatus err1; | ||||
| UInt32 outSize; | UInt32 outSize; | ||||
| UInt32 enableIO; | UInt32 enableIO; | ||||
| AudioStreamBasicDescription srcFormat, dstFormat; | AudioStreamBasicDescription srcFormat, dstFormat; | ||||
| printf("OpenDefault fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate); | |||||
| printf("Open fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate); | |||||
| // Initialize and configure the audio session | // Initialize and configure the audio session | ||||
| err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); | err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); | ||||
| @@ -78,7 +78,7 @@ class TiPhoneCoreAudioRenderer | |||||
| } | } | ||||
| } | } | ||||
| int OpenDefault(int bufferSize, int sampleRate); | |||||
| int Open(int bufferSize, int sampleRate); | |||||
| int Close(); | int Close(); | ||||
| int Start(); | int Start(); | ||||
| @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { | |||||
| audio_output_buffer[i] = (float*)(calloc(buffer_size, sizeof(float))); | audio_output_buffer[i] = (float*)(calloc(buffer_size, sizeof(float))); | ||||
| } | } | ||||
| if (audio_device.OpenDefault(buffer_size, sample_rate) < 0) { | |||||
| if (audio_device.Open(buffer_size, sample_rate) < 0) { | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -11,8 +11,8 @@ | |||||
| #include "TiPhoneCoreAudioRenderer.h" | #include "TiPhoneCoreAudioRenderer.h" | ||||
| #define NUM_INPUT 2 | |||||
| #define NUM_OUTPUT 2 | |||||
| #define NUM_INPUT 1 | |||||
| #define NUM_OUTPUT 1 | |||||
| jack_net_slave_t* net; | jack_net_slave_t* net; | ||||
| jack_adapter_t* adapter; | jack_adapter_t* adapter; | ||||
| @@ -33,23 +33,36 @@ static int net_process(jack_nframes_t buffer_size, | |||||
| 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 | |||||
| if (audio_input == audio_output) { | |||||
| // Copy input to output | |||||
| for (int i = 0; i < audio_input; i++) { | |||||
| memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); | |||||
| } | |||||
| } | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static void SlaveAudioCallback(int frames, float** inputs, float** outputs, void* arg) | static void SlaveAudioCallback(int frames, float** inputs, float** outputs, void* arg) | ||||
| { | { | ||||
| jack_adapter_push_and_pull(adapter, inputs, outputs, frames); | |||||
| //jack_adapter_push_and_pull(adapter, inputs, outputs, frames); | |||||
| } | } | ||||
| //http://www.securityfocus.com/infocus/1884 | |||||
| #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_INPUT, NUM_OUTPUT, 0, 0, DEFAULT_MTU, -1, JackSlowMode }; | |||||
| jack_slave_t request = { NUM_INPUT, NUM_OUTPUT, 0, 0, WIFI_MTU, -1, JackSlowMode }; | |||||
| jack_master_t result; | jack_master_t result; | ||||
| if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { | |||||
| if ((net = jack_net_slave_open("169.254.136.64", DEFAULT_PORT, "iPhone", &request, &result)) == 0) { | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -69,7 +82,7 @@ int main(int argc, char *argv[]) { | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| if (audio_device.OpenDefault(result.buffer_size, result.sample_rate) < 0) { | |||||
| if (audio_device.Open(result.buffer_size, result.sample_rate) < 0) { | |||||
| return -1; | return -1; | ||||
| } | } | ||||