-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAVTonePlayerUnit.swift
66 lines (55 loc) · 1.72 KB
/
AVTonePlayerUnit.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//
// AVTonePlayerUnit.swift
// ToneGenerator
//
// Created by OOPer in cooperation with shlab.jp, on 2015/3/22.
// See LICENSE.txt .
//
import Foundation
import AVFoundation
class AVTonePlayerUnit: AVAudioPlayerNode {
let bufferCapacity: AVAudioFrameCount = 512
let sampleRate: Double = 44_100.0
var frequency: Double = 600 //440.0
var amplitude: Double = 0.25
private var theta: Double = 0.0
private var audioFormat: AVAudioFormat!
override init() {
super.init()
audioFormat = AVAudioFormat(standardFormatWithSampleRate: sampleRate, channels: 1)
}
func prepareBuffer() -> AVAudioPCMBuffer {
let buffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: bufferCapacity)!
fillBuffer(buffer)
return buffer
}
func fillBuffer(_ buffer: AVAudioPCMBuffer) {
let data = buffer.floatChannelData?[0]
let numberFrames = buffer.frameCapacity
var theta = self.theta
let theta_increment = 2.0 * .pi * self.frequency / self.sampleRate
for frame in 0..<Int(numberFrames) {
data?[frame] = Float32(sin(theta) * amplitude)
theta += theta_increment
if theta > 2.0 * .pi {
theta -= 2.0 * .pi
}
}
buffer.frameLength = numberFrames
self.theta = theta
}
func scheduleBuffer() {
let buffer = prepareBuffer()
self.scheduleBuffer(buffer) {
if self.isPlaying {
self.scheduleBuffer()
}
}
}
func preparePlaying() {
scheduleBuffer()
scheduleBuffer()
scheduleBuffer()
scheduleBuffer()
}
}