Subversion Repositories pentevo

Rev

Rev 883 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. #include "../std.h"
  2.  
  3. #include "../emul.h"
  4. #include "../vars.h"
  5.  
  6. /*
  7.    sound resampling core for Unreal Speccy project
  8.    created under public domain license by SMT, jan.2006
  9. */
  10.  
  11. #include "sndrender.h"
  12.  
  13. unsigned SNDRENDER::render(SNDOUT *src, unsigned srclen, unsigned clk_ticks, bufptr_t dst_start)
  14. {
  15.    start_frame(dst_start);
  16.    for (unsigned index = 0; index < srclen; index++)
  17.    {
  18.       // if (src[index].timestamp > clk_ticks) continue; // wrong input data leads to crash
  19.       update(src[index].timestamp, src[index].newvalue.ch.left, src[index].newvalue.ch.right);
  20.    }
  21.    return end_frame(clk_ticks);
  22. }
  23.  
  24. const unsigned TICK_F = (1<<TICK_FF);
  25.  
  26. // b = 1+ln2(max_sndtick) = 1+ln2((max_sndfq*TICK_F)/min_intfq) = 1+ln2(48000*64/10) ~= 19.2;
  27. // assert(b+MULT_C <= 32)
  28.  
  29.  
  30. void SNDRENDER::start_frame(bufptr_t dst_start)
  31. {
  32.    SNDRENDER::dst_start = dstpos = dst_start;
  33.    base_tick = tick;
  34.    firstsmp = 4; //Alone Coder
  35. }
  36.  
  37. void SNDRENDER::update(unsigned timestamp, unsigned l, unsigned r)
  38. {
  39.    if (!((l ^ mix_l) | (r ^ mix_r))) // (l == mix_l) && (r == mix_r)
  40.        return;
  41.  
  42. //[vv]   unsigned endtick = (timestamp * mult_const) >> MULT_C;
  43.    uint64_t endtick = (timestamp * (uint64_t)sample_rate * TICK_F) / clock_rate;
  44.    flush( (unsigned) (base_tick + endtick) );
  45.    mix_l = l; mix_r = r;
  46. }
  47.  
  48. unsigned SNDRENDER::end_frame(unsigned clk_ticks)
  49. {
  50.    // adjusting 'clk_ticks' with whole history will fix accumulation of rounding errors
  51.    //uint64_t endtick = ((passed_clk_ticks + clk_ticks) * mult_const) >> MULT_C;
  52.    uint64_t endtick = ((passed_clk_ticks + clk_ticks) * (uint64_t)sample_rate * TICK_F) / clock_rate;
  53.    flush( (unsigned) (endtick - passed_snd_ticks) );
  54.  
  55.    unsigned ready_samples = dstpos - dst_start;
  56.    #ifdef SND_EXTERNAL_BUFFER
  57.    if ((int)ready_samples < 0) ready_samples += SND_EXTERNAL_BUFFER_SIZE;
  58.    #endif
  59.  
  60.    oldfrmleft = ((long)useleft + (long)olduseleft)/2; //Alone Coder
  61.    oldfrmright = ((long)useright + (long)olduseright)/2; //Alone Coder
  62.  
  63.    tick -= (ready_samples << TICK_FF);
  64.    passed_snd_ticks += (ready_samples << TICK_FF);
  65.    passed_clk_ticks += clk_ticks;
  66.  
  67.    return ready_samples;
  68. }
  69.  
  70. /*
  71. unsigned SNDRENDER::end_empty_frame(unsigned clk_ticks)
  72. {
  73.    // adjusting 'clk_ticks' with whole history will fix accumulation of rounding errors
  74.    //uint64_t endtick = ((passed_clk_ticks + clk_ticks) * mult_const) >> MULT_C;
  75.    uint64_t endtick = ((passed_clk_ticks + clk_ticks) * (uint64_t)sample_rate * TICK_F) / clock_rate;
  76.    tick = (unsigned)(endtick-passed_snd_ticks); // flush(endtick-passed_snd_ticks);
  77.    // todo: change dstpos!
  78.  
  79.    unsigned ready_samples = dstpos - dst_start;
  80.    #ifdef SND_EXTERNAL_BUFFER
  81.    if ((int)ready_samples < 0) ready_samples += SND_EXTERNAL_BUFFER_SIZE;
  82.    #endif
  83.  
  84.    tick -= (ready_samples << TICK_FF);
  85.    passed_snd_ticks += (ready_samples << TICK_FF);
  86.    passed_clk_ticks += clk_ticks;
  87.  
  88.    return ready_samples;
  89. }
  90. */
  91.  
  92. void SNDRENDER::set_timings(unsigned clock_rate, unsigned sample_rate)
  93. {
  94.    SNDRENDER::clock_rate = clock_rate;
  95.    SNDRENDER::sample_rate = sample_rate;
  96.  
  97.    tick = 0; dstpos = dst_start = 0;
  98.    passed_snd_ticks = passed_clk_ticks = 0;
  99.  
  100. //   mult_const = (unsigned) (((uint64_t)sample_rate << (MULT_C+TICK_FF)) / clock_rate);
  101. }
  102.  
  103.  
  104. static unsigned filter_diff[TICK_F*2]; // discrete-time step response
  105. const double filter_sum_full = 1.0, filter_sum_half = 0.5;
  106. const unsigned filter_sum_full_u = (unsigned)(filter_sum_full * 0x10000),
  107.                filter_sum_half_u = (unsigned)(filter_sum_half * 0x10000);
  108.  
  109. void SNDRENDER::flush(unsigned endtick)
  110. {
  111.     unsigned scale;
  112.     if(!((endtick ^ tick) & ~(TICK_F - 1))) // (endtick / TICK_F) == (tick / TICK_F)
  113.     {   // ╬яЄшьшчрЎш , фхЎшьрЎш  эх эєцэр, Є.ъ. яюёых фхЎшьрЎшш tick ёютярфхЄ ё endtick
  114.         // ┬їюфэющ ёшуэры шчьхэшыё  с√ёЄЁхх ўхь юфшэ яхЁшюф Fs т√їюфэюую ёшуэрыр
  115.         // s1 - чэрўхэшх т√їюфэюую ёшуэрыр т ыхтюь єчых фхЎшьрЎшш
  116.         // s2 - чэрўхэшх т√їюфэюую ёшуэрыр т яЁртюь єчых фхЎшьрЎшш
  117.         // mix - чэрўхэшх тїюфэюую ёшуэрыр т шэЄхЁтрых [tick.. endtick)
  118.  
  119.         //same discrete as before
  120.         // ╧Ёртр  Єюўър т√ўшёыхээр  яю яхЁхїюфэющ їрЁръЄхЁшёЄшъх
  121.         scale = filter_diff[(endtick & (TICK_F - 1)) + TICK_F] - filter_diff[(tick & (TICK_F - 1)) + TICK_F];
  122.         s2_l += mix_l * scale;
  123.         s2_r += mix_r * scale;
  124.  
  125.         // ╦хтр  Єюўър т√ўшёыхээр  яю яхЁхїюфэющ їрЁръЄхЁшёЄшъх
  126.         scale = filter_diff[endtick & (TICK_F - 1)] - filter_diff[tick & (TICK_F - 1)];
  127.         s1_l += mix_l * scale;
  128.         s1_r += mix_r * scale;
  129.  
  130.         tick = endtick;
  131.         return;
  132.     }
  133.  
  134.     // ╬ЄЁхчюъ [TICK_F + (tick % TICK_F) ... 2*TICK_F-1]
  135.     scale = filter_sum_full_u - filter_diff[(tick & (TICK_F - 1)) + TICK_F]; // filter_sum_full_u = filter_diff[(TICK_F - 1) + TICK_F]
  136.  
  137.     unsigned sample_value;
  138.     if(conf.soundfilter)
  139.     {
  140.         /*lame noise reduction by Alone Coder*/
  141.         int templeft = int(mix_l * scale + s2_l);
  142.         /*olduseleft = useleft;
  143.         if (firstsmp)useleft=oldfrmleft,firstsmp--;
  144.             else*/ useleft = ((long)templeft + (long)oldleft) / 2;
  145.         oldleft = templeft;
  146.         int tempright = int(mix_r * scale + s2_r);
  147.         /*olduseright = useright;
  148.         if (firstsmp)useright=oldfrmright,firstsmp--;
  149.             else*/ useright = ((long)tempright + (long)oldright) / 2;
  150.         oldright = tempright;
  151.         sample_value = unsigned((useleft >> 16) + int(unsigned(useright) & 0xFFFF0000));
  152.         /**/
  153.     }
  154.     else
  155.     {
  156.         sample_value = ((mix_l*scale + s2_l) >> 16) +
  157.             ((mix_r*scale + s2_r) & 0xFFFF0000);
  158.     }
  159.  
  160. #ifdef SND_EXTERNAL_BUFFER
  161.     SND_EXTERNAL_BUFFER[dstpos].sample += sample_value;
  162.     dstpos = (dstpos + 1) & (SND_EXTERNAL_BUFFER_SIZE - 1);
  163. #else
  164.     dstpos->sample = sample_value;
  165.     dstpos++;
  166. #endif
  167.  
  168.     // ╬ЄЁхчюъ [tick % TICK_F ... TICK_F-1]
  169.     scale = filter_sum_half_u - filter_diff[tick & (TICK_F - 1)];// filter_sum_half_u = filter_diff[TICK_F - 1]
  170.     s2_l = s1_l + mix_l * scale;
  171.     s2_r = s1_r + mix_r * scale;
  172.  
  173.     // ┬√Ёртэштрэшх фю єчыр фхЎшьрЎшш
  174.     tick = (tick | (TICK_F - 1)) + 1;
  175.  
  176.     // ╓шъы фхЎшьрЎшш т TICK_F Ёрч, tick єцх т√Ёютэхэ фю ёхЄъш ё °руюь TICK_F
  177.     // endtick / TICK_F - endtick яюёых фхЎшьрЎшш т TICK_F Ёрч
  178.     // tick / TICK_F - tick яюёых фхЎшьрЎшш т TICK_F Ёрч
  179.     if((endtick ^ tick) & ~(TICK_F - 1)) // (endtick / TICK_F) != (tick / TICK_F)
  180.     { // ╬яЄшьшчрЎш , яЁютхЁър эр эхёютярфхэшх tick ш endtick яюёых фхЎшьрЎшш
  181.  
  182.        // assume filter_coeff is symmetric
  183.         // ╬ЄЁхчюъ [0 ... TICK_F-1]
  184.         unsigned val_l = mix_l * filter_sum_half_u;
  185.         unsigned val_r = mix_r * filter_sum_half_u;
  186.  
  187.         // ╓шъы фхЎшьрЎшш, [tick/TICK_F ... endtick/TICK_F)
  188.         do
  189.         {
  190.             if(conf.soundfilter)
  191.             {
  192.                 /*lame noise reduction by Alone Coder*/
  193.                 int templeft = int(s2_l + val_l);
  194.                 /*olduseleft = useleft;
  195.                 if (firstsmp)useleft=oldfrmleft,firstsmp--;
  196.                    else*/ useleft = ((long)templeft + (long)oldleft) / 2;
  197.                 oldleft = templeft;
  198.                 int tempright = int(s2_r + val_r);
  199.                 /*olduseright = useright;
  200.                 if (firstsmp)useright=oldfrmright,firstsmp--;
  201.                    else*/ useright = ((long)tempright + (long)oldright) / 2;
  202.                 oldright = tempright;
  203.                 sample_value = unsigned((useleft >> 16) + int(unsigned(useright) & 0xFFFF0000));
  204.                 /**/
  205.             }
  206.             else
  207.             {
  208.                 sample_value = ((s2_l + val_l) >> 16) +
  209.                     ((s2_r + val_r) & 0xFFFF0000); // save s2+val
  210.             }
  211.  
  212. #ifdef SND_EXTERNAL_BUFFER
  213.             SND_EXTERNAL_BUFFER[dstpos].sample += sample_value;
  214.             dstpos = (dstpos + 1) & (SND_EXTERNAL_BUFFER_SIZE - 1);
  215. #else
  216.             dstpos->sample = sample_value;
  217.             dstpos++;
  218. #endif
  219.  
  220.             tick += TICK_F;
  221.             s2_l = val_l;
  222.             s2_r = val_r; // s2=s1, s1=0;
  223.  
  224.         } while((endtick ^ tick) & ~(TICK_F - 1)); // (endtick / TICK_F) != (tick / TICK_F)
  225.     }
  226.  
  227.     tick = endtick;
  228.  
  229.     scale = filter_diff[(endtick & (TICK_F - 1)) + TICK_F] - filter_sum_half_u; // filter_sum_half_u = filter_diff[TICK_F - 1]
  230.     s2_l += mix_l * scale;
  231.     s2_r += mix_r * scale;
  232.  
  233.     scale = filter_diff[endtick & (TICK_F - 1)];
  234.     s1_l = mix_l * scale;
  235.     s1_r = mix_r * scale;
  236. }
  237.  
  238. // bw = 1*(10^-2)*pi rad/smp (-3dB)
  239. // bw = 2*(10^-2)*pi rad/smp (-10dB)
  240. // bw = 20 kHz (fs=44100 * 64 = 2822400)
  241. // matlab: fvtool(filter_coeff)
  242.  
  243. // ╧рЁрьхЄЁ√ ёшэЄхчр Їшы№ЄЁр:
  244. // matlab: (fdatool/filterDesigner)
  245. // FIR: Window (Hamming)
  246. // order: 127
  247. // Fs: 2822400
  248. // Fc: 11025
  249.  
  250. const double filter_coeff[TICK_F*2] =
  251. {
  252.    // filter designed with Matlab's DSP toolbox
  253.    0.000797243121022152, 0.000815206499600866, 0.000844792477531490, 0.000886460636664257,
  254.    0.000940630171246217, 0.001007677515787512, 0.001087934129054332, 0.001181684445143001,
  255.    0.001289164001921830, 0.001410557756409498, 0.001545998595893740, 0.001695566052785407,
  256.    0.001859285230354019, 0.002037125945605404, 0.002229002094643918, 0.002434771244914945,
  257.    0.002654234457752337, 0.002887136343664226, 0.003133165351783907, 0.003391954293894633,
  258.    0.003663081102412781, 0.003946069820687711, 0.004240391822953223, 0.004545467260249598,
  259.    0.004860666727631453, 0.005185313146989532, 0.005518683858848785, 0.005860012915564928,
  260.    0.006208493567431684, 0.006563280932335042, 0.006923494838753613, 0.007288222831108771,
  261.    0.007656523325719262, 0.008027428904915214, 0.008399949736219575, 0.008773077102914008,
  262.    0.009145787031773989, 0.009517044003286715, 0.009885804729257883, 0.010251021982371376,
  263.    0.010611648461991030, 0.010966640680287394, 0.011314962852635887, 0.011655590776166550,
  264.    0.011987515680350414, 0.012309748033583185, 0.012621321289873522, 0.012921295559959939,
  265.    0.013208761191466523, 0.013482842243062109, 0.013742699838008606, 0.013987535382970279,
  266.    0.014216593638504731, 0.014429165628265581, 0.014624591374614174, 0.014802262449059521,
  267.    0.014961624326719471, 0.015102178534818147, 0.015223484586101132, 0.015325161688957322,
  268.    0.015406890226980602, 0.015468413001680802, 0.015509536233058410, 0.015530130313785910,
  269.    0.015530130313785910, 0.015509536233058410, 0.015468413001680802, 0.015406890226980602,
  270.    0.015325161688957322, 0.015223484586101132, 0.015102178534818147, 0.014961624326719471,
  271.    0.014802262449059521, 0.014624591374614174, 0.014429165628265581, 0.014216593638504731,
  272.    0.013987535382970279, 0.013742699838008606, 0.013482842243062109, 0.013208761191466523,
  273.    0.012921295559959939, 0.012621321289873522, 0.012309748033583185, 0.011987515680350414,
  274.    0.011655590776166550, 0.011314962852635887, 0.010966640680287394, 0.010611648461991030,
  275.    0.010251021982371376, 0.009885804729257883, 0.009517044003286715, 0.009145787031773989,
  276.    0.008773077102914008, 0.008399949736219575, 0.008027428904915214, 0.007656523325719262,
  277.    0.007288222831108771, 0.006923494838753613, 0.006563280932335042, 0.006208493567431684,
  278.    0.005860012915564928, 0.005518683858848785, 0.005185313146989532, 0.004860666727631453,
  279.    0.004545467260249598, 0.004240391822953223, 0.003946069820687711, 0.003663081102412781,
  280.    0.003391954293894633, 0.003133165351783907, 0.002887136343664226, 0.002654234457752337,
  281.    0.002434771244914945, 0.002229002094643918, 0.002037125945605404, 0.001859285230354019,
  282.    0.001695566052785407, 0.001545998595893740, 0.001410557756409498, 0.001289164001921830,
  283.    0.001181684445143001, 0.001087934129054332, 0.001007677515787512, 0.000940630171246217,
  284.    0.000886460636664257, 0.000844792477531490, 0.000815206499600866, 0.000797243121022152
  285. };
  286.  
  287. // h - impulse response
  288. // s - step response
  289. // h[n] = s[n] - s[n-1]
  290.  
  291. // y[n] = sum(x[k]*h[n-k]) = sum(h[k]*x[n-k])
  292. //         k                  k
  293. // ─ы  ъєёюўэю яюёЄю ээюую ёшуэрыр яЁшьхэшьр юяЄшьшчрЎш  т т√ўшёыхэш ї (эхЄ эхюсїюфшьюёЄш т√ўшёы Є№ яЁюьхцєЄюўэ√х Єюўъш)
  294. // y[n] = y[k] + x*(s[n] - s[k])
  295. // уфх n ш k - ъюэЎ√ шэЄхЁтрыр, эр ъюЄюЁюь ёшуэры x яюёЄю эхэ
  296.  
  297. // ╬с∙шх ЇюЁьєы√:
  298. // u - unit step
  299. // s - step response
  300. //                        inf
  301. // x[n] = x[-inf] + sum((x[k]-x[k-1])u[n-k])
  302. //                       -inf
  303. //
  304. //                        inf
  305. // y[n] = x[-inf]s[inf] + sum(x[k]-x[k-1])s[n-k]
  306. //                       -inf
  307. // ╚ч ЇюЁьъы тшфэю, ўЄю чэрўхэш  шьх■Є Єюы№ъю ЇЁюэЄ√ ёшуэрыр, Єрь уфх ёшуэры яюёЄю ээ√щ ёырурх√х юсЁр∙р■Єё  т эюы№
  308. // юЄё■фр ёЄрэютшЄё  тючьюцэр ъєёюўэю-яюёЄю ээр  юяЄшьшчрЎш 
  309.  
  310. // ─ы  YM (чэрўхэш  схЁєЄё  шч ъюэЇшур)
  311. // фы  яЁшьхЁр:
  312. // clock_rate = 1750000 / 8 = 218750
  313. //              1774400 / 8 = 221800
  314. // sample_rate = 44100
  315. // ╧╫ = sample_rate * 64 = 2822400
  316. // ╧хЁхэюё тїюфэюую ёшуэрыр эр ╧╫ фхырхЄё  фюьэюцхэшхь эр (sample_rate*64)/clock_rate =
  317. // 12.9024 (фы  clock_rate = 1.7500) ш 12.724977 (фы  clock_rate = 1.7744)
  318. // ═р ╧╫ фхырхЄё  Їшы№ЄЁрЎш  ш фхЎшьрЎш  т 64 Ёрчр фю sample_rate
  319.  
  320. SNDRENDER::SNDRENDER()
  321. {
  322.    set_timings(SNDR_DEFAULT_SYSTICK_RATE, SNDR_DEFAULT_SAMPLE_RATE);
  323.  
  324.    static char diff_ready = 0;
  325.    if (!diff_ready) {
  326.       double sum = 0;
  327.       for (unsigned i = 0; i < TICK_F*2; i++) { // calculate discrete-time step response
  328.          filter_diff[i] = unsigned(sum * 0x10000);
  329.          sum += filter_coeff[i]; // ╥єЄ ю°шсър, ёєььє эрфю т√ўшёы Є№ фю яюёЄЁюхэш  яхЁхїюфэющ їрЁръЄхЁшёЄшъш, ўЄюс√ filter_diff[0] == filter_coeff[0]
  330.                                  // filter_diff[TICK_F - 1] == 0.5, filter_diff[2*TICK_F - 1] == 1.0
  331.       }
  332.       diff_ready = 1;
  333.    }
  334. }
  335.