Recorded voice notes slows the application - iphone

In my iPhone application, i am recording voice of user and saving it in device.
My setting of AVAudioRecorder is as follows:
NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:16000.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute,
sizeof(audioRouteOverride), &audioRouteOverride);
If I save more voices,the application gets slower and slower.I have kept Sample rate low to solve the purpose but even that not woked.What should I do?

I minimized the sample rate to 8000 which hammered the clarity of voice a bit but it solved my purpose.Hope this may help any other person having similar problem :)

Related

How to Recognise voice using AVAudioRecorder in iphone

I am using AVAudioRecorder .if I tap on record button,The recording should start/save only after recognising the voice.
- (void)viewDidLoad
{
recording = NO;
NSString * filePath = [NSHomeDirectory()
stringByAppendingPathComponent:#"Documents/recording.caf"];
NSDictionary *recordSettings =
[[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0],AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless],
AVFormatIDKey,
[NSNumber numberWithInt: 1],
AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax],
AVEncoderAudioQualityKey,nil];
AVAudioRecorder *newRecorder = [[AVAudioRecorder alloc]
initWithURL: [NSURL fileURLWithPath:filePath]
settings: recordSettings
error: nil];
[recordSettings release];
self.soundRecorder = newRecorder;
[newRecorder release];
self.soundRecorder.delegate = self;
NSLog(#"path is %#",filePath);
[super viewDidLoad];
}
- (IBAction) record:(id) sender {
if (recording) {
[self.soundRecorder stop];
[recordBtn setTitle:#"Record" forState:UIControlStateNormal];
recording = NO;
} else {
[self.soundRecorder record];
[recordBtn setTitle:#"Stop" forState:UIControlStateNormal];
recording = YES;
}
}
- (IBAction) play {
NSString * filePath = [NSHomeDirectory()
stringByAppendingPathComponent:#"Documents/recording.caf"];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: [NSURL fileURLWithPath:filePath] error: nil];
newPlayer.delegate = self;
NSLog(#"playing file at url %# %d",[[newPlayer url] description],[newPlayer play]);
}
Please Help me out.
That's a challenging goal you have. iOS doesn't include the smarts to recognize voice specifically, you will have to provide a filter or your own to do that. If you just want VOX type support (i.e. start recording when a given level of audio is detected) it is easily done by monitoring audio levels using the Audio Toolbox Framework.
If you need to recognize voice specifically you will need a specialized recognition filter to run your audio data through.
If you had such a filter you could take one of two approaches: a) Just record everything then post-process the resulting audio data to locate the time index at which voice is recognized and just ignore the data up to that point (copy the remaining data to another buffer perhaps) or b) use the Audio Toolbox Framework to monitor the recorded data in real time. Pass the data through your voice finding filter and only start buffering the data when your filter triggers.
Actual implementation is quite involved and too long to address here, but I have seen sample code in books and online that you could start from. I'm sorry I don't have any links to share at this time but will post any I come across in the near future.
I think this might help you with this. I think detecting a volume spike is all you need for your purposes, right?
http://mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/
Pier.

Implement a noise filter algorithm for recorded audio in iPhone

I am developing an application like TomCat. I have recorded audio with a funny voice and playing it with Audio Queue Services. I have changed the settings of AVAudioRecorder, But while i am playing there is some noise or distortions.
NSMutableDictionary *settings = [[NSMutableDictionary alloc] init];
[settings setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[settings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[settings setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
[settings setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[settings setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[settings setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
self.recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:self.audioPath] settings:settings error:nil];
self.recorder = [self.recorder retain];
[self.recorder prepareToRecord];
[self.recorder record];
I know how to covert the decibels to amplitude, or use LowPassFilter Blocks if the frequencies are too high. The HighPassFilter blocks if the frequencies are too low. How do I implement this in Objective-C?
//convert decibels to amp
const double ALPHA = 0.05;
double peakPowerForChannel = pow(10, (0.05 * [audioMonitor peakPowerForChannel:0]));
double audioMonitorResults;
audioMonitorResults= ALPHA * peakPowerForChannel + (1.0 - ALPHA) *audioMonitorResults;
Your question is not clear. In case you are looking to ensure you adhere to the Nyquist sampling criteria, your filter needs to be implemented BEFORE the ADC i.e., in hardware if your sampling frequency is close to the spectrum you intend to record.
If you do have an appropriate LPF and still hear funny noises, I suggest to you that your input audio levels are too high. This is again a hardware issue; bring down your input volume.
Another source of noise might be that your record does not really consists of one continuous sample block without interruptions. Alternatively, this could be a playback issue also.
Lots of things can go wrong that lead to "noise or distortions"...

AVAudioRecorder meter delay on iPad

I am having trouble getting an accurate meter reading from the AVAudioRecorder (testing on iPad).
It seems to work fine while the volume is rising, however a delay happens when the volume drops. For example: I speak into the mic and slowly raise my voice. The readings increment from -35.567 to -34.678 up to -10.579 as I would hope, but when I stop talking there is a delay of 1 - 2 seconds before it drops back down to -35.567 (or whatever it happens to be).
The NSLog continues to update from the loop but the meter number stays the same during the delay even though the sound has long ended.
I have added the gist of the code below and would be happy to supply full code if need be.
I initialize the recorder like so:
AVAudioSession * audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: &error];
[audioSession setActive:YES error: &error];
NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
recordedTmpFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithString: #"Recording.caf"]]];
recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:&error];
[recorder setDelegate:self];
[recorder prepareToRecord];
[recorder setMeteringEnabled:YES];
[recorder record];
and update the meter in a loop:
-(void) loop:(ccTime)dt
{
if(isRecording == YES)
{
//get volume levels
[recorder updateMeters];
float level = [recorder peakPowerForChannel:0];
NSLog(#"Vol: %f", level);
}
}
edited: I should also mention that I am using the Cocos2d schedule for the loop:
[self schedule:#selector(loop:)];
Any ideas why there would be such a long delay?
edited: I have tried using the average peak power and this has no delay. So I could possibly use that as a work around. However I would rather not use and averaged peak power and it would be nice to understand what is going on.
I'm sure that most have figured this out but if you want less lag on your metering you need to use AudioQueue or RemoteIO. See the better explanation here:
Confusion with meters in AVAudioRecorder
You can fix this by resetting the meteringEnabled property to YES.
yourRecorderName.meteringEnabled = YES
Call this every time you want the levels to reset to ambient levels. This takes about 0.02 seconds, and in that time the levels will briefly drop down to 0, or -120 dB before resetting to ambient.
Alternatively, you can use:
[yourRecorderName stop]
[yourRecorderName record]
This takes about 0.05 seconds, but the levels won't drop down to 0 in the wait time. In fact, nothing will happen because in this case, it actually takes the recorder object 0.05 seconds to stop and start recording again.
How about using a timer ? it would be mutch quicker
after
NSError* error
if (recorder) {
recorder.meteringEnabled = YES;
[recorder record];
levelTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 target: self selector: #selector(levelTimerCallback:) userInfo: nil repeats: YES];
} else
NSLog(#" error %#",[error description]);
}
Where levelTimer is the NStimer that calls the function that does what you want(levelTimerCallback:), updates the meters, etc.
-(IBAction)levelTimerCallback:(NSTimer*)timer
{
[recorder updateMeters];
float level = [recorder peakPowerForChannel:0];
NSLog(#"Vol: %f", level);
}

avaudiorecorder distorts sound when played after recording

i have used an avaudiorecoder to record user's voice. it records it but when i play it the sound is crackled. any help regarding this will be appreciated..... following the code of my recorder's settings..
NSDictionary *recordSetting =[[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:kAudioFormatAppleIMA4],AVFormatIDKey,
[NSNumber numberWithInt:16000.0],AVSampleRateKey,
[NSNumber numberWithInt: 1],AVNumberOfChannelsKey,
[NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithInt:AVAudioQualityMax],AVEncoderAudioQualityKey,
nil];
Why do you use a sample rate of 16000 Hz? Could it be noisy because the sample rate is not fast enough? When using PCM the usual sample rate is 44100 Hz.
Maybe this other post helps you:
How do I record audio on iPhone with AVAudioRecorder?

Detect a blow into the microphone

For a project of mine I need to detect when the user blows into the mic. I've following this tutorial: http://www.mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/ and this question: Detect blow in Mic and do something
But still I do not get the results I want. The blow is detected way too late, or sometimes not at all. When I tweak some results the blow is detected correctly, but then the blow is triggered too fast, ie. when you talk or make a clicking sound it is detected as a blow too.
Has anyone found a good way of detecting a blow? Thanks.
The AVAudioRecorder sound level API is not designed to give you reliable results in separating blowing sounds from other types of sounds received by the mic.
I suggest using the Audio Queue or the Audio Unit RemoteIO API, measuring RMS signal energy, envelope duration, and then using the Accelerate FFT library to check the spectrum for broadband noise vs. peaks that would suggest voiced talking instead of blowing.
e.g. a more reliable result will require a lot more work than 1 OS call.
Use return as you get first lowpass results >0.55
I have solve the issue have a look.
-(void)readyToBlow1 { NSURL *url = [NSURL fileURLWithPath:#"/dev/null"];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey,
nil];
NSError *error;
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if (recorder) {
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
[recorder record];
levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: #selector(levelTimerCallback1:) userInfo: nil repeats: YES];
} else
NSLog(#"%#",[error description]);
}
(void)levelTimerCallback1:(NSTimer *)timer { [recorder updateMeters];
const double ALPHA = 0.05; double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0])); lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; //NSLog(#"lowPassResults= %f",lowPassResults);
if (lowPassResults > 0.55) { lowPassResults = 0.0;
[self invalidateTimers];
NextPhase *objNextView =[[NextPhase alloc]init];
[UIView transitionFromView:self.view
toView:objNextView.view
duration:2.0
options:UIViewAnimationOptionTransitionCurlUp
completion:^(BOOL finished) {
}
];
[self.navigationController pushViewController:objNextView animated:NO];
**return;**
}
}
I've had good success using AudioQueueGetProperty() for the kAudioQueueProperty_CurrentLevelMeter.