summaryrefslogtreecommitdiffstats
path: root/src/audio_core/common.h
blob: e6b95769f1aa39ced3daecb2c7629ee10ca02766 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/result.h"

namespace AudioCommon {
namespace Audren {
constexpr ResultCode ERR_INVALID_PARAMETERS{ErrorModule::Audio, 41};
constexpr ResultCode ERR_SPLITTER_SORT_FAILED{ErrorModule::Audio, 43};
} // namespace Audren

constexpr u8 BASE_REVISION = '0';
constexpr u32_le CURRENT_PROCESS_REVISION =
    Common::MakeMagic('R', 'E', 'V', static_cast<u8>(BASE_REVISION + 0xA));
constexpr std::size_t MAX_MIX_BUFFERS = 24;
constexpr std::size_t MAX_BIQUAD_FILTERS = 2;
constexpr std::size_t MAX_CHANNEL_COUNT = 6;
constexpr std::size_t MAX_WAVE_BUFFERS = 4;
constexpr std::size_t MAX_SAMPLE_HISTORY = 4;
constexpr u32 STREAM_SAMPLE_RATE = 48000;
constexpr u32 STREAM_NUM_CHANNELS = 2;
constexpr s32 NO_SPLITTER = -1;
constexpr s32 NO_MIX = 0x7fffffff;
constexpr s32 NO_FINAL_MIX = std::numeric_limits<s32>::min();
constexpr s32 FINAL_MIX = 0;
constexpr s32 NO_EFFECT_ORDER = -1;
constexpr std::size_t TEMP_MIX_BASE_SIZE = 0x3f00; // TODO(ogniK): Work out this constant
// Any size checks seem to take the sample history into account
// and our const ends up being 0x3f04, the 4 bytes are most
// likely the sample history
constexpr std::size_t TOTAL_TEMP_MIX_SIZE = TEMP_MIX_BASE_SIZE + AudioCommon::MAX_SAMPLE_HISTORY;
constexpr f32 I3DL2REVERB_MAX_LEVEL = 5000.0f;
constexpr f32 I3DL2REVERB_MIN_REFLECTION_DURATION = 0.02f;
constexpr std::size_t I3DL2REVERB_TAPS = 20;
constexpr std::size_t I3DL2REVERB_DELAY_LINE_COUNT = 4;
using Fractional = s32;

template <typename T>
constexpr Fractional ToFractional(T x) {
    return static_cast<Fractional>(x * static_cast<T>(0x4000));
}

constexpr Fractional MultiplyFractional(Fractional lhs, Fractional rhs) {
    return static_cast<Fractional>(static_cast<s64>(lhs) * rhs >> 14);
}

constexpr s32 FractionalToFixed(Fractional x) {
    const auto s = x & (1 << 13);
    return static_cast<s32>(x >> 14) + s;
}

constexpr s32 CalculateDelaySamples(s32 sample_rate_khz, float time) {
    return FractionalToFixed(MultiplyFractional(ToFractional(sample_rate_khz), ToFractional(time)));
}

static constexpr u32 VersionFromRevision(u32_le rev) {
    // "REV7" -> 7
    return ((rev >> 24) & 0xff) - 0x30;
}

static constexpr bool IsRevisionSupported(u32 required, u32_le user_revision) {
    const auto base = VersionFromRevision(user_revision);
    return required <= base;
}

static constexpr bool IsValidRevision(u32_le revision) {
    const auto base = VersionFromRevision(revision);
    constexpr auto max_rev = VersionFromRevision(CURRENT_PROCESS_REVISION);
    return base <= max_rev;
}

static constexpr bool CanConsumeBuffer(std::size_t size, std::size_t offset, std::size_t required) {
    if (offset > size) {
        return false;
    }
    if (size < required) {
        return false;
    }
    if ((size - offset) < required) {
        return false;
    }
    return true;
}

struct UpdateDataSizes {
    u32_le behavior{};
    u32_le memory_pool{};
    u32_le voice{};
    u32_le voice_channel_resource{};
    u32_le effect{};
    u32_le mixer{};
    u32_le sink{};
    u32_le performance{};
    u32_le splitter{};
    u32_le render_info{};
    INSERT_PADDING_WORDS(4);
};
static_assert(sizeof(UpdateDataSizes) == 0x38, "UpdateDataSizes is an invalid size");

struct UpdateDataHeader {
    u32_le revision{};
    UpdateDataSizes size{};
    u32_le total_size{};
};
static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader is an invalid size");

struct AudioRendererParameter {
    u32_le sample_rate;
    u32_le sample_count;
    u32_le mix_buffer_count;
    u32_le submix_count;
    u32_le voice_count;
    u32_le sink_count;
    u32_le effect_count;
    u32_le performance_frame_count;
    u8 is_voice_drop_enabled;
    u8 unknown_21;
    u8 unknown_22;
    u8 execution_mode;
    u32_le splitter_count;
    u32_le num_splitter_send_channels;
    u32_le unknown_30;
    u32_le revision;
};
static_assert(sizeof(AudioRendererParameter) == 52, "AudioRendererParameter is an invalid size");

} // namespace AudioCommon