コード例 #1
0
ファイル: YSFControl.cpp プロジェクト: g4klx/MMDVMHost
bool CYSFControl::insertSilence(const unsigned char* data, unsigned char n)
{
	assert(data != NULL);

	// Check to see if we have any spaces to fill?
	unsigned char newN = (m_netN + 1U) % 128U;
	if (newN == n) {
		// Just copy the data, nothing else to do here
		::memcpy(m_lastFrame, data, YSF_FRAME_LENGTH_BYTES + 2U);
		m_lastFrameValid = true;
		return true;
	}

	LogDebug("YSF, current=%u last=%u", n, m_netN);

	unsigned int count;
	if (n > newN)
		count = n - newN;
	else
		count = (128U + n) - newN;

	if (count >= 4U) {
		LogDebug("YSF, frame is out of range, count = %u", count);
		return false;
	}

	insertSilence(count);

	::memcpy(m_lastFrame, data, YSF_FRAME_LENGTH_BYTES + 2U);
	m_lastFrameValid = true;

	return true;
}
コード例 #2
0
ファイル: AudioDecoderThread.cpp プロジェクト: BeepC/libavg
void AudioDecoderThread::handleSeekDone(AVPacket* pPacket)
{
    m_MsgQ.clear();
    m_LastFrameTime = float(pPacket->dts*av_q2d(m_pStream->time_base))
            - m_AudioStartTimestamp;

   if (fabs(m_LastFrameTime - m_SeekTime) < 0.01) {
        pushSeekDone(m_LastFrameTime, m_SeekSeqNum);
        decodePacket(pPacket);
        m_State = DECODING;
    } else {
        if (m_LastFrameTime-0.01f < m_SeekTime) {
            // Received frame that's earlier than the destination, so throw away frames
            // until the time is correct.
            m_State = DISCARDING;
        } else {
            // Received frame that's too late, so insert a buffer of silence to 
            // compensate.
            insertSilence(m_LastFrameTime - m_SeekTime);
            m_LastFrameTime = m_SeekTime;
            pushSeekDone(m_LastFrameTime, m_SeekSeqNum);
            decodePacket(pPacket);
            m_State = DECODING;
        }
    }
}
コード例 #3
0
ファイル: DStarControl.cpp プロジェクト: zarya/MMDVMHost
void CDStarControl::insertSilence(const unsigned char* data, unsigned char seqNo)
{
	assert(data != NULL);

	// Check to see if we have any spaces to fill?
	unsigned char seq = (m_n + 1U) % 21U;
	if (seq == seqNo) {
		// Just copy the data, nothing else to do here
		::memcpy(m_lastFrame, data, DSTAR_FRAME_LENGTH_BYTES + 1U);
		return;
	}

	unsigned int oldSeqNo = (m_n + 1U) % 21U;
	unsigned int newSeqNo = seqNo;

	unsigned int count;
	if (newSeqNo > oldSeqNo)
		count = newSeqNo - oldSeqNo;
	else
		count = (21U + newSeqNo) - oldSeqNo;

	if (count < 10U)
		insertSilence(count);

	::memcpy(m_lastFrame, data, DSTAR_FRAME_LENGTH_BYTES + 1U);
}
コード例 #4
0
ファイル: DStarControl.cpp プロジェクト: zarya/MMDVMHost
void CDStarControl::clock(unsigned int ms)
{
	if (m_network != NULL)
		writeNetwork();

	m_ackTimer.clock(ms);
	if (m_ackTimer.isRunning() && m_ackTimer.hasExpired()) {
		sendAck();
		m_ackTimer.stop();
	}

	m_holdoffTimer.clock(ms);
	if (m_holdoffTimer.isRunning() && m_holdoffTimer.hasExpired())
		m_holdoffTimer.stop();

	m_timeoutTimer.clock(ms);

	if (m_state == RS_RELAYING_NETWORK_AUDIO) {
		m_networkWatchdog.clock(ms);

		if (m_networkWatchdog.hasExpired()) {
			// We're received the header haven't we?
			m_frames += 1U;
			if (m_bits == 0U) m_bits = 1U;
			LogMessage("D-Star, network watchdog has expired, %.1f seconds,  %u%% packet loss, BER: %.1f%%", float(m_frames) / 50.0F, (m_lost * 100U) / m_frames, float(m_errs * 100U) / float(m_bits));
			m_timeoutTimer.stop();
			writeEndOfTransmission();
#if defined(DUMP_DSTAR)
			closeFile();
#endif
		}
	}

	if (m_state == RS_RELAYING_NETWORK_AUDIO) {
		m_packetTimer.clock(ms);

		if (m_packetTimer.isRunning() && m_packetTimer.hasExpired()) {
			unsigned int frames = m_elapsed.elapsed() / DSTAR_FRAME_TIME;

			if (frames > m_frames) {
				unsigned int count = frames - m_frames;
				if (count > 3U) {
					LogMessage("D-Star, lost audio for 300ms filling in, %u %u", frames, m_frames);
					insertSilence(count - 1U);
				}
			}

			m_packetTimer.start();
		}
	}
}
コード例 #5
0
ファイル: DMRSlot.cpp プロジェクト: jcyfkimi/MMDVMHost
void CDMRSlot::clock(unsigned int ms)
{
	m_timeoutTimer.clock(ms);

	if (m_state == RS_RELAYING_NETWORK_AUDIO || m_state == RS_RELAYING_NETWORK_DATA) {
		m_networkWatchdog.clock(ms);

		if (m_networkWatchdog.hasExpired()) {
			// We've received the voice header haven't we?
			m_frames += 1U;
			if (m_state == RS_RELAYING_NETWORK_AUDIO)
				LogMessage("DMR Slot %u, network watchdog has expired, %u%% packet loss, BER: %u%%", m_slotNo, (m_lost * 100U) / m_frames, (m_errs * 100U) / m_bits);
			else
				LogMessage("DMR Slot %u, network watchdog has expired", m_slotNo);
			writeEndOfTransmission();
#if defined(DUMP_DMR)
			closeFile();
#endif
		}
	}

	if (m_state == RS_RELAYING_NETWORK_AUDIO) {
		m_packetTimer.clock(ms);

		if (m_packetTimer.hasExpired()) {
			unsigned int frames = m_elapsed.elapsed() / DMR_SLOT_TIME;

			if (frames > m_frames) {
				unsigned int count = frames - m_frames;
				if (count > 3U)
					insertSilence(m_seqNo + count - 1U);
			}

			m_packetTimer.start();
		}
	}
}
コード例 #6
0
ファイル: DStarControl.cpp プロジェクト: zarya/MMDVMHost
void CDStarControl::writeNetwork()
{
	assert(m_network != NULL);

	unsigned char data[DSTAR_HEADER_LENGTH_BYTES + 2U];
	unsigned int length = m_network->read(data, DSTAR_HEADER_LENGTH_BYTES + 2U);
	if (length == 0U)
		return;

	if (m_state == RS_RELAYING_RF_AUDIO || m_state == RS_LATE_ENTRY)
		return;

	m_networkWatchdog.start();

	unsigned char type = data[0U];

	if (type == TAG_HEADER) {
		if (m_state != RS_LISTENING)
			return;

		CDStarHeader header(data + 1U);

		unsigned char my1[DSTAR_LONG_CALLSIGN_LENGTH];
		header.getMyCall1(my1);

		unsigned char my2[DSTAR_SHORT_CALLSIGN_LENGTH];
		header.getMyCall2(my2);

		unsigned char your[DSTAR_LONG_CALLSIGN_LENGTH];
		header.getYourCall(your);

		m_header = header;

		m_timeoutTimer.start();
		m_elapsed.start();
		m_ackTimer.stop();

		m_frames = 0U;
		m_lost = 0U;

		m_n = 0U;

		m_bits = 1U;
		m_errs = 0U;

		writeQueueHeader(data);

#if defined(DUMP_DSTAR)
		openFile();
		writeFile(data + 1U, length - 1U);
#endif
		m_state = RS_RELAYING_NETWORK_AUDIO;

		m_display->writeDStar(std::string((char*)my1, 8U), std::string((char*)my2, 4U));

		LogMessage("D-Star, received network header from %8.8s/%4.4s to %8.8s", my1, my2, your);
	} else if (type == TAG_EOT) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		m_timeoutTimer.stop();

		data[1U] = TAG_EOT;
		for (unsigned int i = 0U; i < 3U; i++)
			writeQueueData(data + 1U);

#if defined(DUMP_DSTAR)
		writeFile(data + 1U, length - 1U);
		closeFile();
#endif
		// We've received the header and EOT haven't we?
		m_frames += 2U;
		if (m_bits == 0U) m_bits = 1U;
		LogMessage("D-Star, received network end of transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%", float(m_frames) / 50.0F, (m_lost * 100U) / m_frames, float(m_errs * 100U) / float(m_bits));

		writeEndOfTransmission();
	} else if (type == TAG_DATA) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		unsigned char n = data[1U];

		insertSilence(data + 2U, n);

		m_errs += m_fec.regenerateDStar(data + 2U);
		m_bits += 48U;

		blankDTMF(data + 2U);

		// Regenerate the sync
		if (n == 0U)
			::memcpy(data + DSTAR_VOICE_FRAME_LENGTH_BYTES + 2U, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES);

		m_n = n;

		m_packetTimer.start();
		m_frames++;

		data[1U] = TAG_DATA;

