Skip to content

Commit

Permalink
Initial audio
Browse files Browse the repository at this point in the history
  • Loading branch information
drhelius committed Aug 24, 2024
1 parent d4b54b1 commit f1c4972
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 24 deletions.
16 changes: 14 additions & 2 deletions platforms/shared/desktop/gui_debug_psg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ void gui_debug_window_psg(void)

ImGui::Columns(2, "channels", false);

ImGui::TextColored(cyan, "DDA "); ImGui::SameLine();
ImGui::TextColored(violet, " "); ImGui::SameLine();
ImGui::TextColored(white, "%d", psg_channel->output);

ImGui::TextColored(cyan, "R02 "); ImGui::SameLine();
ImGui::TextColored(violet, "FREQ LOW "); ImGui::SameLine();
ImGui::TextColored(white, "%02X", psg_channel->frequency & 0xFF);
Expand All @@ -115,8 +119,16 @@ void gui_debug_window_psg(void)
if (channel > 3)
{
ImGui::TextColored(cyan, "R07 "); ImGui::SameLine();
ImGui::TextColored(violet, "NOISE "); ImGui::SameLine();
ImGui::TextColored(white, "%02X", psg_channel->noise);
ImGui::TextColored(violet, "NOISE CTRL "); ImGui::SameLine();
ImGui::TextColored(white, "%02X", psg_channel->noise_control);

ImGui::TextColored(cyan, " "); ImGui::SameLine();
ImGui::TextColored(violet, "NOISE FREQ "); ImGui::SameLine();
ImGui::TextColored(white, "%04X", psg_channel->noise_frequency);

ImGui::TextColored(cyan, " "); ImGui::SameLine();
ImGui::TextColored(violet, "NOISE SEED "); ImGui::SameLine();
ImGui::TextColored(white, "%04X", psg_channel->noise_seed);
}

ImGui::NewLine();
Expand Down
114 changes: 105 additions & 9 deletions src/huc6280_psg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
*
*/

#include <cmath>
#include <algorithm>
#include "huc6280_psg.h"

HuC6280PSG::HuC6280PSG()
{
InitPointer(m_channels);
InitPointer(m_current_channel);
InitPointer(m_ch);
}

HuC6280PSG::~HuC6280PSG()
Expand All @@ -44,6 +46,7 @@ void HuC6280PSG::Init()
m_state.BUFFER = m_buffer;
m_state.CHANNELS = m_channels;

ComputeVolumeLUT();
Reset();
}

Expand All @@ -59,16 +62,25 @@ void HuC6280PSG::Reset()
m_lfo_frequency = 0;
m_lfo_control = 0;

m_current_channel = &m_channels[0];
m_left_sample = 0;
m_right_sample = 0;

m_ch = &m_channels[0];

