libswresample/audioconvert.c
Go to the documentation of this file.
1 /*
2  * audio conversion
3  * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
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 /**
23  * @file
24  * audio conversion
25  * @author Michael Niedermayer <michaelni@gmx.at>
26  */
27 
28 #include "libavutil/avstring.h"
29 #include "libavutil/avassert.h"
30 #include "libavutil/libm.h"
31 #include "libavutil/samplefmt.h"
32 #include "audioconvert.h"
33 
34 
35 #define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt
36 
37 //FIXME rounding ?
38 #define CONV_FUNC(ofmt, otype, ifmt, expr)\
39 static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *po, const uint8_t *pi, int is, int os, uint8_t *end)\
40 {\
41  uint8_t *end2 = end - 3*os;\
42  while(po < end2){\
43  *(otype*)po = expr; pi += is; po += os;\
44  *(otype*)po = expr; pi += is; po += os;\
45  *(otype*)po = expr; pi += is; po += os;\
46  *(otype*)po = expr; pi += is; po += os;\
47  }\
48  while(po < end){\
49  *(otype*)po = expr; pi += is; po += os;\
50  }\
51 }
52 
53 //FIXME put things below under ifdefs so we do not waste space for cases no codec will need
55 CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<8)
56 CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<24)
57 CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0f/ (1<<7)))
58 CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7)))
59 CONV_FUNC(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S16, (*(const int16_t*)pi>>8) + 0x80)
60 CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi)
61 CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi<<16)
62 CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0f/ (1<<15)))
63 CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15)))
64 CONV_FUNC(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S32, (*(const int32_t*)pi>>24) + 0x80)
65 CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi>>16)
66 CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi)
67 CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0f/ (1U<<31)))
68 CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31)))
69 CONV_FUNC(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8( lrintf(*(const float*)pi * (1<<7)) + 0x80))
70 CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16( lrintf(*(const float*)pi * (1<<15))))
71 CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float*)pi * (1U<<31))))
72 CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_FLT, *(const float*)pi)
73 CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_FLT, *(const float*)pi)
74 CONV_FUNC(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8( lrint(*(const double*)pi * (1<<7)) + 0x80))
75 CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16( lrint(*(const double*)pi * (1<<15))))
76 CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double*)pi * (1U<<31))))
77 CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_DBL, *(const double*)pi)
78 CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_DBL, *(const double*)pi)
79 
80 #define FMT_PAIR_FUNC(out, in) [out + AV_SAMPLE_FMT_NB*in] = CONV_FUNC_NAME(out, in)
81 
82 static conv_func_type * const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB*AV_SAMPLE_FMT_NB] = {
83  FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8 , AV_SAMPLE_FMT_U8 ),
84  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8 ),
85  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8 ),
86  FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8 ),
87  FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8 ),
88  FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8 , AV_SAMPLE_FMT_S16),
89  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16),
90  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16),
91  FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16),
92  FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16),
93  FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8 , AV_SAMPLE_FMT_S32),
94  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32),
95  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32),
96  FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32),
97  FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32),
98  FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8 , AV_SAMPLE_FMT_FLT),
99  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT),
100  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT),
101  FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT),
102  FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT),
103  FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8 , AV_SAMPLE_FMT_DBL),
104  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL),
105  FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL),
106  FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL),
107  FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL),
108 };
109 
110 static void cpy1(uint8_t **dst, const uint8_t **src, int len){
111  memcpy(*dst, *src, len);
112 }
113 static void cpy2(uint8_t **dst, const uint8_t **src, int len){
114  memcpy(*dst, *src, 2*len);
115 }
116 static void cpy4(uint8_t **dst, const uint8_t **src, int len){
117  memcpy(*dst, *src, 4*len);
118 }
119 static void cpy8(uint8_t **dst, const uint8_t **src, int len){
120  memcpy(*dst, *src, 8*len);
121 }
122 
124  enum AVSampleFormat in_fmt,
125  int channels, const int *ch_map,
126  int flags)
127 {
128  AudioConvert *ctx;
129  conv_func_type *f = fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt) + AV_SAMPLE_FMT_NB*av_get_packed_sample_fmt(in_fmt)];
130 
131  if (!f)
132  return NULL;
133  ctx = av_mallocz(sizeof(*ctx));
134  if (!ctx)
135  return NULL;
136 
137  if(channels == 1){
138  in_fmt = av_get_planar_sample_fmt( in_fmt);
139  out_fmt = av_get_planar_sample_fmt(out_fmt);
140  }
141 
142  ctx->channels = channels;
143  ctx->conv_f = f;
144  ctx->ch_map = ch_map;
145  if (in_fmt == AV_SAMPLE_FMT_U8 || in_fmt == AV_SAMPLE_FMT_U8P)
146  memset(ctx->silence, 0x80, sizeof(ctx->silence));
147 
148  if(out_fmt == in_fmt && !ch_map) {
149  switch(av_get_bytes_per_sample(in_fmt)){
150  case 1:ctx->simd_f = cpy1; break;
151  case 2:ctx->simd_f = cpy2; break;
152  case 4:ctx->simd_f = cpy4; break;
153  case 8:ctx->simd_f = cpy8; break;
154  }
155  }
156 
157  if(HAVE_YASM && HAVE_MMX) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);
158  if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);
159 
160  return ctx;
161 }
162 
164 {
165  av_freep(ctx);
166 }
167 
169 {
170  int ch;
171  int off=0;
172  const int os= (out->planar ? 1 :out->ch_count) *out->bps;
173  unsigned misaligned = 0;
174 
175  av_assert0(ctx->channels == out->ch_count);
176 
177  if (ctx->in_simd_align_mask) {
178  int planes = in->planar ? in->ch_count : 1;
179  unsigned m = 0;
180  for (ch = 0; ch < planes; ch++)
181  m |= (intptr_t)in->ch[ch];
182  misaligned |= m & ctx->in_simd_align_mask;
183  }
184  if (ctx->out_simd_align_mask) {
185  int planes = out->planar ? out->ch_count : 1;
186  unsigned m = 0;
187  for (ch = 0; ch < planes; ch++)
188  m |= (intptr_t)out->ch[ch];
189  misaligned |= m & ctx->out_simd_align_mask;
190  }
191 
192  //FIXME optimize common cases
193 
194  if(ctx->simd_f && !ctx->ch_map && !misaligned){
195  off = len&~15;
196  av_assert1(off>=0);
197  av_assert1(off<=len);
198  av_assert2(ctx->channels == SWR_CH_MAX || !in->ch[ctx->channels]);
199  if(off>0){
200  if(out->planar == in->planar){
201  int planes = out->planar ? out->ch_count : 1;
202  for(ch=0; ch<planes; ch++){
203  ctx->simd_f(out->ch+ch, (const uint8_t **)in->ch+ch, off * (out->planar ? 1 :out->ch_count));
204  }
205  }else{
206  ctx->simd_f(out->ch, (const uint8_t **)in->ch, off);
207  }
208  }
209  if(off == len)
210  return 0;
211  }
212 
213  for(ch=0; ch<ctx->channels; ch++){
214  const int ich= ctx->ch_map ? ctx->ch_map[ch] : ch;
215  const int is= ich < 0 ? 0 : (in->planar ? 1 : in->ch_count) * in->bps;
216  const uint8_t *pi= ich < 0 ? ctx->silence : in->ch[ich];
217  uint8_t *po= out->ch[ch];
218  uint8_t *end= po + os*len;
219  if(!po)
220  continue;
221  ctx->conv_f(po+off*os, pi+off*is, is, os, end);
222  }
223  return 0;
224 }
Number of sample formats. DO NOT USE if linking dynamically.
Definition: samplefmt.h:63
simd_func_type * simd_f
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
#define HAVE_YASM
Definition: config.h:115
Audio buffer used for intermediate storage between conversion phases.
Definition: oss_audio.c:46
void( conv_func_type)(uint8_t *po, const uint8_t *pi, int is, int os, uint8_t *end)
int ch_count
number of channels
void swri_audio_convert_free(AudioConvert **ctx)
Free audio sample format converter context.
Sinusoidal phase f
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip in
Definition: git-howto.txt:5
signed 16 bits
Definition: samplefmt.h:52
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
av_cold void swri_audio_convert_init_arm(struct AudioConvert *ac, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
#define CONV_FUNC(ofmt, otype, ifmt, expr)
uint8_t
AudioConvert * swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags)
Create an audio sample format converter context.
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:63
end end
enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt)
Get the planar alternative form of the given sample format.
Definition: samplefmt.c:82
#define llrintf(x)
Definition: libm.h:117
#define lrintf(x)
Definition: libm_mips.h:70
unsigned m
#define U(x)
simple assert() macros that are a bit more flexible than ISO C assert().
void swri_audio_convert_init_x86(struct AudioConvert *ac, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels)
signed 32 bits
Definition: samplefmt.h:53
#define FMT_PAIR_FUNC(out, in)
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
#define ARCH_ARM
Definition: config.h:16
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
Definition: samplefmt.c:73
int bps
bytes per sample
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:104
NULL
Definition: eval.c:55
AVS_Value src
Definition: avisynth_c.h:523
#define llrint(x)
Definition: libm.h:112
Replacements for frequently missing libm functions.
static av_always_inline av_const long int lrint(double x)
Definition: libm.h:148
Audio format conversion routines.
static int flags
Definition: cpu.c:23
#define SWR_CH_MAX
Maximum number of channels.
Definition: swresample.h:102
AVSampleFormat
Audio Sample Formats.
Definition: samplefmt.h:49
uint8_t silence[8]
silence input sample
conv_func_type * conv_f
int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len)
Convert between audio sample formats.
unsigned 8 bits, planar
Definition: samplefmt.h:57
int len
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
The official guide to swscale for confused that is
Definition: swscale.txt:2
int planar
1 if planar audio, 0 otherwise
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
uint8_t * ch[SWR_CH_MAX]
samples buffer per channel
#define HAVE_MMX
Definition: config.h:48