[英]How do you make the iphone acceleromator trigger sound more effectively using avaudioplayer?
I have created a simple app that triggers 3 different sounds based on the x, y, z axis of the accelorometer, like an instrument. 我创建了一个简单的应用程序,它可以基于加速度计的x,y,z轴触发3种不同的声音,就像乐器一样。 At the moment, if I set the frequency update interval of the accelometer too low, it plays the sound to much, and if I set it too high it it isn't responsive enough.
此刻,如果我将加速度计的频率更新间隔设置得太低,它会播放太多声音,而如果将它设置得太高,则它的响应速度不够。 I am a complete beginner to objective c and iphone development, can you tell by the code!..
我是目标c和iphone开发的一个完整的初学者,您可以通过代码看出来!..
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional
UIAccelerometer* accelerometer = [UIAccelerometer sharedAccelerometer];
[accelerometer setUpdateInterval: 25.0 / 10.0f];
[[AVAudioSession sharedInstance] setDelegate: self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
[accelerometer setDelegate:self];
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
player.volume = 0.5;
player.numberOfLoops = 0;
player.delegate = self;
}
- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler
{
if (aceler.x > 0.5) {
NSString *fileName = [NSString stringWithFormat:@"snare"];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
NSLog(@"acceleration.x = %+.6f greater", aceler.x);
[player play];
}
else if (aceler.y > 0.5) {
NSString *fileName = [NSString stringWithFormat:@"kick2"];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
NSLog(@"acceleration.y = %+.6f greater", aceler.y);
[player play];
}
else if (aceler.z > 0.5) {
NSString *fileName = [NSString stringWithFormat:@"hat"];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
NSLog(@"acceleration.y = %+.6f greater", aceler.z);
[player play];
}
else {
[player stop];
};
}
Setting the accelerometer's update frequency to a low value wont help here. 将加速度计的更新频率设置为较低值在这里无济于事。 Imagine the following situation:
想象一下以下情况:
time: ------------------------>
real world acceleration event: ___X_____X_____X_____X___
acceleration update: X_____X_____X_____X_____X
sound output started: _________________________
This draft represents a user shaking the device with the same frequency as the accelerometer is updated. 该草稿代表用户以与加速度计更新相同的频率摇动设备。 But the shake event occurs just in the middle between two accelerometer updates.
但是抖动事件仅发生在两次加速度计更新之间的中间。 As a result, the shake events won't be registered and no sound is played.
结果,摇动事件将不会被记录,并且不会播放声音。
Consider a high accelerometer update frequency in contrast to the prior approach: 与以前的方法相比,请考虑较高的加速度计更新频率:
real world acceleration event: ___X_____X_____X_____X___
acceleration update: XXXXXXXXXXXXXXXXXXXXXXXXX
sound output started: ___X_____X_____X_____X___
Basically all real world events result in a sound play within this situation. 基本上所有现实世界的事件都会在这种情况下产生声音。
The amended code is the following: 修改后的代码如下:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"viewDidLoad");
UIAccelerometer* accelerometer = [UIAccelerometer sharedAccelerometer];
//[accelerometer setUpdateInterval: 25.0 / 10.0f];
[accelerometer setUpdateInterval: 0.01f];
[[AVAudioSession sharedInstance] setDelegate: self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
[accelerometer setDelegate:self];
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
//player.volume = 0.5;
//player.numberOfLoops = 0;
//player.delegate = self;
}
- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler
{
if ((aceler.x > ACC_THRESHOLD)&&((playerX == nil)||(playerX.isPlaying == NO))) {
NSString *fileName = [NSString stringWithFormat:@"snare"];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
playerX = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
NSLog(@"acceleration.x = %+.6f greater", aceler.x);
playerX.delegate = self;
[playerX play];
}
if ((aceler.y > ACC_THRESHOLD)&&((playerY == nil)||(playerY.isPlaying == NO))) {
NSString *fileName = [NSString stringWithFormat:@"kick2"];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
playerY = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
NSLog(@"acceleration.y = %+.6f greater", aceler.y);
playerY.delegate = self;
[playerY play];
}
if ((aceler.z > ACC_THRESHOLD)&&((playerZ== nil)||(playerZ.isPlaying == NO))) {
NSString *fileName = [NSString stringWithFormat:@"hat"];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
playerZ = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
NSLog(@"acceleration.z = %+.6f greater", aceler.z);
playerZ.delegate = self;
[playerZ play];
}
//else {
// [player stop];
//};
}
Please note, that multiple sound plays may be triggered by just one event as each dimension is evaluated separately now. 请注意,一个声音事件可能会触发一个声音事件,因为每个维度现在都需要分别评估。 A constant has been introduced by
#define ACC_THRESHOLD 0.5f
. #define ACC_THRESHOLD 0.5f
引入了一个常量。 A new sound play for one dimension is started only, after a previous play finished. 仅在上一个播放结束后才开始一个维度的新声音播放。
After these general change of event handling you may start optimizations with a signal filter . 在事件处理的这些常规更改之后,您可以使用信号过滤器开始优化。
Additionally you may use AVAudioPlayer's delegate methods for more detailed sound handling: 另外,您可以使用AVAudioPlayer的委托方法进行更详细的声音处理:
#pragma mark -
#pragma mark AVAudioPlayerDelegate methods
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
NSLog(@"audioPlayerDidFinishPlaying: %i", flag);
}
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{
NSLog(@"audioPlayerDecodeErrorDidOccur: %@", error.description);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.