home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / xmovie / audiodevice.C < prev    next >
C/C++ Source or Header  |  2000-11-29  |  5KB  |  247 lines

  1. #include "asset.h"
  2. #include "audiodevice.h"
  3.  
  4. #include <fcntl.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <sys/ioctl.h>
  8.  
  9. #ifndef OTHERAUDIO
  10. #include <sys/soundcard.h>
  11. #endif
  12.  
  13. #include <unistd.h>
  14.  
  15. AudioDevice::AudioDevice(Asset *asset) : Thread()
  16. {
  17.     this->asset = asset;
  18.     software_sync = 0;
  19.     total_samples_written = 0;
  20.     last_samples_written = 0;
  21.     playing_back = 0;
  22.     last_position = 0;
  23. }
  24.  
  25. AudioDevice::~AudioDevice()
  26. {
  27. }
  28.  
  29. int AudioDevice::set_software_sync(int value)
  30. {
  31.     this->software_sync = value;
  32.     return 0;
  33. }
  34.  
  35. long AudioDevice::get_fmt()
  36. {
  37. #ifndef OTHERAUDIO
  38.     return AFMT_S16_LE;
  39. #endif
  40.     return 0;
  41. }
  42.  
  43. int AudioDevice::start_playback()
  44. {
  45.     int format = get_fmt();
  46.     timer.update();
  47.     actual_buffer = 65536;
  48.  
  49. #ifndef OTHERAUDIO
  50.     audio_buf_info playinfo;
  51.  
  52.     dsp_out = open("/dev/dsp", O_WRONLY);
  53.     if(dsp_out < 0) 
  54.     {
  55.         printf("open odevice failed\n");
  56.         software_sync = 1;
  57.     }
  58.     else
  59.     {
  60.         if(ioctl(dsp_out, SNDCTL_DSP_SETFMT, &format) < 0) printf("SNDCTL_DSP_SETFMT failed\n");
  61.         if(ioctl(dsp_out, SNDCTL_DSP_CHANNELS, &asset->channels) < 0) printf("SNDCTL_DSP_CHANNELS failed\n");
  62.         if(ioctl(dsp_out, SNDCTL_DSP_SPEED, &asset->rate) < 0) printf("SNDCTL_DSP_SPEED failed\n");
  63.         ioctl(dsp_out, SNDCTL_DSP_GETOSPACE, &playinfo);
  64.         actual_buffer = playinfo.bytes / (asset->bits / 8) / asset->channels;
  65.     }
  66. #endif
  67.  
  68.     for(int i = 0; i < TOTAL_BUFFERS; i++)
  69.     {
  70.         output_lock[i].lock();
  71.         output_buffers[i] = 0;
  72.         buffer_len[i] = 0;
  73.     }
  74.  
  75.     Thread::synchronous = 1;
  76.     playing_back = 1;
  77.     last_position = 0;
  78.     current_inbuffer = 0;
  79.     current_outbuffer = 0;
  80.     done = 0;
  81.     start();
  82.     return actual_buffer;
  83. }
  84.  
  85. int AudioDevice::interrupt_playback()
  86. {
  87.     if(playing_back)
  88.     {
  89.         done = 1;
  90.         Thread::end();
  91.  
  92.         for(int i = 0; i < TOTAL_BUFFERS; i++)
  93.             input_lock[i].unlock();
  94.     }
  95.     return 0;
  96. }
  97.  
  98. int AudioDevice::stop_playback()
  99. {
  100.     Thread::join();
  101.     reset();
  102.     playing_back = 0;
  103.     return 0;
  104. }
  105.  
  106. int AudioDevice::reset()
  107. {
  108. #ifndef OTHERAUDIO
  109.     ioctl(dsp_out, SNDCTL_DSP_RESET, 0);
  110.     close(dsp_out);
  111. #endif
  112.  
  113.     for(int i = 0; i < TOTAL_BUFFERS; i++)
  114.     {
  115.         if(output_buffers[i]) delete output_buffers[i];
  116.         output_buffers[i] = 0;
  117.     }
  118.     return 0;
  119. }
  120.  
  121. long AudioDevice::samples_rendered()
  122. {
  123.     static long result;
  124.  
  125. #ifndef OTHERAUDIO
  126.     count_info info;
  127. #endif
  128.  
  129.     if(playing_back)
  130.     {
  131.         if(software_sync)
  132.         {
  133.             timer_lock.lock();
  134.             result = total_samples_written - last_samples_written - 
  135.                 actual_buffer;
  136.             result += timer.get_scaled_difference(asset->rate);
  137.  
  138. //printf("AudioDevice::samples_rendered %ld - %ld - %ld + %ld = %ld\n", total_samples_written, last_samples_written, actual_buffer, timer.get_scaled_difference(asset->rate), result);
  139.             if(result < 0) result = 0;
  140.             timer_lock.unlock();
  141.  
  142.             if(result < last_position) 
  143.             result = last_position;
  144.             else
  145.             last_position = result;
  146.  
  147.             return result;
  148.         }
  149.         else
  150.         {
  151. #ifndef OTHERAUDIO
  152.             if(!ioctl(dsp_out, SNDCTL_DSP_GETOPTR, &info))
  153.             {
  154.                 result = info.bytes / (asset->bits / 8) / asset->channels;
  155.                 return result;
  156.             }
  157.             return 0;
  158. #endif
  159.         }
  160.     }
  161.     else
  162.         return total_samples_written;
  163. }
  164.  
  165. int AudioDevice::write_audio(char *buffer, long samples)
  166. {
  167.     if(done) return 1;
  168.     input_lock[current_inbuffer].lock();
  169.     if(done) return 1;
  170.     long bytes = samples_to_bytes(samples);
  171.  
  172.     allocate_buffer(current_inbuffer, samples);
  173.     buffer_len[current_inbuffer] = samples;
  174.  
  175.     if(buffer)
  176.     {
  177.         for(int i = 0; i < bytes; i++)
  178.         {
  179.             output_buffers[current_inbuffer][i] = buffer[i];
  180.         }
  181.     }
  182.  
  183.     output_lock[current_inbuffer].unlock();
  184.     current_inbuffer = next_buffer(current_inbuffer);
  185.     return 0;
  186. }
  187.  
  188. void AudioDevice::run()
  189. {
  190.     while(!done && playing_back)
  191.     {
  192.         output_lock[current_outbuffer].lock();
  193.         if(buffer_len[current_outbuffer] && !done)
  194.         {
  195.             total_samples_written += buffer_len[current_outbuffer];
  196.             last_samples_written = buffer_len[current_outbuffer];
  197.             timer_lock.lock();
  198.             timer.update();
  199.             timer_lock.unlock();
  200.  
  201. #ifndef OTHERAUDIO
  202.             if(write(dsp_out, output_buffers[current_outbuffer], 
  203.                 samples_to_bytes(buffer_len[current_outbuffer])) < 0)
  204.                     sleep(1);
  205. #else
  206.             sleep(1);
  207. #endif
  208.         }
  209.         else
  210.             done = 1;  // No more buffers
  211.  
  212.         input_lock[current_outbuffer].unlock();
  213.         current_outbuffer = next_buffer(current_outbuffer);
  214.     }
  215.  
  216. #ifndef OTHERAUDIO
  217.     ioctl(dsp_out, SNDCTL_DSP_SYNC, 0);
  218. #endif
  219. }
  220.  
  221. int AudioDevice::next_buffer(int buffer_num)
  222. {
  223.     buffer_num++;
  224.     if(buffer_num == TOTAL_BUFFERS) buffer_num = 0;
  225.     return buffer_num;
  226. }
  227.  
  228. int AudioDevice::allocate_buffer(int buffer_num, long size)
  229. {
  230.     if(size > buffer_len[buffer_num] && output_buffers[buffer_num])
  231.     {
  232.         delete output_buffers[buffer_num];
  233.         output_buffers[buffer_num] = 0;
  234.     }
  235.     
  236.     if(!output_buffers[buffer_num])
  237.     {
  238.         output_buffers[buffer_num] = new char[samples_to_bytes(size)];
  239.     }
  240.     return 0;
  241. }
  242.  
  243. long AudioDevice::samples_to_bytes(long samples)
  244. {
  245.     return samples * asset->bits / 8 * asset->channels;
  246. }
  247.