stream.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include "music/stream.hh"
  9. #include "loaders/wav_load.hh"
  10. #include "file/file.hh"
  11. #include "sound/sound.hh"
  12. #include "error/error.hh"
  13. #include <memory.h>
  14. void i4_wav_callback(w32 count, void *context)
  15. {
  16. ((i4_stream_wav_player *)context)->PRIVATE_callback(count);
  17. }
  18. void i4_stream_wav_player::set_volume(i4_volume vol)
  19. {
  20. if (voice)
  21. voice->set_volume(vol);
  22. }
  23. // loads more data from disk or clears the buffer
  24. void i4_stream_wav_player::load_buffer(i4_bool async)
  25. {
  26. wait_read = i4_F;
  27. prev_total = 0;
  28. if (async)
  29. {
  30. wait_read = i4_T; //we're waiting for this read to finish now
  31. if (!fp->async_read(locked_buffer_start, locked_buffer_size, i4_wav_callback, this))
  32. {
  33. wait_read = i4_F;
  34. i4_warning("i4_stream_wav_player::async read failed");
  35. i4_wav_callback(fp->read(locked_buffer_start, locked_buffer_size), this);
  36. }
  37. }
  38. else
  39. i4_wav_callback(fp->read(locked_buffer_start, locked_buffer_size), this);
  40. }
  41. i4_stream_wav_player::i4_stream_wav_player(i4_file_class *_fp,
  42. w32 _buf_size,
  43. i4_bool _loop,
  44. i4_bool first_load_is_async,
  45. i4_bool _3d_capable)
  46. {
  47. fp = _fp;
  48. loop = _loop;
  49. buf_size = _buf_size;
  50. first_time = i4_T;
  51. file_finished = i4_F;
  52. voice = 0;
  53. // don't bother if there is no sound
  54. if (i4_sound_man==&i4_null_sound)
  55. return ;
  56. i4_sound_info info;
  57. if (i4_load_wav_info(fp, info))
  58. {
  59. total_size = info.size;
  60. if (info.size <= buf_size)
  61. {
  62. buf_size = info.size;
  63. fits_in_memory = i4_T;
  64. }
  65. else
  66. fits_in_memory = i4_F;
  67. if (_3d_capable)
  68. first_time = i4_F;
  69. i4_sound_manager_class::sound_parameters p(info.sample_rate,
  70. info.channels,
  71. info.sample_size,
  72. I4_SOUND_VOLUME_LEVELS-1,
  73. 0, // pan = 0
  74. (loop || !fits_in_memory), // loop ones that dont fit in memory
  75. 0, // no reverb
  76. i4_T, // turn on streaming
  77. _3d_capable); // 3d capable
  78. voice = i4_sound_man->alloc(buf_size, p);
  79. if (voice)
  80. {
  81. start_file_offset = fp->tell();
  82. total_read = 0;
  83. last_read = SECOND_HALF;
  84. //poll() will see that the second half has already been read, wont read in
  85. //the first half until the play cursor gets halfway into the buffer
  86. voice->lock(0, buf_size, locked_buffer_start, locked_buffer_size, unused1, unused2);
  87. load_buffer(first_load_is_async);
  88. }
  89. }
  90. }
  91. //be careful in this function, its recursive (although, it recurses in a different thread)
  92. //but watch out for how you manipulate the variable wait_read
  93. void i4_stream_wav_player::PRIVATE_callback(w32 count)
  94. {
  95. total_read += count;
  96. if (total_read > total_size)
  97. {
  98. count -= (total_read - total_size); //we really only read this many *valid* bytes
  99. total_read = total_size;
  100. }
  101. if (count + prev_total < locked_buffer_size)
  102. {
  103. // we reached the end of the sample data
  104. if (loop)
  105. {
  106. //start back at the beginning
  107. fp->seek(start_file_offset);
  108. total_read = 0;
  109. prev_total += count;
  110. if (!fp->async_read(((w8 *)locked_buffer_start) + prev_total, locked_buffer_size - prev_total, i4_wav_callback, this))
  111. {
  112. wait_read = i4_F;
  113. i4_warning("i4_stream_wav_player::async read failed");
  114. i4_wav_callback(fp->read(((w8 *)locked_buffer_start) + prev_total, locked_buffer_size - prev_total), this);
  115. }
  116. }
  117. else
  118. {
  119. //indicate that we're done
  120. file_finished = i4_T;
  121. //set the remaining part of the buffer to 0
  122. w8 *start_clearing_here = (w8 *)locked_buffer_start + count;
  123. memset(start_clearing_here, 0, locked_buffer_size - count);
  124. voice->unlock(locked_buffer_start, locked_buffer_size, unused1, unused2);
  125. finish_pos = count;
  126. wait_read = i4_F;
  127. }
  128. }
  129. else
  130. {
  131. if (fits_in_memory)
  132. {
  133. file_finished = i4_T;
  134. finish_pos = total_size;
  135. }
  136. voice->unlock(locked_buffer_start, locked_buffer_size, unused1, unused2);
  137. wait_read = i4_F;
  138. }
  139. if (first_time) // if this was the first load, we need to start playing the sound
  140. {
  141. voice->play();
  142. first_time = i4_F;
  143. }
  144. }
  145. void i4_stream_wav_player::pause()
  146. {
  147. if (voice && voice->is_playing())
  148. voice->stop();
  149. }
  150. void i4_stream_wav_player::unpause()
  151. {
  152. if (voice && !voice->is_playing())
  153. voice->play();
  154. }
  155. i4_bool i4_stream_wav_player::poll()
  156. {
  157. if (!voice)
  158. return i4_F;
  159. if (wait_read) // if we are waiting for a read to finish or init failed
  160. return i4_T;
  161. if (fits_in_memory && loop)
  162. return i4_T;
  163. w32 pos = voice->get_sound_position();
  164. if (!file_finished && !fits_in_memory)
  165. {
  166. if (pos > buf_size/2 && last_read!=FIRST_HALF)
  167. {
  168. //read more into the first half of the buffer
  169. voice->lock(0, buf_size/2, locked_buffer_start, locked_buffer_size, unused1, unused2);
  170. last_read = FIRST_HALF;
  171. load_buffer();
  172. }
  173. else
  174. if (pos < buf_size/2 && last_read != SECOND_HALF)
  175. {
  176. //read more into the second half of the buffer
  177. voice->lock(buf_size/2, buf_size/2, locked_buffer_start, locked_buffer_size, unused1, unused2);
  178. last_read = SECOND_HALF;
  179. load_buffer();
  180. }
  181. }
  182. else
  183. {
  184. if (!voice->is_playing())
  185. return i4_F;
  186. if (pos < buf_size/2)
  187. {
  188. if (last_read==FIRST_HALF)
  189. {
  190. if (pos >= finish_pos)
  191. {
  192. voice->stop();
  193. return i4_F;
  194. }
  195. }
  196. }
  197. else
  198. {
  199. if (last_read==SECOND_HALF)
  200. {
  201. if (pos >= finish_pos+buf_size/2)
  202. {
  203. voice->stop();
  204. return i4_F;
  205. }
  206. }
  207. }
  208. }
  209. return i4_T;
  210. }
  211. i4_stream_wav_player::~i4_stream_wav_player()
  212. {
  213. if (voice)
  214. {
  215. while (wait_read); // if we need to wait for an async read to finish
  216. i4_sound_man->free_voice(voice);
  217. voice = 0;
  218. }
  219. if (fp)
  220. {
  221. delete fp;
  222. fp = 0;
  223. }
  224. }