March 10, 2009

Playing looping audio files

Posted in Uncategorized tagged , , , , , , , , , at 3:48 pm by tetontech

QuickConnectiPhone 1.5 Beta 3 is going to include the playing of audio files using the new AVAudioPlayer made available in recent releases of the iPhone OS.  This will allow easy looping and greatly reduce the amount of code required in the QCiPhone framework.  All good.  I am including in this post the code that will be in Beta 3 so that those of you using 1.1.3 can put the code in the applications you are creating.

The code can also be used as an example of how to use the AVAudioPlayer Objective-C class.

Be aware that looping compressed files such as mp3’s will leave a ‘plop’ or gap in playing between loops.  If you want to avoid this you can use uncompressed files such as wav files or follow the advice onthis page.

The changes to com.js.  Replace the record, stopRecording, play, and stopPlaying functions with the following code.

function record(aFileName){

if(aFileName){

var params = new Array();

if(aFileName.indexOf(‘.’) == –1){

aFileName = aFileName+“.caf”;

}

params[0] = aFileName;

params[1] = “start”;

makeCall(“rec”, JSON.stringify(params));

}

}

function stopRecording(aFileName){

if(aFileName){

var params = new Array();

if(aFileName.indexOf(‘.’) == –1){

aFileName = aFileName+“.caf”;

}

params[0] = aFileName;

params[1] = “stop”;

makeCall(“rec”, JSON.stringify(params));

}

}

//set loop count to a number of loops or -1 for continuous looping

function play(aFileName, loopCount){

if(aFileName){

var params = new Array();

if(aFileName.indexOf(‘.’) == –1){

aFileName = aFileName+“.caf”;

}

params[0] = aFileName;

params[1] = “start”;

params[2] = 0;

if(loopCount){

params[2] = loopCount;

}

makeCall(“play”, JSON.stringify(params));

}

}

/*

* Pause is removed for now since the standard apple Objective-C

*  class fails to play an audio file that is paused.

*

function pausePlaying(aFileName){

if(aFileName){

var params = new Array();

if(aFileName.indexOf(‘.’) == -1){

aFileName = aFileName+”.caf”;

}

params[0] = aFileName;

params[1] = “pause”;

makeCall(“play”, JSON.stringify(params));

}

}

*/

function stopPlaying(aFileName){

if(aFileName){

var params = new Array();

if(aFileName.indexOf(‘.’) == –1){

aFileName = aFileName+“.caf”;

}

params[0] = aFileName;

params[1] = “stop”;

makeCall(“play”, JSON.stringify(params));

}

}

Replace the code in the Classes->CommandObjects->PlayAudioVCO.m Objective-C file with the following
//

//  PlayAudioVCO.m

//

/*

Copyright 2009 Lee S. Barney

This file is part of QuickConnectiPhone.

QuickConnectiPhone is free software: you can redistribute it and/or modify

it under the terms of the GNU Lesser General Public License as published by

the Free Software Foundation, either version 3 of the License, or

(at your option) any later version.

QuickConnectiPhone is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License

along with QuickConnectiPhone.  If not, see <http://www.gnu.org/licenses/>.

*/

#import <AVFoundation/AVFoundation.h>

#import “PlayAudioVCO.h”

#import “QuickConnectViewController.h”

@implementation PlayAudioVCO

+ (id) doCommand:(NSArray*) parameters{

NSString *flag = [parameters objectAtIndex:2];

QuickConnectViewController *aController = [parameters objectAtIndex:0];

if([flag compare:@”start”] == NSOrderedSame){

NSString *fileName = [parameters objectAtIndex:1];

NSArray *split = [fileName componentsSeparatedByString:@”.”];

NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:[split objectAtIndex:0] ofType:[split objectAtIndex:1]];

if(audioFilePath == nil){

//recorded file.

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

audioFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];

}

AVAudioPlayer *audioPlayer =  [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:audioFilePath] error:NULL];

aController.audioPlayer = audioPlayer;

[audioPlayer release];

aController.audioPlayer.numberOfLoops = [parameters objectAtIndex:3];

[audioPlayer prepareToPlay];

BOOL plays = [audioPlayer play];

if(plays){

MESSAGE(@”done playing”);

}

else{

MESSAGE(@”play failed”);

}

}

else if([flag compare:@”pause”] == NSOrderedSame){

MESSAGE(@”pausing”);

[aController.audioPlayer pause];

}

else{

[aController.audioPlayer stop];

}

MESSAGE(@”done with PlayAudioVCO”);

return nil;

}

@end


Advertisements

1 Comment »

  1. bob said,

    if([flag compare:@”start”] == NSOrderedSame)
    should be written as
    if([flag isEqualToString:@”start”])


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: