summaryrefslogtreecommitdiff
path: root/src/audio_core/hle/dsp.cpp
diff options
context:
space:
mode:
authorGravatar James Rowe2018-01-11 19:21:20 -0700
committerGravatar James Rowe2018-01-12 19:11:03 -0700
commitebf9a784a9f7f4148a669dbb39e7cd50df779a14 (patch)
treed585685a1c0a34b903af1d086d62560bf56bb29f /src/audio_core/hle/dsp.cpp
parentconfig: Default CPU core to Unicorn. (diff)
downloadyuzu-ebf9a784a9f7f4148a669dbb39e7cd50df779a14.tar.gz
yuzu-ebf9a784a9f7f4148a669dbb39e7cd50df779a14.tar.xz
yuzu-ebf9a784a9f7f4148a669dbb39e7cd50df779a14.zip
Massive removal of unused modules
Diffstat (limited to 'src/audio_core/hle/dsp.cpp')
-rw-r--r--src/audio_core/hle/dsp.cpp172
1 files changed, 0 insertions, 172 deletions
diff --git a/src/audio_core/hle/dsp.cpp b/src/audio_core/hle/dsp.cpp
deleted file mode 100644
index 260b182ed..000000000
--- a/src/audio_core/hle/dsp.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <array>
6#include <memory>
7#include "audio_core/hle/dsp.h"
8#include "audio_core/hle/mixers.h"
9#include "audio_core/hle/pipe.h"
10#include "audio_core/hle/source.h"
11#include "audio_core/sink.h"
12#include "audio_core/time_stretch.h"
13
14namespace DSP {
15namespace HLE {
16
17// Region management
18
19DspMemory g_dsp_memory;
20
21static size_t CurrentRegionIndex() {
22 // The region with the higher frame counter is chosen unless there is wraparound.
23 // This function only returns a 0 or 1.
24 u16 frame_counter_0 = g_dsp_memory.region_0.frame_counter;
25 u16 frame_counter_1 = g_dsp_memory.region_1.frame_counter;
26
27 if (frame_counter_0 == 0xFFFFu && frame_counter_1 != 0xFFFEu) {
28 // Wraparound has occurred.
29 return 1;
30 }
31
32 if (frame_counter_1 == 0xFFFFu && frame_counter_0 != 0xFFFEu) {
33 // Wraparound has occurred.
34 return 0;
35 }
36
37 return (frame_counter_0 > frame_counter_1) ? 0 : 1;
38}
39
40static SharedMemory& ReadRegion() {
41 return CurrentRegionIndex() == 0 ? g_dsp_memory.region_0 : g_dsp_memory.region_1;
42}
43
44static SharedMemory& WriteRegion() {
45 return CurrentRegionIndex() != 0 ? g_dsp_memory.region_0 : g_dsp_memory.region_1;
46}
47
48// Audio processing and mixing
49
50static std::array<Source, num_sources> sources = {
51 Source(0), Source(1), Source(2), Source(3), Source(4), Source(5), Source(6), Source(7),
52 Source(8), Source(9), Source(10), Source(11), Source(12), Source(13), Source(14), Source(15),
53 Source(16), Source(17), Source(18), Source(19), Source(20), Source(21), Source(22), Source(23),
54};
55static Mixers mixers;
56
57static StereoFrame16 GenerateCurrentFrame() {
58 SharedMemory& read = ReadRegion();
59 SharedMemory& write = WriteRegion();
60
61 std::array<QuadFrame32, 3> intermediate_mixes = {};
62
63 // Generate intermediate mixes
64 for (size_t i = 0; i < num_sources; i++) {
65 write.source_statuses.status[i] =
66 sources[i].Tick(read.source_configurations.config[i], read.adpcm_coefficients.coeff[i]);
67 for (size_t mix = 0; mix < 3; mix++) {
68 sources[i].MixInto(intermediate_mixes[mix], mix);
69 }
70 }
71
72 // Generate final mix
73 write.dsp_status = mixers.Tick(read.dsp_configuration, read.intermediate_mix_samples,
74 write.intermediate_mix_samples, intermediate_mixes);
75
76 StereoFrame16 output_frame = mixers.GetOutput();
77
78 // Write current output frame to the shared memory region
79 for (size_t samplei = 0; samplei < output_frame.size(); samplei++) {
80 for (size_t channeli = 0; channeli < output_frame[0].size(); channeli++) {
81 write.final_samples.pcm16[samplei][channeli] = s16_le(output_frame[samplei][channeli]);
82 }
83 }
84
85 return output_frame;
86}
87
88// Audio output
89
90static bool perform_time_stretching = true;
91static std::unique_ptr<AudioCore::Sink> sink;
92static AudioCore::TimeStretcher time_stretcher;
93
94static void FlushResidualStretcherAudio() {
95 time_stretcher.Flush();
96 while (true) {
97 std::vector<s16> residual_audio = time_stretcher.Process(sink->SamplesInQueue());
98 if (residual_audio.empty())
99 break;
100 sink->EnqueueSamples(residual_audio.data(), residual_audio.size() / 2);
101 }
102}
103
104static void OutputCurrentFrame(const StereoFrame16& frame) {
105 if (perform_time_stretching) {
106 time_stretcher.AddSamples(&frame[0][0], frame.size());
107 std::vector<s16> stretched_samples = time_stretcher.Process(sink->SamplesInQueue());
108 sink->EnqueueSamples(stretched_samples.data(), stretched_samples.size() / 2);
109 } else {
110 constexpr size_t maximum_sample_latency = 2048; // about 64 miliseconds
111 if (sink->SamplesInQueue() > maximum_sample_latency) {
112 // This can occur if we're running too fast and samples are starting to back up.
113 // Just drop the samples.
114 return;
115 }
116
117 sink->EnqueueSamples(&frame[0][0], frame.size());
118 }
119}
120
121void EnableStretching(bool enable) {
122 if (perform_time_stretching == enable)
123 return;
124
125 if (!enable) {
126 FlushResidualStretcherAudio();
127 }
128 perform_time_stretching = enable;
129}
130
131// Public Interface
132
133void Init() {
134 DSP::HLE::ResetPipes();
135
136 for (auto& source : sources) {
137 source.Reset();
138 }
139
140 mixers.Reset();
141
142 time_stretcher.Reset();
143 if (sink) {
144 time_stretcher.SetOutputSampleRate(sink->GetNativeSampleRate());
145 }
146}
147
148void Shutdown() {
149 if (perform_time_stretching) {
150 FlushResidualStretcherAudio();
151 }
152}
153
154bool Tick() {
155 StereoFrame16 current_frame = {};
156
157 // TODO: Check dsp::DSP semaphore (which indicates emulated application has finished writing to
158 // shared memory region)
159 current_frame = GenerateCurrentFrame();
160
161 OutputCurrentFrame(current_frame);
162
163 return true;
164}
165
166void SetSink(std::unique_ptr<AudioCore::Sink> sink_) {
167 sink = std::move(sink_);
168 time_stretcher.SetOutputSampleRate(sink->GetNativeSampleRate());
169}
170
171} // namespace HLE
172} // namespace DSP