質問編集履歴

1

多々変更

2018/01/24 09:31

投稿

YMD_kts
YMD_kts

スコア23

test CHANGED
@@ -1 +1 @@
1
- AVAudioEngineを用いたABループ機能
1
+ AVAudioEngineを用いた指定部分ループ機能
test CHANGED
@@ -8,15 +8,49 @@
8
8
 
9
9
  ##質問内容
10
10
 
11
- https://qiita.com/muukii0803/items/437fa0c8038878b5a23c
12
-
13
- http://asmz.hatenablog.jp/entry/avaudioengine-seek-the-time-of-the-song
14
-
15
-
16
-
17
- 上記サイトを元に、ABリピートのように自分ループしたい部分を選択できるプログラムを書きたいのですが色々といじっている内に再生さえされなかったりNSWindowがエラーを吐いたりとどうすればよいかわからなくなってしまいました。
18
-
19
- ```
11
+ 現在、playを押すと音楽が無限ループで流れる状態です。
12
+
13
+ そしてloopStartSettingを押してloopEndSettingを押すと、音楽が最初から流れ、StartからEndを押すまでの間を無限ループします。
14
+
15
+ しかし音楽が2周目以降にloopStartとloopEndを設定しようとするとloopEndSettingを押したときにエラーを出します。
16
+
17
+ そこ
18
+
19
+
20
+
21
+ 1. 音楽が2周目以降でもStartEnd間でループさせたい
22
+
23
+
24
+
25
+ 2.StartEnd間でループが始まる前に音楽が最初から流れるのをloopStartSettingを押した時点から再生させたい(イメージとしてはABリピート)
26
+
27
+
28
+
29
+ この二点の問題を解決したいです
30
+
31
+ よろしくお願いします
32
+
33
+
34
+
35
+ ---
36
+
37
+ ```
38
+
39
+ try! file.read(into: loopBuffer, frameCount: frametoplay)
40
+
41
+ ```
42
+
43
+
44
+
45
+ ```エラーコード
46
+
47
+ fatal error: 'try!' expression unexpectedly raised an error: Foundation._GenericObjCError.nilError: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.65.2/src/swift/stdlib/public/core/ErrorType.swift, line 181
48
+
49
+ ```
50
+
51
+
52
+
53
+ ```Swift4.0
20
54
 
21
55
  import Cocoa
22
56
 
@@ -24,9 +58,7 @@
24
58
 
25
59
 
26
60
 
