Skip to content

Commit f2bf793

Browse files
committed
debug: SPU stereo recording to wav file
1 parent 47bbec1 commit f2bf793

File tree

9 files changed

+114
-14
lines changed

9 files changed

+114
-14
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ add_library(core STATIC
247247
src/input/input_manager.cpp
248248
src/sound/adpcm.cpp
249249
src/sound/tables.cpp
250+
src/sound/wave.cpp
250251
src/state/state.cpp
251252
src/stdafx.cpp
252253
src/system.cpp

src/device/spu/spu.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ void SPU::step(device::cdrom::CDROM* cdrom) {
126126

127127
audioBufferPos += 2;
128128
if (audioBufferPos >= AUDIO_BUFFER_SIZE) {
129+
if (recording) {
130+
std::copy(audioBuffer.begin(), audioBuffer.end(), std::back_inserter(recordBuffer));
131+
}
129132
audioBufferPos = 0;
130133
bufferReady = true;
131134
}

src/device/spu/spu.h

+4
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ struct SPU {
5656

5757
System* sys;
5858

59+
// Debug
60+
bool recording;
61+
std::vector<uint16_t> recordBuffer;
62+
5963
uint8_t readVoice(uint32_t address) const;
6064
void writeVoice(uint32_t address, uint8_t data);
6165

src/platform/windows/gui/debug/spu.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
#include <vector>
55
#include "device/spu/spu.h"
66
#include "system.h"
7+
#include "sound/wave.h"
78
#include <SDL.h>
9+
#include <utils/event.h>
10+
#include <iomanip>
11+
#include <config.h>
12+
#include <sstream>
13+
#include "platform/windows/gui/helper/file_dialog.h"
814

915
namespace ImGui {
1016
template <typename... Args>
@@ -297,6 +303,38 @@ void renderSamples(spu::SPU* spu) {
297303
ImGui::PlotLines("Preview", samples.data(), (int)samples.size(), 0, nullptr, -1.0f, 1.0f, ImVec2(400, 80));
298304
}
299305

306+
void SPU::recordingWindow(spu::SPU* spu) {
307+
if (ImGui::Button(spu->recording ? "Pause" : "Record")) {
308+
spu->recording = !spu->recording;
309+
}
310+
if (!spu->recordBuffer.empty()) {
311+
if (!spu->recording) {
312+
ImGui::SameLine();
313+
if (ImGui::Button("Save")) {
314+
auto t = std::time(nullptr);
315+
std::stringstream ss;
316+
ss << std::put_time(std::localtime(&t), "spu-%Y-%m-%d_%H-%M-%S.wav");
317+
auto file = ss.str();
318+
319+
bool saved = wave::writeToFile(spu->recordBuffer, fmt::format("{}/{}", avocado::PATH_USER, file).c_str());
320+
toast(saved ? fmt::format("Saved to {}", file) : fmt::format("Problem saving to {}", file));
321+
if (saved) {
322+
spu->recordBuffer.clear();
323+
showOpenDirectory = true;
324+
}
325+
}
326+
}
327+
328+
ImGui::SameLine();
329+
ImGui::TextUnformatted(fmt::format("{:.2f} seconds captured...", spu->recordBuffer.size() / 44100.f / 2).c_str());
330+
}
331+
332+
if (showOpenDirectory) {
333+
ImGui::SameLine();
334+
gui::helper::openFileBrowserButton(avocado::PATH_USER);
335+
}
336+
}
337+
300338
void SPU::spuWindow(spu::SPU* spu) {
301339
const auto treeFlags = ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_DefaultOpen;
302340
static bool parseValues = true;
@@ -309,6 +347,8 @@ void SPU::spuWindow(spu::SPU* spu) {
309347

310348
ImGui::Checkbox("Parse values", &parseValues);
311349
renderSamples(spu);
350+
351+
if (ImGui::TreeNodeEx("Recording", treeFlags)) recordingWindow(spu);
312352
ImGui::End();
313353
}
314354

src/platform/windows/gui/debug/spu.h

+3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ struct SPU;
88

99
namespace gui::debug {
1010
class SPU {
11+
bool showOpenDirectory = false;
12+
1113
void spuWindow(spu::SPU* spu);
1214

1315
public:
1416
bool spuWindowOpen = false;
1517
void displayWindows(System* sys);
18+
void recordingWindow(spu::SPU* spu);
1619
};
1720
} // namespace gui::debug

src/platform/windows/gui/helper/file_dialog.cpp

+17-14
Original file line numberDiff line numberDiff line change
@@ -227,20 +227,7 @@ void FileDialog::display(bool& windowOpen) {
227227
ImGui::PopStyleVar();
228228
ImGui::PopStyleVar();
229229

230-
#if defined(__APPLE__)
231-
if (ImGui::Button("Reveal in Finder")) {
232-
openFileBrowser(path.string());
233-
}
234-
#elif defined(_WIN32)
235-
if (ImGui::Button("Open in Explorer")) {
236-
openFileBrowser(path.string());
237-
}
238-
#elif defined(__linux__)
239-
if (ImGui::Button("Open in file explorer")) {
240-
openFileBrowser(path.string());
241-
}
242-
#endif
243-
230+
openFileBrowserButton(path.string());
244231
ImGui::End();
245232

246233
if (!windowOpen) {
@@ -258,5 +245,21 @@ const std::string formatFileSize(uintmax_t bytes) {
258245
char pre = units.at(exp - 1);
259246

260247
return fmt::format("{:4.0f} {}B", (float)bytes / std::pow(unit, exp), pre);
248+
}
249+
250+
void openFileBrowserButton(const std::string& path) {
251+
#if defined(__APPLE__)
252+
if (ImGui::Button("Reveal in Finder")) {
253+
openFileBrowser(path);
254+
}
255+
#elif defined(_WIN32)
256+
if (ImGui::Button("Open in Explorer")) {
257+
openFileBrowser(path);
258+
}
259+
#elif defined(__linux__)
260+
if (ImGui::Button("Open in file explorer")) {
261+
openFileBrowser(path);
262+
}
263+
#endif
261264
};
262265
}; // namespace gui::helper

src/platform/windows/gui/helper/file_dialog.h

+2
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,6 @@ class FileDialog {
4848
};
4949

5050
const std::string formatFileSize(uintmax_t bytes);
51+
52+
void openFileBrowserButton(const std::string& path);
5153
}; // namespace gui::helper

src/sound/wave.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include "wave.h"
2+
3+
namespace wave {
4+
bool writeToFile(const std::vector<uint16_t>& buffer, const char* filename, int channels) {
5+
FILE* f = fopen(filename, "wb");
6+
if (!f) {
7+
return false;
8+
}
9+
auto wstr = [&](const char* str) { fwrite(str, 1, strlen(str), f); };
10+
auto w32 = [f](uint32_t i) { fwrite(&i, sizeof(i), 1, f); };
11+
auto w16 = [f](uint16_t i) { fwrite(&i, sizeof(i), 1, f); };
12+
13+
const int bitPerSample = 16;
14+
const int sampleRate = 44100;
15+
16+
wstr("RIFF");
17+
w32((buffer.size() * bitPerSample / 8) + 36);
18+
19+
wstr("WAVE");
20+
wstr("fmt ");
21+
w32(16); // Subchunk size
22+
w16(1); // PCM
23+
w16(channels);
24+
w32(sampleRate);
25+
w32(sampleRate * channels * bitPerSample / 8);
26+
w16(channels * bitPerSample / 8);
27+
w16(bitPerSample);
28+
29+
wstr("data");
30+
w32(buffer.size() * bitPerSample / 8);
31+
for (uint16_t s : buffer) {
32+
w16(s);
33+
}
34+
35+
fclose(f);
36+
return true;
37+
}
38+
}; // namespace wave

src/sound/wave.h

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#pragma once
2+
#include <vector>
3+
4+
namespace wave {
5+
bool writeToFile(const std::vector<uint16_t>& buffer, const char* filename, int channels = 2);
6+
};

0 commit comments

Comments
 (0)