b3SoundEngine.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #include "b3SoundEngine.h"
  2. #include "RtAudio.h"
  3. #include "b3AudioListener.h"
  4. #include "b3SoundSource.h"
  5. #include "Bullet3Common/b3AlignedObjectArray.h"
  6. #include "b3ReadWavFile.h"
  7. #include "../Utils/b3ResourcePath.h"
  8. #include "Bullet3Common/b3HashMap.h"
  9. // The default real-time audio input and output buffer size. If
  10. // clicks are occuring in the input and/or output sound stream, a
  11. // larger buffer size may help. Larger buffer sizes, however, produce
  12. // more latency.
  13. //const unsigned int RT_BUFFER_SIZE = 1024;
  14. const unsigned int RT_BUFFER_SIZE = 256;
  15. struct b3SoundEngineInternalData
  16. {
  17. b3AudioListener m_listener;
  18. RtAudio m_dac;
  19. bool m_useRealTimeDac;
  20. b3AlignedObjectArray<b3SoundSource*> m_soundSources;
  21. b3HashMap<b3HashInt, b3ReadWavFile*> m_wavFiles;
  22. b3HashMap<b3HashString, int> m_name2wav;
  23. int m_wavFileUidGenerator;
  24. b3SoundEngineInternalData()
  25. : m_useRealTimeDac(false),
  26. m_wavFileUidGenerator(123)
  27. {
  28. }
  29. };
  30. b3SoundEngine::b3SoundEngine()
  31. {
  32. m_data = new b3SoundEngineInternalData();
  33. }
  34. b3SoundEngine::~b3SoundEngine()
  35. {
  36. exit();
  37. delete m_data;
  38. }
  39. void b3SoundEngine::init(int maxNumSoundSources, bool useRealTimeDac)
  40. {
  41. for (int i = 0; i < maxNumSoundSources; i++)
  42. {
  43. b3SoundSource* source = new b3SoundSource();
  44. m_data->m_soundSources.push_back(source);
  45. m_data->m_listener.addSoundSource(source);
  46. }
  47. this->m_data->m_useRealTimeDac = useRealTimeDac;
  48. if (useRealTimeDac)
  49. {
  50. RtAudioFormat format = (sizeof(double) == 8) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
  51. RtAudio::StreamParameters parameters;
  52. parameters.deviceId = m_data->m_dac.getDefaultOutputDevice();
  53. parameters.nChannels = 2;
  54. unsigned int bufferFrames = RT_BUFFER_SIZE;
  55. double sampleRate = m_data->m_listener.getSampleRate();
  56. m_data->m_dac.openStream(&parameters, NULL, format, (unsigned int)sampleRate, &bufferFrames, &b3AudioListener::tick,
  57. (void*)m_data->m_listener.getTickData());
  58. m_data->m_dac.startStream();
  59. }
  60. }
  61. void b3SoundEngine::exit()
  62. {
  63. m_data->m_dac.closeStream();
  64. m_data->m_useRealTimeDac = false;
  65. for (int i = 0; i < m_data->m_soundSources.size(); i++)
  66. {
  67. m_data->m_listener.removeSoundSource(m_data->m_soundSources[i]);
  68. m_data->m_soundSources[i]->stopSound();
  69. delete m_data->m_soundSources[i];
  70. }
  71. m_data->m_soundSources.clear();
  72. for (int i = 0; i < m_data->m_wavFiles.size(); i++)
  73. {
  74. b3ReadWavFile** wavPtr = m_data->m_wavFiles.getAtIndex(i);
  75. if (wavPtr && *wavPtr)
  76. {
  77. b3ReadWavFile* wav = *wavPtr;
  78. delete wav;
  79. }
  80. }
  81. m_data->m_wavFiles.clear();
  82. m_data->m_name2wav.clear();
  83. }
  84. int b3SoundEngine::getAvailableSoundSource()
  85. {
  86. for (int i = 0; i < m_data->m_soundSources.size(); i++)
  87. {
  88. if (m_data->m_soundSources[i]->isAvailable())
  89. {
  90. return i;
  91. }
  92. }
  93. return -1;
  94. }
  95. void b3SoundEngine::startSound(int soundSourceIndex, b3SoundMessage msg)
  96. {
  97. b3SoundSource* soundSource = m_data->m_soundSources[soundSourceIndex];
  98. soundSource->setOscillatorAmplitude(0, msg.m_amplitude);
  99. soundSource->setOscillatorAmplitude(1, msg.m_amplitude);
  100. soundSource->setADSR(msg.m_attackRate, msg.m_decayRate, msg.m_sustainLevel, msg.m_releaseRate);
  101. switch (msg.m_type)
  102. {
  103. case B3_SOUND_SOURCE_SINE_OSCILLATOR:
  104. {
  105. soundSource->setOscillatorFrequency(0, msg.m_frequency);
  106. soundSource->setOscillatorFrequency(1, msg.m_frequency);
  107. soundSource->startSound(msg.m_autoKeyOff);
  108. break;
  109. }
  110. case B3_SOUND_SOURCE_WAV_FILE:
  111. {
  112. b3ReadWavFile** wavFilePtr = m_data->m_wavFiles[msg.m_wavId];
  113. if (wavFilePtr)
  114. {
  115. b3ReadWavFile* wavFile = *wavFilePtr;
  116. soundSource->setWavFile(0, wavFile, getSampleRate());
  117. soundSource->setWavFile(1, wavFile, getSampleRate());
  118. soundSource->startSound(msg.m_autoKeyOff);
  119. }
  120. break;
  121. }
  122. default:
  123. {
  124. }
  125. }
  126. }
  127. void b3SoundEngine::releaseSound(int soundSourceIndex)
  128. {
  129. b3SoundSource* soundSource = m_data->m_soundSources[soundSourceIndex];
  130. soundSource->stopSound();
  131. }
  132. int b3SoundEngine::loadWavFile(const char* fileName)
  133. {
  134. int* wavUidPtr = m_data->m_name2wav[fileName];
  135. if (wavUidPtr)
  136. {
  137. return *wavUidPtr;
  138. }
  139. char resourcePath[1024];
  140. if (b3ResourcePath::findResourcePath(fileName, resourcePath, 1024, 0))
  141. {
  142. b3ReadWavFile* wavFile = new b3ReadWavFile();
  143. wavFile->getWavInfo(resourcePath);
  144. wavFile->resize();
  145. wavFile->read(0, true);
  146. wavFile->normalize(1);
  147. int wavUID = m_data->m_wavFileUidGenerator++;
  148. m_data->m_wavFiles.insert(wavUID, wavFile);
  149. m_data->m_name2wav.insert(fileName, wavUID);
  150. return wavUID;
  151. }
  152. return 0;
  153. }
  154. double b3SoundEngine::getSampleRate() const
  155. {
  156. return m_data->m_listener.getSampleRate();
  157. }