Merge pull request #5378 from NishiOwO/audio4

audio(4) support
This commit is contained in:
Miran Grča
2025-03-24 13:54:05 +01:00
committed by GitHub
4 changed files with 172 additions and 3 deletions

View File

@@ -20,8 +20,8 @@
#ifndef EMU_86BOX_H
#define EMU_86BOX_H
#ifdef __NetBSD__
/* Doesn't compile on NetBSD without this include */
#if defined(__NetBSD__) || defined(__OpenBSD__)
/* Doesn't compile on NetBSD/OpenBSD without this include */
#include <stdarg.h>
#endif

View File

@@ -53,7 +53,10 @@ add_library(snd OBJECT
snd_opl_esfm.c
)
if(OPENAL)
# TODO: Should platform-specific audio driver be here?
if(AUDIO4)
target_sources(snd PRIVATE audio4.c)
elseif(OPENAL)
if(VCPKG_TOOLCHAIN)
find_package(OpenAL CONFIG REQUIRED)
elseif(MINGW)

160
src/sound/audio4.c Normal file
View File

@@ -0,0 +1,160 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Interface to audio(4) for NetBSD/OpenBSD.
*
*
* Authors: Nishi
*
* Copyright 2025 Nishi.
*/
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/audioio.h>
#include <sys/param.h>
#include <86box/86box.h>
#include <86box/sound.h>
#include <86box/plat_unused.h>
#if defined(OpenBSD) && OpenBSD >= 201709
#define USE_NEW_API
#endif
#define I_NORMAL 0
#define I_MUSIC 1
#define I_WT 2
#define I_CD 3
#define I_MIDI 4
static int audio[5] = {-1, -1, -1, -1, -1};
#ifdef USE_NEW_API
static struct audio_swpar info[5];
#else
static audio_info_t info[5];
#endif
static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0};
void closeal(void){
int i;
for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){
if(audio[i] != -1){
close(audio[i]);
}
audio[i] = -1;
}
}
void inital(void){
int i;
for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){
audio[i] = open("/dev/audio", O_WRONLY);
if(audio[i] == -1) audio[i] = open("/dev/audio0", O_WRONLY);
if(audio[i] != -1){
#ifdef USE_NEW_API
AUDIO_INITPAR(&info[i]);
ioctl(audio[i], AUDIO_GETPAR, &info[i]);
info[i].pchan = 2;
info[i].bits = 16;
info[i].bps = 2;
ioctl(audio[i], AUDIO_SETPAR, &info[i]);
#else
AUDIO_INITINFO(&info[i]);
#if defined(__NetBSD__) && (__NetBSD_Version__ >= 900000000)
ioctl(audio[i], AUDIO_GETFORMAT, &info[i]);
#else
ioctl(audio[i], AUDIO_GETINFO, &info[i]);
#endif
info[i].play.channels = 2;
info[i].play.precision = 16;
info[i].play.encoding = AUDIO_ENCODING_SLINEAR;
info[i].hiwat = 5;
info[i].lowat = 3;
ioctl(audio[i], AUDIO_SETINFO, &info[i]);
#endif
}
}
}
void givealbuffer_common(const void *buf, const uint8_t src, const int size){
const int freq = freqs[src];
int16_t* output;
int output_size;
int16_t* conv;
int conv_size;
int i;
double gain;
int target_rate;
if(audio[src] == -1) return;
gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0);
if(sound_is_float){
float* input = (float*)buf;
conv_size = sizeof(int16_t) * size;
conv = malloc(conv_size);
for(i = 0; i < conv_size / sizeof(int16_t); i++){
conv[i] = 32767 * input[i];
}
}else{
conv_size = size * sizeof(int16_t);
conv = malloc(conv_size);
memcpy(conv, buf, conv_size);
}
#ifdef USE_NEW_API
target_rate = info[src].rate;
#else
target_rate = info[src].play.sample_rate;
#endif
output_size = (double)conv_size * target_rate / freq;
output_size -= output_size % 4;
output = malloc(output_size);
for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){
int ind = i * freq / target_rate * 2;
output[i * 2 + 0] = conv[ind + 0] * gain;
output[i * 2 + 1] = conv[ind + 1] * gain;
}
write(audio[src], output, output_size);
free(conv);
free(output);
}
void givealbuffer(const void *buf){
givealbuffer_common(buf, I_NORMAL, SOUNDBUFLEN << 1);
}
void givealbuffer_music(const void *buf){
givealbuffer_common(buf, I_MUSIC, MUSICBUFLEN << 1);
}
void givealbuffer_wt(const void *buf){
givealbuffer_common(buf, I_WT, WTBUFLEN << 1);
}
void givealbuffer_cd(const void *buf){
givealbuffer_common(buf, I_CD, CD_BUFLEN << 1);
}
void givealbuffer_midi(const void *buf, const uint32_t size){
givealbuffer_common(buf, I_MIDI, (int) size);
}
void al_set_midi(const int freq, UNUSED(const int buf_size)){
freqs[I_MIDI] = freq;
}