音频demo:将PCM数据与g726数据的相互转换

1、README

前言

本demo是将使用了开源项目EasyAACEncoder里的src/g726.cpp(demo中的已重命名为g726.c)和src/g726.h将16位小字节序的pcm数据和g726进行相互转换。

注:相关测试文件已存放在demo的audio目录下,目前发现pcm转换得到的g726文件用软件Audacity播放不正常(没找到g726,所以选的VOX ADPCM),而将所得到的g726再转换回pcm却播放正常,网上说需要支持g726解码的播放器才能播放,用ffmpeg播放也出错,所以看到本注释时的g726都是播放不了的。

a. 编译
$ make clean && make # 或者`make DEBUG=1`打开调试打印信息,又或者指定`CC=your-crosscompile-gcc`进行编译交叉编译
b. 使用
$ ./pcm_g726_convert
Usage:./pcm_g726_convert -t pcm_2_g726 -i ./audio/test_8khz_16bit_mono_128kbps.pcm -r 16000 -o out_8khz_16kbps.g726./pcm_g726_convert -t pcm_2_g726 -i ./audio/test_8khz_16bit_mono_128kbps.pcm -r 24000 -o out_8khz_24kbps.g726./pcm_g726_convert -t pcm_2_g726 -i ./audio/test_8khz_16bit_mono_128kbps.pcm -r 32000 -o out_8khz_32kbps.g726./pcm_g726_convert -t pcm_2_g726 -i ./audio/test_8khz_16bit_mono_128kbps.pcm -r 40000 -o out_8khz_40kbps.g726./pcm_g726_convert -t g726_2_pcm -i ./audio/test_8khz_16kbps.g726 -r 16000 -o out_8khz_16bit_mono_128kbps-1.pcm./pcm_g726_convert -t g726_2_pcm -i ./audio/test_8khz_24kbps.g726 -r 24000 -o out_8khz_16bit_mono_128kbps-2.pcm./pcm_g726_convert -t g726_2_pcm -i ./audio/test_8khz_32kbps.g726 -r 32000 -o out_8khz_16bit_mono_128kbps-3.pcm./pcm_g726_convert -t g726_2_pcm -i ./audio/test_8khz_40kbps.g726 -r 40000 -o out_8khz_16bit_mono_128kbps-4.pcm
c. 参考文章
  • 音频采样及编解码——LPCM 、ADPCM、G711、G726、AAC_夜风的博客-CSDN博客_adpcm

  • g726转pcm_ybn187的专栏-CSDN博客_g726转pcm

  • g726算法的一些总结_那年晴天的博客-CSDN博客

d. demo目录架构
$ tree
.
├── audio
│   ├── test_8khz_16bit_mono_128kbps.pcm
│   ├── test_8khz_16kbps.g726
│   ├── test_8khz_24kbps.g726
│   ├── test_8khz_32kbps.g726
│   └── test_8khz_40kbps.g726
├── docs
│   ├── g726算法的一些总结_那年晴天的博客-CSDN博客.mhtml
│   ├── g726转pcm_ybn187的专栏-CSDN博客_g726转pcm.mhtml
│   └── 音频采样及编解码——LPCM 、ADPCM、G711、G726、AAC_夜风的博客-CSDN博客_adpcm.mhtml
├── g726.c
├── g726.h
├── main.c
├── Makefile
└── README.md

2、主要代码片段

