1.单声道录音
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef void (^kAudioUnitRecorderOnputBlock)(AudioBufferList *bufferList);
@interface FSUnitRecorder : NSObject
@property (assign, nonatomic) double sampleRate;
@property (assign, nonatomic, readonly) BOOL isRecording;
@property (copy, nonatomic) kAudioUnitRecorderOnputBlock bufferListBlock;
- (void)start;
- (void)stop;
@end
NS_ASSUME_NONNULL_END
#import "FSUnitRecorder.h"
@interface FSUnitRecorder ()
{
AudioUnit audioUnit;
BOOL audioComponentInitialized;
}
@property (nonatomic,assign) AudioStreamBasicDescription inputStreamDesc;
@end
@implementation FSUnitRecorder
- (instancetype)init {
self = [super init];
if (self) {
self = [super init];
if (self) {
[self defaultSetting];
}
return self;
}
return self;
}
- (void)defaultSetting {
NSArray *sampleRates = @[@16000, @11025, @22050, @44100];
for (NSNumber *sampleRate in sampleRates) {
OSStatus status = [self prepareRecord:sampleRate.doubleValue];
if (status == noErr) {
self.sampleRate = [sampleRate doubleValue];
break;
}
}
}
- (OSStatus)prepareRecord:(double)sampleRate {
OSStatus status = noErr;
NSError *error;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionAllowBluetooth error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
#ifdef IGNORE
NSInteger inputChannels = session.inputNumberOfChannels;
if (!inputChannels) {
NSLog(@"ERROR: NO AUDIO INPUT DEVICE");
return -1;
}
#endif
if (!audioComponentInitialized) {
audioComponentInitialized = YES;
AudioComponentDescription audioComponentDescription;
audioComponentDescription.componentType = kAudioUnitType_Output;
audioComponentDescription.componentSubType = kAudioUnitSubType_RemoteIO;
audioComponentDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
audioComponentDescription.componentFlags = 0;
audioComponentDescription.componentFlagsMask = 0;
AudioComponent remoteIOComponent = AudioComponentFindNext(NULL,&audioComponentDescription);
status = AudioComponentInstanceNew(remoteIOComponent,&(self->audioUnit));
if (CheckError(status, "Couldn't get RemoteIO unit instance")) {
return status;
}
}
UInt32 oneFlag = 1;
AudioUnitElement bus0 = 0;
AudioUnitElement bus1 = 1;
if ((NO)) {
status = AudioUnitSetProperty (self->audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
bus0,
&oneFlag,
sizeof(oneFlag));
if (CheckError(status, "Couldn't enable RemoteIO output")) {
return status;
}
}
status = AudioUnitSetProperty(self->audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
bus1,
&oneFlag,
sizeof(oneFlag));
if (CheckError(status, "Couldn't enable RemoteIO input")) {
return status;
}
AudioStreamBasicDescription asbd;
memset(&asbd, 0, sizeof(asbd));
asbd.mSampleRate = sampleRate;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
asbd.mBytesPerPacket = 2;
asbd.mFramesPerPacket = 1;
asbd.mBytesPerFrame = 2;
asbd.mChannelsPerFrame = 2;
asbd.mBitsPerChannel = 16;
status = AudioUnitSetProperty(self->audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
bus0,
&asbd,