📄 codecs.cxx
字号:
}unsigned H323AudioCodec::GetFrameRate() const{ return samplesPerFrame;}unsigned H323AudioCodec::GetTimeUnits() const{ return 8; // Assuming standard 8kHz sample rate}BOOL H323AudioCodec::NeedsJitterBuffer() const{ return TRUE;}BOOL H323AudioCodec::AttachChannel(PChannel * channel, BOOL autoDelete){ if (deleteChannel) delete rawDataChannel; rawDataChannel = channel; deleteChannel = autoDelete; return channel != NULL;}void H323AudioCodec::Close(){ if (rawDataChannel != NULL) rawDataChannel->Close();}H323AudioCodec::SilenceDetectionMode H323AudioCodec::GetSilenceDetectionMode() const{ return silenceDetectMode;}void H323AudioCodec::SetSilenceDetectionMode(SilenceDetectionMode mode, unsigned threshold, unsigned signalDeadband, unsigned silenceDeadband, unsigned adaptivePeriod){ silenceDetectMode = mode; // The silence deadband is the number of frames of low energy that have to // occur before the system stops sending data over the RTP link. signalDeadbandFrames = (signalDeadband+samplesPerFrame-1)/samplesPerFrame; silenceDeadbandFrames = (silenceDeadband+samplesPerFrame-1)/samplesPerFrame; // This is the period over which the adaptive algorithm operates adaptiveThresholdFrames = (adaptivePeriod+samplesPerFrame-1)/samplesPerFrame; if (mode != AdaptiveSilenceDetection) { levelThreshold = threshold; return; } // Initials threshold levels levelThreshold = 0; // Initialise the adaptive threshold variables. signalMinimum = UINT_MAX; silenceMaximum = 0; signalFramesReceived = 0; silenceFramesReceived = 0; // Restart in silent mode inTalkBurst = FALSE;}BOOL H323AudioCodec::DetectSilence(){ // Can never have silence if NoSilenceDetection if (silenceDetectMode == NoSilenceDetection) return FALSE; // Can never have average signal level that high, this indicates that the // hardware cannot do silence detection. unsigned level = GetAverageSignalLevel(); if (level == UINT_MAX) return FALSE; // Convert to a logarithmic scale - use uLaw which is complemented level = linear2ulaw(level) ^ 0xff; // Now if signal level above threshold we are "talking" BOOL haveSignal = level > levelThreshold; // If no change ie still talking or still silent, resent frame counter if (inTalkBurst == haveSignal) framesReceived = 0; else { framesReceived++; // If have had enough consecutive frames talking/silent, swap modes. if (framesReceived > (inTalkBurst ? silenceDeadbandFrames : signalDeadbandFrames)) { inTalkBurst = !inTalkBurst; PTRACE(4, "Codec\tSilence detection transition: " << (inTalkBurst ? "Talk" : "Silent") << " level=" << level << " threshold=" << levelThreshold); // If we had talk/silence transition restart adaptive threshold measurements signalMinimum = UINT_MAX; silenceMaximum = 0; signalFramesReceived = 0; silenceFramesReceived = 0; } } if (silenceDetectMode == FixedSilenceDetection) return !inTalkBurst; if (levelThreshold == 0) { if (level > 1) { // Bootstrap condition, use first frame level as silence level levelThreshold = level/2; PTRACE(4, "Codec\tSilence detection threshold initialised to: " << levelThreshold); } return TRUE; // inTalkBurst always FALSE here, so return silent } // Count the number of silent and signal frames and calculate min/max if (haveSignal) { if (level < signalMinimum) signalMinimum = level; signalFramesReceived++; } else { if (level > silenceMaximum) silenceMaximum = level; silenceFramesReceived++; } // See if we have had enough frames to look at proportions of silence/signal if ((signalFramesReceived + silenceFramesReceived) > adaptiveThresholdFrames) { /* Now we have had a period of time to look at some average values we can make some adjustments to the threshold. There are four cases: */ if (signalFramesReceived >= adaptiveThresholdFrames) { /* If every frame was noisy, move threshold up. Don't want to move too fast so only go a quarter of the way to minimum signal value over the period. This avoids oscillations, and time will continue to make the level go up if there really is a lot of background noise. */ int delta = (signalMinimum - levelThreshold)/4; if (delta != 0) { levelThreshold += delta; PTRACE(4, "Codec\tSilence detection threshold increased to: " << levelThreshold); } } else if (silenceFramesReceived >= adaptiveThresholdFrames) { /* If every frame was silent, move threshold down. Again do not want to move too quickly, but we do want it to move faster down than up, so move to halfway to maximum value of the quiet period. As a rule the lower the threshold the better as it would improve response time to the start of a talk burst. */ unsigned newThreshold = (levelThreshold + silenceMaximum)/2 + 1; if (levelThreshold != newThreshold) { levelThreshold = newThreshold; PTRACE(4, "Codec\tSilence detection threshold decreased to: " << levelThreshold); } } else if (signalFramesReceived > silenceFramesReceived) { /* We haven't got a definitive silent or signal period, but if we are constantly hovering at the threshold and have more signal than silence we should creep up a bit. */ levelThreshold++; PTRACE(4, "Codec\tSilence detection threshold incremented to: " << levelThreshold << " signal=" << signalFramesReceived << ' ' << signalMinimum << " silence=" << silenceFramesReceived << ' ' << silenceMaximum); } signalMinimum = UINT_MAX; silenceMaximum = 0; signalFramesReceived = 0; silenceFramesReceived = 0; } return !inTalkBurst;}unsigned H323AudioCodec::GetAverageSignalLevel(){ return UINT_MAX;}/////////////////////////////////////////////////////////////////////////////H323FramedAudioCodec::H323FramedAudioCodec(Direction dir, unsigned samples, unsigned bytes) : H323AudioCodec(dir, samples), sampleBuffer(samples){ bytesPerFrame = bytes;}BOOL H323FramedAudioCodec::Read(BYTE * buffer, unsigned & length, RTP_DataFrame &){ if (rawDataChannel == NULL) { PTRACE(1, "Codec\tNo audio channel for read"); return FALSE; } if (direction != Encoder) { PTRACE(1, "Codec\tAttempt to decode from encoder"); return FALSE; } if (!rawDataChannel->Read(sampleBuffer.GetPointer(samplesPerFrame), samplesPerFrame*2)) { PTRACE(1, "Codec\tAudio read failed: " << rawDataChannel->GetErrorText()); return FALSE; } if (DetectSilence()) { length = 0; return TRUE; } // Default length is the frame size length = bytesPerFrame; return EncodeFrame(buffer, length);}BOOL H323FramedAudioCodec::Write(const BYTE * buffer, unsigned length, const RTP_DataFrame & /*rtpFrame*/, unsigned & written){ if (rawDataChannel == NULL) { PTRACE(1, "Codec\tNo audio channel for write"); return FALSE; } if (direction != Decoder) { PTRACE(1, "Codec\tAttempt to encode from decoder"); return FALSE; } // If length is zero then it indicates silence, do nothing. if (length == 0) { memset(sampleBuffer.GetPointer(), 0, samplesPerFrame*2); written = 0; } else { if (length > bytesPerFrame) length = bytesPerFrame; written = bytesPerFrame; // Decode the data if (!DecodeFrame(buffer, length, written)) return FALSE; } // Write as 16bit PCM to sound channel if (rawDataChannel->Write(sampleBuffer, samplesPerFrame*2)) return TRUE; PTRACE(1, "Codec\tWrite failed: " << rawDataChannel->GetErrorText()); return TRUE; // This probably should be FALSE as write error is fatal, maybe}unsigned H323FramedAudioCodec::GetAverageSignalLevel(){ // Calculate the average signal level of this frame int sum = 0; const short * pcm = sampleBuffer; const short * end = pcm + samplesPerFrame; while (pcm != end) { if (*pcm < 0) sum -= *pcm++; else sum += *pcm++; } return sum/samplesPerFrame;}unsigned H323FramedAudioCodec::GetBandwidth() const{ // Want 100's of bits per second from the number of bytes in a frame // the number of time units per frame and number of units per millisecond. return 80*bytesPerFrame*GetTimeUnits()/GetFrameRate();}/////////////////////////////////////////////////////////////////////////////H323StreamedAudioCodec::H323StreamedAudioCodec(Direction dir, unsigned samples, unsigned bits) : H323FramedAudioCodec(dir, samples, (samples*bits+7)/8){ bitsPerSample = bits;}BOOL H323StreamedAudioCodec::EncodeFrame(BYTE * buffer, unsigned &){ PINDEX i; switch (bitsPerSample) { case 8 : for (i = 0; i < (PINDEX)samplesPerFrame; i++) *buffer++ = (BYTE)Encode(sampleBuffer[i]); break; case 4 : for (i = 0; i < (PINDEX)samplesPerFrame; i++) { if ((i&1) == 0) *buffer = (BYTE)Encode(sampleBuffer[i]); else *buffer |= (BYTE)(Encode(sampleBuffer[i]) << 4); } break; default : PAssertAlways("Unsupported bit size"); return FALSE; } return TRUE;}BOOL H323StreamedAudioCodec::DecodeFrame(const BYTE * buffer, unsigned length, unsigned & written){ unsigned i; short * out = sampleBuffer.GetPointer(samplesPerFrame); switch (bitsPerSample) { case 8 : for (i = 0; i < length; i++) *out++ = Decode(*buffer++); break; case 4 : for (i = 0; i < length; i++) { *out++ = Decode(*buffer & 15); *out++ = Decode(*buffer >> 4); buffer++; } break; default : PAssertAlways("Unsupported bit size"); return FALSE; } written = length; return TRUE;}/////////////////////////////////////////////////////////////////////////////H323_ALawCodec::H323_ALawCodec(Direction dir, BOOL at56kbps, unsigned frameSize) : H323StreamedAudioCodec(dir, frameSize, 8){ rtpPayloadType = RTP_DataFrame::PCMA; sevenBit = at56kbps; PTRACE(3, "Codec\tG711 ALaw " << (dir == Encoder ? "en" : "de") << "coder created for at " << (sevenBit ? "56k" : "64k") << ", " << frameSize << " samples");}int H323_ALawCodec::Encode(short sample) const{ return linear2alaw(sample);}short H323_ALawCodec::Decode(int sample) const{ return (short)alaw2linear((unsigned char)sample);}/////////////////////////////////////////////////////////////////////////////H323_muLawCodec::H323_muLawCodec(Direction dir, BOOL at56kbps, unsigned frameSize) : H323StreamedAudioCodec(dir, frameSize, 8){ rtpPayloadType = RTP_DataFrame::PCMU; sevenBit = at56kbps; PTRACE(3, "Codec\tG711 uLaw " << (dir == Encoder ? "en" : "de") << "coder created for at " << (sevenBit ? "56k" : "64k") << ", frame of " << frameSize << " samples");}int H323_muLawCodec::Encode(short sample) const{ return linear2ulaw(sample);}short H323_muLawCodec::Decode(int sample) const{ return (short)ulaw2linear((unsigned char)sample);}/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -