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;
};