2 * RFC 3389 comfort noise generator
3 * Copyright (c) 2012 Martin Storsjo
5 * This file is part of FFmpeg.
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.
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.
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
24 #include "libavutil/common.h"
29 typedef struct CNGContext
{
36 static av_cold
int cng_encode_close(AVCodecContext
*avctx
)
38 CNGContext
*p
= avctx
->priv_data
;
40 av_free(p
->samples32
);
45 static av_cold
int cng_encode_init(AVCodecContext
*avctx
)
47 CNGContext
*p
= avctx
->priv_data
;
50 if (avctx
->channels
!= 1) {
51 av_log(avctx
, AV_LOG_ERROR
, "Only mono supported\n");
52 return AVERROR(EINVAL
);
55 avctx
->frame_size
= 640;
57 if ((ret
= ff_lpc_init(&p
->lpc
, avctx
->frame_size
, p
->order
, FF_LPC_TYPE_LEVINSON
)) < 0)
59 p
->samples32
= av_malloc_array(avctx
->frame_size
, sizeof(*p
->samples32
));
60 p
->ref_coef
= av_malloc_array(p
->order
, sizeof(*p
->ref_coef
));
61 if (!p
->samples32
|| !p
->ref_coef
) {
62 cng_encode_close(avctx
);
63 return AVERROR(ENOMEM
);
69 static int cng_encode_frame(AVCodecContext
*avctx
, AVPacket
*avpkt
,
70 const AVFrame
*frame
, int *got_packet_ptr
)
72 CNGContext
*p
= avctx
->priv_data
;
76 int16_t *samples
= (int16_t*) frame
->data
[0];
78 if ((ret
= ff_alloc_packet(avpkt
, 1 + p
->order
))) {
79 av_log(avctx
, AV_LOG_ERROR
, "Error getting output packet\n");
83 for (i
= 0; i
< frame
->nb_samples
; i
++) {
84 p
->samples32
[i
] = samples
[i
];
85 energy
+= samples
[i
] * samples
[i
];
87 energy
/= frame
->nb_samples
;
89 double dbov
= 10 * log10(energy
/ 1081109975);
90 qdbov
= av_clip(-floor(dbov
), 0, 127);
94 ret
= ff_lpc_calc_ref_coefs(&p
->lpc
, p
->samples32
, p
->order
, p
->ref_coef
);
95 avpkt
->data
[0] = qdbov
;
96 for (i
= 0; i
< p
->order
; i
++)
97 avpkt
->data
[1 + i
] = p
->ref_coef
[i
] * 127 + 127;
100 avpkt
->size
= 1 + p
->order
;
105 AVCodec ff_comfortnoise_encoder
= {
106 .name
= "comfortnoise",
107 .long_name
= NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"),
108 .type
= AVMEDIA_TYPE_AUDIO
,
109 .id
= AV_CODEC_ID_COMFORT_NOISE
,
110 .priv_data_size
= sizeof(CNGContext
),
111 .init
= cng_encode_init
,
112 .encode2
= cng_encode_frame
,
113 .close
= cng_encode_close
,
114 .sample_fmts
= (const enum AVSampleFormat
[]){ AV_SAMPLE_FMT_S16
,
115 AV_SAMPLE_FMT_NONE
},