123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- #include "main.h"
- #include "decoder.h"
- #include <math.h>
- #include <locale.h>
- #pragma warning(disable:4244)
- #include "shaper.h"
- #include "api__in_vorbis.h"
- Decoder::~Decoder() {if (shaper) delete shaper;}
- extern CfgInt
- cfg_mc6_dm, cfg_mc6_map;
- /*
- if (vorbis_cfg.use_hq_preamp)
- {
- sample *= pow(10., preamp_db/20);
-
- //hard 6dB limiting
- if (sample < -0.5)
- sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
- else if (sample > 0.5)
- sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
- } */
- #if 0
- static float q_tanh(float x)
- {
- double foo1, foo2;
- foo1 = pow(2.71828182845904523536028747135266, x);
- foo2 = 1.0 / foo1;
- return (foo1 -foo2) / (foo1 + foo2);
- }
- #else
- #define q_tanh tanh
- #endif
- float VorbisFile::GetGain()
- {
- float peak;
- vorbis_comment * c;
- float scale = 1.0f;
- c = ov_comment(&vf, -1);
- peak = 0.99f;
- if (c)
- {
- if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain", false))
- {
- char * _peak = 0, *_gain = 0;
- float gain = 0;
- bool have_rg = 0;
- float lwing_gain = 0;
- char *gain1 = 0, *gain2 = 0, *peak1 = 0, *peak2 = 0;
- gain1 = vorbis_comment_query(c, "replaygain_album_gain", 0);
- if (!gain1) gain1 = vorbis_comment_query(c, "rg_audiophile", 0);
- gain2 = vorbis_comment_query(c, "replaygain_track_gain", 0);
- if (!gain2) gain2 = vorbis_comment_query(c, "rg_radio", 0);
- peak1 = vorbis_comment_query(c, "replaygain_album_peak", 0);
- peak2 = vorbis_comment_query(c, "replaygain_track_peak", 0);
- switch (AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"replaygain_source", 0))
- {
- case 0: // track
- _gain = gain2;
- if (!_gain && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
- _gain = gain1;
- _peak = peak2;
- if (!_peak && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
- _peak = peak1;
- break;
- case 1: // album
- _gain = gain1;
- if (!_gain && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
- _gain = gain2;
- _peak = peak1;
- if (!_peak && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
- _peak = peak2;
- break;
- }
- if (!_peak)
- {
- _peak = vorbis_comment_query(c, "rg_peak", 0);
- }
- _locale_t C_locale = WASABI_API_LNG->Get_C_NumericLocale();
- if (_peak) peak = _atof_l(_peak, C_locale);
- if (_gain) gain = _atof_l(_gain, C_locale);
- if (!_peak && !_gain)
- {
- char * l = vorbis_comment_query(c, "lwing_gain", 0);
- if (l)
- {
- lwing_gain = _atof_l(l, C_locale);
- have_rg = 1;
- }
- }
- else have_rg = 1;
- if (!have_rg)
- {
- gain = AGAVE_API_CONFIG->GetFloat(playbackConfigGroupGUID, L"non_replaygain", -6.0f);
- }
- scale = powf(10, (gain) / 20.0f);
- if (lwing_gain)
- scale *= lwing_gain;
- else if (have_rg)
- switch (AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"replaygain_mode", 1))
- {
- case 1: // apply gain, but don't clip
- if (scale*peak > 1.0) scale = 1.0 / peak;
- break;
- case 2: // normalize
- scale = 1.0 / peak;
- break;
- case 3: // no clipping
- if (peak > 1.0f)
- scale = 1.0 / peak;
- break;
- }
- }
- }
- return scale;
- }
- void Decoder::process_rg()
- {
- scale = file->GetGain();
- }
- void Decoder::setup_mc()
- {
- if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"mono", false))
- nch = 1;
- else if (src_nch == 6)
- {
- switch (cfg_mc6_dm)
- {
- case 2:
- nch = 4;
- break;
- case 3:
- case 4:
- nch = 2;
- break;
- case 5:
- nch = 1;
- break;
- }
- if (nch > 2 && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"surround", true))
- nch = 2;
- }
- }
- void Decoder::Flush()
- {
- bptr = 0;
- pcmbuf = 0;
- data = 0;
- pos = 0;
- if (shaper) {delete shaper;shaper = 0;}
- }
- void Decoder::Init(VorbisFile * f, UINT _bits, UINT _nch, bool _useFloat, bool allowRG)
- {
- useFloat = _useFloat;
- file = f;
- vorbis_info * i = ov_info(&file->vf, -1);
- if (allowRG)
- process_rg();
- else
- scale = 1.0f;
- if (useFloat)
- {
- dither = false;
- bps = 32;
- }
- else
- {
- dither = AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"dither", true);
- if (_bits)
- bps = _bits;
- else
- bps = AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"bits", 16);
- }
- if (useFloat)
- {
- clipmin = -10000; // some arbitrarily large number
- clipmax = 10000; // some arbitrarily large number
- }
- else
- {
- clipmin = - (1 << (bps - 1));
- clipmax = (1 << (bps - 1)) - 1;
- }
- sr = i->rate;
- nch = src_nch = i->channels;
- Flush();
- cur_link = file->vf.current_link;
- if (_nch)
- nch = _nch;
- else
- setup_mc();
- }
- UINT Decoder::DataAvailable()
- {
- return data * (bps >> 3);
- }
- int Decoder::DoFrame()
- {
- need_reopen = 0;
- while (1)
- {
- data = ov_read_float(&file->vf, &pcmbuf, 576, 0);
- if ((int)data <= 0)
- {
- if (data == OV_HOLE) {continue;}
- data = 0;
- return 0;
- }
- break;
- }
- pos = 0;
- if (cur_link != file->vf.current_link)
- {
- vorbis_info* i = ov_info(&file->vf, -1);
- if (sr != (UINT)i->rate || src_nch != (UINT)i->channels)
- {
- UINT old_nch = nch, old_sr = sr;
- if (shaper) {delete shaper;shaper = 0;}
- sr = i->rate;
- src_nch = nch = i->channels;
- setup_mc();
- if (nch != old_nch || sr != old_sr)
- {
- need_reopen = 1;
- }
- }
- process_rg();
- cur_link = file->vf.current_link;
- }
- data *= nch;
- return 1;
- }
- int Decoder::Read(UINT bytes, void * buf)
- {
- UINT wr = 0;
- if (buf && bytes && data > 0)
- {
- char* out = (char*)buf;
- UINT d;
- double mul;
- int ofs;
- float * img;
- d = bytes / (bps >> 3);
- if (d > data) d = data;
- if (!d) return 0;
- data -= d;
- if (useFloat)
- {
- mul = 1.0;
- ofs = 0;
- }
- else
- {
- mul = (double)( (1 << ((bps) - 1)) - 1 );
- ofs = (bps == 8) ? 0x80 : 0;
- }
- wr += d * (bps >> 3);
- img = (float*)alloca(sizeof(float) * nch);
- do
- {
- UINT cur_ch;
- if (nch == 1 && src_nch > 0)
- {
- UINT c;
- img[0] = 0;
- for (c = 0;c < src_nch;c++)
- {
- img[0] += pcmbuf[c][pos];
- }
- img[0] /= (float)src_nch;
- }
- else if (nch == src_nch && !(nch == 6 && cfg_mc6_dm == 1))
- {
- UINT c;
- for (c = 0;c < nch;c++)
- {
- img[c] = pcmbuf[c][pos];
- }
- }
- else if (src_nch == 6)
- {
- UINT FL, FR, C;
- if (cfg_mc6_map == 1)
- {
- FL = 0;
- FR = 1;
- C = 2;
- }
- else
- {
- FL = 0;
- C = 1;
- FR = 2;
- }
- if (nch == 6)
- { //remap order for correct 5.1 output
- img[0] = pcmbuf[FL][pos];
- img[1] = pcmbuf[FR][pos];
- img[2] = pcmbuf[C][pos];
- img[3] = pcmbuf[5][pos];
- img[4] = pcmbuf[3][pos];
- img[5] = pcmbuf[4][pos];
- }
- else if (nch == 2)
- {
- /*
- FL FR C BL BR LFE
- 0 1 2 3 4 5
-
- L,C,R,SL,SR,LFE
- 0 1 2 3 4 5
-
-
- output:
- FL FR C LFE BL BR
-
-
- stereo:
- Lt=L+0.707*(V-SL-SR+LFE)
- Rt=R+0.707*(C+SL+SR+LFE)
-
-
- Lt=L+0.707*(C+LFE)
- Rt=R+0.707*(C+LFE)
- SLt=SL
- SRt=SR
-
- */
- if (cfg_mc6_dm == 4) //ds2
- {
- const double a = pow(10., 1.5 / 20.), b = 1 / a;
- img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] - a * pcmbuf[3][pos] - b * pcmbuf[4][pos] + pcmbuf[5][pos]);
- img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + b * pcmbuf[3][pos] + a * pcmbuf[4][pos] + pcmbuf[5][pos]);
- }
- else
- {
- img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] - pcmbuf[3][pos] - pcmbuf[4][pos] + pcmbuf[5][pos]);
- img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[3][pos] + pcmbuf[4][pos] + pcmbuf[5][pos]);
- }
- }
- else if (nch == 4)
- {
- img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[5][pos]);
- img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[5][pos]);
- img[2] = pcmbuf[3][pos];
- img[3] = pcmbuf[4][pos];
- }
- }
- for (cur_ch = 0;cur_ch < nch;cur_ch++)
- {
- float v = img[cur_ch];
- int val;
- v *= scale;
- v *= mul;
- if (dither)
- {
- if (!shaper)
- {
- //Shaper(int freq,int _nch,int min,int max,int _dtype,int pdf,double noiseamp);
- shaper = new Shaper(sr, nch, clipmin, clipmax, 2, DITHER_TRIANGLE, 0);
- }
- // double peak=0;
- val = shaper->do_shaping(v /*,&peak*/, cur_ch);
- //shaper clips for us
- }
- else
- {
- val = (int)v;
- if (val < clipmin) val = clipmin;
- else if (val > clipmax) val = clipmax;
- //1<<16 = 0x10000
- }
- val += ofs;
- switch (bps)
- {
- case 8:
- *(BYTE*)out = (UINT)val;
- break;
- case 16:
- *(short*)out = val;
- break;
- case 24:
- {
- ((BYTE*)out)[0] = (UINT)val;
- ((BYTE*)out)[1] = (UINT)val >> 8;
- ((BYTE*)out)[2] = (UINT)val >> 16;
- }
- break;
- case 32:
- if (useFloat)
- {
- *(float *)out = v;
- }
- else
- {
- //*(long*)out=val;
- //break;
- *(long*)out = 0;
- }
- break;
- };
- out += (bps >> 3);
- d--;
- }
- pos++;
- }
- while (d);
- }
- return wr;
- }
- int VorbisFile::Seek(double p) { return ov_time_seek(&vf, p);}
- int Decoder::Seek(double p)
- {
- Flush();
- return file->Seek(p);
- }
- //char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count)
- const char* VorbisFile::get_meta(const char* tag, UINT c)
- {
- return vorbis_comment_query(vf.seekable ? vf.vc + vf.current_link : vf.vc, (char*)tag, c);
- }
|