10#include <miniaudio/miniaudio.hpp>
12class SoundDevice final
19 void Dummy(
void)
const {};
22 SoundDevice * m_pDevice;
23 ::std::vector<uint8_t> m_Data;
25 ma_uint64 m_Lenght = 0;
26 ma_uint64 m_CurrentPosition = 0;
29 Sound(SoundDevice * _pDevice, const ::std::string & _PathToFile) :
33 ma_decoder_init_file(_PathToFile.c_str(), &_pDevice->m_DecoderConfig, &m_Decoder);
34 if (Result != MA_SUCCESS)
36 throw ::std::runtime_error{
" ma_decoder_init_...() fail." };
40 ma_decoder_get_length_in_pcm_frames(&m_Decoder, &m_Lenght);
42 ::std::lock_guard<::std::mutex> lock(m_pDevice->m_Mutex);
43 m_pDevice->m_Decoders.push_back(
this);
46 Sound(SoundDevice * _pDevice, const ::std::vector<uint8_t> & _Data) :
50 const auto Result = ma_decoder_init_memory(m_Data.data(),
51 m_Data.size(), &_pDevice->m_DecoderConfig, &m_Decoder);
52 if (Result != MA_SUCCESS)
54 throw ::std::runtime_error{
" ma_decoder_init_...() fail." };
58 ma_decoder_get_length_in_pcm_frames(&m_Decoder, &m_Lenght);
60 ::std::lock_guard<::std::mutex> lock(m_pDevice->m_Mutex);
61 m_pDevice->m_Decoders.push_back(
this);
66 ::std::lock_guard<::std::mutex> lock(m_pDevice->m_Mutex);
67 const auto itThis = ::std::find(m_pDevice->m_Decoders.cbegin(),
68 m_pDevice->m_Decoders.cend(),
this);
69 m_pDevice->m_Decoders.erase(itThis);
70 ma_decoder_uninit(&m_Decoder);
76 ::std::shared_ptr<Sound> Make(
const T & _PathToFile)
78 return ::std::make_shared<Sound>(
this, _PathToFile);
86 ma_uint32 _FrameCount)
88 auto * pSoundDevice =
reinterpret_cast<SoundDevice *
>(_pDevice->pUserData);
89 if (pSoundDevice ==
nullptr)
return;
91 auto * pOutput =
reinterpret_cast<float *
>(_pOutput);
92 memset(pOutput, 0x00,
sizeof(
float) * _FrameCount * CHANNEL_COUNT);
94 ::std::vector<float> Buffer(_FrameCount * CHANNEL_COUNT, 0.0f);
96 ::std::lock_guard<::std::mutex> lock(pSoundDevice->m_Mutex);
98 for (
auto * pSound : pSoundDevice->m_Decoders)
100 ma_uint64 FrameCount = 0;
102 ma_decoder_read_pcm_frames(&pSound->m_Decoder, Buffer.data(), _FrameCount, &FrameCount);
107 pSound->m_CurrentPosition = 0;
110 const auto Result = ma_decoder_seek_to_pcm_frame(&pSound->m_Decoder, 0);
111 if (Result != MA_SUCCESS)
continue;
115 pSound->m_CurrentPosition += FrameCount;
118 for (::std::size_t i = 0; i < Buffer.size(); i++)
120 pOutput[i] += Buffer[i];
128 static const ma_uint32 CHANNEL_COUNT = 2;
129 const ma_decoder_config m_DecoderConfig;
130 ma_device_config m_DeviceConfig;
132 ::std::vector<Sound *> m_Decoders;
133 ::std::mutex m_Mutex;
137 m_DecoderConfig{ ma_decoder_config_init(ma_format_f32, CHANNEL_COUNT, 44100) },
138 m_DeviceConfig(ma_device_config_init(ma_device_type_playback))
140 m_DeviceConfig.playback.format = m_DecoderConfig.format;
141 m_DeviceConfig.playback.channels = m_DecoderConfig.channels;
142 m_DeviceConfig.sampleRate = m_DecoderConfig.sampleRate;
143 m_DeviceConfig.dataCallback = cbData;
144 m_DeviceConfig.pUserData =
this;
146 auto Result = ma_device_init(NULL, &m_DeviceConfig, &m_Device);
147 if (Result != MA_SUCCESS)
149 throw ::std::runtime_error{
"ma_device_init() fail." };
152 Result = ma_device_start(&m_Device);
153 if (Result != MA_SUCCESS)
155 throw ::std::runtime_error{
"ma_device_start() fail." };
160 ma_device_uninit(&m_Device);