From 09edc12bc45312aac0be72e258c931b1fb37fb20 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Mon, 19 Jan 2009 20:00:34 +0000 Subject: [PATCH] More work on sound.cpp, especially definition of time constants --- apple2.cfg | 4 ++-- src/apple2.cpp | 19 +++++++++++++++++++ src/sound.cpp | 33 ++++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/apple2.cfg b/apple2.cfg index 5ee931d..ee5cc6b 100755 --- a/apple2.cfg +++ b/apple2.cfg @@ -21,9 +21,9 @@ autoSaveState = 1 #floppyImage1 = ./disks/temp.nib #floppyImage1 = ./disks/temp.dsk # Yes -floppyImage1 = ./disks/bt1_boot.dsk +#floppyImage1 = ./disks/bt1_boot.dsk # Yes -#floppyImage1 = ./disks/bt2_boot.dsk +floppyImage1 = ./disks/bt2_boot.dsk # No (gets stuck on 1st track) #floppyImage1 = ./disks/bt3_boot.dsk # Yes diff --git a/src/apple2.cpp b/src/apple2.cpp index 729dc23..f50454d 100755 --- a/src/apple2.cpp +++ b/src/apple2.cpp @@ -163,6 +163,23 @@ if (addr >= 0xC080 && addr <= 0xC08F) } else if ((addr & 0xFFF0) == 0xC030) { +/* +This is problematic, mainly because the v65C02 removes actual cycles run after each call. +Therefore, we don't really have a reliable method of sending a timestamp to the sound routine. +How to fix? + +What we need to send is a delta T value but related to the IRQ buffer routine. E.g., if the buffer +hasn't had any changes in it then we just fill it with the last sample value and are done. Then +we need to adjust our delta T accordingly. What we could do is keep a running total of time since the +last change and adjust it accordingly, i.e., whenever a sound IRQ happens. +How to keep track? + +Have deltaT somewhere. Then, whenever there's a toggle, backfill buffer with last spkr state and reset +deltaT to zero. In the sound IRQ, if deltaT > buffer size, then subtract buffer size from deltaT. (?) + + + +*/ ToggleSpeaker(GetCurrentV65C02Clock()); //should it return something else here??? return 0x00; @@ -797,6 +814,8 @@ else if (event.key.keysym.sym == SDLK_F10) SetCallbackTime(FrameCallback, 16666.66666667); //Instead of this, we should yield remaining time to other processes... !!! FIX !!! +//lessee... +//nope. SDL_Delay(10); while (SDL_GetTicks() - startTicks < 16); // Wait for next frame... startTicks = SDL_GetTicks(); } diff --git a/src/sound.cpp b/src/sound.cpp index 9158db6..d8a8771 100755 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -26,6 +26,10 @@ #include "log.h" +#define SAMPLE_RATE (44100.0) +#define SAMPLES_PER_FRAME (SAMPLE_RATE / 60.0) +#define CYCLES_PER_SAMPLE ((1024000.0 / 60.0) / (SAMPLES_PER_FRAME)) +#define SOUND_BUFFER_SIZE 8192 #define AMPLITUDE (32) // -32 - +32 seems to be plenty loud! // Global variables @@ -36,7 +40,7 @@ static SDL_AudioSpec desired; static bool soundInitialized = false; static bool speakerState; -static uint8 soundBuffer[4096]; +static uint8 soundBuffer[SOUND_BUFFER_SIZE]; static uint32 soundBufferPos; static uint32 sampleBase; static SDL_cond * conditional = NULL; @@ -56,7 +60,7 @@ void SoundInit(void) return; #endif - desired.freq = 44100; // SDL will do conversion on the fly, if it can't get the exact rate. Nice! + desired.freq = SAMPLE_RATE; // SDL will do conversion on the fly, if it can't get the exact rate. Nice! desired.format = AUDIO_S8; // This uses the native endian (for portability)... // desired.format = AUDIO_S16SYS; // This uses the native endian (for portability)... desired.channels = 1; @@ -173,9 +177,9 @@ if (time > 95085)//(time & 0x80000000) // (or do we?) SDL_LockAudio(); - uint32 currentPos = sampleBase + (uint32)((double)time / 23.2199); + uint32 currentPos = sampleBase + (uint32)((double)time / CYCLES_PER_SAMPLE); - if (currentPos > 4095) + if (currentPos > SOUND_BUFFER_SIZE - 1) { #if 0 WriteLog("ToggleSpeaker() about to go into spinlock at time: %08X (%u) (sampleBase=%u)!\n", time, time, sampleBase); @@ -216,6 +220,25 @@ void HandleSoundAtFrameEdge(void) return; SDL_LockAudio(); - sampleBase += 735; + sampleBase += SAMPLES_PER_FRAME; SDL_UnlockAudio(); } + +/* +A better way might be as follows: + +Keep timestamp array of speaker toggle times. In the sound routine, unpack as many as will fit +into the given buffer and keep going. Have the toggle function check to see if the buffer is full, +and if it is, way for a signal from the interrupt that there's room for more. Can keep a circular +buffer. Also, would need a timestamp buffer on the order of 2096 samples *in theory* could toggle +each sample + +Instead of a timestamp, just keep a delta. That way, don't need to deal with wrapping and all that +(though the timestamp could wrap--need to check into that) + +Need to consider corner cases where a sound IRQ happens but no speaker toggle happened. + +*/ + + + -- 2.37.2