Libav
|
00001 /* 00002 * audio conversion 00003 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00028 #include "libavutil/avstring.h" 00029 #include "libavutil/libm.h" 00030 #include "avcodec.h" 00031 #include "audioconvert.h" 00032 00033 typedef struct SampleFmtInfo { 00034 const char *name; 00035 int bits; 00036 } SampleFmtInfo; 00037 00039 static const SampleFmtInfo sample_fmt_info[SAMPLE_FMT_NB] = { 00040 [SAMPLE_FMT_U8] = { .name = "u8", .bits = 8 }, 00041 [SAMPLE_FMT_S16] = { .name = "s16", .bits = 16 }, 00042 [SAMPLE_FMT_S32] = { .name = "s32", .bits = 32 }, 00043 [SAMPLE_FMT_FLT] = { .name = "flt", .bits = 32 }, 00044 [SAMPLE_FMT_DBL] = { .name = "dbl", .bits = 64 }, 00045 }; 00046 00047 const char *avcodec_get_sample_fmt_name(int sample_fmt) 00048 { 00049 if (sample_fmt < 0 || sample_fmt >= SAMPLE_FMT_NB) 00050 return NULL; 00051 return sample_fmt_info[sample_fmt].name; 00052 } 00053 00054 enum SampleFormat avcodec_get_sample_fmt(const char* name) 00055 { 00056 int i; 00057 00058 for (i=0; i < SAMPLE_FMT_NB; i++) 00059 if (!strcmp(sample_fmt_info[i].name, name)) 00060 return i; 00061 return SAMPLE_FMT_NONE; 00062 } 00063 00064 void avcodec_sample_fmt_string (char *buf, int buf_size, int sample_fmt) 00065 { 00066 /* print header */ 00067 if (sample_fmt < 0) 00068 snprintf (buf, buf_size, "name " " depth"); 00069 else if (sample_fmt < SAMPLE_FMT_NB) { 00070 SampleFmtInfo info= sample_fmt_info[sample_fmt]; 00071 snprintf (buf, buf_size, "%-6s" " %2d ", info.name, info.bits); 00072 } 00073 } 00074 00075 static const char* const channel_names[]={ 00076 "FL", "FR", "FC", "LFE", "BL", "BR", "FLC", "FRC", 00077 "BC", "SL", "SR", "TC", "TFL", "TFC", "TFR", "TBL", 00078 "TBC", "TBR", 00079 [29] = "DL", 00080 [30] = "DR", 00081 }; 00082 00083 static const char *get_channel_name(int channel_id) 00084 { 00085 if (channel_id<0 || channel_id>=FF_ARRAY_ELEMS(channel_names)) 00086 return NULL; 00087 return channel_names[channel_id]; 00088 } 00089 00090 int64_t avcodec_guess_channel_layout(int nb_channels, enum CodecID codec_id, const char *fmt_name) 00091 { 00092 switch(nb_channels) { 00093 case 1: return CH_LAYOUT_MONO; 00094 case 2: return CH_LAYOUT_STEREO; 00095 case 3: return CH_LAYOUT_SURROUND; 00096 case 4: return CH_LAYOUT_QUAD; 00097 case 5: return CH_LAYOUT_5POINT0; 00098 case 6: return CH_LAYOUT_5POINT1; 00099 case 8: return CH_LAYOUT_7POINT1; 00100 default: return 0; 00101 } 00102 } 00103 00104 static const struct { 00105 const char *name; 00106 int nb_channels; 00107 int64_t layout; 00108 } channel_layout_map[] = { 00109 { "mono", 1, CH_LAYOUT_MONO }, 00110 { "stereo", 2, CH_LAYOUT_STEREO }, 00111 { "4.0", 4, CH_LAYOUT_4POINT0 }, 00112 { "quad", 4, CH_LAYOUT_QUAD }, 00113 { "5.0", 5, CH_LAYOUT_5POINT0 }, 00114 { "5.0", 5, CH_LAYOUT_5POINT0_BACK }, 00115 { "5.1", 6, CH_LAYOUT_5POINT1 }, 00116 { "5.1", 6, CH_LAYOUT_5POINT1_BACK }, 00117 { "5.1+downmix", 8, CH_LAYOUT_5POINT1|CH_LAYOUT_STEREO_DOWNMIX, }, 00118 { "7.1", 8, CH_LAYOUT_7POINT1 }, 00119 { "7.1(wide)", 8, CH_LAYOUT_7POINT1_WIDE }, 00120 { "7.1+downmix", 10, CH_LAYOUT_7POINT1|CH_LAYOUT_STEREO_DOWNMIX, }, 00121 { 0 } 00122 }; 00123 00124 void avcodec_get_channel_layout_string(char *buf, int buf_size, int nb_channels, int64_t channel_layout) 00125 { 00126 int i; 00127 00128 for (i=0; channel_layout_map[i].name; i++) 00129 if (nb_channels == channel_layout_map[i].nb_channels && 00130 channel_layout == channel_layout_map[i].layout) { 00131 av_strlcpy(buf, channel_layout_map[i].name, buf_size); 00132 return; 00133 } 00134 00135 snprintf(buf, buf_size, "%d channels", nb_channels); 00136 if (channel_layout) { 00137 int i,ch; 00138 av_strlcat(buf, " (", buf_size); 00139 for(i=0,ch=0; i<64; i++) { 00140 if ((channel_layout & (1L<<i))) { 00141 const char *name = get_channel_name(i); 00142 if (name) { 00143 if (ch>0) av_strlcat(buf, "|", buf_size); 00144 av_strlcat(buf, name, buf_size); 00145 } 00146 ch++; 00147 } 00148 } 00149 av_strlcat(buf, ")", buf_size); 00150 } 00151 } 00152 00153 int avcodec_channel_layout_num_channels(int64_t channel_layout) 00154 { 00155 int count; 00156 uint64_t x = channel_layout; 00157 for (count = 0; x; count++) 00158 x &= x-1; // unset lowest set bit 00159 return count; 00160 } 00161 00162 struct AVAudioConvert { 00163 int in_channels, out_channels; 00164 int fmt_pair; 00165 }; 00166 00167 AVAudioConvert *av_audio_convert_alloc(enum SampleFormat out_fmt, int out_channels, 00168 enum SampleFormat in_fmt, int in_channels, 00169 const float *matrix, int flags) 00170 { 00171 AVAudioConvert *ctx; 00172 if (in_channels!=out_channels) 00173 return NULL; /* FIXME: not supported */ 00174 ctx = av_malloc(sizeof(AVAudioConvert)); 00175 if (!ctx) 00176 return NULL; 00177 ctx->in_channels = in_channels; 00178 ctx->out_channels = out_channels; 00179 ctx->fmt_pair = out_fmt + SAMPLE_FMT_NB*in_fmt; 00180 return ctx; 00181 } 00182 00183 void av_audio_convert_free(AVAudioConvert *ctx) 00184 { 00185 av_free(ctx); 00186 } 00187 00188 int av_audio_convert(AVAudioConvert *ctx, 00189 void * const out[6], const int out_stride[6], 00190 const void * const in[6], const int in_stride[6], int len) 00191 { 00192 int ch; 00193 00194 //FIXME optimize common cases 00195 00196 for(ch=0; ch<ctx->out_channels; ch++){ 00197 const int is= in_stride[ch]; 00198 const int os= out_stride[ch]; 00199 const uint8_t *pi= in[ch]; 00200 uint8_t *po= out[ch]; 00201 uint8_t *end= po + os*len; 00202 if(!out[ch]) 00203 continue; 00204 00205 #define CONV(ofmt, otype, ifmt, expr)\ 00206 if(ctx->fmt_pair == ofmt + SAMPLE_FMT_NB*ifmt){\ 00207 do{\ 00208 *(otype*)po = expr; pi += is; po += os;\ 00209 }while(po < end);\ 00210 } 00211 00212 //FIXME put things below under ifdefs so we do not waste space for cases no codec will need 00213 //FIXME rounding ? 00214 00215 CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_U8 , *(const uint8_t*)pi) 00216 else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<8) 00217 else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<24) 00218 else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) 00219 else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) 00220 else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_S16, (*(const int16_t*)pi>>8) + 0x80) 00221 else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_S16, *(const int16_t*)pi) 00222 else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_S16, *(const int16_t*)pi<<16) 00223 else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) 00224 else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) 00225 else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_S32, (*(const int32_t*)pi>>24) + 0x80) 00226 else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_S32, *(const int32_t*)pi>>16) 00227 else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_S32, *(const int32_t*)pi) 00228 else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1<<31))) 00229 else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1<<31))) 00230 else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_FLT, av_clip_uint8( lrintf(*(const float*)pi * (1<<7)) + 0x80)) 00231 else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_FLT, av_clip_int16( lrintf(*(const float*)pi * (1<<15)))) 00232 else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float*)pi * (1U<<31)))) 00233 else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_FLT, *(const float*)pi) 00234 else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_FLT, *(const float*)pi) 00235 else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_DBL, av_clip_uint8( lrint(*(const double*)pi * (1<<7)) + 0x80)) 00236 else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_DBL, av_clip_int16( lrint(*(const double*)pi * (1<<15)))) 00237 else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double*)pi * (1U<<31)))) 00238 else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_DBL, *(const double*)pi) 00239 else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_DBL, *(const double*)pi) 00240 else return -1; 00241 } 00242 return 0; 00243 }