Skip to content

Commit

Permalink
Add SDL sound to SDL version
Browse files Browse the repository at this point in the history
  • Loading branch information
Memotech-Bill committed Apr 12, 2024
1 parent 97c56f0 commit cb75b01
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 10 deletions.
12 changes: 5 additions & 7 deletions run_time/memu.cfg
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
-mem-blocks 36
-mem-blocks 32
-rom4 "~E/roms/boot-type07.rom"
-rom5 "~E/roms/sdx-type07.rom"
-largerom 456 "~E/roms/mfx.rom"
-no-largerom 456 "~E/roms/mfx.rom"
-no-cfx2 "~E/roms/CFX-II.rom"
-mfx-max
-kbd-remap
-kbd-country 0
-vid-win
-vid-win-max
-snd-portaudio
-mon-size 2
-disk-dir "~E/disks"
-sdx-mfloppy "~W/disks/andy_sys.mfloppy"
-sdx-mfloppy2 "~W/disks/games.mfloppy"
-sd-type sdhc -sd-image 0 "~C/disks/SDMaster_240101.bin"
-sdx-mfloppy "~E/disks/andy_sys.mfloppy"
-sdx-mfloppy2 "~E/disks/games.mfloppy"
-tape-dir "~E/tapes"
-rom-enable 0x73
-rom-enable 0x23
2 changes: 1 addition & 1 deletion src/memu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ elseif("${TARGET}" STREQUAL "SDL")
${CMAKE_CURRENT_LIST_DIR}/sdcard.c
${CMAKE_CURRENT_LIST_DIR}/sdxfdc.c
${CMAKE_CURRENT_LIST_DIR}/sid.c
${CMAKE_CURRENT_LIST_DIR}/snd.c
${CMAKE_CURRENT_LIST_DIR}/snd_sdl.c
${CMAKE_CURRENT_LIST_DIR}/spec.c
${CMAKE_CURRENT_LIST_DIR}/tape.c
${CMAKE_CURRENT_LIST_DIR}/txtwin.c
Expand Down
256 changes: 256 additions & 0 deletions src/memu/snd_sdl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
/*
snd.c - Sound
In this code, the tone generators are numbered 0 to 2.
In the documentation, they're referred to as 1 to 3.
See http://www.smspower.org/Development/SN76489.
*/

/*...sincludes:0:*/
#include <stdio.h>
#include <fcntl.h>
#include <math.h>
#ifndef WIN32
#include <unistd.h>
#endif

#include "types.h"
#include "diag.h"
#include "common.h"
#include "snd.h"

/*...vtypes\46\h:0:*/
/*...vdiag\46\h:0:*/
/*...vcommon\46\h:0:*/
/*...vsnd\46\h:0:*/
/*...e*/

/*...svars:0:*/
#define FREQ 44100

static int snd_emu = 0;

typedef struct
{
word freq;
byte atten;
float phase;
} CHANNEL;

static CHANNEL snd_channels[3];
static int snd_channel;
static byte snd_noise_ctrl;
static byte snd_noise_atten;
static float snd_noise_phase;
static word snd_noise_shifter;
static int snd_noise_bit;
static float snd_lastvol;

#include <SDL2/SDL.h>

static SDL_AudioDeviceID dev_id = 0;
static SDL_AudioSpec aspec;
/*...e*/

