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