Subversion Repositories pentevo

Rev

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