Browse code

Add libswresample. Similar to libswscale this does resampling and format convertion, just for audio instead of video. changing sampling rate, sample formats, channel layouts and sample packing all in one with a very simple public interface.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2011/09/19 13:13:30
Showing 18 changed files
... ...
@@ -33,6 +33,7 @@ FFLIBS-$(CONFIG_AVFILTER) += avfilter
33 33
 FFLIBS-$(CONFIG_AVFORMAT) += avformat
34 34
 FFLIBS-$(CONFIG_AVCODEC)  += avcodec
35 35
 FFLIBS-$(CONFIG_POSTPROC) += postproc
36
+FFLIBS-$(CONFIG_SWRESAMPLE)+= swresample
36 37
 FFLIBS-$(CONFIG_SWSCALE)  += swscale
37 38
 
38 39
 FFLIBS := avutil
... ...
@@ -20,7 +20,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR))))
20 20
 $(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))
21 21
 endif
22 22
 
23
-ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale
23
+ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale swresample
24 24
 
25 25
 # NASM requires -I path terminated with /
26 26
 IFLAGS     := -I. -I$(SRC_PATH)/
... ...
@@ -89,6 +89,7 @@ Configuration options:
89 89
   --disable-avdevice       disable libavdevice build
90 90
   --disable-avcodec        disable libavcodec build
91 91
   --disable-avformat       disable libavformat build
92
+  --disable-swresample     disable libswresample build
92 93
   --disable-swscale        disable libswscale build
93 94
   --disable-postproc       disable libpostproc build
94 95
   --disable-avfilter       disable video filter support [no]
... ...
@@ -1037,6 +1038,7 @@ CONFIG_LIST="
1037 1037
     small
1038 1038
     sram
1039 1039
     static
1040
+    swresample
1040 1041
     swscale
1041 1042
     swscale_alpha
1042 1043
     thumb
... ...
@@ -1603,7 +1605,7 @@ avformat_deps="avcodec"
1603 1603
 postproc_deps="gpl"
1604 1604
 
1605 1605
 # programs
1606
-ffmpeg_deps="avcodec avformat swscale"
1606
+ffmpeg_deps="avcodec avformat swscale swresample"
1607 1607
 ffmpeg_select="buffer_filter buffersink_filter"
1608 1608
 avconv_deps="avcodec avformat swscale"
1609 1609
 avconv_select="buffer_filter"
... ...
@@ -1766,6 +1768,7 @@ enable postproc
1766 1766
 enable protocols
1767 1767
 enable static
1768 1768
 enable stripping
1769
+enable swresample
1769 1770
 enable swscale
1770 1771
 enable swscale_alpha
1771 1772
 
... ...
@@ -3143,7 +3146,7 @@ enabled extra_warnings && check_cflags -Winline
3143 3143
 
3144 3144
 # add some linker flags
3145 3145
 check_ldflags -Wl,--warn-common
3146
-check_ldflags -Wl,-rpath-link=libpostproc:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil
3146
+check_ldflags -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil
3147 3147
 test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic
3148 3148
 
3149 3149
 echo "X{};" > $TMPV
... ...
@@ -45,6 +45,7 @@
45 45
 #include "libavutil/avstring.h"
46 46
 #include "libavutil/libm.h"
47 47
 #include "libavformat/os_support.h"
48
+#include "libswresample/swresample.h"
48 49
 
49 50
 #include "libavformat/ffm.h" // not public API
50 51
 
... ...
@@ -229,15 +230,14 @@ typedef struct OutputStream {
229 229
 
230 230
     /* audio only */
231 231
     int audio_resample;
232
-    ReSampleContext *resample; /* for audio resampling */
233 232
     int resample_sample_fmt;
234 233
     int resample_channels;
235 234
     int resample_sample_rate;
236
-    int reformat_pair;
237
-    AVAudioConvert *reformat_ctx;
238 235
     AVFifoBuffer *fifo;     /* for compression: one audio fifo per codec */
239 236
     FILE *logfile;
240 237
 
238
+    struct SwrContext *swr;
239
+
241 240
 #if CONFIG_AVFILTER
242 241
     AVFilterContext *output_video_filter;
243 242
     AVFilterContext *input_video_filter;
... ...
@@ -843,14 +843,15 @@ need_realloc:
843 843
         exit_program(1);
844 844
     }
845 845
 
846
-    if (enc->channels != dec->channels)
846
+    if (enc->channels != dec->channels
847
+     || enc->sample_fmt != dec->sample_fmt)
847 848
         ost->audio_resample = 1;
848 849
 
849 850
     resample_changed = ost->resample_sample_fmt  != dec->sample_fmt ||
850 851
                        ost->resample_channels    != dec->channels   ||
851 852
                        ost->resample_sample_rate != dec->sample_rate;
852 853
 
853
-    if ((ost->audio_resample && !ost->resample) || resample_changed) {
854
+    if ((ost->audio_resample && !ost->swr) || resample_changed) {
854 855
         if (resample_changed) {
855 856
             av_log(NULL, AV_LOG_INFO, "Input stream #%d.%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n",
856 857
                    ist->file_index, ist->st->index,
... ...
@@ -859,24 +860,29 @@ need_realloc:
859 859
             ost->resample_sample_fmt  = dec->sample_fmt;
860 860
             ost->resample_channels    = dec->channels;
861 861
             ost->resample_sample_rate = dec->sample_rate;
862
-            if (ost->resample)
863
-                audio_resample_close(ost->resample);
862
+            swr_free(&ost->swr);
864 863
         }
865 864
         /* if audio_sync_method is >1 the resampler is needed for audio drift compensation */
866 865
         if (audio_sync_method <= 1 &&
867 866
             ost->resample_sample_fmt  == enc->sample_fmt &&
868 867
             ost->resample_channels    == enc->channels   &&
869 868
             ost->resample_sample_rate == enc->sample_rate) {
870
-            ost->resample = NULL;
869
+            //ost->swr = NULL;
871 870
             ost->audio_resample = 0;
872 871
         } else {
873
-            if (dec->sample_fmt != AV_SAMPLE_FMT_S16)
874
-                fprintf(stderr, "Warning, using s16 intermediate sample format for resampling\n");
875
-            ost->resample = av_audio_resample_init(enc->channels,    dec->channels,
876
-                                                   enc->sample_rate, dec->sample_rate,
877
-                                                   enc->sample_fmt,  dec->sample_fmt,
878
-                                                   16, 10, 0, 0.8);
879
-            if (!ost->resample) {
872
+            ost->swr = swr_alloc2(ost->swr,
873
+                                  enc->channel_layout, enc->sample_fmt, enc->sample_rate,
874
+                                  dec->channel_layout, dec->sample_fmt, dec->sample_rate,
875
+                                  0, NULL);
876
+            av_set_int(ost->swr, "ich", dec->channels);
877
+            av_set_int(ost->swr, "och", enc->channels);
878
+            if(audio_sync_method>1) av_set_int(ost->swr, "flags", SWR_FLAG_RESAMPLE);
879
+            if(ost->swr && swr_init(ost->swr) < 0){
880
+                fprintf(stderr, "swr_init() failed\n");
881
+                swr_free(&ost->swr);
882
+            }
883
+
884
+            if (!ost->swr) {
880 885
                 fprintf(stderr, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n",
881 886
                         dec->channels, dec->sample_rate,
882 887
                         enc->channels, enc->sample_rate);
... ...
@@ -885,21 +891,7 @@ need_realloc:
885 885
         }
886 886
     }
887 887
 
888
-#define MAKE_SFMT_PAIR(a,b) ((a)+AV_SAMPLE_FMT_NB*(b))
889
-    if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt &&
890
-        MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt)!=ost->reformat_pair) {
891
-        if (ost->reformat_ctx)
892
-            av_audio_convert_free(ost->reformat_ctx);
893
-        ost->reformat_ctx = av_audio_convert_alloc(enc->sample_fmt, 1,
894
-                                                   dec->sample_fmt, 1, NULL, 0);
895
-        if (!ost->reformat_ctx) {
896
-            fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
897
-                av_get_sample_fmt_name(dec->sample_fmt),
898
-                av_get_sample_fmt_name(enc->sample_fmt));
899
-            exit_program(1);
900
-        }
901
-        ost->reformat_pair=MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt);
902
-    }
888
+    av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt);
903 889
 
904 890
     if(audio_sync_method){
905 891
         double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts
... ...
@@ -941,7 +933,7 @@ need_realloc:
941 941
                 if(verbose > 2)
942 942
                     fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate);
943 943
 //                fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
944
-                av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate);
944
+                swr_compensate(ost->swr, comp, enc->sample_rate);
945 945
             }
946 946
         }
947 947
     }else
... ...
@@ -950,30 +942,15 @@ need_realloc:
950 950
 
951 951
     if (ost->audio_resample) {
952 952
         buftmp = audio_buf;
953
-        size_out = audio_resample(ost->resample,
954
-                                  (short *)buftmp, (short *)buf,
955
-                                  size / (dec->channels * isize));
953
+        size_out = swr_convert(ost->swr, (      uint8_t*[]){buftmp}, audio_buf_size / (enc->channels * osize),
954
+                                         (const uint8_t*[]){buf   }, size / (dec->channels * isize));
956 955
         size_out = size_out * enc->channels * osize;
957 956
     } else {
958 957
         buftmp = buf;
959 958
         size_out = size;
960 959
     }
961 960
 
962
-    if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt) {
963
-        const void *ibuf[6]= {buftmp};
964
-        void *obuf[6]= {audio_buf};
965
-        int istride[6]= {isize};
966
-        int ostride[6]= {osize};
967
-        int len= size_out/istride[0];
968
-        if (av_audio_convert(ost->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
969
-            printf("av_audio_convert() failed\n");
970
-            if (exit_on_error)
971
-                exit_program(1);
972
-            return;
973
-        }
974
-        buftmp = audio_buf;
975
-        size_out = len*osize;
976
-    }
961
+    av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt);
977 962
 
978 963
     /* now encode as many frames as possible */
