Skip to content

Commit

Permalink
Fixed audio on RPI frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas-jonsson committed Nov 19, 2024
1 parent 10d2157 commit ebd13f0
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 43 deletions.
14 changes: 8 additions & 6 deletions .github/workflows/libretro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ on:
env:
VXT_VERSION: 1.2.0
ZIG_VERSION: 0.10.1
ZIG_ARCHS: "x86_64-linux-gnu i386-linux-gnu aarch64-linux-gnu arm-linux-gnueabi x86_64-macos-none aarch64-macos-none"
#ZIG_ARCHS: "x86_64-linux-gnu i386-linux-gnu aarch64-linux-gnu arm-linux-gnueabi x86_64-macos-none aarch64-macos-none"
ZIG_ARCHS: "x86_64-linux-gnu"
NDK_VERSION: r20
NDK_ARCHS: "aarch64-linux-android armv7a-linux-androideabi x86_64-linux-android i686-linux-android"
#NDK_ARCHS: "aarch64-linux-android armv7a-linux-androideabi x86_64-linux-android i686-linux-android"
NDK_ARCHS: "aarch64-linux-android"

jobs:
libretro-build:
Expand Down Expand Up @@ -92,7 +94,7 @@ jobs:
cp build/libretro/*.so package/virtualxt/${arch}
done
- name: Package & Deploy
env:
BUTLER_API_KEY: ${{ secrets.BUTLER_API_KEY }}
run: if [[ $GITHUB_REF_NAME =~ ^(edge|release)$ ]]; then ./tools/package/itch/push-libretro.sh; fi
#- name: Package & Deploy
# env:
# BUTLER_API_KEY: ${{ secrets.BUTLER_API_KEY }}
# run: if [[ $GITHUB_REF_NAME =~ ^(edge|release)$ ]]; then ./tools/package/itch/push-libretro.sh; fi
3 changes: 2 additions & 1 deletion front/rpi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ endif

LIBCHOME = $(VXTHOME)/../scanf

C_STANDARD = -std=c11
CFLAGS = -DVXT_NO_LIBC -DFRONTEND_VIDEO_RED=2 -DFRONTEND_VIDEO_GREEN=1 -DFRONTEND_VIDEO_BLUE=0 -DFRONTEND_VIDEO_ALPHA=3 -I$(VXTHOME)/include -I../common

OBJS_VXT = $(VXTHOME)/cpu.o \
Expand All @@ -24,7 +25,7 @@ EXTRACLEAN = $(VXTHOME)/*.o $(VXTHOME)/*.d
OBJS_LIBC = $(LIBCHOME)/scanf.o
EXTRACLEAN += $(LIBCHOME)/*.o $(LIBCHOME)/*.d

OBJS = main.o kernel.o ethernet.o cga.o mouse.o ems.o vga.o $(OBJS_VXT) $(OBJS_LIBC)
OBJS = main.o kernel.o ethernet.o cga.o vga.o mouse.o ems.o adlib.o $(OBJS_VXT) $(OBJS_LIBC)

LIBS = $(CIRCLEHOME)/lib/usb/libusb.a \
$(CIRCLEHOME)/lib/sound/libsound.a \
Expand Down
30 changes: 30 additions & 0 deletions front/rpi/adlib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2019-2024 Andreas T Jonsson <mail@andreasjonsson.se>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.

#include "../../modules/adlib/nuked-opl3/opl3.c"
#include "../../modules/adlib/adlib.c"

struct vxt_peripheral *adlib_create(vxt_allocator *alloc, struct frontend_audio_adapter *aa) {
struct vxt_peripheral *p = create(alloc, NULL, NULL);
if (p)
*aa = (struct frontend_audio_adapter){p, &generate_sample};
return p;
}
82 changes: 61 additions & 21 deletions front/rpi/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,19 @@
#include <frontend.h>
#include "keymap.h"

//#define LOGSERIAL

#define DRIVE "SD:"
#define BIOSIMAGE "GLABIOS.ROM"
#define SAMPLE_RATE 22050
#define CHUNK_SIZE 256
#define AUDIO_LATENCY_MS 10

volatile bool mouse_updated = false;
struct frontend_mouse_event mouse_state;
struct frontend_video_adapter video_adapter;

struct frontend_video_adapter video_adapter = {0};
struct frontend_audio_adapter audio_adapter = {0};

unsigned cpu_frequency = VXT_DEFAULT_FREQUENCY;

Expand All @@ -41,19 +51,16 @@ int screen_height = 0;
struct vxt_peripheral *ppi = 0;
struct vxt_peripheral *mouse = 0;

const unsigned audio_buffer_size = (SAMPLE_RATE / 1000) * AUDIO_LATENCY_MS;
unsigned audio_buffer_len = 0;
DMA_BUFFER(short, audio_buffer, audio_buffer_size);

CKernel *CKernel::s_pThis = 0;
CBcmFrameBuffer *pFrameBuffer = 0;
CDevice *pUMSD1 = 0;
volatile int pUMSD1_head = 0;

FIL log_file = {0};

//#define LOGSERIAL

#define DRIVE "SD:"
#define BIOSIMAGE "GLABIOS.ROM"
#define SAMPLE_RATE 48000

extern "C" {
// From joystick.c
bool joystick_push_event(struct vxt_peripheral *p, const struct frontend_joystick_event *ev);
Expand All @@ -69,6 +76,9 @@ extern "C" {
// From ems.c
struct vxt_peripheral *ems_create(vxt_allocator *alloc, const char *args);

// From adlib.c
struct vxt_peripheral *adlib_create(vxt_allocator *alloc, struct frontend_audio_adapter *aa);

// From cga.c
struct vxt_peripheral *cga_card_create(vxt_allocator *alloc, struct frontend_video_adapter *va);

Expand Down Expand Up @@ -259,6 +269,7 @@ CKernel::CKernel(void)

memset(&mouse_state, 0, sizeof(mouse_state));
memset(&video_adapter, 0, sizeof(video_adapter));
memset(audio_buffer, 0, audio_buffer_size * 2);
memset(m_RawKeys, 0, sizeof(m_RawKeys));
s_pThis = this;
}
Expand Down Expand Up @@ -346,22 +357,35 @@ TShutdownMode CKernel::Run(void) {
if ((pUMSD1 = m_DeviceNameService.GetDevice("umsd1", TRUE)))
VXT_LOG("Found USB storage device!");

VXT_LOG("Initializing audio...");
const char *pSoundDevice = m_Options.GetSoundDevice();
if (!strcmp(pSoundDevice, "sndpwm")) {
m_pSound = new CPWMSoundBaseDevice(&m_Interrupt, SAMPLE_RATE, 1);
if (pSoundDevice) {
if (!strcmp(pSoundDevice, "sndhdmi"))
m_pSound = new CHDMISoundBaseDevice(&m_Interrupt, SAMPLE_RATE, CHUNK_SIZE);

if (!m_pSound->AllocateQueueFrames(1))
VXT_LOG("Cannot allocate sound queue!");
#if RASPPI >= 4
if (!m_pSound && !strcmp(pSoundDevice, "sndusb"))
m_pSound = new CUSBSoundBaseDevice(SAMPLE_RATE);
#endif
}

// Use PWM as default audio device.
if (!m_pSound) {
pSoundDevice = "sndpwm";
m_pSound = new CPWMSoundBaseDevice(&m_Interrupt, SAMPLE_RATE, CHUNK_SIZE);
}

if (m_pSound) {
VXT_LOG("Sound device: %s", pSoundDevice);
m_pSound->SetWriteFormat(SoundFormatSigned16, 1);

//unsigned nQueueSizeFrames = m_pSound->GetQueueSizeFrames();
//WriteSoundData(nQueueSizeFrames);
if (!m_pSound->AllocateQueue(AUDIO_LATENCY_MS))
VXT_LOG("Cannot allocate sound queue!");

if (!m_pSound->Start())
VXT_LOG("Cannot start sound device!");
} else {
VXT_LOG("No supported audio device!");
VXT_LOG("Sound device is not supported!");
}

struct vxtu_disk_interface2 intrf = {
Expand All @@ -385,6 +409,7 @@ TShutdownMode CKernel::Run(void) {
(disk = vxtu_disk_create2(&allocator, &intrf)),
(mouse = mouse_create(&allocator, NULL, "0x3F8")),
//(joystick = joystick_create(&allocator, NULL, "0x201")),
adlib_create(&allocator, &audio_adapter),
use_cga ? cga_card_create(&allocator, &video_adapter) : vga_card_create(&allocator, &video_adapter),
use_cga ? NULL : load_bios("vgabios.bin", 0xC0000),
NULL
Expand Down Expand Up @@ -469,12 +494,27 @@ TShutdownMode CKernel::Run(void) {
video_adapter.render(video_adapter.device, &render_callback, &m_Options);
}

if ((ticks - audioTicks) >= (CLOCKHZ / SAMPLE_RATE)) {
audioTicks = ticks;
if (m_pSound && m_pSound->IsActive()) {
while ((ticks - audioTicks) >= (CLOCKHZ / SAMPLE_RATE)) {
audioTicks += CLOCKHZ / SAMPLE_RATE;

// Generate audio.
if (audio_buffer_len < audio_buffer_size) {
short sample = vxtu_ppi_generate_sample(ppi, SAMPLE_RATE);
m_pSound->Write((u8*)&sample, 2);
}
if (audio_adapter.device)
sample += audio_adapter.generate_sample(audio_adapter.device, SAMPLE_RATE);
audio_buffer[audio_buffer_len++] = sample;
}

// Write audio data to output device.
if (m_pSound && m_pSound->IsActive()) {
const unsigned samples_needed = m_pSound->GetQueueSizeFrames() - m_pSound->GetQueueFramesAvail();

if ((audio_buffer_len == audio_buffer_size) || (samples_needed > audio_buffer_len)) {
unsigned num_samples = (samples_needed < audio_buffer_len) ? samples_needed : audio_buffer_len;
m_pSound->Write((u8*)audio_buffer, num_samples * 2);
audio_buffer_len = 0;
}
}
}

u64 cpuTicks = ticks * (cpu_frequency / 1000000);
Expand Down
2 changes: 2 additions & 0 deletions front/rpi/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#include <circle/logger.h>
#include <circle/sound/soundbasedevice.h>
#include <circle/sound/pwmsoundbasedevice.h>
#include <circle/sound/hdmisoundbasedevice.h>
#include <circle/sound/usbsoundbasedevice.h>
#include <circle/usb/usbhcidevice.h>
#include <circle/usb/usbkeyboard.h>
#include <circle/input/mouse.h>
Expand Down
20 changes: 11 additions & 9 deletions modules/adlib/adlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,16 @@ static const char *name(struct adlib *a) {
(void)a; return "AdLib Music Synthesizer";
}

VXTU_MODULE_CREATE(adlib, {
DEVICE->freq = 48000;
if (FRONTEND)
DEVICE->set_audio_adapter = ((struct frontend_interface*)FRONTEND)->set_audio_adapter;
static struct vxt_peripheral *create(vxt_allocator *alloc, void *frontend, const char *args) VXT_PERIPHERAL_CREATE(alloc, adlib, {
if (frontend)
DEVICE->set_audio_adapter = ((struct frontend_interface*)frontend)->set_audio_adapter;

PERIPHERAL->install = &install;
PERIPHERAL->reset = &reset;
PERIPHERAL->name = &name;
PERIPHERAL->io.in = &in;
PERIPHERAL->io.out = &out;
DEVICE->freq = 48000;
PERIPHERAL->install = &install;
PERIPHERAL->reset = &reset;
PERIPHERAL->name = &name;
PERIPHERAL->io.in = &in;
PERIPHERAL->io.out = &out;
})

VXTU_MODULE_ENTRIES(&create)
17 changes: 11 additions & 6 deletions premake5.lua
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ workspace "virtualxt"

cleancommands {
"{RMFILE} modules/" .. name .. ".*",
"make clean %{cfg.buildcfg}"
"${MAKE} clean %{cfg.buildcfg}"
}

filter {}
Expand Down Expand Up @@ -258,7 +258,7 @@ workspace "virtualxt"

cleancommands {
"{RMDIR} build/libretro",
"make clean %{cfg.buildcfg}"
"${MAKE} clean %{cfg.buildcfg}"
}

filter "toolset:clang or gcc"
Expand Down Expand Up @@ -320,7 +320,7 @@ workspace "virtualxt"

cleancommands {
"{RMDIR} build/web",
"make clean %{cfg.buildcfg}"
"${MAKE} clean %{cfg.buildcfg}"
}

project "sdl2-frontend"
Expand Down Expand Up @@ -349,7 +349,7 @@ workspace "virtualxt"

cleancommands {
"{RMDIR} build/sdl2",
"make clean %{cfg.buildcfg}"
"${MAKE} clean %{cfg.buildcfg}"
}

filter "action:vs*"
Expand Down Expand Up @@ -402,7 +402,7 @@ workspace "virtualxt"

cleancommands {
"{RMDIR} build/sdl3",
"make clean %{cfg.buildcfg}"
"${MAKE} clean %{cfg.buildcfg}"
}

filter "action:vs*"
Expand Down Expand Up @@ -452,7 +452,7 @@ workspace "virtualxt"

cleancommands {
"{RMDIR} build/terminal",
"make clean %{cfg.buildcfg}"
"${MAKE} clean %{cfg.buildcfg}"
}

filter "options:validator"
Expand All @@ -468,6 +468,11 @@ workspace "virtualxt"
filter "toolset:gcc"
buildoptions "-Wno-maybe-uninitialized"

project "rpi-frontend"
kind "Makefile"
buildcommands "${MAKE} -C front/rpi"
cleancommands "${MAKE} -C front/rpi clean"

if _OPTIONS["test"] then
project "test"
kind "ConsoleApp"
Expand Down

0 comments on commit ebd13f0

Please sign in to comment.