X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Faudioconvert.c;h=112e22096b65d0e720b0b64c84df558e6aec7aea;hb=b6a6e90a7c79f9530637a1efb62e0af4049822c1;hp=4c021219f0f93fa62ef58ea1f0c243113d75bd88;hpb=e5a389a1b70a32a56aa83377e88bf718251aa8f0;p=ffmpeg diff --git a/libavcodec/audioconvert.c b/libavcodec/audioconvert.c index 4c021219f0f..112e22096b6 100644 --- a/libavcodec/audioconvert.c +++ b/libavcodec/audioconvert.c @@ -2,76 +2,113 @@ * audio conversion * Copyright (c) 2006 Michael Niedermayer * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** - * @file audioconvert.c + * @file * audio conversion * @author Michael Niedermayer */ +#include "libavutil/avstring.h" +#include "libavutil/libm.h" +#include "libavutil/samplefmt.h" #include "avcodec.h" +#include "audioconvert.h" -int av_audio_convert(void *maybe_dspcontext_or_something_av_convert_specific, - void *out[6], int out_stride[6], enum SampleFormat out_fmt, - void * in[6], int in_stride[6], enum SampleFormat in_fmt, int len){ +struct AVAudioConvert { + int in_channels, out_channels; + int fmt_pair; +}; + +AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels, + enum AVSampleFormat in_fmt, int in_channels, + const float *matrix, int flags) +{ + AVAudioConvert *ctx; + if (in_channels!=out_channels) + return NULL; /* FIXME: not supported */ + ctx = av_malloc(sizeof(AVAudioConvert)); + if (!ctx) + return NULL; + ctx->in_channels = in_channels; + ctx->out_channels = out_channels; + ctx->fmt_pair = out_fmt + AV_SAMPLE_FMT_NB*in_fmt; + return ctx; +} + +void av_audio_convert_free(AVAudioConvert *ctx) +{ + av_free(ctx); +} + +int av_audio_convert(AVAudioConvert *ctx, + void * const out[6], const int out_stride[6], + const void * const in[6], const int in_stride[6], int len) +{ int ch; - const int isize= FFMIN( in_fmt+1, 4); - const int osize= FFMIN(out_fmt+1, 4); - const int fmt_pair= out_fmt + 5*in_fmt; //FIXME optimize common cases - for(ch=0; ch<6; ch++){ - const int is= in_stride[ch] * isize; - const int os= out_stride[ch] * osize; - uint8_t *pi= in[ch]; + for(ch=0; chout_channels; ch++){ + const int is= in_stride[ch]; + const int os= out_stride[ch]; + const uint8_t *pi= in[ch]; uint8_t *po= out[ch]; - uint8_t *end= po + os; + uint8_t *end= po + os*len; if(!out[ch]) continue; #define CONV(ofmt, otype, ifmt, expr)\ -if(fmt_pair == ofmt + 5*ifmt){\ +if(ctx->fmt_pair == ofmt + AV_SAMPLE_FMT_NB*ifmt){\ do{\ *(otype*)po = expr; pi += is; po += os;\ }while(po < end);\ } //FIXME put things below under ifdefs so we do not waste space for cases no codec will need -//FIXME rounding and clipping ? +//FIXME rounding ? - CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_U8 , *(uint8_t*)pi) - else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_U8 , (*(uint8_t*)pi - 0x80)<<8) - else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_U8 , (*(uint8_t*)pi - 0x80)<<24) - else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_U8 , (*(uint8_t*)pi - 0x80)*(1.0 / (1<<7))) - else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_S16, (*(int16_t*)pi>>8) + 0x80) - else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_S16, *(int16_t*)pi) - else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_S16, *(int16_t*)pi<<16) - else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_S16, *(int16_t*)pi*(1.0 / (1<<15))) - else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_S32, (*(int32_t*)pi>>24) + 0x80) - else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_S32, *(int32_t*)pi>>16) - else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_S32, *(int32_t*)pi) - else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_S32, *(int32_t*)pi*(1.0 / (1<<31))) - else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_FLT, lrintf(*(float*)pi * (1<<7)) + 0x80) - else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_FLT, lrintf(*(float*)pi * (1<<15))) - else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_FLT, lrintf(*(float*)pi * (1<<31))) - else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_FLT, *(float*)pi) + CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_U8 , *(const uint8_t*)pi) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<8) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<24) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) + else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S16, (*(const int16_t*)pi>>8) + 0x80) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi<<16) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) + else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S32, (*(const int32_t*)pi>>24) + 0x80) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi>>16) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31))) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31))) + else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8( lrintf(*(const float*)pi * (1<<7)) + 0x80)) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16( lrintf(*(const float*)pi * (1<<15)))) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float*)pi * (1U<<31)))) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_FLT, *(const float*)pi) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_FLT, *(const float*)pi) + else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8( lrint(*(const double*)pi * (1<<7)) + 0x80)) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16( lrint(*(const double*)pi * (1<<15)))) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double*)pi * (1U<<31)))) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_DBL, *(const double*)pi) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_DBL, *(const double*)pi) else return -1; } return 0;