g726.c
/*Copyright (c) 2013-2016 EasyDarwin.ORG.  All rights reserved.Github: https://github.com/EasyDarwinWEChat: EasyDarwinWebsite: http://www.easydarwin.org
*/#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "g726.h"static const int qtab_726_16[1] =
{261
};static const int qtab_726_24[3] =
{8, 218, 331
};static const int qtab_726_32[7] =
{-124, 80, 178, 246, 300, 349, 400
};static const int qtab_726_40[15] =
{-122, -16,  68, 139, 198, 250, 298, 339,378, 413, 445, 475, 502, 528, 553
};static __inline int top_bit(unsigned int bits)
{
#if defined(__i386__)  ||  defined(__x86_64__)int res;__asm__ (" xorl %[res],%[res];\n"" decl %[res];\n"" bsrl %[bits],%[res]\n": [res] "=&r" (res): [bits] "rm" (bits));return res;
#elif defined(__ppc__)  ||   defined(__powerpc__)int res;__asm__ ("cntlzw %[res],%[bits];\n": [res] "=&r" (res): [bits] "r" (bits));return 31 - res;
#elif defined(_M_IX86) // Visual Studio x86__asm{xor eax, eaxdec eaxbsr eax, bits}
#elseint res;if (bits == 0)return -1;res = 0;if (bits & 0xFFFF0000){bits &= 0xFFFF0000;res += 16;}if (bits & 0xFF00FF00){bits &= 0xFF00FF00;res += 8;}if (bits & 0xF0F0F0F0){bits &= 0xF0F0F0F0;res += 4;}if (bits & 0xCCCCCCCC){bits &= 0xCCCCCCCC;res += 2;}if (bits & 0xAAAAAAAA){bits &= 0xAAAAAAAA;res += 1;}return res;
#endif
}static bitstream_state_t *bitstream_init(bitstream_state_t *s)
{if (s == NULL)return NULL;s->bitstream = 0;s->residue = 0;return s;
}/** Given a raw sample, 'd', of the difference signal and a* quantization step size scale factor, 'y', this routine returns the* ADPCM codeword to which that sample gets quantized.  The step* size scale factor division operation is done in the log base 2 domain* as a subtraction.*/
static short quantize(int d,                  /* Raw difference signal sample */int y,                  /* Step size multiplier */const int table[],     /* quantization table */int quantizer_states)   /* table size of short integers */
{short dqm;    /* Magnitude of 'd' */short exp;    /* Integer part of base 2 log of 'd' */short mant;   /* Fractional part of base 2 log */short dl;     /* Log of magnitude of 'd' */short dln;    /* Step size scale factor normalized log */int i;int size;/** LOG** Compute base 2 log of 'd', and store in 'dl'.*/dqm = (short) abs(d);exp = (short) (top_bit(dqm >> 1) + 1);/* Fractional portion. */mant = ((dqm << 7) >> exp) & 0x7F;dl = (exp << 7) + mant;/** SUBTB** "Divide" by step size multiplier.*/dln = dl - (short) (y >> 2);/** QUAN** Search for codword i for 'dln'.*/size = (quantizer_states - 1) >> 1;for (i = 0;  i < size;  i++){if (dln < table[i])break;}if (d < 0){/* Take 1's complement of i */return (short) ((size << 1) + 1 - i);}if (i == 0  &&  (quantizer_states & 1)){/* Zero is only valid if there are an even number of states, sotake the 1's complement if the code is zero. */return (short) quantizer_states;}return (short) i;
}
/*- End of function --------------------------------------------------------*//*
* returns the integer product of the 14-bit integer "an" and
* "floating point" representation (4-bit exponent, 6-bit mantessa) "srn".
*/
static short fmult(short an, short srn)
{short anmag;short anexp;short anmant;short wanexp;short wanmant;short retval;anmag = (an > 0)  ?  an  :  ((-an) & 0x1FFF);anexp = (short) (top_bit(anmag) - 5);anmant = (anmag == 0)  ?  32  :  (anexp >= 0)  ?  (anmag >> anexp)  :  (anmag << -anexp);wanexp = anexp + ((srn >> 6) & 0xF) - 13;wanmant = (anmant*(srn & 0x3F) + 0x30) >> 4;retval = (wanexp >= 0)  ?  ((wanmant << wanexp) & 0x7FFF)  :  (wanmant >> -wanexp);return (((an ^ srn) < 0)  ?  -retval  :  retval);
}/*
* Compute the estimated signal from the 6-zero predictor.
*/
static __inline short predictor_zero(g726_state_t *s)
{int i;int sezi;sezi = fmult(s->b[0] >> 2, s->dq[0]);/* ACCUM */for (i = 1;  i < 6;  i++)sezi += fmult(s->b[i] >> 2, s->dq[i]);return (short) sezi;
}
/*- End of function --------------------------------------------------------*//*
* Computes the estimated signal from the 2-pole predictor.
*/
static __inline short predictor_pole(g726_state_t *s)
{return (fmult(s->a[1] >> 2, s->sr[1]) + fmult(s->a[0] >> 2, s->sr[0]));
}/*
* Computes the quantization step size of the adaptive quantizer.
*/
static int step_size(g726_state_t *s)
{int y;int dif;int al;if (s->ap >= 256)return s->yu;y = s->yl >> 6;dif = s->yu - y;al = s->ap >> 2;if (dif > 0)y += (dif*al) >> 6;else if (dif < 0)y += (dif*al + 0x3F) >> 6;return y;
}
/*- End of function --------------------------------------------------------*//*
* Returns reconstructed difference signal 'dq' obtained from
* codeword 'i' and quantization step size scale factor 'y'.
* Multiplication is performed in log base 2 domain as addition.
*/
static short reconstruct(int sign,    /* 0 for non-negative value */int dqln,    /* G.72x codeword */int y)       /* Step size multiplier */
{short dql;    /* Log of 'dq' magnitude */short dex;    /* Integer part of log */short dqt;short dq;     /* Reconstructed difference signal sample */dql = (short) (dqln + (y >> 2));  /* ADDA */if (dql < 0)return ((sign)  ?  -0x8000  :  0);/* ANTILOG */dex = (dql >> 7) & 15;dqt = 128 + (dql & 127);dq = (dqt << 7) >> (14 - dex);return ((sign)  ?  (dq - 0x8000)  :  dq);
}
/*- End of function --------------------------------------------------------*//*
* updates the state variables for each output code
*/
static void update(g726_state_t *s,int y,       /* quantizer step size */int wi,      /* scale factor multiplier */int fi,      /* for long/short term energies */int dq,      /* quantized prediction difference */int sr,      /* reconstructed signal */int dqsez)   /* difference from 2-pole predictor */
{short mag;short exp;short a2p;        /* LIMC */short a1ul;       /* UPA1 */short pks1;       /* UPA2 */short fa1;short ylint;short dqthr;short ylfrac;short thr;short pk0;int i;int tr;a2p = 0;/* Needed in updating predictor poles */pk0 = (dqsez < 0)  ?  1  :  0;/* prediction difference magnitude */mag = (short) (dq & 0x7FFF);/* TRANS */ylint = (short) (s->yl >> 15);            /* exponent part of yl */ylfrac = (short) ((s->yl >> 10) & 0x1F);  /* fractional part of yl *//* Limit threshold to 31 << 10 */thr = (ylint > 9)  ?  (31 << 10)  :  ((32 + ylfrac) << ylint);dqthr = (thr + (thr >> 1)) >> 1;            /* dqthr = 0.75 * thr */if (!s->td)                                 /* signal supposed voice */tr = 0;else if (mag <= dqthr)                      /* supposed data, but small mag */tr = 0;                             /* treated as voice */else                                        /* signal is data (modem) */tr = 1;/** Quantizer scale factor adaptation.*//* FUNCTW & FILTD & DELAY *//* update non-steady state step size multiplier */s->yu = (short) (y + ((wi - y) >> 5));/* LIMB */if (s->yu < 544)s->yu = 544;else if (s->yu > 5120)s->yu = 5120;/* FILTE & DELAY *//* update steady state step size multiplier */s->yl += s->yu + ((-s->yl) >> 6);/** Adaptive predictor coefficients.*/if (tr){/* Reset the a's and b's for a modem signal */s->a[0] = 0;s->a[1] = 0;s->b[0] = 0;s->b[1] = 0;s->b[2] = 0;s->b[3] = 0;s->b[4] = 0;s->b[5] = 0;}else{/* Update the a's and b's *//* UPA2 */pks1 = pk0 ^ s->pk[0];/* Update predictor pole a[1] */a2p = s->a[1] - (s->a[1] >> 7);if (dqsez != 0){fa1 = (pks1)  ?  s->a[0]  :  -s->a[0];/* a2p = function of fa1 */if (fa1 < -8191)a2p -= 0x100;else if (fa1 > 8191)a2p += 0xFF;elsea2p += fa1 >> 5;if (pk0 ^ s->pk[1]){/* LIMC */if (a2p <= -12160)a2p = -12288;else if (a2p >= 12416)a2p = 12288;elsea2p -= 0x80;}else if (a2p <= -12416)a2p = -12288;else if (a2p >= 12160)a2p = 12288;elsea2p += 0x80;}/* TRIGB & DELAY */s->a[1] = a2p;/* UPA1 *//* Update predictor pole a[0] */s->a[0] -= s->a[0] >> 8;if (dqsez != 0){if (pks1 == 0)s->a[0] += 192;elses->a[0] -= 192;}/* LIMD */a1ul = 15360 - a2p;if (s->a[0] < -a1ul)s->a[0] = -a1ul;else if (s->a[0] > a1ul)s->a[0] = a1ul;/* UPB : update predictor zeros b[6] */for (i = 0;  i < 6;  i++){/* Distinguish 40Kbps mode from the others */s->b[i] -= s->b[i] >> ((s->bits_per_sample == 5)  ?  9  :  8);if (dq & 0x7FFF){/* XOR */if ((dq ^ s->dq[i]) >= 0)s->b[i] += 128;elses->b[i] -= 128;}}}for (i = 5;  i > 0;  i--)s->dq[i] = s->dq[i - 1];/* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */if (mag == 0){s->dq[0] = (dq >= 0)  ?  0x20  :  0xFC20;}else{exp = (short) (top_bit(mag) + 1);s->dq[0] = (dq >= 0)?  ((exp << 6) + ((mag << 6) >> exp)):  ((exp << 6) + ((mag << 6) >> exp) - 0x400);}s->sr[1] = s->sr[0];/* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */if (sr == 0){s->sr[0] = 0x20;}else if (sr > 0){exp = (short) (top_bit(sr) + 1);s->sr[0] = (short) ((exp << 6) + ((sr << 6) >> exp));}else if (sr > -32768){mag = (short) -sr;exp = (short) (top_bit(mag) + 1);s->sr[0] =  (exp << 6) + ((mag << 6) >> exp) - 0x400;}else{s->sr[0] = (short) 0xFC20;}/* DELAY A */s->pk[1] = s->pk[0];s->pk[0] = pk0;/* TONE */if (tr)                 /* this sample has been treated as data */s->td = 0;      /* next one will be treated as voice */else if (a2p < -11776)  /* small sample-to-sample correlation */s->td = 1;       /* signal may be data */else                    /* signal is voice */s->td = 0;/* Adaptation speed control. *//* FILTA */s->dms += ((short) fi - s->dms) >> 5;/* FILTB */s->dml += (((short) (fi << 2) - s->dml) >> 7);if (tr)s->ap = 256;else if (y < 1536)                      /* SUBTC */s->ap += (0x200 - s->ap) >> 4;else if (s->td)s->ap += (0x200 - s->ap) >> 4;else if (abs((s->dms << 2) - s->dml) >= (s->dml >> 3))s->ap += (0x200 - s->ap) >> 4;elses->ap += (-s->ap) >> 4;
}/*
* Decodes a 2-bit CCITT G.726_16 ADPCM code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
*/
static short g726_16_decoder(g726_state_t *s, unsigned char code)
{short sezi;short sei;short se;short sr;short dq;short dqsez;int y;/* Mask to get proper bits */code &= 0x03;sezi = predictor_zero(s);sei = sezi + predictor_pole(s);y = step_size(s);dq = reconstruct(code & 2, g726_16_dqlntab[code], y);/* Reconstruct the signal */se = sei >> 1;sr = (dq < 0)  ?  (se - (dq & 0x3FFF))  :  (se + dq);/* Pole prediction difference */dqsez = sr + (sezi >> 1) - se;update(s, y, g726_16_witab[code], g726_16_fitab[code], dq, sr, dqsez);return (sr << 2);
}
/*- End of function --------------------------------------------------------*//** Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code.*/
static unsigned char g726_16_encoder(g726_state_t *s, short amp)
{int y;short sei;short sezi;short se;short d;short sr;short dqsez;short dq;short i;sezi = predictor_zero(s);sei = sezi + predictor_pole(s);se = sei >> 1;d = amp - se;/* Quantize prediction difference */y = step_size(s);i = quantize(d, y, qtab_726_16, 4);dq = reconstruct(i & 2, g726_16_dqlntab[i], y);/* Reconstruct the signal */sr = (dq < 0)  ?  (se - (dq & 0x3FFF))  :  (se + dq);/* Pole prediction difference */dqsez = sr + (sezi >> 1) - se;update(s, y, g726_16_witab[i], g726_16_fitab[i], dq, sr, dqsez);return (unsigned char) i;
}/*
* Decodes a 3-bit CCITT G.726_24 ADPCM code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
*/
static short g726_24_decoder(g726_state_t *s, unsigned char code)
{short sezi;short sei;short se;short sr;short dq;short dqsez;int y;/* Mask to get proper bits */code &= 0x07;sezi = predictor_zero(s);sei = sezi + predictor_pole(s);y = step_size(s);dq = reconstruct(code & 4, g726_24_dqlntab[code], y);/* Reconstruct the signal */se = sei >> 1;sr = (dq < 0)  ?  (se - (dq & 0x3FFF))  :  (se + dq);/* Pole prediction difference */dqsez = sr + (sezi >> 1) - se;update(s, y, g726_24_witab[code], g726_24_fitab[code], dq, sr, dqsez);return (sr << 2);
}
/*- End of function --------------------------------------------------------*//** Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code.*/
static unsigned char g726_24_encoder(g726_state_t *s, short amp)
{short sei;short sezi;short se;short d;short sr;short dqsez;short dq;short i;int y;sezi = predictor_zero(s);sei = sezi + predictor_pole(s);se = sei >> 1;d = amp - se;/* Quantize prediction difference */y = step_size(s);i = quantize(d, y, qtab_726_24, 7);dq = reconstruct(i & 4, g726_24_dqlntab[i], y);/* Reconstruct the signal */sr = (dq < 0)  ?  (se - (dq & 0x3FFF))  :  (se + dq);/* Pole prediction difference */dqsez = sr + (sezi >> 1) - se;update(s, y, g726_24_witab[i], g726_24_fitab[i], dq, sr, dqsez);return (unsigned char) i;
}/*
* Decodes a 4-bit CCITT G.726_32 ADPCM code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
*/
static short g726_32_decoder(g726_state_t *s, unsigned char code)
{short sezi;short sei;short se;short sr;short dq;short dqsez;int y;/* Mask to get proper bits */code &= 0x0F;sezi = predictor_zero(s);sei = sezi + predictor_pole(s);y = step_size(s);dq = reconstruct(code & 8, g726_32_dqlntab[code], y);/* Reconstruct the signal */se = sei >> 1;sr = (dq < 0)  ?  (se - (dq & 0x3FFF))  :  (se + dq);/* Pole prediction difference */dqsez = sr + (sezi >> 1) - se;update(s, y, g726_32_witab[code], g726_32_fitab[code], dq, sr, dqsez);return (sr << 2);
}
/*- End of function --------------------------------------------------------*//** Encodes a linear input sample and returns its 4-bit code.*/
static unsigned char g726_32_encoder(g726_state_t *s, short amp)
{short sei;short sezi;short se;short d;short sr;short dqsez;short dq;short i;int y;sezi = predictor_zero(s);sei = sezi + predictor_pole(s);se = sei >> 1;d = amp - se;/* Quantize the prediction difference */y = step_size(s);i = quantize(d, y, qtab_726_32, 15);dq = reconstruct(i & 8, g726_32_dqlntab[i], y);/* Reconstruct the signal */sr = (dq < 0)  ?  (se - (dq & 0x3FFF))  :  (se + dq);/* Pole prediction difference */dqsez = sr + (sezi >> 1) - se;update(s, y, g726_32_witab[i], g726_32_fitab[i], dq, sr, dqsez);return (unsigned char) i;
}/*
* Decodes a 5-bit CCITT G.726 40Kbps code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
*/
static short g726_40_decoder(g726_state_t *s, unsigned char code)
{short sezi;short sei;short se;short sr;short dq;short dqsez;int y;/* Mask to get proper bits */code &= 0x1F;sezi = predictor_zero(s);sei = sezi + predictor_pole(s);y = step_size(s);dq = reconstruct(code & 0x10, g726_40_dqlntab[code], y);/* Reconstruct the signal */se = sei >> 1;sr = (dq < 0)  ?  (se - (dq & 0x7FFF))  :  (se + dq);/* Pole prediction difference */dqsez = sr + (sezi >> 1) - se;update(s, y, g726_40_witab[code], g726_40_fitab[code], dq, sr, dqsez);return (sr << 2);
}
/*- End of function --------------------------------------------------------*//** Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens* the resulting 5-bit CCITT G.726 40Kbps code.*/
static unsigned char g726_40_encoder(g726_state_t *s, short amp)
{short sei;short sezi;short se;short d;short sr;short dqsez;short dq;short i;int y;sezi = predictor_zero(s);sei = sezi + predictor_pole(s);se = sei >> 1;d = amp - se;/* Quantize prediction difference */y = step_size(s);i = quantize(d, y, qtab_726_40, 31);dq = reconstruct(i & 0x10, g726_40_dqlntab[i], y);/* Reconstruct the signal */sr = (dq < 0)  ?  (se - (dq & 0x7FFF))  :  (se + dq);/* Pole prediction difference */dqsez = sr + (sezi >> 1) - se;update(s, y, g726_40_witab[i], g726_40_fitab[i], dq, sr, dqsez);return (unsigned char) i;
}g726_state_t *g726_init(g726_state_t *s, int bit_rate)
{int i;if (bit_rate != 16000  &&  bit_rate != 24000  &&  bit_rate != 32000  &&  bit_rate != 40000)return NULL;s->yl = 34816;s->yu = 544;s->dms = 0;s->dml = 0;s->ap = 0;s->rate = bit_rate;for (i = 0; i < 2; i++){s->a[i] = 0;s->pk[i] = 0;s->sr[i] = 32;}for (i = 0; i < 6; i++){s->b[i] = 0;s->dq[i] = 32;}s->td = 0;switch (bit_rate){case 16000:s->enc_func = g726_16_encoder;s->dec_func = g726_16_decoder;s->bits_per_sample = 2;break;case 24000:s->enc_func = g726_24_encoder;s->dec_func = g726_24_decoder;s->bits_per_sample = 3;break;case 32000:default:s->enc_func = g726_32_encoder;s->dec_func = g726_32_decoder;s->bits_per_sample = 4;break;case 40000:s->enc_func = g726_40_encoder;s->dec_func = g726_40_decoder;s->bits_per_sample = 5;break;}bitstream_init(&s->bs);return s;
}int g726_decode(g726_state_t *s,short amp[],const unsigned char g726_data[],int g726_bytes)
{int i;int samples;unsigned char code;int sl;for (samples = i = 0;  ;  ){if (s->bs.residue < s->bits_per_sample){if (i >= g726_bytes)break;s->bs.bitstream = (s->bs.bitstream << 8) | g726_data[i++];s->bs.residue += 8;}code = (unsigned char) ((s->bs.bitstream >> (s->bs.residue - s->bits_per_sample)) & ((1 << s->bits_per_sample) - 1));s->bs.residue -= s->bits_per_sample;sl = s->dec_func(s, code);amp[samples++] = (short) sl;}return samples;
}int g726_encode(g726_state_t *s,unsigned char g726_data[],const short amp[],int len)
{int i;int g726_bytes;short sl;unsigned char code;for (g726_bytes = i = 0;  i < len;  i++){sl = amp[i] >> 2;code = s->enc_func(s, sl);s->bs.bitstream = (s->bs.bitstream << s->bits_per_sample) | code;s->bs.residue += s->bits_per_sample;if (s->bs.residue >= 8){g726_data[g726_bytes++] = (unsigned char) ((s->bs.bitstream >> (s->bs.residue - 8)) & 0xFF);s->bs.residue -= 8;}}return g726_bytes;
}
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>#include "g726.h"// 编译时Makefile里控制
#ifdef ENABLE_DEBUG#define DEBUG(fmt, args...)     printf(fmt, ##args)
#else#define DEBUG(fmt, args...)
#endif#define BUF_SIZE 	2048	void print_Usage(char *processName)
{printf("Usage: \n""   %s -t pcm_2_g726 -i ./audio/test_8khz_16bit_mono_128kbps.pcm -r 16000 -o out_8khz_16kbps.g726\n""   %s -t pcm_2_g726 -i ./audio/test_8khz_16bit_mono_128kbps.pcm -r 24000 -o out_8khz_24kbps.g726\n""   %s -t pcm_2_g726 -i ./audio/test_8khz_16bit_mono_128kbps.pcm -r 32000 -o out_8khz_32kbps.g726\n""   %s -t pcm_2_g726 -i ./audio/test_8khz_16bit_mono_128kbps.pcm -r 40000 -o out_8khz_40kbps.g726\n""   %s -t g726_2_pcm -i ./audio/test_8khz_16kbps.g726 -r 16000 -o out_8khz_16bit_mono_128kbps-1.pcm\n""   %s -t g726_2_pcm -i ./audio/test_8khz_24kbps.g726 -r 24000 -o out_8khz_16bit_mono_128kbps-2.pcm\n""   %s -t g726_2_pcm -i ./audio/test_8khz_32kbps.g726 -r 32000 -o out_8khz_16bit_mono_128kbps-3.pcm\n""   %s -t g726_2_pcm -i ./audio/test_8khz_40kbps.g726 -r 40000 -o out_8khz_16bit_mono_128kbps-4.pcm\n",processName, processName, processName, processName, processName, processName, processName, processName);
}int main(int argc, char *argv[])
{unsigned int bitRates = 0;unsigned char *inBuf = (unsigned char *)malloc(BUF_SIZE);unsigned char *outBuf = (unsigned char *)malloc(BUF_SIZE);char convertType[128];char inputFileName[128];char outputFileName[128];FILE *fpInput = NULL;FILE *fpOutput = NULL;g726_state_t *g726Handler = NULL; // g726操作句柄if(argc == 1){print_Usage(argv[0]);return -1;}// 解析命令行参数 -- start --char option = 0;int option_index = 0;const char *short_options = "ht:i:o:r:";struct option long_options[] ={{"help",         no_argument,       NULL, 'h'},{"convert_type", required_argument, NULL, 't'},{"input_file", 	 required_argument, NULL, 'i'},{"output_file",  required_argument, NULL, 'o'},{"bit_rates",    required_argument, NULL, 'r'},{NULL,           0,                 NULL,  0 },};  while((option = getopt_long_only(argc, argv, short_options, long_options, &option_index)) != -1) {switch(option){case 'h':print_Usage(argv[0]);return 0;case 't':strncpy(convertType, optarg, 128);break;case 'i':strncpy(inputFileName, optarg, 128);break;case 'o':strncpy(outputFileName, optarg, 128);break;case 'r':bitRates = atoi(optarg);break;defalut:printf("Unknown argument!\n");break;}}// 解析命令行参数 -- end --printf("\n**************************************\n""convert type: %s\n""input file name: %s\n""output file name: %s\n""g726 bit rates: %d bps\n""**************************************\n\n",!strcmp(convertType, "pcm_2_g726") ? "pcm -> g726" : "g726 -> pcm",inputFileName, outputFileName, bitRates);fpInput  = fopen(inputFileName, "rb");fpOutput = fopen(outputFileName, "wb");if(!fpInput || !fpOutput){printf("Open Input/Output file failed!\n");return -1;}// step 1: 先分配内存空间给操作句柄g726Handler = (g726_state_t *)malloc(sizeof(g726_state_t));if(g726Handler == NULL){printf("Alloc memory for g726 handler failed!\n");return -1;}// step 2: 根据比特率(码率)进行初始化得到句柄g726Handler = g726_init(g726Handler, bitRates);// 按一"帧"160个采样点进行操作#define SAMPLES_PER_FRAME 	(160)if(strcmp(convertType, "pcm_2_g726") == 0) // encode{int readBytes = -1;int ret = -1;while(1){readBytes = fread(inBuf, 1, SAMPLES_PER_FRAME*(16/8), fpInput);if(readBytes <= 0)break;/* 参数:句柄、g726缓存(传出)、pcm缓存(传入)、pcm的采样点个数;* 返回值:编码得到的g726数据长度*/ret = g726_encode(g726Handler, (unsigned char*)outBuf, (const short*)inBuf, readBytes/2); // 记得读到的字节数要除以2DEBUG("[g726_encode]  read pcm bytes: %d  ->  encode g726 bytes: %d\n", readBytes, ret);if(ret != readBytes * bitRates / 128000){printf("PCM encode to G726 failed!\n");printf("\033[31mFailed!\033[0m\n");break;}fwrite(outBuf, 1, ret, fpOutput);}}else if(strcmp(convertType, "g726_2_pcm") == 0) // decode{int readBytes = -1;int ret = -1;while(1){readBytes = fread(inBuf, 1, SAMPLES_PER_FRAME * (16/8) * bitRates / 128000, fpInput);if(readBytes <= 0)break;/* 参数:句柄、pcm缓存(传出)、g726缓存(传入)、g726数据长度;* 返回值:pcm的采样点个数,注意不是字节数!!!所以字节数是要x2*/ret = g726_decode(g726Handler, (short*)outBuf, inBuf, readBytes);DEBUG("[g726_decode] read g726 bytes: %d  ->  decode pcm bytes: %d\n", readBytes, ret*2);if(ret*2 * bitRates / 128000 != readBytes){printf("G726 decode to PCM failed!\n");printf("\033[31mFailed!\033[0m\n");break;}fwrite(outBuf, 2, ret, fpOutput);}}else{printf("Unknown convert type!\n");printf("\033[31mFailed!\033[0m\n");return -1;}printf("\033[32msuccess!\033[0m\n");// step : 释放句柄的内存free(g726Handler);free(inBuf);free(outBuf);fclose(fpInput);fclose(fpOutput);return 0;
}

