blob: 754008ec4560801a5eb9fe0e405450d0d5e94b9c [file] [log] [blame] [edit]
#ifdef WITH_RIVE_AUDIO
#ifndef _RIVE_AUDIO_SOUND_HPP_
#define _RIVE_AUDIO_SOUND_HPP_
#include "miniaudio.h"
#include "rive/refcnt.hpp"
#include "rive/audio/audio_source.hpp"
namespace rive
{
class AudioEngine;
class Artboard;
struct ma_end_clipped_decoder
{
ma_data_source_base base;
ma_decoder decoder;
ma_uint64 frameCursor;
ma_uint64 endFrame;
};
static ma_result ma_end_clipped_decoder_read(ma_data_source* pDataSource,
void* pFramesOut,
ma_uint64 frameCount,
ma_uint64* pFramesRead)
{
ma_end_clipped_decoder* clipped = (ma_end_clipped_decoder*)pDataSource;
ma_result result = ma_decoder_read_pcm_frames(&clipped->decoder,
pFramesOut,
frameCount,
pFramesRead);
clipped->frameCursor += *pFramesRead;
if (clipped->frameCursor >= clipped->endFrame)
{
ma_uint64 overflow = clipped->frameCursor - clipped->endFrame;
if (*pFramesRead > overflow)
{
*pFramesRead -= overflow;
}
else
{
*pFramesRead = 0;
return MA_AT_END;
}
}
return result;
}
static ma_result ma_end_clipped_decoder_seek(ma_data_source* pDataSource,
ma_uint64 frameIndex)
{
ma_end_clipped_decoder* clipped = (ma_end_clipped_decoder*)pDataSource;
ma_result result =
ma_decoder_seek_to_pcm_frame(&clipped->decoder, frameIndex);
if (result != MA_SUCCESS)
{
return result;
}
clipped->frameCursor = frameIndex;
return result;
}
static ma_result ma_end_clipped_decoder_get_data_format(
ma_data_source* pDataSource,
ma_format* pFormat,
ma_uint32* pChannels,
ma_uint32* pSampleRate,
ma_channel* pChannelMap,
size_t channelMapCap)
{
ma_end_clipped_decoder* clipped = (ma_end_clipped_decoder*)pDataSource;
return ma_decoder_get_data_format(&clipped->decoder,
pFormat,
pChannels,
pSampleRate,
pChannelMap,
channelMapCap);
}
static ma_result ma_end_clipped_decoder_get_cursor(ma_data_source* pDataSource,
ma_uint64* pCursor)
{
ma_end_clipped_decoder* clipped = (ma_end_clipped_decoder*)pDataSource;
*pCursor = clipped->frameCursor;
return MA_SUCCESS;
}
static ma_result ma_end_clipped_decoder_get_length(ma_data_source* pDataSource,
ma_uint64* pLength)
{
ma_end_clipped_decoder* clipped = (ma_end_clipped_decoder*)pDataSource;
return ma_decoder_get_length_in_pcm_frames(&clipped->decoder, pLength);
}
static ma_data_source_vtable g_ma_end_clipped_decoder_vtable = {
ma_end_clipped_decoder_read,
ma_end_clipped_decoder_seek,
ma_end_clipped_decoder_get_data_format,
ma_end_clipped_decoder_get_cursor,
ma_end_clipped_decoder_get_length};
class AudioSound : public RefCnt<AudioSound>
{
friend class AudioEngine;
public:
bool seek(uint64_t timeInFrames);
~AudioSound();
void stop(uint64_t fadeTimeInFrames = 0);
float volume();
void volume(float value);
bool completed() const;
private:
AudioSound(AudioEngine* engine,
rcp<AudioSource> source,
Artboard* artboard);
ma_end_clipped_decoder* clippedDecoder() { return &m_decoder; }
ma_audio_buffer* buffer() { return &m_buffer; }
ma_sound* sound() { return &m_sound; }
void dispose();
ma_end_clipped_decoder m_decoder;
ma_audio_buffer m_buffer;
ma_sound m_sound;
rcp<AudioSource> m_source;
// This is storage used by the AudioEngine.
bool m_isDisposed;
rcp<AudioSound> m_nextPlaying;
rcp<AudioSound> m_prevPlaying;
AudioEngine* m_engine;
Artboard* m_artboard;
};
} // namespace rive
#endif
#endif