979 964
     if (enc->frame_size > 1) {
... ...
@@ -2133,7 +2110,6 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
2133 2133
                 if (!ost->fifo) {
2134 2134
                     return AVERROR(ENOMEM);
2135 2135
                 }
2136
-                ost->reformat_pair = MAKE_SFMT_PAIR(AV_SAMPLE_FMT_NONE,AV_SAMPLE_FMT_NONE);
2137 2136
                 if (!codec->sample_rate) {
2138 2137
                     codec->sample_rate = icodec->sample_rate;
2139 2138
                 }
... ...
@@ -2149,6 +2125,8 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
2149 2149
                 if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels)
2150 2150
                     codec->channel_layout = 0;
2151 2151
                 ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
2152
+                ost->audio_resample |=    codec->sample_fmt     != icodec->sample_fmt
2153
+                                       || codec->channel_layout != icodec->channel_layout;
2152 2154
                 icodec->request_channels = codec->channels;
2153 2155
                 ist->decoding_needed = 1;
2154 2156
                 ost->encoding_needed = 1;
... ...
@@ -2679,10 +2657,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
2679 2679
                 av_free(ost->forced_kf_pts);
2680 2680
                 if (ost->video_resample)
2681 2681
                     sws_freeContext(ost->img_resample_ctx);
2682
-                if (ost->resample)
2683
-                    audio_resample_close(ost->resample);
2684
-                if (ost->reformat_ctx)
2685
-                    av_audio_convert_free(ost->reformat_ctx);
2682
+                swr_free(&ost->swr);
2686 2683
                 av_dict_free(&ost->opts);
2687 2684
             }
2688 2685
         }