#if defined(DUMP_DSTAR)
		writeFile(data + 1U, length - 1U);
#endif
		writeQueueData(data + 1U);
	} else {
		CUtils::dump("D-Star, unknown data from network", data, DSTAR_FRAME_LENGTH_BYTES + 1U);
	}
}
コード例 #7
0
ファイル: DMRSlot.cpp プロジェクト: jcyfkimi/MMDVMHost
void CDMRSlot::writeNetwork(const CDMRData& dmrData)
{
	if (m_state == RS_RELAYING_RF_AUDIO || m_state == RS_RELAYING_RF_DATA || m_state == RS_LATE_ENTRY)
		return;

	m_networkWatchdog.start();

	unsigned char dataType = dmrData.getDataType();

	unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
	dmrData.getData(data + 2U);

	if (dataType == DT_VOICE_LC_HEADER) {
		if (m_state == RS_RELAYING_NETWORK_AUDIO)
			return;

		CFullLC fullLC;
		m_lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER);
		if (m_lc == NULL) {
			LogMessage("DMR Slot %u, bad LC received from the network", m_slotNo);
			return;
		}

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_VOICE_LC_HEADER);
		slotType.getData(data + 2U);

		// Convert the Data Sync to be from the BS
		CDMRSync sync;
		sync.addSync(data + 2U, DST_BS_DATA);

		data[0U] = TAG_DATA;
		data[1U] = 0x00U;

		m_timeoutTimer.start();

		m_frames = 0U;

		m_bits = 1U;
		m_errs = 0U;

		// 540ms of idle to give breathing space for lost frames
		for (unsigned int i = 0U; i < 9U; i++)
			writeQueue(m_idle);

		for (unsigned int i = 0U; i < 3U; i++)
			writeQueue(data);

		m_state = RS_RELAYING_NETWORK_AUDIO;

		setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO());

		m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId());

