home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Archived / Updates / Flash / flashplayer / flashlib / c++ / soundcode < prev   
Encoding:
Text File  |  2000-06-03  |  8.0 KB  |  256 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. // oslib
  5. #include "os.h"
  6. #include "osmodule.h"
  7. #include "OS:h.sound"
  8. //
  9. #include "soundcode.h"
  10.  
  11. static int sound_claimed = 0;
  12. static int *sound_rma = NULL;
  13. static int sound_written = 0;
  14. static int sound_previoussamplerate;
  15. static soundcode_memory *sound_parameters;
  16. static os_dynamic_area_no sound_area = 0;
  17.  
  18. /*
  19. int main(int argc, char *argv[]) {
  20.  
  21.   FILE *fh;
  22.   int total, read, freespace, used, played, channels;
  23.   short buffer[20000];
  24.  
  25.   fh = fopen("ADFS::HardDisc4.$.Program.PlayModule.BillyJoel3", "rb");
  26.   channels = 2;
  27.   if (soundcode_play(44100, channels) < 0)  return 0;
  28.   total = 0x7f000000;
  29.   do {
  30.     // get free space
  31.     soundcode_readposition(&played, &freespace);
  32.     if (freespace > 1000) {
  33.       // don't bother if there's less than 1000
  34.       // don't read more than the buffer can hold...
  35.       if (freespace > 20000/channels)   freespace = 20000/channels;
  36.       // read the data
  37.       read = fread(buffer, 2*channels, freespace, fh);
  38.       // if we got less than we wanted, we're at the end of the file
  39.       if (read < freespace)
  40.         // fill the buffer and read the total no. of samples we've used
  41.         soundcode_fill(buffer, read, &used, &total);
  42.       else
  43.         soundcode_fill(buffer, read, &used, NULL);
  44.     }
  45.   } while (played < total);
  46.  
  47.   soundcode_stop();
  48.   return 0;
  49. } */
  50.  
  51.  
  52.  
  53. // soundcode_stop             stop playback
  54. void soundcode_stop() {
  55.  
  56.   void *oldcode, *oldworkspace;
  57.  
  58.   if ((!sound_rma) || (!sound_claimed))  return;
  59.   sound_claimed = 0;
  60.  
  61.   // read current handler
  62.   xsound_linear_handler(0, NULL, NULL, &oldcode, &oldworkspace);
  63.   if ((oldcode      == sound_parameters->address) &&
  64.       (oldworkspace == sound_parameters->arg)) {
  65.     xsound_linear_handler(1, NULL, NULL, NULL, NULL);
  66.     xsoundsamplerate_select(sound_previoussamplerate, NULL, NULL);
  67.   }
  68.  
  69.   // release memory
  70.   xosmodule_free((byte *)sound_rma);
  71.   xosdynamicarea_delete(sound_area);
  72. }
  73.  
  74.  
  75. // soundcode_play             start playback
  76. // returns buffersize (in 16 bit samples/channel) for OK or -1 for error
  77. // on entry
  78. // freq                       playback frequency
  79. // chans                      no. of channels to play (1 or 2)
  80. int soundcode_play(int freq, int chans) {
  81.  
  82.   int rateindex, i, nsr, prevrate, sr, rate, buffersize;
  83.   short *bufferstart;
  84.  
  85.   if (freq < 4000 || freq > 50000 || chans < 1 || chans > 2)  return -1;
  86.   if (sound_claimed)  return -1;
  87.  
  88.   // make sure 16 bit sound is supported
  89.   if (xsoundsamplerate_read_count(&nsr))  return -1;
  90.  
  91.   // find the best playback-frequency
  92.   rateindex = -1;
  93.   xsoundsamplerate_lookup(1, &prevrate);
  94.   prevrate = prevrate >> 10;
  95.  
  96.   for (sr = 2; sr <= nsr; sr++) {
  97.     xsoundsamplerate_lookup(sr, &rate);
  98.     rate = rate >> 10;
  99.     if ((rateindex == -1) && (prevrate < freq) && (rate >= freq))
  100.         rateindex = sr;
  101.     prevrate = rate;
  102.   }
  103.   if (rateindex == -1)  return -1;
  104.  
  105.   // get RMA block for buffer-fill-code
  106.   sound_rma = NULL;
  107.   if (xosmodule_alloc(4*SOUNDCODE_SIZE, (void **)&sound_rma))  return -1;
  108.   // copy buffer-fill-code
  109.   for (i = 0; i < SOUNDCODE_SIZE; i++)  sound_rma[i] = soundcode[i];
  110.   sound_rma[SOUNDCODE_FILLCODE] += (int)sound_rma;
  111.  
  112.   sound_parameters = (soundcode_memory *)&sound_rma[SOUNDCODE_PARAMETERS];
  113.  
  114.   // get ~2 seconds buffer
  115.   buffersize = 2*2*chans*freq & ~4095;
  116.   if (xosdynamicarea_create((os_dynamic_area_no)-1, buffersize,
  117.                              (byte *)-1, 128, buffersize,
  118.                              NULL, NULL, "Sound buffer",
  119.                              &sound_area, (byte **)&bufferstart, NULL))  {
  120.     xosmodule_free((byte *)sound_rma);
  121.     return -1;
  122.   }
  123.   buffersize /= 2;  // convert from bytes to samples
  124.  
  125.   // init the parameter-block passed to the buffer-fill-code
  126.   sound_parameters->startaddress = bufferstart;
  127.   sound_parameters->buffersize = buffersize;
  128.   sound_parameters->readpos = sound_parameters->writepos = 0;
  129.   sound_parameters->channels = chans;
  130.   sound_parameters->flags = 0;
  131.   // select samplerate
  132.   xsoundsamplerate_read_current(&sound_previoussamplerate, NULL);
  133.   xsoundsamplerate_select(rateindex, NULL, NULL);
  134.  
  135.   sound_parameters->address = (void *)sound_rma[SOUNDCODE_FILLCODE];
  136.   sound_parameters->arg = sound_parameters;
  137.  
  138.   xsound_linear_handler(1, sound_parameters->address, sound_parameters->arg, NULL, NULL);
  139.   sound_claimed = 1;
  140.   sound_written = 0;
  141.  
  142.   return buffersize/chans;
  143. }
  144.  
  145.  
  146. // soundcode_fill             fill the sample-buffer
  147. // returns 0 for OK or -1 for error
  148. // on entry
  149. // buffer                     pointer to samples
  150. // samples                    no. of samples/channel in the buffer
  151. // on exit
  152. // used                       no. of samples/channel read from the buffer
  153. // given                      total no. of samples/channel written since start
  154. int soundcode_fill(short *buffer, int samples, int *used, int *given) {
  155.  
  156.   int n, chns, firstpart, secondpart;
  157.  
  158.   if ((!sound_rma) || (!sound_claimed))  return -1;
  159.   *used = 0;
  160.   if (given)   *given = sound_written;
  161.   if (samples <= 0)                      return 0;
  162.  
  163.   chns = sound_parameters->channels;
  164.  
  165.   // no. of samples/channel waiting to be filled
  166.   n = sound_parameters->readpos - sound_parameters->writepos;
  167.   if (n <= 0)  n += sound_parameters->buffersize;
  168.   n = n/chns;
  169.   if (chns == 2)   n &= ~1;
  170.  
  171.   if (n < 4) {      // don't bother
  172.     *used = 0;
  173.     return 0;
  174.   }
  175.  
  176.   n -= 2;           // never fill completely
  177.   if (n > samples)  n = samples;
  178.  
  179.   firstpart = (sound_parameters->buffersize - sound_parameters->writepos)/chns;
  180.   if (firstpart > n)  firstpart = n;
  181.   memcpy(sound_parameters->startaddress + sound_parameters->writepos,
  182.          buffer,
  183.          2*chns*firstpart);
  184.   sound_parameters->writepos += chns*firstpart;
  185.   if (sound_parameters->writepos == sound_parameters->buffersize)
  186.     sound_parameters->writepos = 0;
  187.  
  188.   secondpart = n - firstpart;
  189.   if (secondpart > 0) {
  190.     memcpy(sound_parameters->startaddress, buffer + chns*firstpart, 2*chns*secondpart);
  191.     sound_parameters->writepos = chns*secondpart;
  192.   }
  193.  
  194.   *used = n;
  195.   sound_written += n;
  196.   if (given)  *given = sound_written;
  197.  
  198.   return 0;
  199. }
  200.  
  201.  
  202. // soundcode_readposition     read info about playback
  203. // returns 0 for OK or -1 for error
  204. // on exit
  205. // played                     no. of samples/channel played
  206. // freespace                  amount of free space (samples/channel) in buffer
  207. int soundcode_readposition(int *played, int *freespace) {
  208.  
  209.   if ((!sound_rma) || (!sound_claimed))  return -1;
  210.  
  211.   if (played)
  212.     *played = sound_parameters->playedsamples;
  213.  
  214.   if (freespace) {
  215.     int n;
  216.  
  217.     n = sound_parameters->readpos - sound_parameters->writepos;
  218.     if (n <= 0)  n += sound_parameters->buffersize;
  219.     *freespace = n/sound_parameters->channels;
  220.   }
  221.  
  222.   return 0;
  223. }
  224.  
  225.  
  226. // soundcode_control          read/write buffer/flags
  227. // on entry
  228. // newflags                   new flags or -1
  229. //                            bit 0 set   pause playback
  230. //                            bit 0 clear continue playback
  231. //                            bit 1 set   repeated playback
  232. //                            bit 1 clear normal playback
  233. // newreadpos                 new read pos or -1
  234. // newwritepos                new write pos or -1
  235. // on exit
  236. // oldflags                   old flags
  237. // oldreadpos                 old read pos
  238. // oldwritepos                old write pos
  239. // bufferstart                pointer to start of buffer
  240. // buffersize                 size of buffer (in bytes)
  241. int soundcode_control(int newflags, int newreadpos, int newwritepos, int *oldflags, int *oldreadpos, int *oldwritepos, short **bufferstart, int *buffersize) {
  242.  
  243.   if ((!sound_rma) || (!sound_claimed))  return -1;
  244.  
  245.   if (oldflags)            *oldflags = sound_parameters->flags;
  246.   if (oldreadpos)          *oldreadpos = sound_parameters->readpos;
  247.   if (oldwritepos)         *oldwritepos = sound_parameters->writepos;
  248.   if (bufferstart)         *bufferstart = sound_parameters->startaddress;
  249.   if (buffersize)          *buffersize = sound_parameters->buffersize*2;
  250.   if (newflags != -1)      sound_parameters->flags = newflags;
  251.   if (newreadpos != -1)    sound_parameters->readpos = newreadpos;
  252.   if (newwritepos != -1)   sound_parameters->writepos = newwritepos;
  253.  
  254.   return 0;
  255. }
  256.