3、demo下载地址(任选一个)

  • https://download.csdn.net/download/weixin_44498318/89525480
  • https://gitee.com/linriming/audio_pcm_g726_convert.git
  • https://github.com/linriming20/audio_pcm_g726_convert.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/374643.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot大学校园二手书交易APP-计算机毕业设计源码25753

摘 要 在数字化与移动互联网迅猛发展的今天&#xff0c;人们对于图书的需求与消费方式也在悄然改变。为了满足广大读者对图书的热爱与追求&#xff0c;我们倾力打造了一款基于Android平台的图书交易APP。这款APP不仅汇聚了海量的图书资源&#xff0c;提供了便捷的交易平台&…

usbserver工程师手记(三)手工开通 OTP功能

1、设定密钥&#xff0c;用户自行选择一个密钥&#xff0c;以下以密钥为 EAZAYOKNGETBOPC5 为例说明 2、usb server 配置otp 密钥&#xff0c;目前还没有UI 界面开通&#xff0c;后续版本会支持从管理界面开通 curl -X POST -H Content-Type: application/json -H Accept: app…

【深度学习入门篇 ②】Pytorch完成线性回归!

&#x1f34a;嗨&#xff0c;大家好&#xff0c;我是小森( &#xfe61;ˆoˆ&#xfe61; )&#xff01; 易编橙终身成长社群创始团队嘉宾&#xff0c;橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官、CSDN人工智能领域优质创作者 。 易编橙&#xff1a;一个帮助编程小…