/*...ssnd_out6:0:*/
/*...ssnd_set_tone_freq_low:0:*/
static void snd_set_tone_freq_low(int channel, byte val)
{
snd_channel = channel; /* for subsequent high update */
snd_channels[channel].freq = (snd_channels[channel].freq & 0x3f0)
| (val & 0x0f);
diag_message(DIAG_SND_REGISTERS, "Tone %d frequency low changed, freq=%d", channel, snd_channels[channel].freq);
}
/*...e*/
/*...ssnd_set_tone_freq_high:0:*/
static void snd_set_tone_freq_high(byte val)
{
snd_channels[snd_channel].freq = (snd_channels[snd_channel].freq & 0x00f)
| (((word)val<<4) & 0x3f0);
diag_message(DIAG_SND_REGISTERS, "Tone %d frequency high changed, freq=%d", snd_channel, snd_channels[snd_channel].freq);
}
/*...e*/
/*...ssnd_set_tone_atten:0:*/
static void snd_set_tone_atten(int channel, byte val)
{
snd_channels[channel].atten = (val&0x0f);
diag_message(DIAG_SND_REGISTERS, "Tone %d attenuation changed, atten=%d", channel, snd_channels[channel].atten);
}
/*...e*/
/*...ssnd_set_noise_ctrl:0:*/
static void snd_set_noise_ctrl(byte val)
{
static const char *shift_rates[] =
{ "N/512", "N/1024", "N/2048", "tone generator 2 output" };
snd_noise_ctrl = (val & 0x07);
snd_noise_shifter = 0x8000;
diag_message(DIAG_SND_REGISTERS, "Noise control changed, %s noise, %s shift rate",
(snd_noise_ctrl & 0x04) ? "white" : "periodic",
shift_rates[snd_noise_ctrl&0x03]);
}
/*...e*/
/*...ssnd_set_noise_atten:0:*/
static void snd_set_noise_atten(byte val)
{
snd_noise_atten = (val&0x0f);
diag_message(DIAG_SND_REGISTERS, "Noise attenuation changed, atten=%d", snd_noise_atten);
}
/*...e*/

void snd_out6(byte val)
{
if ( val & 0x80 )
/* Write to register */
switch ( val & 0x70 )
{
case 0x00: snd_set_tone_freq_low(0, val); break;
case 0x10: snd_set_tone_atten(0, val); break;
case 0x20: snd_set_tone_freq_low(1, val); break;
case 0x30: snd_set_tone_atten(1, val); break;
case 0x40: snd_set_tone_freq_low(2, val); break;
case 0x50: snd_set_tone_atten(2, val); break;
case 0x60: snd_set_noise_ctrl(val); break;
case 0x70: snd_set_noise_atten(val); break;
}
else
/* High 6 bits of frequency */
snd_set_tone_freq_high(val);
}
/*...e*/
/*...ssnd_in3:0:*/
/* There is no data returned by sound hardware when inputing from port 3.
So we return the most recent value fetched over the bus.
If the code did in a,(3), this will be 3, and Pothole Pete relies on this.
Not sure how we'd cope with in a,(c). */

byte snd_in3(void)
{
return (byte) 0x03;
}
/*...e*/

/*...ssnd_callback:0:*/
/*...ssnd_step:0:*/
/* Its important we cope with a frequency value of 0.
Kilopede doesn't set a frequency initially, and yet varies the volume.
We should get a low note, rather than no sound. */

static float snd_step(word freq)
{
float hz;
if ( freq == 0 )
freq = 0x400;
hz = (float) ( 4000000.0 / ( 32.0 * (float) freq ) );
return (float) ( hz * 2.0 ) / (float) FREQ;
}
/*...e*/
/*...ssnd_scale:0:*/
static float snd_scale(byte atten)
{
return (float) ( 0.25 * ( (float) (15-atten) / 15.0 ) );
}
/*...e*/
/*...ssnd_next_noise_bit:0:*/
static int snd_next_noise_bit(void)
{
word input = ( snd_noise_ctrl & 0x04 )
/* White noise */
? ((snd_noise_shifter&0x0008)<<12) ^ ((snd_noise_shifter&0x0001)<<15)
/* Periodic noise */
: ((snd_noise_shifter&0x0001)<<15);
snd_noise_shifter = input | ( snd_noise_shifter >> 1 );
if ( snd_noise_shifter == 0 )
snd_noise_shifter = 0x8000;
return (int) ( snd_noise_shifter & 1 );
}
/*...e*/

