AVAudioPlayerを使ったライブラリを作りました。AVAudioPlayerの実例が少なかったからしっかりとまとめた。AudioQueueとかAudioUnitじゃないとできないんじゃないの?ということがAVAudioPlayerでできます。
AudioPlayerDelegateをdelegateして使いたいクラスに取り込んであげてください。
/* AudioPlayer.h */
#import <Foundation/Foundation.h>
#include <AVFoundation/AVFoundation.h>
@protocol AudioPlayerDelegate
-(void) audioSequence:(double)currentTime;
-(void) audioFadein:(double)volume;
-(void) audioFadeout:(double)volume;
@optional
@end
@interface AudioPlayer : NSObject
<AVAudioPlayerDelegate>
{
NSTimer * timer;
NSTimer * timerFade;
AVAudioPlayer * audio;
float power, currentVolume;
double duration;
BOOL fading, pausing;
id<AudioPlayerDelegate> delegate;
}
@property (nonatomic, assign) id<AudioPlayerDelegate> delegate;
@property (nonatomic, retain) AVAudioPlayer * audio;
@property double duration;
@property float power;
@property float currentVolume;
-(id) initWithFilename:(NSString *)filename ofType:(NSString *)ofType delegate:(id)targetDelegate;
-(void)audioStart:(BOOL)fade currentTime:(double)currentTime volume:(float)volume;
-(void)audioStop:(BOOL)fade;
-(void)audioPause;
-(void)audioPlayThreaded:(id)threadAudio;
-(void)setVolume:(double)volume;
@end
/* AudioPlayer.m */
#import "AudioPlayer.h"
@implementation AudioPlayer
@synthesize delegate, duration, power, currentVolume, audio;
#define FEDE_SEED 0.01f
#define VOLUME_SEED 0.005f
#define SEQUENCE_INTERVAL 0.5f
#define AVEPW4CH 0
-(id) initWithFilename:(NSString *)filename ofType:(NSString *)ofType delegate:(id)targetDelegate{
NSString * path = [[NSBundle mainBundle] pathForResource:filename ofType:ofType];
NSURL * url = [NSURL fileURLWithPath:path];
audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audio setMeteringEnabled:YES];
audio.delegate = targetDelegate;
self.delegate = targetDelegate;
duration = audio.duration;
fading = NO;
currentVolume = 0.5f;
return self;
}
- (void)audioSequence{
if(audio == nil) return;
if(audio.playing){
[audio updateMeters];
power = [audio averagePowerForChannel:AVEPW4CH]; // averagePowerForChannel OR peakPowerForChannel
[self.delegate audioSequence:audio.currentTime];
}
}
-(void)audioStart:(BOOL)fade currentTime:(double)currentTime volume:(float)volume{
if(audio.playing) return;
currentVolume = volume;
if(fade){
if(fading == NO){
[audio setVolume:0.0f];
timerFade = [NSTimer scheduledTimerWithTimeInterval:FEDE_SEED target:self selector:@selector(audioFadein) userInfo:nil repeats:YES];
}
}
audio.currentTime = currentTime;
[NSThread detachNewThreadSelector:@selector(audioPlayThreaded:) toTarget:self withObject:audio];
timer = [NSTimer scheduledTimerWithTimeInterval:SEQUENCE_INTERVAL target:self selector:@selector(audioSequence) userInfo:nil repeats:YES];
}
-(void)audioStop:(BOOL)fade{
if(audio == nil) return;
if(fade){
if(fading == NO) timerFade = [NSTimer scheduledTimerWithTimeInterval:FEDE_SEED target:self selector:@selector(audioFadeout) userInfo:nil repeats:YES];
} else {
if(audio.playing){
[audio prepareToPlay];
[audio stop];
[audio setCurrentTime:0.0f];
}
}
}
-(void)audioPause{
if(audio == nil) return;
if(audio.playing){
[audio pause];
}
}
-(void)audioFadein{
if(audio.playing){
if((audio.volume+VOLUME_SEED) < currentVolume){
fading = YES;
[self.delegate audioFadein:audio.volume];
[audio setVolume:audio.volume+VOLUME_SEED];
} else {
fading = NO;
if([timerFade isValid]) [timerFade invalidate];
}
}
}
-(void)audioFadeout{
if(audio.volume <= 0.0f){
fading = NO;
if([timerFade isValid]) [timerFade invalidate];
[self audioStop:NO];
} else {
fading = YES;
[self.delegate audioFadeout:audio.volume];
[audio setVolume:audio.volume-VOLUME_SEED];
}
}
-(void)audioPlayThreaded:(id)threadAudio{
if(threadAudio == nil) return;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[(AVAudioPlayer *)threadAudio prepareToPlay];
[(AVAudioPlayer *)threadAudio play];
[pool release];
}
-(void)setVolume:(double)volume{
[audio setVolume:volume];
}
@end
使い方は簡単。
-(void) main{
ap = [[AudioPlayer alloc]initWithFilename:@"filename" ofType:@"mp3" delegate:self];
[ap audioStart:YES currentTime:0.0f volume:0.5f]; // フェードで始まる。
[ap audioStop:YES]; // フェードで終わる
}
-(void)audioSequence:(double)currentTime{
// 再生中の処理
NSLog(@"%f", currentTime); // 現在時間
NSLog(@"%f", ap.power); // デシベル数 averagePowerForChannelで設定してある
}
// フェードイン中
-(void)audioFadein:(double)volume{
NSLog(@"fadein = %f", volume);
}
// フェードアウト中
-(void)audioFadeout:(double)volume{
NSLog(@"fadeout = %f", volume);
}