mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-16 05:27:43 +00:00
Merge pull request #444 from TomHarte/AppleAudio
Introduces a low-pass filter for the Apple II
This commit is contained in:
@@ -139,6 +139,11 @@ class ConcreteMachine:
|
|||||||
// decision to sample it at seven times the CPU clock (plus stretches).
|
// decision to sample it at seven times the CPU clock (plus stretches).
|
||||||
speaker_.set_input_rate(static_cast<float>(master_clock / (2.0 * static_cast<float>(audio_divider))));
|
speaker_.set_input_rate(static_cast<float>(master_clock / (2.0 * static_cast<float>(audio_divider))));
|
||||||
|
|
||||||
|
// Apply a 6Khz low-pass filter. This was picked by ear and by an attempt to understand the
|
||||||
|
// Apple II schematic but, well, I don't claim much insight on the latter. This is definitely
|
||||||
|
// something to review in the future.
|
||||||
|
speaker_.set_high_frequency_cutoff(6000);
|
||||||
|
|
||||||
// Also, start with randomised memory contents.
|
// Also, start with randomised memory contents.
|
||||||
Memory::Fuzz(ram_, sizeof(ram_));
|
Memory::Fuzz(ram_, sizeof(ram_));
|
||||||
}
|
}
|
||||||
|
@@ -27,9 +27,9 @@ static NSLock *CSAudioQueueDeallocLock;
|
|||||||
|
|
||||||
@implementation CSAudioQueue {
|
@implementation CSAudioQueue {
|
||||||
AudioQueueRef _audioQueue;
|
AudioQueueRef _audioQueue;
|
||||||
AudioQueueBufferRef _storedBuffers[NumberOfStoredAudioQueueBuffer];
|
|
||||||
NSLock *_storedBuffersLock;
|
NSLock *_storedBuffersLock;
|
||||||
CSWeakAudioQueuePointer *_weakPointer;
|
CSWeakAudioQueuePointer *_weakPointer;
|
||||||
|
int _enqueuedBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - AudioQueue callbacks
|
#pragma mark - AudioQueue callbacks
|
||||||
@@ -39,16 +39,19 @@ static NSLock *CSAudioQueueDeallocLock;
|
|||||||
*/
|
*/
|
||||||
- (BOOL)audioQueue:(AudioQueueRef)theAudioQueue didCallbackWithBuffer:(AudioQueueBufferRef)buffer {
|
- (BOOL)audioQueue:(AudioQueueRef)theAudioQueue didCallbackWithBuffer:(AudioQueueBufferRef)buffer {
|
||||||
[_storedBuffersLock lock];
|
[_storedBuffersLock lock];
|
||||||
for(int c = 0; c < NumberOfStoredAudioQueueBuffer; c++) {
|
--_enqueuedBuffers;
|
||||||
if(!_storedBuffers[c] || buffer->mAudioDataBytesCapacity > _storedBuffers[c]->mAudioDataBytesCapacity) {
|
|
||||||
if(_storedBuffers[c]) AudioQueueFreeBuffer(_audioQueue, _storedBuffers[c]);
|
// If that leaves nothing in the queue, re-enqueue whatever just came back in order to keep the
|
||||||
_storedBuffers[c] = buffer;
|
// queue going. AudioQueues seem to stop playing and never restart no matter how much encouragement
|
||||||
[_storedBuffersLock unlock];
|
// if exhausted.
|
||||||
return YES;
|
if(!_enqueuedBuffers) {
|
||||||
}
|
AudioQueueEnqueueBuffer(theAudioQueue, buffer, 0, NULL);
|
||||||
|
++_enqueuedBuffers;
|
||||||
|
} else {
|
||||||
|
AudioQueueFreeBuffer(_audioQueue, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[_storedBuffersLock unlock];
|
[_storedBuffersLock unlock];
|
||||||
AudioQueueFreeBuffer(_audioQueue, buffer);
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,18 +161,12 @@ static void audioOutputCallback(
|
|||||||
size_t bufferBytes = lengthInSamples * sizeof(int16_t);
|
size_t bufferBytes = lengthInSamples * sizeof(int16_t);
|
||||||
|
|
||||||
[_storedBuffersLock lock];
|
[_storedBuffersLock lock];
|
||||||
for(int c = 0; c < NumberOfStoredAudioQueueBuffer; c++) {
|
// Don't enqueue more than 4 buffers ahead of now, to ensure not too much latency accrues.
|
||||||
if(_storedBuffers[c] && _storedBuffers[c]->mAudioDataBytesCapacity >= bufferBytes) {
|
if(_enqueuedBuffers > 4) {
|
||||||
memcpy(_storedBuffers[c]->mAudioData, buffer, bufferBytes);
|
[_storedBuffersLock unlock];
|
||||||
_storedBuffers[c]->mAudioDataByteSize = (UInt32)bufferBytes;
|
return;
|
||||||
|
|
||||||
AudioQueueEnqueueBuffer(_audioQueue, _storedBuffers[c], 0, NULL);
|
|
||||||
_storedBuffers[c] = NULL;
|
|
||||||
[_storedBuffersLock unlock];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
[_storedBuffersLock unlock];
|
++_enqueuedBuffers;
|
||||||
|
|
||||||
AudioQueueBufferRef newBuffer;
|
AudioQueueBufferRef newBuffer;
|
||||||
AudioQueueAllocateBuffer(_audioQueue, (UInt32)bufferBytes * 2, &newBuffer);
|
AudioQueueAllocateBuffer(_audioQueue, (UInt32)bufferBytes * 2, &newBuffer);
|
||||||
@@ -177,6 +174,7 @@ static void audioOutputCallback(
|
|||||||
newBuffer->mAudioDataByteSize = (UInt32)bufferBytes;
|
newBuffer->mAudioDataByteSize = (UInt32)bufferBytes;
|
||||||
|
|
||||||
AudioQueueEnqueueBuffer(_audioQueue, newBuffer, 0, NULL);
|
AudioQueueEnqueueBuffer(_audioQueue, newBuffer, 0, NULL);
|
||||||
|
[_storedBuffersLock unlock];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Sampling Rate getters
|
#pragma mark - Sampling Rate getters
|
||||||
|
Reference in New Issue
Block a user