Hello, I've got the sound emulation working and all channels sounds good. I know I'm missing a lot of the "obscure behaviors" from the guides, but it works better than I expected.
Problem is: Channel 4 is generating a "buzz" effect that sounds louder than it should be. The effect of the "ocean waves" in the Zelda: Link's Awakening intro, or almost all songs from Mega Man III are good examples.
The noise is more noticeable than the other channels on Mega Man III, which is pretty annoying. Other channels sounds good.
Also, I noticed the Zelda logo "tliiiin" hiss that plays when it appears in the intro is not reached (looks like it's tone is higher than what I can sample), so it sounds just like a normal buzz. Other sounds effects plays correctly.
I followed the GBSOUND and Sound Hardware wiki page, maybe I'm doing something really wrong.
I was sampling before at 44100 Hz, but increased to 96000 Hz and sound quality improved, but both works.
I steps cycles in multiples of 4, inside a loop until all elapsed cycles are consumed (based on the last instruction cycles count - my emu is cycle count accurate only).
The periods for sampling are:
I fill a buffer with that number of samples, and audio request comes from another thread.
When called, I copy the buffer to audio buffer and clear my buffer for next frame.
The emulation is not synced to audio, so there's some skip (small sound gaps, sometimes very rarely)
All channels sounds good with that configuration, but channel 4 has those issues I mentioned earlier.
Code for channel 4:
I will not post the code for volume envelope and length control, as it's the same for all channels, so it should be good (missing some APU quirks, but in normal conditions, it works).
The sampling code is
Can someone spot anything wrong that would cause the issues I mentioned?
Maybe I need some kind of audio filter for this channel?
Edit: if needed, full code is at https://github.com/fattard/xFF/blob/gb/emu-snd/unity3D_proj/Assets/source/EmuCores/GB/HW/audio/SoundChannel4.cs
Problem is: Channel 4 is generating a "buzz" effect that sounds louder than it should be. The effect of the "ocean waves" in the Zelda: Link's Awakening intro, or almost all songs from Mega Man III are good examples.
The noise is more noticeable than the other channels on Mega Man III, which is pretty annoying. Other channels sounds good.
Also, I noticed the Zelda logo "tliiiin" hiss that plays when it appears in the intro is not reached (looks like it's tone is higher than what I can sample), so it sounds just like a normal buzz. Other sounds effects plays correctly.
I followed the GBSOUND and Sound Hardware wiki page, maybe I'm doing something really wrong.
I was sampling before at 44100 Hz, but increased to 96000 Hz and sound quality improved, but both works.
I steps cycles in multiples of 4, inside a loop until all elapsed cycles are consumed (based on the last instruction cycles count - my emu is cycle count accurate only).
The periods for sampling are:
Code:
44100 Hz: 4194304 / (44100 / 2); // gives ~735 samples
96000 Hz: 4194304 / (96000 / 2); // gives ~1606 samples
96000 Hz: 4194304 / (96000 / 2); // gives ~1606 samples
I fill a buffer with that number of samples, and audio request comes from another thread.
When called, I copy the buffer to audio buffer and clear my buffer for next frame.
The emulation is not synced to audio, so there's some skip (small sound gaps, sometimes very rarely)
All channels sounds good with that configuration, but channel 4 has those issues I mentioned earlier.
Code for channel 4:
Code:
public void FreqTimerStep( )
{
// for each 4 cycles, this method is called from APU
m_timer -= 4;
if (m_timer <= 0)
{
int result = (m_linearShiftReg & 0x1) ^ ((m_linearShiftReg >> 1) & 0x1);
m_linearShiftReg >>= 1;
m_linearShiftReg |= result << 14;
if (m_stepsMode == 1)
{
m_linearShiftReg &= ~0x40; // clear bit 6
m_linearShiftReg |= result << 6;
}
// Reload Frequency
m_timer += CalcFrequency();
}
}
int CalcFrequency( )
{
int freq = 8;
switch (m_divRatio)
{
case 0:
freq = 8 << m_shiftFreq;
break;
case 1:
freq = 16 << m_shiftFreq;
break;
case 2:
freq = 32 << m_shiftFreq;
break;
case 3:
freq = 48 << m_shiftFreq;
break;
case 4:
freq = 64 << m_shiftFreq;
break;
case 5:
freq = 80 << m_shiftFreq;
break;
case 6:
freq = 96 << m_shiftFreq;
break;
case 7:
freq = 112 << m_shiftFreq;
break;
}
return freq;
}
{
// for each 4 cycles, this method is called from APU
m_timer -= 4;
if (m_timer <= 0)
{
int result = (m_linearShiftReg & 0x1) ^ ((m_linearShiftReg >> 1) & 0x1);
m_linearShiftReg >>= 1;
m_linearShiftReg |= result << 14;
if (m_stepsMode == 1)
{
m_linearShiftReg &= ~0x40; // clear bit 6
m_linearShiftReg |= result << 6;
}
// Reload Frequency
m_timer += CalcFrequency();
}
}
int CalcFrequency( )
{
int freq = 8;
switch (m_divRatio)
{
case 0:
freq = 8 << m_shiftFreq;
break;
case 1:
freq = 16 << m_shiftFreq;
break;
case 2:
freq = 32 << m_shiftFreq;
break;
case 3:
freq = 48 << m_shiftFreq;
break;
case 4:
freq = 64 << m_shiftFreq;
break;
case 5:
freq = 80 << m_shiftFreq;
break;
case 6:
freq = 96 << m_shiftFreq;
break;
case 7:
freq = 112 << m_shiftFreq;
break;
}
return freq;
}
I will not post the code for volume envelope and length control, as it's the same for all channels, so it should be good (missing some APU quirks, but in normal conditions, it works).
The sampling code is
Code:
// Output is bit 0 inverted
if ((m_linearShiftReg & 0x1) == 0)
{
return 15 & m_curVolume;
}
return 0;
if ((m_linearShiftReg & 0x1) == 0)
{
return 15 & m_curVolume;
}
return 0;
Can someone spot anything wrong that would cause the issues I mentioned?
Maybe I need some kind of audio filter for this channel?
Edit: if needed, full code is at https://github.com/fattard/xFF/blob/gb/emu-snd/unity3D_proj/Assets/source/EmuCores/GB/HW/audio/SoundChannel4.cs