home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / mix_server.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  14.2 KB  |  672 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <string.h>
  5. #include <malloc.h>
  6.  
  7. #include <conf.h>
  8. #include "clstandardtypes.h"
  9. #include "sysdeps.h"
  10. #include "log.h"
  11. #include "mix_server.h"
  12. #include "xmalloc.h"
  13.  
  14. #define _L     LOG_SOUND | LOG_INFO
  15.  
  16. /*        MIXER SERVER        */
  17.  
  18. #if defined(UNDER_UNIX)
  19. #define WRITE_TO_FILE 1
  20. #endif
  21.  
  22. #if WRITE_TO_FILE
  23. #include <fcntl.h>
  24. int snd_file;
  25. #endif
  26.  
  27. /*    This is a OS-generic module for mixing digitized samples together. */
  28. void        
  29. mix_init(mix_context * m, u32 hertz, u32 bufsize,
  30.          bool issigned, bool eightbit, bool bigendian)
  31. {
  32.     u16         x;
  33.  
  34. #if WRITE_TO_FILE
  35.     snd_file = open("digital.raw", O_CREAT|O_TRUNC|O_WRONLY, 0666);
  36.     if (snd_file < 0) snd_file = 0;
  37. #endif
  38.  
  39.     x = ('A' << 8) + 'B';
  40.     m->soundhz = hertz < 4000 ? 4000 : hertz;
  41.     m->issigned = issigned;
  42.     m->eightbit = eightbit;
  43.     m->swapendian = (*(u8 *) & x == 'B') == bigendian;
  44.  
  45.     logger(_L | L_1, "mix_init: swapendian=%d\n\n", m->swapendian);
  46.     m->buffer = (s32 *) xmalloc(sizeof(s32) * bufsize);
  47.     m->bufsize = bufsize;
  48. }
  49.  
  50. void
  51. mix_term(mix_context * m)
  52. {
  53.     if (m->buffer) {
  54.         xfree(m->buffer);
  55.         m->buffer = NULL;
  56.     }
  57. #if WRITE_TO_FILE
  58.     if (snd_file) close(snd_file);
  59. #endif
  60. }
  61.  
  62. void
  63. mix_restart(mix_context * m)
  64. {
  65.     memset(m->voices, 0, sizeof(m->voices));
  66.     m->voices[0].clock = m->voices[1].clock = m->voices[2].clock =
  67.         m->voices[3].clock = m->voices[4].clock = m->voices[5].clock =
  68.         m->soundhz;
  69.     m->voices[3].ns1 = 0xaaaaaaaa;
  70.     m->voices[3].ns2 = 1;
  71. }
  72.  
  73. //  Step a tone voice by one sample and return contrib.
  74. INLINE void
  75. step_tone(sample * v, s32 * chn, int * active)
  76. {
  77.     v->div += v->delta;
  78.     if (v->div >= v->clock) {
  79.         /*if (v->vol) */  {
  80.             *chn += v->vol;
  81.             (*active)++;
  82.         }
  83.         while (v->div >= v->clock)
  84.             v->div -= v->clock;
  85.     } else {
  86.         //*chn += -v->vol;
  87.         //(*active)++;
  88.     }    
  89. }
  90.  
  91. //  Advance a tone voice by X samples.
  92. INLINE void
  93. advance_tone(sample * v, u32 samples)
  94. {
  95.     v->div = (v->div + v->delta * samples) % v->clock;
  96. }
  97.  
  98.  
  99. //  Step white noise by one sample and update dat.
  100.  
  101. #define NOISE_GATE(x,y) \
  102.     do {                        \
  103.         x = (x<<1) | (x>>31);    \
  104.         x ^= y;                    \
  105.         if ((y += x)==0)    y++; \
  106.     } while (0)
  107.  
  108. INLINE void
  109. step_white(sample * v, s32 * chn, int * active)
  110. {
  111.     v->div += v->delta;
  112.     while (v->div >= v->clock) {
  113.         NOISE_GATE(v->ns1, v->ns2);
  114.         v->div -= v->clock;
  115.     }
  116.     if (v->ns1 & 1) {
  117.         /*if (v->vol) */  {
  118.             *chn += v->vol;
  119.             (*active)++;
  120.         }
  121.     } else {
  122.         
  123. //        *chn -= v->vol;
  124. //        (*active)++;
  125.     }
  126. }
  127.  
  128. //  Advance white noise by X samples
  129. INLINE void
  130. advance_white(sample * v, u32 samples)
  131. {
  132.     u32         chg;
  133.     u32         steps;
  134.  
  135.     chg = v->delta * samples;
  136.     steps = (v->div + chg) / v->clock;
  137.     v->div = (v->div + chg) % v->clock;
  138.     while (steps--) {
  139.         NOISE_GATE(v->ns1, v->ns2);
  140.     }
  141. }
  142.  
  143. //  Step periodic noise by one sample and update dat.
  144. #define PERIODMULT 16
  145. INLINE void
  146. step_periodic(sample * v, s32 * chn, int * active)
  147. {
  148.     v->div += v->delta;
  149.     if (v->div >= v->clock) {
  150.         /*if (v->vol) */  {
  151.             *chn += v->vol;
  152.             (*active)++;
  153.         }
  154.         while (v->div >= v->clock)
  155.             v->div -= v->clock;
  156.     } else {
  157.         //*chn -= v->vol;
  158.         //(*active)++;
  159.     }        
  160. }
  161.  
  162. //  Advance periodic noise by X samples
  163. INLINE void
  164. advance_periodic(sample * v, u32 samples)
  165. {
  166.     v->div = (v->div + v->delta * samples) % v->clock;
  167. }
  168.  
  169. //  Step speech by one sample and update dat.
  170. //  Sample is finished when s->used==0.  Caller should free memory.
  171. INLINE void
  172. step_digital(sample * v, s32 * chn, int * active)
  173. {
  174.     if (v->used) {
  175.         *chn += v->data[v->st] * (signed) v->vol / (signed) 256;
  176.         (*active)++;
  177.  
  178.         v->div += v->delta;
  179.         while (v->div >= v->clock) {
  180.             v->div -= v->clock;
  181.             v->st++;
  182.             v->used--;
  183.             if (v->used == 0) {
  184.                 v->st = v->en = 0;
  185.             } else if (v->st >= v->len) {
  186.                 v->st -= v->len;
  187.             }
  188.         }
  189.     }
  190. }
  191.  
  192. //  Advance digital data by X samples
  193. INLINE void
  194. advance_digital(sample * v, u32 samples)
  195. {
  196.     u32         chg = v->delta * samples;
  197.     u32         steps = (v->div + chg) / v->clock;
  198.  
  199.     v->div = (v->div + chg) % v->clock;
  200.     v->st = (v->st + steps) % v->len;
  201.  
  202.     // unless we loop [we don't],
  203.     // we are done when we've stepped through
  204.     // the whole sample.
  205.     if (v->used <= steps || v->used == 0) {
  206.         v->st = v->en = 0;
  207.         // don't free memory (there's a bug here)
  208. //      xfree(v->data);
  209. //      v->data = NULL;
  210.         v->used = 0;
  211.         v->len = 0;
  212.     } else {
  213.         v->used -= steps;
  214.     }
  215. }
  216.  
  217. #if 0
  218. //  Step audio gate 
  219. INLINE void
  220. step_audiogate(sample * v, s32 * chn, int * active)
  221. {
  222.     // since this can change so fast, we set v->clock
  223.     // to indicate something should happen
  224.     if (v->clock & 1) {
  225.         *chn += v->vol;
  226.     } else if (v->clock) {
  227.         *chn -= 0x7fffff;
  228.     }
  229.     (*active)++;
  230. }
  231.  
  232. //  Advance audio gate
  233. INLINE void
  234. advance_audiogate(sample * v, u32 samples)
  235. {
  236.     if (v->clock > samples)
  237.         v->clock -= samples;
  238.     else
  239.         v->clock = 0;
  240. }
  241. #endif
  242.  
  243. static int  had_silent_frame = 0;
  244. static int
  245. mix_silence(mix_context * m)
  246. {
  247.     // check that something is on
  248.     return (
  249.             (m->voices[0].vol | m->voices[1].vol | m->voices[2].
  250.              vol | m->voices[3].vol | m->voices[4].vol | m->voices[5].vol) ==
  251.             0 ||
  252.             // and that nothing is illegal
  253.             (m->voices[0].clock && m->voices[1].clock && m->voices[2].clock
  254.              && m->voices[3].clock && m->voices[4].clock
  255.              && m->voices[5].clock) == 0);
  256. }
  257.  
  258. /*
  259.     Mix the channels together and generate a segment of
  260.     sound.  Does not advance the mixer's idea of time;
  261.     use mix_advance() to do that.
  262. */
  263. void
  264. mix_mixit(mix_context * m, u32 advance, u32 samples)
  265. {
  266.     s32        *out = m->buffer, *end = out + samples;
  267.     s32         dat = 0;
  268.     int         div = 0;
  269.     int         silent;
  270.     sample      myvoices[6];
  271.  
  272.     //  work on local copy of m->voices.
  273.     memcpy(myvoices, m->voices, sizeof(myvoices));
  274.  
  275.     if (advance)
  276.         mix_advance(m, advance);
  277.  
  278.     silent = mix_silence(m);
  279.     if (!silent || !had_silent_frame) {
  280.         had_silent_frame = silent;
  281.  
  282.         while (out < end) {
  283.             dat = 0;
  284.             div = 0;
  285.  
  286.             // tones
  287.             if (myvoices[0].vol)
  288.                 step_tone(&myvoices[0], &dat, &div);
  289.             if (myvoices[1].vol)
  290.                 step_tone(&myvoices[1], &dat, &div);
  291.             if (myvoices[2].vol)
  292.                 step_tone(&myvoices[2], &dat, &div);
  293.  
  294.             // noise
  295.             if (myvoices[3].vol) {
  296.                 sample     *n = &myvoices[3];
  297.  
  298.                 if (n->iswhite) {
  299.                     step_white(n, &dat, &div);
  300.                 } else {
  301.                     step_periodic(n, &dat, &div);
  302.                 }
  303.  
  304.             }
  305.             // speech
  306.             if (myvoices[4].used) {
  307.                 step_digital(&myvoices[4], &dat, &div);
  308.             }
  309.             // audio gate
  310.             if (myvoices[5].used) {
  311.                 step_digital(&myvoices[5], &dat, &div);
  312.             }
  313.  
  314.             if (div) {
  315.                 //dat /= div;
  316.                 dat >>= 1;
  317.                 if (dat)
  318.                     logger(_L | L_3, "dat[%d]=%08X \n", div, dat);
  319.             }
  320.  
  321.             *out++ = dat <= -0x00800000 ? -0x007fffff :
  322.                 dat >= 0x00800000 ? 0x007fffff : dat;
  323.         }
  324.  
  325.     } else {
  326.         memset(m->buffer, 0, samples * sizeof(s32));
  327.         had_silent_frame = true;
  328.     }
  329.  
  330.     /*  Convert sample  */
  331.  
  332.     if (m->eightbit) {
  333.         int         idx;
  334.         s8         *ptr = (s8 *) m->buffer;
  335.  
  336.         for (idx = 0; idx < samples; idx++)
  337.             *ptr++ = m->buffer[idx] >> 16;    /* 24 -> 8 */
  338.     } else {
  339.         int         idx;
  340.         s16        *ptr = (s16 *) m->buffer;
  341.  
  342.         for (idx = 0; idx < samples; idx++)
  343.             *ptr++ = m->buffer[idx] >> 8;    /* 24 -> 16 */
  344.     }
  345.  
  346.     if (!m->issigned) {
  347.         int         idx;
  348.         int         step = (m->eightbit ? 1 : 2);
  349.         s8         *ptr = (s8 *) m->buffer;
  350.  
  351.         for (idx = (m->swapendian ? step - 1 : 0); idx < samples; idx += step)
  352.             ptr[idx] ^= 0x80;
  353.     }
  354.  
  355.     if (m->swapendian && !m->eightbit) {
  356.         swab((char *) m->buffer, (const char *) m->buffer,
  357.              samples * sizeof(u16));
  358.     }
  359.  
  360. }
  361.  
  362. /*    Advance mixer time by so many samples. */
  363. void
  364. mix_advance(mix_context * m, int samples)
  365. {
  366.     // tones
  367.     if (m->voices[0].clock)
  368.         advance_tone(&m->voices[0], samples);
  369.     if (m->voices[1].clock)
  370.         advance_tone(&m->voices[1], samples);
  371.     if (m->voices[2].clock)
  372.         advance_tone(&m->voices[2], samples);
  373.  
  374.     // noise
  375.     if (m->voices[3].iswhite) {
  376.         if (m->voices[3].clock)
  377.             advance_white(&m->voices[3], samples);
  378.     } else {
  379.         if (m->voices[3].clock)
  380.             advance_periodic(&m->voices[3], samples);
  381.     }
  382.  
  383.     // speech
  384.     if (m->voices[4].used) {
  385.         advance_digital(&m->voices[4], samples);
  386.     }
  387.     // audio gate
  388.     if (m->voices[5].used) {
  389.         advance_digital(&m->voices[5], samples);
  390.     }
  391. }
  392.  
  393. static void
  394. stackdata(sample * s, s8 * bytes, int size)
  395. {
  396.     int         cnt;
  397.  
  398.     /*  This routine is apt to occur during a speech
  399.        interrupt and lead to inconsistencies.  We do all
  400.        our work on a copy of the sample.  The worst that
  401.        can happen, it appears, is for a part of the
  402.        sample to be repeated when this routine resets
  403.        the s->st and s->en pointers.  */
  404.  
  405.     sample      in = *s;
  406.  
  407.     if (bytes == NULL)
  408.         return;
  409.  
  410. #if 0
  411.     //  Simplest algorithm, but very bad on memory.
  412.  
  413.     in.data = (u8 *) xrealloc(in.data, size + in.len);
  414.     memcpy(in.data + in.en, bytes, size);
  415.     in.len += size;
  416.     in.en += size;
  417.     in.used += size;
  418.     *s = in;
  419.     return;
  420. #endif
  421.  
  422.     logger(_L | L_1, "IN:  in.data=%p, in.len=%d, in.used=%d, in.st=%d, in.en=%d\n",
  423.          in.data, in.len, in.used, in.st, in.en);
  424.  
  425.     if (in.st > in.len || in.en > in.len ||
  426.         (in.st >= in.en ?
  427.          (in.used != (in.len - in.st + in.en)) :
  428.          (in.used != (in.en - in.st)))) {
  429.         logger(_L | LOG_ERROR | LOG_USER,
  430.              "consistency error: in.len=%d, in.st=%d, in.en=%d, in.used=%d\n",
  431.              in.len, in.st, in.en, in.used);
  432.         if (in.data) xfree(in.data); in.data = NULL;
  433.         in.used = in.len = in.st = in.en = 0;
  434.     }
  435.  
  436.     /* need to shrink the ring? */
  437.     if (in.data != NULL && (in.used < in.len) && (in.used + size < in.len)) {
  438.         /* two cases:  (1) all data is contiguous:  move to beginning,
  439.            reset pointers, and continue.
  440.            (2) data wraps.  Move [0,...) part up, move end part to beginning. */
  441.  
  442.         logger(_L | L_1, "shrinking block");
  443.         /*  non-wrapping case */
  444.         if (in.used > 0 && in.st < in.en) {
  445.             memmove(in.data, in.data + in.st, in.used);
  446.             in.st = 0;
  447.             in.en = in.used;
  448.             in.data = (s8 *) xrealloc(in.data, in.used);
  449.             in.len = in.used;
  450.         }
  451.         /*  wrapping case */
  452.         else
  453.             if (in.used > 0 && in.st > in.en
  454.                 && (in.len - in.st + in.en < in.st)) {
  455.             int         endsize = in.len - in.st;
  456.  
  457.             memmove(in.data + endsize, in.data, in.en);
  458.             memmove(in.data, in.data + in.st, endsize);
  459.             in.st = 0;
  460.             in.en += endsize;
  461.             in.data = (s8 *) xrealloc(in.data, in.en);
  462.             in.len = in.en;
  463.         }
  464.     }
  465.  
  466.     /* need to grow the ring? */
  467.     if (in.data == NULL || in.used + size > in.len) {
  468.         int         nw;
  469.  
  470.         logger(_L | L_1, "resizing:  in.used+size=%d, in.len=%d, in.data=%p\n\n",
  471.              in.used + size, in.len, in.data);
  472.         nw = in.used + size;
  473.         in.data = (s8 *) xrealloc(in.data, nw);
  474.  
  475.         /* if we grew the buffer and the used part was wrapping,
  476.            move the end of the old buffer to the end of the
  477.            new buffer */
  478.         if (in.used > 0 && in.en <= in.st && in.st > 0) {
  479.             int         endsize = in.len - in.st;
  480.  
  481.             memmove(in.data + nw - endsize, in.data + in.st, endsize);
  482.             in.st = nw - endsize;
  483.         }
  484.         if (in.en == in.st && in.en == 0)
  485.             in.en = in.len;
  486.         in.len = nw;
  487.     }
  488.  
  489.     /* paste on the end of the current block, don't wrap */
  490.     cnt = (in.len - in.en <= size) ? in.len - in.en : size;
  491.     memcpy(in.data + in.en, bytes, cnt);
  492.  
  493.     /*  copy the rest to the beginning of the ring */
  494.     memcpy(in.data, bytes + cnt, size - cnt);
  495.  
  496.     in.used += size;
  497.     in.en += size;
  498.     if (in.en >= in.len)
  499.         in.en -= in.len;
  500.  
  501.     *s = in;
  502.  
  503.     logger(_L | L_1, "OUT: s->data=%p, s->len=%d, s->used=%d, s->st=%d, s->en=%d\n",
  504.          s->data, s->len, s->used, s->st, s->en);
  505.  
  506. }
  507.  
  508. ///////////////////////////////////////////////////////
  509.  
  510. /*
  511. #include <math.h>
  512. #include <stdio.h>
  513.  
  514. int main(void)
  515. {
  516.         int x;
  517.         for (x=0; x<16; x++)
  518.         {
  519.                 double f = exp((x/15.0) * log(17)) ;
  520.                 printf("\t%08X,\n", (int)(f * 0x080000));
  521.  
  522.         }
  523. }
  524. */
  525.  
  526. static u32  atten[16] = {
  527.     0x00000000,
  528. //  0x00080000,
  529.     0x0009A9C5,
  530.     0x000BAC10,
  531.     0x000E1945,
  532.     0x001107A1,
  533.     0x001491FC,
  534.     0x0018D8C4,
  535.     0x001E0327,
  536.     0x00244075,
  537.     0x002BC9D6,
  538.     0x0034E454,
  539.     0x003FE353,
  540.     0x004D2B8C,
  541.     0x005D36AB,
  542.     0x007097A5,
  543.     0x007FFFFF
  544. };
  545.  
  546. void
  547. mix_handle_voice(mix_context * m, u8 channel, u32 hertz, u8 volume)
  548. {
  549.     sample     *s;
  550.  
  551.     logger(_L | L_2, "mix_handle_voice: channel %d, hertz = 0x%x, volume = %d\n",
  552.          channel, hertz, volume);
  553.  
  554.     if (channel >= mix_CHN0 && channel <= mix_CHN2) 
  555.     {
  556.         s = &m->voices[channel];
  557.  
  558.         // sounds this high-pitched won't
  559.         // work at all.
  560.         if (hertz * 2 >= m->soundhz) {
  561.             s->delta = 0;
  562.             s->vol = 0;
  563.             s->clock = m->soundhz;    // assure no zero divides
  564.         } else {
  565.             s->clock = m->soundhz;
  566.             s->delta = hertz;
  567.             s->div = volume ? s->div : 0;
  568.             s->vol = atten[volume];
  569.         }
  570.     }
  571. }
  572.  
  573. void
  574. mix_handle_noise(mix_context * m, u8 channel, u32 hertz, u8 volume, 
  575.                  int iswhite)
  576. {
  577.     sample     *s;
  578.  
  579.     logger(_L | L_2, "mix_handle_noise: channel %d, hertz = 0x%x, volume = %d, iswhite = %d\n",
  580.          channel, hertz, volume, iswhite);
  581.  
  582.     if (channel == mix_Noise)
  583.     {
  584.         s = &m->voices[channel];
  585.  
  586.         if (iswhite) {
  587.             s->clock = m->soundhz;
  588.             s->delta = hertz;
  589.             s->div = volume ? s->div : 0;
  590.             s->vol = atten[volume];
  591.             s->iswhite = 1;
  592.         } else {
  593.             s->clock = m->soundhz * PERIODMULT;
  594.             s->delta = hertz;
  595.             s->div = volume ? s->div : 0;
  596.             s->vol = atten[volume];
  597.             s->iswhite = 0;
  598.         }
  599.     }
  600. }
  601.  
  602. void
  603. mix_handle_data(mix_context * m, u8 channel, u32 hertz, u8 volume, u32 length,
  604.                 s8 * data)
  605. {
  606.     logger(_L | L_1, "mix_handle_data: using %d bytes of %d Hz data on channel %d\n",
  607.          length, hertz, channel);
  608.  
  609. #if WRITE_TO_FILE
  610.     if (snd_file) write(snd_file, data, length);
  611. #endif
  612.  
  613.     switch (channel) {
  614.     case mix_Speech:
  615.     {
  616.         sample     *s = &m->voices[4];
  617.         if (data && length) {
  618.             s->clock = m->soundhz;
  619.             s->delta = hertz;
  620.             s->div = 0;
  621.             s->vol = volume << 15;
  622.             stackdata(s, data, length);
  623.         } else {
  624.             // flush
  625.             if (s->delta > 0)
  626.             while (s->len > s->delta) 
  627.             {
  628.                 
  629.             }
  630. /*            xfree(s->data);
  631.             s->data = 0L;
  632.             s->len = s->used = s->st = s->en = 0;*/
  633.         }
  634.  
  635.         break;
  636.     }
  637.  
  638.     case mix_AudioGate:
  639.     {
  640.         /*  for the audio gate, we only use the volume;
  641.            no data need be passed.  This is because we interpret
  642.            'length' as a repeat count for 'vol'.  */
  643.  
  644.         if (length) {
  645.             s8         *tmp = (s8 *) alloca(length);
  646.             sample     *s = &m->voices[5];
  647.  
  648. //              int x;
  649.             logger(_L | L_2, "writing %d bytes of %d as audio gate\n", length, volume);
  650. //              for (x=0; x<length; x++)
  651. //                  tmp[x] = ((volume ^ !!(x&1)) ? 0x7f : 0) ;
  652.             memset(tmp, volume, length);
  653.             s->clock = m->soundhz;
  654.             s->delta = hertz;
  655.             s->div = 0;
  656.             s->vol = volume << 15;
  657.             stackdata(s, tmp, length);
  658.         } else {
  659.             sample     *s = &m->voices[5];
  660.  
  661.             if (s->used > s->delta) {
  662. //                  if (s->data) xfree(s->data); s->data = NULL;
  663.                 s->st = s->en = s->len = s->used = 0;
  664.             }
  665.         }
  666.         break;
  667.     }
  668.     }
  669. }
  670.  
  671. /*********************************/
  672.