/src/ffmpeg/libavcodec/cngdec.c
Line | Count | Source |
1 | | /* |
2 | | * RFC 3389 comfort noise generator |
3 | | * Copyright (c) 2012 Martin Storsjo |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #include <math.h> |
23 | | |
24 | | #include "libavutil/common.h" |
25 | | #include "libavutil/ffmath.h" |
26 | | #include "libavutil/mem.h" |
27 | | #include "avcodec.h" |
28 | | #include "celp_filters.h" |
29 | | #include "codec_internal.h" |
30 | | #include "decode.h" |
31 | | #include "internal.h" |
32 | | #include "libavutil/lfg.h" |
33 | | |
34 | | typedef struct CNGContext { |
35 | | float *refl_coef, *target_refl_coef; |
36 | | float *lpc_coef; |
37 | | int order; |
38 | | int energy, target_energy; |
39 | | int inited; |
40 | | float *filter_out; |
41 | | float *excitation; |
42 | | AVLFG lfg; |
43 | | } CNGContext; |
44 | | |
45 | | static av_cold int cng_decode_close(AVCodecContext *avctx) |
46 | 658 | { |
47 | 658 | CNGContext *p = avctx->priv_data; |
48 | 658 | av_freep(&p->refl_coef); |
49 | 658 | av_freep(&p->target_refl_coef); |
50 | 658 | av_freep(&p->lpc_coef); |
51 | 658 | av_freep(&p->filter_out); |
52 | 658 | av_freep(&p->excitation); |
53 | 658 | return 0; |
54 | 658 | } |
55 | | |
56 | | static av_cold int cng_decode_init(AVCodecContext *avctx) |
57 | 658 | { |
58 | 658 | CNGContext *p = avctx->priv_data; |
59 | | |
60 | 658 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
61 | 658 | av_channel_layout_uninit(&avctx->ch_layout); |
62 | 658 | avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; |
63 | 658 | avctx->sample_rate = 8000; |
64 | | |
65 | 658 | p->order = 12; |
66 | 658 | avctx->frame_size = 640; |
67 | 658 | p->refl_coef = av_calloc(p->order, sizeof(*p->refl_coef)); |
68 | 658 | p->target_refl_coef = av_calloc(p->order, sizeof(*p->target_refl_coef)); |
69 | 658 | p->lpc_coef = av_calloc(p->order, sizeof(*p->lpc_coef)); |
70 | 658 | p->filter_out = av_calloc(avctx->frame_size + p->order, |
71 | 658 | sizeof(*p->filter_out)); |
72 | 658 | p->excitation = av_calloc(avctx->frame_size, sizeof(*p->excitation)); |
73 | 658 | if (!p->refl_coef || !p->target_refl_coef || !p->lpc_coef || |
74 | 658 | !p->filter_out || !p->excitation) { |
75 | 0 | return AVERROR(ENOMEM); |
76 | 0 | } |
77 | | |
78 | 658 | av_lfg_init(&p->lfg, 0); |
79 | | |
80 | 658 | return 0; |
81 | 658 | } |
82 | | |
83 | | static void make_lpc_coefs(float *lpc, const float *refl, int order) |
84 | 203k | { |
85 | 203k | float buf[100]; |
86 | 203k | float *next, *cur; |
87 | 203k | int m, i; |
88 | 203k | next = buf; |
89 | 203k | cur = lpc; |
90 | 2.63M | for (m = 0; m < order; m++) { |
91 | 2.43M | next[m] = refl[m]; |
92 | 15.8M | for (i = 0; i < m; i++) |
93 | 13.3M | next[i] = cur[i] + refl[m] * cur[m - i - 1]; |
94 | 2.43M | FFSWAP(float*, next, cur); |
95 | 2.43M | } |
96 | 203k | if (cur != lpc) |
97 | 0 | memcpy(lpc, cur, sizeof(*lpc) * order); |
98 | 203k | } |
99 | | |
100 | | static av_cold void cng_decode_flush(AVCodecContext *avctx) |
101 | 45.5k | { |
102 | 45.5k | CNGContext *p = avctx->priv_data; |
103 | 45.5k | p->inited = 0; |
104 | 45.5k | } |
105 | | |
106 | | static int cng_decode_frame(AVCodecContext *avctx, AVFrame *frame, |
107 | | int *got_frame_ptr, AVPacket *avpkt) |
108 | 203k | { |
109 | 203k | CNGContext *p = avctx->priv_data; |
110 | 203k | int buf_size = avpkt->size; |
111 | 203k | int ret, i; |
112 | 203k | int16_t *buf_out; |
113 | 203k | float e = 1.0; |
114 | 203k | float scaling; |
115 | | |
116 | 203k | if (avpkt->size) { |
117 | 203k | int dbov = -avpkt->data[0]; |
118 | 203k | p->target_energy = 1081109975 * ff_exp10(dbov / 10.0) * 0.75; |
119 | 203k | memset(p->target_refl_coef, 0, p->order * sizeof(*p->target_refl_coef)); |
120 | 263k | for (i = 0; i < FFMIN(avpkt->size - 1, p->order); i++) { |
121 | 60.6k | p->target_refl_coef[i] = (avpkt->data[1 + i] - 127) / 128.0; |
122 | 60.6k | } |
123 | 203k | } |
124 | | |
125 | 203k | if (avctx->internal->skip_samples > 10 * avctx->frame_size) { |
126 | 0 | avctx->internal->skip_samples = 0; |
127 | 0 | return AVERROR_INVALIDDATA; |
128 | 0 | } |
129 | | |
130 | 203k | if (p->inited) { |
131 | 156k | p->energy = p->energy / 2 + p->target_energy / 2; |
132 | 2.04M | for (i = 0; i < p->order; i++) |
133 | 1.88M | p->refl_coef[i] = 0.6 *p->refl_coef[i] + 0.4 * p->target_refl_coef[i]; |
134 | 156k | } else { |
135 | 46.0k | p->energy = p->target_energy; |
136 | 46.0k | memcpy(p->refl_coef, p->target_refl_coef, p->order * sizeof(*p->refl_coef)); |
137 | 46.0k | p->inited = 1; |
138 | 46.0k | } |
139 | 203k | make_lpc_coefs(p->lpc_coef, p->refl_coef, p->order); |
140 | | |
141 | 2.63M | for (i = 0; i < p->order; i++) |
142 | 2.43M | e *= 1.0 - p->refl_coef[i]*p->refl_coef[i]; |
143 | | |
144 | 203k | scaling = sqrt(e * p->energy / 1081109975); |
145 | 130M | for (i = 0; i < avctx->frame_size; i++) { |
146 | 129M | int r = (av_lfg_get(&p->lfg) & 0xffff) - 0x8000; |
147 | 129M | p->excitation[i] = scaling * r; |
148 | 129M | } |
149 | 203k | ff_celp_lp_synthesis_filterf(p->filter_out + p->order, p->lpc_coef, |
150 | 203k | p->excitation, avctx->frame_size, p->order); |
151 | | |
152 | 203k | frame->nb_samples = avctx->frame_size; |
153 | 203k | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
154 | 0 | return ret; |
155 | 203k | buf_out = (int16_t *)frame->data[0]; |
156 | 130M | for (i = 0; i < avctx->frame_size; i++) |
157 | 129M | buf_out[i] = av_clip_int16(p->filter_out[i + p->order]); |
158 | 203k | memcpy(p->filter_out, p->filter_out + avctx->frame_size, |
159 | 203k | p->order * sizeof(*p->filter_out)); |
160 | | |
161 | 203k | *got_frame_ptr = 1; |
162 | | |
163 | 203k | return buf_size; |
164 | 203k | } |
165 | | |
166 | | const FFCodec ff_comfortnoise_decoder = { |
167 | | .p.name = "comfortnoise", |
168 | | CODEC_LONG_NAME("RFC 3389 comfort noise generator"), |
169 | | .p.type = AVMEDIA_TYPE_AUDIO, |
170 | | .p.id = AV_CODEC_ID_COMFORT_NOISE, |
171 | | .priv_data_size = sizeof(CNGContext), |
172 | | .init = cng_decode_init, |
173 | | FF_CODEC_DECODE_CB(cng_decode_frame), |
174 | | .flush = cng_decode_flush, |
175 | | .close = cng_decode_close, |
176 | | CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16), |
177 | | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, |
178 | | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, |
179 | | }; |