数据结构复习计划之复杂度分析(时间、空间)

第二节&#xff1a;算法 时间复杂度和空间复杂度 算法(Algorithm)&#xff1a;是对特定问题求解方法(步骤)的一种描述&#xff0c;是指令的有限序列&#xff0c;其中每一条指令表示一个或多个操作。 算法可以有三种表示形式&#xff1a; 伪代码 自然语言 流程图 算法的五…

FFmpeg 实现从麦克风获取流并通过RTMP推流

使用FFmpeg库&#xff08;版本号为&#xff1a;4.4.2-0ubuntu0.22.04.1&#xff09;实现从麦克风获取流并通过RTMP推流。 RTMP服务器使用的是SRS&#xff0c;我这边是跑在Ubuntu上的&#xff0c;最好是关闭掉系统防火墙&#xff0c;不然连接服务器好像会出问题&#xff0c;拉流…

SpringBoot开发实用篇(三)

一&#xff1a;任务 1&#xff1a;SpringBoot整合Quartz 导入SpringBoot整合quartz的坐标定义具体要执行的任务&#xff0c;继承QuartzJobBean定义工作明细和触发器&#xff0c;并绑定对应关系 2&#xff1a;SpringBoot整合task 开启定时任务功能设置定时执行的任务&#x…

怎么样的主食冻干算好冻干?品质卓越、安全可靠的主食冻干分享

