2 * audio encoder psychoacoustic model
3 * Copyright (C) 2008 Konstantin Shishkov
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
26 #include "iirfilter.h"
27 #include "libavutil/mem.h"
29 extern const FFPsyModel ff_aac_psy_model
;
31 av_cold
int ff_psy_init(FFPsyContext
*ctx
, AVCodecContext
*avctx
, int num_lens
,
32 const uint8_t **bands
, const int* num_bands
,
33 int num_groups
, const uint8_t *group_map
)
38 ctx
->ch
= av_mallocz_array(sizeof(ctx
->ch
[0]), avctx
->channels
* 2);
39 ctx
->group
= av_mallocz_array(sizeof(ctx
->group
[0]), num_groups
);
40 ctx
->bands
= av_malloc_array (sizeof(ctx
->bands
[0]), num_lens
);
41 ctx
->num_bands
= av_malloc_array (sizeof(ctx
->num_bands
[0]), num_lens
);
42 memcpy(ctx
->bands
, bands
, sizeof(ctx
->bands
[0]) * num_lens
);
43 memcpy(ctx
->num_bands
, num_bands
, sizeof(ctx
->num_bands
[0]) * num_lens
);
45 /* assign channels to groups (with virtual channels for coupling) */
46 for (i
= 0; i
< num_groups
; i
++) {
47 /* NOTE: Add 1 to handle the AAC chan_config without modification.
48 * This has the side effect of allowing an array of 0s to map
49 * to one channel per group.
51 ctx
->group
[i
].num_ch
= group_map
[i
] + 1;
52 for (j
= 0; j
< ctx
->group
[i
].num_ch
* 2; j
++)
53 ctx
->group
[i
].ch
[j
] = &ctx
->ch
[k
++];
56 switch (ctx
->avctx
->codec_id
) {
58 ctx
->model
= &ff_aac_psy_model
;
62 return ctx
->model
->init(ctx
);
66 FFPsyChannelGroup
*ff_psy_find_group(FFPsyContext
*ctx
, int channel
)
71 ch
+= ctx
->group
[i
++].num_ch
;
73 return &ctx
->group
[i
-1];
76 av_cold
void ff_psy_end(FFPsyContext
*ctx
)
78 if (ctx
->model
&& ctx
->model
->end
)
80 av_freep(&ctx
->bands
);
81 av_freep(&ctx
->num_bands
);
82 av_freep(&ctx
->group
);
86 typedef struct FFPsyPreprocessContext
{
87 AVCodecContext
*avctx
;
89 struct FFIIRFilterCoeffs
*fcoeffs
;
90 struct FFIIRFilterState
**fstate
;
91 struct FFIIRFilterContext fiir
;
92 }FFPsyPreprocessContext
;
96 av_cold
struct FFPsyPreprocessContext
* ff_psy_preprocess_init(AVCodecContext
*avctx
)
98 FFPsyPreprocessContext
*ctx
;
100 float cutoff_coeff
= 0;
101 ctx
= av_mallocz(sizeof(FFPsyPreprocessContext
));
104 if (avctx
->cutoff
> 0)
105 cutoff_coeff
= 2.0 * avctx
->cutoff
/ avctx
->sample_rate
;
107 if (!cutoff_coeff
&& avctx
->codec_id
== AV_CODEC_ID_AAC
)
108 cutoff_coeff
= 2.0 * AAC_CUTOFF(avctx
) / avctx
->sample_rate
;
110 if (cutoff_coeff
&& cutoff_coeff
< 0.98)
111 ctx
->fcoeffs
= ff_iir_filter_init_coeffs(avctx
, FF_FILTER_TYPE_BUTTERWORTH
,
112 FF_FILTER_MODE_LOWPASS
, FILT_ORDER
,
113 cutoff_coeff
, 0.0, 0.0);
115 ctx
->fstate
= av_mallocz_array(sizeof(ctx
->fstate
[0]), avctx
->channels
);
116 for (i
= 0; i
< avctx
->channels
; i
++)
117 ctx
->fstate
[i
] = ff_iir_filter_init_state(FILT_ORDER
);
120 ff_iir_filter_init(&ctx
->fiir
);
125 void ff_psy_preprocess(struct FFPsyPreprocessContext
*ctx
, float **audio
, int channels
)
128 int frame_size
= ctx
->avctx
->frame_size
;
129 FFIIRFilterContext
*iir
= &ctx
->fiir
;
132 for (ch
= 0; ch
< channels
; ch
++)
133 iir
->filter_flt(ctx
->fcoeffs
, ctx
->fstate
[ch
], frame_size
,
134 &audio
[ch
][frame_size
], 1, &audio
[ch
][frame_size
], 1);
138 av_cold
void ff_psy_preprocess_end(struct FFPsyPreprocessContext
*ctx
)
141 ff_iir_filter_free_coeffsp(&ctx
->fcoeffs
);
143 for (i
= 0; i
< ctx
->avctx
->channels
; i
++)
144 ff_iir_filter_free_statep(&ctx
->fstate
[i
]);
145 av_freep(&ctx
->fstate
);