您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

205 行
4.4 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 "core.h"
  31. using namespace std;
  32. namespace lol
  33. {
  34. /*
  35. * Sample implementation class
  36. */
  37. class SampleData
  38. {
  39. friend class Sample;
  40. private:
  41. String m_name;
  42. #if __CELLOS_LV2__
  43. static void Callback(int stream, void *data, int type,
  44. void *write_buf, int buf_size)
  45. {
  46. UNUSED(write_buf, buf_size);
  47. switch (type)
  48. {
  49. case CELL_MS_CALLBACK_MOREDATA:
  50. /* For streamed sound */
  51. break;
  52. case CELL_MS_CALLBACK_CLOSESTREAM:
  53. case CELL_MS_CALLBACK_FINISHSTREAM:
  54. /* Finished playing */
  55. break;
  56. default:
  57. /* FIXME: we can't reach here */
  58. break;
  59. }
  60. }
  61. String m_data;
  62. int m_channel;
  63. #elif defined USE_SDL_MIXER
  64. Mix_Chunk *m_chunk;
  65. int m_channel;
  66. #endif
  67. };
  68. /*
  69. * Public Sample class
  70. */
  71. Sample::Sample(char const *path)
  72. : data(new SampleData())
  73. {
  74. data->m_name = String("<sample> ") + path;
  75. #if __CELLOS_LV2__
  76. Array<String> pathlist = System::GetPathList(path);
  77. File f;
  78. for (int i = 0; i < pathlist.Count(); ++i)
  79. {
  80. f.Open(pathlist[i], FileAccess::Read);
  81. if (f.IsValid())
  82. {
  83. data->m_data = f.ReadString();
  84. f.Close();
  85. break;
  86. }
  87. }
  88. if (data->m_data.Count() == 0)
  89. {
  90. Log::Error("could not load sample %s\n", path);
  91. }
  92. #elif defined USE_SDL_MIXER
  93. Array<String> pathlist = System::GetPathList(path);
  94. for (int i = 0; i < pathlist.Count(); ++i)
  95. {
  96. data->m_chunk = Mix_LoadWAV(pathlist[i].C());
  97. if (data->m_chunk)
  98. break;
  99. }
  100. if (!data->m_chunk)
  101. {
  102. Log::Error("could not load sample %s: %s\n", path, Mix_GetError());
  103. }
  104. data->m_channel = -1;
  105. #endif
  106. }
  107. Sample::~Sample()
  108. {
  109. #if __CELLOS_LV2__
  110. /* Nothing to do */
  111. #elif defined USE_SDL_MIXER
  112. if (data->m_chunk)
  113. Mix_FreeChunk(data->m_chunk);
  114. #endif
  115. delete data;
  116. }
  117. void Sample::TickGame(float seconds)
  118. {
  119. Entity::TickGame(seconds);
  120. }
  121. char const *Sample::GetName()
  122. {
  123. return data->m_name.C();
  124. }
  125. void Sample::Play()
  126. {
  127. #if __CELLOS_LV2__
  128. if (data->m_data.Count() <= 64 + 256)
  129. return;
  130. data->m_channel = cellMSStreamOpen();
  131. CellMSInfo mi;
  132. mi.SubBusGroup = CELL_MS_MASTER_BUS;
  133. mi.FirstBuffer = &data->m_data[0] + 64;
  134. /* FIXME: hardcoded crap */
  135. mi.FirstBufferSize = data->m_data.Count() - 64 - 256;
  136. mi.SecondBuffer = nullptr;
  137. mi.SecondBufferSize = 0;
  138. mi.Pitch = 44100;
  139. mi.numChannels = 2;
  140. mi.flags = CELL_MS_STREAM_AUTOCLOSE;
  141. mi.initialOffset = 0;
  142. mi.inputType = CELL_MS_16BIT_LITTLE;
  143. cellMSStreamSetInfo(data->m_channel, &mi);
  144. cellMSStreamSetCallbackFunc(data->m_channel, SampleData::Callback);
  145. cellMSCoreSetVolume1(data->m_channel, CELL_MS_DRY,
  146. CELL_MS_SPEAKER_FL, CELL_MS_CHANNEL_0, 1.0f);
  147. cellMSCoreSetVolume1(data->m_channel, CELL_MS_DRY,
  148. CELL_MS_SPEAKER_FR, CELL_MS_CHANNEL_0, 1.0f);
  149. cellMSStreamPlay(data->m_channel);
  150. #elif defined USE_SDL_MIXER
  151. if (data->m_chunk)
  152. data->m_channel = Mix_PlayChannel(-1, data->m_chunk, 0);
  153. #endif
  154. }
  155. void Sample::Loop()
  156. {
  157. #if __CELLOS_LV2__
  158. /* FIXME: not implemented */
  159. Play();
  160. #elif defined USE_SDL_MIXER
  161. if (data->m_chunk)
  162. data->m_channel = Mix_PlayChannel(-1, data->m_chunk, -1);
  163. #endif
  164. }
  165. void Sample::Stop()
  166. {
  167. #if __CELLOS_LV2__
  168. if (data->m_channel >= 0)
  169. cellMSStreamClose(data->m_channel);
  170. data->m_channel = -1;
  171. #elif defined USE_SDL_MIXER
  172. if (data->m_channel >= 0)
  173. Mix_HaltChannel(data->m_channel);
  174. data->m_channel = -1;
  175. #endif
  176. }
  177. } /* namespace lol */