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