More work on audio prompts.

This commit is contained in:
Jonathan Naylor
2017-05-01 20:05:41 +01:00
parent b9ebdee601
commit 196908bedc
10 changed files with 272 additions and 13 deletions

BIN
Audio/de_DE.ambe Normal file

Binary file not shown.

12
Audio/de_DE.indx Normal file
View File

@@ -0,0 +1,12 @@
0 0 18
1 18 24
2 42 24
3 66 24
4 90 27
5 117 29
6 146 28
7 174 31
8 205 23
9 228 25
connected 253 77
disconnected 330 72

BIN
Audio/en_GB.ambe Normal file

Binary file not shown.

12
Audio/en_GB.indx Normal file
View File

@@ -0,0 +1,12 @@
0 0 50
1 50 31
2 81 30
3 111 43
4 154 42
5 196 48
6 244 40
7 284 37
8 321 32
9 353 43
connected 396 52
disconnected 448 45

View File

@@ -52,6 +52,7 @@ m_logFilePath(),
m_logFileRoot(), m_logFileRoot(),
m_voiceEnabled(true), m_voiceEnabled(true),
m_voiceLanguage("en_GB"), m_voiceLanguage("en_GB"),
m_voiceDirectory(),
m_dmrNetworkAddress(), m_dmrNetworkAddress(),
m_dmrNetworkPort(0U), m_dmrNetworkPort(0U),
m_dmrNetworkLocal(0U), m_dmrNetworkLocal(0U),
@@ -143,6 +144,8 @@ bool CConf::read()
m_voiceEnabled = ::atoi(value) == 1; m_voiceEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Language") == 0) else if (::strcmp(key, "Language") == 0)
m_voiceLanguage = value; m_voiceLanguage = value;
else if (::strcmp(key, "Directory") == 0)
m_voiceDirectory = value;
} else if (section == SECTION_XLX_NETWORK) { } else if (section == SECTION_XLX_NETWORK) {
if (::strcmp(key, "Address") == 0) if (::strcmp(key, "Address") == 0)
m_xlxNetworkAddress = value; m_xlxNetworkAddress = value;
@@ -250,6 +253,11 @@ std::string CConf::getVoiceLanguage() const
return m_voiceLanguage; return m_voiceLanguage;
} }
std::string CConf::getVoiceDirectory() const
{
return m_voiceDirectory;
}
std::string CConf::getXLXNetworkAddress() const std::string CConf::getXLXNetworkAddress() const
{ {
return m_xlxNetworkAddress; return m_xlxNetworkAddress;

2
Conf.h
View File

@@ -50,6 +50,7 @@ public:
// The Voice section // The Voice section
bool getVoiceEnabled() const; bool getVoiceEnabled() const;
std::string getVoiceLanguage() const; std::string getVoiceLanguage() const;
std::string getVoiceDirectory() const;
// The DMR Network section // The DMR Network section
std::string getDMRNetworkAddress() const; std::string getDMRNetworkAddress() const;
@@ -80,6 +81,7 @@ private:
bool m_voiceEnabled; bool m_voiceEnabled;
std::string m_voiceLanguage; std::string m_voiceLanguage;
std::string m_voiceDirectory;
unsigned int m_logDisplayLevel; unsigned int m_logDisplayLevel;
unsigned int m_logFileLevel; unsigned int m_logFileLevel;

View File

@@ -250,13 +250,15 @@ int CDMRGateway::run()
CVoice* voice = NULL; CVoice* voice = NULL;
if (m_conf.getVoiceEnabled()) { if (m_conf.getVoiceEnabled()) {
std::string language = m_conf.getVoiceLanguage(); std::string language = m_conf.getVoiceLanguage();
std::string directory = m_conf.getVoiceDirectory();
LogInfo("Voice Parameters"); LogInfo("Voice Parameters");
LogInfo(" Enabled: yes"); LogInfo(" Enabled: yes");
LogInfo(" Language: %s", language.c_str()); LogInfo(" Language: %s", language.c_str());
LogInfo(" Directory: %s", directory.c_str());
voice = new CVoice(language, xlxSlot, xlxTG); voice = new CVoice(directory, language, m_repeater->getId(), xlxSlot, xlxTG);
bool ret = voice->open(); bool ret = voice->open();
if (!ret) { if (!ret) {

View File

@@ -19,6 +19,7 @@ FileRoot=DMRGateway
[Voice] [Voice]
Enabled=1 Enabled=1
Language=en_GB Language=en_GB
Directory=./Audio
[XLX Network] [XLX Network]
Address=xlx950.epf.lu Address=xlx950.epf.lu

214
Voice.cpp
View File

@@ -16,35 +16,190 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include "DMRSlotType.h"
#include "DMRFullLC.h"
#include "DMREMB.h"
#include "Voice.h" #include "Voice.h"
#include "Sync.h"
#include "Log.h"
CVoice::CVoice(const std::string& language, unsigned int slot, unsigned int tg) : #include <cstring>
m_language(language),
#include <sys/stat.h>
const unsigned char COLOR_CODE = 3U;
CVoice::CVoice(const std::string& directory, const std::string& language, unsigned int id, unsigned int slot, unsigned int tg) :
m_indxFile(),
m_ambeFile(),
m_slot(slot), m_slot(slot),
m_tg(tg), m_lc(FLCO_GROUP, id, tg),
m_embeddedLC(),
m_status(VS_NONE), m_status(VS_NONE),
m_timer(1000U, 1U), m_timer(1000U, 1U),
m_stopWatch() m_stopWatch(),
m_seqNo(0U),
m_streamId(0U),
m_sent(0U),
m_ambe(NULL),
m_data(),
m_it(),
m_start(),
m_length()
{ {
m_embeddedLC.setLC(m_lc);
#if defined(_WIN32) || defined(_WIN64)
m_indxFile = directory + "\\" + language + ".indx";
m_ambeFile = directory + "\\" + language + ".ambe";
#else
m_indxFile = directory + "/" + language + ".indx";
m_ambeFile = directory + "/" + language + ".ambe";
#endif
} }
CVoice::~CVoice() CVoice::~CVoice()
{ {
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
m_data.clear();
delete[] m_ambe;
} }
bool CVoice::open() bool CVoice::open()
{ {
FILE* fpindx = ::fopen(m_indxFile.c_str(), "rt");
if (fpindx == NULL) {
LogError("Unable to open the index file - %s", m_indxFile.c_str());
return false;
}
struct stat statStruct;
int ret = ::stat(m_ambeFile.c_str(), &statStruct);
if (ret != 0) {
LogError("Unable to stat the AMBE file - %s", m_ambeFile.c_str());
::fclose(fpindx);
return false;
}
FILE* fpambe = ::fopen(m_ambeFile.c_str(), "rb");
if (fpambe == NULL) {
LogError("Unable to open the AMBE file - %s", m_ambeFile.c_str());
::fclose(fpindx);
return false;
}
m_ambe = new unsigned char[statStruct.st_size];
::fread(m_ambe, 1U, statStruct.st_size, fpambe);
char buffer[80U];
while (::fgets(buffer, 80, fpindx) != NULL) {
char* p1 = ::strtok(buffer, "\t\r\n");
char* p2 = ::strtok(NULL, "\t\r\n");
char* p3 = ::strtok(NULL, "\t\r\n");
if (p1 != NULL && p2 != NULL && p3 != NULL) {
unsigned int start = ::atoi(p2) * 9U;
unsigned int length = ::atoi(p3) * 9U;
m_start[p1] = start;
m_length[p1] = length;
}
}
::fclose(fpindx);
::fclose(fpambe);
return true; return true;
} }
void CVoice::linkedTo(unsigned int id) void CVoice::linkedTo(unsigned int id)
{ {
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
m_data.clear();
m_streamId = ::rand() + 1U;
m_seqNo = 0U;
createHeaderTerminator(DT_VOICE_LC_HEADER);
createHeaderTerminator(DT_VOICE_LC_HEADER);
createHeaderTerminator(DT_VOICE_LC_HEADER);
unsigned int length = 0U;
unsigned char* ambe = new unsigned char[10000U];
delete[] ambe;
createHeaderTerminator(DT_TERMINATOR_WITH_LC);
m_status = VS_WAITING; m_status = VS_WAITING;
m_timer.start(); m_timer.start();
} }
void CVoice::unlinked() void CVoice::unlinked()
{ {
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
m_data.clear();
m_streamId = ::rand() + 1U;
m_seqNo = 0U;
createHeaderTerminator(DT_VOICE_LC_HEADER);
createHeaderTerminator(DT_VOICE_LC_HEADER);
createHeaderTerminator(DT_VOICE_LC_HEADER);
unsigned int start = m_start["disconnected"];
unsigned int length = m_length["disconnected"] / 9U;
unsigned char buffer[DMR_FRAME_LENGTH_BYTES];
unsigned char* p = m_ambe + start;
for (unsigned int i = 0U; i < length; i++, p += 27U) {
CDMRData* data = new CDMRData;
data->setSlotNo(m_slot);
data->setFLCO(FLCO_GROUP);
data->setSrcId(m_lc.getSrcId());
data->setDstId(m_lc.getDstId());
data->setN();
data->setSeqNo(m_seqNo++);
data->setStreamId(m_streamId);
::memcpy(buffer + 0U, p + 0U, 9U);
::memcpy(buffer + 9U, p + 9U, 9U);
::memcpy(buffer + 15U, p + 9U, 9U);
::memcpy(buffer + 24U, p + 18U, 9U);
if (n == 0U) {
CSync::addDMRAudioSync(buffer);
data->setDataType(DT_VOICE_SYNC);
} else {
CDMREMB emb;
emb.setColorCode(COLOR_CODE);
emb.setPI(false);
emb.setLCSS();
emb.getData(buffer);
m_embeddedLC.getData(buffer, n);
data->setDataType(DT_VOICE);
}
data->setData(buffer);
m_data.push_back(data);
}
createHeaderTerminator(DT_TERMINATOR_WITH_LC);
m_status = VS_WAITING; m_status = VS_WAITING;
m_timer.start(); m_timer.start();
} }
@@ -54,6 +209,25 @@ bool CVoice::read(CDMRData& data)
if (m_status != VS_SENDING) if (m_status != VS_SENDING)
return false; return false;
unsigned int count = m_stopWatch.elapsed() / DMR_SLOT_TIME;
if (m_sent < count) {
data = *(*m_it);
++m_sent;
++m_it;
if (m_it == m_data.end()) {
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
m_data.clear();
m_timer.stop();
m_status = VS_NONE;
}
return true;
}
return false; return false;
} }
@@ -64,6 +238,38 @@ void CVoice::clock(unsigned int ms)
if (m_status == VS_WAITING) { if (m_status == VS_WAITING) {
m_stopWatch.start(); m_stopWatch.start();
m_status = VS_SENDING; m_status = VS_SENDING;
m_it = m_data.begin();
m_sent = 0U;
} }
} }
} }
void CVoice::createHeaderTerminator(unsigned char type)
{
CDMRData* data = new CDMRData;
data->setSlotNo(m_slot);
data->setFLCO(FLCO_GROUP);
data->setSrcId(m_lc.getSrcId());
data->setDstId(m_lc.getDstId());
data->setDataType(type);
data->setN(0U);
data->setSeqNo(m_seqNo++);
data->setStreamId(m_streamId);
unsigned char buffer[DMR_FRAME_LENGTH_BYTES];
CDMRFullLC fullLC;
fullLC.encode(m_lc, buffer, type);
CDMRSlotType slotType;
slotType.setColorCode(COLOR_CODE);
slotType.setDataType(type);
slotType.getData(buffer);
CSync::addDMRDataSync(buffer, true);
data->setData(buffer);
m_data.push_back(data);
}

