I've mostly implemented the APU, but I'm unsure of how to implement the timing of actually outputting crisp sound.
First, I tried to calculate the number of APU cycles per sample (NTSC_FREQ / sampleRate), and that worked pretty well, but there was minor crackling when VSync was on. When there was no frame limiting, it sounded perfect, but it was much slower than the video. I've attached the audio in cycle.mp3
Then, I tried to calculate the time between each cycle (1 / sampleRate), but in that case, there was significantly more crackling, to the point where it was practically unrecognizable. I've attached the audio in time.mp3
By looking at Audacity, I've realized that the crackling is caused by the period of silence after one segment of audio has finished playing but before the next one is queued. How would I get crisp sound without any crackling while still having the audio speeding up if the framerate increases?
First, I tried to calculate the number of APU cycles per sample (NTSC_FREQ / sampleRate), and that worked pretty well, but there was minor crackling when VSync was on. When there was no frame limiting, it sounded perfect, but it was much slower than the video. I've attached the audio in cycle.mp3
Code:
this->sampleSum += this->generateSample();
if(this->cycleCount >= this->cyclesPerSample) {
Sint16 sample = static_cast<Sint16>(globalVolumeFactor * this->sampleSum / this->cycleCount);
SDL_QueueAudio(this->audio.device, &sample, sizeof(sample));
this->cycleCount = 0;
this->sampleSum = 0;
} else this->cycleCount++;
if(this->cycleCount >= this->cyclesPerSample) {
Sint16 sample = static_cast<Sint16>(globalVolumeFactor * this->sampleSum / this->cycleCount);
SDL_QueueAudio(this->audio.device, &sample, sizeof(sample));
this->cycleCount = 0;
this->sampleSum = 0;
} else this->cycleCount++;
Then, I tried to calculate the time between each cycle (1 / sampleRate), but in that case, there was significantly more crackling, to the point where it was practically unrecognizable. I've attached the audio in time.mp3
Code:
this->sampleSum += this->generateSample();
double curTime = glfwGetTime();
if((curTime - this->prevTime) * Audio::sampleRate >= 1) {
this->prevTime = curTime;
Sint16 sample = static_cast<Sint16>(globalVolumeFactor * this->sampleSum / this->cycleCount);
SDL_QueueAudio(this->audio.device, &sample, sizeof(sample));
this->cycleCount = 0;
this->sampleSum = 0;
} else this->cycleCount++;
double curTime = glfwGetTime();
if((curTime - this->prevTime) * Audio::sampleRate >= 1) {
this->prevTime = curTime;
Sint16 sample = static_cast<Sint16>(globalVolumeFactor * this->sampleSum / this->cycleCount);
SDL_QueueAudio(this->audio.device, &sample, sizeof(sample));
this->cycleCount = 0;
this->sampleSum = 0;
} else this->cycleCount++;
By looking at Audacity, I've realized that the crackling is caused by the period of silence after one segment of audio has finished playing but before the next one is queued. How would I get crisp sound without any crackling while still having the audio speeding up if the framerate increases?