summaryrefslogtreecommitdiffstats
path: root/src/audio_core/device/device_session.h
blob: f3fae26175673195472bd8037db569ae6534194b (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
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <chrono>
#include <memory>
#include <optional>
#include <span>

#include "audio_core/common/common.h"
#include "audio_core/sink/sink.h"
#include "common/scratch_buffer.h"
#include "core/hle/service/audio/errors.h"

namespace Core {
class System;
namespace Timing {
struct EventType;
} // namespace Timing
} // namespace Core

namespace Kernel {
class KProcess;
} // namespace Kernel

namespace AudioCore {

namespace Sink {
class SinkStream;
struct SinkBuffer;
} // namespace Sink

struct AudioBuffer;

/**
 * Represents an input or output device stream for audio in and audio out (not used for render).
 **/
class DeviceSession {
public:
    explicit DeviceSession(Core::System& system);
    ~DeviceSession();

    /**
     * Initialize this device session.
     *
     * @param name                    - Name of this device.
     * @param sample_format           - Sample format for this device's output.
     * @param channel_count           - Number of channels for this device (2 or 6).
     * @param session_id              - This session's id.
     * @param handle                  - Process handle for this device session.
     * @param applet_resource_user_id - Applet resource user id for this device session (unused).
     * @param type                    - Type of this stream (Render, In, Out).
     * @return Result code for this call.
     */
    Result Initialize(std::string_view name, SampleFormat sample_format, u16 channel_count,
                      size_t session_id, Kernel::KProcess* handle, u64 applet_resource_user_id,
                      Sink::StreamType type);

    /**
     * Finalize this device session.
     */
    void Finalize();

    /**
     * Append audio buffers to this device session to be played back.
     *
     * @param buffers - The buffers to play.
     */
    void AppendBuffers(std::span<const AudioBuffer> buffers);

    /**
     * (Audio In only) Pop samples from the backend, and write them back to this buffer's address.
     *
     * @param buffer - The buffer to write to.
     */
    void ReleaseBuffer(const AudioBuffer& buffer) const;

    /**
     * Check if the buffer for the given tag has been consumed by the backend.
     *
     * @param buffer - the buffer to check.
     *
     * @return true if the buffer has been consumed, otherwise false.
     */
    bool IsBufferConsumed(const AudioBuffer& buffer) const;

    /**
     * Start this device session, starting the backend stream.
     */
    void Start();

    /**
     * Stop this device session, stopping the backend stream.
     */
    void Stop();

    /**
     * Clear out the underlying audio buffers in the backend stream.
     */
    void ClearBuffers();

    /**
     * Set this device session's volume.
     *
     * @param volume - New volume for this session.
     */
    void SetVolume(f32 volume) const;

    /**
     * Get this device session's total played sample count.
     *
     * @return Samples played by this session.
     */
    u64 GetPlayedSampleCount() const;

    /*
     * CoreTiming callback to increment played_sample_count over time.
     */
    std::optional<std::chrono::nanoseconds> ThreadFunc();

    /*
     * Set the size of the ring buffer.
     */
    void SetRingSize(u32 ring_size);

private:
    /// System
    Core::System& system;
    /// Output sink this device will use
    Sink::Sink* sink{};
    /// The backend stream for this device session to send samples to
    Sink::SinkStream* stream{};
    /// Name of this device session
    std::string name{};
    /// Type of this device session (render/in/out)
    Sink::StreamType type{};
    /// Sample format for this device.
    SampleFormat sample_format{SampleFormat::PcmInt16};
    /// Channel count for this device session
    u16 channel_count{};
    /// Session id of this device session
    size_t session_id{};
    /// Process handle of device memory owner
    Kernel::KProcess* handle{};
    /// Applet resource user id of this device session
    u64 applet_resource_user_id{};
    /// Total number of samples played by this device session
    std::atomic<u64> played_sample_count{};
    /// Event increasing the played sample count every 5ms
    std::shared_ptr<Core::Timing::EventType> thread_event;
    /// Is this session initialised?
    bool initialized{};
    /// Temporary sample buffer
    Common::ScratchBuffer<s16> tmp_samples{};
};

} // namespace AudioCore