2689 2686
new file mode 100644
... ...
@@ -0,0 +1,12 @@
0
+include $(SUBDIR)../config.mak
1
+
2
+NAME = swresample
3
+FFLIBS = avutil
4
+
5
+HEADERS = swresample.h
6
+
7
+OBJS = swresample.o audioconvert.o resample2.o rematrix.o
8
+
9
+TESTPROGS = swresample_test
10
+
11
+include $(SUBDIR)../subdir.mak
0 12
new file mode 100644
... ...
@@ -0,0 +1,113 @@
0
+/*
1
+ * audio conversion
2
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * audio conversion
24
+ * @author Michael Niedermayer <michaelni@gmx.at>
25
+ */
26
+
27
+#include "libavutil/avstring.h"
28
+#include "libavutil/avassert.h"
29
+#include "libavutil/libm.h"
30
+#include "libavutil/samplefmt.h"
31
+#include "audioconvert.h"
32
+
33
+
34
+struct AVAudioConvert {
35
+    int channels;
36
+    int fmt_pair;
37
+};
38
+
39
+AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,
40
+                                        enum AVSampleFormat in_fmt,
41
+                                        int channels, int flags)
42
+{
43
+    AVAudioConvert *ctx;
44
+    ctx = av_malloc(sizeof(AVAudioConvert));
45
+    if (!ctx)
46
+        return NULL;
47
+    ctx->channels = channels;
48
+    ctx->fmt_pair = out_fmt + AV_SAMPLE_FMT_NB*in_fmt;
49
+    return ctx;
50
+}
51
+
52
+void swr_audio_convert_free(AVAudioConvert **ctx)
53
+{
54
+    av_freep(ctx);
55
+}
56
+
57
+int swr_audio_convert(AVAudioConvert *ctx, AudioData *out, AudioData*in, int len)
58
+{
59
+    int ch;
60
+
61
+    av_assert0(ctx->channels == out->ch_count);
62
+
63
+    //FIXME optimize common cases
64
+
65
+    for(ch=0; ch<ctx->channels; ch++){
66
+        const int is= (in ->planar ? 1 : in->ch_count) * in->bps;
67
+        const int os= (out->planar ? 1 :out->ch_count) *out->bps;
68
+        const uint8_t *pi= in ->ch[ch];
69
+        uint8_t       *po= out->ch[ch];
70
+        uint8_t *end= po + os*len;
71
+        if(!po)
72
+            continue;
73
+
74
+#define CONV(ofmt, otype, ifmt, expr)\
75
+if(ctx->fmt_pair == ofmt + AV_SAMPLE_FMT_NB*ifmt){\
76
+    do{\
77
+        *(otype*)po = expr; pi += is; po += os;\
78
+    }while(po < end);\
79
+}
80
+
81
+//FIXME put things below under ifdefs so we do not waste space for cases no codec will need
82
+//FIXME rounding ?
83
+
84
+             CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_U8 ,  *(const uint8_t*)pi)
85
+        else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<8)
86
+        else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<24)
87
+        else CONV(AV_SAMPLE_FMT_FLT, float  , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7)))
88
+        else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7)))
89
+        else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S16, (*(const int16_t*)pi>>8) + 0x80)
90
+        else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16,  *(const int16_t*)pi)
91
+        else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16,  *(const int16_t*)pi<<16)
92
+        else CONV(AV_SAMPLE_FMT_FLT, float  , AV_SAMPLE_FMT_S16,  *(const int16_t*)pi*(1.0 / (1<<15)))
93
+        else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S16,  *(const int16_t*)pi*(1.0 / (1<<15)))
94
+        else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S32, (*(const int32_t*)pi>>24) + 0x80)
95
+        else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32,  *(const int32_t*)pi>>16)
96
+        else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32,  *(const int32_t*)pi)
97
+        else CONV(AV_SAMPLE_FMT_FLT, float  , AV_SAMPLE_FMT_S32,  *(const int32_t*)pi*(1.0 / (1U<<31)))
98
+        else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S32,  *(const int32_t*)pi*(1.0 / (1U<<31)))
99
+        else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(  lrintf(*(const float*)pi * (1<<7)) + 0x80))
100
+        else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(  lrintf(*(const float*)pi * (1<<15))))
101
+        else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float*)pi * (1U<<31))))
102
+        else CONV(AV_SAMPLE_FMT_FLT, float  , AV_SAMPLE_FMT_FLT, *(const float*)pi)
103
+        else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_FLT, *(const float*)pi)
104
+        else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(  lrint(*(const double*)pi * (1<<7)) + 0x80))
105
+        else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(  lrint(*(const double*)pi * (1<<15))))
106
+        else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double*)pi * (1U<<31))))
107
+        else CONV(AV_SAMPLE_FMT_FLT, float  , AV_SAMPLE_FMT_DBL, *(const double*)pi)
108
+        else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_DBL, *(const double*)pi)
109
+        else return -1;
110
+    }
111
+    return 0;
112
+}
0 113
new file mode 100644
... ...
@@ -0,0 +1,65 @@
0
+/*
1
+ * audio conversion
2
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
3
+ * Copyright (c) 2008 Peter Ross
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
+#ifndef SWR_AUDIOCONVERT_H
23
+#define SWR_AUDIOCONVERT_H
24
+
25
+/**
26
+ * @file
27
+ * Audio format conversion routines
28
+ */
29
+
30
+
31
+#include "swresample_internal.h"
32
+#include "libavutil/cpu.h"
33
+#include "libavutil/audioconvert.h"
34
+
35
+struct AVAudioConvert;
36
+typedef struct AVAudioConvert AVAudioConvert;
37
+
38
+/**
39
+ * Create an audio sample format converter context
40
+ * @param out_fmt Output sample format
41
+ * @param in_fmt Input sample format
42
+ * @param channels Number of channels
43
+ * @param flags See AV_CPU_FLAG_xx
44
+ * @return NULL on error
45
+ */
46
+AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,
47
+                                        enum AVSampleFormat in_fmt,
48
+                                        int channels, int flags);
49
+
50
+/**
51
+ * Free audio sample format converter context.
52
+ * and set the pointer to NULL
53
+ */
54
+void swr_audio_convert_free(AVAudioConvert **ctx);
55
+
56
+/**
57
+ * Convert between audio sample formats
58
+ * @param[in] out array of output buffers for each channel. set to NULL to ignore processing of the given channel.
59
+ * @param[in] in array of input buffers for each channel
60
+ * @param len length of audio frame size (measured in samples)
61
+ */
62
+int swr_audio_convert(AVAudioConvert *ctx, AudioData *out, AudioData *in, int len);
63
+
64
+#endif /* AVCODEC_AUDIOCONVERT_H */
0 65
new file mode 100644
... ...
@@ -0,0 +1,271 @@
0
+/*
1
+ * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
2
+ *
3
+ * This file is part of libswresample
4
+ *
5
+ * libswresample is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * libswresample is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with libswresample; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "swresample_internal.h"
21
+#include "libavutil/audioconvert.h"
22
+#include "libavutil/avassert.h"
23
+
24
+#define SAMPLE float
25
+#define RENAME(x) x ## _float
26
+#include "rematrix_template.c"
27
+#undef SAMPLE
28
+#undef RENAME
29
+
30
+#define SAMPLE int16_t
31
+#define RENAME(x) x ## _s16
32
+#include "rematrix_template.c"
33
+
34
+
35
+#define FRONT_LEFT             0
36
+#define FRONT_RIGHT            1
37
+#define FRONT_CENTER           2
38
+#define LOW_FREQUENCY          3
39
+#define BACK_LEFT              4
40
+#define BACK_RIGHT             5
41
+#define FRONT_LEFT_OF_CENTER   6
42
+#define FRONT_RIGHT_OF_CENTER  7
43
+#define BACK_CENTER            8
44
+#define SIDE_LEFT              9
45
+#define SIDE_RIGHT             10
46
+#define TOP_CENTER             11
47
+#define TOP_FRONT_LEFT         12
48
+#define TOP_FRONT_CENTER       13
49
+#define TOP_FRONT_RIGHT        14
50
+#define TOP_BACK_LEFT          15
51
+#define TOP_BACK_CENTER        16
52
+#define TOP_BACK_RIGHT         17
53
+
54
+static int even(int64_t layout){
55
+    if(!layout) return 1;
56
+    if(layout&(layout-1)) return 1;
57
+    return 0;
58
+}
59
+
60
+static int sane_layout(int64_t layout){
61
+    if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
62
+        return 0;
63
+    if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front
64
+        return 0;
65
+    if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))   // no asymetric side
66
+        return 0;
67
+    if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
68
+        return 0;
69
+    if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))
70
+        return 0;
71
+    if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX)
72
+        return 0;
73
+
74
+    return 1;
75
+}
76
+
77
+int swr_rematrix_init(SwrContext *s){
78
+    int i, j, in_i, out_i;
79
+    float matrix[64][64]={0};
80
+    int64_t unaccounted= s->in_ch_layout & ~s->out_ch_layout;
81
+    float maxcoef=0;
82
+
83
+    for(i=0; i<64; i++){
84
+        if(s->in_ch_layout & s->out_ch_layout & (1LL<<i))
85
+            matrix[i][i]= 1.0;
86
+    }
87
+
88
+    if(!sane_layout(s->in_ch_layout)){
89
+        av_log(s, AV_LOG_ERROR, "Input channel layout isnt supported\n");
90
+        return AVERROR(EINVAL);
91
+    }
92
+    if(!sane_layout(s->out_ch_layout)){
93
+        av_log(s, AV_LOG_ERROR, "Output channel layout isnt supported\n");
94
+        return AVERROR(EINVAL);
95
+    }
96
+
97
+//FIXME implement dolby surround
98
+//FIXME implement full ac3
99
+
100
+
101
+    if(unaccounted & AV_CH_FRONT_CENTER){
102
+        if((s->out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
103
+            matrix[ FRONT_LEFT][FRONT_CENTER]+= sqrt(0.5);
104
+            matrix[FRONT_RIGHT][FRONT_CENTER]+= sqrt(0.5);
105
+        }else
106
+            av_assert0(0);
107
+    }
108
+    if(unaccounted & AV_CH_LAYOUT_STEREO){
109
+        if(s->out_ch_layout & AV_CH_FRONT_CENTER){
110
+            matrix[FRONT_CENTER][ FRONT_LEFT]+= sqrt(0.5);
111
+            matrix[FRONT_CENTER][FRONT_RIGHT]+= sqrt(0.5);
112
+            if(s->in_ch_layout & AV_CH_FRONT_CENTER)
113
+                matrix[FRONT_CENTER][ FRONT_CENTER] = s->clev*sqrt(2);
114
+        }else
115
+            av_assert0(0);
116
+    }
117
+
118
+    if(unaccounted & AV_CH_BACK_CENTER){
119
+        if(s->out_ch_layout & AV_CH_BACK_LEFT){
120
+            matrix[ BACK_LEFT][BACK_CENTER]+= sqrt(0.5);
121
+            matrix[BACK_RIGHT][BACK_CENTER]+= sqrt(0.5);
122
+        }else if(s->out_ch_layout & AV_CH_SIDE_LEFT){
123
+            matrix[ SIDE_LEFT][BACK_CENTER]+= sqrt(0.5);
124
+            matrix[SIDE_RIGHT][BACK_CENTER]+= sqrt(0.5);
125
+        }else if(s->out_ch_layout & AV_CH_FRONT_LEFT){
126
+            matrix[ FRONT_LEFT][BACK_CENTER]+= s->slev*sqrt(0.5);
127
+            matrix[FRONT_RIGHT][BACK_CENTER]+= s->slev*sqrt(0.5);
128
+        }else if(s->out_ch_layout & AV_CH_FRONT_CENTER){
129
+            matrix[ FRONT_CENTER][BACK_CENTER]+= s->slev*sqrt(0.5);
130
+        }else
131
+            av_assert0(0);
132
+    }
133
+    if(unaccounted & AV_CH_BACK_LEFT){
134
+        if(s->out_ch_layout & AV_CH_BACK_CENTER){
135
+            matrix[BACK_CENTER][ BACK_LEFT]+= sqrt(0.5);
136
+            matrix[BACK_CENTER][BACK_RIGHT]+= sqrt(0.5);
137
+        }else if(s->out_ch_layout & AV_CH_SIDE_LEFT){
138
+            if(s->in_ch_layout & AV_CH_SIDE_LEFT){
139
+                matrix[ SIDE_LEFT][ BACK_LEFT]+= sqrt(0.5);
140
+                matrix[SIDE_RIGHT][BACK_RIGHT]+= sqrt(0.5);
141
+            }else{
142
+            matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
143
+            matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
144
+            }
145
+        }else if(s->out_ch_layout & AV_CH_FRONT_LEFT){
146
+            matrix[ FRONT_LEFT][ BACK_LEFT]+= s->slev;
147
+            matrix[FRONT_RIGHT][BACK_RIGHT]+= s->slev;
148
+        }else if(s->out_ch_layout & AV_CH_FRONT_CENTER){
149
+            matrix[ FRONT_CENTER][BACK_LEFT ]+= s->slev*sqrt(0.5);
150
+            matrix[ FRONT_CENTER][BACK_RIGHT]+= s->slev*sqrt(0.5);
151
+        }else
152
+            av_assert0(0);
153
+    }
154
+
155
+    if(unaccounted & AV_CH_SIDE_LEFT){
156
+        if(s->out_ch_layout & AV_CH_BACK_LEFT){
157
+            matrix[ BACK_LEFT][ SIDE_LEFT]+= 1.0;
158
+            matrix[BACK_RIGHT][SIDE_RIGHT]+= 1.0;
159
+        }else if(s->out_ch_layout & AV_CH_BACK_CENTER){
160
+            matrix[BACK_CENTER][ SIDE_LEFT]+= sqrt(0.5);
161
+            matrix[BACK_CENTER][SIDE_RIGHT]+= sqrt(0.5);
162
+        }else if(s->out_ch_layout & AV_CH_FRONT_LEFT){
163
+            matrix[ FRONT_LEFT][ SIDE_LEFT]+= s->slev;
164
+            matrix[FRONT_RIGHT][SIDE_RIGHT]+= s->slev;
165
+        }else if(s->out_ch_layout & AV_CH_FRONT_CENTER){
166
+            matrix[ FRONT_CENTER][SIDE_LEFT ]+= s->slev*sqrt(0.5);
167
+            matrix[ FRONT_CENTER][SIDE_RIGHT]+= s->slev*sqrt(0.5);
168
+        }else
169
+            av_assert0(0);
170
+    }
171
+
172
+    if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
173
+        if(s->out_ch_layout & AV_CH_FRONT_LEFT){
174
+            matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
175
+            matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
176
+        }else if(s->out_ch_layout & AV_CH_FRONT_CENTER){
177
+            matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= sqrt(0.5);
178
+            matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= sqrt(0.5);
179
+        }else
180
+            av_assert0(0);
181
+    }
182
+
183
+    //FIXME quantize for integeres
184
+    for(out_i=i=0; i<64; i++){
185
+        double sum=0;
186
+        int in_i=0;
187
+        int ch_in=0;
188
+        for(j=0; j<64; j++){
189
+            s->matrix[out_i][in_i]= matrix[i][j];
190
+            if(matrix[i][j]){
191
+                s->matrix_ch[out_i][++ch_in]= in_i;
192
+                sum += fabs(matrix[i][j]);
193
+            }
194
+            if(s->in_ch_layout & (1ULL<<j))
195
+                in_i++;
196
+        }
197
+        s->matrix_ch[out_i][0]= ch_in;
198
+        maxcoef= FFMAX(maxcoef, sum);
199
+        if(s->out_ch_layout & (1ULL<<i))
200
+            out_i++;
201
+    }
202
+    if((   s->out_sample_fmt < AV_SAMPLE_FMT_FLT
203
+        || s->int_sample_fmt < AV_SAMPLE_FMT_FLT) && maxcoef > 1.0){
204
+        for(i=0; i<SWR_CH_MAX; i++)
205
+            for(j=0; j<SWR_CH_MAX; j++)
206
+                s->matrix[i][j] /= maxcoef;
207
+    }
208
+        for(i=0; i<av_get_channel_layout_nb_channels(s->out_ch_layout); i++){
209
+            for(j=0; j<av_get_channel_layout_nb_channels(s->in_ch_layout); j++){
210
+                av_log(NULL, AV_LOG_ERROR, "%f ", s->matrix[i][j]);
211
+            }
212
+            av_log(NULL, AV_LOG_ERROR, "\n");
213
+        }
214
+    return 0;
215
+}
216
+
217
+int swr_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
218
+    int out_i, in_i, i, j;
219
+
220
+av_assert0(out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
221
+av_assert0(in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
222
+
223
+    for(out_i=0; out_i<out->ch_count; out_i++){
224
+        switch(s->matrix_ch[out_i][0]){
225
+        case 1:
226
+            in_i= s->matrix_ch[out_i][1];
227
+            if(mustcopy || s->matrix[out_i][in_i]!=1.0){
228
+                if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){
229
+                    copy_float(out->ch[out_i], in->ch[in_i], s->matrix[out_i][in_i], len);
230
+                }else
231
+                    copy_s16  (out->ch[out_i], in->ch[in_i], s->matrix[out_i][in_i], len);
232
+            }else{
233
+                out->ch[out_i]= in->ch[in_i];
234
+            }
235
+            break;
236
+        case 2:
237
+            if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){
238
+                sum2_float(out->ch[out_i], in->ch[ s->matrix_ch[out_i][1] ],           in->ch[ s->matrix_ch[out_i][2] ],
239
+                                 s->matrix[out_i][ s->matrix_ch[out_i][1] ], s->matrix[out_i][ s->matrix_ch[out_i][2] ],
240
+                           len);
241
+            }else{
242
+                sum2_s16  (out->ch[out_i], in->ch[ s->matrix_ch[out_i][1] ],           in->ch[ s->matrix_ch[out_i][2] ],
243
+                                 s->matrix[out_i][ s->matrix_ch[out_i][1] ], s->matrix[out_i][ s->matrix_ch[out_i][2] ],
244
+                           len);
245
+            }
246
+            break;
247
+        default:
248
+            if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){
249
+                for(i=0; i<len; i++){
250
+                    float v=0;
251
+                    for(j=0; j<s->matrix_ch[out_i][0]; j++){
252
+                        in_i= s->matrix_ch[out_i][1+j];
253
+                        v+= ((float*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
254
+                    }
255
+                    ((float*)out->ch[out_i])[i]= v;
256
+                }
257
+            }else{
258
+                for(i=0; i<len; i++){
259
+                    int v=0;
260
+                    for(j=0; j<s->matrix_ch[out_i][0]; j++){
261
+                        in_i= s->matrix_ch[out_i][1+j];
262
+                        v+= ((int16_t*)in->ch[in_i])[i] * s->matrix[out_i][in_i]; //FIXME use int16 coeffs
263
+                    }
264
+                    ((int16_t*)out->ch[out_i])[i]= v;
265
+                }
266
+            }
267
+        }
268
+    }
269
+    return 0;
270
+}
0 271
new file mode 100644
... ...
@@ -0,0 +1,38 @@
0
+/*
1
+ * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
2
+ *
3
+ * This file is part of libswresample
4
+ *
5
+ * libswresample is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * libswresample is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with libswresample; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+
21
+static void RENAME(sum2)(SAMPLE *out, const SAMPLE *in1, const SAMPLE *in2, float coeff1, float coeff2, int len){
22
+    int i;
23
+
24
+    for(i=0; i<len; i++)
25
+        out[i] = coeff1*in1[i] + coeff2*in2[i]; //FIXME better int16
26
+}
27
+
28
+static void RENAME(copy)(SAMPLE *out, const SAMPLE *in, float coeff, int len){
29
+    if(coeff == 1.0){
30
+        memcpy(out, in, sizeof(SAMPLE)*len);
31
+    }else{
32
+        int i;
33
+        for(i=0; i<len; i++)
34
+            out[i] = coeff*in[i]; //FIXME better int16
35
+    }
36
+}
37
+
0 38
new file mode 100644
... ...
@@ -0,0 +1,352 @@
0
+/*
1
+ * audio resampling
2
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * audio resampling
24
+ * @author Michael Niedermayer <michaelni@gmx.at>
25
+ */
26
+
27
+#include "libavutil/log.h"
28
+#include "swresample_internal.h"
29
+
30
+#ifndef CONFIG_RESAMPLE_HP
31
+#define FILTER_SHIFT 15
32
+
33
+#define FELEM int16_t
34
+#define FELEM2 int32_t
35
+#define FELEML int64_t
36
+#define FELEM_MAX INT16_MAX
37
+#define FELEM_MIN INT16_MIN
38
+#define WINDOW_TYPE 9
39
+#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE)
40
+#define FILTER_SHIFT 30
41
+
42
+#define FELEM int32_t
43
+#define FELEM2 int64_t
44
+#define FELEML int64_t
45
+#define FELEM_MAX INT32_MAX
46
+#define FELEM_MIN INT32_MIN
47
+#define WINDOW_TYPE 12
48
+#else
49
+#define FILTER_SHIFT 0
50
+
51
+#define FELEM double
52
+#define FELEM2 double
53
+#define FELEML double
54
+#define WINDOW_TYPE 24
55
+#endif
56
+
57
+
58
+typedef struct AVResampleContext{
59
+    const AVClass *av_class;
60
+    FELEM *filter_bank;
61
+    int filter_length;
62
+    int ideal_dst_incr;
63
+    int dst_incr;
64
+    int index;
65
+    int frac;
66
+    int src_incr;
67
+    int compensation_distance;
68
+    int phase_shift;
69
+    int phase_mask;
70
+    int linear;
71
+    double factor;
72
+}AVResampleContext;
73
+
74
+/**
75
+ * 0th order modified bessel function of the first kind.
76
+ */
77
+static double bessel(double x){
78
+    double v=1;
79
+    double lastv=0;
80
+    double t=1;
81
+    int i;
82
+    static const double inv[100]={
83
+ 1.0/( 1* 1), 1.0/( 2* 2), 1.0/( 3* 3), 1.0/( 4* 4), 1.0/( 5* 5), 1.0/( 6* 6), 1.0/( 7* 7), 1.0/( 8* 8), 1.0/( 9* 9), 1.0/(10*10),
84
+ 1.0/(11*11), 1.0/(12*12), 1.0/(13*13), 1.0/(14*14), 1.0/(15*15), 1.0/(16*16), 1.0/(17*17), 1.0/(18*18), 1.0/(19*19), 1.0/(20*20),
85
+ 1.0/(21*21), 1.0/(22*22), 1.0/(23*23), 1.0/(24*24), 1.0/(25*25), 1.0/(26*26), 1.0/(27*27), 1.0/(28*28), 1.0/(29*29), 1.0/(30*30),
86
+ 1.0/(31*31), 1.0/(32*32), 1.0/(33*33), 1.0/(34*34), 1.0/(35*35), 1.0/(36*36), 1.0/(37*37), 1.0/(38*38), 1.0/(39*39), 1.0/(40*40),
87
+ 1.0/(41*41), 1.0/(42*42), 1.0/(43*43), 1.0/(44*44), 1.0/(45*45), 1.0/(46*46), 1.0/(47*47), 1.0/(48*48), 1.0/(49*49), 1.0/(50*50),
88
+ 1.0/(51*51), 1.0/(52*52), 1.0/(53*53), 1.0/(54*54), 1.0/(55*55), 1.0/(56*56), 1.0/(57*57), 1.0/(58*58), 1.0/(59*59), 1.0/(60*60),
89
+ 1.0/(61*61), 1.0/(62*62), 1.0/(63*63), 1.0/(64*64), 1.0/(65*65), 1.0/(66*66), 1.0/(67*67), 1.0/(68*68), 1.0/(69*69), 1.0/(70*70),
90
+ 1.0/(71*71), 1.0/(72*72), 1.0/(73*73), 1.0/(74*74), 1.0/(75*75), 1.0/(76*76), 1.0/(77*77), 1.0/(78*78), 1.0/(79*79), 1.0/(80*80),
91
+ 1.0/(81*81), 1.0/(82*82), 1.0/(83*83), 1.0/(84*84), 1.0/(85*85), 1.0/(86*86), 1.0/(87*87), 1.0/(88*88), 1.0/(89*89), 1.0/(90*90),
92
+ 1.0/(91*91), 1.0/(92*92), 1.0/(93*93), 1.0/(94*94), 1.0/(95*95), 1.0/(96*96), 1.0/(97*97), 1.0/(98*98), 1.0/(99*99), 1.0/(10000)
93
+    };
94
+
95
+    x= x*x/4;
96
+    for(i=0; v != lastv; i++){
97
+        lastv=v;
98
+        t *= x*inv[i];
99
+        v += t;
100
+    }
101
+    return v;
102
+}
103
+
104
+/**
105
+ * builds a polyphase filterbank.
106
+ * @param factor resampling factor
107
+ * @param scale wanted sum of coefficients for each filter
108
+ * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16
109
+ * @return 0 on success, negative on error
110
+ */
111
+static int build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){
112
+    int ph, i;
113
+    double x, y, w;
114
+    double *tab = av_malloc(tap_count * sizeof(*tab));
115
+    const int center= (tap_count-1)/2;
116
+
117
+    if (!tab)
118
+        return AVERROR(ENOMEM);
119
+
120
+    /* if upsampling, only need to interpolate, no filter */
121
+    if (factor > 1.0)
122
+        factor = 1.0;
123
+
124
+    for(ph=0;ph<phase_count;ph++) {
125
+        double norm = 0;
126
+        for(i=0;i<tap_count;i++) {
127
+            x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
128
+            if (x == 0) y = 1.0;
129
+            else        y = sin(x) / x;
130
+            switch(type){
131
+            case 0:{
132
+                const float d= -0.5; //first order derivative = -0.5
133
+                x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
134
+                if(x<1.0) y= 1 - 3*x*x + 2*x*x*x + d*(            -x*x + x*x*x);
135
+                else      y=                       d*(-4 + 8*x - 5*x*x + x*x*x);
136
+                break;}
137
+            case 1:
138
+                w = 2.0*x / (factor*tap_count) + M_PI;
139
+                y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w);
140
+                break;
141
+            default:
142
+                w = 2.0*x / (factor*tap_count*M_PI);
143
+                y *= bessel(type*sqrt(FFMAX(1-w*w, 0)));
144
+                break;
145
+            }
146
+
147
+            tab[i] = y;
148
+            norm += y;
149
+        }
150
+
151
+        /* normalize so that an uniform color remains the same */
152
+        for(i=0;i<tap_count;i++) {
153
+#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
154
+            filter[ph * tap_count + i] = tab[i] / norm;
155
+#else
156
+            filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm), FELEM_MIN, FELEM_MAX);
157
+#endif
158
+        }
159
+    }
160
+#if 0
161
+    {
162
+#define LEN 1024
163
+        int j,k;
164
+        double sine[LEN + tap_count];
165
+        double filtered[LEN];
166
+        double maxff=-2, minff=2, maxsf=-2, minsf=2;
167
+        for(i=0; i<LEN; i++){
168
+            double ss=0, sf=0, ff=0;
169
+            for(j=0; j<LEN+tap_count; j++)
170
+                sine[j]= cos(i*j*M_PI/LEN);
171
+            for(j=0; j<LEN; j++){
172
+                double sum=0;
173
+                ph=0;
174
+                for(k=0; k<tap_count; k++)
175
+                    sum += filter[ph * tap_count + k] * sine[k+j];
176
+                filtered[j]= sum / (1<<FILTER_SHIFT);
177
+                ss+= sine[j + center] * sine[j + center];
178
+                ff+= filtered[j] * filtered[j];
179
+                sf+= sine[j + center] * filtered[j];
180
+            }
181
+            ss= sqrt(2*ss/LEN);
182
+            ff= sqrt(2*ff/LEN);
183
+            sf= 2*sf/LEN;
184
+            maxff= FFMAX(maxff, ff);
185
+            minff= FFMIN(minff, ff);
186
+            maxsf= FFMAX(maxsf, sf);
187
+            minsf= FFMIN(minsf, sf);
188
+            if(i%11==0){
189
+                av_log(NULL, AV_LOG_ERROR, "i:%4d ss:%f ff:%13.6e-%13.6e sf:%13.6e-%13.6e\n", i, ss, maxff, minff, maxsf, minsf);
190
+                minff=minsf= 2;
191
+                maxff=maxsf= -2;
192
+            }
193
+        }
194
+    }
195
+#endif
196
+
197
+    av_free(tab);
198
+    return 0;
199
+}
200
+
201
+AVResampleContext *swr_resample_init(AVResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff){
202
+    double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
203
+    int phase_count= 1<<phase_shift;
204
+
205
+    if(!c || c->phase_shift!=phase_shift || c->linear!=linear || c->factor != factor
206
+         || c->filter_length!=FFMAX((int)ceil(filter_size/factor), 1)){
207
+    c= av_mallocz(sizeof(AVResampleContext));
208
+    if (!c)
209
+        return NULL;
210
+
211
+    c->phase_shift= phase_shift;
212
+    c->phase_mask= phase_count-1;
213
+    c->linear= linear;
214
+    c->factor= factor;
215
+
216
+    c->filter_length= FFMAX((int)ceil(filter_size/factor), 1);
217
+    c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM));
218
+    if (!c->filter_bank)
219
+        goto error;
220
+    if (build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, WINDOW_TYPE))
221
+        goto error;
222
+    memcpy(&c->filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM));
223
+    c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1];
224
+    }
225
+
226
+    c->compensation_distance= 0;
227
+    c->src_incr= out_rate;
228
+    c->ideal_dst_incr= c->dst_incr= in_rate * phase_count;
229
+    c->index= -phase_count*((c->filter_length-1)/2);
230
+    c->frac= 0;
231
+
232
+    return c;
233
+error:
234
+    av_free(c->filter_bank);
235
+    av_free(c);
236
+    return NULL;
237
+}
238
+
239
+void swr_resample_free(AVResampleContext **c){
240
+    if(!*c)
241
+        return;
242
+    av_freep(&(*c)->filter_bank);
243
+    av_freep(c);
244
+}
245
+
246
+void swr_compensate(struct SwrContext *s, int sample_delta, int compensation_distance){
247
+    AVResampleContext *c= s->resample;
248
+//    sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr;
249
+    c->compensation_distance= compensation_distance;
250
+    c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance;
251
+}
252
+
253
+int swr_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){
254
+    int dst_index, i;
255
+    int index= c->index;
256
+    int frac= c->frac;
257
+    int dst_incr_frac= c->dst_incr % c->src_incr;
258
+    int dst_incr=      c->dst_incr / c->src_incr;
259
+    int compensation_distance= c->compensation_distance;
260
+
261
+  if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){
262
+        int64_t index2= ((int64_t)index)<<32;
263
+        int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr;
264
+        dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr);
265
+
266
+        for(dst_index=0; dst_index < dst_size; dst_index++){
267
+            dst[dst_index] = src[index2>>32];
268
+            index2 += incr;
269
+        }
270
+        frac += dst_index * dst_incr_frac;
271
+        index += dst_index * dst_incr;
272
+        index += frac / c->src_incr;
273
+        frac %= c->src_incr;
274
+  }else{
275
+    for(dst_index=0; dst_index < dst_size; dst_index++){
276
+        FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask);
277
+        int sample_index= index >> c->phase_shift;
278
+        FELEM2 val=0;
279
+
280
+        if(sample_index < 0){
281
+            for(i=0; i<c->filter_length; i++)
282
+                val += src[FFABS(sample_index + i) % src_size] * filter[i];
283
+        }else if(sample_index + c->filter_length > src_size){
284
+            break;
285
+        }else if(c->linear){
286
+            FELEM2 v2=0;
287
+            for(i=0; i<c->filter_length; i++){
288
+                val += src[sample_index + i] * (FELEM2)filter[i];
289
+                v2  += src[sample_index + i] * (FELEM2)filter[i + c->filter_length];
290
+            }
291
+            val+=(v2-val)*(FELEML)frac / c->src_incr;
292
+        }else{
293
+            for(i=0; i<c->filter_length; i++){
294
+                val += src[sample_index + i] * (FELEM2)filter[i];
295
+            }
296
+        }
297
+
298
+#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
299
+        dst[dst_index] = av_clip_int16(lrintf(val));
300
+#else
301
+        val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
302
+        dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val;
303
+#endif
304
+
305
+        frac += dst_incr_frac;
306
+        index += dst_incr;
307
+        if(frac >= c->src_incr){
308
+            frac -= c->src_incr;
309
+            index++;
310
+        }
311
+
312
+        if(dst_index + 1 == compensation_distance){
313
+            compensation_distance= 0;
314
+            dst_incr_frac= c->ideal_dst_incr % c->src_incr;
315
+            dst_incr=      c->ideal_dst_incr / c->src_incr;
316
+        }
317
+    }
318
+  }
319
+    *consumed= FFMAX(index, 0) >> c->phase_shift;
320
+    if(index>=0) index &= c->phase_mask;
321
+
322
+    if(compensation_distance){
323
+        compensation_distance -= dst_index;
324
+        assert(compensation_distance > 0);
325
+    }
326
+    if(update_ctx){
327
+        c->frac= frac;
328
+        c->index= index;
329
+        c->dst_incr= dst_incr_frac + c->src_incr*dst_incr;
330
+        c->compensation_distance= compensation_distance;
331
+    }
332
+#if 0
333
+    if(update_ctx && !c->compensation_distance){
334
+#undef rand
335
+        av_resample_compensate(c, rand() % (8000*2) - 8000, 8000*2);
336
+av_log(NULL, AV_LOG_DEBUG, "%d %d %d\n", c->dst_incr, c->ideal_dst_incr, c->compensation_distance);
337
+    }
338
+#endif
339
+
340
+    return dst_index;
341
+}
342
+
343
+int swr_multiple_resample(AVResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){
344
+    int i, ret= -1;
345
+
346
+    for(i=0; i<dst->ch_count; i++){
347
+        ret= swr_resample(c, dst->ch[i], src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count);
348
+    }
349
+
350
+    return ret;
351
+}
0 352
new file mode 100644
... ...
@@ -0,0 +1,432 @@
0
+/*
1
+ * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
2
+ *
3
+ * This file is part of libswresample
4
+ *
5
+ * libswresample is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * libswresample is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with libswresample; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "libavutil/opt.h"
21
+#include "swresample_internal.h"
22
+#include "audioconvert.h"
23
+#include "libavutil/avassert.h"
24
+
25
+#define  C30DB  M_SQRT2
26
+#define  C15DB  1.189207115
27
+#define C__0DB  1.0
28
+#define C_15DB  0.840896415
29
+#define C_30DB  M_SQRT1_2
30
+#define C_45DB  0.594603558
31
+#define C_60DB  0.5
32
+
33
+
34
+//TODO split options array out?
35
+#define OFFSET(x) offsetof(SwrContext,x)
36
+static const AVOption options[]={
37
+{"ich",  "input channel count", OFFSET( in.ch_count   ), FF_OPT_TYPE_INT, {.dbl=2}, 1, SWR_CH_MAX, 0},
38
+{"och", "output channel count", OFFSET(out.ch_count   ), FF_OPT_TYPE_INT, {.dbl=2}, 1, SWR_CH_MAX, 0},
39
+{"isr",  "input sample rate"  , OFFSET( in_sample_rate), FF_OPT_TYPE_INT, {.dbl=48000}, 1, INT_MAX, 0},
40
+{"osr", "output sample rate"  , OFFSET(out_sample_rate), FF_OPT_TYPE_INT, {.dbl=48000}, 1, INT_MAX, 0},
41
+{"ip" ,  "input planar"       , OFFSET( in.planar     ), FF_OPT_TYPE_INT, {.dbl=0},    0,       1, 0},
42
+{"op" , "output planar"       , OFFSET(out.planar     ), FF_OPT_TYPE_INT, {.dbl=0},    0,       1, 0},
43
+{"isf",  "input sample format", OFFSET( in_sample_fmt ), FF_OPT_TYPE_INT, {.dbl=AV_SAMPLE_FMT_S16}, 0, AV_SAMPLE_FMT_NB-1, 0},
44
+{"osf", "output sample format", OFFSET(out_sample_fmt ), FF_OPT_TYPE_INT, {.dbl=AV_SAMPLE_FMT_S16}, 0, AV_SAMPLE_FMT_NB-1, 0},
45
+{"tsf", "internal sample format", OFFSET(int_sample_fmt ), FF_OPT_TYPE_INT, {.dbl=AV_SAMPLE_FMT_NONE}, -1, AV_SAMPLE_FMT_FLT, 0},
46
+{"icl",  "input channel layout" , OFFSET( in_ch_layout), FF_OPT_TYPE_INT64, {.dbl=0}, 0, INT64_MAX, 0, "channel_layout"},
47
+{"ocl",  "output channel layout", OFFSET(out_ch_layout), FF_OPT_TYPE_INT64, {.dbl=0}, 0, INT64_MAX, 0, "channel_layout"},
48
+{"clev", "center mix level"     , OFFSET(clev)         , FF_OPT_TYPE_FLOAT, {.dbl=C_30DB}, 0, 4, 0},
49
+{"slev", "sourround mix level"  , OFFSET(slev)         , FF_OPT_TYPE_FLOAT, {.dbl=C_30DB}, 0, 4, 0},
50
+{"flags", NULL                  , OFFSET(flags)        , FF_OPT_TYPE_FLAGS, {.dbl=0}, 0,  UINT_MAX, 0, "flags"},
51
+{"res", "force resampling", 0, FF_OPT_TYPE_CONST, {.dbl=SWR_FLAG_RESAMPLE}, INT_MIN, INT_MAX, 0, "flags"},
52
+
53
+{0}
54
+};
55
+
56
+static const char* context_to_name(void* ptr) {
57
+    return "SWR";
58
+}
59
+
60
+static const AVClass av_class = { "SwrContext", context_to_name, options, LIBAVUTIL_VERSION_INT, OFFSET(log_level_offset), OFFSET(log_ctx) };
61
+
62
+static int resample(SwrContext *s, AudioData *out_param, int out_count,
63
+                             const AudioData * in_param, int in_count);
64
+
65
+SwrContext *swr_alloc(void){
66
+    SwrContext *s= av_mallocz(sizeof(SwrContext));
67
+    if(s){
68
+        s->av_class= &av_class;
69
+        av_opt_set_defaults2(s, 0, 0);
70
+    }
71
+    return s;
72
+}
73
+
74
+SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
75
+                       int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
76
+                       int log_offset, void *log_ctx){
77
+    if(!s) s= swr_alloc();
78
+    if(!s) return NULL;
79
+
80
+    s->log_level_offset= log_offset;
81
+    s->log_ctx= log_ctx;
82
+
83
+    av_set_int(s, "ocl", out_ch_layout);
84
+    av_set_int(s, "osf", out_sample_fmt);
85
+    av_set_int(s, "osr", out_sample_rate);
86
+    av_set_int(s, "icl", in_ch_layout);
87
+    av_set_int(s, "isf", in_sample_fmt);
88
+    av_set_int(s, "isr", in_sample_rate);
89
+
90
+    s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
91
+    s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
92
+    s->int_sample_fmt = AV_SAMPLE_FMT_S16;
93
+
94
+    return s;
95
+}
96
+
97
+
98
+static void free_temp(AudioData *a){
99
+    av_free(a->data);
100
+    memset(a, 0, sizeof(*a));
101
+}
102
+
103
+void swr_free(SwrContext **ss){
104
+    SwrContext *s= *ss;
105
+    if(s){
106
+        free_temp(&s->postin);
107
+        free_temp(&s->midbuf);
108
+        free_temp(&s->preout);
109
+        free_temp(&s->in_buffer);
110
+        swr_audio_convert_free(&s-> in_convert);
111
+        swr_audio_convert_free(&s->out_convert);
112
+        swr_resample_free(&s->resample);
113
+    }
114
+
115
+    av_freep(ss);
116
+}
117
+
118
+static int64_t guess_layout(int ch){
119
+    switch(ch){
120
+    case 1: return AV_CH_LAYOUT_MONO;
121
+    case 2: return AV_CH_LAYOUT_STEREO;
122
+    case 5: return AV_CH_LAYOUT_5POINT0;
123
+    case 6: return AV_CH_LAYOUT_5POINT1;
124
+    case 7: return AV_CH_LAYOUT_7POINT0;
125
+    case 8: return AV_CH_LAYOUT_7POINT1;
126
+    default: return 0;
127
+    }
128
+}
129
+
130
+int swr_init(SwrContext *s){
131
+    s->in_buffer_index= 0;
132
+    s->in_buffer_count= 0;
133
+    s->resample_in_constraint= 0;
134
+    free_temp(&s->postin);
135
+    free_temp(&s->midbuf);
136
+    free_temp(&s->preout);
137
+    free_temp(&s->in_buffer);
138
+    swr_audio_convert_free(&s-> in_convert);
139
+    swr_audio_convert_free(&s->out_convert);
140
+
141
+    //We assume AVOptions checked the various values and the defaults where allowed
142
+    if(   s->int_sample_fmt != AV_SAMPLE_FMT_S16
143
+        &&s->int_sample_fmt != AV_SAMPLE_FMT_FLT){
144
+        av_log(s, AV_LOG_ERROR, "Requested sample format %s is not supported internally, only float & S16 is supported\n", av_get_sample_fmt_name(s->int_sample_fmt));
145
+        return AVERROR(EINVAL);
146
+    }
147
+
148
+    //FIXME should we allow/support using FLT on material that doesnt need it ?
149
+    if(s->in_sample_fmt <= AV_SAMPLE_FMT_S16 || s->int_sample_fmt==AV_SAMPLE_FMT_S16){
150
+        s->int_sample_fmt= AV_SAMPLE_FMT_S16;
151
+    }else
152
+        s->int_sample_fmt= AV_SAMPLE_FMT_FLT;
153
+
154
+
155
+    if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){
156
+        s->resample = swr_resample_init(s->resample, s->out_sample_rate, s->in_sample_rate, 16, 10, 0, 0.8);
157
+    }else
158
+        swr_resample_free(&s->resample);
159
+    if(s->int_sample_fmt != AV_SAMPLE_FMT_S16 && s->resample){
160
+        av_log(s, AV_LOG_ERROR, "Resampling only supported with internal s16 currently\n"); //FIXME
161
+        return -1;
162
+    }
163
+
164
+    if(!s-> in_ch_layout)
165
+        s-> in_ch_layout= guess_layout(s->in.ch_count);
166
+    if(!s->out_ch_layout)
167
+        s->out_ch_layout= guess_layout(s->out.ch_count);
168
+
169
+    s->rematrix= s->out_ch_layout  !=s->in_ch_layout;
170
+
171
+#define RSC 1 //FIXME finetune
172
+    if(!s-> in.ch_count)
173
+        s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
174
+    if(!s->out.ch_count)
175
+        s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
176
+
177
+av_assert0(s-> in.ch_count);
178
+av_assert0(s->out.ch_count);
179
+    s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0;
180
+
181
+    s-> in.bps= av_get_bits_per_sample_fmt(s-> in_sample_fmt)/8;
182
+    s->int_bps= av_get_bits_per_sample_fmt(s->int_sample_fmt)/8;
183
+    s->out.bps= av_get_bits_per_sample_fmt(s->out_sample_fmt)/8;
184
+
185
+    s->in_convert = swr_audio_convert_alloc(s->int_sample_fmt,
186
+                                            s-> in_sample_fmt, s-> in.ch_count, 0);
187
+    s->out_convert= swr_audio_convert_alloc(s->out_sample_fmt,
188
+                                            s->int_sample_fmt, s->out.ch_count, 0);
189
+
190
+
191
+    s->postin= s->in;
192
+    s->preout= s->out;
193
+    s->midbuf= s->in;
194
+    s->in_buffer= s->in;
195
+    if(!s->resample_first){
196
+        s->midbuf.ch_count= s->out.ch_count;
197
+        s->in_buffer.ch_count = s->out.ch_count;
198
+    }
199
+
200
+    s->in_buffer.bps = s->postin.bps = s->midbuf.bps = s->preout.bps =  s->int_bps;
201
+    s->in_buffer.planar = s->postin.planar = s->midbuf.planar = s->preout.planar =  1;
202
+
203
+
204
+    if(s->rematrix && swr_rematrix_init(s)<0)
205
+        return -1;
206
+
207
+    return 0;
208
+}
209
+
210
+static int realloc_audio(AudioData *a, int count){
211
+    int i, countb;
212
+    AudioData old;
213
+
214
+    if(a->count >= count)
215
+        return 0;
216
+
217
+    count*=2;
218
+
219
+    countb= FFALIGN(count*a->bps, 32);
220
+    old= *a;
221
+
222
+    av_assert0(a->planar);
223
+    av_assert0(a->bps);
224
+    av_assert0(a->ch_count);
225
+
226
+    a->data= av_malloc(countb*a->ch_count);
227
+    if(!a->data)
228
+        return AVERROR(ENOMEM);
229
+    for(i=0; i<a->ch_count; i++){
230
+        a->ch[i]= a->data + i*(a->planar ? countb : a->bps);
231
+        if(a->planar) memcpy(a->ch[i], old.ch[i], a->count*a->bps);
232
+    }
233
+    av_free(old.data);
234
+    a->count= count;
235
+
236
+    return 1;
237
+}
238
+
239
+static void copy(AudioData *out, AudioData *in,
240
+                 int count){
241
+    av_assert0(out->planar == in->planar);
242
+    av_assert0(out->bps == in->bps);
243
+    av_assert0(out->ch_count == in->ch_count);
244
+    if(out->planar){
245
+        int ch;
246
+        for(ch=0; ch<out->ch_count; ch++)
247
+            memcpy(out->ch[ch], in->ch[ch], count*out->bps);
248
+    }else
249
+        memcpy(out->ch[0], in->ch[0], count*out->ch_count*out->bps);
250
+}
251
+
252
+int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count,
253
+                         const uint8_t *in_arg [SWR_CH_MAX], int  in_count){
254
+    AudioData *postin, *midbuf, *preout;
255
+    int ret, i/*, in_max*/;
256
+    AudioData * in= &s->in;
257
+    AudioData *out= &s->out;
258
+    AudioData preout_tmp, midbuf_tmp;
259
+
260
+    if(!s->resample){
261
+        if(in_count > out_count)
262
+            return -1;
263
+        out_count = in_count;
264
+    }
265
+
266
+    av_assert0(in ->planar == 0);
267
+    av_assert0(out->planar == 0);
268
+    for(i=0; i<s-> in.ch_count; i++)
269
+        in ->ch[i]=  in_arg[0] + i* in->bps;
270
+    for(i=0; i<s->out.ch_count; i++)
271
+        out->ch[i]= out_arg[0] + i*out->bps;
272
+
273
+//     in_max= out_count*(int64_t)s->in_sample_rate / s->out_sample_rate + resample_filter_taps;
274
+//     in_count= FFMIN(in_count, in_in + 2 - s->hist_buffer_count);
275
+
276
+    if((ret=realloc_audio(&s->postin, in_count))<0)
277
+        return ret;
278
+    if(s->resample_first){
279
+        av_assert0(s->midbuf.ch_count ==  s-> in.ch_count);
280
+        if((ret=realloc_audio(&s->midbuf, out_count))<0)
281
+            return ret;
282
+    }else{
283
+        av_assert0(s->midbuf.ch_count ==  s->out.ch_count);
284
+        if((ret=realloc_audio(&s->midbuf,  in_count))<0)
285
+            return ret;
286
+    }
287
+    if((ret=realloc_audio(&s->preout, out_count))<0)
288
+        return ret;
289
+
290
+    postin= &s->postin;
291
+
292
+    midbuf_tmp= s->midbuf;
293
+    midbuf= &midbuf_tmp;
294
+    preout_tmp= s->preout;
295
+    preout= &preout_tmp;
296
+
297
+    if(s->int_sample_fmt == s-> in_sample_fmt && s->in.planar)
298
+        postin= in;
299
+
300
+    if(s->resample_first ? !s->resample : !s->rematrix)
301
+        midbuf= postin;
302
+
303
+    if(s->resample_first ? !s->rematrix : !s->resample)
304
+        preout= midbuf;
305
+
306
+    if(s->int_sample_fmt == s->out_sample_fmt && s->out.planar){
307
+        if(preout==in){
308
+            out_count= FFMIN(out_count, in_count); //TODO check at teh end if this is needed or redundant
309
+            av_assert0(s->in.planar); //we only support planar internally so it has to be, we support copying non planar though
310
+            copy(out, in, out_count);
311
+            return out_count;
312
+        }
313
+        else if(preout==postin) preout= midbuf= postin= out;
314
+        else if(preout==midbuf) preout= midbuf= out;
315
+        else                    preout= out;
316
+    }
317
+
318
+    if(in != postin){
319
+        swr_audio_convert(s->in_convert, postin, in, in_count);
320
+    }
321
+
322
+    if(s->resample_first){
323
+        if(postin != midbuf)
324
+            out_count= resample(s, midbuf, out_count, postin, in_count);
325
+        if(midbuf != preout)
326
+            swr_rematrix(s, preout, midbuf, out_count, preout==out);
327
+    }else{
328
+        if(postin != midbuf)
329
+            swr_rematrix(s, midbuf, postin, in_count, midbuf==out);
330
+        if(midbuf != preout)
331
+            out_count= resample(s, preout, out_count, midbuf, in_count);
332
+    }
333
+
334
+    if(preout != out){
335
+//FIXME packed doesnt need more than 1 chan here!
336
+        swr_audio_convert(s->out_convert, out, preout, out_count);
337
+    }
338
+    return out_count;
339
+}
340
+
341
+/**
342
+ *
343
+ * out may be equal in.
344
+ */
345
+static void buf_set(AudioData *out, AudioData *in, int count){
346
+    if(in->planar){
347
+        int ch;
348
+        for(ch=0; ch<out->ch_count; ch++)
349
+            out->ch[ch]= in->ch[ch] + count*out->bps;
350
+    }else
351
+        out->ch[0]= in->ch[0] + count*out->ch_count*out->bps;
352
+}
353
+
354
+/**
355
+ *
356
+ * @return number of samples output per channel
357
+ */
358
+static int resample(SwrContext *s, AudioData *out_param, int out_count,
359
+                             const AudioData * in_param, int in_count){
360
+    AudioData in, out, tmp;
361
+    int ret_sum=0;
362
+    int border=0;
363
+    int ch_count= s->resample_first ? s->in.ch_count : s->out.ch_count;
364
+
365
+    tmp=out=*out_param;
366
+    in =  *in_param;
367
+
368
+    do{
369
+        int ret, size, consumed;
370
+        if(!s->resample_in_constraint && s->in_buffer_count){
371
+            buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
372
+            ret= swr_multiple_resample(s->resample, &out, out_count, &tmp, s->in_buffer_count, &consumed);
373
+            out_count -= ret;
374
+            ret_sum += ret;
375
+            buf_set(&out, &out, ret);
376
+            s->in_buffer_count -= consumed;
377
+            s->in_buffer_index += consumed;
378
+
379
+            if(!in_count)
380
+                break;
381
+            if(s->in_buffer_count <= border){
382
+                buf_set(&in, &in, -s->in_buffer_count);
383
+                in_count += s->in_buffer_count;
384
+                s->in_buffer_count=0;
385
+                s->in_buffer_index=0;
386
+                border = 0;
387
+            }
388
+        }
389
+
390
+        if(in_count && !s->in_buffer_count){
391
+            s->in_buffer_index=0;
392
+            ret= swr_multiple_resample(s->resample, &out, out_count, &in, in_count, &consumed);
393
+            out_count -= ret;
394
+            ret_sum += ret;
395
+            buf_set(&out, &out, ret);
396
+            in_count -= consumed;
397
+            buf_set(&in, &in, consumed);
398
+        }
399
+
400
+        //TODO is this check sane considering the advanced copy avoidance below
401
+        size= s->in_buffer_index + s->in_buffer_count + in_count;
402
+        if(   size > s->in_buffer.count
403
+           && s->in_buffer_count + in_count <= s->in_buffer_index){
404
+            buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
405
+            copy(&s->in_buffer, &tmp, s->in_buffer_count);
406
+            s->in_buffer_index=0;
407
+        }else
408
+            if((ret=realloc_audio(&s->in_buffer, size)) < 0)
409
+                return ret;
410
+
411
+        if(in_count){
412
+            int count= in_count;
413
+            if(s->in_buffer_count && s->in_buffer_count+2 < count && out_count) count= s->in_buffer_count+2;
414
+
415
+            buf_set(&tmp, &s->in_buffer, s->in_buffer_index + s->in_buffer_count);
416
+            copy(&tmp, &in, /*in_*/count);
417
+            s->in_buffer_count += count;
418
+            in_count -= count;
419
+            border += count;
420
+            buf_set(&in, &in, count);
421
+            s->resample_in_constraint= 0;
422
+            if(s->in_buffer_count != count || in_count)
423
+                continue;
424
+        }
425
+        break;
426
+    }while(1);
427
+
428
+    s->resample_in_constraint= !!out_count;
429
+
430
+    return ret_sum;
431
+}
0 432
new file mode 100644
... ...
@@ -0,0 +1,79 @@
0
+/*
1
+ * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
2
+ *
3
+ * This file is part of libswresample
4
+ *
5
+ * libswresample is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * libswresample is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with libswresample; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#ifndef SWR_H
21
+#define SWR_H
22
+
23
+#include <inttypes.h>
24
+#include "libavutil/samplefmt.h"
25
+
26
+#define LIBSWRESAMPLE_VERSION_MAJOR 0
27
+#define LIBSWRESAMPLE_VERSION_MINOR 0
28
+#define LIBSWRESAMPLE_VERSION_MICRO 0
29
+
30
+#define SWR_CH_MAX 16
31
+
32
+#define SWR_FLAG_RESAMPLE 1///< Force resampling even if equal sample rate
33
+//TODO use int resample ?
34
+//long term TODO can we enable this dynamically?
35
+
36
+
37
+struct SwrContext;
38
+
39
+/**
40
+ * Allocate SwrContext.
41
+ * @see swr_init(),swr_free()
42
+ * @return NULL on error
43
+ */
44
+struct SwrContext *swr_alloc(void);
45
+
46
+/**
47
+ * Initialize context after user parameters have been set.
48
+ * @return negativo n error
49
+ */
50
+int swr_init(struct SwrContext *s);
51
+
52
+/**
53
+ * Allocate SwrContext.
54
+ * @see swr_init(),swr_free()
55
+ * @return NULL on error
56
+ */
57
+struct SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
58
+                              int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
59
+                              int log_offset, void *log_ctx);
60
+
61
+/**
62
+ * Free the given SwrContext.
63
+ * And set the pointer to NULL
64
+ */
65
+void swr_free(struct SwrContext **s);
66
+
67
+/**
68
+ * Convert audio.
69
+ * @param  in_count Number of input samples available in one channel.
70
+ * @param out_count Amount of space available for output in samples per channel.
71
+ * @return number of samples output per channel
72
+ */
73
+int swr_convert(struct SwrContext *s, uint8_t *out[SWR_CH_MAX], int out_count,
74
+                                const uint8_t *in [SWR_CH_MAX], int in_count);
75
+
76
+void swr_compensate(struct SwrContext *s, int sample_delta, int compensation_distance);
77
+
78
+#endif
0 79
new file mode 100644
... ...
@@ -0,0 +1,77 @@
0
+/*
1
+ * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
2
+ *
3
+ * This file is part of libswresample
4
+ *
5
+ * libswresample is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * libswresample is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with libswresample; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#ifndef SWR_INTERNAL_H
21
+#define SWR_INTERNAL_H
22
+
23
+#include "swresample.h"
24
+
25
+typedef struct AudioData{
26
+    uint8_t *ch[SWR_CH_MAX];
27
+    uint8_t *data;
28
+    int ch_count;
29
+    int bps;
30
+    int count;
31
+    int planar;
32
+} AudioData;
33
+
34
+typedef struct SwrContext {          //FIXME find unused fields
35
+    AVClass *av_class;
36
+    int log_level_offset;
37
+    void *log_ctx;
38
+    enum AVSampleFormat  in_sample_fmt;
39
+    enum AVSampleFormat int_sample_fmt; ///<AV_SAMPLE_FMT_FLT OR AV_SAMPLE_FMT_S16
40
+    enum AVSampleFormat out_sample_fmt;
41
+    int64_t  in_ch_layout;
42
+    int64_t out_ch_layout;
43
+    int      in_sample_rate;
44
+    int     out_sample_rate;
45
+    int flags;
46
+    float slev, clev;
47
+
48
+    //below are private
49
+    int int_bps;
50
+    int resample_first;
51
+    int rematrix;                   ///< flag to indicate if rematrixing is used
52
+
53
+    AudioData in, postin, midbuf, preout, out, in_buffer;
54
+    int in_buffer_index;
55
+    int in_buffer_count;
56
+    int resample_in_constraint;
57
+
58
+    struct AVAudioConvert *in_convert;
59
+    struct AVAudioConvert *out_convert;
60
+    struct AVResampleContext *resample;
61
+
62
+    float matrix[SWR_CH_MAX][SWR_CH_MAX];
63
+    uint8_t matrix_ch[SWR_CH_MAX][SWR_CH_MAX+1];
64
+
65
+    //TODO callbacks for asm optims
66
+}SwrContext;
67
+
68
+struct AVResampleContext *swr_resample_init(struct AVResampleContext *, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff);
69
+void swr_resample_free(struct AVResampleContext **c);
70
+int swr_multiple_resample(struct AVResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed);
71
+void swr_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance);
72
+int swr_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx);
73
+
74
+int swr_rematrix_init(SwrContext *s);
75
+int swr_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy);
76
+#endif
0 77
new file mode 100644
... ...
@@ -0,0 +1,149 @@
0
+/*
1
+ * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
2
+ *
3
+ * This file is part of libswresample
4
+ *
5
+ * libswresample is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation; either version 2 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * libswresample is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with libswresample; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "libavutil/avassert.h"
21
+#include "libavutil/common.h"
22
+#include "libavutil/audioconvert.h"
23
+#include "swresample.h"
24
+#undef fprintf
25
+
26
+#define SAMPLES 1000
27
+
28
+#define ASSERT_LEVEL 2
29
+
30
+static double get(const void *p, int index, enum AVSampleFormat f){
31
+    switch(f){
32
+    case AV_SAMPLE_FMT_U8 : return ((const uint8_t*)p)[index]/255.0*2-1.0;
33
+    case AV_SAMPLE_FMT_S16: return ((const int16_t*)p)[index]/32767.0;
34
+    case AV_SAMPLE_FMT_S32: return ((const int32_t*)p)[index]/2147483647.0;
35
+    case AV_SAMPLE_FMT_FLT: return ((const float  *)p)[index];
36
+    case AV_SAMPLE_FMT_DBL: return ((const double *)p)[index];
37
+    default: av_assert2(0);
38
+    }
39
+}
40
+
41
+static void  set(void *p, int index, enum AVSampleFormat f, double v){
42
+    switch(f){
43
+    case AV_SAMPLE_FMT_U8 : ((uint8_t*)p)[index]= (v+1.0)*255.0/2; break;
44
+    case AV_SAMPLE_FMT_S16: ((int16_t*)p)[index]= v*32767;         break;
45
+    case AV_SAMPLE_FMT_S32: ((int32_t*)p)[index]= v*2147483647;    break;
46
+    case AV_SAMPLE_FMT_FLT: ((float  *)p)[index]= v;               break;
47
+    case AV_SAMPLE_FMT_DBL: ((double *)p)[index]= v;               break;
48
+    default: av_assert2(0);
49
+    }
50
+}
51
+
52
+uint64_t layouts[]={
53
+AV_CH_LAYOUT_MONO                    ,
54
+AV_CH_LAYOUT_STEREO                  ,
55
+AV_CH_LAYOUT_2_1                     ,
56
+AV_CH_LAYOUT_SURROUND                ,
57
+AV_CH_LAYOUT_4POINT0                 ,
58
+AV_CH_LAYOUT_2_2                     ,
59
+AV_CH_LAYOUT_QUAD                    ,
60
+AV_CH_LAYOUT_5POINT0                 ,
61
+AV_CH_LAYOUT_5POINT1                 ,
62
+AV_CH_LAYOUT_5POINT0_BACK            ,
63
+AV_CH_LAYOUT_5POINT1_BACK            ,
64
+AV_CH_LAYOUT_7POINT0                 ,
65
+AV_CH_LAYOUT_7POINT1                 ,
66
+AV_CH_LAYOUT_7POINT1_WIDE            ,
67
+0
68
+};
69
+
70
+int main(int argc, char **argv){
71
+    int in_sample_rate, out_sample_rate, ch ,i, in_ch_layout_index, out_ch_layout_index, osr;
72
+    uint64_t in_ch_layout, out_ch_layout;
73
+    enum AVSampleFormat in_sample_fmt, out_sample_fmt;
74
+    int sample_rates[]={8000,11025,16000,22050,32000};
75
+    uint8_t array_in[SAMPLES*8*8];
76
+    uint8_t array_mid[SAMPLES*8*8*3];
77
+    uint8_t array_out[SAMPLES*8*8+100];
78
+    struct SwrContext * forw_ctx= NULL;
79
+    struct SwrContext *backw_ctx= NULL;
80
+
81
+    in_sample_rate=16000;
82
+    for(osr=0; osr<5; osr++){
83
+        out_sample_rate= sample_rates[osr];
84
+        for(in_sample_fmt= AV_SAMPLE_FMT_U8; in_sample_fmt<=AV_SAMPLE_FMT_DBL; in_sample_fmt++){
85
+            for(out_sample_fmt= AV_SAMPLE_FMT_U8; out_sample_fmt<=AV_SAMPLE_FMT_DBL; out_sample_fmt++){
86
+                for(in_ch_layout_index=0; layouts[in_ch_layout_index]; in_ch_layout_index++){
87
+                    in_ch_layout= layouts[in_ch_layout_index];
88
+                    int in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout);
89
+                    for(out_ch_layout_index=0; layouts[out_ch_layout_index]; out_ch_layout_index++){
90
+                        int out_count, mid_count;
91
+                        out_ch_layout= layouts[out_ch_layout_index];
92
+                        int out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout);
93
+                        fprintf(stderr, "ch %d->%d, rate:%5d->%5d, fmt:%s->%s",
94
+                               in_ch_count, out_ch_count,
95
+                               in_sample_rate, out_sample_rate,
96
+                               av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));
97
+                        forw_ctx  = swr_alloc2(forw_ctx, out_ch_layout, out_sample_fmt, out_sample_rate,
98
+                                                                  in_ch_layout,  in_sample_fmt,  in_sample_rate, 0, 0);
99
+                        backw_ctx = swr_alloc2(backw_ctx,in_ch_layout,  in_sample_fmt,  in_sample_rate,
100
+                                                                 out_ch_layout, out_sample_fmt, out_sample_rate, 0, 0);
101
+                        if(swr_init( forw_ctx) < 0)
102
+                            fprintf(stderr, "swr_init(->) failed\n");
103
+                        if(swr_init(backw_ctx) < 0)
104
+                            fprintf(stderr, "swr_init(<-) failed\n");
105
+                        if(!forw_ctx)
106
+                            fprintf(stderr, "Failed to init forw_cts\n");
107
+                        if(!backw_ctx)
108
+                            fprintf(stderr, "Failed to init backw_ctx\n");
109
+                               //FIXME test planar
110
+                        for(ch=0; ch<in_ch_count; ch++){
111
+                            for(i=0; i<SAMPLES; i++)
112
+                                set(array_in, ch + i*in_ch_count, in_sample_fmt, sin(i*i*3/SAMPLES));
113
+                        }
114
+                        mid_count= swr_convert(forw_ctx, (      uint8_t*[]){array_mid}, 3*SAMPLES,
115
+                                                                (const uint8_t*[]){array_in }, SAMPLES);
116
+                        out_count= swr_convert(backw_ctx,(      uint8_t*[]){array_out}, 3*SAMPLES,
117
+                                                                (const uint8_t*[]){array_mid}, mid_count);
118
+                        for(ch=0; ch<in_ch_count; ch++){
119
+                            double sse, x, maxdiff=0;
120
+                            double sum_a= 0;
121
+                            double sum_b= 0;
122
+                            double sum_aa= 0;
123
+                            double sum_bb= 0;
124
+                            double sum_ab= 0;
125
+                            for(i=0; i<SAMPLES; i++){
126
+                                double a= get(array_in , ch + i*in_ch_count, in_sample_fmt);
127
+                                double b= get(array_out, ch + i*in_ch_count, in_sample_fmt);
128
+                                sum_a += a;
129
+                                sum_b += b;
130
+                                sum_aa+= a*a;
131
+                                sum_bb+= b*b;
132
+                                sum_ab+= a*b;
133
+                                maxdiff= FFMAX(maxdiff, FFABS(a-b));
134
+                            }
135
+                            x = sum_ab/sum_bb;
136
+                            sse= sum_aa + sum_bb*x*x - 2*x*sum_ab;
137
+
138
+                            fprintf(stderr, "[%f %f %f] len:%5d\n", sqrt(sse/SAMPLES), x, maxdiff, out_count);
139
+                        }
140
+                        fprintf(stderr, "\n");
141
+                    }
142
+                }
143
+            }
144
+        }
145
+    }
146
+
147
+    return 0;
148
+}
... ...
@@ -1,4 +1,4 @@
1
-fd090ddf05cc3401cc75c4a5ace1d05a *./tests/data/acodec/g726.wav
1
+a76fc937faac62c5de057cd69191732a *./tests/data/acodec/g726.wav
2 2
 24052 ./tests/data/acodec/g726.wav
3
-74abea06027375111eeac1b2f8c7d3af *./tests/data/g726.acodec.out.wav
4
-stddev: 8554.55 PSNR: 17.69 MAXDIFF:29353 bytes:    95984/  1058400
3
+124de13e6cb5af64ea8758aa49feb7fc *./tests/data/g726.acodec.out.wav
4
+stddev: 8554.23 PSNR: 17.69 MAXDIFF:29353 bytes:    95984/  1058400
... ...
@@ -66,7 +66,7 @@ stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
66 66
 529256 ./tests/data/acodec/pcm_zork.wav
67 67
 864c8c866ac25642c29a13b122c70709 *./tests/data/pcm.acodec.out.wav
68 68
 stddev:  633.11 PSNR: 40.30 MAXDIFF:32768 bytes:  1058400/  1058400
69
-8168a5c1343553ef027541830f2cb879 *./tests/data/acodec/pcm_s24daud.302
69
+1b75d5198ae789ab3c48f7024e08f4a9 *./tests/data/acodec/pcm_s24daud.302
70 70
 10368730 ./tests/data/acodec/pcm_s24daud.302
71
-f552afadfdfcd6348a07095da6382de5 *./tests/data/pcm.acodec.out.wav
72
-stddev: 9416.28 PSNR: 16.85 MAXDIFF:42744 bytes:  6911796/  1058400
71
+4708f86529c594e29404603c64bb208c *./tests/data/pcm.acodec.out.wav
72
+stddev: 8967.92 PSNR: 17.28 MAXDIFF:42548 bytes:  6911796/  1058400
... ...
@@ -1,3 +1,3 @@
1
-188f804bd2d10cd436c8a7b111bdcd2a *./tests/data/lavf/lavf.dv
1
+6e716216d5f9e3819db8eb8796de9129 *./tests/data/lavf/lavf.dv
2 2
 3600000 ./tests/data/lavf/lavf.dv
3
-./tests/data/lavf/lavf.dv CRC=0x02c0af30
3
+./tests/data/lavf/lavf.dv CRC=0x92d1e3f0
... ...
@@ -1,3 +1,3 @@
1
-b3174e2db508564c1cce0b5e3c1bc1bd *./tests/data/lavf/lavf.mxf_d10
1
+8eb67301f72f2b5860fafab422b920ad *./tests/data/lavf/lavf.mxf_d10
2 2
 5330989 ./tests/data/lavf/lavf.mxf_d10
3
-./tests/data/lavf/lavf.mxf_d10 CRC=0xc3f4f92e
3
+./tests/data/lavf/lavf.mxf_d10 CRC=0x96c02dfd