diff --git a/Controller.cpp b/Controller.cpp index 755db5c..5984dce 100644 --- a/Controller.cpp +++ b/Controller.cpp @@ -14,36 +14,32 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include #include +#include "TranscoderPacket.h" #include "Controller.h" bool CController::Start() { - if (reader.Open("urfd2tcd")) + if (InitDevices() || reader.Open("urfd2tcd")) { keep_running = false; return true; } - future = std::async(std::launch::async, &CController::Processing, this); + reflectorThread = std::async(std::launch::async, &CController::ReadReflector, this); + ambeThread = std::async(std::launch::async, &CController::ReadAmbeDevices, this); return false; } void CController::Stop() { keep_running = false; - future.get(); + reflectorThread.get(); + ambeThread.get(); reader.Close(); } -void CController::Processing() -{ - while (keep_running) - { - // anything to read? - } -} - bool CController::InitDevices() { // unpack all the device paths @@ -80,13 +76,25 @@ bool CController::InitDevices() // add it to the list, according to type if (Encoding::dstar == type) - dstar_devices.push_back(a3003); + { + dstar_device.push_back(a3003); + dstar_vocoder_count += 3; + } else - dmr_devices.push_back(a3003); + { + dmr_device.push_back(a3003); + dmr_vocoder_count += 3; + } // finally, toggle the type for the next device type = (type == Encoding::dstar) ? Encoding::dmr : Encoding::dstar; } + + dmr_audio_block.resize(dmr_vocoder_count); + dmr_packet_queue.resize(dmr_vocoder_count); + dstar_audio_block.resize(dstar_vocoder_count); + dstar_packet_queue.resize(dstar_vocoder_count); + return false; } @@ -104,3 +112,133 @@ void CController::CSVtoSet(const std::string &str, std::set &set, c pos = str.find_first_of(delimiters, lastPos); // Find next non-delimiter. } } + +void CController::IncrementDMRVocoder() +{ + current_dmr_vocoder = (current_dmr_vocoder + 1) % dmr_vocoder_count; +} + +void CController::IncrementDStarVocoder() +{ + current_dstar_vocoder = (current_dstar_vocoder + 1) % dstar_vocoder_count; +} + +void CController::ReadReflector() +{ + while (keep_running) { + STCPacket tcpack; + //wait up to 40 ms to read something on the unix port + if (reader.Receive(&tcpack, 40)) { + //create a std::shared_ptr to a new packet + auto packet = std::unique_ptr(new CTranscoderPacket(tcpack)); + switch (packet->GetCodecIn()) { + case ECodecType::dstar: + //send it to the next available dstar vocoder + dstar_device[current_dstar_vocoder/3]->SendData(current_dstar_vocoder%3, packet->GetDStarData()); + //push the packet onto that vocoder's queue + dstar_packet_queue[current_dstar_vocoder].push(packet); + //increment the dstar vocoder index + IncrementDStarVocoder(); + break; + case ECodecType::dmr: + //send it to the next avaiable dmr vocoder + dmr_device[current_dmr_vocoder/3]->SendData(current_dmr_vocoder%3, packet->GetDMRData()); + //push the packet onto that vocoder's queue + dmr_packet_queue[current_dmr_vocoder].push(packet); + //increment the dmr vocoder index + IncrementDMRVocoder(); + break; + case ECodecType::c2_1600: + case ECodecType::c2_3200: + if (packet->IsSecond()) { + if (packet->GetCodecIn() == ECodecType::c2_3200) { + //decode the second 8 data bytes + //move the 160 audio samples to the packet + } else /* the codec is C2_1600 */ { + //copy the audio from local storage + } + // encode the audio to dstar + //create a 3003 audio packet + //save the dstar vocoder index in the packet + //push the packet onto the dstar vocoder's queue + //send the 3003 audio packet to the dstar vocoder specified in the packet + //increment the dstar vocoder index + // encode the audio to dmr + //save the dmr vocoder index in the packet + //push the packet onto the dmr vocoder's queue + //send the same 3003 audio packet to the dmr vocoder specified in the packet + //increment the dmr vocoder index + } else /* it's a "first packet" */ { + //decode the first 8 bytes of data to get the up to 320 audio samples + //move the first 160 audio samples to the packet + // encode the audio to dstar + //create a 3003 audio packet + //save the dstar vocoder index in the packet + //push the packet onto the vocoder's queue + //send it to the dstar vocoder specified in the packet + //increment the dstar vocoder index + // encode the audio to dmr + //save the dmr vocoder index in the packet + //push the packet onto the vocoder's queue + //send the same audio packet to the dmr vocoder specified in the packet + //increment the dmr vocoder index + // save the second half of the audio if the m17 packet was c2_1600 + if (packet->GetCodecIn() == ECodecType::c2_1600) { + //put the second 160 audio samples into local storage + } + } + } + } + } +} + +void CController::ReadAmbeDevices() +{ + while (keep_running) + { + //wait for up to 40 ms to read anthing from all devices + if (something is ready to be read) { + // from the device file descriptor, we'll know if it's dstar or dmr + //save the dmr/dstar type + //read the response from the vocoder + //get the packet from either the dstar or dmr vocoder's queue + if (the response is audio) { + // if the response is audio, this means that packet.codec_in is an ambe codec + // so we need to encode the m17 + //encode the audio to c2_3200 + if (packet.IsSecond()) { + //move the c2_3200 data to the second half of the M17 packet + } else /* the packet is first */ { + //move the c2_3200 data do the first half of the M17 packet + if (packet->IsLast()) { + // we have an odd number of packets, so we have to do finish up the m17 packet + const uint8_t silence[] = {0x00, 0x01, 0x43, 0x09, 0xe4, 0x9c, 0x08, 0x21 }; + //put codec silence in the second half of the codec + } + } + //create a 3003 audio packet + //move the response audio to the packet + if (the dmr/dstar type == dstar) { + //send the audio packet to the next available dmr vocoder + //push the packet onto the dmr vocoder's queue + //increment the dmr vocoder index + } else /* the dmr/dstar type is dmr */ { + //send the audio packet to the next available dstar vocoder + //push the packet onto the dstar vocoder's queue + //increment the dstar vocoder index + } + } else /* the response is ambe */ { + if (the dmr/dstar type == dstar) { + //move the ambe to the packet.dstar + } else { + //move the ambe to the packet.dmr + } + if (packet.AllCodecsAreSet()) { + //open a socket to the reflector channel + //send the packet over the socket + //close the socket + } + } + } + } +} diff --git a/Controller.h b/Controller.h index 1825c8a..f9c95f5 100644 --- a/Controller.h +++ b/Controller.h @@ -22,27 +22,47 @@ #include #include +#include "PacketQueue.h" #include "DV3003.h" #include "configure.h" #include "UnixDgramSocket.h" +// local audio storage +class CAudioBlock +{ +public: + int16_t operator [](int i) const {return audio[i];} + int16_t & operator [](int i) {return audio[i];} + int16_t *data() { return audio; } + const int16_t *cdata() const { return audio; } +protected: + int16_t audio[160]; +}; + class CController { public: - CController() : keep_running(true) {} - bool InitDevices(); + CController() : dmr_vocoder_count(0), current_dmr_vocoder(0), dstar_vocoder_count(0), current_dstar_vocoder(0), keep_running(true) {} bool Start(); void Stop(); bool IsRunning() { return keep_running; } -private: +protected: + unsigned int dmr_vocoder_count, current_dmr_vocoder, dstar_vocoder_count, current_dstar_vocoder; std::atomic keep_running; - std::future future; - std::vector> dmr_devices, dstar_devices; + std::future reflectorThread, ambeThread; + std::vector> dmr_device, dstar_device; CUnixDgramReader reader; CUnixDgramWriter writer; + std::vector dmr_audio_block, dstar_audio_block; + std::vector dmr_packet_queue, dstar_packet_queue; - void Processing(); + bool InitDevices(); + void IncrementDMRVocoder(void); + void IncrementDStarVocoder(void); + // processing threads + void ReadReflector(); + void ReadAmbeDevices(); void CSVtoSet(const std::string &str, std::set &set, const std::string &delimiters = ","); }; diff --git a/PacketQueue.h b/PacketQueue.h index cc8adef..452f438 100644 --- a/PacketQueue.h +++ b/PacketQueue.h @@ -22,21 +22,41 @@ #include #include -#include "TCPacketDef.h" +#include "TranscoderPacket.h" +// for holding CTranscoder packets while the vocoders are working their magic class CPacketQueue { public: - // lock - void Lock() { mutex.lock(); } - void Unlock() { mutex.unlock(); } - // pass thru - std::unique_ptr pop() { auto pack = std::move(queue.front()); queue.pop(); return std::move(pack); } - bool empty() const { return queue.empty(); } - void push(std::unique_ptr &packet) { queue.push(std::move(packet)); } + std::unique_ptr pop() + { + std::unique_ptr pack; + mutex.lock(); + if (! queue.empty()) { + pack = std::move(queue.front()); + queue.pop(); + } + mutex.unlock(); + return std::move(pack); + } + + bool empty() + { + mutex.lock(); + bool rval = queue.empty(); + mutex.unlock(); + return rval; + } + + void push(std::unique_ptr &packet) + { + mutex.lock(); + queue.push(std::move(packet)); + mutex.unlock(); + } protected: - std::mutex mutex; - std::queue> queue; + std::mutex mutex; + std::queue> queue; }; diff --git a/TranscoderPacket.cpp b/TranscoderPacket.cpp index 4f182f6..724db24 100644 --- a/TranscoderPacket.cpp +++ b/TranscoderPacket.cpp @@ -14,11 +14,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include + #include "TranscoderPacket.h" -CTranscoderPacket::CTranscoderPacket(char mod) : dstar_set(false), dmr_set(false), m17_set(false) +CTranscoderPacket::CTranscoderPacket(const STCPacket &tcp) : dstar_set(false), dmr_set(false), m17_set(false) { - tcpacket.module = mod; + tcpacket.module = tcp.module; + tcpacket.is_last = tcp.is_last; + tcpacket.is_second = tcp.is_second; + tcpacket.streamid = tcp.streamid; + tcpacket.codec_in = tcp.codec_in; + switch (tcp.codec_in) + { + case ECodecType::dstar: + SetDStarData(tcp.dstar); + break; + case ECodecType::dmr: + SetDMRData(tcp.dmr); + break; + case ECodecType::c2_1600: + case ECodecType::c2_3200: + SetM17Data(tcp.m17); + break; + default: + std::cerr << "Trying to allocate CTranscoderPacket with an unknown codec type!" << std::endl; + break; + } } char CTranscoderPacket::GetModule() const @@ -52,11 +74,15 @@ void CTranscoderPacket::SetDMRData(const uint8_t *dmr ) dmr_set = true; } -void CTranscoderPacket::SetM17Data(const uint8_t *m17, bool is_3200) +void CTranscoderPacket::SetM17Data(const uint8_t *m17) { - memcpy(tcpacket.m17, m17, is_3200 ? 16 : 8); + memcpy(tcpacket.m17, m17, 16); m17_set = true; - m17_is_3200 = is_3200; +} + +int16_t *CTranscoderPacket::GetAudio() +{ + return audio; } ECodecType CTranscoderPacket::GetCodecIn() const @@ -64,6 +90,21 @@ ECodecType CTranscoderPacket::GetCodecIn() const return tcpacket.codec_in; } +uint16_t CTranscoderPacket::GetStreamId() const +{ + return tcpacket.streamid; +} + +bool CTranscoderPacket::IsLast() const +{ + return tcpacket.is_last; +} + +bool CTranscoderPacket::IsSecond() const +{ + return tcpacket.is_second; +} + bool CTranscoderPacket::DStarIsSet() const { return dstar_set; @@ -79,12 +120,7 @@ bool CTranscoderPacket::M17IsSet() const return m17_set; } -bool CTranscoderPacket::M17Is3200() const -{ - return m17_is_3200; -} - -bool CTranscoderPacket::AllAreSet() const +bool CTranscoderPacket::AllCodecsAreSet() const { return (dstar_set && dmr_set && m17_set); } diff --git a/TranscoderPacket.h b/TranscoderPacket.h index e81c7ea..d33caa4 100644 --- a/TranscoderPacket.h +++ b/TranscoderPacket.h @@ -22,11 +22,13 @@ #include "TCPacketDef.h" +enum class EAudioSection { firsthalf, secondhalf, all }; + class CTranscoderPacket { public: // constructor - CTranscoderPacket(char mod); + CTranscoderPacket(const STCPacket &tcp); // this packet's refector module; char GetModule() const; @@ -36,19 +38,24 @@ public: const uint8_t *GetDMRData(); const uint8_t *GetM17Data(); void SetDStarData(const uint8_t *dstar); - void SetDMRData(const uint8_t *dmr ); - void SetM17Data(const uint8_t *m17, bool is_3200); + void SetDMRData(const uint8_t *dmr); + void SetM17Data(const uint8_t *m17); + + // audio + int16_t *GetAudio(); // state of packet ECodecType GetCodecIn() const; + uint16_t GetStreamId() const; + bool IsLast() const; + bool IsSecond() const; bool DStarIsSet() const; bool DMRIsSet() const; bool M17IsSet() const; - bool M17Is3200() const; - bool AllAreSet() const; + bool AllCodecsAreSet() const; private: STCPacket tcpacket; - uint16_t audio[320]; - bool m17_is_3200, dstar_set, dmr_set, m17_set; + int16_t audio[160]; + bool dstar_set, dmr_set, m17_set; };