for (int i = 0; i < 6; i++)
{
m_channels[i].frequency = 0;
m_channels[i].control = 0;
m_channels[i].amplitude = 0;
m_channels[i].wave = 0;
m_channels[i].noise = 0;
m_channels[i].wave_index = 0;
m_channels[i].noise_control = 0;
m_channels[i].noise_frequency = 0;
m_channels[i].noise_seed = 0;
m_channels[i].noise_counter = 0;
m_channels[i].counter = 0;
m_channels[i].output = 0;

for (int j = 0; j < 32; j++)
{
m_channels[i].wave_data[j] = 0;
Expand Down Expand Up @@ -102,20 +114,84 @@ HuC6280PSG::HuC6280PSG_State* HuC6280PSG::GetState()

void HuC6280PSG::Sync()
{


for (int i = 0; i < m_elapsed_cycles; i++)
{
u8 main_left_vol = (m_main_amplitude >> 4) & 0x0F;
u8 main_right_vol = m_main_amplitude & 0x0F;

m_left_sample = 0;
m_right_sample = 0;

for (int i = 0; i < 1; i++)
{
HuC6280PSG_Channel* ch = &m_channels[i];

// Channel off
if (!(ch->control & 0x80))
continue;

u8 left_vol = (ch->amplitude >> 4) & 0x0F;
u8 right_vol = ch->amplitude & 0x0F;
u8 channel_vol = (ch->control >> 1) & 0x0F;

int temp_left_vol = std::min(0x0F, (0x0F - main_left_vol) + (0x0F - left_vol) + (0x0F - channel_vol));
int temp_right_vol = std::min(0x0F, (0x0F - main_right_vol) + (0x0F - right_vol) + (0x0F - channel_vol));

int final_left_vol = m_volume_lut[(temp_left_vol << 1) | (~ch->control & 0x01)];
int final_right_vol = m_volume_lut[(temp_right_vol << 1) | (~ch->control & 0x01)];

// Noise
if ((i >=4) && (ch->noise_control & 0x80))
{

}
// DDA
else if (ch->control & 0x40)
{

}
// Waveform
else
{
// LFO
if ((i < 2) && (m_lfo_control & 0x03))
{
if (i == 1)
continue;
}
// No LFO
else
{
u32 feq = ch->frequency ? ch->frequency : 0x1000;

//for (int j = 0; j < cycles; j++)
{
int data = ch->wave_data[ch->wave_index];
ch->counter--;

if (ch->counter <= 0)
{
ch->counter = feq;
ch->wave_index = (ch->wave_index + 1) & 0x1F;
}

m_left_sample += (s16)((data - 16));// * final_left_vol);
m_right_sample += (s16)((data - 16));// * final_right_vol);
}
}
}
}

m_sample_cycle_counter++;

if (m_sample_cycle_counter >= m_cycles_per_sample)
{
m_sample_cycle_counter -= m_cycles_per_sample;

s16 sample = 0;

// TODO: PSG sound generation

m_buffer[m_buffer_index] = sample;
m_buffer[m_buffer_index + 1] = sample;
m_buffer[m_buffer_index] = m_left_sample;
m_buffer[m_buffer_index + 1] = m_right_sample;
m_buffer_index += 2;

if (m_buffer_index >= GG_AUDIO_BUFFER_SIZE)
Expand All @@ -127,4 +203,24 @@ void HuC6280PSG::Sync()
}

m_elapsed_cycles = 0;
}

void HuC6280PSG::UpdateChannels(int cycles)
{

}

void HuC6280PSG::ComputeVolumeLUT()
{
double amplitude = 65535.0 / 6.0 / 32.0;
double step = 48.0 / 32.0;

for (int i = 0; i < 30; i++)
{
m_volume_lut[i] = (u16)amplitude;
amplitude /= pow(10.0, step / 20.0);
}

m_volume_lut[30] = 0;
m_volume_lut[31] = 0;
}
14 changes: 12 additions & 2 deletions src/huc6280_psg.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ class HuC6280PSG
u8 control;
u8 amplitude;
u8 wave;
u8 noise;
u8 wave_index;
u8 wave_data[32];
u8 noise_control;
u32 noise_frequency;
u32 noise_seed;
int noise_counter;
int counter;
s16 output;
};

struct HuC6280PSG_State
Expand All @@ -65,11 +70,13 @@ class HuC6280PSG

private:
void Sync();
void UpdateChannels(int cycles);
void ComputeVolumeLUT();

private:
HuC6280PSG_State m_state;
HuC6280PSG_Channel* m_channels;
HuC6280PSG_Channel* m_current_channel;
HuC6280PSG_Channel* m_ch;
u8 m_channel_select;
u8 m_main_amplitude;
u8 m_lfo_frequency;
Expand All @@ -79,6 +86,9 @@ class HuC6280PSG
int m_cycles_per_sample;
int m_buffer_index;
s16* m_buffer;
u16 m_volume_lut[32];
s16 m_left_sample;
s16 m_right_sample;
};

#include "huc6280_psg_inline.h"
Expand Down
32 changes: 21 additions & 11 deletions src/huc6280_psg_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ inline void HuC6280PSG::Write(u32 address, u8 value)
if (reg == 0)
{
m_channel_select = value & 0x07;
m_current_channel = &m_channels[m_channel_select];
m_ch = &m_channels[m_channel_select];
return;
}

Expand All @@ -51,53 +51,63 @@ inline void HuC6280PSG::Write(u32 address, u8 value)
case 2:
if (m_channel_select < 6)
{
m_current_channel->frequency = (m_current_channel->frequency & 0x0F00) | value;
m_ch->frequency = (m_ch->frequency & 0x0F00) | value;
}
break;
// Channel frequency (high)
case 3:
if (m_channel_select < 6)
{
m_current_channel->frequency = (m_current_channel->frequency & 0x00FF) | ((value & 0x0F) << 8);
m_ch->frequency = (m_ch->frequency & 0x00FF) | ((value & 0x0F) << 8);
}
break;
// Channel control
case 4:
if (m_channel_select < 6)
{
m_current_channel->control = value;
// DDA on to off
if ((m_ch->control & 0x40) && (!(value & 0x40)))
{
m_ch->wave_index = 0;
}
// Channel off to on
if ((!(m_ch->control & 0x80)) && (value & 0x80))
{
m_ch->counter = m_ch->frequency;
}
m_ch->control = value;
}
break;
// Channel amplitude
case 5:
if (m_channel_select < 6)
{
m_current_channel->amplitude = value;
m_ch->amplitude = value;
}
break;
// Channel waveform data
case 6:
if (m_channel_select < 6)
{
int data = value & 0x1F;
m_current_channel->wave = data;
m_ch->wave = data;

// DDA off
if((m_current_channel->control & 0x40) == 0)
if((m_ch->control & 0x40) == 0)
{
m_current_channel->wave_data[m_current_channel->wave_index] = data;
m_ch->wave_data[m_ch->wave_index] = data;
}

// Channel off, DDA off
if((m_current_channel->control & 0xC0) == 0)
m_current_channel->wave_index = ((m_current_channel->wave_index + 1) & 0x1F);
if((m_ch->control & 0xC0) == 0)
m_ch->wave_index = ((m_ch->wave_index + 1) & 0x1F);
}
break;
// Channel noise (only channels 4 and 5)
case 7:
if ((m_channel_select > 3) && (m_channel_select < 6))
{
m_current_channel->noise = value;
m_ch->noise_control = value;
}
break;
// LFO frequency
Expand Down

0 comments on commit f1c4972

Please sign in to comment.