如何在WatchOS 3中播放将在手表扬声器上播放的自定义声音

时间:2016-09-03 02:26:23

标签: audio sprite-kit watch-os-3

我已经读过,我们现在可以在监视器3中的苹果手表上播放自定义声音。

根据Apple发布的声明显然有但我没有一个例子来测试它:使用SCNAudioSource或SCNAudioPlayer实现的3D空间音频。相反,使用playAudioSource:waitForCompletion:或WatchKit声音或触觉API。在此处找到:https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInwatchOS/Articles/watchOS3.html

有人可以举一个简单的例子。我没有在我的应用程序中使用SceneKit,因为我不需要它,但如果这是播放自定义声音的唯一方法,那么我想知道完成此操作所需的最少代码。最好是在目标c中,但我会把它带到任何形状。如果这也更容易,我可以使用SpriteKit。

这是我到目前为止所做的,但它不起作用:

SCNNode * audioNode = [[SCNNode alloc] init];

SCNAudioSource * audioSource = [SCNAudioSource audioSourceNamed:@"mysound.mp3"];
SCNAudioPlayer * audioPlayer = [SCNAudioPlayer audioPlayerWithSource:audioSource];  
[audioNode addAudioPlayer:audioPlayer];

SCNAction * play = [SCNAction playAudioSource:audioSource waitForCompletion:YES];
[audioNode runAction:play];

3 个答案:

答案 0 :(得分:6)

这是Objective-c但可以翻译成Swift

我最终使用AVAudioEngineAVAudioPlayerNode在Apple手表上播放音频。

如何做到这一点的要点如下:

我在我的AudioPlayer的init方法中调用以下内容(它是一个NSObject子类来封装功能)

_audioPlayer = [[AVAudioPlayerNode alloc] init];
_audioEngine = [[AVAudioEngine alloc] init];
[_audioEngine attachNode:_audioPlayer];

AVAudioFormat *stereoFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100 channels:2];
[_audioEngine connect:_audioPlayer to:_audioEngine.mainMixerNode format:stereoFormat];

if (!_audioEngine.isRunning) {
    NSError* error;
    [_audioEngine startAndReturnError:&error];
}

我有一个缓存设置,因此每次我想播放声音时都不会重新创建AVAudioFile资源但是你不需要。

接下来创建一个AVAudioFile对象:

NSError *error;
NSBundle* appBundle = [NSBundle mainBundle];
NSURL *url = [NSURL fileURLWithPath:[appBundle pathForResource:key ofType:@"aifc"]];
AVAudioFile *asset = [[AVAudioFile alloc] initForReading:url &error];

然后播放该文件:

[_audioPlayer scheduleFile:asset atTime:nil completionHandler:nil];
[_audioPlayer play];

更新:如果应用程序进入睡眠状态或被置于后台,则音频可能会停止播放/淡出。通过激活音频会话,这将被阻止。

    NSError *error;
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
    if (error) {
      NSLog(@"AVAudioSession setCategory ERROR: %@", error.localizedDescription);
    }
    [[AVAudioSession sharedInstance] setActive:YES error:&error];
    if (error) {
      NSLog(@"AVAudioSession setActive ERROR: %@", error.localizedDescription);
    }

我没有过去处理任何错误,但这应该有效。不要忘记在实施文件的顶部#import <AVFoundation/AVFoundation.h>

答案 1 :(得分:6)

我可以确认,@ ApperleyA解决方案确实有效!

这是swift版本:

var _audioPlayer : AVAudioPlayerNode!
var _audioEngine : AVAudioEngine!

func playAudio()
{
    if (_audioPlayer==nil) {
        _audioPlayer = AVAudioPlayerNode()
        _audioEngine = AVAudioEngine()
        _audioEngine.attach(_audioPlayer)

        let stereoFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 2)
        _audioEngine.connect(_audioPlayer, to: _audioEngine.mainMixerNode, format: stereoFormat)

        do {

            if !_audioEngine.isRunning {
                try _audioEngine.start()
            }

        } catch {}

    }


    if let path = Bundle.main.path(forResource: "test", ofType: "mp3") {

        let fileUrl = URL(fileURLWithPath: path)

        do {
            let asset = try AVAudioFile(forReading: fileUrl)

            _audioPlayer.scheduleFile(asset, at: nil, completionHandler: nil)
            _audioPlayer.play()

        } catch {
            print ("asset error")
        }

    }


}

答案 2 :(得分:0)

这在模拟器中对我有用

  let soundPath = Bundle.main.path(forResource: "cheerMP3", ofType: "mp3")
  let soundPathURL = URL(fileURLWithPath: soundPath!)
  let audioFile = WKAudioFileAsset(url: soundPathURL)
  let audioItem = WKAudioFilePlayerItem(asset: audioFile)

  let audioPlayer = WKAudioFilePlayer.init(playerItem: audioItem)

  if audioPlayer.status == .readyToPlay
  {
    audioPlayer.play()
  }
  else
  {
    print("Not ready!!")
  }

但是只有我在audioPlayer.play()和最后一个}之后都有断点。

dunqan,你在文件的顶部放了什么,import语句?我无法包括

导入AVFoundation

使用Xcode 8.2.1

时没有错误