30
Voice.h
View File

@@ -19,11 +19,15 @@
#if !defined(Voice_H) #if !defined(Voice_H)
#define Voice_H #define Voice_H
#include "DMREmbeddedData.h"
#include "StopWatch.h" #include "StopWatch.h"
#include "DMRData.h" #include "DMRData.h"
#include "DMRLC.h"
#include "Timer.h" #include "Timer.h"
#include <unordered_map>
#include <string> #include <string>
#include <vector>
enum VOICE_STATUS { enum VOICE_STATUS {
VS_NONE, VS_NONE,
@@ -33,7 +37,7 @@ enum VOICE_STATUS {
class CVoice { class CVoice {
public: public:
CVoice(const std::string& language, unsigned int slot, unsigned int tg); CVoice(const std::string& directory, const std::string& language, unsigned int id, unsigned int slot, unsigned int tg);
~CVoice(); ~CVoice();
bool open(); bool open();
@@ -46,12 +50,24 @@ public:
void clock(unsigned int ms); void clock(unsigned int ms);
private: private:
std::string m_language; std::string m_indxFile;
unsigned int m_slot; std::string m_ambeFile;
unsigned int m_tg; unsigned int m_slot;
VOICE_STATUS m_status; CDMRLC m_lc;
CTimer m_timer; CDMREmbeddedData m_embeddedLC;
CStopWatch m_stopWatch; VOICE_STATUS m_status;
CTimer m_timer;
CStopWatch m_stopWatch;
unsigned int m_seqNo;
unsigned int m_streamId;
unsigned int m_sent;
unsigned char* m_ambe;
std::vector<CDMRData*> m_data;
std::vector<CDMRData*>::const_iterator m_it;
std::unordered_map<std::string, unsigned int> m_start;
std::unordered_map<std::string, unsigned int> m_length;
void createHeaderTerminator(unsigned char type);
}; };
#endif #endif