Skip to content

Commit

Permalink
Audio asset volume + VU
Browse files Browse the repository at this point in the history
This also fixes a bug where multiple sounds would play at the same time making clipping even worse...

Some more details here:

https://2dimensions.slack.com/archives/CHMAP278R/p1712443028936919

Diffs=
f832e2617 Audio asset volume + VU (#6985)

Co-authored-by: Luigi Rosso <[email protected]>
  • Loading branch information
luigi-rosso and luigi-rosso committed Apr 7, 2024
1 parent 40cc4f8 commit a96799e
Show file tree
Hide file tree
Showing 17 changed files with 506 additions and 61 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
522a31bc24b4f8179b9a4f27d9a8154af385767a
f832e26172cfbd11d52114ebb667e13418a5b1cd
2 changes: 1 addition & 1 deletion build/rive_build_config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ do
staticruntime('on') -- Match Skia's /MT flag for link compatibility
runtime('Release') -- Use /MT even in debug (/MTd is incompatible with Skia)
architecture('x64')
defines({ '_USE_MATH_DEFINES' })
defines({ '_USE_MATH_DEFINES', 'NOMINMAX' })
end

filter({ 'system:windows', 'options:toolset=clang' })
Expand Down
16 changes: 15 additions & 1 deletion dev/core_generator/lib/src/definition.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,24 @@ class Definition {
properties.where((property) => property.getExportType().storesData);

Definition? _extensionOf;
Definition? _rawExtensionOf;
Key? _key;
bool _isAbstract = false;
bool _editorOnly = false;
bool _forRuntime = true;
bool get forRuntime => _forRuntime;

Definition? getRuntimeExtensionOf(Definition? definition) {
var extensionOf = definition;
if (extensionOf != null) {
if (extensionOf._forRuntime) {
return extensionOf;
}
return getRuntimeExtensionOf(extensionOf._extensionOf);
}
return extensionOf;
}

static Definition? make(String filename) {
var definition = definitions[filename];
if (definition != null) {
Expand All @@ -61,7 +74,8 @@ class Definition {
Definition.fromFilename(this._filename, Map<String, dynamic> data) {
dynamic extendsFilename = data['extends'];
if (extendsFilename is String) {
_extensionOf = Definition.make(extendsFilename);
_rawExtensionOf = Definition.make(extendsFilename);
_extensionOf = getRuntimeExtensionOf(_rawExtensionOf);
}
dynamic nameValue = data['name'];
if (nameValue is String) {
Expand Down
11 changes: 0 additions & 11 deletions dev/defs/artboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,6 @@
"description": "List of selected animations",
"runtime": false,
"coop": false
},
"viewModelId": {
"type": "Id",
"typeRuntime": "uint",
"initialValue": "Core.missingId",
"initialValueRuntime": "-1",
"key": {
"int": 434,
"string": "viewmodelid"
},
"description": "The view model attached to this artboard data context."
}
}
}
54 changes: 53 additions & 1 deletion dev/defs/assets/audio_asset.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,57 @@
"int": 406,
"string": "audioasset"
},
"extends": "assets/file_asset.json"
"extends": "assets/export_audio.json",
"properties": {
"sampleRate": {
"type": "uint",
"initialValue": "0",
"key": {
"int": 473,
"string": "samplerate"
},
"description": "Sample rate of the source audio file.",
"runtime": false
},
"channels": {
"type": "uint",
"initialValue": "0",
"key": {
"int": 474,
"string": "channels"
},
"description": "Channel count of the source audio file.",
"runtime": false
},
"durationSeconds": {
"type": "double",
"initialValue": "0",
"key": {
"int": 475,
"string": "durationseconds"
},
"description": "Duration in seconds of the source audio file.",
"runtime": false
},
"formatValue": {
"type": "uint",
"initialValue": "0",
"key": {
"int": 476,
"string": "formatvalue"
},
"description": "Container format value of the source audio file.",
"runtime": false
},
"isCustom": {
"type": "bool",
"initialValue": "true",
"key": {
"int": 426,
"string": "iscustom"
},
"description": "True if a custom asset, i.e the user has uploaded it",
"runtime": false
}
}
}
40 changes: 40 additions & 0 deletions dev/defs/assets/export_audio.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "ExportAudio",
"key": {
"int": 422,
"string": "exportaudio"
},
"abstract": true,
"extends": "assets/file_asset.json",
"properties": {
"exportFormatValue": {
"type": "uint",
"initialValue": "0",
"key": {
"int": 527,
"string": "formatvalue"
},
"description": "Start seconds of this clip",
"runtime": false
},
"exportQualityValue": {
"type": "uint",
"initialValue": "0",
"key": {
"int": 528,
"string": "qualityvalue"
},
"description": "Start seconds of this clip",
"runtime": false
},
"volume": {
"type": "double",
"initialValue": "1",
"key": {
"int": 530,
"string": "volume"
},
"description": "Volume applied to all instances of this audio asset."
}
}
}
1 change: 1 addition & 0 deletions dev/test/premake5.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defines({
'WITH_RIVE_TOOLS',
'WITH_RIVE_TEXT',
'WITH_RIVE_AUDIO',
'WITH_RIVE_AUDIO_TOOLS',
})

dofile(path.join(path.getabsolute('../../'), 'premake5_v2.lua'))
Expand Down
13 changes: 13 additions & 0 deletions include/rive/assets/export_audio.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef _RIVE_EXPORT_AUDIO_HPP_
#define _RIVE_EXPORT_AUDIO_HPP_
#include "rive/generated/assets/export_audio_base.hpp"
#include <stdio.h>
namespace rive
{
class ExportAudio : public ExportAudioBase
{
public:
};
} // namespace rive

#endif
19 changes: 15 additions & 4 deletions include/rive/audio/audio_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@
typedef struct ma_engine ma_engine;
typedef struct ma_sound ma_sound;
typedef struct ma_device ma_device;
typedef struct ma_node_base ma_node_base;

namespace rive
{
class AudioSound;
class AudioSource;

class LevelsNode;
class AudioEngine : public RefCnt<AudioEngine>
{
friend class AudioSound;
friend class AudioSource;
friend class LevelsNode;

public:
static const uint32_t defaultNumChannels = 2;
Expand Down Expand Up @@ -48,17 +50,26 @@ class AudioEngine : public RefCnt<AudioEngine>
bool sumAudioFrames(float* frames, uint64_t numFrames);
#endif

#ifdef WITH_RIVE_AUDIO_TOOLS
void initLevelMonitor();
void levels(Span<float> levels);
float level(uint32_t channel);
#endif

private:
AudioEngine(ma_engine* engine);
ma_device* m_device;
ma_engine* m_engine;

std::vector<rcp<AudioSound>> m_completedSounds;

void completeSound(rcp<AudioSound> sound);
void purgeCompletedSounds();
rcp<AudioSound> m_playingSoundsHead;
static void SoundCompleted(void* pUserData, ma_sound* pSound);

#ifdef WITH_RIVE_AUDIO_TOOLS
void measureLevels(const float* frames, uint32_t frameCount);
std::vector<float> m_levels;
LevelsNode* m_levelMonitor = nullptr;
#endif
#ifdef EXTERNAL_RIVE_AUDIO_ENGINE
std::vector<float> m_readFrames;
#endif
Expand Down
19 changes: 13 additions & 6 deletions include/rive/audio/audio_sound.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,26 @@ class AudioSound : public RefCnt<AudioSound>
bool seek(uint64_t timeInFrames);
~AudioSound();
void stop(uint64_t fadeTimeInFrames = 0);
float volume();
void volume(float value);
bool completed() const;

private:
AudioSound(rcp<AudioEngine> engine);
void complete();
AudioSound(AudioEngine* engine);
ma_decoder* decoder() { return &m_decoder; }
ma_audio_buffer* buffer() { return &m_buffer; }
ma_sound* sound() { return &m_sound; }
void dispose();

rcp<AudioEngine> m_engine;
ma_decoder m_decoder;
ma_audio_buffer m_buffer;
ma_sound m_sound;

ma_decoder* decoder() { return &m_decoder; }
ma_audio_buffer* buffer() { return &m_buffer; }
ma_sound* sound() { return &m_sound; }
// This is storage used by the AudioEngine.
bool m_isDisposed;
rcp<AudioSound> m_nextPlaying;
rcp<AudioSound> m_prevPlaying;
AudioEngine* m_engine;
};
} // namespace rive

Expand Down
7 changes: 4 additions & 3 deletions include/rive/generated/assets/audio_asset_base.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#ifndef _RIVE_AUDIO_ASSET_BASE_HPP_
#define _RIVE_AUDIO_ASSET_BASE_HPP_
#include "rive/assets/file_asset.hpp"
#include "rive/assets/export_audio.hpp"
namespace rive
{
class AudioAssetBase : public FileAsset
class AudioAssetBase : public ExportAudio
{
protected:
typedef FileAsset Super;
typedef ExportAudio Super;

public:
static const uint16_t typeKey = 406;
Expand All @@ -18,6 +18,7 @@ class AudioAssetBase : public FileAsset
switch (typeKey)
{
case AudioAssetBase::typeKey:
case ExportAudioBase::typeKey:
case FileAssetBase::typeKey:
case AssetBase::typeKey:
return true;
Expand Down
71 changes: 71 additions & 0 deletions include/rive/generated/assets/export_audio_base.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#ifndef _RIVE_EXPORT_AUDIO_BASE_HPP_
#define _RIVE_EXPORT_AUDIO_BASE_HPP_
#include "rive/assets/file_asset.hpp"
#include "rive/core/field_types/core_double_type.hpp"
namespace rive
{
class ExportAudioBase : public FileAsset
{
protected:
typedef FileAsset Super;

public:
static const uint16_t typeKey = 422;

/// Helper to quickly determine if a core object extends another without RTTI
/// at runtime.
bool isTypeOf(uint16_t typeKey) const override
{
switch (typeKey)
{
case ExportAudioBase::typeKey:
case FileAssetBase::typeKey:
case AssetBase::typeKey:
return true;
default:
return false;
}
}

uint16_t coreType() const override { return typeKey; }

static const uint16_t volumePropertyKey = 530;

private:
float m_Volume = 1.0f;

public:
inline float volume() const { return m_Volume; }
void volume(float value)
{
if (m_Volume == value)
{
return;
}
m_Volume = value;
volumeChanged();
}

void copy(const ExportAudioBase& object)
{
m_Volume = object.m_Volume;
FileAsset::copy(object);
}

bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
{
switch (propertyKey)
{
case volumePropertyKey:
m_Volume = CoreDoubleType::deserialize(reader);
return true;
}
return FileAsset::deserialize(propertyKey, reader);
}

protected:
virtual void volumeChanged() {}
};
} // namespace rive

#endif
Loading

0 comments on commit a96799e

Please sign in to comment.