📄 audio_g711.cpp
字号:
/* * The following code is subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this code * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000-2002. All Rights Reserved. * * Contributor(s): * Dave Mackie dmackie@cisco.com */#include "mp4live.h"#include "audio_g711.h"static uint32_t g711_sample_rate[] = { 8000, };static uint32_t *g711_bitrate_for_samplerate (uint32_t samplerate, uint8_t chans, uint32_t *ret_size){ uint32_t *ret = MALLOC_STRUCTURE(uint32_t); *ret = 64000; *ret_size = 1; return ret;}audio_encoder_table_t g711_alaw_audio_encoder_table = { "G.711 alaw", AUDIO_ENCODER_G711, AUDIO_ENCODING_ALAW, g711_sample_rate, NUM_ELEMENTS_IN_ARRAY(g711_sample_rate), g711_bitrate_for_samplerate, 1, NULL};audio_encoder_table_t g711_ulaw_audio_encoder_table = { "G.711 ulaw", AUDIO_ENCODER_G711, AUDIO_ENCODING_ULAW, g711_sample_rate, NUM_ELEMENTS_IN_ARRAY(g711_sample_rate), g711_bitrate_for_samplerate, 1, NULL};MediaType g711_mp4_fileinfo (CAudioProfile *pConfig, bool *mpeg4, bool *isma_compliant, uint8_t *audioProfile, uint8_t **audioConfig, uint32_t *audioConfigLen, uint8_t *mp4AudioType){ const char *encodingName = pConfig->GetStringValue(CFG_AUDIO_ENCODING); *mpeg4 = false; *isma_compliant = false; *audioProfile = 0; *audioConfig = NULL; *audioConfigLen = 0; if (mp4AudioType != NULL) { *mp4AudioType = 0; } if (!strcasecmp(encodingName, AUDIO_ENCODING_ULAW)) { if (mp4AudioType != NULL) { *mp4AudioType = MP4_ULAW_AUDIO_TYPE; } return ULAWAUDIOFRAME; } else if (!strcasecmp(encodingName, AUDIO_ENCODING_ALAW)) { if (mp4AudioType != NULL) { *mp4AudioType = MP4_ALAW_AUDIO_TYPE; } return ALAWAUDIOFRAME; } return UNDEFINEDFRAME;}media_desc_t *g711_create_audio_sdp (CAudioProfile *pConfig, bool *mpeg4, bool *isma_compliant, uint8_t *audioProfile, uint8_t **audioConfig, uint32_t *audioConfigLen){ media_desc_t *sdpMediaAudio; format_list_t *sdpMediaAudioFormat; MediaType type; type = g711_mp4_fileinfo(pConfig, mpeg4, isma_compliant, audioProfile, audioConfig, audioConfigLen, NULL); sdpMediaAudio = MALLOC_STRUCTURE(media_desc_t); memset(sdpMediaAudio, 0, sizeof(*sdpMediaAudio)); sdpMediaAudioFormat = MALLOC_STRUCTURE(format_list_t); memset(sdpMediaAudioFormat, 0, sizeof(*sdpMediaAudioFormat)); sdpMediaAudio->fmt_list = sdpMediaAudioFormat; sdpMediaAudioFormat->media = sdpMediaAudio; if (type == ALAWAUDIOFRAME) { sdpMediaAudioFormat->fmt = strdup("8"); } else if (type == ULAWAUDIOFRAME) { sdpMediaAudioFormat->fmt = strdup("0"); } return sdpMediaAudio;}bool g711_get_audio_rtp_info (CAudioProfile *pConfig, MediaType *audioFrameType, uint32_t *audioTimeScale, uint8_t *audioPayloadNumber, uint8_t *audioPayloadBytesPerPacket, uint8_t *audioPayloadBytesPerFrame, uint8_t *audioQueueMaxCount, audio_set_rtp_payload_f *audio_set_rtp_payload, audio_set_rtp_header_f *audio_set_header, audio_set_rtp_jumbo_frame_f *audio_set_jumbo, void **ud){ const char *encodingName = pConfig->GetStringValue(CFG_AUDIO_ENCODING); if (strcasecmp(encodingName, AUDIO_ENCODING_ALAW) == 0 || strcasecmp(encodingName, AUDIO_ENCODING_ULAW) == 0) { if (strcasecmp(encodingName, AUDIO_ENCODING_ALAW) == 0) { *audioFrameType = ALAWAUDIOFRAME; *audioPayloadNumber = 8; } else { *audioFrameType = ULAWAUDIOFRAME; *audioPayloadNumber = 0; } *audioTimeScale = 8000; *audioPayloadBytesPerPacket = 0; *audioPayloadBytesPerFrame = 0; *audioQueueMaxCount = 1; *audio_set_header = NULL; *audio_set_jumbo = NULL; *ud = NULL; return true; } return false; } CG711AudioEncoder::CG711AudioEncoder(CAudioProfile *ap, CAudioEncoder *next, u_int8_t srcChannels, u_int32_t srcSampleRate, uint16_t mtu, bool realTime) : CAudioEncoder(ap, next, srcChannels, srcSampleRate, mtu, realTime){ m_pFrameBuffer = NULL; m_frameBufferLength = 0;}bool CG711AudioEncoder::Init (void){#if 1 m_samplesPerFrame = 160; // 20ms worth of samples#else m_samplesPerFrame = 320; // 40ms worth of samples#endif m_useULAW = !strcasecmp( Profile()->GetStringValue(CFG_AUDIO_ENCODING), AUDIO_ENCODING_ULAW); Profile()->SetIntegerValue(CFG_AUDIO_BIT_RATE, m_pConfig->GetIntegerValue(CFG_AUDIO_CHANNELS) * m_pConfig->GetIntegerValue(CFG_AUDIO_SAMPLE_RATE) * 8); Initialize(); return true;}u_int32_t CG711AudioEncoder::GetSamplesPerFrame(){ return m_samplesPerFrame;}static uint8_t linear2alaw(int16_t pcm_val);static uint8_t linear2ulaw(int16_t pcm_val);bool CG711AudioEncoder::EncodeSamples( int16_t* pSamples, u_int32_t numSamplesPerChannel, u_int8_t numChannels){ if (numChannels != 1) { return false; // invalid numChannels } // check for signal to end encoding if (pSamples == NULL) { // unlike lame, G711 doesn't need to finish up anything return false; } // get an output buffer setup free(m_pFrameBuffer); m_frameBufferLength = numSamplesPerChannel * m_pConfig->GetIntegerValue(CFG_AUDIO_CHANNELS); m_pFrameBuffer = (u_int8_t*)Malloc(m_frameBufferLength); for (uint32_t ix = 0; ix < numSamplesPerChannel; ix++) { if (m_useULAW) { m_pFrameBuffer[ix] = linear2ulaw(pSamples[ix]); } else { m_pFrameBuffer[ix] = linear2alaw(pSamples[ix]); } } return true;}bool CG711AudioEncoder::GetEncodedFrame( u_int8_t** ppBuffer, u_int32_t* pBufferLength, u_int32_t* pNumSamplesPerChannel){ *ppBuffer = m_pFrameBuffer; *pBufferLength = m_frameBufferLength; *pNumSamplesPerChannel = m_frameBufferLength; m_pFrameBuffer = NULL; m_frameBufferLength = 0; return true;}void CG711AudioEncoder::StopEncoder (void){ free(m_pFrameBuffer); m_pFrameBuffer = NULL;}/* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use. Users may copy or modify this source code without * charge. * * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 *//* * g711.c * * u-law, A-law and linear PCM conversions. */#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */#define QUANT_MASK (0xf) /* Quantization field mask. */#define NSEGS (8) /* Number of A-law segments. */#define SEG_SHIFT (4) /* Left shift for segment number. */#define SEG_MASK (0x70) /* Segment field mask. */// wmay - changed from short to int16_tstatic uint16_t seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};// wmay - removed tables _u2a _a2u// wmay - change static uint8_tsearch( uint16_t val, uint16_t *table, uint8_t size){ uint8_t i; for (i = 0; i < size; i++) { if (val <= *table++) return (i); } return (size);}/* * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law * * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. * * Linear Input Code Compressed Code * ------------------------ --------------- * 0000000wxyza 000wxyz * 0000001wxyza 001wxyz * 000001wxyzab 010wxyz * 00001wxyzabc 011wxyz * 0001wxyzabcd 100wxyz * 001wxyzabcde 101wxyz * 01wxyzabcdef 110wxyz * 1wxyzabcdefg 111wxyz * * For further information see John C. Bellamy's Digital Telephony, 1982, * John Wiley & Sons, pps 98-111 and 472-476. */// wmay - changed definitions of variablestatic uint8_tlinear2alaw( int16_t pcm_val) /* 2's complement (16-bit range) */{ uint8_t mask; uint8_t seg; uint8_t aval; if (pcm_val >= 0) { mask = 0xD5; /* sign (7th) bit = 1 */ } else { mask = 0x55; /* sign bit = 0 */ pcm_val = ~pcm_val; // wmay -pcm_val - 8; } /* Convert the scaled magnitude to segment number. */ seg = search((uint16_t)pcm_val, seg_end, 8); /* Combine the sign, segment, and quantization bits. */ if (seg >= 8) /* out of range, return maximum value. */ return (0x7F ^ mask); else { aval = seg << SEG_SHIFT; if (seg < 2) aval |= (pcm_val >> 4) & QUANT_MASK; else aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; return (aval ^ mask); }}// wmay - removed alaw2linear#define BIAS (0x84) /* Bias for linear code. *//* * linear2ulaw() - Convert a linear PCM value to u-law * * In order to simplify the encoding process, the original linear magnitude * is biased by adding 33 which shifts the encoding range from (0 - 8158) to * (33 - 8191). The result can be seen in the following encoding table: * * Biased Linear Input Code Compressed Code * ------------------------ --------------- * 00000001wxyza 000wxyz * 0000001wxyzab 001wxyz * 000001wxyzabc 010wxyz * 00001wxyzabcd 011wxyz * 0001wxyzabcde 100wxyz * 001wxyzabcdef 101wxyz * 01wxyzabcdefg 110wxyz * 1wxyzabcdefgh 111wxyz * * Each biased linear code has a leading 1 which identifies the segment * number. The value of the segment number is equal to 7 minus the number * of leading 0's. The quantization interval is directly available as the * four bits wxyz. * The trailing bits (a - h) are ignored. * * Ordinarily the complement of the resulting code word is used for * transmission, and so the code word is complemented before it is returned. * * For further information see John C. Bellamy's Digital Telephony, 1982, * John Wiley & Sons, pps 98-111 and 472-476. */static uint8_tlinear2ulaw( int16_t pcm_val) /* 2's complement (16-bit range) */{ uint8_t mask; uint8_t seg; uint8_t uval; /* if someone has passed in a bum short (e.g. they manipulated an * int rather than a short, so the value looks positive, not * negative) fix that */#if 0 if(pcm_val & 0x8000) { pcm_val = - (~pcm_val & 0x7fff) - 1; }#endif /* Get the sign and the magnitude of the value. */ if (pcm_val < 0) { pcm_val = BIAS - pcm_val; mask = 0x7F; } else { pcm_val += BIAS; mask = 0xFF; } /* Convert the scaled magnitude to segment number. */ seg = search(pcm_val, seg_end, 8); /* * Combine the sign, segment, quantization bits; * and complement the code word. */ if (seg >= 8) /* out of range, return maximum value. */ return (0x7F ^ mask); else { uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); return (uval ^ mask); }}// wmay - remove ulaw2linear, alaw2ulaw, ulaw2alaw
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -