如何在按下按钮时播放音频并在我的手指离开同一个按钮时立即停止?

Posted

技术标签:

【中文标题】如何在按下按钮时播放音频并在我的手指离开同一个按钮时立即停止?【英文标题】:How can I make audio play when the button is pressed and immediately stop when I take my finger off the same button? 【发布时间】:2014-02-08 06:51:44 【问题描述】:

我当前的按钮代码是。

-(IBAction)playsnare;    

    CFBundleRef mainBundle = CFBundleGetMainBundle();
    CFURLRef soundfileURLRef;
    soundfileURLRef =CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"snare", CFSTR ("wav"), NULL);
    UInt32 SoundID;
    AudioservicesCreateSystemSoundID(soundfileURLRef, &SoundID);
    AudioServicesPlaySystemSound(SoundID);

我可以添加什么以使按钮在按下时播放并在未按下时停止。

【问题讨论】:

手指离开按钮时要停止声音吗?嗯……我从没听说过这个壮举。 适用于鼓垫之类的应用程序。您将在按钮上附加一个循环,但是当您松开按钮时,循环将停止。 我没做过,但是你可能想通过子类化 UIButton 来尝试一下。 【参考方案1】:

您播放音频样本的实现不允许这样做。因为您使用的是 AudioToolbox 框架中的 AudioServicesPlaySystemSound,所以一旦触发音频样本,就无法停止播放。您只能在播放完毕后获得回调。

这种播放声音的方式也有其他限制(取自文档)

另外,当你使用AudioServicesPlaySystemSound函数时:

声音以当前系统音量播放,没有程序化 音量控制可用

声音立即播放

循环和立体定位不可用

无法同时播放:一次只能播放一个声音 时间

声音在设备扬声器上本地播放;它不使用 音频路由。

要控制一旦触发就停止声音,您需要使用另一个 API。对于高级 API,请尝试 AVFoundation 框架中的 AVAudioPlayer 类。然后,您将能够从诸如touch down 之类的按钮连接事件以开始播放声音,也可以连接诸如touch up insidetouch drag outside 之类的事件以停止声音播放。

您可能会也可能不会遇到性能问题,具体取决于您正在执行的其他操作。为了获得更好的性能(和更多的代码编写AudioUnits将是首选。

使用 AVAudioPlayer 类的简短示例如下-

以下代码假设有一个 AVAudioPlayer 类型的属性,名为 loopPlayer 在 UIViewController 子类中使用名为 some_audio_loop_file.wav 的文件进行初始化。

yourViewController.h

@property (nonatomic, strong) AVAudioPlayer *loopPlayer;

yourViewController.m

// set up loopPlayer property in for example viewDidLoad
NSURL* audioFileURL = [[NSBundle mainBundle] URLForResource:@"some_audio_loop_file" withExtension:@"wav"];
self.loopPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil];

// called from a UIButton touch down event
-(IBAction)startAudioSample:(id)sender 
     [self.loopPlayer play];


// called from a UIButton touch up inside and touch drag outside events
-(IBAction)stopAudioSample:(id)sender 
     if (self.loopPlayer.isPlaying) 
          [self.loopPlayer stop];
          self.loopPlayer.currentTime = 0;
          self.loopPlayer.numberOfLoops = -1;
          [self.loopPlayer prepareToPlay];

【讨论】:

我知道这似乎是一个愚蠢的问题,但是您会在哪里将声音文件的名称和文件类型添加到该代码中? 请看我的编辑。我添加了使用文件设置 AVAudioPlayer 的代码。 我添加了所有代码,它基本上可以满足我的要求,谢谢!但是,每次按下按钮时,有没有办法将音频样本重置回开头?目前每次我按下它都会从它停止的地方开始。 停止播放器不会重置播放头。为此,请将 currentTime 属性设置为 0。我将在我的答案中更新 stopAudioSample: 方法。 欢迎您。我建议阅读 AVAudioPlayer 类参考并查看 AVAudioPlayerDelegate 协议参考以获取更多信息。【参考方案2】:

试试:

-(IBAction)longPress:(UILongPressGestureRecognizer*)playsnare;    

CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundfileURLRef;
soundfileURLRef =CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"snare", CFSTR ("wav"), NULL);
UInt32 SoundID;
AudioServicesCreateSystemSoundID(soundfileURLRef, &SoundID);
AudioServicesPlaySystemSound(SoundID);

UILongPressGestureRecognizer 是一个连续事件识别器。您必须查看状态以查看这是事件的开始、中间还是结束,并采取相应的行动。即,您可以在开始后排除所有事件,或者仅根据需要查看运动。来自类参考:

长按手势是连续的。当允许的手指数量 (numberOfTouchesRequired) 在指定的时间 (minimumPressDuration) 内被按下并且触摸没有超出允许的移动范围 (allowableMovement) 时,手势开始 (UIGestureRecognizerStateBegan)。每当手指移动时,手势识别器就会转换到 Change 状态,并在任何手指抬起时结束 (UIGestureRecognizerStateEnded)。

现在您可以像这样跟踪状态

-  (void)handleLongPress:(UILongPressGestureRecognizer*)sender  
        if (sender.state == UIGestureRecognizerStateEnded) 
           NSLog(@"UIGestureRecognizerStateEnded");
           //Do Whatever You want on End of Gesture
        
       else if (sender.state == UIGestureRecognizerStateBegan)
           NSLog(@"UIGestureRecognizerStateBegan.");
          //Do Whatever You want on Began of Gesture
        
  

详情来自:https://***.com/a/3320351/1255945

【讨论】:

我有点困惑,因为我对 Xcode 还很陌生。我应该用长按做什么:显示在收到的操作下?我还应该在反斜杠下添加代码以使音频停止和播放吗?【参考方案3】:

创建属性

bool isPlaying

然后就像在您的 IBAction 函数中一样

if(isPlaying)
  stop();
else
 play();

【讨论】:

以上是关于如何在按下按钮时播放音频并在我的手指离开同一个按钮时立即停止?的主要内容,如果未能解决你的问题,请参考以下文章

如何基于VB中文本框的内容播放一系列音频文件?

Android:如何在按下按钮时关闭一个活动并在按下另一个按钮时关闭整个后台堆栈? [复制]

如何在按下按钮后每 10 分钟重复一次方法并在按下另一个按钮时结束它

在swiftui中按钮的触摸动作播放音频

应用播放背景音频不起作用

按下后退按钮时音频停止播放