mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Added lots of debugging output while I attempt to locate the source of audio scratchiness, also simplified manner of dealing with wraparound within the AudioQueue wrapper.
This commit is contained in:
parent
b58e59e2bb
commit
ddcc34740b
@ -10,6 +10,6 @@
|
|||||||
|
|
||||||
@interface AudioQueue : NSObject
|
@interface AudioQueue : NSObject
|
||||||
|
|
||||||
- (void)enqueueAudioBuffer:(const int16_t *)buffer numberOfSamples:(unsigned int)lengthInSamples;
|
- (void)enqueueAudioBuffer:(const int16_t *)buffer numberOfSamples:(size_t)lengthInSamples;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -17,9 +17,8 @@
|
|||||||
{
|
{
|
||||||
AudioQueueRef _audioQueue;
|
AudioQueueRef _audioQueue;
|
||||||
AudioQueueBufferRef _audioBuffers[AudioQueueNumAudioBuffers];
|
AudioQueueBufferRef _audioBuffers[AudioQueueNumAudioBuffers];
|
||||||
unsigned int _audioStreamReadPosition, _audioStreamWritePosition, _queuedAudioStreamSegments;
|
unsigned int _audioStreamReadPosition, _audioStreamWritePosition;
|
||||||
int16_t _audioStream[AudioQueueStreamLength];
|
int16_t _audioStream[AudioQueueStreamLength];
|
||||||
BOOL _isOutputtingAudio;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -30,18 +29,26 @@
|
|||||||
{
|
{
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
if(_queuedAudioStreamSegments > AudioQueueNumAudioBuffers-1) _isOutputtingAudio = YES;
|
const unsigned int writeLead = _audioStreamWritePosition - _audioStreamReadPosition;
|
||||||
|
const size_t audioDataSampleSize = buffer->mAudioDataByteSize / sizeof(int16_t);
|
||||||
if(_isOutputtingAudio && _queuedAudioStreamSegments)
|
if(writeLead >= audioDataSampleSize)
|
||||||
{
|
{
|
||||||
_queuedAudioStreamSegments--;
|
size_t samplesBeforeOverflow = AudioQueueStreamLength - (_audioStreamReadPosition % AudioQueueStreamLength);
|
||||||
memcpy(buffer->mAudioData, &_audioStream[_audioStreamReadPosition], buffer->mAudioDataByteSize);
|
if(audioDataSampleSize <= samplesBeforeOverflow)
|
||||||
_audioStreamReadPosition = (_audioStreamReadPosition + AudioQueueBufferLength)%AudioQueueStreamLength;
|
{
|
||||||
|
memcpy(buffer->mAudioData, &_audioStream[_audioStreamReadPosition % AudioQueueStreamLength], buffer->mAudioDataByteSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const size_t bytesRemaining = samplesBeforeOverflow * sizeof(int16_t);
|
||||||
|
memcpy(buffer->mAudioData, &_audioStream[_audioStreamReadPosition % AudioQueueStreamLength], bytesRemaining);
|
||||||
|
memcpy(buffer->mAudioData, &_audioStream[0], buffer->mAudioDataByteSize - bytesRemaining);
|
||||||
|
}
|
||||||
|
_audioStreamReadPosition += audioDataSampleSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memset(buffer->mAudioData, 0, buffer->mAudioDataByteSize);
|
memset(buffer->mAudioData, 0, buffer->mAudioDataByteSize);
|
||||||
_isOutputtingAudio = NO;
|
|
||||||
}
|
}
|
||||||
AudioQueueEnqueueBuffer(theAudioQueue, buffer, 0, NULL);
|
AudioQueueEnqueueBuffer(theAudioQueue, buffer, 0, NULL);
|
||||||
}
|
}
|
||||||
@ -91,7 +98,6 @@ static void audioOutputCallback(
|
|||||||
0,
|
0,
|
||||||
&_audioQueue))
|
&_audioQueue))
|
||||||
{
|
{
|
||||||
_audioStreamWritePosition = AudioQueueBufferLength;
|
|
||||||
UInt32 bufferBytes = AudioQueueBufferLength * sizeof(int16_t);
|
UInt32 bufferBytes = AudioQueueBufferLength * sizeof(int16_t);
|
||||||
|
|
||||||
int c = AudioQueueNumAudioBuffers;
|
int c = AudioQueueNumAudioBuffers;
|
||||||
@ -115,21 +121,23 @@ static void audioOutputCallback(
|
|||||||
if(_audioQueue) AudioQueueDispose(_audioQueue, NO);
|
if(_audioQueue) AudioQueueDispose(_audioQueue, NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)enqueueAudioBuffer:(const int16_t *)buffer numberOfSamples:(unsigned int)lengthInSamples
|
- (void)enqueueAudioBuffer:(const int16_t *)buffer numberOfSamples:(size_t)lengthInSamples
|
||||||
{
|
{
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
memcpy(&_audioStream[_audioStreamWritePosition], buffer, lengthInSamples * sizeof(int16_t));
|
size_t samplesBeforeOverflow = AudioQueueStreamLength - (_audioStreamWritePosition % AudioQueueStreamLength);
|
||||||
_audioStreamWritePosition = (_audioStreamWritePosition + lengthInSamples)%AudioQueueStreamLength;
|
|
||||||
|
|
||||||
if(_queuedAudioStreamSegments == (AudioQueueStreamLength/AudioQueueBufferLength))
|
if(samplesBeforeOverflow < lengthInSamples)
|
||||||
{
|
{
|
||||||
_audioStreamReadPosition = (_audioStreamReadPosition + lengthInSamples)%AudioQueueStreamLength;
|
memcpy(&_audioStream[_audioStreamWritePosition % AudioQueueStreamLength], buffer, samplesBeforeOverflow * sizeof(int16_t));
|
||||||
|
memcpy(&_audioStream[0], &buffer[samplesBeforeOverflow], (lengthInSamples - samplesBeforeOverflow) * sizeof(int16_t));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_queuedAudioStreamSegments++;
|
memcpy(&_audioStream[_audioStreamWritePosition % AudioQueueStreamLength], buffer, lengthInSamples * sizeof(int16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_audioStreamWritePosition += lengthInSamples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,9 +13,21 @@
|
|||||||
|
|
||||||
@implementation CSElectron {
|
@implementation CSElectron {
|
||||||
Electron::Machine _electron;
|
Electron::Machine _electron;
|
||||||
|
|
||||||
|
NSTimeInterval _periodicStart;
|
||||||
|
int _numberOfCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)doRunForNumberOfCycles:(int)numberOfCycles {
|
- (void)doRunForNumberOfCycles:(int)numberOfCycles {
|
||||||
|
_numberOfCycles += numberOfCycles;
|
||||||
|
NSTimeInterval timeNow = [NSDate timeIntervalSinceReferenceDate];
|
||||||
|
NSTimeInterval difference = timeNow - _periodicStart;
|
||||||
|
if(difference > 1.0)
|
||||||
|
{
|
||||||
|
NSLog(@"cycles: %0.0f", (double)_numberOfCycles / difference);
|
||||||
|
_periodicStart = timeNow;
|
||||||
|
_numberOfCycles = 0;
|
||||||
|
}
|
||||||
_electron.run_for_cycles(numberOfCycles);
|
_electron.run_for_cycles(numberOfCycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
#include "../SignalProcessing/Stepper.hpp"
|
#include "../SignalProcessing/Stepper.hpp"
|
||||||
|
|
||||||
namespace Outputs {
|
namespace Outputs {
|
||||||
@ -76,6 +77,17 @@ template <class T> class Filter: public Speaker {
|
|||||||
{
|
{
|
||||||
if(_coefficients_are_dirty) update_filter_coefficients();
|
if(_coefficients_are_dirty) update_filter_coefficients();
|
||||||
|
|
||||||
|
_periodic_cycles += input_cycles;
|
||||||
|
time_t time_now = time(nullptr);
|
||||||
|
if(time_now > _periodic_start)
|
||||||
|
{
|
||||||
|
printf("input audio samples: %d\n", _periodic_cycles);
|
||||||
|
printf("output audio samples: %d\n", _periodic_output);
|
||||||
|
_periodic_cycles = 0;
|
||||||
|
_periodic_output = 0;
|
||||||
|
_periodic_start = time_now;
|
||||||
|
}
|
||||||
|
|
||||||
// point sample for now, as a temporary measure
|
// point sample for now, as a temporary measure
|
||||||
input_cycles += _input_cycles_carry;
|
input_cycles += _input_cycles_carry;
|
||||||
while(input_cycles > 0)
|
while(input_cycles > 0)
|
||||||
@ -99,11 +111,17 @@ template <class T> class Filter: public Speaker {
|
|||||||
if(steps > 1)
|
if(steps > 1)
|
||||||
static_cast<T *>(this)->skip_samples((unsigned int)(steps-1));
|
static_cast<T *>(this)->skip_samples((unsigned int)(steps-1));
|
||||||
input_cycles -= steps;
|
input_cycles -= steps;
|
||||||
|
_periodic_output ++;
|
||||||
}
|
}
|
||||||
_input_cycles_carry = input_cycles;
|
_input_cycles_carry = input_cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Filter() : _periodic_cycles(0), _periodic_start(0) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
time_t _periodic_start;
|
||||||
|
int _periodic_cycles;
|
||||||
|
int _periodic_output;
|
||||||
SignalProcessing::Stepper *_stepper;
|
SignalProcessing::Stepper *_stepper;
|
||||||
int _input_cycles_carry;
|
int _input_cycles_carry;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user