gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

tcpConnection.cpp (5553B)


      1 #include "tcpConnection.h"
      2 
      3 #include "audioBuffers.h"
      4 #include "networkLib/exception.h"
      5 #include "networkLib/logging.h"
      6 
      7 #include "synthLib/midiTypes.h"
      8 
      9 namespace bridgeLib
     10 {
     11 	TcpConnection::TcpConnection(std::unique_ptr<networkLib::TcpStream>&& _stream) : CommandReader(nullptr), m_stream(std::move(_stream))
     12 	{
     13 		m_audioTransferBuffer.reserve(16384);
     14 
     15 		start();
     16 	}
     17 
     18 	TcpConnection::~TcpConnection()
     19 	{
     20 		shutdown();
     21 	}
     22 
     23 	void TcpConnection::handleCommand(const Command _command, baseLib::BinaryStream& _in)
     24 	{
     25 		switch (_command)
     26 		{
     27 		case Command::Invalid:
     28 		case Command::Ping:
     29 		case Command::Pong:
     30 			break;
     31 		case Command::PluginInfo:			handleStruct<PluginDesc>(_in); break;
     32 		case Command::ServerInfo:			handleStruct<ServerInfo>(_in); break;
     33 		case Command::Error:				handleStruct<Error>(_in); break;
     34 		case Command::DeviceInfo:			handleDeviceInfo(_in); break;
     35 		case Command::Midi:					handleMidi(_in); break;
     36 		case Command::Audio:				handleAudio(_in); break;
     37 		case Command::DeviceState:			handleDeviceState(_in); break;
     38 		case Command::RequestDeviceState:	handleRequestDeviceState(_in); break;
     39 		case Command::DeviceCreateParams:	handleStruct<DeviceCreateParams>(_in); break;
     40 		case Command::SetSamplerate:		handleStruct<SetSamplerate>(_in); break;
     41 		case Command::SetDspClockPercent:	handleStruct<SetDspClockPercent>(_in); break;
     42 		case Command::SetUnknownCustomData:	handleStruct<SetUnknownCustomData>(_in); break;
     43 		}
     44 	}
     45 
     46 	void TcpConnection::threadFunc()
     47 	{
     48 		try
     49 		{
     50 			NetworkThread::threadFunc();
     51 		}
     52 		catch (const networkLib::NetException& e)
     53 		{
     54 			m_stream->close();
     55 			LOGNET(networkLib::LogLevel::Warning, "Network Exception, code " << e.type() << ": " << e.what());
     56 			handleException(e);
     57 		}
     58 	}
     59 
     60 	void TcpConnection::threadLoopFunc()
     61 	{
     62 		read(*m_stream);
     63 	}
     64 
     65 	void TcpConnection::send(const Command _command, const CommandStruct& _data)
     66 	{
     67 		m_writer.build(_command, _data);
     68 		m_writer.write(*m_stream);
     69 	}
     70 
     71 	void TcpConnection::send(Command _command)
     72 	{
     73 		m_writer.build(_command);
     74 		m_writer.write(*m_stream);
     75 	}
     76 
     77 	void TcpConnection::handleMidi(baseLib::BinaryStream& _in)
     78 	{
     79 		synthLib::SMidiEvent& ev = m_midiEvent;
     80 		_in.read(ev.a);
     81 		_in.read(ev.b);
     82 		_in.read(ev.c);
     83 		_in.read(ev.sysex);
     84 		_in.read(ev.offset);
     85 		ev.source = static_cast<synthLib::MidiEventSource>(_in.read<uint8_t>());
     86 		handleMidi(ev);
     87 	}
     88 
     89 	void TcpConnection::sendAudio(const float* const* _data, const uint32_t _numChannels, const uint32_t _numSamplesPerChannel)
     90 	{
     91 		auto& s = m_writer.build(Command::Audio);
     92 		s.write(static_cast<uint8_t>(_numChannels));
     93 		s.write(_numSamplesPerChannel);
     94 
     95 		for(uint32_t i=0; i<_numChannels; ++i)
     96 		{
     97 			// if a channel has data, write it. If not, write 0 for the length
     98 			if(const float* channelData = _data[i])
     99 			{
    100 				s.write(_numSamplesPerChannel);
    101 				s.write(channelData, _numSamplesPerChannel);
    102 			}
    103 			else
    104 			{
    105 				s.write(0);
    106 			}
    107 		}
    108 		send();
    109 	}
    110 
    111 	void TcpConnection::sendAudio(AudioBuffers& _buffers, const uint32_t _numChannels, uint32_t _numSamplesPerChannel)
    112 	{
    113 		auto& s = m_writer.build(Command::Audio);
    114 		s.write(static_cast<uint8_t>(_numChannels));
    115 		s.write(_numSamplesPerChannel);
    116 
    117 		if(m_audioTransferBuffer.size() < _numSamplesPerChannel)
    118 			m_audioTransferBuffer.resize(_numSamplesPerChannel);
    119 
    120 		for(uint32_t i=0; i<_numChannels; ++i)
    121 		{
    122 			_buffers.readInput(i, m_audioTransferBuffer, _numSamplesPerChannel);
    123 			s.write(_numSamplesPerChannel);
    124 			s.write(m_audioTransferBuffer.data(), _numSamplesPerChannel);
    125 		}
    126 
    127 		_buffers.onInputRead(_numSamplesPerChannel);
    128 
    129 		send();
    130 	}
    131 
    132 	uint32_t TcpConnection::handleAudio(float* const* _output, baseLib::BinaryStream& _in)
    133 	{
    134 		const uint32_t numChannels = _in.read<uint8_t>();
    135 		const uint32_t numSamplesMax = _in.read<uint32_t>();
    136 
    137 		for(uint32_t i=0; i<numChannels; ++i)
    138 		{
    139 			const auto numSamples = _in.read<uint32_t>();
    140 			if(numSamples)
    141 			{
    142 				assert(_output[i]);
    143 				_in.read(_output[i], numSamples);
    144 			}
    145 		}
    146 		return numSamplesMax;
    147 	}
    148 
    149 	void TcpConnection::handleAudio(AudioBuffers& _buffers, baseLib::BinaryStream& _in)
    150 	{
    151 		const uint32_t numChannels = _in.read<uint8_t>();
    152 		const uint32_t numSamplesMax = _in.read<uint32_t>();
    153 
    154 		for(uint32_t i=0; i<numChannels; ++i)
    155 		{
    156 			const auto numSamples = _in.read<uint32_t>();
    157 
    158 			if(numSamples)
    159 			{
    160 				if(m_audioTransferBuffer.size() < numSamples)
    161 					m_audioTransferBuffer.resize(numSamples);
    162 				_in.read(m_audioTransferBuffer.data(), numSamples);
    163 				_buffers.writeOutput(i, m_audioTransferBuffer, numSamples);
    164 			}
    165 		}
    166 		_buffers.onOutputWritten(numSamplesMax);
    167 	}
    168 
    169 	void TcpConnection::handleAudio(baseLib::BinaryStream& _in)
    170 	{
    171 	}
    172 
    173 	void TcpConnection::handleRequestDeviceState(baseLib::BinaryStream& _in)
    174 	{
    175 		RequestDeviceState requestDeviceState;
    176 		requestDeviceState.read(_in);
    177 		handleRequestDeviceState(requestDeviceState);
    178 	}
    179 
    180 	void TcpConnection::handleDeviceState(baseLib::BinaryStream& _in)
    181 	{
    182 		m_deviceState.read(_in);
    183 		handleDeviceState(m_deviceState);
    184 	}
    185 
    186 	void TcpConnection::handleDeviceInfo(baseLib::BinaryStream& _in)
    187 	{
    188 		handleStruct<DeviceDesc>(_in);
    189 	}
    190 
    191 	bool TcpConnection::send(const synthLib::SMidiEvent& _ev)
    192 	{
    193 		if(!isValid())
    194 			return false;
    195 		auto& bs = m_writer.build(Command::Midi);
    196 		bs.write(_ev.a);
    197 		bs.write(_ev.b);
    198 		bs.write(_ev.c);
    199 		bs.write(_ev.sysex);
    200 		bs.write(_ev.offset);
    201 		bs.write<uint8_t>(static_cast<uint8_t>(_ev.source));
    202 		send();
    203 		return true;
    204 	}
    205 
    206 	void TcpConnection::close() const
    207 	{
    208 		if(m_stream)
    209 			m_stream->close();
    210 	}
    211 
    212 	void TcpConnection::shutdown()
    213 	{
    214 		close();
    215 		stop();
    216 		m_stream.reset();
    217 	}
    218 }