mirror of
https://github.com/polpo/picogus.git
synced 2026-10-25 21:40:16 +00:00
Volume control
This commit is contained in:
1 parent
a2904c9929
commit
c84773c562
13 files changed
+379
-14
No files matched your search
@@ -88,6 +88,13 @@ static const char *modenames[8] = {
|
||||
#define MODE_CDNAME 0x65 // Get name of loaded CD image
|
||||
#define MODE_CDAUTOADV 0x66 // Set autoadvance for CD image on USB reinsert
|
||||
|
||||
#define MODE_MAINVOL 0x70 // Main Volume
|
||||
#define MODE_OPLVOL 0x71 // Adlib volume
|
||||
#define MODE_SBVOL 0x72 // Sound Blaster volume
|
||||
#define MODE_CDVOL 0x73 // CD Audio Volume
|
||||
#define MODE_GUSVOL 0x74 // GUS Volume
|
||||
#define MODE_PSGVOL 0x75 // PSG Volume
|
||||
|
||||
#define MODE_DEFAULTS 0xE0 // Select reset to defaults register
|
||||
#define MODE_SAVE 0xE1 // Select save settings register
|
||||
#define MODE_REBOOT 0xE2 // Select reboot register
|
||||
|
||||
+106
-2
@@ -42,6 +42,7 @@ static void usage(card_mode_t mode, bool print_all) {
|
||||
printf(" /defaults - set all settings for all modes to defaults\n");
|
||||
printf(" /wtvol x - set volume of WT header. 0-100, Default 100 (2.0 cards only)\n");
|
||||
printf(" /joy 1|0 - enable/disable USB joystick support, Default: 0\n");
|
||||
printf(" /mainvol x - set the main audio volume: 0 - 100\n");
|
||||
// "...............................................................................\n"
|
||||
printf("MPU-401 settings:\n");
|
||||
printf(" /mpuport x - set the base port of the MPU-401. Default: 330, 0 to disable\n");
|
||||
@@ -57,16 +58,19 @@ static void usage(card_mode_t mode, bool print_all) {
|
||||
printf(" Specifying 0 restores the GUS default behavior.\n");
|
||||
printf(" (increase to fix games with streaming audio like Doom)\n");
|
||||
printf(" /gus44k 1|0 - Fixed 44.1kHz output for all active voice #s [EXPERIMENTAL]\n");
|
||||
printf(" /gusvol x - set the GUS audio volume: 0 - 100\n");
|
||||
}
|
||||
if (mode == SB_MODE || print_all) {
|
||||
// "...............................................................................\n"
|
||||
printf("Sound Blaster settings:\n");
|
||||
printf(" /sbport x - set the base port of the Sound Blaster. Default: 220\n");
|
||||
printf(" /sbvol x - set the Sound Blaster audio volume: 0 - 100%\n");
|
||||
}
|
||||
if (mode == SB_MODE || mode == ADLIB_MODE || print_all) {
|
||||
printf("AdLib settings:\n");
|
||||
printf(" /oplport x - set the base port of the OPL2. Default: 388, 0 to disable\n");
|
||||
printf(" /oplwait 1|0 - wait on OPL2 write. Can fix speed-sensitive early AdLib games\n");
|
||||
printf(" /oplvol x - set the OPL2 audio volume: 0 - 100\n");
|
||||
}
|
||||
if (mode == SB_MODE || mode == USB_MODE || print_all) {
|
||||
printf("CD-ROM settings:\n");
|
||||
@@ -74,17 +78,20 @@ static void usage(card_mode_t mode, bool print_all) {
|
||||
printf(" /cdlist - list CD images on the inserted USB drive\n");
|
||||
printf(" /cdload n - load image n in the list given by /cdlist. 0 to unload image\n");
|
||||
printf(" /cdloadname x - load CD image by name. Names with spaces can be quoted\n");
|
||||
printf(" /cdvol n - set the CD audio volume: 0 - 100\n");
|
||||
printf(" /cdauto 1|0 - auto-advance loaded image when same USB drive is reinserted\n");
|
||||
}
|
||||
if (mode == PSG_MODE || print_all) {
|
||||
// "...............................................................................\n"
|
||||
printf("Tandy settings:\n");
|
||||
printf(" /tandyport x - set the base port of the Tandy 3-voice. Default: 2C0\n");
|
||||
printf(" /psgvol x - set the PSG audio volume: 0 - 100\n");
|
||||
}
|
||||
if (mode == PSG_MODE || print_all) {
|
||||
// "...............................................................................\n"
|
||||
printf("CMS settings:\n");
|
||||
printf(" /cmsport x - set the base port of the CMS. Default: 220\n");
|
||||
printf(" /psgvol x - set the PSG audio volume: 0 - 100\n");
|
||||
}
|
||||
if (mode == USB_MODE || mode == PSG_MODE || mode == ADLIB_MODE || print_all) {
|
||||
// "...............................................................................\n"
|
||||
@@ -326,7 +333,10 @@ static void print_cdemu_status(void) {
|
||||
uint8_t tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
outp(CONTROL_PORT, MODE_CDPORT); // Select port register
|
||||
uint16_t tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
|
||||
printf("CD-ROM emulation on port %x, image auto-advance %s\n", tmp_uint16, tmp_uint8 ? "enabled" : "disabled");
|
||||
outp(CONTROL_PORT, MODE_CDVOL); // Select CD volume register
|
||||
uint16_t tmp_vol = inp(DATA_PORT_HIGH);
|
||||
printf("CD-ROM emulation on port %x, image auto-advance %s\nCD-Audio Volume: %u%\n", tmp_uint16, tmp_uint8 ? "enabled" : "disabled", tmp_vol);
|
||||
|
||||
print_cdimage_current();
|
||||
}
|
||||
|
||||
@@ -508,7 +518,6 @@ static void send_string(uint8_t mode, char* str, int16_t max_len)
|
||||
outp(DATA_PORT_HIGH, 0);
|
||||
}
|
||||
|
||||
|
||||
#define process_bool_opt(option) \
|
||||
if (i + 1 >= argc) { \
|
||||
usage(mode, false); \
|
||||
@@ -833,6 +842,78 @@ int main(int argc, char* argv[]) {
|
||||
process_bool_opt(tmp_uint8);
|
||||
outp(CONTROL_PORT, MODE_CDAUTOADV); // Select CD image autoadvance register
|
||||
outp(DATA_PORT_HIGH, tmp_uint8);
|
||||
} else if (stricmp(argv[i], "/mainvol") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
usage(mode, false);
|
||||
return 255;
|
||||
}
|
||||
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
|
||||
if (e != 1 || tmp_uint8 > 100) {
|
||||
usage(mode, false);
|
||||
return 4;
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_MAINVOL); // Set the volume for all outputs
|
||||
outp(DATA_PORT_HIGH, tmp_uint8);
|
||||
} else if (stricmp(argv[i], "/oplvol") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
usage(mode, false);
|
||||
return 255;
|
||||
}
|
||||
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
|
||||
if (e != 1 || tmp_uint8 > 100) {
|
||||
usage(mode, false);
|
||||
return 4;
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_OPLVOL); // Set the volume for Sound Blaster
|
||||
outp(DATA_PORT_HIGH, tmp_uint8);
|
||||
} else if (stricmp(argv[i], "/sbvol") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
usage(mode, false);
|
||||
return 255;
|
||||
}
|
||||
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
|
||||
if (e != 1 || tmp_uint8 > 100) {
|
||||
usage(mode, false);
|
||||
return 4;
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_SBVOL); // Set the volume for Sound Blaster
|
||||
outp(DATA_PORT_HIGH, tmp_uint8);
|
||||
} else if (stricmp(argv[i], "/cdvol") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
usage(mode, false);
|
||||
return 255;
|
||||
}
|
||||
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
|
||||
if (e != 1 || tmp_uint8 > 100) {
|
||||
usage(mode, false);
|
||||
return 4;
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_CDVOL); // Set the volume for CD Audio
|
||||
outp(DATA_PORT_HIGH, tmp_uint8);
|
||||
} else if (stricmp(argv[i], "/gusvol") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
usage(mode, false);
|
||||
return 255;
|
||||
}
|
||||
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
|
||||
if (e != 1 || tmp_uint8 > 100) {
|
||||
usage(mode, false);
|
||||
return 4;
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_GUSVOL); // Set the volume for GUS
|
||||
outp(DATA_PORT_HIGH, tmp_uint8);
|
||||
} else if (stricmp(argv[i], "/psgvol") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
usage(mode, false);
|
||||
return 255;
|
||||
}
|
||||
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
|
||||
if (e != 1 || tmp_uint8 > 100) {
|
||||
usage(mode, false);
|
||||
return 4;
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_PSGVOL); // Set the volume for PSG
|
||||
outp(DATA_PORT_HIGH, tmp_uint8);
|
||||
} else {
|
||||
printf("Unknown option: %s\n", argv[i]);
|
||||
usage(mode, false);
|
||||
@@ -929,6 +1010,11 @@ int main(int argc, char* argv[]) {
|
||||
outp(CONTROL_PORT, MODE_GUSPORT); // Select port register
|
||||
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
|
||||
printf("Running in GUS mode on port %x\n", tmp_uint16);
|
||||
outp(CONTROL_PORT, MODE_GUSVOL); // Select GUS volume register
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
outp(CONTROL_PORT, MODE_MAINVOL); // Select Main volume register
|
||||
tmp_uint16 = inp(DATA_PORT_HIGH);
|
||||
printf("Volume: GUS: %u Main: %u\n", tmp_uint8, tmp_uint16);
|
||||
break;
|
||||
case ADLIB_MODE:
|
||||
outp(CONTROL_PORT, MODE_OPLPORT); // Select port register
|
||||
@@ -952,6 +1038,11 @@ int main(int argc, char* argv[]) {
|
||||
outp(CONTROL_PORT, MODE_CMSPORT); // Select port register
|
||||
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
|
||||
printf("CMS/Game Blaster on port %x)\n", tmp_uint16);
|
||||
outp(CONTROL_PORT, MODE_PSGVOL); // Select PSG volume register
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
outp(CONTROL_PORT, MODE_MAINVOL); // Select Main volume register
|
||||
tmp_uint16 = inp(DATA_PORT_HIGH);
|
||||
printf("Volume: PSG: %u Main: %u\n", tmp_uint8, tmp_uint16);
|
||||
break;
|
||||
case SB_MODE:
|
||||
if (init_sb()) {
|
||||
@@ -967,9 +1058,22 @@ int main(int argc, char* argv[]) {
|
||||
outp(CONTROL_PORT, MODE_OPLWAIT); // Select Adlib wait register
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("%s)\n", tmp_uint8 ? ", wait on" : "");
|
||||
outp(CONTROL_PORT, MODE_OPLVOL); // Select Adlib volume register
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("Volume: ");
|
||||
printf("OPL: %u ", tmp_uint8);
|
||||
} else {
|
||||
printf("(AdLib port disabled)\n");
|
||||
printf("Volume: ");
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_SBVOL); // Select Sound Blaster volume register
|
||||
uint8_t tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("SB: %u ", tmp_uint8);
|
||||
|
||||
outp(CONTROL_PORT, MODE_MAINVOL); // Select Sound Blaster volume register
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("Main: %u \n", tmp_uint8);
|
||||
|
||||
print_cdemu_status();
|
||||
break;
|
||||
case NE2000_MODE:
|
||||
|
||||
+11
-2
@@ -204,6 +204,7 @@ function(build_gus TARGET_NAME MULTIFW)
|
||||
config_target(${TARGET_NAME} ${MULTIFW})
|
||||
pico_set_program_name(${TARGET_NAME} "picogus-gus")
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
volctrl.cpp
|
||||
gusplay.cpp
|
||||
isa_dma.c
|
||||
)
|
||||
@@ -241,6 +242,7 @@ function(build_sb TARGET_NAME MULTIFW)
|
||||
config_target(${TARGET_NAME} ${MULTIFW})
|
||||
pico_set_program_name(${TARGET_NAME} "picogus-sb")
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
volctrl.cpp
|
||||
sbdsp.cpp
|
||||
sbplay.cpp
|
||||
isa_dma.c
|
||||
@@ -263,7 +265,10 @@ function(build_adlib TARGET_NAME MULTIFW)
|
||||
set(SOUND_OPL TRUE)
|
||||
config_target(${TARGET_NAME} ${MULTIFW})
|
||||
pico_set_program_name(${TARGET_NAME} "picogus-adlib")
|
||||
target_sources(${TARGET_NAME} PRIVATE sbplay.cpp)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
volctrl.cpp
|
||||
sbplay.cpp
|
||||
)
|
||||
endfunction()
|
||||
|
||||
################################################################################
|
||||
@@ -295,6 +300,7 @@ function(build_psg TARGET_NAME MULTIFW)
|
||||
SOUND_CMS=1
|
||||
)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
volctrl.cpp
|
||||
square/square.cpp
|
||||
)
|
||||
target_sources(${TARGET_NAME} PRIVATE psgplay.cpp)
|
||||
@@ -312,7 +318,10 @@ function(build_usb TARGET_NAME MULTIFW)
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE
|
||||
USB_ONLY=1
|
||||
)
|
||||
target_sources(${TARGET_NAME} PRIVATE usbplay.cpp)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
volctrl.cpp
|
||||
usbplay.cpp
|
||||
)
|
||||
endfunction()
|
||||
|
||||
|
||||
|
||||
+9
-1
@@ -32,6 +32,7 @@
|
||||
#include "cdrom_error_msg.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/structs/timer.h"
|
||||
#include "../volctrl.h"
|
||||
|
||||
|
||||
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
|
||||
@@ -399,7 +400,14 @@ uint32_t cdrom_audio_callback_simple(cdrom_t *dev, int16_t *buffer, uint32_t len
|
||||
|
||||
/* printf("%u\n", samples_to_transfer); */
|
||||
// Add samples from sector buffer to FIFO
|
||||
memcpy(buffer + samples_produced, &dev->current_sector_samples[dev->audio_sector_consumed_samples], samples_to_transfer * sizeof(int16_t));
|
||||
//memcpy(buffer + samples_produced, &dev->current_sector_samples[dev->audio_sector_consumed_samples], samples_to_transfer * sizeof(int16_t));
|
||||
|
||||
for (uint32_t i = 0; i < samples_to_transfer; i++)
|
||||
{
|
||||
int32_t sample = dev->current_sector_samples[dev->audio_sector_consumed_samples + i];
|
||||
buffer[samples_produced + i] = (int16_t)scale_sample(sample, cd_audio_volume, 0);
|
||||
}
|
||||
|
||||
samples_produced += samples_to_transfer;
|
||||
dev->audio_sector_consumed_samples += samples_to_transfer;
|
||||
} // End while (fifo_level < len && ret)
|
||||
|
||||
+5
-1
@@ -15,6 +15,7 @@
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright (C) 2024 Kevin Moonlight
|
||||
* Copyright (C) 2025 Ian Scott
|
||||
* Copyright (C) 2025 Daniel Arnold
|
||||
*/
|
||||
|
||||
#ifndef EMU_CDROM_H
|
||||
@@ -61,7 +62,6 @@
|
||||
#define STAT_DISK 0x40
|
||||
#define STAT_TRAY 0x80
|
||||
|
||||
|
||||
/* This is so that if/when this is changed to something else,
|
||||
changing this one define will be enough. */
|
||||
#define CDROM_EMPTY !dev->host_drive
|
||||
@@ -201,6 +201,7 @@ typedef struct cdrom {
|
||||
int16_t *current_sector_samples; // Convenience pointer: (int16_t*)audio_sector_buffer
|
||||
int audio_sector_total_samples; // Samples available in current_sector_samples after a read
|
||||
int audio_sector_consumed_samples; // Samples consumed from current_sector_samples
|
||||
|
||||
#if USE_CD_AUDIO_FIFO
|
||||
audio_fifo_t audio_fifo;
|
||||
#endif
|
||||
@@ -272,6 +273,9 @@ extern int find_cdrom_for_scsi_id(uint8_t scsi_id);
|
||||
extern void cdrom_close(void);
|
||||
extern void cdrom_global_init(void);
|
||||
|
||||
extern int32_t cd_audio_volume;
|
||||
extern void cdrom_set_volume_scale(uint8_t percent);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -77,6 +77,14 @@ static const Settings defaultSettings = {
|
||||
.MMB = {
|
||||
// Mindscape Music Board defaults to off because its port is so common
|
||||
.basePort = 0xffff
|
||||
},
|
||||
.Volume = {
|
||||
.mainVol = 100,
|
||||
.oplVol = 90,
|
||||
.sbVol = 100,
|
||||
.cdVol = 100,
|
||||
.gusVol = 100,
|
||||
.psgVol = 80
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -80,6 +80,14 @@ typedef struct Settings {
|
||||
struct {
|
||||
uint16_t basePort;
|
||||
} MMB;
|
||||
struct {
|
||||
uint8_t mainVol;
|
||||
uint8_t oplVol;
|
||||
uint8_t sbVol;
|
||||
uint8_t cdVol;
|
||||
uint8_t gusVol;
|
||||
uint8_t psgVol;
|
||||
} Volume;
|
||||
} Settings;
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ critical_section_t gus_crit;
|
||||
extern dma_inst_t dma_config;
|
||||
|
||||
#include "clamp.h"
|
||||
#include "volctrl.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -615,6 +616,7 @@ class GUSChannels {
|
||||
|
||||
// Output stereo sample if DAC enable on
|
||||
// if ((GUS_reset_reg & 0x02/*DAC enable*/) == 0x02) {
|
||||
tmpsamp = scale_sample(tmpsamp, gus_volume, 0);
|
||||
stream[0] += tmpsamp * VolLeft;
|
||||
stream[1] += tmpsamp * VolRight;
|
||||
WaveUpdate();
|
||||
|
||||
+67
-1
@@ -58,6 +58,8 @@ uint LED_PIN;
|
||||
#include "M62429/M62429.h"
|
||||
M62429* m62429;
|
||||
|
||||
|
||||
|
||||
#ifdef SOUND_SB
|
||||
static uint16_t sb_port_test;
|
||||
extern void sbdsp_write(uint8_t address, uint8_t value);
|
||||
@@ -89,7 +91,6 @@ static uint32_t cur_read_idx;
|
||||
|
||||
#ifdef SOUND_GUS
|
||||
#include "gus-x.cpp"
|
||||
|
||||
#include "isa_dma.h"
|
||||
dma_inst_t dma_config;
|
||||
static uint16_t gus_port_test;
|
||||
@@ -140,6 +141,10 @@ uint8_t joystate_bin;
|
||||
void play_usb(void);
|
||||
#endif
|
||||
|
||||
#if SOUND_GUS || SOUND_SB || SOUND_OPL || CDROM || SOUND_TANDY || SOUND_CMS
|
||||
#include "volctrl.h"
|
||||
#endif
|
||||
|
||||
|
||||
// PicoGUS control and data ports
|
||||
static bool control_active = false;
|
||||
@@ -232,6 +237,12 @@ __force_inline void select_picogus(uint8_t value) {
|
||||
case MODE_CDSTATUS:
|
||||
case MODE_CDLOAD:
|
||||
case MODE_CDAUTOADV:
|
||||
case MODE_MAINVOL:
|
||||
case MODE_OPLVOL:
|
||||
case MODE_SBVOL:
|
||||
case MODE_CDVOL:
|
||||
case MODE_GUSVOL:
|
||||
case MODE_PSGVOL:
|
||||
break;
|
||||
case MODE_CDNAME:
|
||||
cur_write = 0;
|
||||
@@ -412,6 +423,45 @@ __force_inline void write_picogus_high(uint8_t value) {
|
||||
cdman_set_autoadvance(settings.CD.autoAdvance);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MODE_MAINVOL: // Set the volume for CD Audio
|
||||
settings.Volume.mainVol = value;
|
||||
|
||||
#if SOUND_GUS || SOUND_SB || SOUND_OPL || CDROM || SOUND_TANDY || SOUND_CMS
|
||||
set_volume(MODE_MAINVOL);
|
||||
#endif
|
||||
break;
|
||||
case MODE_OPLVOL: // Set the volume for Adlib
|
||||
settings.Volume.oplVol = value;
|
||||
#ifdef SOUND_SB
|
||||
set_volume(MODE_OPLVOL);
|
||||
#endif
|
||||
break;
|
||||
case MODE_SBVOL: // Set the volume for Sound Blaster
|
||||
settings.Volume.sbVol = value;
|
||||
#ifdef SOUND_SB
|
||||
set_volume(MODE_SBVOL);
|
||||
#endif
|
||||
break;
|
||||
case MODE_CDVOL: // Set the volume for CD Audio
|
||||
settings.Volume.cdVol = value;
|
||||
#ifdef CDROM
|
||||
set_volume(MODE_CDVOL);
|
||||
#endif
|
||||
break;
|
||||
case MODE_GUSVOL: // Set the volume for GUS
|
||||
settings.Volume.gusVol = value;
|
||||
#ifdef SOUND_GUS
|
||||
set_volume(MODE_GUSVOL);
|
||||
#endif
|
||||
break;
|
||||
case MODE_PSGVOL: // Set the volume for PSG
|
||||
settings.Volume.psgVol = value;
|
||||
#if SOUND_PSG || SOUND_TANDY || SOUND_CMS
|
||||
set_volume(MODE_PSGVOL);
|
||||
#endif
|
||||
break;
|
||||
|
||||
// For multifw
|
||||
case MODE_BOOTMODE:
|
||||
settings.startupMode = value;
|
||||
@@ -565,6 +615,18 @@ __force_inline uint8_t read_picogus_high(void) {
|
||||
#endif
|
||||
case MODE_CDAUTOADV: // enable joystick
|
||||
return settings.CD.autoAdvance;
|
||||
case MODE_MAINVOL: // CD audio volume
|
||||
return settings.Volume.mainVol;
|
||||
case MODE_OPLVOL: // Adlib volume
|
||||
return settings.Volume.oplVol;
|
||||
case MODE_SBVOL: // Sound Blaster volume
|
||||
return settings.Volume.sbVol;
|
||||
case MODE_CDVOL: // CD audio volume
|
||||
return settings.Volume.cdVol;
|
||||
case MODE_GUSVOL: // GUS volume
|
||||
return settings.Volume.gusVol;
|
||||
case MODE_PSGVOL: // PSG volume
|
||||
return settings.Volume.psgVol;
|
||||
case MODE_HWTYPE: // Hardware version
|
||||
return BOARD_TYPE;
|
||||
case MODE_FLASH:
|
||||
@@ -579,12 +641,16 @@ __force_inline uint8_t read_picogus_high(void) {
|
||||
void processSettings(void) {
|
||||
#if defined(SOUND_GUS)
|
||||
settings.startupMode = GUS_MODE;
|
||||
set_volume(MODE_GUSVOL);
|
||||
#elif (SOUND_TANDY || SOUND_CMS)
|
||||
settings.startupMode = PSG_MODE;
|
||||
set_volume(MODE_PSGVOL);
|
||||
#elif defined(SOUND_SB)
|
||||
settings.startupMode = SB_MODE;
|
||||
set_volume(MODE_SBVOL);
|
||||
#elif defined(SOUND_OPL)
|
||||
settings.startupMode = ADLIB_MODE;
|
||||
set_volume(MODE_OPLVOL);
|
||||
#elif defined(MPU_ONLY)
|
||||
settings.startupMode = MPU_MODE;
|
||||
#elif defined(USB_ONLY)
|
||||
|
||||
+4
-3
@@ -32,6 +32,7 @@
|
||||
#include "square/square.h"
|
||||
|
||||
#include "cmd_buffers.h"
|
||||
#include "volctrl.h"
|
||||
|
||||
#if SOUND_TANDY
|
||||
extern tandy_buffer_t tandy_buffer;
|
||||
@@ -170,9 +171,9 @@ void play_psg() {
|
||||
cms.generator(0).generate_frames(buf, SAMPLES_PER_BUFFER);
|
||||
cms.generator(1).generate_frames(buf, SAMPLES_PER_BUFFER);
|
||||
#endif
|
||||
for (int i = 0; i < SAMPLES_PER_BUFFER; ++i) {
|
||||
samples[i << 1] = buf[i << 1] >> 1;
|
||||
samples[(i << 1) + 1] = buf[(i << 1) + 1] >> 1;
|
||||
for (int i = 0; i < SAMPLES_PER_BUFFER; ++i) {
|
||||
samples[i << 1] = scale_sample(buf[i << 1], psg_volume, 0);
|
||||
samples[(i << 1) + 1] = scale_sample(buf[(i << 1) + 1], psg_volume, 0);
|
||||
}
|
||||
buffer->sample_count = SAMPLES_PER_BUFFER;
|
||||
|
||||
|
||||
+24
-4
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/audio_i2s.h"
|
||||
#include "volctrl.h"
|
||||
|
||||
#include "opl.h"
|
||||
extern "C" void OPL_Pico_simple(int16_t *buffer, uint32_t nsamples);
|
||||
@@ -121,6 +122,7 @@ struct audio_buffer_pool *init_audio() {
|
||||
ok = audio_i2s_connect_extra(producer_pool, false, 0, 0, NULL);
|
||||
assert(ok);
|
||||
audio_i2s_set_enabled(true);
|
||||
|
||||
return producer_pool;
|
||||
}
|
||||
|
||||
@@ -140,7 +142,6 @@ static inline int16_t lerp_fixed(int16_t v0, int16_t v1, uint32_t frac) {
|
||||
return v0 + (int16_t)(((int32_t)(v1 - v0) * frac) >> FRAC_BITS);
|
||||
}
|
||||
|
||||
|
||||
void play_adlib() {
|
||||
puts("starting core 1");
|
||||
// flash_safe_execute_core_init();
|
||||
@@ -244,9 +245,13 @@ void play_adlib() {
|
||||
int32_t opl_sample = lerp_fixed(
|
||||
opl_samples[opl_index & OPL_BUFFER_BITS],
|
||||
opl_samples[(opl_index + 1) & OPL_BUFFER_BITS],
|
||||
opl_frac);
|
||||
opl_frac);
|
||||
|
||||
opl_sample = scale_sample(opl_sample << 2, opl_volume, 1);
|
||||
|
||||
accum[0] += opl_sample;
|
||||
accum[1] += opl_sample;
|
||||
|
||||
#if SOUND_SB
|
||||
if (!sb_left) {
|
||||
// putchar('t');
|
||||
@@ -260,11 +265,26 @@ void play_adlib() {
|
||||
}
|
||||
sb_index_old = sb_index;
|
||||
sb_frac = sb_pos & FRAC_MASK;
|
||||
sb_ratio = fixed_ratio(sbdsp_sample_rate(), 44100);
|
||||
//sb_ratio = fixed_ratio(sbdsp_sample_rate(), 44100);
|
||||
|
||||
static uint16_t last_sb_rate = 0;
|
||||
uint16_t current_rate = sbdsp_sample_rate();
|
||||
if (current_rate != last_sb_rate)
|
||||
{
|
||||
sb_ratio = fixed_ratio(current_rate, 44100);
|
||||
last_sb_rate = current_rate;
|
||||
}
|
||||
|
||||
sb_pos += sb_ratio;
|
||||
// putchar('p');
|
||||
if (!sbdsp_muted()) {
|
||||
int16_t sb_sample = sb_fifo->buffer[sb_index & AUDIO_FIFO_BITS];
|
||||
//int16_t sb_sample = sb_fifo->buffer[sb_index & AUDIO_FIFO_BITS];
|
||||
|
||||
int16_t *fifo_buf = sb_fifo->buffer;
|
||||
int16_t sb_sample = fifo_buf[sb_index & AUDIO_FIFO_BITS];
|
||||
|
||||
sb_sample = scale_sample((int32_t)sb_sample >> 1, sb_volume, 1);
|
||||
|
||||
accum[0] += sb_sample;
|
||||
accum[1] += sb_sample;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Daniel Arnold
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "flash_settings.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "volctrl.h"
|
||||
#include "clamp.h"
|
||||
#include "flash_settings.h"
|
||||
extern Settings settings;
|
||||
|
||||
int32_t opl_volume = 0x10000; // default 1.0x volume
|
||||
int32_t sb_volume = 0x10000; // default 1.0x volume
|
||||
int32_t cd_audio_volume = 0x10000; // default 1.0x volume
|
||||
int32_t gus_volume = 0x10000; // default 1.0x volume
|
||||
int32_t psg_volume = 0x10000; // default 1.0x volume
|
||||
|
||||
|
||||
int32_t set_volume_scale (uint8_t percent) {
|
||||
if (percent > 100)
|
||||
percent = 100;
|
||||
|
||||
uint8_t delta = 100 - settings.Volume.mainVol;
|
||||
|
||||
int32_t volume = ((percent - delta) * 65536) / 100;
|
||||
|
||||
if (percent < 1)
|
||||
volume = 0;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
int32_t scale_sample (int32_t sample, int32_t scale, int clamp) {
|
||||
sample = (sample * scale) >> 16;
|
||||
|
||||
if (clamp)
|
||||
clamp16(sample);
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
||||
void set_volume(uint16_t mode) {
|
||||
|
||||
switch (mode){
|
||||
case MODE_MAINVOL:
|
||||
set_volume(MODE_OPLVOL);
|
||||
set_volume(MODE_SBVOL);
|
||||
set_volume(MODE_CDVOL);
|
||||
set_volume(MODE_GUSVOL);
|
||||
set_volume(MODE_PSGVOL);
|
||||
break;
|
||||
case MODE_OPLVOL:
|
||||
opl_volume = set_volume_scale(settings.Volume.oplVol);
|
||||
break;
|
||||
case MODE_SBVOL:
|
||||
sb_volume = set_volume_scale(settings.Volume.sbVol);
|
||||
break;
|
||||
case MODE_CDVOL:
|
||||
cd_audio_volume = set_volume_scale(settings.Volume.sbVol);
|
||||
break;
|
||||
case MODE_GUSVOL:
|
||||
gus_volume = set_volume_scale(settings.Volume.gusVol);
|
||||
break;
|
||||
case MODE_PSGVOL:
|
||||
psg_volume = set_volume_scale(settings.Volume.psgVol);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Daniel Arnold
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../common/picogus.h"
|
||||
#include "flash_settings.h"
|
||||
|
||||
extern int32_t opl_volume;
|
||||
extern int32_t sb_volume;
|
||||
extern int32_t cd_audio_volume;
|
||||
extern int32_t gus_volume;
|
||||
extern int32_t psg_volume;
|
||||
|
||||
|
||||
extern int32_t set_volume_scale (uint8_t percent);
|
||||
extern int32_t scale_sample (int32_t sample, int32_t scale, int clamp);
|
||||
|
||||
void set_volume(uint16_t mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user