Skip to content

Commit

Permalink
Kind of working dual OPL2 playback using EMU8950_LINEAR/SLOT_RENDER
Browse files Browse the repository at this point in the history
  • Loading branch information
polpo committed Jul 25, 2024
1 parent 73f3f7d commit 6d80f9a
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 28 deletions.
39 changes: 33 additions & 6 deletions sw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,17 @@ add_subdirectory(opl)
################################################################################
# Build GUS firmware
function(build_gus TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
#set(USB_JOYSTICK TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-gus")
target_sources(${TARGET_NAME} PRIVATE gusplay.cpp pico_pic.c isa_dma.c)
target_sources(${TARGET_NAME} PRIVATE
mpu401/mpu401.c
mpu401/midi.c
)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_GUS=1
SOUND_MPU=1
PSRAM=1
TEST_PSRAM=1
PSRAM_ASYNC=1
Expand All @@ -173,31 +178,51 @@ function(build_gus TARGET_NAME MULTIFW)
)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa_dma.pio)
target_link_libraries(${TARGET_NAME} rp2040-psram hardware_interp)
pico_enable_stdio_uart(${TARGET_NAME} 1)
pico_enable_stdio_usb(${TARGET_NAME} 0)
pico_enable_stdio_uart(${TARGET_NAME} 0)
pico_enable_stdio_usb(${TARGET_NAME} 1)
pico_enable_stdio_semihosting(${TARGET_NAME} 0)
endfunction()

################################################################################
# Build SB firmware
function(build_sb TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
#set(USB_JOYSTICK TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-sb")
target_sources(${TARGET_NAME} PRIVATE sbdsp.cpp sbplay.cpp pico_pic.c isa_dma.c)
target_link_libraries(${TARGET_NAME} opl)
target_sources(${TARGET_NAME} PRIVATE
mpu401/mpu401.c
mpu401/midi.c
)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_SB=1
SOUND_OPL=1
SOUND_DSP=1
SOUND_MPU=1
USE_ALARM=1
USE_EMU8950_OPL=1
EMU8950_ASM=1
EMU8950_NO_WAVE_TABLE_MAP=1
EMU8950_NO_TLL=1 # don't use lookup table for total level
EMU8950_NO_FLOAT=1 # double check there is no float
EMU8950_NO_TIMER=1 # disable timer which isn't used
EMU8950_NO_TEST_FLAG=1 # disable test flags (which aren't used)
EMU8950_SIMPLER_NOISE=1 # only generate noise bit when needed
EMU8950_SHORT_NOISE_UPDATE_CHECK=1 # only update short noise if it is used
# actually this doesn't make things faster
#EMU8950_LINEAR_NEG_NOT_NOT=1 # negative values rounded towrds -infinity not 0 without this; does it matter?
EMU8950_LINEAR_SKIP=1 # skip silent slots
EMU8950_LINEAR_END_OF_NOTE_OPTIMIZATION=1 # early out envelope when DECAY/SUSTAIN/RELEASE envelope reaches mute
EMU8950_NO_PERCUSSION_MODE=1 # rhythm only mode (doom doesn't use percussion; whhhaaaah!?)
EMU8950_LINEAR=1 # reorganize to do linear runs of channels
EMU8950_SLOT_RENDER=1

# PICOW=1
)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa_dma.pio)
pico_enable_stdio_uart(${TARGET_NAME} 1)
pico_enable_stdio_usb(${TARGET_NAME} 0)
pico_enable_stdio_uart(${TARGET_NAME} 0)
pico_enable_stdio_usb(${TARGET_NAME} 1)
pico_enable_stdio_semihosting(${TARGET_NAME} 0)
endfunction()

