-
Notifications
You must be signed in to change notification settings - Fork 18
/
AudioViewController.swift
120 lines (101 loc) · 3.77 KB
/
AudioViewController.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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//
// AudioViewController.swift
// iSensorSwift
//
// Created by koogawa on 2016/04/15.
// Copyright © 2016 koogawa. All rights reserved.
//
import UIKit
import AudioToolbox
private func AudioQueueInputCallback(
_ inUserData: UnsafeMutableRawPointer?,
inAQ: AudioQueueRef,
inBuffer: AudioQueueBufferRef,
inStartTime: UnsafePointer<AudioTimeStamp>,
inNumberPacketDescriptions: UInt32,
inPacketDescs: UnsafePointer<AudioStreamPacketDescription>?)
{
// Do nothing, because not recoding.
}
class AudioViewController: UIViewController {
@IBOutlet weak var loudLabel: UILabel!
@IBOutlet weak var peakTextField: UITextField!
@IBOutlet weak var averageTextField: UITextField!
var queue: AudioQueueRef!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
self.startUpdatingVolume()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.stopUpdatingVolume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Internal methods
func startUpdatingVolume() {
// Set data format
var dataFormat = AudioStreamBasicDescription(
mSampleRate: 44100.0,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: AudioFormatFlags(kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked),
mBytesPerPacket: 2,
mFramesPerPacket: 1,
mBytesPerFrame: 2,
mChannelsPerFrame: 1,
mBitsPerChannel: 16,
mReserved: 0)
// Observe input level
var audioQueue: AudioQueueRef? = nil
var error = noErr
error = AudioQueueNewInput(
&dataFormat,
AudioQueueInputCallback,
UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),
.none,
.none,
0,
&audioQueue)
if error == noErr {
self.queue = audioQueue
}
AudioQueueStart(self.queue, nil)
// Enable level meter
var enabledLevelMeter: UInt32 = 1
AudioQueueSetProperty(self.queue, kAudioQueueProperty_EnableLevelMetering, &enabledLevelMeter, UInt32(MemoryLayout<UInt32>.size))
self.timer = Timer.scheduledTimer(timeInterval: 0.5,
target: self,
selector: #selector(AudioViewController.detectVolume(_:)),
userInfo: nil,
repeats: true)
self.timer?.fire()
}
func stopUpdatingVolume()
{
// Finish observation
self.timer.invalidate()
self.timer = nil
AudioQueueFlush(self.queue)
AudioQueueStop(self.queue, false)
AudioQueueDispose(self.queue, true)
}
@objc func detectVolume(_ timer: Timer)
{
// Get level
var levelMeter = AudioQueueLevelMeterState()
var propertySize = UInt32(MemoryLayout<AudioQueueLevelMeterState>.size)
AudioQueueGetProperty(
self.queue,
kAudioQueueProperty_CurrentLevelMeterDB,
&levelMeter,
&propertySize)
// Show the audio channel's peak and average RMS power.
self.peakTextField.text = "".appendingFormat("%.2f", levelMeter.mPeakPower)
self.averageTextField.text = "".appendingFormat("%.2f", levelMeter.mAveragePower)
// Show "LOUD!!" if mPeakPower is larger than -1.0
self.loudLabel.isHidden = (levelMeter.mPeakPower >= -1.0) ? false : true
}
}