Reply 40 of 57, by superfury
Manually running the title.exe of Links with cycles set to 6000 seems to work a bit. Display works, but it's very slow. A bit of sound at the first 1-2 seconds? Some tone or sweep? After that it's quiet?
Edit: I think that the PIT output is probably correct(according to 1 cycle/instruction and osdev description of modes). I think the problem is in the 'decoding' thaf output and converting it into PCM samples.
//PC speaker output!
speaker_ticktiming += timepassed; //Get the amount of time passed for the PC speaker (current emulated time passed according to set speed)!
if (speaker_ticktiming >= speaker_tick) //Enough time passed to render?
{
length = (uint_32)SAFEDIV(speaker_ticktiming, speaker_tick); //How many ticks to tick?
speaker_ticktiming -= (length*speaker_tick); //Rest the amount of ticks!
if (!FIFOBUFFER_LOCK) //Not locked?
{
lockaudio(); //Lock the audio!
}
//Ticks the speaker when needed!
i = 0; //Init counter!
if (PCSpeakerPort & 2) //Speaker is turned on?
{
short s; //Set the channels! We generate 1 sample of output here!
sword sample; //Current sample!
//Generate the samples from the output signal!
for (;;) //Generate samples!
{
//Average our input ticks!
PITchannels[2].samplesleft += ticklength; //Add our time to the one-shot samples!
tempf = floorf(PITchannels[2].samplesleft); //Take the rounded number of samples to process!
PITchannels[2].samplesleft -= tempf; //Take off the samples we've processed!
render_ticks = (uint_32)tempf; //The ticks to render!
//render_ticks contains the samples to process! Calculate the duty cycle and use it to generate a sample!
dutycycle = 0; //Start with nothing!
for (dutycyclei = render_ticks;dutycyclei;)
{
if (!readfifobuffer(PITchannels[2].rawsignal, ¤tsample)) break; //Failed to read the sample? Stop counting!
sample = currentsample?SHRT_MAX:SHRT_MIN; //Convert sample to 16-bit!
applySpeakerLowpassFilter(&sample); //Low pass filter the signal!
dutycycle += sample; //Add the sample to the duty cycle!
--dutycyclei; //Decrease!
}
if (!render_ticks) //Invalid?
{
s = 0; //Nothing to process!
}
else
{
s = (short)(((float)dutycycle)/((float)render_ticks)); //Convert duty cycle to full average factor!
}
//Add the result to our buffer!
writefifobuffer16(PITchannels[2].buffer, s); //Write the sample to the buffer (mono buffer)!
if (++i == length) //Fully rendered?
{
if (!FIFOBUFFER_LOCK) //Not locked?
{
unlockaudio(); //Unlock the audio!
}
return; //Next item!
}
}
}
else //Not on? Generate quiet signal!
{
//Generate a quiet signal!
for (;;) //Generate samples!
{
writefifobuffer16(PITchannels[2].buffer, 0); //Write the sample to the buffer (mono buffer)!
if (++i == length)
{
if (!FIFOBUFFER_LOCK) //Not locked?
{
unlockaudio(); //Lock the audio!
}
return; //Next item!
}
}
}
if (!FIFOBUFFER_LOCK) //Not locked?
{
unlockaudio(); //Unlock the audio!
}
}
Currently the speaker itself is operating at 44100Hz.
Also:
const float ticklength = (1.0f / SPEAKER_RATE)*TIME_RATE; //Length of one shot samples to read every sample!
Where SPEAKER_RATE is 44100.0f and TIME_RATE is 1193182.0f . So ticklength contains the amount of PIT samples to average for every 44100Hz sample. Is this done correctly? Or is this response sample average different(perhaps actually a different samplerate, like 1000000.0f/60.0f(one sample based on 60us of PIT data). What does all software expect? How long does this period to average need to be? Osdev says 60us, but different average input sample counts give different average values=correct output or junk results, depending on what software expects of the speaker.
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io