当前主食冻干市场产品质量参差不齐。一些品牌过于追求营养数据的堆砌和利润的增长&#xff0c;却忽视了猫咪健康饮食的基本原则&#xff0c;导致市场上出现了以肉粉冒充鲜肉、修改产品日期等不诚信行为。更令人担忧的是&#xff0c;部分产品未经过严格的第三方质量检测便上市销…

记录文字视差背景学习

效果图 文字背景会随鼠标上下移动变成红色或透明 html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…

【linux】服务器卸载cuda

【linux】服务器卸载cuda 文章目录 【linux】服务器卸载cuda1、查找已安装的 CUDA 包&#xff1a;2、卸载 CUDA&#xff1a;3、删除残留文件4、更新系统的包索引&#xff1a;5、检查是否卸载干净&#xff1a; 1、查找已安装的 CUDA 包&#xff1a; dpkg -l | grep cuda2、卸载…

CSS3实现彩色变形爱心动画【附源码】

随着前端技术的发展&#xff0c;CSS3 为我们提供了丰富的动画效果&#xff0c;使得网页设计更加生动和有趣。今天&#xff0c;我们将探讨如何使用 CSS3 实现一个彩色变形爱心加载动画特效。这种动画不仅美观&#xff0c;而且可以应用于各种网页元素&#xff0c;比如加载指示器或…

