- Adaptat el mòdul 'ay-3-8912' per a usar zx_speaker, pero encara no fa roidets, a vore si demà trobe el perquè

This commit is contained in:
2025-07-24 21:37:01 +02:00
parent 91a8933544
commit 9725e58d92
6 changed files with 101 additions and 97 deletions

View File

@@ -1,6 +1,7 @@
#include "ay-3-8912.h"
#include "z80.h"
#include <SDL2/SDL.h>
#include "zx_ula.h"
#define MIXER_REG_A_TONE 0x01
#define MIXER_REG_B_TONE 0x02
@@ -70,33 +71,34 @@ namespace audio
case 0:
case 1: {
uint16_t freq = registers[0] | ((registers[1] & 0xf) << 8);
channel_a_tone_freq = clock / freq;
channel_a_tone_freq = clock / freq==0?1:freq;
channel_a_tone_freq_counter = 0;
break;
}
case 2:
case 3: {
uint16_t freq = registers[2] | ((registers[3] & 0xf) << 8);
channel_b_tone_freq = clock / freq;
channel_b_tone_freq = clock / freq==0?1:freq;
channel_b_tone_freq_counter = 0;
break;
}
case 4:
case 5: {
uint16_t freq = registers[4] | ((registers[5] & 0xf) << 8);
channel_c_tone_freq = clock / freq;
channel_c_tone_freq = clock / freq==0?1:freq;
channel_c_tone_freq_counter = 0;
break;
}
case 6: {
noise_freq = clock / (registers[6] & 0x1f);
uint8_t freq = (registers[6] & 0x1f);
noise_freq = clock / freq==0?1:freq;
noise_freq_counter = 0;
break;
}
case 11:
case 12: {
uint16_t freq = registers[11] | (registers[12] << 8);
envelope_freq = clock / freq;
envelope_freq = clock / freq==0?1:freq;
break;
}
case 13:
@@ -112,13 +114,9 @@ namespace audio
void init()
{
SDL_AudioSpec audioSpec{SAMPLING_FREQ, AUDIO_U8, 1, 0, AUDIO_BUFFER_SIZE, 0, 0, NULL, NULL};
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
cycles_per_sample = z80::getClock() / SAMPLING_FREQ;
reset();
z80::connect_port(0xfffd, 0xffff, audio::read_register, audio::select_register);
z80::connect_port(0xbffd, 0xffff, nullptr, audio::write_register);
resume();
}
void reset()
@@ -127,97 +125,96 @@ namespace audio
for (int i=0; i<16;++i) registers[i]=0;
}
void silence()
{
SDL_PauseAudioDevice(sdlAudioDevice, 1);
}
void resume()
{
SDL_PauseAudioDevice(sdlAudioDevice, 0);
}
void update(uint32_t dt)
{
for (int i=0;i<dt;i+=2)
{
// Oscillate (0-1) channel A tone level given its frequency
channel_a_tone_freq_counter++;
if (channel_a_tone_freq_counter == channel_a_tone_freq) {
channel_a_tone_freq_counter = 0;
channel_a_tone_level = channel_a_tone_level ^ 1;
}
dt = dt >> 1;
// Oscillate (0-1) channel B tone level given its frequency
channel_b_tone_freq_counter++;
if (channel_b_tone_freq_counter == channel_b_tone_freq) {
channel_b_tone_freq_counter = 0;
channel_b_tone_level = channel_b_tone_level ^ 1;
}
// Oscillate (0-1) channel A tone level given its frequency
channel_a_tone_freq_counter+=dt;
if (channel_a_tone_freq_counter >= channel_a_tone_freq) {
channel_a_tone_freq_counter -= channel_a_tone_freq;
channel_a_tone_level = channel_a_tone_level ^ 1;
}
// Oscillate (0-1) channel C tone level given its frequency
channel_c_tone_freq_counter++;
if (channel_c_tone_freq_counter == channel_c_tone_freq) {
channel_c_tone_freq_counter = 0;
channel_c_tone_level = channel_c_tone_level ^ 1;
}
// Oscillate (0-1) channel B tone level given its frequency
channel_b_tone_freq_counter+=dt;
if (channel_b_tone_freq_counter >= channel_b_tone_freq) {
channel_b_tone_freq_counter -= channel_b_tone_freq;
channel_b_tone_level = channel_b_tone_level ^ 1;
}
// Oscillate (0-1) noise level given its frequency and shift register
noise_freq_counter++;
if (noise_freq_counter == noise_freq) {
noise_freq_counter = 0;
noise_level = noise_level ^ shiftreg;
uint32_t newbit = shiftreg ^ (shiftreg >> 3);
shiftreg = ((shiftreg >> 1) & 0xff) | ((newbit << 16) & 0x100);
}
// Oscillate (0-1) channel C tone level given its frequency
channel_c_tone_freq_counter+=dt;
if (channel_c_tone_freq_counter >= channel_c_tone_freq) {
channel_c_tone_freq_counter -= channel_c_tone_freq;
channel_c_tone_level = channel_c_tone_level ^ 1;
}
// Mix tone and noise on channel A given register 7 values
channel_a_level = 1;
if (registers[7] & MIXER_REG_A_TONE) channel_a_level &= channel_a_tone_level;
if (registers[7] & MIXER_REG_A_NOISE) channel_a_level &= noise_level;
// Mix tone and noise on channel B given register 7 values
channel_b_level = 1;
if (registers[7] & MIXER_REG_B_TONE) channel_b_level &= channel_b_tone_level;
if (registers[7] & MIXER_REG_B_NOISE) channel_b_level &= noise_level;
// Mix tone and noise on channel C given register 7 values
channel_c_level = 1;
if (registers[7] & MIXER_REG_C_TONE) channel_c_level &= channel_c_tone_level;
if (registers[7] & MIXER_REG_C_NOISE) channel_c_level &= noise_level;
// Oscillate (0-1) noise level given its frequency and shift register
noise_freq_counter+=dt;
if (noise_freq_counter >= noise_freq) {
noise_freq_counter -= noise_freq;
noise_level = noise_level ^ shiftreg;
uint32_t newbit = shiftreg ^ (shiftreg >> 3);
shiftreg = ((shiftreg >> 1) & 0xff) | ((newbit << 16) & 0x100);
}
// Develop (0-15) envelope volume given its frequency and shape
envelope_freq_counter+=dt;
if (envelope_freq_counter >= envelope_freq) {
envelope_freq_counter -= envelope_freq;
// Develop (0-15) envelope volume given its frequency and shape
envelope_freq_counter++;
if (envelope_freq_counter == envelope_freq) {
envelope_freq_counter = 0;
envelope_volume += envelope_direction;
if ( (envelope_volume > 15) || (envelope_volume < 0) ) {
switch(registers[13]&0xf) {
case 8:
case 12:
envelope_volume &= 0x0f;
break;
case 10:
case 14:
envelope_direction = -envelope_direction;
envelope_volume += envelope_direction;
case 11:
case 13:
envelope_direction = 0;
envelope_volume = 15;
default:
envelope_direction = 0;
envelope_volume = 0;
}
envelope_volume += envelope_direction;
if ( (envelope_volume > 15) || (envelope_volume < 0) ) {
switch(registers[13]&0xf) {
case 8:
case 12:
envelope_volume &= 0x0f;
break;
case 10:
case 14:
envelope_direction = -envelope_direction;
envelope_volume += envelope_direction;
case 11:
case 13:
envelope_direction = 0;
envelope_volume = 15;
default:
envelope_direction = 0;
envelope_volume = 0;
}
}
uint8_t channel_a_volume = (registers[8]&0x10) ? envelope_volume : registers[8]&0xf;
uint8_t channel_b_volume = (registers[9]&0x10) ? envelope_volume : registers[9]&0xf;
uint8_t channel_c_volume = (registers[10]&0x10) ? envelope_volume : registers[10]&0xf;
}
}
uint8_t get_sample()
{
// Mix tone and noise on channel A given register 7 values
channel_a_level = 1;
if (registers[7] & MIXER_REG_A_TONE) channel_a_level &= channel_a_tone_level;
if (registers[7] & MIXER_REG_A_NOISE) channel_a_level &= noise_level;
// Mix tone and noise on channel B given register 7 values
channel_b_level = 1;
if (registers[7] & MIXER_REG_B_TONE) channel_b_level &= channel_b_tone_level;
if (registers[7] & MIXER_REG_B_NOISE) channel_b_level &= noise_level;
// Mix tone and noise on channel C given register 7 values
channel_c_level = 1;
if (registers[7] & MIXER_REG_C_TONE) channel_c_level &= channel_c_tone_level;
if (registers[7] & MIXER_REG_C_NOISE) channel_c_level &= noise_level;
const uint8_t channel_a_volume = (registers[8]&0x10) ? envelope_volume : registers[8]&0xf;
const uint8_t channel_b_volume = (registers[9]&0x10) ? envelope_volume : registers[9]&0xf;
const uint8_t channel_c_volume = (registers[10]&0x10) ? envelope_volume : registers[10]&0xf;
const uint8_t channel_a_sample = volume_table[(channel_a_level&1) * channel_a_volume] >> 1;
const uint8_t channel_b_sample = volume_table[(channel_b_level&1) * channel_b_volume] >> 1;
const uint8_t channel_c_sample = volume_table[(channel_c_level&1) * channel_c_volume] >> 1;
uint8_t sample = (channel_a_sample+channel_b_sample+channel_c_sample)&0xff;
zx_ula::set_border_color(sample&0xf);
return sample;
}
}