I need to make clap recognition on iPhone.
I know an algorithm how to make it analyzing amplitude-from-time audio signal. But it's not clear for me now how to get such a representation of audio signal from microphone.
Now I only know how to write audio files from microphone:
recorder.h
recorder.m
I have an idea to replace AudioFileWritePackets in callback AudioInputCallback. And that inBuffer->mAudioDataByteSize bites from pointer inBuffer->mAudioData will be amplitude-time signal representation... But I do not know how to decode that memory area: looks like I need to work with a pairs of bites (mBytesPerPacket = 2). May I represent them as one of "standart" types (like int)? Is it signed or not?
I know an algorithm how to make it analyzing amplitude-from-time audio signal. But it's not clear for me now how to get such a representation of audio signal from microphone.
Now I only know how to write audio files from microphone:
recorder.h
Code:
#import <Cocoa/Cocoa.h>
#import <AudioToolbox/AudioQueue.h>
#import <AudioToolbox/AudioFile.h>
#define NUM_BUFFERS 10
typedef struct {
AudioFileID audioFile;
AudioStreamBasicDescription dataFormat;
AudioQueueRef queue;
AudioQueueBufferRef buffers[NUM_BUFFERS];
UInt32 bufferByteSize;
SInt64 currentPacket;
BOOL recording;
} RecordState;
@interface recorder : NSObject {
@private
BOOL recording;
RecordState recordState;
}
@property(nonatomic, assign) BOOL recording;
- (void)start;
- (void)stop;
@end
recorder.m
Code:
#import "recorder.h"
@implementation recorder
-(void)setRecording:(BOOL)val {
if(val)
[self start];
else
[self stop];
}
-(BOOL)recording {
return self->recording;
}
- (id)init {
if (self = [super init]) {
recording = NO;
recordState.dataFormat.mSampleRate = 8000.0;
recordState.dataFormat.mFormatID = kAudioFormatLinearPCM;
recordState.dataFormat.mFramesPerPacket = 1;
recordState.dataFormat.mChannelsPerFrame = 1;
recordState.dataFormat.mBytesPerFrame = 2;
recordState.dataFormat.mBytesPerPacket = 2;
recordState.dataFormat.mBitsPerChannel = 16;
recordState.dataFormat.mReserved = 0;
recordState.dataFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
}
return self;
}
- (void)dealloc {
[super dealloc];
}
void AudioInputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs) {
RecordState *recordState = (RecordState *)inUserData;
OSStatus status = AudioFileWritePackets(recordState->audioFile, false, inBuffer->mAudioDataByteSize, inPacketDescs, recordState->currentPacket, &inNumberPacketDescriptions, inBuffer->mAudioData);
if(status == 0)
recordState->currentPacket += inNumberPacketDescriptions;
AudioQueueEnqueueBuffer(recordState->queue, inBuffer, 0, NULL);
}
- (void)start {
if(!recording) {
self->recording = YES;
recordState.currentPacket = 0;
OSStatus status = AudioQueueNewInput(&recordState.dataFormat, AudioInputCallback, &recordState, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &recordState.queue);
if(status == 0) {
for(int i = 0; i < NUM_BUFFERS; i++) {
AudioQueueAllocateBuffer(recordState.queue, 16000, &recordState.buffers[i]);
AudioQueueEnqueueBuffer(recordState.queue, recordState.buffers[i], 0, NULL);
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:@"audio.aiff"];
NSLog(writablePath);
CFURLRef fileURL = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *) [writablePath UTF8String], [writablePath length], NO);
status = AudioFileCreateWithURL(fileURL, kAudioFileAIFFType, &recordState.dataFormat, kAudioFileFlags_EraseFile, &recordState.audioFile);
if(status == 0)
status = AudioQueueStart(recordState.queue, NULL);
}
if(status != 0)
NSLog(@"Recording Failed!");
}
}
- (void)stop {
if(recording) {
self->recording = NO;
NSLog(@"Stopping queue...");
AudioQueueStop(recordState.queue, true);
NSLog(@"Queue stopped");
for(int i = 0; i < NUM_BUFFERS; i++)
AudioQueueFreeBuffer(recordState.queue, recordState.buffers[i]);
AudioQueueDispose(recordState.queue, true);
AudioFileClose(recordState.audioFile);
NSLog(@"Audio file closed");
}
}
@end
I have an idea to replace AudioFileWritePackets in callback AudioInputCallback. And that inBuffer->mAudioDataByteSize bites from pointer inBuffer->mAudioData will be amplitude-time signal representation... But I do not know how to decode that memory area: looks like I need to work with a pairs of bites (mBytesPerPacket = 2). May I represent them as one of "standart" types (like int)? Is it signed or not?