swift3 効果音 引っかかり?
受付中
回答 1
投稿
- 評価
- クリップ 0
- VIEW 1,286
iPadのアプリを制作しています。
ドラッグで移動するViewのy座標に合わせて効果音を1回だけ再生したいです。
yが150のときに「雨の音」
yが300のときは「風の音」など
一応出来たんですが・・
効果音が再生されるときにドラッグに引っかかりが出るというか
再生待ち?になるのか、一瞬(というか再生開始まで)止まってしまい
スムーズに動きません。
再生後はまたスムーズに動くという感じになります。
初回の効果音が特にそうなります。
Xcodeのシミュレーターでは問題無く動くのですが
実機テストでは上記のようになりました。
上手く伝わらないかも知れずで恐縮です、、、
以下、コードです。
ちなみに試してみた事として
効果音を用意したときに
ボリューム0で先に再生しておくと多少マシにはなるようではあるのですが、、
完全に無くなるという事でも無いようです
何か重くなるコードを書いてをしてしまっているんでしょうか。
よろしくお願い致します。
OSX 10.11.6
Xcode 8.2.1
Swift 3
テスト実機 iPad Air2 MNV72J/A iOS10.2
import UIKit
import AVFoundation
class ViewController: UIViewController {
//ドラッグ用のView
var my:UIView = UIView()
//雨の音
var rain:AVAudioPlayer! = nil
//雨の音監視用
var rainPlay:Bool = true
//風の音
var wind:AVAudioPlayer! = nil
//風の音監視用
var windPlay:Bool = true
//ドラッグのy座標監視 タイマーにて
var timer:Timer!
override func viewDidLoad() {
super.viewDidLoad()
//View設置
my.frame = CGRect(x:100, y:100, width:200, height:200)
my.backgroundColor = UIColor.gray
self.view.addSubview(my)
//効果音用意(雨の音)
var url = NSURL.fileURL(withPath: Bundle.main.path(forResource: "rain", ofType: "mp3")!)
do{
rain = try AVAudioPlayer(contentsOf: url)
}catch{
print("no rain")
}
rain.prepareToPlay()
//先にボリューム0で再生してみたテストです
//rain.volume = 0
//rain.play()
//先再生したテストでは多少はましになります。
//効果音用意(風の音)
url = NSURL.fileURL(withPath: Bundle.main.path(forResource: "wind", ofType: "mp3")!)
do{
wind = try AVAudioPlayer(contentsOf: url)
}catch{
print("no wind")
}
wind.prepareToPlay()
}
//ドラッグはtouchMovedで
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let e = touches.first!
let dx = e.location(in:self.view).x - e.previousLocation(in:self.view).x
let dy = e.location(in:self.view).y - e.previousLocation(in:self.view).y
my.frame.origin.x += dx
my.frame.origin.y += dy
}
//座標監視はas3で云うenterFrame的なそれで
func enterFrame(){
let y = my.frame.origin.y
//最初の効果音(雨の音)
//ここでドラッグが効果音に引っかる?ように一旦止まり、効果音再生後にはまたスムーズにドラッグ操作が出来きます
if(y > 150){
if(rainPlay){
rainPlay = false
//先再生テスト用
//rain.volume = 1
rain.play()
}
}else{rainPlay = true}
//2番目の効果音(風の音)
//初回ほどでは無いですが、やや引っかかりがあったり無かったりです
if(y > 300){
if(windPlay){
windPlay = false
wind.play()
}
}else{windPlay = true}
//以下、、、3番目、4番目と続きます
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
//タイマー監視
timer = Timer.scheduledTimer(timeInterval:0.5,target:self,selector:#selector(self.enterFrame),userInfo:nil,repeats:true)
timer.fire()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(true)
//タイマー破棄?
timer.invalidate()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
iPadやSwiftに暗いのですが一般的な問題と捉えた範囲でのコメントをします。
音声の再生が始まるとハードウェアによるバックグラウンド処理により発音されるのですが、ハードウェアを動かすための初期動作に多少時間がかかることはよくあると思います。例えばバッファを確保してそこへ全部あるいは一部の音声データを読み込んだりといったことが考えられます。あらかじめ音量0で鳴らすと現象が軽減されるというのは、初期動作で行ったI/O結果がキャッシュされたためと考えられます。
いずれにせよ音を鳴らすための処理に数10msec~100msecオーダーの時間がかかるとしてそれをUIスレッドで直接行ってしまうとご質問のような影響が出る結果になると思います。
対応としては一般的に以下のような考え方にすると思います。
- バックグラウンド処理を行うためのスレッドをあらかじめ起動しておく
例えばマウスドラッグで音を鳴らすような画面を開いた時点でスレッドを起動してしまいます。音を鳴らす処理はこのスレッド上で行うようにします。 - UIスレッドではバックグラウンドスレッドへ簡単な指示(この音を鳴らせなど)のみ行う
どんな言語・ライブラリーでもスレッド間の同期をとるための機能が提供されていると思いますのでそうしたものを使いスレッド間で情報のやりとりを行います。ただ今回のようなものですと厳密なスレッド間同期の必要性は低く、単にUIスレッドから鳴らしたい音が変化した際に大域変数的なものへ音の種類を直接設定し、バックグラウンドスレッドでは100msec前後の間隔でその変数を監視しつつ音を鳴らすといったシンプルな作りでもよい気もします。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.09%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/01/22 08:27
勉強になります。急ぎその方向での検証をしてみます。