Add option to remove audio pops (#257)

Some audio can be inaccurate with this option enabled.
This commit is contained in:
paulb-nl
2024-09-05 07:42:36 +02:00
committed by GitHub
parent 7c576b02e8
commit fe5758fd33
3 changed files with 35 additions and 15 deletions

View File

@@ -200,7 +200,7 @@ assign AUDIO_MIX = status[8:7];
// 0 1 2 3 4 5 6
// 01234567890123456789012345678901 23456789012345678901234567890123
// 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV
// XXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXX
// XXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX
`include "build_id.v"
localparam CONF_STR = {
@@ -241,6 +241,7 @@ localparam CONF_STR = {
"P1o2,Analog width,Narrow,Wide;",
"P1-;",
"P1O78,Stereo mix,none,25%,50%,100%;",
"P1O[43],Audio mode,Accurate,No Pops;",
"P2,Bootroms;",
"P2-;",
@@ -665,6 +666,7 @@ gb gb (
// audio
.audio_l ( GB_AUDIO_L ),
.audio_r ( GB_AUDIO_R ),
.audio_no_pops (status[43]),
// interface to the lcd
.lcd_clkena ( lcd_clkena ),

View File

@@ -58,6 +58,7 @@ module gb (
// audio
output [15:0] audio_l,
output [15:0] audio_r,
input audio_no_pops,
// Megaduck?
input megaduck,
@@ -445,6 +446,7 @@ gbc_snd audio (
.reset ( reset_ss ),
.is_gbc ( isGBC ),
.remove_pops ( audio_no_pops ),
.s1_read ( audio_rd ),
.s1_write ( audio_wr ),

View File

@@ -19,6 +19,7 @@ entity gbc_snd is
reset : in std_logic;
is_gbc : in std_logic;
remove_pops : in std_logic; -- 0: Accurate output, 1: Toggling DACs will not cause pops but some audio can be inaccurate.
s1_read : in std_logic;
s1_write : in std_logic;
@@ -45,6 +46,7 @@ architecture SYN of gbc_snd is
clk : in std_logic;
ce : in std_logic;
dac_en : in std_logic;
dac_invert : in std_logic;
dac_input : in std_logic_vector(3 downto 0);
dac_output : out signed(8 downto 0)
);
@@ -1643,13 +1645,13 @@ begin
-- Analog hardware emulation
sq1_dac : apu_dac port map (clk=>clk, ce=>ce, dac_en=>sq1_dac_en, dac_input=>sq1_wav,dac_output=>sq1_dac_out);
sq2_dac : apu_dac port map (clk=>clk, ce=>ce, dac_en=>sq2_dac_en, dac_input=>sq2_wav,dac_output=>sq2_dac_out);
wav_dac : apu_dac port map (clk=>clk, ce=>ce, dac_en=>wav_enable, dac_input=>wav_wav,dac_output=>wav_dac_out);
noi_dac : apu_dac port map (clk=>clk, ce=>ce, dac_en=>noi_dac_en, dac_input=>noi_wav,dac_output=>noi_dac_out);
sq1_dac : apu_dac port map (clk=>clk, ce=>ce, dac_en=>sq1_dac_en, dac_invert => not remove_pops, dac_input=>sq1_wav,dac_output=>sq1_dac_out);
sq2_dac : apu_dac port map (clk=>clk, ce=>ce, dac_en=>sq2_dac_en, dac_invert => not remove_pops, dac_input=>sq2_wav,dac_output=>sq2_dac_out);
wav_dac : apu_dac port map (clk=>clk, ce=>ce, dac_en=>wav_enable, dac_invert => not remove_pops, dac_input=>wav_wav,dac_output=>wav_dac_out);
noi_dac : apu_dac port map (clk=>clk, ce=>ce, dac_en=>noi_dac_en, dac_invert => not remove_pops, dac_input=>noi_wav,dac_output=>noi_dac_out);
mixer : process (sq1_dac_out, sq2_dac_out, wav_dac_out, noi_dac_out, ch_map, ch_vol)
mixer : process (sq1_dac_out, sq2_dac_out, wav_dac_out, noi_dac_out, ch_map, ch_vol, remove_pops)
variable snd_left_in : signed(10 downto 0);
variable snd_right_in : signed(10 downto 0);
variable snd_tmp : signed(15 downto 0);
@@ -1678,12 +1680,20 @@ begin
snd_left_in := snd_left_in + wav_analog;
end if;
end loop;
snd_tmp := snd_right_in * signed(("00" & ch_vol(2 downto 0)) + '1');
snd_right <= std_logic_vector(snd_tmp);
snd_tmp := snd_left_in * signed(("00" & ch_vol(6 downto 4)) + '1');
snd_left <= std_logic_vector(snd_tmp);
snd_tmp := snd_right_in * signed(("00" & ch_vol(2 downto 0)) + '1');
if (remove_pops = '1') then
snd_right <= std_logic_vector(shift_left(snd_tmp,1)); -- Compensate lower volume
else
snd_right <= std_logic_vector(snd_tmp);
end if;
snd_tmp := snd_left_in * signed(("00" & ch_vol(6 downto 4)) + '1');
if (remove_pops = '1') then
snd_left <= std_logic_vector(shift_left(snd_tmp,1));
else
snd_left <= std_logic_vector(snd_tmp);
end if;
end process;
end SYN;
@@ -1697,6 +1707,7 @@ entity apu_dac is
clk : in std_logic;
ce : in std_logic;
dac_en : in std_logic;
dac_invert : in std_logic;
dac_input : in std_logic_vector(3 downto 0);
dac_output : out signed(8 downto 0)
);
@@ -1712,10 +1723,15 @@ architecture apu_dac_arch of apu_dac is
-- Convert a DAC input code to a pseudo-analog value
function dac_out(
wav : std_logic_vector(3 downto 0)
wav : std_logic_vector(3 downto 0);
invert : std_logic
) return signed is
begin
return signed((wav xor "0111") & "00000");
if (invert = '1') then
return signed((wav xor "0111") & "00000"); -- 0xF = -256, 0x0 = 224.
else
return signed("0" & wav & "0000"); -- 0xF = 240, 0x0 = 0.
end if;
end function;
begin
dac_output <= dac_analog;
@@ -1735,11 +1751,11 @@ begin
end if;
end process timers;
process(clk, ce, dac_en, dac_input, dac_decay_timer)
process(clk, ce, dac_en, dac_invert, dac_input, dac_decay_timer)
begin
if rising_edge(clk) and ce = '1' then
if dac_en = '1' then
dac_analog <= dac_out(dac_input);
dac_analog <= dac_out(dac_input, dac_invert);
elsif dac_decay_timer = 0 then
if dac_analog < 0 then
dac_analog <= dac_analog + 1;