You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

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