Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

203 строки
4.3 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstdlib>
  14. #include <cstdio>
  15. #include <cstring>
  16. #if __CELLOS_LV2__
  17. # include <cell/mstream.h> /* multistream */
  18. #elif defined USE_SDL_MIXER
  19. # if defined HAVE_SDL_SDL_H
  20. # include <SDL/SDL.h>
  21. # else
  22. # include <SDL.h>
  23. # endif
  24. # if defined HAVE_SDL_SDL_MIXER_H
  25. # include <SDL/SDL_mixer.h>
  26. # else
  27. # include <SDL_mixer.h>
  28. # endif
  29. #endif
  30. #include <lol/main.h>
  31. namespace lol
  32. {
  33. /*
  34. * Sample implementation class
  35. */
  36. class SampleData
  37. {
  38. friend class Sample;
  39. private:
  40. String m_name;
  41. #if __CELLOS_LV2__
  42. static void Callback(int stream, void *data, int type,
  43. void *write_buf, int buf_size)
  44. {
  45. UNUSED(write_buf, buf_size);
  46. switch (type)
  47. {
  48. case CELL_MS_CALLBACK_MOREDATA:
  49. /* For streamed sound */
  50. break;
  51. case CELL_MS_CALLBACK_CLOSESTREAM:
  52. case CELL_MS_CALLBACK_FINISHSTREAM:
  53. /* Finished playing */
  54. break;
  55. default:
  56. /* FIXME: we can't reach here */
  57. break;
  58. }
  59. }
  60. String m_data;
  61. int m_channel;
  62. #elif defined USE_SDL_MIXER
  63. Mix_Chunk *m_chunk;
  64. int m_channel;
  65. #endif
  66. };
  67. /*
  68. * Public Sample class
  69. */
  70. Sample::Sample(char const *path)
  71. : data(new SampleData())
  72. {
  73. data->m_name = String("<sample> ") + path;
  74. #if __CELLOS_LV2__
  75. array<String> pathlist = System::GetPathList(path);
  76. File f;
  77. for (int i = 0; i < pathlist.Count(); ++i)
  78. {
  79. f.Open(pathlist[i], FileAccess::Read);
  80. if (f.IsValid())
  81. {
  82. data->m_data = f.ReadString();
  83. f.Close();
  84. break;
  85. }
  86. }
  87. if (data->m_data.Count() == 0)
  88. {
  89. Log::Error("could not load sample %s\n", path);
  90. }
  91. #elif defined USE_SDL_MIXER
  92. array<String> pathlist = System::GetPathList(path);
  93. for (int i = 0; i < pathlist.Count(); ++i)
  94. {
  95. data->m_chunk = Mix_LoadWAV(pathlist[i].C());
  96. if (data->m_chunk)
  97. break;
  98. }
  99. if (!data->m_chunk)
  100. {
  101. Log::Error("could not load sample %s: %s\n", path, Mix_GetError());
  102. }
  103. data->m_channel = -1;
  104. #endif
  105. }
  106. Sample::~Sample()
  107. {
  108. #if __CELLOS_LV2__
  109. /* Nothing to do */
  110. #elif defined USE_SDL_MIXER
  111. if (data->m_chunk)
  112. Mix_FreeChunk(data->m_chunk);
  113. #endif
  114. delete data;
  115. }
  116. void Sample::TickGame(float seconds)
  117. {
  118. Entity::TickGame(seconds);
  119. }
  120. char const *Sample::GetName()
  121. {
  122. return data->m_name.C();
  123. }
  124. void Sample::Play()
  125. {
  126. #if __CELLOS_LV2__
  127. if (data->m_data.Count() <= 64 + 256)
  128. return;
  129. data->m_channel = cellMSStreamOpen();
  130. CellMSInfo mi;
  131. mi.SubBusGroup = CELL_MS_MASTER_BUS;
  132. mi.FirstBuffer = &data->m_data[0] + 64;
  133. /* FIXME: hardcoded crap */
  134. mi.FirstBufferSize = data->m_data.Count() - 64 - 256;
  135. mi.SecondBuffer = nullptr;
  136. mi.SecondBufferSize = 0;
  137. mi.Pitch = 44100;
  138. mi.numChannels = 2;
  139. mi.flags = CELL_MS_STREAM_AUTOCLOSE;
  140. mi.initialOffset = 0;
  141. mi.inputType = CELL_MS_16BIT_LITTLE;
  142. cellMSStreamSetInfo(data->m_channel, &mi);
  143. cellMSStreamSetCallbackFunc(data->m_channel, SampleData::Callback);
  144. cellMSCoreSetVolume1(data->m_channel, CELL_MS_DRY,
  145. CELL_MS_SPEAKER_FL, CELL_MS_CHANNEL_0, 1.0f);
  146. cellMSCoreSetVolume1(data->m_channel, CELL_MS_DRY,
  147. CELL_MS_SPEAKER_FR, CELL_MS_CHANNEL_0, 1.0f);
  148. cellMSStreamPlay(data->m_channel);
  149. #elif defined USE_SDL_MIXER
  150. if (data->m_chunk)
  151. data->m_channel = Mix_PlayChannel(-1, data->m_chunk, 0);
  152. #endif
  153. }
  154. void Sample::Loop()
  155. {
  156. #if __CELLOS_LV2__
  157. /* FIXME: not implemented */
  158. Play();
  159. #elif defined USE_SDL_MIXER
  160. if (data->m_chunk)
  161. data->m_channel = Mix_PlayChannel(-1, data->m_chunk, -1);
  162. #endif
  163. }
  164. void Sample::Stop()
  165. {
  166. #if __CELLOS_LV2__
  167. if (data->m_channel >= 0)
  168. cellMSStreamClose(data->m_channel);
  169. data->m_channel = -1;
  170. #elif defined USE_SDL_MIXER
  171. if (data->m_channel >= 0)
  172. Mix_HaltChannel(data->m_channel);
  173. data->m_channel = -1;
  174. #endif
  175. }
  176. } /* namespace lol */