summaryrefslogtreecommitdiffstats
path: root/src/audio_core/renderer/adsp/adsp.h
blob: f7a2f25e4a082b3eff492ca16e1ef1378432f7d2 (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <memory>
#include <mutex>

#include "audio_core/renderer/adsp/audio_renderer.h"
#include "common/common_types.h"

namespace Core {
namespace Memory {
class Memory;
}
class System;
} // namespace Core

namespace AudioCore {
namespace Sink {
class Sink;
}

namespace AudioRenderer::ADSP {
struct CommandBuffer;

enum class State {
    Started,
    Stopped,
};

/**
 * Represents the ADSP embedded within the audio sysmodule.
 * This is a 32-bit Linux4Tegra kernel from nVidia, which is launched with the sysmodule on boot.
 *
 * The kernel will run apps you program for it, Nintendo have the following:
 *
 * Gmix - Responsible for mixing final audio and sending it out to hardware. This is last place all
 *        audio samples end up, and we skip it entirely, since we have very different backends and
 *        mixing is implicitly handled by the OS (but also due to lack of research/simplicity).
 *
 * AudioRenderer - Receives command lists generated by the audio render
 *                 system, processes them, and sends the samples to Gmix.
 *
 * OpusDecoder - Contains libopus, and controls processing Opus audio and sends it to Gmix.
 *               Not much research done here, TODO if needed.
 *
 * We only implement the AudioRenderer for now.
 *
 * Communication for the apps is done through mailboxes, and some shared memory.
 */
class ADSP {
public:
    explicit ADSP(Core::System& system, Sink::Sink& sink);
    ~ADSP();

    /**
     * Start the ADSP.
     *
     * @return True if started or already running, otherwise false.
     */
    bool Start();

    /**
     * Stop the ADSP.
     */
    void Stop();

    /**
     * Get the ADSP's state.
     *
     * @return Started or Stopped.
     */
    State GetState() const;

    /**
     * Get the AudioRenderer mailbox to communicate with it.
     *
     * @return The AudioRenderer mailbox.
     */
    AudioRenderer_Mailbox* GetRenderMailbox();

    /**
     * Get the tick the ADSP was signalled.
     *
     * @return The tick the ADSP was signalled.
     */
    u64 GetSignalledTick() const;

    /**
     * Get the total time it took for the ADSP to run the last command lists (both command lists).
     *
     * @return The tick the ADSP was signalled.
     */
    u64 GetTimeTaken() const;

    /**
     * Get the last time a given command list took to run.
     *
     * @param session_id - The session id to check (0 or 1).
     * @return The time it took.
     */
    u64 GetRenderTimeTaken(u32 session_id);

    /**
     * Clear the remaining command count for a given session.
     *
     * @param session_id - The session id to check (0 or 1).
     */
    void ClearRemainCount(u32 session_id);

    /**
     * Get the remaining number of commands left to process for a command list.
     *
     * @param session_id - The session id to check (0 or 1).
     * @return The number of commands remaining.
     */
    u32 GetRemainCommandCount(u32 session_id) const;

    /**
     * Get the last tick a command list started processing.
     *
     * @param session_id - The session id to check (0 or 1).
     * @return The last tick the given command list started.
     */
    u64 GetRenderingStartTick(u32 session_id);

    /**
     * Set a command buffer to be processed.
     *
     * @param session_id     - The session id to check (0 or 1).
     * @param command_buffer - The command buffer to process.
     */
    void SendCommandBuffer(u32 session_id, const CommandBuffer& command_buffer);

    /**
     * Clear the command buffers (does not clear the time taken or the remaining command count)
     */
    void ClearCommandBuffers();

    /**
     * Signal the AudioRenderer to begin processing.
     */
    void Signal();

    /**
     * Wait for the AudioRenderer to finish processing.
     */
    void Wait();

private:
    /// Core system
    Core::System& system;
    /// Core memory
    Core::Memory::Memory& memory;
    /// Number of systems active, used to prevent accidental shutdowns
    u8 systems_active{0};
    /// ADSP running state
    std::atomic<bool> running{false};
    /// Output sink used by the ADSP
    Sink::Sink& sink;
    /// AudioRenderer app
    std::unique_ptr<AudioRenderer> audio_renderer{};
    /// Communication for the AudioRenderer
    AudioRenderer_Mailbox render_mailbox{};
    /// Mailbox lock ffor the render mailbox
    std::mutex mailbox_lock;
};

} // namespace AudioRenderer::ADSP
} // namespace AudioCore