00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <cstdio>
00021 #include <cstdlib>
00022 #include <cerrno>
00023 #include <cmath>
00024
00025 #include <iostream>
00026 #include <sstream>
00027 #include <vector>
00028 #include <list>
00029 #include <map>
00030 using namespace std;
00031
00032 #include "compat.h"
00033 #include "mythlogging.h"
00034 #include "freesurround.h"
00035 #include "el_processor.h"
00036
00037 #include <QString>
00038 #include <QDateTime>
00039
00040
00041 static const unsigned default_block_size = SURROUND_BUFSIZE;
00042
00043 static const float center_level = 0.707107;
00044 static const float m3db = 0.7071067811865476f;
00045
00046 unsigned int block_size = default_block_size;
00047
00048
00049 template<class T> T pop_back(std::list<T> &l)
00050 {
00051 T result(l.back());
00052 l.pop_back();
00053 return result;
00054 }
00055
00056
00057
00058 class object_pool
00059 {
00060 public:
00061 typedef void* (*callback)();
00062
00063 object_pool(callback cbf):construct(cbf) { }
00064 ~object_pool()
00065 {
00066 for (std::map<void*,void*>::iterator i=pool.begin(),e=pool.end();
00067 i != e; i++)
00068 delete i->second;
00069 for (std::list<void*>::iterator i=freelist.begin(),e=freelist.end();
00070 i != e; i++)
00071 delete *i;
00072 }
00073
00074 void *acquire(void *who)
00075 {
00076 std::map<void*,void*>::iterator i(pool.find(who));
00077 if (i != pool.end())
00078 return i->second;
00079 else
00080 if (!freelist.empty())
00081 return pool.insert(std::make_pair(who,pop_back(freelist)))
00082 .first->second;
00083 else
00084 return pool.insert(std::make_pair(who,construct()))
00085 .first->second;
00086 }
00087
00088 void release(void *who)
00089 {
00090 std::map<void*,void*>::iterator i(pool.find(who));
00091 if (i != pool.end()) {
00092 freelist.push_back(i->second);
00093 pool.erase(i);
00094 }
00095 }
00096 public:
00097 callback construct;
00098 std::list<void*> freelist;
00099 std::map<void*,void*> pool;
00100 };
00101
00102
00103 struct buffers
00104 {
00105 buffers(unsigned int s):
00106 l(s),r(s),c(s),ls(s),rs(s),lfe(s), rls(s), rrs(s) { }
00107 void resize(unsigned int s)
00108 {
00109 l.resize(s); r.resize(s); lfe.resize(s);
00110 ls.resize(s); rs.resize(s); c.resize(s);
00111 rls.resize(s); rrs.resize(s);
00112 }
00113 void clear()
00114 {
00115 l.clear(); r.clear(); lfe.clear();
00116 ls.clear(); rs.clear(); c.clear();
00117 rls.clear(); rrs.clear();
00118 }
00119 std::vector<float> l,r,c,ls,rs,lfe,cs,lcs,rcs,
00120 rls, rrs;
00121 };
00122
00123
00124 void *new_decoder() { return new fsurround_decoder(block_size); }
00125 void *new_buffers() { return new buffers(block_size/2); }
00126
00127 object_pool dp(&new_decoder);
00128 object_pool bp(&new_buffers);
00129
00130
00131 #ifdef SPEAKERTEST
00132 int channel_select = -1;
00133 #endif
00134
00135 FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) :
00136 srate(srate),
00137 open_(false),
00138 initialized_(false),
00139 bufs(NULL),
00140 decoder(0),
00141 in_count(0),
00142 out_count(0),
00143 processed(true),
00144 processed_size(0),
00145 surround_mode(smode),
00146 latency_frames(0)
00147 {
00148 LOG(VB_AUDIO, LOG_DEBUG,
00149 QString("FreeSurround::FreeSurround rate %1 moviemode %2")
00150 .arg(srate).arg(moviemode));
00151
00152 if (moviemode)
00153 {
00154 params.phasemode = 1;
00155 params.center_width = 25;
00156 params.dimension = 0.5;
00157 }
00158 else
00159 {
00160 params.center_width = 65;
00161 params.dimension = 0.3;
00162 }
00163 switch (surround_mode)
00164 {
00165 case SurroundModeActiveSimple:
00166 params.steering = 0;
00167 break;
00168 case SurroundModeActiveLinear:
00169 params.steering = 1;
00170 latency_frames = block_size/2;
00171 break;
00172 default:
00173 break;
00174 }
00175
00176 bufs = (buffers*)bp.acquire((void*)1);
00177 open();
00178 #ifdef SPEAKERTEST
00179 channel_select++;
00180 if (channel_select>=6)
00181 channel_select = 0;
00182 LOG(VB_AUDIO, LOG_DEBUG,
00183 QString("FreeSurround::FreeSurround channel_select %1")
00184 .arg(channel_select));
00185 #endif
00186 LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::FreeSurround done"));
00187 }
00188
00189 void FreeSurround::SetParams()
00190 {
00191 if (decoder)
00192 {
00193 decoder->steering_mode(params.steering);
00194 decoder->phase_mode(params.phasemode);
00195 decoder->surround_coefficients(params.coeff_a, params.coeff_b);
00196 decoder->separation(params.front_sep/100.0,params.rear_sep/100.0);
00197 }
00198 }
00199
00200 FreeSurround::fsurround_params::fsurround_params(int32_t center_width,
00201 int32_t dimension) :
00202 center_width(center_width),
00203 dimension(dimension),
00204 coeff_a(0.8165),coeff_b(0.5774),
00205 phasemode(0),
00206 steering(1),
00207 front_sep(100),
00208 rear_sep(100)
00209 {
00210 }
00211
00212 FreeSurround::~FreeSurround()
00213 {
00214 LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround"));
00215 close();
00216 if (bufs)
00217 {
00218 bp.release((void*)1);
00219 bufs = NULL;
00220 }
00221 LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround done"));
00222 }
00223
00224 uint FreeSurround::putFrames(void* buffer, uint numFrames, uint numChannels)
00225 {
00226 int i = 0;
00227 int ic = in_count;
00228 int bs = block_size/2;
00229 bool process = true;
00230 float *samples = (float *)buffer;
00231
00232
00233 float **inputs = decoder->getInputBuffers();
00234 float *lt = &inputs[0][ic];
00235 float *rt = &inputs[1][ic];
00236
00237 if ((surround_mode != SurroundModePassive) && (ic+numFrames > bs))
00238 {
00239 numFrames = bs - ic;
00240 }
00241
00242 switch (numChannels)
00243 {
00244 case 1:
00245 switch (surround_mode)
00246 {
00247 case SurroundModePassive:
00248 for (i = 0; i < numFrames && ic < bs; i++,ic++)
00249 bufs->l[ic] = bufs->c[ic] = bufs->r[ic] = samples[i];
00250 process = false;
00251 break;
00252 default:
00253 for (i=0; i<numFrames; i++)
00254 *lt++ = *rt++ = *samples++;
00255 process = true;
00256 break;
00257 }
00258 channels = 6;
00259 break;
00260
00261 case 2:
00262 switch (surround_mode)
00263 {
00264 case SurroundModePassive:
00265 for (i = 0; i < numFrames && ic < bs; i++,ic++)
00266 {
00267 float lt = *samples++;
00268 float rt = *samples++;
00269 bufs->l[ic] = lt;
00270 bufs->lfe[ic] = bufs->c[ic] = (lt+rt) * center_level;
00271 bufs->r[ic] = rt;
00272 bufs->ls[ic] = bufs->rs[ic] = (lt-rt) * center_level;
00273 }
00274 process = false;
00275 break;
00276 default:
00277 for (i=0; i<numFrames; i++)
00278 {
00279 *lt++ = *samples++;
00280 *rt++ = *samples++;
00281 }
00282 process = true;
00283 break;
00284 }
00285 channels = 6;
00286 break;
00287
00288 case 5:
00289 for (i = 0; i < numFrames && ic < bs; i++,ic++)
00290 {
00291 float lt = *samples++;
00292 float rt = *samples++;
00293 float c = *samples++;
00294 float ls = *samples++;
00295 float rs = *samples++;
00296 bufs->l[ic] = lt;
00297 bufs->lfe[ic] = 0.0f;
00298 bufs->c[ic] = c;
00299 bufs->r[ic] = rt;
00300 bufs->ls[ic] = ls;
00301 bufs->rs[ic] = rs;
00302 }
00303 process = false;
00304 channels = 6;
00305 break;
00306
00307 case 7:
00308 for (i = 0; i < numFrames && ic < bs; i++,ic++)
00309 {
00310
00311 float lt = *samples++;
00312 float rt = *samples++;
00313 float c = *samples++;
00314 float lfe = *samples++;
00315 float cs = *samples++;
00316 float ls = *samples++;
00317 float rs = *samples++;
00318 bufs->l[ic] = lt;
00319 bufs->lfe[ic] = lfe;
00320 bufs->c[ic] = c;
00321 bufs->r[ic] = rt;
00322 bufs->ls[ic] = ls;
00323 bufs->rs[ic] = rs;
00324 bufs->rls[ic] = bufs->rrs[ic] = cs * m3db;
00325 }
00326 process = false;
00327 channels = 8;
00328 break;
00329 default:
00330 break;
00331 }
00332 if (process)
00333 {
00334 ic += numFrames;
00335 if (ic != bs)
00336 {
00337
00338
00339 in_count = ic;
00340 }
00341 else
00342 {
00343 processed = process;
00344
00345
00346 process_block();
00347 in_count = 0;
00348 out_count = bs;
00349 processed_size = bs;
00350 latency_frames = block_size/2;
00351 }
00352 }
00353 else
00354 {
00355 in_count = 0;
00356 out_count = processed_size = ic;
00357 processed = false;
00358 latency_frames = 0;
00359 }
00360
00361 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
00362 QString("FreeSurround::putFrames %1 #ch %2 used %3 generated %4")
00363 .arg(numFrames).arg(numChannels).arg(i).arg(out_count));
00364
00365 return i;
00366 }
00367
00368 uint FreeSurround::receiveFrames(void *buffer, uint maxFrames)
00369 {
00370 uint i;
00371 uint oc = out_count;
00372 if (maxFrames > oc) maxFrames = oc;
00373 uint outindex = processed_size - oc;
00374 float *output = (float *)buffer;
00375 if (channels == 8)
00376 {
00377 float *l = &bufs->l[outindex];
00378 float *c = &bufs->c[outindex];
00379 float *r = &bufs->r[outindex];
00380 float *ls = &bufs->ls[outindex];
00381 float *rs = &bufs->rs[outindex];
00382 float *lfe = &bufs->lfe[outindex];
00383 float *rls = &bufs->rls[outindex];
00384 float *rrs = &bufs->rrs[outindex];
00385 for (i = 0; i < maxFrames; i++)
00386 {
00387
00388
00389
00390
00391 *output++ = *l++;
00392 *output++ = *r++;
00393 *output++ = *c++;
00394 *output++ = *lfe++;
00395 *output++ = *rls++;
00396 *output++ = *rrs++;
00397 *output++ = *ls++;
00398 *output++ = *rs++;
00399 }
00400 oc -= maxFrames;
00401 outindex += maxFrames;
00402 }
00403 else
00404 {
00405 if (processed)
00406 {
00407 float** outputs = decoder->getOutputBuffers();
00408 float *l = &outputs[0][outindex];
00409 float *c = &outputs[1][outindex];
00410 float *r = &outputs[2][outindex];
00411 float *ls = &outputs[3][outindex];
00412 float *rs = &outputs[4][outindex];
00413 float *lfe = &outputs[5][outindex];
00414 for (i = 0; i < maxFrames; i++)
00415 {
00416 *output++ = *l++;
00417 *output++ = *r++;
00418 *output++ = *c++;
00419 *output++ = *lfe++;
00420 *output++ = *ls++;
00421 *output++ = *rs++;
00422 }
00423 oc -= maxFrames;
00424 outindex += maxFrames;
00425 }
00426 else
00427 {
00428 float *l = &bufs->l[outindex];
00429 float *c = &bufs->c[outindex];
00430 float *r = &bufs->r[outindex];
00431 float *ls = &bufs->ls[outindex];
00432 float *rs = &bufs->rs[outindex];
00433 float *lfe = &bufs->lfe[outindex];
00434 for (i = 0; i < maxFrames; i++)
00435 {
00436 *output++ = *l++;
00437 *output++ = *r++;
00438 *output++ = *c++;
00439 *output++ = *lfe++;
00440 *output++ = *ls++;
00441 *output++ = *rs++;
00442 }
00443 oc -= maxFrames;
00444 outindex += maxFrames;
00445 }
00446 }
00447 out_count = oc;
00448 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
00449 QString("FreeSurround::receiveFrames %1").arg(maxFrames));
00450 return maxFrames;
00451 }
00452
00453 void FreeSurround::process_block()
00454 {
00455
00456 try
00457 {
00458 if (decoder)
00459 {
00460 decoder->decode(params.center_width/100.0,params.dimension/100.0);
00461 }
00462 }
00463 catch(...)
00464 {
00465 }
00466 }
00467
00468 long long FreeSurround::getLatency()
00469 {
00470
00471 if (latency_frames == 0)
00472 return 0;
00473 return decoder ? ((latency_frames + in_count)*1000000)/(2*srate) : 0;
00474 }
00475
00476 void FreeSurround::flush()
00477 {
00478 if (decoder)
00479 decoder->flush();
00480 bufs->clear();
00481 }
00482
00483
00484 void FreeSurround::open()
00485 {
00486 if (!decoder)
00487 {
00488 decoder = (fsurround_decoder*)dp.acquire((void*)1);
00489 decoder->flush();
00490 if (bufs)
00491 bufs->clear();
00492 decoder->sample_rate(srate);
00493 }
00494 SetParams();
00495 }
00496
00497 void FreeSurround::close()
00498 {
00499 if (decoder)
00500 {
00501 dp.release(this);
00502 decoder = 0;
00503 }
00504 }
00505
00506 uint FreeSurround::numUnprocessedFrames()
00507 {
00508 return in_count;
00509 }
00510
00511 uint FreeSurround::numFrames()
00512 {
00513 return out_count;
00514 }
00515
00516 uint FreeSurround::frameLatency()
00517 {
00518 if (processed)
00519 return in_count + out_count + (block_size/2);
00520 else
00521 return in_count + out_count;
00522 }
00523
00524 uint FreeSurround::framesPerBlock()
00525 {
00526 return block_size/2;
00527 }
00528