- [NEW] mòdul 'zx_speaker' per a unificar la eixida de só

This commit is contained in:
2025-07-24 19:39:57 +02:00
parent 780afbc6a8
commit 91a8933544
6 changed files with 83 additions and 55 deletions

View File

@@ -4,6 +4,7 @@
#include "z80dis.h"
#include "z80debug.h"
#include "zx_ula.h"
#include "zx_speaker.h"
#include "zx_screen.h"
#include "zx_tape.h"
#include <SDL2/SDL.h>
@@ -128,7 +129,8 @@ int main(int argc, char *argv[])
ui::menu::addbooloption(menu, "STOP ON INVALID OP", z80::getOption(Z80_OPTION_STOP_ON_INVALID), actions::decZoom);
ui::menu::addoption(menu, "SHOW ANALYZER", actions::showAnalyzer);
zx_ula::sound_init();
speaker::init();
speaker::register_source(zx_ula::get_sample);
zx_tape::load("ROBOCOP1.TAP");
@@ -228,7 +230,7 @@ int main(int argc, char *argv[])
time = SDL_GetTicks();
zx_tape::report();
}
//zx_ula::sound_update(dt);
//speaker::update(dt);
//zxscreen::refresh(dt);
}
if (fastload) { printf("%i\n", SDL_GetTicks()-time); t_states=0; }
@@ -243,7 +245,7 @@ int main(int argc, char *argv[])
t_states += dt;
zx_tape::update(dt);
zx_ula::sound_update(dt);
speaker::update(dt);
zxscreen::refresh(dt);
if (z80debug::debugging()) break;
}

View File

@@ -5,6 +5,7 @@
#include "zx_mem.h"
#include "z80analyze.h"
#include "zx_ula.h"
#include "zx_speaker.h"
#include "zx_tape.h"
#include "ui.h"
#include "ui_window.h"
@@ -360,7 +361,7 @@ namespace z80debug
void pause()
{
zx_ula::sound_disable();
speaker::disable();
is_paused = true;
breakpoints[z80::getPC()] &= ~8;
}
@@ -383,7 +384,7 @@ namespace z80debug
//hide();
refresh();
zxscreen::focus();
zx_ula::sound_enable();
speaker::enable();
}
const bool debugging() { return is_debugging; }
@@ -791,7 +792,7 @@ namespace z80debug
if (strcmp(cmd, "s")==0 || strcmp(cmd, "step")==0) {
uint8_t dt = z80::step();
zx_tape::update(dt);
zx_ula::sound_update(dt);
speaker::update(dt);
zxscreen::fullrefresh();
z80analyze::refresh();
} else if (strcmp(cmd, "c")==0 || strcmp(cmd, "cont")==0) {

60
zx_speaker.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include "zx_speaker.h"
#include <SDL2/SDL.h>
#include "z80.h"
#include <vector>
namespace speaker
{
#define SAMPLING_FREQ 44100
#define AUDIO_BUFFER_SIZE 2048
SDL_AudioDeviceID sdlAudioDevice;
uint8_t sound_buffer[AUDIO_BUFFER_SIZE];
uint16_t sound_pos=0;
uint16_t t_sound=0;
std::vector<uint8_t(*)()> sources;
float cycles_per_sample;
void init()
{
SDL_AudioSpec audioSpec{SAMPLING_FREQ, AUDIO_U8, 1, 0, AUDIO_BUFFER_SIZE>>2, 0, 0, NULL, NULL};
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
cycles_per_sample = z80::getClock() / SAMPLING_FREQ;
enable();
}
void enable()
{
SDL_PauseAudioDevice(sdlAudioDevice, 0);
}
void disable()
{
SDL_PauseAudioDevice(sdlAudioDevice, 1);
}
void register_source(uint8_t(*callback)())
{
sources.push_back(callback);
}
void update(const uint8_t dt)
{
t_sound += dt;
if (t_sound>=cycles_per_sample) {
t_sound-=cycles_per_sample;
uint32_t sample = 0;
for (auto callback : sources) sample += callback();
sample /= sources.size();
sound_buffer[(sound_pos++)&(AUDIO_BUFFER_SIZE-1)] = sample;
}
if (sound_pos>=1000) {
SDL_QueueAudio(sdlAudioDevice, sound_buffer, sound_pos);
sound_pos = 0;
while (SDL_GetQueuedAudioSize(sdlAudioDevice) > 4096 ) {}
}
}
}

11
zx_speaker.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
#include <stdint.h>
namespace speaker
{
void init();
void enable();
void disable();
void register_source(uint8_t(*callback)());
void update(const uint8_t dt);
}

View File

@@ -68,11 +68,6 @@ namespace zx_ula
static uint8_t ear = 0;
static uint8_t mic = 0;
// this variable keeps track of the last "1" written to the sound buffer, so when streaming it in the audio callback, if there
// are only zeros remaining in the buffer, we just discard it. It's a poor man's method of keeping the buffer size in control.
// This is useless when there are music, sounds, tape loading, etc... as 1's and 0's keep alternating
static uint16_t last_1 = 0;
void update_zx_keyboard()
{
const uint8_t *keys = SDL_GetKeyboardState(NULL);
@@ -231,47 +226,9 @@ namespace zx_ula
uint8_t get_ear() { return ear; }
void set_ear(const uint8_t val) { ear = val; }
#define SAMPLING_FREQ 44100
#define AUDIO_BUFFER_SIZE 2048
float cycles_per_sample;
SDL_AudioDeviceID sdlAudioDevice;
uint8_t sound_buffer[AUDIO_BUFFER_SIZE];
uint16_t sound_pos=0;
uint16_t t_sound=0;
void sound_init()
uint8_t get_sample()
{
SDL_AudioSpec audioSpec{SAMPLING_FREQ, AUDIO_U8, 1, 0, AUDIO_BUFFER_SIZE>>2, 0, 0, NULL, NULL};
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
cycles_per_sample = z80::getClock() / SAMPLING_FREQ;
sound_enable();
}
void sound_enable()
{
SDL_PauseAudioDevice(sdlAudioDevice, 0);
}
void sound_disable()
{
SDL_PauseAudioDevice(sdlAudioDevice, 1);
}
void sound_update(const uint8_t dt)
{
t_sound += dt;
if (t_sound>=cycles_per_sample) {
t_sound-=cycles_per_sample;
sound_buffer[(sound_pos++)&(AUDIO_BUFFER_SIZE-1)] = ear*128;
}
if (sound_pos>=1000) {
SDL_QueueAudio(sdlAudioDevice, sound_buffer, sound_pos);
sound_pos = 0;
while (SDL_GetQueuedAudioSize(sdlAudioDevice) > 4096 ) {}
}
return ear*128;
}
const int getKey(const char key)

View File

@@ -11,10 +11,7 @@ namespace zx_ula
uint8_t get_ear();
void set_ear(const uint8_t val);
void sound_init();
void sound_enable();
void sound_disable();
void sound_update(const uint8_t dt);
uint8_t get_sample();
void keydown(const char key);
void keyup(const char key);