基于深度学习LightWeight的人体姿态之行为识别系统源码

一. LightWeight概述 light weight openpose是openpose的简化版本&#xff0c;使用了openpose的大体流程。 Light weight openpose和openpose的区别是&#xff1a; a 前者使用的是Mobilenet V1&#xff08;到conv5_5&#xff09;&#xff0c;后者使用的是Vgg19&#xff08;前10…

Django QuerySet对象,exclude()方法

模型参考上一章内容&#xff1a; Django QuerySet对象&#xff0c;filter()方法-CSDN博客 exclude()方法&#xff0c;用于排除符合条件的数据。 1&#xff0c;添加视图函数 Test/app11/views.py from django.shortcuts import render from .models import Postdef index(re…

从0开始的STM32HAL库学习4

对射式红外传感器计数复现 配置工程 我们直接复制oled的工程&#xff0c;但是要重命名。 将PB14设置为中断引脚 自定义命名为sensorcount 设置为上升沿触发 打开中断 配置NVCI 都为默认就可以了 修改代码 修改stm32f1xx_it.c 文件 找到中断函数并修改 void EXTI15_10_I…

pytorch实现水果2分类(蓝莓,苹果)

1.数据集的路径&#xff0c;结构 dataset.py 目的&#xff1a; 输入&#xff1a;没有输入&#xff0c;路径是写死了的。 输出&#xff1a;返回的是一个对象&#xff0c;里面有self.data。self.data是一个列表&#xff0c;里面是&#xff08;图片路径.jpg&#xff0c;标签&…

