Skip to content

Commit

Permalink
Added channel count initializer for AEAudioFileRecorderModule
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeltyson committed Jun 14, 2016
1 parent 6506758 commit 1d8f5de
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 11 deletions.
18 changes: 18 additions & 0 deletions TheAmazingAudioEngine/Modules/Taps/AEAudioFileRecorderModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,31 @@ typedef void (^AEAudioFileRecorderModuleCompletionBlock)();
/*!
* Default initialiser
*
* Records stereo audio.
*
* @param renderer The renderer
* @param url URL to the file to write to
* @param type The type of the file to write
* @param error If not NULL, the error on output
*/
- (instancetype _Nullable)initWithRenderer:(AERenderer * _Nullable)renderer
URL:(NSURL * _Nonnull)url
type:(AEAudioFileType)type
error:(NSError * _Nullable * _Nullable)error;

/*!
* Initialiser, with channel count
*
* @param renderer The renderer
* @param url URL to the file to write to
* @param type The type of the file to write
* @param numberOfChannels Number of channels to record (will mix down or double channels if input is different)
* @param error If not NULL, the error on output
*/
- (instancetype _Nullable)initWithRenderer:(AERenderer * _Nullable)renderer
URL:(NSURL * _Nonnull)url
type:(AEAudioFileType)type
numberOfChannels:(int)numberOfChannels
error:(NSError * _Nullable * _Nullable)error;

/*!
Expand All @@ -71,6 +88,7 @@ typedef void (^AEAudioFileRecorderModuleCompletionBlock)();
*/
- (void)stopRecordingAtTime:(AEHostTicks)time completionBlock:(AEAudioFileRecorderModuleCompletionBlock _Nullable)block;

@property (nonatomic, readonly) int numberOfChannels; //!< Number of channels that will be recorded
@property (nonatomic, readonly) BOOL recording; //!< Whether recording is in progress
@property (nonatomic, readonly) AESeconds recordedTime; //!< Current recording length, in seconds
@end
Expand Down
37 changes: 26 additions & 11 deletions TheAmazingAudioEngine/Modules/Taps/AEAudioFileRecorderModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import "AETypes.h"
#import "AEAudioBufferListUtilities.h"
#import "AEWeakRetainingProxy.h"
#import "AEDSPUtilities.h"
#import <AudioToolbox/AudioToolbox.h>

@interface AEAudioFileRecorderModule () {
Expand All @@ -20,6 +21,7 @@ @interface AEAudioFileRecorderModule () {
BOOL _complete;
UInt32 _recordedFrames;
}
@property (nonatomic, readwrite) int numberOfChannels;
@property (nonatomic, readwrite) BOOL recording;
@property (nonatomic, copy) void (^completionBlock)();
@property (nonatomic, strong) NSTimer * pollTimer;
Expand All @@ -29,14 +31,21 @@ @implementation AEAudioFileRecorderModule

- (instancetype)initWithRenderer:(AERenderer *)renderer URL:(NSURL *)url
type:(AEAudioFileType)type error:(NSError **)error {
return [self initWithRenderer:renderer URL:url type:type numberOfChannels:2 error:error];
}

- (instancetype)initWithRenderer:(AERenderer *)renderer URL:(NSURL *)url type:(AEAudioFileType)type
numberOfChannels:(int)numberOfChannels error:(NSError **)error {

if ( !(self = [super initWithRenderer:renderer]) ) return nil;

if ( !(_audioFile = AEExtAudioFileRefCreate(url, type, self.renderer.sampleRate, 2, error)) ) return nil;
if ( !(_audioFile = AEExtAudioFileRefCreate(url, type, self.renderer.sampleRate, numberOfChannels, error)) ) return nil;

// Prime async recording
ExtAudioFileWriteAsync(_audioFile, 0, NULL);

self.processFunction = AEAudioFileRecorderModuleProcess;
self.numberOfChannels = numberOfChannels;

return self;
}
Expand Down Expand Up @@ -88,33 +97,39 @@ static void AEAudioFileRecorderModuleProcess(__unsafe_unretained AEAudioFileReco
const AudioBufferList * abl = AEBufferStackGet(context->stack, 0);
if ( !abl ) return;

// Prepare stereo buffer
AEAudioBufferListCreateOnStack(stereoBuffer);
for ( int i=0; i<stereoBuffer->mNumberBuffers; i++ ) {
stereoBuffer->mBuffers[i] = abl->mBuffers[MIN(abl->mNumberBuffers-1, i)];
// Prepare buffer with the right number of channels
AEAudioBufferListCreateOnStackWithFormat(buffer, AEAudioDescriptionWithChannelsAndRate(THIS->_numberOfChannels, 0));
for ( int i=0; i<buffer->mNumberBuffers; i++ ) {
buffer->mBuffers[i] = abl->mBuffers[MIN(abl->mNumberBuffers-1, i)];
}
if ( buffer->mBuffers == 1 && abl->mNumberBuffers > 1 ) {
// Mix down to mono
for ( int i=1; i<abl->mNumberBuffers; i++ ) {
AEDSPMixMono(abl->mBuffers[i].mData, buffer->mBuffers[0].mData, 1.0, 1.0, context->frames, buffer->mBuffers[0].mData);
}
}

// Advance frames, if we have a start time mid-buffer
UInt32 frames = context->frames;
if ( startTime && startTime > context->timestamp->mHostTime ) {
UInt32 advanceFrames = round(AESecondsFromHostTicks(startTime - context->timestamp->mHostTime) * context->sampleRate);
for ( int i=0; i<stereoBuffer->mNumberBuffers; i++ ) {
stereoBuffer->mBuffers[i].mData += AEAudioDescription.mBytesPerFrame * advanceFrames;
stereoBuffer->mBuffers[i].mDataByteSize -= AEAudioDescription.mBytesPerFrame * advanceFrames;
for ( int i=0; i<buffer->mNumberBuffers; i++ ) {
buffer->mBuffers[i].mData += AEAudioDescription.mBytesPerFrame * advanceFrames;
buffer->mBuffers[i].mDataByteSize -= AEAudioDescription.mBytesPerFrame * advanceFrames;
}
frames -= advanceFrames;
}

// Truncate if we have a stop time mid-buffer
if ( stopTime && stopTime < hostTimeAtBufferEnd ) {
UInt32 truncateFrames = round(AESecondsFromHostTicks(hostTimeAtBufferEnd - stopTime) * context->sampleRate);
for ( int i=0; i<stereoBuffer->mNumberBuffers; i++ ) {
stereoBuffer->mBuffers[i].mDataByteSize -= AEAudioDescription.mBytesPerFrame * truncateFrames;
for ( int i=0; i<buffer->mNumberBuffers; i++ ) {
buffer->mBuffers[i].mDataByteSize -= AEAudioDescription.mBytesPerFrame * truncateFrames;
}
frames -= truncateFrames;
}

AECheckOSStatus(ExtAudioFileWriteAsync(THIS->_audioFile, frames, stereoBuffer), "ExtAudioFileWriteAsync");
AECheckOSStatus(ExtAudioFileWriteAsync(THIS->_audioFile, frames, buffer), "ExtAudioFileWriteAsync");
THIS->_recordedFrames += frames;

if ( stopTime && stopTime < hostTimeAtBufferEnd ) {
Expand Down

0 comments on commit 1d8f5de

Please sign in to comment.