Volume control

This commit is contained in:
Daniel Arnold committed 2025-06-30 07:56:53 -06:00
1 parent a2904c9929
commit c84773c562
13 files changed
+379 -14

No files matched your search

+7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+8
View File
@@ -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
}
};
+8
View File
@@ -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;
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+85
View File
@@ -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;
}
}
+43
View File
@@ -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