Docker安装遇到问题:curl: (7) Failed to connect to download.docker.com port 443: 拒绝连接

问题描述 首先&#xff0c;完全按照Docker官方文档进行安装&#xff1a; Install Docker Engine on Ubuntu | Docker Docs 在第1步&#xff1a;Set up Dockers apt repository&#xff0c;执行如下指令&#xff1a; sudo curl -fsSL https://download.docker.com/linux/ubu…

MybatisPlus 使用教程

MyBatisPlus使用教程 文章目录 MyBatisPlus使用教程1、使用方式1.1 引入依赖1.2 构建mapper接口 2、常用注解2.1 TableName2.2 TableId2.3 TableField MyBatisPlus顾名思义便是对MyBatis的加强版&#xff0c;但两者本身并不冲突(只做增强不做改变)&#xff1a; 引入它并不会对原…

[数据集][目标检测]护目镜检测数据集VOC+YOLO格式888张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;888 标注数量(xml文件个数)&#xff1a;888 标注数量(txt文件个数)&#xff1a;888 标注类别…

C语言基本概念

C语言是什么&#xff1f; 1.人与人之间 自然语言 2.人与计算机之间 计算机语言 例如C、Java、Go、Python 在计算机语言中 1.解释型语言&#xff1a;Python 2.编译型语言&#xff1a;C/C 编译和链接 C语言源代码都是文本文件.c&#xff0c;必须通过编译器的编译和链接器的…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-第十八章 Linux编写第一个自己的命令

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

基于Python的哔哩哔哩数据分析系统设计实现过程,技术使用flask、MySQL、echarts,前端使用Layui

背景和意义 随着互联网和数字媒体行业的快速发展&#xff0c;视频网站作为重要的内容传播平台之一&#xff0c;用户量和内容丰富度呈现爆发式增长。本研究旨在设计并实现一种基于Python的哔哩哔哩数据分析系统&#xff0c;采用Flask框架、MySQL数据库以及echarts数据可视化技术…