4

我听说我们现在可以在 watchos 3 的 Apple Watch 上播放自定义声音。

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

有人可以举一个简单的例子。我没有在我的应用程序中使用 SceneKit,因为我不需要它,但如果这是播放自定义声音的唯一方法,那么我想知道完成此操作所需的最少代码。最好在Objective 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];
4

3 回答 3

7

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

这是快速版本:

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")
        }

    }


}
于 2016-11-16T15:30:37.640 回答
6

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

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

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

我在我的 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>在你的实现文件的顶部。

于 2016-10-04T18:40:05.000 回答
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,你在文件顶部放了什么导入语句?我无法包括

导入 AVFoundation

使用 Xcode 8.2.1 没有错误

于 2016-12-22T17:55:01.683 回答