#if defined(DUMP_DMR)
		openFile();
		writeFile(data);
#endif
		LogMessage("DMR Slot %u, received network voice header from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId());
	} else if (dataType == DT_VOICE_PI_HEADER) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_VOICE_PI_HEADER);
		slotType.getData(data + 2U);

		// Convert the Data Sync to be from the BS
		CDMRSync sync;
		sync.addSync(data + 2U, DST_BS_DATA);

		data[0U] = TAG_DATA;
		data[1U] = 0x00U;

		writeQueue(data);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else if (dataType == DT_TERMINATOR_WITH_LC) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_TERMINATOR_WITH_LC);
		slotType.getData(data + 2U);

		// Convert the Data Sync to be from the BS
		CDMRSync sync;
		sync.addSync(data + 2U, DST_BS_DATA);

		data[0U] = TAG_EOT;
		data[1U] = 0x00U;

		writeQueue(data);
		writeEndOfTransmission();

#if defined(DUMP_DMR)
		writeFile(data);
		closeFile();
#endif
		// We've received the voice header and terminator haven't we?
		m_frames += 2U;
		LogMessage("DMR Slot %u, received network end of voice transmission, %u%% packet loss, BER: %u%%", m_slotNo, (m_lost * 100U) / m_frames, (m_errs * 100U) / m_bits);
	} else if (dataType == DT_DATA_HEADER) {
		if (m_state == RS_RELAYING_NETWORK_DATA)
			return;

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_DATA_HEADER);
		slotType.getData(data + 2U);

		// Convert the Data Sync to be from the BS
		CDMRSync sync;
		sync.addSync(data + 2U, DST_BS_DATA);

		data[0U] = TAG_DATA;
		data[1U] = 0x00U;

		// Put a small delay into starting transmission
		writeQueue(m_idle);
		writeQueue(m_idle);

		for (unsigned i = 0U; i < 3U; i++)
			writeQueue(data);

		m_state = RS_RELAYING_NETWORK_DATA;

		// setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO());

		// m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId());

		// LogMessage("DMR Slot %u, received network data header from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId());
		LogMessage("DMR Slot %u, received network data header", m_slotNo);
	} else if (dataType == DT_VOICE_SYNC) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		// Initialise the lost packet data
		if (m_frames == 0U) {
			m_seqNo = dmrData.getSeqNo();
			m_n     = dmrData.getN();
			m_elapsed.start();
			m_lost = 0U;
		} else {
			insertSilence(dmrData.getSeqNo());
		}

		// Convert the Audio Sync to be from the BS
		CDMRSync sync;
		sync.addSync(data + 2U, DST_BS_AUDIO);

		unsigned char fid = m_lc->getFID();
		if (fid == FID_ETSI || fid == FID_DMRA)
			m_errs += m_fec.regenerateDMR(data + 2U);
		m_bits += 216U;

		data[0U] = TAG_DATA;
		data[1U] = 0x00U;

		writeQueue(data);

		m_packetTimer.start();
		m_frames++;

		// Save details in case we need to infill data
		m_seqNo = dmrData.getSeqNo();
		m_n     = dmrData.getN();
		::memcpy(m_lastFrame, data, DMR_FRAME_LENGTH_BYTES + 2U);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else if (dataType == DT_VOICE) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		// Initialise the lost packet data
		if (m_frames == 0U) {
			m_seqNo = dmrData.getSeqNo();
			m_n     = dmrData.getN();
			m_elapsed.start();
			m_lost = 0U;
		} else {
			insertSilence(dmrData.getSeqNo());
		}

		unsigned char fid = m_lc->getFID();
		if (fid == FID_ETSI || fid == FID_DMRA)
			m_errs += m_fec.regenerateDMR(data + 2U);
		m_bits += 216U;

		// Change the color code in the EMB
		CEMB emb;
		emb.putData(data + 2U);
		emb.setColorCode(m_colorCode);
		emb.getData(data + 2U);

		data[0U] = TAG_DATA;
		data[1U] = 0x00U;

		writeQueue(data);

		m_packetTimer.start();
		m_frames++;

		// Save details in case we need to infill data
		m_seqNo = dmrData.getSeqNo();
		m_n     = dmrData.getN();
		::memcpy(m_lastFrame, data, DMR_FRAME_LENGTH_BYTES + 2U);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else {
		// Change the Color Code of the Slot Type
		CSlotType slotType;
		slotType.putData(data + 2U);
		slotType.setColorCode(m_colorCode);
		slotType.getData(data + 2U);

		// Convert the Data Sync to be from the BS
		CDMRSync sync;
		sync.addSync(data + 2U, DST_BS_DATA);

		data[0U] = TAG_DATA;
		data[1U] = 0x00U;

		writeQueue(data);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	}
}