27
- public class ViewController: NSViewController {
61
+ class ViewController: NSViewController {
28
-
29
-
30
62
 
31
63
  let engine = AVAudioEngine()
32
64
 
@@ -34,31 +66,27 @@
34
66
 
35
67
 
36
68
 
37
- @IBOutlet var currentTimeLabel: NSTextField!
38
-
39
- @IBOutlet var totalTimeLabel: NSTextField!
40
-
41
- @IBOutlet var playButtonTitle: NSButton!
42
-
43
-
44
-
45
-
46
-
47
69
  let url = Bundle.main.url(forResource: "moo", withExtension: "mp3")!
48
70
 
49
71
 
50
72
 
51
- var loopStart: AVAudioFramePosition = 0
73
+ var loopStart: Double = 0
52
-
74
+
53
- var loopEnd: AVAudioFramePosition = 0
75
+ var loopEnd: Double = 0
76
+
54
-
77
+ var loopBuffer = AVAudioPCMBuffer()
78
+
55
-
79
+ var introBuffer = AVAudioPCMBuffer()
56
-
57
-
58
-
80
+
81
+
82
+
59
- @IBAction func playButton(_ sender: Any) {
83
+ @IBAction func play(_ sender: Any) {
84
+
60
-
85
+ try! engine.start()
86
+
87
+
88
+
61
- if !player.isPlaying{
89
+ if !player.isPlaying {
62
90
 
63
91
  player.play()
64
92
 
@@ -72,75 +100,81 @@
72
100
 
73
101
 
74
102
 
75
- func loopSetA(startFrame: Double) {
76
-
77
- let file = try! AVAudioFile(forReading: url)
78
-
79
-
80
-
81
-
82
-
83
- let loopStartCount = AVAudioFrameCount(AVAudioFramePosition(startFrame))
84
-
85
- let loopStartBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: loopStartCount)!
86
-
87
- try! file.read(into: loopStartBuffer, frameCount: loopStartCount)
88
-
89
- player.scheduleBuffer(loopStartBuffer, at: nil, options: .interrupts)
90
-
91
-
92
-
93
- }
94
-
95
-
96
-
97
- func loopSetB(endFrame: Double, loopStart: AVAudioFrameCount) {
98
-
99
- let file = try! AVAudioFile(forReading: url)
100
-
101
-
102
-
103
- let loopFrameCount = AVAudioFrameCount(endFrame) - AVAudioFrameCount(loopStart)
104
-
105
- let loopFrameBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: loopFrameCount)!
106
-
107
- try! file.read(into: loopFrameBuffer, frameCount: loopFrameCount)
108
-
109
- player.scheduleBuffer(loopFrameBuffer, at: nil, options: .loops)
110
-
111
- }
112
-
113
-
114
-
115
-
116
-
117
-
103
+ @IBAction func pause(_ sender: Any) {
104
+
105
+ player.pause()
106
+
107
+ }
108
+
109
+
110
+
111
+ func loopControl() {
112
+
113
+ let file = try! AVAudioFile(forReading: url)
114
+
115
+ let sampleRate = file.fileFormat.sampleRate
116
+
117
+
118
+
119
+ let newsampleTime = AVAudioFrameCount(sampleRate * loopStart) //シーク位置(AVAudioFramePositon)取得
120
+
121
+ let length = loopEnd - loopStart //残り時間取得(秒)
122
+
123
+ let frametoplay = AVAudioFrameCount(sampleRate * length)
124
+
125
+
126
+
127
+ introBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: newsampleTime)!//Aを押すまでのバッファ
128
+
129
+ loopBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: frametoplay)!//AからBまでのバッファ
130
+
131
+
132
+
133
+ try! file.read(into: introBuffer, frameCount: newsampleTime)
134
+
135
+ try! file.read(into: loopBuffer, frameCount: frametoplay)
136
+
137
+
138
+
139
+ player.stop()
140
+
141
+ if frametoplay > 100 {
142
+
143
+
144
+
145
+ player.scheduleBuffer(introBuffer, at: nil, completionHandler: nil)
146
+
147
+ player.scheduleBuffer(loopBuffer, at: nil, options: .loops, completionHandler: nil)
148
+
149
+ }
150
+
151
+
152
+
153
+ player.play()
154
+
155
+ }
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
118
164
 
119
165
  @IBAction func loopStartSetting(_ sender: Any) {
120
166
 
121
- if loopStart == 0{
122
-
123
- let startNodeTime = player.lastRenderTime
124
-
125
- let startPlayerTime = player.playerTime(forNodeTime: startNodeTime!)
167
+ let file = try! AVAudioFile(forReading: url)
126
-
168
+
127
- let currentFrame = Double(startPlayerTime!.sampleRate)
169
+ let sampleRate = file.fileFormat.sampleRate
128
-
129
- loopStart = AVAudioFramePosition(currentFrame)
170
+
130
-
131
- loopSetA(startFrame: currentFrame)
171
+
132
-
133
- }else{
172
+
134
-
135
- let endNodeTime = player.lastRenderTime
173
+ let nodeTime = player.lastRenderTime
136
-
174
+
137
- let endPlayerTime = player.playerTime(forNodeTime: endNodeTime!)
175
+ let playerTime = player.playerTime(forNodeTime: nodeTime!)
138
-
176
+
139
- let endFrame = Double(endPlayerTime!.sampleRate)
177
+ loopStart = (Double(playerTime!.sampleTime) / sampleRate)
140
-
141
- loopSetB(endFrame: endFrame, loopStart: AVAudioFrameCount(loopStart))
142
-
143
- }
144
178
 
145
179
  }
146
180
 
@@ -148,13 +182,27 @@
148
182
 
149
183
  @IBAction func loopEndSetting(_ sender: Any) {
150
184
 
151
-
185
+ let file = try! AVAudioFile(forReading: url)
186
+
152
-
187
+ let sampleRate = file.fileFormat.sampleRate
188
+
189
+
190
+
191
+ let nodeTime = player.lastRenderTime
192
+
193
+ let playerTime = player.playerTime(forNodeTime: nodeTime!)
194
+
195
+ loopEnd = (Double(playerTime!.sampleTime) / sampleRate)
196
+
197
+
198
+
199
+ loopControl()
200
+
153
- }
201
+ }
154
-
155
-
156
-
202
+
203
+
204
+
157
- override public func viewDidLoad() {
205
+ override func viewDidLoad() {
158
206
 
159
207
  super.viewDidLoad()
160
208
 
@@ -162,7 +210,7 @@
162
210
 
163
211
  engine.attach(player)
164
212
 
165
-
213
+
166
214
 
167
215
  let file = try! AVAudioFile(forReading: url)
168
216
 
@@ -170,56 +218,16 @@
170
218
 
171
219
  let totalFrameCount = AVAudioFrameCount(file.length)
172
220
 
173
- let loopStartCount = AVAudioFrameCount(loopStart)
174
-
175
- let loopFrameCount = totalFrameCount - loopStartCount
176
-
177
-
178
-
179
- //イントロとループ部のバッファ作成
180
-
181
- let loopStartBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: loopStartCount)!
182
-
183
- let loopFrameBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: loopFrameCount)!
221
+ let totalFrameBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: totalFrameCount)
184
-
185
-
186
-
187
- try! file.read(into: loopStartBuffer, frameCount: loopStartCount)
222
+
188
-
189
- try! file.read(into: loopFrameBuffer, frameCount: loopFrameCount)
223
+ try! file.read(into: totalFrameBuffer!, frameCount: totalFrameCount)
190
-
191
-
192
-
193
- player.scheduleBuffer(loopStartBuffer, at: nil, options: .interrupts)
194
-
195
- player.scheduleBuffer(loopFrameBuffer, at: nil, options: .loops)
196
224
 
197
225
 
198
226
 
199
227
  engine.connect(player, to: engine.mainMixerNode, format: file.processingFormat)
200
228
 
201
- try! engine.start()
229
+ player.scheduleBuffer(totalFrameBuffer!, at: nil, options: .loops, completionHandler: nil)
202
-
230
+
203
- }
231
+ }
204
-
205
-
206
-
207
- override public var representedObject: Any? {
232
+
208
-
209
- didSet {
210
-
211
- // Update the view, if already loaded.
212
-
213
- }
214
-
215
- }
216
-
217
- }
218
-
219
- ```
233
+ ```
220
-
221
-
222
-
223
- 機能としてはAボタンを押してその後Bボタンを押すとAB間がループする、もしくは同じぼんを1回押して、少し間を開けてもう1回押すと2回めに押すまでに流れた音楽がリピートするといったものを目指しています。
224
-
225
- ご回答よろしくお願いします