Expand Down Expand Up @@ -230,6 +255,8 @@ function(build_mpu TARGET_NAME MULTIFW)
pico_set_program_name(${TARGET_NAME} "picogus-mpu401")
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_MPU=1
MPU_ONLY=1
MPU_IRQ=1
)
target_sources(${TARGET_NAME} PRIVATE
pico_pic.c
Expand Down
5 changes: 4 additions & 1 deletion sw/clamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ static void clamp_setup(void) {
#endif
}

#ifndef INLINE
#define INLINE __force_inline
#endif

static int16_t __force_inline clamp16(int32_t d) {
static INLINE int16_t clamp16(int32_t d) {
#ifdef INTERP_CLAMP
interp1->accum[0] = d;
return interp1->peek[0];
Expand Down
2 changes: 1 addition & 1 deletion sw/mpuplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void play_mpu() {
MPU401_Init(settings.MPU.delaySysex, settings.MPU.fakeAllNotesOff);

for (;;) {
send_midi_byte(4); // see if we need to send a byte
send_midi_bytes(4); // see if we need to send a byte
#ifdef USB_STACK
// Service TinyUSB events
tuh_task();
Expand Down
18 changes: 12 additions & 6 deletions sw/opl/emu8950.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#endif
#endif

#include "../clamp.h"

#define _PI_ 3.14159265358979323846264338327950288

/* dynamic range of envelope output */
Expand Down Expand Up @@ -727,6 +729,7 @@ static INLINE void set_block(OPL *opl, int ch, int blk) {
}

static INLINE void update_perc_mode(OPL *opl) {
if ((opl->reg[0xbd] >> 5) & 1) printf("perc");
#if !EMU8950_NO_PERCUSSION_MODE
const uint8_t new_perc_mode = (opl->reg[0xbd] >> 5) & 1;

Expand Down Expand Up @@ -1723,9 +1726,9 @@ uint32_t __not_in_flash_func(slot_car_linear_alg0)(OPL *opl, OPL_SLOT *slot, uin
}
#endif

static_assert(EMU8950_NO_PERCUSSION_MODE, "");
//static_assert(EMU8950_NO_PERCUSSION_MODE, "");
// this produces stereo
void OPL_calc_buffer_linear(OPL *opl, int32_t *buffer, uint32_t nsamples) {
static INLINE void OPL_calc_buffer_linear(OPL *opl, int32_t *buffer, uint32_t nsamples) {
int i;
#if EMU8950_SLOT_RENDER
// kind of a nit pick, but so cheap - saves a bug every 24 hours due to an optimization
Expand Down Expand Up @@ -1852,8 +1855,11 @@ void OPL_calc_buffer_linear(OPL *opl, int32_t *buffer, uint32_t nsamples) {
}
#endif

void OPL_calc_buffer_stereo(OPL *opl, int32_t *buffer, uint32_t nsamples) {
static int32_t buffer[256];

void OPL_calc_buffer_stereo(OPL *opl, int16_t *in_buffer, uint32_t nsamples) {
assert(opl->out_step == opl->inp_step);
memset(buffer, 0, nsamples * sizeof(int32_t));
#if DUMPO
bc++;
#endif
Expand All @@ -1869,7 +1875,7 @@ void OPL_calc_buffer_stereo(OPL *opl, int32_t *buffer, uint32_t nsamples) {
printf("\n");
#endif

buffer[i] = (raw << 16u) | raw;
in_buffer[i] = raw;
}
#else
OPL_calc_buffer_linear(opl, buffer, nsamples);
Expand All @@ -1883,10 +1889,10 @@ void OPL_calc_buffer_stereo(OPL *opl, int32_t *buffer, uint32_t nsamples) {
}
printf("\n");
#else
uint16_t raw = buffer[i] >> 1; // _MO()
//uint16_t raw = buffer[i];// >> 1; // _MO()
#endif
// todo clamp?
buffer[i] = (raw << 16u) | raw;
in_buffer[i] = clamp16(buffer[i]);
}
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion sw/opl/emu8950.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ int16_t OPL_calc(OPL *opl);

void OPL_calc_buffer(OPL *opl, int16_t *buffer, uint32_t nsamples);
// LE left/right channels int16:int16
void OPL_calc_buffer_stereo(OPL *opl, int32_t *buffer, uint32_t nsamples);
void OPL_calc_buffer_stereo(OPL *opl, int16_t *buffer, uint32_t nsamples);

/**
* Set channel mask
Expand Down
11 changes: 7 additions & 4 deletions sw/opl/opl_pico.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ void OPL_Pico_simple(int16_t *buffer, uint32_t nsamples) {
}

void OPL_Pico_stereo(int16_t *buffer_l, int16_t *buffer_r, uint32_t nsamples) {
OPL_calc_buffer(opl_l.emu8950_opl, buffer_l, nsamples);
OPL_calc_buffer(opl_r.emu8950_opl, buffer_r, nsamples);
//OPL_calc_buffer_linear(opl_l.emu8950_opl, buffer_l, nsamples);
OPL_calc_buffer_stereo(opl_l.emu8950_opl, buffer_l, nsamples);
OPL_calc_buffer_stereo(opl_r.emu8950_opl, buffer_r, nsamples);
//OPL_calc_buffer(opl_l.emu8950_opl, buffer_l, nsamples);
//OPL_calc_buffer(opl_r.emu8950_opl, buffer_r, nsamples);
}

int OPL_Pico_Init(void)
Expand Down Expand Up @@ -134,7 +137,7 @@ static void WriteRegister(opl_instance_t* opl, unsigned int reg_num, unsigned in
{
switch (reg_num)
{
#if !EMU8950_NO_TIMER
//#if !EMU8950_NO_TIMER
case OPL_REG_TIMER1:
opl->timer1.value = value;
OPLTimer_CalculateEndTime(&opl->timer1);
Expand Down Expand Up @@ -168,7 +171,7 @@ static void WriteRegister(opl_instance_t* opl, unsigned int reg_num, unsigned in
}

break;
#endif
//#endif
case OPL_REG_NEW:
default:
OPL_writeReg(opl->emu8950_opl, reg_num, value);
Expand Down
8 changes: 4 additions & 4 deletions sw/sbdsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ typedef struct sbdsp_t {

uint16_t dma_interval;
// int16_t dma_interval_trim;
uint8_t dma_transfer_size;
uint8_t dma_buffer[DSP_DMA_FIFO_SIZE];
volatile uint16_t dma_buffer_tail;
volatile uint16_t dma_buffer_head;
// uint8_t dma_transfer_size;
// uint8_t dma_buffer[DSP_DMA_FIFO_SIZE];
// volatile uint16_t dma_buffer_tail;
// volatile uint16_t dma_buffer_head;

uint16_t dma_pause_duration;
uint8_t dma_pause_duration_low;
Expand Down
24 changes: 19 additions & 5 deletions sw/sbplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Minimum expected sample rate from DSP should be 8000hz?
Maximum number of DSP to process at once should be 64.
49716 / 8000 = 6.2145 * 64 = 397
*/
#define SAMPLES_PER_BUFFER 512
#define SAMPLES_PER_BUFFER 8

struct audio_buffer_pool *init_audio() {

Expand Down Expand Up @@ -146,17 +146,31 @@ void play_adlib() {
struct audio_buffer *buffer = take_audio_buffer(ap, true);
int16_t *samples = (int16_t *) buffer->buffer->bytes;
#ifdef SOUND_SB
int16_t sb_sample = sbdsp_sample();
int16_t opl_samples[2];
OPL_Pico_stereo(&opl_samples[0], &opl_samples[1], 1);
int16_t sb_sample = 0; //sbdsp_sample();
//

int16_t opl_samples_l[SAMPLES_PER_BUFFER];
int16_t opl_samples_r[SAMPLES_PER_BUFFER];
//uint32_t audio_begin = time_us_32();
OPL_Pico_stereo(opl_samples_l, opl_samples_r, SAMPLES_PER_BUFFER);
/*
samples[0] = clamp16((int32_t)sb_sample + (int32_t)opl_samples[0]);
samples[1] = clamp16((int32_t)sb_sample + (int32_t)opl_samples[1]);
*/
for (int i = 0; i < SAMPLES_PER_BUFFER; ++i) {
samples[i << 1] = opl_samples_l[i];
samples[(i << 1) + 1] = opl_samples_r[i];
}
//uint32_t audio_elapsed = time_us_32() - audio_begin;
//if (audio_elapsed > 5149) {
// printf("%u ", audio_elapsed);
//}
#else
int16_t opl_sample;
OPL_Pico_simple(&opl_sample, 1);
samples[0] = samples[1] = opl_sample;
#endif
buffer->sample_count=1;
buffer->sample_count=SAMPLES_PER_BUFFER;
// putchar((unsigned char)buffer->buffer->bytes[1]);
give_audio_buffer(ap, buffer);
#ifdef USB_STACK
Expand Down

0 comments on commit 6d80f9a

Please sign in to comment.