Mercurial > mplayer.hg
comparison libao2/pl_surround.c @ 3485:439b0b1d50b9
include 7kHz lowpass filter for surround channels, as per Dolby recommendation
author | steve |
---|---|
date | Thu, 13 Dec 2001 23:37:27 +0000 |
parents | cfc10bc948c4 |
children | cc1c879533ee |
comparison
equal
deleted
inserted
replaced
3484:72e299c83b4f | 3485:439b0b1d50b9 |
---|---|
33 #include "audio_out.h" | 33 #include "audio_out.h" |
34 #include "audio_plugin.h" | 34 #include "audio_plugin.h" |
35 #include "audio_plugin_internal.h" | 35 #include "audio_plugin_internal.h" |
36 #include "afmt.h" | 36 #include "afmt.h" |
37 | 37 |
38 #include "remez.h" | |
39 #include "firfilter.c" | |
40 | |
38 static ao_info_t info = | 41 static ao_info_t info = |
39 { | 42 { |
40 "Surround decoder plugin", | 43 "Surround decoder plugin", |
41 "surround", | 44 "surround", |
42 "Steve Davies <steve@daviesfam.org>", | 45 "Steve Davies <steve@daviesfam.org>", |
49 typedef struct pl_surround_s | 52 typedef struct pl_surround_s |
50 { | 53 { |
51 int passthrough; // Just be a "NO-OP" | 54 int passthrough; // Just be a "NO-OP" |
52 int msecs; // Rear channel delay in milliseconds | 55 int msecs; // Rear channel delay in milliseconds |
53 int16_t* databuf; // Output audio buffer | 56 int16_t* databuf; // Output audio buffer |
54 int16_t* delaybuf; // circular buffer to be used for delaying Ls and Rs audio | 57 int16_t* Ls_delaybuf; // circular buffer to be used for delaying Ls audio |
55 int delaybuf_len; // local buffer length in samples | 58 int16_t* Rs_delaybuf; // circular buffer to be used for delaying Rs audio |
56 int delaybuf_ptr; // offset in buffer where we are reading/writing | 59 int delaybuf_len; // delaybuf buffer length in samples |
60 int delaybuf_pos; // offset in buffer where we are reading/writing | |
61 double* filter_coefs_surround; // FIR filter coefficients for surround sound 7kHz lowpass | |
57 int rate; // input data rate | 62 int rate; // input data rate |
58 int format; // input format | 63 int format; // input format |
59 int input_channels; // input channels | 64 int input_channels; // input channels |
60 | 65 |
61 } pl_surround_t; | 66 } pl_surround_t; |
62 | 67 |
63 static pl_surround_t pl_surround={0,15,NULL,NULL,0,0,0,0,0}; | 68 static pl_surround_t pl_surround={0,15,NULL,NULL,NULL,0,0,NULL,0,0,0}; |
64 | 69 |
65 // to set/get/query special features/parameters | 70 // to set/get/query special features/parameters |
66 static int control(int cmd,int arg){ | 71 static int control(int cmd,int arg){ |
67 switch(cmd){ | 72 switch(cmd){ |
68 case AOCONTROL_PLUGIN_SET_LEN: | 73 case AOCONTROL_PLUGIN_SET_LEN: |
71 //fprintf(stderr, "pl_surround: ao_plugin_data.len=%d\n", ao_plugin_data.len); | 76 //fprintf(stderr, "pl_surround: ao_plugin_data.len=%d\n", ao_plugin_data.len); |
72 // Allocate an output buffer | 77 // Allocate an output buffer |
73 if (pl_surround.databuf != NULL) { | 78 if (pl_surround.databuf != NULL) { |
74 free(pl_surround.databuf); pl_surround.databuf = NULL; | 79 free(pl_surround.databuf); pl_surround.databuf = NULL; |
75 } | 80 } |
81 // Allocate output buffer | |
76 pl_surround.databuf = calloc(ao_plugin_data.len, 1); | 82 pl_surround.databuf = calloc(ao_plugin_data.len, 1); |
77 // Return back smaller len so we don't get overflowed... (??seems the right thing to do?) | 83 // Return back smaller len so we don't get overflowed... |
78 ao_plugin_data.len /= 2; | 84 ao_plugin_data.len /= 2; |
79 return CONTROL_OK; | 85 return CONTROL_OK; |
80 } | 86 } |
81 return -1; | 87 return -1; |
82 } | 88 } |
106 | 112 |
107 // Input 2 channels, output will be 4 - tell ao_plugin | 113 // Input 2 channels, output will be 4 - tell ao_plugin |
108 ao_plugin_data.channels = 4; | 114 ao_plugin_data.channels = 4; |
109 ao_plugin_data.sz_mult /= 2; | 115 ao_plugin_data.sz_mult /= 2; |
110 | 116 |
111 // Figure out buffer space needed for the 15msec delay | 117 // Figure out buffer space (in int16_ts) needed for the 15msec delay |
112 pl_surround.delaybuf_len = 2 * (pl_surround.rate * pl_surround.msecs / 1000); | 118 pl_surround.delaybuf_len = (pl_surround.rate * pl_surround.msecs / 1000); |
113 // Allocate delay buffer | 119 // Allocate delay buffers |
114 pl_surround.delaybuf=(void*)calloc(pl_surround.delaybuf_len,sizeof(int16_t)); | 120 pl_surround.Ls_delaybuf=(void*)calloc(pl_surround.delaybuf_len,sizeof(int16_t)); |
115 fprintf(stderr, "pl_surround: %dmsec surround delay, rate %d - buffer is %d bytes\n", | 121 pl_surround.Rs_delaybuf=(void*)calloc(pl_surround.delaybuf_len,sizeof(int16_t)); |
122 fprintf(stderr, "pl_surround: %dmsec surround delay, rate %d - buffers are %d bytes each\n", | |
116 pl_surround.msecs,pl_surround.rate, pl_surround.delaybuf_len*sizeof(int16_t)); | 123 pl_surround.msecs,pl_surround.rate, pl_surround.delaybuf_len*sizeof(int16_t)); |
117 pl_surround.delaybuf_ptr = 0; | 124 pl_surround.delaybuf_pos = 0; |
125 // Surround filer coefficients | |
126 pl_surround.filter_coefs_surround = calc_coefficients_7kHz_lowpass(pl_surround.rate); | |
118 | 127 |
119 return 1; | 128 return 1; |
120 } | 129 } |
121 | 130 |
122 // close plugin | 131 // close plugin |
123 static void uninit(){ | 132 static void uninit(){ |
124 // fprintf(stderr, "pl_surround: uninit called!\n"); | 133 // fprintf(stderr, "pl_surround: uninit called!\n"); |
125 if (pl_surround.passthrough) return; | 134 if (pl_surround.passthrough) return; |
126 if(pl_surround.delaybuf) | 135 if(pl_surround.Ls_delaybuf) |
127 free(pl_surround.delaybuf); | 136 free(pl_surround.Ls_delaybuf); |
137 if(pl_surround.Rs_delaybuf) | |
138 free(pl_surround.Rs_delaybuf); | |
128 if(pl_surround.databuf) | 139 if(pl_surround.databuf) |
129 free(pl_surround.databuf); | 140 free(pl_surround.databuf); |
130 pl_surround.delaybuf_len=0; | 141 pl_surround.delaybuf_len=0; |
131 } | 142 } |
132 | 143 |
133 // empty buffers | 144 // empty buffers |
134 static void reset() | 145 static void reset() |
135 { | 146 { |
136 if (pl_surround.passthrough) return; | 147 if (pl_surround.passthrough) return; |
137 //fprintf(stderr, "pl_surround: reset called\n"); | 148 //fprintf(stderr, "pl_surround: reset called\n"); |
138 pl_surround.delaybuf_ptr = 0; | 149 pl_surround.delaybuf_pos = 0; |
139 memset(pl_surround.delaybuf, 0, sizeof(int16_t)*pl_surround.delaybuf_len); | 150 memset(pl_surround.Ls_delaybuf, 0, sizeof(int16_t)*pl_surround.delaybuf_len); |
151 memset(pl_surround.Rs_delaybuf, 0, sizeof(int16_t)*pl_surround.delaybuf_len); | |
140 } | 152 } |
141 | 153 |
142 | 154 |
143 // processes 'ao_plugin_data.len' bytes of 'data' | 155 // processes 'ao_plugin_data.len' bytes of 'data' |
144 // called for every block of data | 156 // called for every block of data |
163 // (Lt-Rt) | 175 // (Lt-Rt) |
164 // But we are splitting the S to two output channels, so we | 176 // But we are splitting the S to two output channels, so we |
165 // must take 3dB off as we split it: | 177 // must take 3dB off as we split it: |
166 // Ls=Rs=.707*(Lt-Rt) | 178 // Ls=Rs=.707*(Lt-Rt) |
167 // Trouble is, Lt could be +32767, Rt -32768, so possibility that S will | 179 // Trouble is, Lt could be +32767, Rt -32768, so possibility that S will |
168 // clip. So to compensate, we cut L/R by 3dB (*.707), and S by 6dB (/2). | 180 // clip. So to avoid that, we cut L/R by 3dB (*.707), and S by 6dB (/2). |
169 | 181 |
170 // output front left and right | 182 // output front left and right |
171 out[0] = in[0]*.707; | 183 out[0] = in[0]*.707; |
172 out[1] = in[1]*.707; | 184 out[1] = in[1]*.707; |
173 // output Ls and Rs - from 15msec ago | 185 // output Ls and Rs - from 15msec ago, lowpass filtered @ 7kHz |
174 out[2] = pl_surround.delaybuf[pl_surround.delaybuf_ptr]; | 186 out[2] = firfilter(pl_surround.Ls_delaybuf, pl_surround.delaybuf_pos, |
175 out[3] = pl_surround.delaybuf[pl_surround.delaybuf_ptr+1]; | 187 pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); |
188 out[3] = - out[2]; | |
189 // out[3] = firfilter(pl_surround.Rs_delaybuf, pl_surround.delaybuf_pos, | |
190 // pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); | |
176 // calculate and save surround for 15msecs time | 191 // calculate and save surround for 15msecs time |
177 surround = (in[0]/2 - in[1]/2); | 192 surround = (in[0]/2 - in[1]/2); |
178 pl_surround.delaybuf[pl_surround.delaybuf_ptr++] = surround; | 193 pl_surround.Ls_delaybuf[pl_surround.delaybuf_pos] = surround; |
179 pl_surround.delaybuf[pl_surround.delaybuf_ptr++] = - surround; | 194 pl_surround.Rs_delaybuf[pl_surround.delaybuf_pos++] = - surround; |
180 pl_surround.delaybuf_ptr %= pl_surround.delaybuf_len; | 195 pl_surround.delaybuf_pos %= pl_surround.delaybuf_len; |
181 // next samples... | 196 // next samples... |
182 in = &in[pl_surround.input_channels]; out = &out[4]; | 197 in = &in[pl_surround.input_channels]; out = &out[4]; |
183 } | 198 } |
184 | 199 |
185 // Set output block/len | 200 // Set output block/len |