home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Archived / Updates / Flash / flashplayer / flashlib / c++ / sound < prev    next >
Text File  |  2000-06-04  |  13KB  |  561 lines

  1. /////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998,1999 Olivier Debon
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. //
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //
  22.  
  23. #include "swf.h"
  24. #include <time.h>
  25.  
  26. #ifndef NOSOUND
  27. #include "soundcode.h"
  28. #endif
  29.  
  30. #ifdef RCSID
  31. static char *rcsid = "$Id: sound.cc,v 1.11 1999/01/31 21:14:22 olivier Exp $";
  32. #endif
  33.  
  34. #define PRINT 0
  35.  
  36. //////////// SOUND
  37.  
  38. Sound::Sound(long id) : Character(SoundType, id)
  39. {
  40.     samples = 0;
  41.     stereo = 0;
  42.     soundRate = 0;
  43.     sampleSize = 1;
  44. }
  45.  
  46. Sound::~Sound()
  47. {
  48.     if (samples) {
  49.         delete samples;
  50.     }
  51. }
  52.  
  53. void
  54. Sound::setSoundFlags(long f) {
  55.     switch (GET_SOUND_RATE_CODE(f)) {
  56.         case 0:
  57.             soundRate = 5512;
  58.             break;
  59.         case 1:
  60.             soundRate = 11025;
  61.             break;
  62.         case 2:
  63.             soundRate = 22050;
  64.             break;
  65.         case 3:
  66.             soundRate = 44100;
  67.             break;
  68.     }
  69.     if (f & soundIsStereo)   stereo = 1;
  70.     if (f & soundIs16bit)    sampleSize = 2;
  71. }
  72.  
  73. char *
  74. Sound::setNbSamples(long n) {
  75.     long size;
  76.  
  77.     nbSamples = n;
  78.  
  79.     size = nbSamples * (stereo ? 2 : 1) * sampleSize;
  80.     samples = new char[ size ];
  81.     memset((char *)samples,0, size);
  82.  
  83.     return samples;
  84. }
  85.  
  86. long
  87. Sound::getRate() {
  88.     return soundRate;
  89. }
  90.  
  91. long
  92. Sound::getChannel() {
  93.     return stereo ? 2 : 1;
  94. }
  95.  
  96. long
  97. Sound::getNbSamples() {
  98.     return nbSamples;
  99. }
  100.  
  101. long
  102. Sound::getSampleSize() {
  103.     return sampleSize;
  104. }
  105.  
  106. char *
  107. Sound::getSamples() {
  108.     return samples;
  109. }
  110.  
  111. //////////// SOUND MIXER
  112.  
  113. long  SoundMixer::dsp = -1;    // Init of descriptor
  114. long  SoundMixer::blockSize = 0;    // Driver sound buffer size
  115. long  SoundMixer::nbInst = 0;    // Nb SoundMixer instances
  116. long  SoundMixer::sampleSize = 0;
  117. long  SoundMixer::stereo = 0;
  118. long  SoundMixer::soundRate = 0;
  119. char *SoundMixer::buffer = 0;
  120.  
  121. SoundMixer::SoundMixer(char *device)
  122. {
  123. #ifndef NOSOUND
  124.     list = 0;    // No sound to play
  125.  
  126.     if (nbInst++) {
  127.         // Device is already open
  128.         return;
  129.     }
  130.  
  131.     // Set stereo channel and frequency
  132.     stereo = 0;           // set to 1 to use stereo or 0 for mono
  133.     soundRate = 22050;    // either 22050 or 44100
  134.  
  135.     // Get device buffer size and start playback
  136.     if (stereo)
  137.           blockSize = 2*soundcode_play(soundRate, 2);
  138.     else
  139.           blockSize = soundcode_play(soundRate, 1);
  140.     if (blockSize < 0) {
  141.       dsp = -1;
  142.       return;
  143.     }
  144.     buffer = (char *)malloc(blockSize);
  145.     if (!buffer) {
  146.       soundcode_stop();
  147.       dsp = -1;
  148.       return;
  149.     }
  150.         dsp = 1;
  151. #endif
  152. }
  153.  
  154. SoundMixer::~SoundMixer()
  155. {
  156. #ifndef NOSOUND
  157.     if (--nbInst == 0) {
  158.         if (dsp > 0) {
  159.                 soundcode_stop();
  160.             free(buffer);
  161.         }
  162.     }
  163. #endif
  164. }
  165.  
  166. void
  167. SoundMixer::stopSounds()
  168. {
  169. #ifndef NOSOUND
  170.     SoundList *sl,*del;
  171.  
  172.     for(sl = list; sl; ) {
  173.         del = sl;
  174.         sl = sl->next;
  175.         delete del;
  176.     }
  177.     list = 0;
  178. #endif
  179. }
  180.  
  181.  
  182. void
  183. SoundMixer::startSound(Sound *sound, long loops, long flags)
  184. {
  185. #ifndef NOSOUND
  186.           SoundList *sl;
  187.       int rd, wr, bytes, size;
  188.       char *start;
  189.  
  190.           if (dsp < 0)   return;
  191.       if (!sound)    return;
  192.  
  193.           if (flags == 0x01) {          // no multiple
  194.             SoundList *prev;
  195.             char *sampleptr;
  196.             int alreadyplaying;
  197.  
  198.             sl = list;
  199.             alreadyplaying = 0;
  200.             prev = 0;
  201.             sampleptr = sound->getSamples();
  202.             while (sl) {
  203.               // scan list of sound to find one that matches
  204.               if (sl->source == sampleptr)  alreadyplaying = 1;
  205.               sl = sl->next;
  206.             }
  207.             if (alreadyplaying)  return;
  208.           }
  209.           if (flags == 0x02) {          // stop
  210.             SoundList *prev;
  211.             char *sampleptr;
  212.  
  213.             sl = list;
  214.             prev = 0;
  215.             sampleptr = sound->getSamples();
  216.             while (sl) {
  217.               // scan list of sound to find one that matches
  218.               if (sl->source == sampleptr) {
  219.                 if (prev) {
  220.                   prev->next = sl->next;
  221.                   delete sl;
  222.                   sl = prev->next;
  223.                 } else {
  224.                   list = sl->next;
  225.                   delete sl;
  226.                   sl = list;
  227.                 }
  228.               } else
  229.                 sl = sl->next;
  230.             }
  231.             return;
  232.           }
  233.  
  234.           // Add sound in list
  235.           sl = new SoundList;
  236.           sl->rate = sound->getRate();
  237.           sl->stereo = (sound->getChannel() == 2);
  238.           sl->sampleSize = sound->getSampleSize();
  239.           sl->current = sound->getSamples();
  240.           sl->source = sl->current;
  241.           sl->remaining = sound->getSampleSize()*sound->getNbSamples()*sound->getChannel();
  242.           sl->total = sl->remaining;
  243.           sl->loops = loops;
  244.           sl->next = list;
  245.           list = sl;
  246.             // halt playback
  247.           soundcode_control(SOUNDCODEFLAGS_REPEAT, -1, -1, NULL, NULL, NULL, NULL, NULL);
  248.           // get info about the unplayed samples in the buffer
  249.           soundcode_control(-1, -1, -1, NULL, &rd, &wr, (short **)&start, &size);
  250.           rd *= 2;          // convert from samples to bytes
  251.           wr *= 2;
  252.           if (wr >= size)  wr = 0;
  253.           if (rd >= size)  rd = 0;
  254.           // mix sound with contents of buffer
  255.           if (rd < wr) {
  256.             bytes = fillSoundBuffer(sl, start + rd, wr - rd);
  257.           } else if (rd > wr) {
  258.             bytes = fillSoundBuffer(sl, start + rd, size - rd);
  259.             if (sl->remaining) {
  260.               bytes += fillSoundBuffer(sl, start, wr);
  261.             }
  262.           } else {          // rd == wr -> buffer is empty
  263.             // use the generic buffer filling routine
  264.             playSounds();
  265.             bytes = 0;
  266.           }
  267.           // continue playback
  268.           soundcode_control(0, -1, -1, NULL, NULL, NULL, NULL, NULL);
  269.           //
  270.           if (bytes) {
  271.             if (sl->remaining == 0) {
  272.               list = sl->next;
  273.               delete sl;
  274.             }
  275.           }
  276. #endif
  277. }
  278.  
  279.  
  280. long
  281. SoundMixer::playSounds()
  282. {
  283. #ifdef NOSOUND
  284.   return 0;
  285. #else
  286.   FILE *fp;
  287.   long nbBytes, n;
  288.   int freespace;
  289.   SoundList *sl,*prev;
  290.  
  291.   // Init failed
  292.   if (dsp < 0) return 0;
  293.  
  294.   // No sound to play
  295.   if (list == 0) return 0;
  296.  
  297.   soundcode_readposition(NULL, &freespace);
  298.   if (stereo)
  299.     freespace *= 4;
  300.   else
  301.     freespace *= 2;
  302.   // Free space is not large enough to output data without blocking
  303.    // But there are still sounds to play. We must wait.
  304.   if (freespace < blockSize) return 1;
  305.  
  306.   nbBytes = 0;
  307.   // Fill buffer with silence.
  308.   memset((void*)buffer, 0, blockSize);
  309.   prev = 0;
  310.   sl = list;
  311.   while(sl) {
  312.  
  313.       // Ask sound to fill the buffer
  314.       // according to device capabilities
  315.       n = fillSoundBuffer(sl, buffer, blockSize);
  316.  
  317.       // Remember the largest written size
  318.       if (n > nbBytes) {
  319.         nbBytes = n;
  320.       }
  321.  
  322.       // No more samples for this sound
  323.       if (sl->remaining == 0) {
  324.         // Remove sound from list
  325.         if (prev) {
  326.           prev->next = sl->next;
  327.           delete sl;
  328.           sl = prev->next;
  329.         } else {
  330.           list = sl->next;
  331.           delete sl;
  332.           sl = list;
  333.         }
  334.       } else {
  335.         sl = sl->next;
  336.       }
  337.       break; // LJBS no mixing, one sample
  338.   }
  339.   if (nbBytes) {
  340.     int used, given;
  341.     if (stereo) {
  342.       soundcode_fill((short *)buffer, nbBytes/(2*2), &used, &given);
  343.     } else {
  344.       soundcode_fill((short *)buffer, nbBytes/2, &used, &given);
  345.     }
  346.   }
  347.   return nbBytes;
  348. #endif
  349. }
  350.  
  351. long
  352. SoundMixer::fillSoundBuffer(SoundList *sl, char *buff, long buffSize)
  353. {
  354.     long sampleLeft, sampleRight;
  355.     long skipOut, skipOutInit;
  356.     long skipIn, skipInInit;
  357.     long freqRatio;
  358.     long totalOut = 0;
  359.  
  360.     sampleLeft = sampleRight = 0;
  361.     skipOutInit = skipInInit = 0;
  362.  
  363.     freqRatio = sl->rate / soundRate;
  364.     if (freqRatio) {
  365.         skipOutInit = freqRatio - 1;
  366.         skipInInit = 0;
  367.     }
  368.  
  369.     freqRatio = soundRate / sl->rate;
  370.     if (freqRatio) {
  371.         skipInInit = freqRatio - 1;
  372.         skipOutInit = 0;
  373.     }
  374.  
  375.     skipOut = skipOutInit;
  376.     skipIn = skipInInit;
  377.  
  378.     if ((sl->sampleSize == 2) && (sl->stereo)) {
  379.       // STEREO 16 BIT
  380.           while (buffSize && sl->remaining) {
  381.             if (skipIn-- == 0) {
  382.                // Get sampleLeft
  383.                sampleLeft = (long)(*(short *)(sl->current));
  384.                sl->current += 2;
  385.                // Get sampleRight
  386.                sampleRight = (long)(*(short *)(sl->current));
  387.                sl->current += 2;
  388.  
  389.                sl->remaining -= 2*2;
  390.  
  391.                skipIn = skipInInit;
  392.              }
  393.  
  394.             if (skipOut-- == 0) {
  395.               // Output
  396.               *((short *)buff) += sampleLeft/2;
  397.               buff += 2;
  398.               *((short *)buff) += sampleRight/2;
  399.               buff += 2;
  400.  
  401.               buffSize -= 2*2;
  402.               totalOut += 2*2;
  403.  
  404.               skipOut = skipOutInit;
  405.             }
  406.             if (!sl->remaining)
  407.               if (--sl->loops) {
  408.                 sl->remaining = sl->total;
  409.                 sl->current = sl->source;
  410.               }
  411.           }
  412.  
  413.     } else if (sl->sampleSize == 2) {
  414.       // MONO 16 BIT
  415.           while (buffSize && sl->remaining) {
  416.             if (skipIn-- == 0) {
  417.                // Get sampleLeft
  418.                sampleLeft = (long)(*(short *)(sl->current));
  419.                sl->current += 2;
  420.                sl->remaining -= 2;
  421.  
  422.                skipIn = skipInInit;
  423.              }
  424.  
  425.             if (skipOut-- == 0) {
  426.               // Output
  427.               *((short *)buff) += sampleLeft/2;
  428.               buffSize -= 2;
  429.               buff += 2;
  430.               totalOut += 2;
  431.  
  432.               skipOut = skipOutInit;
  433.             }
  434.             if (!sl->remaining)
  435.               if (--sl->loops) {
  436.                 sl->remaining = sl->total;
  437.                 sl->current = sl->source;
  438.               }
  439.           }
  440.  
  441.     } else if ((sl->sampleSize == 1) && (sl->stereo)) {
  442.           // STEREO 8 BIT
  443.           while (buffSize && sl->remaining) {
  444.             if (skipIn-- == 0) {
  445.                // Get sampleLeft
  446.                sampleLeft = (long)*(sl->current);
  447.                sampleLeft <<= 8;
  448.                sl->current += 1;
  449.                sl->remaining -= 1;
  450.  
  451.                // Get sampleRight
  452.                sampleRight = (long)*(sl->current);
  453.                sl->current += 1;
  454.                sl->remaining -= 1;
  455.  
  456.                skipIn = skipInInit;
  457.              }
  458.  
  459.             if (skipOut-- == 0) {
  460.               // Output
  461.               *((short *)buff) += sampleLeft/2;
  462.               buffSize -= 2;
  463.               buff += 2;
  464.               *((short *)buff) += sampleRight/2;
  465.               buffSize -= 2;
  466.               buff += 2;
  467.               totalOut += 2*2;
  468.  
  469.               skipOut = skipOutInit;
  470.             }
  471.             if (!sl->remaining)
  472.               if (--sl->loops) {
  473.                 sl->remaining = sl->total;
  474.                 sl->current = sl->source;
  475.               }
  476.           }
  477.  
  478.     } else if (sl->sampleSize == 1) {
  479.       // MONO 8 BIT
  480.           while (buffSize && sl->remaining) {
  481.             if (skipIn-- == 0) {
  482.                // Get sampleLeft
  483.                sampleLeft = (long)*(sl->current);
  484.                sampleLeft <<= 8;
  485.                sl->current += 1;
  486.                sl->remaining -= 1;
  487.  
  488.                skipIn = skipInInit;
  489.              }
  490.  
  491.             if (skipOut-- == 0) {
  492.               // Output
  493.               *((short *)buff) += sampleLeft/2;
  494.               buffSize -= 2;
  495.               buff += 2;
  496.               totalOut += 2;
  497.  
  498.               skipOut = skipOutInit;
  499.             }
  500.             if (!sl->remaining)
  501.               if (--sl->loops) {
  502.                 sl->remaining = sl->total;
  503.                 sl->current = sl->source;
  504.               }
  505.           }
  506.     }
  507. /*
  508.     while (buffSize && sl->remaining) {
  509.         if (skipIn-- == 0) {
  510.             // Get sampleLeft
  511.             if (sl->sampleSize == 2) {
  512.                 sampleLeft = (long)(*(short *)(sl->current));
  513.             } else {
  514.                 sampleLeft = (long)*(sl->current);
  515.                 sampleLeft <<= 8;
  516.             }
  517.             sl->current += sl->sampleSize;
  518.             sl->remaining -= sl->sampleSize;
  519.  
  520.             if (sl->stereo) {
  521.                 // Get sampleRight
  522.                 if (sl->sampleSize == 2) {
  523.                     sampleRight = (long)(*(short *)(sl->current));
  524.                 } else {
  525.                     sampleRight = (long)*(sl->current);
  526.                     sampleRight <<= 8;
  527.                 }
  528.                 sl->current += sl->sampleSize;
  529.                 sl->remaining -= sl->sampleSize;
  530.  
  531.             } else {
  532.                 sampleRight = sampleLeft;
  533.             }
  534.  
  535.             skipIn = skipInInit;
  536.         }
  537.  
  538.         if (skipOut-- == 0) {
  539.             // Output
  540.             if (stereo) {
  541.                     *((short *)buff) += sampleLeft/2;
  542.                 buffSize -= 2;
  543.                 buff += 2;
  544.                 *((short *)buff) += sampleRight/2;
  545.                 buffSize -= 2;
  546.                 buff += 2;
  547.                 totalOut += 2*2;
  548.             } else {
  549.                 *((short *)buff) += (sampleLeft+sampleRight)>>2;
  550.                 buffSize -= 2;
  551.                 buff += 2;
  552.                 totalOut += 2;
  553.             }
  554.  
  555.             skipOut = skipOutInit;
  556.         }
  557.     }
  558. */
  559.     return totalOut;
  560. }
  561.