1、编码说明
gsm6.10编码:
gsm6.10是GSM通信网络的标准编码方式,才有8KHZ采样率,每20ms生成一个语音包,每个样本可以分为13位A率或者14位u率的16位PCM编码,每个采样生成的数据量为8000×20/1000×16=2560bits的原始数据,通过gsm编码器压缩为260bits的GSM帧,压缩后的数据率为1625byte,相当于13kbps,由于260位(32.5byte)的gsm帧不是8位的整数倍,因此编码器输出的GSM帧为264位的线性PCM码,即33个byte。
采样频率为8 kHz、每个样本为16位的未压缩的话音数据率为128 kbps,使用GSM压缩后的数据率为: (264bit×8000样本/s) / 160样本 = 13.2 kbps。GSM的压缩比:128:13.2 = 9.7,近似于10:1。
2、wav文件头部封装信息:
编码包括了两方面内容,一是按一定格式存储数据,二是采用一定的算法压缩数据。WAV格式对音频流的编码没有硬性规定,支持非压缩的PCM(Puls Code Modulation)脉冲编码调制格式,还支持压缩型的微软自适应分脉冲编码调制Microsoft ADPCM(Adaptive Differential Puls Code Modulation)、国际电报联盟(International Telegraph Union)制定的语音压缩标准ITUG.711 a-law、ITU G.711-law、IMA ADPCM、ITU G.723 ADPCM (Yamaha)、GSM 6.10、ITU G.721 ADPCM编码和其它压缩算法。MP3编码同样也可以运用在WAV中,只要安装相应的Decode,就可以播放WAV中的MP3音乐。
参考:参考WAV文件格式说明
3、编解码参考代码库:
gsm6.10编码每个为33byte,两个为66byte,在写入到wav中时需要将其中一个去掉一个byte,合并为65byte,同时需要设定GSM_OPT_WAV49格式,才能满足;
gsm6.10编码直接转换为rtp数据包时,字节截断的过程。
4、gsm6.10转换为wav文件的参考代码:
/* makewave.c -- Read Sun .au and write GSM-containing MS wave file */
/*
* Copyright (C) 1996 Jeffrey Chilton
*
* Permission is granted to anyone to make or distribute copies of
* this program, in any medium, provided that the copyright notice
* and permission notice are preserved, and that the distributor
* grants the recipient permission for further redistribution as
* permitted by this notice.
*
* Author's E-mail address: jwc@chilton.com
*
*/
#include <stdio.h>
#include "gsm.h"
extern unsigned short MuLaw_Linear[];
#define MULAW_ZERO 255
int F_wav_fmt = 1;
long read_header(FILE *);
int write_header(long, FILE *);
#define BLOCK_SIZE 160
main(argc, argv)
int argc;
char *argv[];
{
register int i;
FILE *sfp;
FILE *dfp;
gsm handle;
long samples;
long data_size;
long total_out;
unsigned char mulaw[2 * BLOCK_SIZE];
gsm_signal linear[2 * BLOCK_SIZE];
gsm_frame frame;
int out_size;
int rc;
if (argc != 2)
{
fprintf(stderr, "usage: %s <.au file>\n", argv[0]);
exit(1);
}
sfp = fopen(argv[1], "r");
if (!sfp)
{
perror("open fails");
exit(1);
}
/* Read .au file header info and calulate output size */
samples = read_header(sfp);
data_size = ((samples + (2 * BLOCK_SIZE - 1)) / (2 * BLOCK_SIZE));
data_size *= 2 * sizeof (frame) - 1;
/*
fprintf(stderr, "samples from header: 0x%x\n", samples);
fprintf(stderr, "calculated data size: 0x%x\n", data_size);
*/
dfp = stdout;
/* Create the GSM codec object and option it for wave framing */
handle = gsm_create();
if (!handle)
{
perror("cannot create gsm codec");
exit(1);
}
(void )gsm_option(handle, GSM_OPT_WAV49, &F_wav_fmt);
/* Write the .wav file header */
rc = write_header(data_size, dfp);
if (rc)
{
perror("error writing header");
exit(1);
}
/* Compress the audio */
total_out = 0;
while (samples > 0)
{
/* Read two frames worth of samples and convert to linear */
rc = fread(mulaw, (size_t )1, sizeof (mulaw), sfp);
if (rc < 0)
{
perror("error reading input");
exit(1);
}
samples -= rc;
if (rc < sizeof (mulaw))
{
memset((char *)mulaw + rc, MULAW_ZERO, sizeof (mulaw) - rc);
}
for (i = 0; i < sizeof (mulaw); i++)
{
linear[i] = MuLaw_Linear[mulaw[i]];
}
/* Encode the even half and write short (32-byte) frame */
gsm_encode(handle, &linear[0], frame);
out_size = sizeof (frame) - 1;
rc = fwrite(frame, (size_t )1, out_size, dfp);
if (rc != out_size)
{
perror("error writing output");
exit(1);
}
total_out += rc;
/* Encode the odd half and write long (33-byte) frame */
gsm_encode(handle, &linear[160], frame);
out_size = sizeof (frame);
rc = fwrite(frame, (size_t )1, out_size, dfp);
if (rc != out_size)
{
perror("error writing output");
exit(1);
}
total_out += rc;
}
/* Pad output to even number of bytes */
if (total_out & 0x1)
{
frame[0] = 0x00;
rc = fwrite(frame, (size_t )1, 1, dfp);
if (rc != 1)
{
perror("error writing output");
exit(1);
}
total_out += rc;
}
/*
fprintf(stderr, "total bytes written: 0x%lx\n", total_out);
*/
/* Clean up */
gsm_destroy(handle);
}
/* read_header - read Sun .au file header */
static long
getlong(fp)
FILE *fp;
{
long l;
l = 0;
l = (l << 8) | 0xFF & getc(fp);
l = (l << 8) | 0xFF & getc(fp);
l = (l << 8) | 0xFF & getc(fp);
l = (l << 8) | 0xFF & getc(fp);
return l;
}
#define AU_FILE_MAGIC 0x2e736e64
#define AU_FILE_MULAW_8 1
#define SAMPLE_RATE 8000
#define SAMPLE_CHANNELS 1
long
read_header(fp)
FILE *fp;
{
long magic;
long header_size;
long data_size;
long code;
long rate;
long n_chan;
int rc;
magic = getlong(fp);
if (magic != AU_FILE_MAGIC)
{
fprintf(stderr, "input is not an audio file\n");
rc = -1;
goto out;
}
header_size = getlong(fp);
data_size = getlong(fp);
code = getlong(fp);
rate = getlong(fp);
n_chan = getlong(fp);
header_size -= 24;
while (header_size)
{
(void )getc(fp);
header_size--;
}
if (code != AU_FILE_MULAW_8 ||
rate != SAMPLE_RATE ||
n_chan != SAMPLE_CHANNELS)
{
fprintf(stderr, "input must by mu-law 8KHz mono\n");
rc = 01;
goto out;
}
rc = data_size;
out:
return rc;
}
unsigned short MuLaw_Linear[] = {
33280, 34308, 35336, 36364, 37393, 38421, 39449, 40477,
41505, 42534, 43562, 44590, 45618, 46647, 47675, 48703,
49474, 49988, 50503, 51017, 51531, 52045, 52559, 53073,
53587, 54101, 54616, 55130, 55644, 56158, 56672, 57186,
57572, 57829, 58086, 58343, 58600, 58857, 59114, 59371,
59628, 59885, 60142, 60399, 60656, 60913, 61171, 61428,
61620, 61749, 61877, 62006, 62134, 62263, 62392, 62520,
62649, 62777, 62906, 63034, 63163, 63291, 63420, 63548,
63645, 63709, 63773, 63838, 63902, 63966, 64030, 64095,
64159, 64223, 64287, 64352, 64416, 64480, 64544, 64609,
64657, 64689, 64721, 64753, 64785, 64818, 64850, 64882,
64914, 64946, 64978, 65010, 65042, 65075, 65107, 65139,
65163, 65179, 65195, 65211, 65227, 65243, 65259, 65275,
65291, 65308, 65324, 65340, 65356, 65372, 65388, 65404,
65416, 65424, 65432, 65440, 65448, 65456, 65464, 65472,
65480, 65488, 65496, 65504, 65512, 65520, 65528, 0,
32256, 31228, 30200, 29172, 28143, 27115, 26087, 25059,
24031, 23002, 21974, 20946, 19918, 18889, 17861, 16833,
16062, 15548, 15033, 14519, 14005, 13491, 12977, 12463,
11949, 11435, 10920, 10406, 9892, 9378, 8864, 8350,
7964, 7707, 7450, 7193, 6936, 6679, 6422, 6165,
5908, 5651, 5394, 5137, 4880, 4623, 4365, 4108,
3916, 3787, 3659, 3530, 3402, 3273, 3144, 3016,
2887, 2759, 2630, 2502, 2373, 2245, 2116, 1988,
1891, 1827, 1763, 1698, 1634, 1570, 1506, 1441,
1377, 1313, 1249, 1184, 1120, 1056, 992, 927,
879, 847, 815, 783, 751, 718, 686, 654,
622, 590, 558, 526, 494, 461, 429, 397,
373, 357, 341, 325, 309, 293, 277, 261,
245, 228, 212, 196, 180, 164, 148, 132,
120, 112, 104, 96, 88, 80, 72, 64,
56, 48, 40, 32, 24, 16, 8, 0
};
/* write_header - write (approximation of) MS wave file header */
static int
fputlong(x, fp)
long x;
FILE *fp;
{
return fputc(x & 0xFF, fp) == EOF ||
fputc((x >> 8) & 0xFF, fp) == EOF ||
fputc((x >> 16) & 0xFF, fp) == EOF ||
fputc((x >> 24) & 0xFF, fp) == EOF;
}
static int
fputshort(x, fp)
short x;
FILE *fp;
{
return fputc(x & 0xFF, fp) == EOF ||
fputc((x >> 8) & 0xFF, fp) == EOF;
}
#define WAVE_HS 20
#define FACT_HS 4
#define GSM_FMT 49 /* Format code number */
#define N_CHAN 1 /* Number of channels (mono) */
#define SAMP_FREQ 8000 /* Uncompressed samples/second */
#define BYTE_FREQ 1625 /* Compressed bytes/second */
#define X_1 65 /* Unknown format-specific */
#define X_2 2 /* Unknown format-specific */
#define X_3 320 /* Unknown format-specific */
#define Y_1 20160 /* Unknown "fact" value */
int
write_header(data_size, fp)
long data_size;
FILE *fp;
{
unsigned short s;
int rc;
rc = 0;
rc |= fputs("RIFF", fp) == EOF;
rc |= fputlong(52 + ((data_size + 1) & ~0x1), fp);
rc |= fputs("WAVEfmt ", fp) == EOF;
rc |= fputlong(WAVE_HS, fp);
rc |= fputshort(GSM_FMT, fp);
rc |= fputshort(N_CHAN, fp);
rc |= fputlong(SAMP_FREQ, fp);
rc |= fputlong(BYTE_FREQ, fp);
rc |= fputlong(X_1, fp);
rc |= fputshort(X_2, fp);
rc |= fputshort(X_3, fp);
rc |= fputs("fact", fp) == EOF;
rc |= fputlong(FACT_HS, fp);
rc |= fputlong(Y_1, fp);
rc |= fputs("data", fp) == EOF;
rc |= fputlong(data_size, fp);
return rc;
}
/*
2 * Interface to libgsm for gsm encoding/decoding
3 * Copyright (c) 2005 Alban Bedel <albeu@free.fr>
4 * Copyright (c) 2006, 2007 Michel Bardiaux <mbardiaux@mediaxim.be>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * Interface to libgsm for gsm encoding/decoding
26 */
27
28 // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html
29
30 #include "config.h"
31 #if HAVE_GSM_H
32 #include <gsm.h>
33 #else
34 #include <gsm/gsm.h>
35 #endif
36
37 #include "libavutil/channel_layout.h"
38 #include "libavutil/common.h"
39 #include "avcodec.h"
40 #include "internal.h"
41 #include "gsm.h"
42
43 static av_cold int libgsm_encode_close(AVCodecContext *avctx) {
44 gsm_destroy(avctx->priv_data);
45 avctx->priv_data = NULL;
46 return 0;
47 }
48
49 static av_cold int libgsm_encode_init(AVCodecContext *avctx) {
50 if (avctx->channels > 1) {
51 av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
52 avctx->channels);
53 return -1;
54 }
55
56 if (avctx->sample_rate != 8000) {
57 av_log(avctx, AV_LOG_ERROR, "Sample rate 8000Hz required for GSM, got %dHz\n",
58 avctx->sample_rate);
59 if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)
60 return -1;
61 }
62 if (avctx->bit_rate != 13000 /* Official */ &&
63 avctx->bit_rate != 13200 /* Very common */ &&
64 avctx->bit_rate != 0 /* Unknown; a.o. mov does not set bitrate when decoding */ ) {
65 av_log(avctx, AV_LOG_ERROR, "Bitrate 13000bps required for GSM, got %dbps\n",
66 avctx->bit_rate);
67 if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)
68 return -1;
69 }
70
71 avctx->priv_data = gsm_create();
72 if (!avctx->priv_data)
73 goto error;
74
75 switch(avctx->codec_id) {
76 case AV_CODEC_ID_GSM:
77 avctx->frame_size = GSM_FRAME_SIZE;
78 avctx->block_align = GSM_BLOCK_SIZE;
79 break;
80 case AV_CODEC_ID_GSM_MS: {
81 int one = 1;
82 gsm_option(avctx->priv_data, GSM_OPT_WAV49, &one);
83 avctx->frame_size = 2*GSM_FRAME_SIZE;
84 avctx->block_align = GSM_MS_BLOCK_SIZE;
85 }
86 }
87
88 return 0;
89 error:
90 libgsm_encode_close(avctx);
91 return -1;
92 }
93
94 static int libgsm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
95 const AVFrame *frame, int *got_packet_ptr)
96 {
97 int ret;
98 gsm_signal *samples = (gsm_signal *)frame->data[0];
99 struct gsm_state *state = avctx->priv_data;
100
101 if ((ret = ff_alloc_packet2(avctx, avpkt, avctx->block_align)) < 0)
102 return ret;
103
104 switch(avctx->codec_id) {
105 case AV_CODEC_ID_GSM:
106 gsm_encode(state, samples, avpkt->data);
107 break;
108 case AV_CODEC_ID_GSM_MS:
109 gsm_encode(state, samples, avpkt->data);
110 gsm_encode(state, samples + GSM_FRAME_SIZE, avpkt->data + 32);
111 }
112
113 *got_packet_ptr = 1;
114 return 0;
115 }
116
117
118 #if CONFIG_LIBGSM_ENCODER
119 AVCodec ff_libgsm_encoder = {
120 .name = "libgsm",
121 .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
122 .type = AVMEDIA_TYPE_AUDIO,
123 .id = AV_CODEC_ID_GSM,
124 .init = libgsm_encode_init,
125 .encode2 = libgsm_encode_frame,
126 .close = libgsm_encode_close,
127 .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
128 AV_SAMPLE_FMT_NONE },
129 };
130 #endif
131 #if CONFIG_LIBGSM_MS_ENCODER
132 AVCodec ff_libgsm_ms_encoder = {
133 .name = "libgsm_ms",
134 .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
135 .type = AVMEDIA_TYPE_AUDIO,
136 .id = AV_CODEC_ID_GSM_MS,
137 .init = libgsm_encode_init,
138 .encode2 = libgsm_encode_frame,
139 .close = libgsm_encode_close,
140 .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
141 AV_SAMPLE_FMT_NONE },
142 };
143 #endif
144
145 typedef struct LibGSMDecodeContext {
146 struct gsm_state *state;
147 } LibGSMDecodeContext;
148
149 static av_cold int libgsm_decode_init(AVCodecContext *avctx) {
150 LibGSMDecodeContext *s = avctx->priv_data;
151
152 avctx->channels = 1;
153 avctx->channel_layout = AV_CH_LAYOUT_MONO;
154 if (!avctx->sample_rate)
155 avctx->sample_rate = 8000;
156 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
157
158 s->state = gsm_create();
159
160 switch(avctx->codec_id) {
161 case AV_CODEC_ID_GSM:
162 avctx->frame_size = GSM_FRAME_SIZE;
163 avctx->block_align = GSM_BLOCK_SIZE;
164 break;
165 case AV_CODEC_ID_GSM_MS: {
166 int one = 1;
167 gsm_option(s->state, GSM_OPT_WAV49, &one);
168 avctx->frame_size = 2 * GSM_FRAME_SIZE;
169 avctx->block_align = GSM_MS_BLOCK_SIZE;
170 }
171 }
172
173 return 0;
174 }
175
176 static av_cold int libgsm_decode_close(AVCodecContext *avctx) {
177 LibGSMDecodeContext *s = avctx->priv_data;
178
179 gsm_destroy(s->state);
180 s->state = NULL;
181 return 0;
182 }
183
184 static int libgsm_decode_frame(AVCodecContext *avctx, void *data,
185 int *got_frame_ptr, AVPacket *avpkt)
186 {
187 int i, ret;
188 LibGSMDecodeContext *s = avctx->priv_data;
189 AVFrame *frame = data;
190 uint8_t *buf = avpkt->data;
191 int buf_size = avpkt->size;
192 int16_t *samples;
193
194 if (buf_size < avctx->block_align) {
195 av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
196 return AVERROR_INVALIDDATA;
197 }
198
199 /* get output buffer */
200 frame->nb_samples = avctx->frame_size;
201 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
202 return ret;
203 samples = (int16_t *)frame->data[0];
204
205 for (i = 0; i < avctx->frame_size / GSM_FRAME_SIZE; i++) {
206 if ((ret = gsm_decode(s->state, buf, samples)) < 0)
207 return -1;
208 buf += GSM_BLOCK_SIZE;
209 samples += GSM_FRAME_SIZE;
210 }
211
212 *got_frame_ptr = 1;
213
214 return avctx->block_align;
215 }
216
217 static void libgsm_flush(AVCodecContext *avctx) {
218 LibGSMDecodeContext *s = avctx->priv_data;
219 int one = 1;
220
221 gsm_destroy(s->state);
222 s->state = gsm_create();
223 if (avctx->codec_id == AV_CODEC_ID_GSM_MS)
224 gsm_option(s->state, GSM_OPT_WAV49, &one);
225 }
226
227 #if CONFIG_LIBGSM_DECODER
228 AVCodec ff_libgsm_decoder = {
229 .name = "libgsm",
230 .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
231 .type = AVMEDIA_TYPE_AUDIO,
232 .id = AV_CODEC_ID_GSM,
233 .priv_data_size = sizeof(LibGSMDecodeContext),
234 .init = libgsm_decode_init,
235 .close = libgsm_decode_close,
236 .decode = libgsm_decode_frame,
237 .flush = libgsm_flush,
238 .capabilities = CODEC_CAP_DR1,
239 };
240 #endif
241 #if CONFIG_LIBGSM_MS_DECODER
242 AVCodec ff_libgsm_ms_decoder = {
243 .name = "libgsm_ms",
244 .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
245 .type = AVMEDIA_TYPE_AUDIO,
246 .id = AV_CODEC_ID_GSM_MS,
247 .priv_data_size = sizeof(LibGSMDecodeContext),
248 .init = libgsm_decode_init,
249 .close = libgsm_decode_close,
250 .decode = libgsm_decode_frame,
251 .flush = libgsm_flush,
252 .capabilities = CODEC_CAP_DR1,
253 };
254 #endif
5、转码验证工具
Adobe Audition CS6
WaveCN 2.0.0.5