Core Audio: Add a slight fading to operations
Add 10 millisecond fade to seeking, pausing and unpausing, and stopping on command. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
fab4d3705e
commit
5e48382774
5 changed files with 86 additions and 3 deletions
|
@ -75,6 +75,7 @@
|
|||
|
||||
[self waitUntilCallbacksExit];
|
||||
if(output) {
|
||||
[output fadeOut];
|
||||
[output setShouldContinue:NO];
|
||||
[output close];
|
||||
}
|
||||
|
@ -83,6 +84,9 @@
|
|||
}
|
||||
[output setupWithInterval:resumeInterval];
|
||||
[output setVolume:volume];
|
||||
if(resumeInterval) {
|
||||
[output fadeIn];
|
||||
}
|
||||
@synchronized(chainQueue) {
|
||||
for(id anObject in chainQueue) {
|
||||
[anObject setShouldContinue:NO];
|
||||
|
@ -166,7 +170,7 @@
|
|||
}
|
||||
|
||||
- (void)pause {
|
||||
[output pause];
|
||||
[output fadeOut];
|
||||
|
||||
[self setPlaybackStatus:CogStatusPaused waitUntilDone:YES];
|
||||
}
|
||||
|
@ -178,6 +182,7 @@
|
|||
[self launchOutputThread];
|
||||
}
|
||||
|
||||
[output fadeIn];
|
||||
[output resume];
|
||||
|
||||
[self setPlaybackStatus:CogStatusPlaying waitUntilDone:YES];
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
- (void)close;
|
||||
- (void)seek:(double)time;
|
||||
|
||||
- (void)fadeOut;
|
||||
- (void)fadeIn;
|
||||
|
||||
- (AudioChunk *)readChunk:(size_t)amount;
|
||||
|
||||
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig;
|
||||
|
|
|
@ -99,6 +99,14 @@
|
|||
[output resume];
|
||||
}
|
||||
|
||||
- (void)fadeOut {
|
||||
[output fadeOut];
|
||||
}
|
||||
|
||||
- (void)fadeIn {
|
||||
[output fadeIn];
|
||||
}
|
||||
|
||||
- (void)incrementAmountPlayed:(double)seconds {
|
||||
amountPlayed += seconds;
|
||||
amountPlayedInterval += seconds;
|
||||
|
|
|
@ -57,6 +57,11 @@ using std::atomic_long;
|
|||
BOOL commandStop;
|
||||
BOOL resetting;
|
||||
|
||||
BOOL fading, faded;
|
||||
float fadeLevel;
|
||||
float fadeStep;
|
||||
float fadeTarget;
|
||||
|
||||
BOOL eqEnabled;
|
||||
BOOL eqInitialized;
|
||||
|
||||
|
@ -110,6 +115,9 @@ using std::atomic_long;
|
|||
- (void)resume;
|
||||
- (void)stop;
|
||||
|
||||
- (void)fadeOut;
|
||||
- (void)fadeIn;
|
||||
|
||||
- (double)latency;
|
||||
|
||||
- (double)volume;
|
||||
|
|
|
@ -534,6 +534,29 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
}
|
||||
}
|
||||
|
||||
static BOOL fadeAudio(float * samples, size_t channels, size_t count, float * fadeLevel, float fadeStep, float fadeTarget) {
|
||||
float _fadeLevel = *fadeLevel;
|
||||
BOOL towardZero = fadeStep < 0.0;
|
||||
BOOL stopping = NO;
|
||||
for(size_t i = 0; i < count; ++i) {
|
||||
for(size_t j = 0; j < channels; ++j) {
|
||||
samples[j] *= _fadeLevel;
|
||||
}
|
||||
_fadeLevel += fadeStep;
|
||||
if(towardZero && _fadeLevel <= fadeTarget) {
|
||||
_fadeLevel = fadeTarget;
|
||||
fadeStep = 0.0;
|
||||
stopping = YES;
|
||||
} else if(!towardZero && _fadeLevel >= fadeTarget) {
|
||||
_fadeLevel = fadeTarget;
|
||||
fadeStep = 0.0;
|
||||
stopping = YES;
|
||||
}
|
||||
}
|
||||
*fadeLevel = _fadeLevel;
|
||||
return stopping;
|
||||
}
|
||||
|
||||
- (void)renderAndConvert {
|
||||
if(resetStreamFormat) {
|
||||
[self updateStreamFormat];
|
||||
|
@ -583,7 +606,7 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
OutputCoreAudio *_self = (__bridge OutputCoreAudio *)refCon;
|
||||
int renderedSamples = 0;
|
||||
|
||||
if(_self->resetting) {
|
||||
if(_self->resetting || _self->faded) {
|
||||
inputData->mBuffers[0].mDataByteSize = frameCount * format->mBytesPerPacket;
|
||||
bzero(inputData->mBuffers[0].mData, inputData->mBuffers[0].mDataByteSize);
|
||||
inputData->mBuffers[0].mNumberChannels = channels;
|
||||
|
@ -610,7 +633,7 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
renderedSamples += inputTodo;
|
||||
}
|
||||
|
||||
if(_self->stopping || _self->resetting) {
|
||||
if(_self->stopping || _self->resetting || _self->faded) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -630,6 +653,17 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
|
||||
scale_by_volume((float*)inputData->mBuffers[0].mData, renderedSamples * channels, volumeScale * _self->volume);
|
||||
|
||||
if(_self->fading) {
|
||||
BOOL faded = fadeAudio((float*)inputData->mBuffers[0].mData, channels, renderedSamples, &_self->fadeLevel, _self->fadeStep, _self->fadeTarget);
|
||||
if(faded) {
|
||||
if(_self->fadeStep < 0.0f) {
|
||||
_self->faded = YES;
|
||||
}
|
||||
_self->fading = NO;
|
||||
_self->fadeStep = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
inputData->mBuffers[0].mDataByteSize = renderedSamples * format->mBytesPerPacket;
|
||||
inputData->mBuffers[0].mNumberChannels = channels;
|
||||
|
||||
|
@ -667,6 +701,12 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
outputDeviceID = -1;
|
||||
restarted = NO;
|
||||
|
||||
fadeTarget = 1.0f;
|
||||
fadeLevel = 1.0f;
|
||||
fadeStep = 0.0f;
|
||||
fading = NO;
|
||||
faded = NO;
|
||||
|
||||
AudioComponentDescription desc;
|
||||
NSError *err;
|
||||
|
||||
|
@ -788,6 +828,11 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
compareVal = [outputController getTotalLatency];
|
||||
usleep(5000);
|
||||
} while(!commandStop && compareVal > 0 && compareMax-- > 0);
|
||||
} else {
|
||||
[self fadeOut];
|
||||
while(fading && !faded) {
|
||||
usleep(5000);
|
||||
}
|
||||
}
|
||||
[_au stopHardware];
|
||||
_au = nil;
|
||||
|
@ -850,4 +895,18 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
return deviceChannelConfig;
|
||||
}
|
||||
|
||||
// 10 milliseconds
|
||||
- (void)fadeOut {
|
||||
fadeTarget = 0.0f;
|
||||
fadeStep = ((fadeTarget - fadeLevel) / deviceFormat.mSampleRate) * (1000.0f / 10.0f);
|
||||
fading = YES;
|
||||
}
|
||||
|
||||
- (void)fadeIn {
|
||||
fadeTarget = 1.0;
|
||||
fadeStep = ((fadeTarget - fadeLevel) / deviceFormat.mSampleRate) * (1000.0f / 10.0f);
|
||||
fading = YES;
|
||||
faded = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in a new issue