void snd_callback (void *user, uint8_t *stream, int len)
{
float *out = (float *) stream;
int framesPerBuffer = len / sizeof (float);
unsigned long i;
int c;
float steps[3];
float scales[3];
float step_noise;
float scale_noise;
// diag_message (DIAG_INIT, "snd_callback (0x%08X, %d)", outputBuffer, framesPerBuffer);
for ( c = 0; c < 3; c++ )
{
word freq = snd_channels[c].freq;
steps[c] = snd_step(freq);
scales[c] = snd_scale(snd_channels[c].atten);
snd_channels[c].phase = (float) fmod(snd_channels[c].phase, 2.0);
}
switch ( snd_noise_ctrl & 0x03 )
{
case 0x00: step_noise = snd_step(16); break;
case 0x01: step_noise = snd_step(32); break;
case 0x02: step_noise = snd_step(64); break;
case 0x03: step_noise = steps[2]; break;
}
scale_noise = snd_scale(snd_noise_atten);
snd_noise_phase = (float) fmod(snd_noise_phase, 2.0);
for ( i = 0; i < framesPerBuffer; i++ )
{
float val = 0.0;
for ( c = 0; c < 3; c++ )
{
if ( (unsigned) snd_channels[c].phase & 1 )
val += scales[c];
else
val -= scales[c];
snd_channels[c].phase += steps[c];
}
if ( ( (unsigned) (snd_noise_phase + step_noise) & 1 ) !=
( (unsigned) (snd_noise_phase ) & 1 ) )
snd_noise_bit = snd_next_noise_bit();
if ( snd_noise_bit )
val += scale_noise;
else
val -= scale_noise;
snd_noise_phase += step_noise;
/* This bit is to try to remove the sharp edges of the
square wave which we are generating */
val = (float) ( val * 0.1 + snd_lastvol * 0.9 );
*out++ = snd_lastvol = val;
}
// diag_message (DIAG_INIT, "Exit snd_callback: aMin = %6.3f aMax = %6.3f", aMin, aMax);
}
/*...e*/

/*...ssnd_init:0:*/
void snd_init(int emu, double latency)
{
if ( emu & SNDEMU_PORTAUDIO )
{
SDL_AudioSpec areq;
snd_emu = emu;
memset (&areq, 0, sizeof (areq));
areq.freq = FREQ;
areq.format = AUDIO_F32SYS;
areq.channels = 1;
if ( latency > 0 ) areq.samples = FREQ * latency;
else areq.samples = 1024;
areq.callback = snd_callback;
SDL_InitSubSystem (SDL_INIT_AUDIO);
dev_id = SDL_OpenAudioDevice (NULL, 0, &areq, &aspec, 0);
SDL_PauseAudioDevice (dev_id, 0);
}
}
/*...e*/
/*...ssnd_term:0:*/
void snd_term(void)
{
if ( snd_emu & SNDEMU_PORTAUDIO )
{
SDL_CloseAudioDevice (dev_id);
dev_id = 0;
}
snd_emu = 0;
}
/*...e*/
9 changes: 7 additions & 2 deletions src/memu/win_sdl.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ static int sdlkey_wk (int keycode)

void win_handle_events (void)
{
SDL_Window *sdl_win;
SDL_Event e;
while ( SDL_PollEvent (&e) != 0 )
{
Expand All @@ -307,15 +308,19 @@ void win_handle_events (void)
case SDL_KEYDOWN:
if ( e.key.repeat == 0 )
{
WIN_PRIV *win = (WIN_PRIV *) SDL_GetWindowData (SDL_GetWindowFromID (e.key.windowID), "MEMU");
sdl_win = SDL_GetWindowFromID (e.key.windowID);
if ( sdl_win == NULL ) break;
WIN_PRIV *win = (WIN_PRIV *) SDL_GetWindowData (sdl_win, "MEMU");
int wk = sdlkey_wk (e.key.keysym.sym);
if (wk > 0) win->keypress ((WIN *) win, wk);
}
break;
case SDL_KEYUP :
if ( e.key.repeat == 0 )
{
WIN_PRIV *win = (WIN_PRIV *) SDL_GetWindowData (SDL_GetWindowFromID (e.key.windowID), "MEMU");
sdl_win = SDL_GetWindowFromID (e.key.windowID);
if ( sdl_win == NULL ) break;
WIN_PRIV *win = (WIN_PRIV *) SDL_GetWindowData (sdl_win, "MEMU");
int wk = sdlkey_wk (e.key.keysym.sym);
if (wk > 0) win->keyrelease ((WIN *) win, wk);
}
Expand Down

0 comments on commit cb75b01

Please sign in to comment.