-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
659 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// | ||
// RKAudioRecorder.h | ||
// Pods | ||
// | ||
// Created by goccy on 2017/06/16. | ||
// | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
#import <AudioToolbox/AudioToolbox.h> | ||
#import <AVFoundation/AVFoundation.h> | ||
|
||
@interface RKAudioRecorder : NSObject | ||
|
||
@property(nonatomic, readonly) BOOL isRecording; | ||
@property(nonatomic, readonly) ExtAudioFileRef audioFile; | ||
|
||
+ (instancetype)sharedInstance; | ||
|
||
- (BOOL)startRecording; | ||
|
||
- (void)stopRecording; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// | ||
// RKAudioRecorder.m | ||
// Pods | ||
// | ||
// Created by goccy on 2017/06/16. | ||
// | ||
// | ||
|
||
#import "RKAudioRecorder.h" | ||
#import "RKAudioUnitProxy.h" | ||
#import "RKRecordFile.h" | ||
|
||
@interface RKAudioRecorder() | ||
|
||
@property(nonatomic, readwrite) BOOL isRecording; | ||
|
||
@property(nonatomic, readwrite) ExtAudioFileRef audioFile; | ||
|
||
@end | ||
|
||
@implementation RKAudioRecorder | ||
|
||
static RKAudioRecorder *g_sharedInstance = nil; | ||
|
||
+ (instancetype)sharedInstance | ||
{ | ||
static dispatch_once_t onceToken; | ||
dispatch_once(&onceToken, ^{ | ||
g_sharedInstance = [RKAudioRecorder new]; | ||
}); | ||
return g_sharedInstance; | ||
} | ||
|
||
- (NSURL *)defaultRecordFileURL | ||
{ | ||
return [RKRecordFile fileURL:@"audio.aiff"]; | ||
} | ||
|
||
- (BOOL)startRecording | ||
{ | ||
AudioStreamBasicDescription asbd; | ||
asbd.mSampleRate = 44100.0; | ||
asbd.mFormatID = kAudioFormatLinearPCM; | ||
asbd.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved; | ||
asbd.mBitsPerChannel = 32; | ||
asbd.mChannelsPerFrame = 2; | ||
asbd.mFramesPerPacket = 1; | ||
asbd.mBytesPerFrame = 4; | ||
asbd.mBytesPerPacket = 4; | ||
asbd.mReserved = 0; | ||
|
||
AudioStreamBasicDescription createASBD; | ||
memcpy(&createASBD, &asbd, sizeof(AudioStreamBasicDescription)); | ||
createASBD.mFormatFlags = kLinearPCMFormatFlagIsBigEndian|kLinearPCMFormatFlagIsSignedInteger|kLinearPCMFormatFlagIsPacked; | ||
createASBD.mBitsPerChannel = 16; | ||
|
||
if (ExtAudioFileCreateWithURL((__bridge CFURLRef)[self defaultRecordFileURL], | ||
kAudioFileAIFFType, | ||
&createASBD, | ||
NULL, | ||
kAudioFileFlags_EraseFile, | ||
&_audioFile) != noErr) { | ||
return NO; | ||
} | ||
// Set up the converter | ||
if (ExtAudioFileSetProperty(self.audioFile, | ||
kExtAudioFileProperty_ClientDataFormat, | ||
sizeof(AudioStreamBasicDescription), | ||
&asbd) != noErr) { | ||
return NO; | ||
} | ||
self.isRecording = YES; | ||
return YES; | ||
} | ||
|
||
- (void)stopRecording | ||
{ | ||
self.isRecording = NO; | ||
ExtAudioFileDispose(self.audioFile); | ||
NSLog(@"write file %@", [self defaultRecordFileURL].path); | ||
} | ||
|
||
+ (void)injectAudioUnitProxy | ||
{ | ||
// (1) Fetch all `AudioComponent` by `AudioComponentFindNext` | ||
// (2) `AudioComponentRegister` can register customized AudioUnit defined lifecycle. | ||
// (3) Define newer version of predefined AudioUnit | ||
// (4) After this section, `AudioComponentFindNext(NULL, desc)` returns `newer` version for AudioUnit ( our customized AudioUnit ) | ||
AudioComponentDescription allDesc = {0}; | ||
AudioComponent component = NULL; | ||
while ((component = AudioComponentFindNext(component, &allDesc)) != NULL) { | ||
AudioComponentDescription outDesc; | ||
AudioComponentGetDescription(component, &outDesc); | ||
CFStringRef name; | ||
AudioComponentCopyName(component, &name); | ||
UInt32 version; | ||
AudioComponentGetVersion(component, &version); | ||
|
||
// ignore not supported componentSubType | ||
if (outDesc.componentSubType == kAudioUnitSubType_AUiPodTime) continue; | ||
if (outDesc.componentSubType == kAudioUnitSubType_AUiPodEQ) continue; | ||
|
||
AudioComponentInstance instance; | ||
assert(AudioComponentInstanceNew(component, &instance) == noErr); | ||
if (AudioUnitInitialize(instance) == noErr) { | ||
AudioComponentRegister(&outDesc, name, version + 1, &RKAudioUnitProxyPlugin::factory); | ||
} | ||
AudioUnitUninitialize(instance); | ||
AudioComponentInstanceDispose(instance); | ||
} | ||
} | ||
|
||
+ (void)load | ||
{ | ||
[[self class] injectAudioUnitProxy]; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// | ||
// RKAudioUnitProxy.h | ||
// Pods | ||
// | ||
// Created by goccy on 2017/06/16. | ||
// | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
#import <AudioToolbox/AudioToolbox.h> | ||
#import <AVFoundation/AVFoundation.h> | ||
|
||
class RKAudioUnitProxy { | ||
public: | ||
AudioUnit __nonnull audioUnit; | ||
AudioUnit __nonnull originalAudioUnit; | ||
AudioComponentDescription audioComponentDescription; | ||
|
||
RKAudioUnitProxy(AudioComponentInstance __nonnull instance); | ||
~RKAudioUnitProxy(void); | ||
void setAudioComponentDescription(AudioComponentDescription from); | ||
}; | ||
|
||
class RKAudioUnitProxyPlugin { | ||
public: | ||
RKAudioUnitProxyPlugin(void); | ||
~RKAudioUnitProxyPlugin(void); | ||
static AudioComponentPlugInInterface *__nonnull factory(const AudioComponentDescription *__nonnull inDesc); | ||
|
||
private: | ||
RKAudioUnitProxy *__nonnull audioUnitProxy; | ||
|
||
static OSStatus open(AudioComponentPlugInInterface *__nonnull plugin, AudioComponentInstance __nonnull instance); | ||
static OSStatus close(AudioComponentPlugInInterface *__nonnull plugin); | ||
static AudioComponentMethod __nonnull lookup(SInt16 selector); | ||
|
||
static OSStatus unInitialize(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus initialize(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus getPropertyInfo(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitPropertyID inID, | ||
AudioUnitScope inScope, | ||
AudioUnitElement inElement, | ||
UInt32 *__nullable outDataSize, | ||
Boolean *__nullable outWritable); | ||
static OSStatus getProperty(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitPropertyID inID, | ||
AudioUnitScope inScope, | ||
AudioUnitElement inElement, | ||
void *__nonnull outData, | ||
UInt32 *__nonnull ioDataSize); | ||
static OSStatus setProperty(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitPropertyID inID, | ||
AudioUnitScope inScope, | ||
AudioUnitElement inElement, | ||
const void * __nullable inData, | ||
UInt32 inDataSize); | ||
static OSStatus addPropertyListener(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitPropertyID inID, | ||
AudioUnitPropertyListenerProc __nonnull inProc, | ||
void * __nullable inProcUserData); | ||
static OSStatus removePropertyListenerWithUserData(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitPropertyID inID, | ||
AudioUnitPropertyListenerProc __nonnull inProc, | ||
void * __nullable inProcUserData); | ||
static OSStatus addRenderNotify(AudioComponentPlugInInterface *__nonnull plugin, | ||
AURenderCallback __nonnull inProc, | ||
void *__nullable inProcUserData); | ||
static OSStatus removeRenderNotify(AudioComponentPlugInInterface *__nonnull plugin, | ||
AURenderCallback __nonnull inProc, | ||
void *__nullable inProcUserData); | ||
static OSStatus getParameter(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitParameterID inID, | ||
AudioUnitScope inScope, | ||
AudioUnitElement inElement, | ||
AudioUnitParameterValue *__nonnull outValue); | ||
static OSStatus setParameter(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitParameterID inID, | ||
AudioUnitScope inScope, | ||
AudioUnitElement inElement, | ||
AudioUnitParameterValue inValue, | ||
UInt32 inBufferOffsetInFrames); | ||
static OSStatus scheduleParameters(AudioComponentPlugInInterface *__nonnull plugin, | ||
const AudioUnitParameterEvent *__nonnull inParameterEvent, | ||
UInt32 inNumParamEvents); | ||
static OSStatus reset(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitScope inScope, | ||
AudioUnitElement inElement); | ||
static OSStatus process(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitRenderActionFlags *__nullable ioActionFlags, | ||
const AudioTimeStamp *__nonnull inTimeStamp, | ||
UInt32 inNumberFrames, | ||
AudioBufferList *__nonnull ioData); | ||
static OSStatus processMultiple(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitRenderActionFlags *__nullable ioActionFlags, | ||
const AudioTimeStamp *__nonnull inTimeStamp, | ||
UInt32 inNumberFrames, | ||
UInt32 inNumberInputBufferLists, | ||
const AudioBufferList * __nonnull * __nonnull inInputBufferLists, | ||
UInt32 inNumberOutputBufferLists, | ||
AudioBufferList * __nonnull * __nonnull ioOutputBufferLists); | ||
static OSStatus render(AudioComponentPlugInInterface *__nonnull plugin, | ||
AudioUnitRenderActionFlags *__nonnull ioActionFlags, | ||
const AudioTimeStamp *__nonnull inTimeStamp, | ||
UInt32 inOutputBusNumber, | ||
UInt32 inNumberFrames, | ||
AudioBufferList *__nonnull ioData); | ||
static OSStatus start(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus stop(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus callback0x101(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus callback0x102(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus callback0x105(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus callback0x106(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus callback0x008(AudioComponentPlugInInterface *__nonnull plugin); | ||
static OSStatus callback0x00c(AudioComponentPlugInInterface *__nonnull plugin); | ||
}; |
Oops, something went wrong.