Cemu/src/audio/audioDebuggerWindow.cpp
2023-09-30 15:27:56 +02:00

332 lines
9.5 KiB
C++

#include "gui/wxgui.h"
#include "audioDebuggerWindow.h"
#include "Cafe/OS/libs/snd_core/ax.h"
#include "Cafe/OS/libs/snd_core/ax_internal.h"
enum
{
// options
REFRESH_ID,
CLOSE_ID,
VOICELIST_ID,
REFRESH_TIMER_ID,
};
wxBEGIN_EVENT_TABLE(AudioDebuggerWindow, wxFrame)
EVT_BUTTON(CLOSE_ID, AudioDebuggerWindow::OnCloseButton)
EVT_BUTTON(REFRESH_ID, AudioDebuggerWindow::OnRefreshButton)
EVT_TIMER(REFRESH_TIMER_ID, AudioDebuggerWindow::OnRefreshTimer)
EVT_CLOSE(AudioDebuggerWindow::OnClose)
wxEND_EVENT_TABLE()
AudioDebuggerWindow::AudioDebuggerWindow(wxFrame& parent)
: wxFrame(&parent, wxID_ANY, _("AX voice viewer"), wxDefaultPosition, wxSize(1126, 580), wxCLOSE_BOX | wxCLIP_CHILDREN | wxCAPTION | wxRESIZE_BORDER)
{
wxPanel* mainPane = new wxPanel(this);
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
voiceListbox = new wxListCtrl(mainPane, VOICELIST_ID, wxPoint(0, 0), wxSize(1126, 570), wxLC_REPORT);
voiceListbox->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, "Courier New"));
// add columns
wxListItem col0;
col0.SetId(0);
col0.SetText("idx");
col0.SetWidth(40);
voiceListbox->InsertColumn(0, col0);
wxListItem col1;
col1.SetId(1);
col1.SetText("state");
col1.SetWidth(48);
voiceListbox->InsertColumn(1, col1);
//wxListItem col2;
// format
col1.SetId(2);
col1.SetText("fmt");
col1.SetWidth(52);
voiceListbox->InsertColumn(2, col1);
// sample base addr
col1.SetId(3);
col1.SetText("base");
col1.SetWidth(70);
voiceListbox->InsertColumn(3, col1);
// current offset
col1.SetId(4);
col1.SetText("current");
col1.SetWidth(70);
voiceListbox->InsertColumn(4, col1);
// loop offset
col1.SetId(5);
col1.SetText("loop");
col1.SetWidth(70);
voiceListbox->InsertColumn(5, col1);
// end offset
col1.SetId(6);
col1.SetText("end");
col1.SetWidth(70);
voiceListbox->InsertColumn(6, col1);
// volume
col1.SetId(7);
col1.SetText("vol");
col1.SetWidth(46);
voiceListbox->InsertColumn(7, col1);
// volume delta
col1.SetId(8);
col1.SetText("volD");
col1.SetWidth(46);
voiceListbox->InsertColumn(8, col1);
// src
col1.SetId(9);
col1.SetText("src");
col1.SetWidth(70);
voiceListbox->InsertColumn(9, col1);
// low-pass filter coef a0
col1.SetId(10);
col1.SetText("lpa0");
col1.SetWidth(46);
voiceListbox->InsertColumn(10, col1);
// low-pass filter coef b0
col1.SetId(11);
col1.SetText("lpb0");
col1.SetWidth(46);
voiceListbox->InsertColumn(11, col1);
// biquad filter coef b0
col1.SetId(12);
col1.SetText("bqb0");
col1.SetWidth(46);
voiceListbox->InsertColumn(12, col1);
// biquad filter coef b0
col1.SetId(13);
col1.SetText("bqb1");
col1.SetWidth(46);
voiceListbox->InsertColumn(13, col1);
// biquad filter coef b0
col1.SetId(14);
col1.SetText("bqb2");
col1.SetWidth(46);
voiceListbox->InsertColumn(14, col1);
// biquad filter coef a0
col1.SetId(15);
col1.SetText("bqa1");
col1.SetWidth(46);
voiceListbox->InsertColumn(15, col1);
// biquad filter coef a1
col1.SetId(16);
col1.SetText("bqa2");
col1.SetWidth(46);
voiceListbox->InsertColumn(16, col1);
// device mix
col1.SetId(17);
col1.SetText("deviceMix");
col1.SetWidth(186);
voiceListbox->InsertColumn(17, col1);
sizer->Add(voiceListbox, 1, wxEXPAND | wxBOTTOM, 0);
voiceListbox->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(AudioDebuggerWindow::OnVoiceListRightClick), NULL, this);
mainPane->SetSizer(sizer);
// add empty entries
for (sint32 i = 0; i < snd_core::AX_MAX_VOICES; i++)
{
wxListItem item;
item.SetId(i);
char tempStr[32];
sprintf(tempStr, "%d", snd_core::AX_MAX_VOICES-i-1);
item.SetText(wxString(tempStr));
voiceListbox->InsertItem(item);
}
RefreshVoiceList();
wxFrame::SetBackgroundColour(*wxWHITE);
// start refresh timer
static const int INTERVAL = 100; // milliseconds
refreshTimer = new wxTimer(this, REFRESH_TIMER_ID);
refreshTimer->Start(INTERVAL);
}
void AudioDebuggerWindow::OnRefreshTimer(wxTimerEvent& event)
{
RefreshVoiceList();
}
void AudioDebuggerWindow::OnCloseButton(wxCommandEvent& event)
{
Close();
}
void AudioDebuggerWindow::OnRefreshButton(wxCommandEvent& event)
{
RefreshVoiceList();
}
void AudioDebuggerWindow::OnClose(wxCloseEvent& event)
{
Close();
}
#define _r(__idx) _swapEndianU32(threadItrBE->context.gpr[__idx])
void AudioDebuggerWindow::RefreshVoiceList_sndgeneric()
{
if (snd_core::__AXVPBInternalVoiceArray == nullptr || snd_core::__AXVPBArrayPtr == nullptr)
return;
snd_core::AXVPB tempVoiceArray[snd_core::AX_MAX_VOICES];
memcpy(tempVoiceArray, snd_core::__AXVPBArrayPtr, sizeof(snd_core::AXVPB)*snd_core::AX_MAX_VOICES);
voiceListbox->Freeze();
char tempStr[64];
for (sint32 i = 0; i < snd_core::AX_MAX_VOICES; i++)
{
sint32 voiceIndex = snd_core::AX_MAX_VOICES - 1 - i;
snd_core::AXVPBInternal_t* internal = snd_core::__AXVPBInternalVoiceArray + voiceIndex;
// index
sprintf(tempStr, "%d", (sint32)tempVoiceArray[voiceIndex].index);
voiceListbox->SetItem(i, 0, tempStr);
// state
uint16 playbackState = _swapEndianU16(internal->playbackState);
if (playbackState)
strcpy(tempStr, "on");
else
strcpy(tempStr, "off");
voiceListbox->SetItem(i, 1, tempStr);
// if voice index is invalid then stop updating here to prevent crashes
if (voiceIndex < 0 || playbackState == 0)
{
voiceListbox->SetItem(i, 0, "");
voiceListbox->SetItem(i, 1, "");
voiceListbox->SetItem(i, 2, "");
voiceListbox->SetItem(i, 3, "");
voiceListbox->SetItem(i, 4, "");
voiceListbox->SetItem(i, 5, "");
voiceListbox->SetItem(i, 6, "");
voiceListbox->SetItem(i, 7, "");
voiceListbox->SetItem(i, 8, "");
voiceListbox->SetItem(i, 9, "");
voiceListbox->SetItem(i, 10, "");
voiceListbox->SetItem(i, 11, "");
voiceListbox->SetItem(i, 12, "");
voiceListbox->SetItem(i, 13, "");
voiceListbox->SetItem(i, 14, "");
voiceListbox->SetItem(i, 15, "");
voiceListbox->SetItem(i, 16, "");
voiceListbox->SetItem(i, 17, "");
continue;
}
// format
if (tempVoiceArray[voiceIndex].offsets.format == _swapEndianU16(snd_core::AX_FORMAT_ADPCM))
strcpy(tempStr, "adpcm");
else if (tempVoiceArray[voiceIndex].offsets.format == _swapEndianU16(snd_core::AX_FORMAT_PCM16))
strcpy(tempStr, "pcm16");
else if (tempVoiceArray[voiceIndex].offsets.format == _swapEndianU16(snd_core::AX_FORMAT_PCM8))
strcpy(tempStr, "pcm8");
else
strcpy(tempStr, "ukn");
voiceListbox->SetItem(i, 2, tempStr);
// update offsets
snd_core::AXPBOFFSET_t tempOffsets;
snd_core::AXGetVoiceOffsets(tempVoiceArray + voiceIndex, &tempOffsets);
// sample base
sprintf(tempStr, "%08x", _swapEndianU32(tempOffsets.samples));
voiceListbox->SetItem(i, 3, tempStr);
// current offset
sprintf(tempStr, "%08x", _swapEndianU32(tempOffsets.currentOffset));
voiceListbox->SetItem(i, 4, tempStr);
// loop offset
if (tempOffsets.loopFlag)
sprintf(tempStr, "%08x", _swapEndianU32(tempOffsets.loopOffset));
else
sprintf(tempStr, "");
voiceListbox->SetItem(i, 5, tempStr);
// end offset
sprintf(tempStr, "%08x", _swapEndianU32(tempOffsets.endOffset));
voiceListbox->SetItem(i, 6, tempStr);
// volume
sprintf(tempStr, "%04x", (uint16)internal->veVolume);
voiceListbox->SetItem(i, 7, tempStr);
// volume delta
sprintf(tempStr, "%04x", (uint16)internal->veDelta);
voiceListbox->SetItem(i, 8, tempStr);
// src
sprintf(tempStr, "%04x%04x", _swapEndianU16(internal->src.ratioHigh), _swapEndianU16(internal->src.ratioLow));
voiceListbox->SetItem(i, 9, tempStr);
// lpf
if (internal->lpf.on)
{
sprintf(tempStr, "%04x", _swapEndianU16(internal->lpf.a0));
voiceListbox->SetItem(i, 10, tempStr);
sprintf(tempStr, "%04x", _swapEndianU16(internal->lpf.b0));
voiceListbox->SetItem(i, 11, tempStr);
}
else
{
voiceListbox->SetItem(i, 10, "");
voiceListbox->SetItem(i, 11, "");
}
// biquad
if (internal->biquad.on)
{
sprintf(tempStr, "%04x", _swapEndianU16(internal->biquad.b0));
voiceListbox->SetItem(i, 12, tempStr);
sprintf(tempStr, "%04x", _swapEndianU16(internal->biquad.b1));
voiceListbox->SetItem(i, 13, tempStr);
sprintf(tempStr, "%04x", _swapEndianU16(internal->biquad.b2));
voiceListbox->SetItem(i, 14, tempStr);
sprintf(tempStr, "%04x", _swapEndianU16(internal->biquad.a1));
voiceListbox->SetItem(i, 15, tempStr);
sprintf(tempStr, "%04x", _swapEndianU16(internal->biquad.a2));
voiceListbox->SetItem(i, 16, tempStr);
}
else
{
voiceListbox->SetItem(i, 12, "");
voiceListbox->SetItem(i, 13, "");
voiceListbox->SetItem(i, 14, "");
voiceListbox->SetItem(i, 15, "");
voiceListbox->SetItem(i, 16, "");
}
// device mix
for (uint32 f = 0; f < snd_core::AX_TV_CHANNEL_COUNT*snd_core::AX_MAX_NUM_BUS; f++)
{
sint32 busIndex = f% snd_core::AX_MAX_NUM_BUS;
sint32 channelIndex = f / snd_core::AX_MAX_NUM_BUS;
//debug_printf("DeviceMix TV Voice %08x b%02d/c%02d vol %04x delta %04x\n", hCPU->gpr[3], busIndex, channelIndex, _swapEndianU16(mixArrayBE[f].vol), _swapEndianU16(mixArrayBE[f].volDelta));
uint32 mixVol = internal->deviceMixTV[channelIndex * 4 + busIndex].vol;
mixVol = (mixVol + 0x0FFF) >> (12);
sprintf(tempStr + f, "%x", mixVol);
//ax.voiceInternal[voiceIndex].deviceMixTVChannel[channelIndex].bus[busIndex].vol = _swapEndianU16(mixArrayBE[f].vol);
}
voiceListbox->SetItem(i, 17, tempStr);
}
voiceListbox->Thaw();
}
void AudioDebuggerWindow::RefreshVoiceList()
{
RefreshVoiceList_sndgeneric();
}
void AudioDebuggerWindow::OnVoiceListPopupClick(wxCommandEvent &evt)
{
}
void AudioDebuggerWindow::OnVoiceListRightClick(wxMouseEvent& event)
{
}
void AudioDebuggerWindow::Close()
{
// this->MakeModal(false);
refreshTimer->Stop();
this->Destroy();
}