Skip to content

Commit 52376d7

Browse files
committed
[Audio Streamer] Release of 2.3.0 (added custom sampling rate
1 parent b140c0a commit 52376d7

2 files changed

Lines changed: 75 additions & 65 deletions

File tree

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,59 @@
1+
## 2.3.0
2+
3+
- implemented custom sample rate functionality
4+
- [PR#521](https://github.com/cph-cachet/flutter-plugins/pull/521)
5+
- [PR#522](https://github.com/cph-cachet/flutter-plugins/pull/522)
6+
17
## 2.2.0+1
8+
29
- updated example app podfile to correctly include permission for iOS
310
- updated README to include podfile permission
411

512
## 2.2.0
13+
614
- upgrade of `permission_handler: ^10.0.0`
715
- Upgraded to Dart 2.17 and Flutter 3.0
816

917
## 2.1.0
18+
1019
- upgrade of `permission_handler: ^9.2.0`
1120
- [PR#503](https://github.com/cph-cachet/flutter-plugins/pull/503)
1221
- [PR#504](https://github.com/cph-cachet/flutter-plugins/pull/504)
1322

1423
## 2.0.3
24+
1525
- [PR#371](https://github.com/cph-cachet/flutter-plugins/pull/371)
1626

1727
## 2.0.2
28+
1829
- [PR#364](https://github.com/cph-cachet/flutter-plugins/pull/364)
1930
- upgrade to `permission_handler: ^8.1.0`
20-
31+
2132
## 2.0.0
33+
2234
- Null safety migration
2335

2436
## 1.3.0
37+
2538
- Fixed an issue where using another media player/recorder would cause the plugin to go into an error state on iOS (see https://github.com/cph-cachet/flutter-plugins/issues/86)
2639

2740
## 1.2.0
41+
2842
- Fixed an issue where the AVAudioRecorder would crash on iOS (see https://github.com/cph-cachet/flutter-plugins/issues/91)
2943

3044
## 1.1.6
45+
3146
- Upgrade to `permission_handler` v. 5.
3247

3348
## 1.1.5
49+
3450
- Added a getter for the sample rate field.
3551

3652
## 1.1.0
53+
3754
- Able to stream audio data on Android as well
3855
- The plugin will now record as soon as the permission dialog ends.
3956

4057
## 1.0.0
58+
4159
- Able to stream audio data on iOS.

packages/audio_streamer/ios/Classes/SwiftAudioStreamerPlugin.swift

Lines changed: 56 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public class SwiftAudioStreamerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
88
var engine = AVAudioEngine()
99
var audioData: [Float] = []
1010
var recording = false
11+
var preferredSampleRate: Int? = nil
1112

1213
// Register plugin
1314
public static func register(with registrar: FlutterPluginRegistrar) {
@@ -38,38 +39,39 @@ public class SwiftAudioStreamerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
3839
object: nil)
3940
}
4041

41-
@objc func handleInterruption(notification: Notification) {
42-
// If no eventSink to emit events to, do nothing (wait)
43-
if eventSink == nil {
44-
return
45-
}
46-
47-
guard let userInfo = notification.userInfo,
48-
let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
49-
let type = AVAudioSession.InterruptionType(rawValue: typeValue)
50-
else {
51-
return
52-
}
53-
54-
switch type {
55-
case .began: ()
56-
case .ended:
57-
// An interruption ended. Resume playback, if appropriate.
58-
59-
guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else { return }
60-
let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
61-
if options.contains(.shouldResume) {
62-
startRecording()
63-
}
64-
65-
default:
66-
eventSink!(
67-
FlutterError(
68-
code: "100", message: "Recording was interrupted",
69-
details: "Another process interrupted recording."))
70-
}
42+
@objc func handleInterruption(notification: Notification) {
43+
// If no eventSink to emit events to, do nothing (wait)
44+
if eventSink == nil {
45+
return
46+
}
47+
48+
guard let userInfo = notification.userInfo,
49+
let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
50+
let type = AVAudioSession.InterruptionType(rawValue: typeValue)
51+
else {
52+
return
7153
}
7254

55+
switch type {
56+
case .began: ()
57+
case .ended:
58+
// An interruption ended. Resume playback, if appropriate.
59+
60+
guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else {
61+
return
62+
}
63+
let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
64+
if options.contains(.shouldResume) {
65+
startRecording(sampleRate: preferredSampleRate)
66+
}
67+
68+
default:
69+
eventSink!(
70+
FlutterError(
71+
code: "100", message: "Recording was interrupted",
72+
details: "Another process interrupted recording."))
73+
}
74+
}
7375

7476
// Handle stream emitting (Swift => Flutter)
7577
private func emitValues(values: [Float]) {
@@ -89,8 +91,8 @@ public class SwiftAudioStreamerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
8991
) -> FlutterError? {
9092
self.eventSink = eventSink
9193
if let args = arguments as? [String: Any] {
92-
let sampleRate = args["sampleRate"] as? Int
93-
startRecording(sampleRate: sampleRate)
94+
preferredSampleRate = args["sampleRate"] as? Int
95+
startRecording(sampleRate: preferredSampleRate)
9496
} else {
9597
startRecording(sampleRate: nil)
9698
}
@@ -108,43 +110,33 @@ public class SwiftAudioStreamerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
108110
func startRecording(sampleRate: Int?) {
109111
engine = AVAudioEngine()
110112

111-
try! AVAudioSession.sharedInstance().setCategory(
112-
AVAudioSession.Category.playAndRecord, options: .mixWithOthers)
113113
do {
114+
try AVAudioSession.sharedInstance().setCategory(
115+
AVAudioSession.Category.playAndRecord, options: .mixWithOthers)
116+
try AVAudioSession.sharedInstance().setActive(true)
117+
114118
if let sampleRateNotNull = sampleRate {
115119
// Try to set sample rate
116-
try print(AVAudioSession.sharedInstance().setPreferredSampleRate(Double(sampleRateNotNull)))
120+
try AVAudioSession.sharedInstance().setPreferredSampleRate(Double(sampleRateNotNull))
117121
}
118-
} catch {
119-
print("Unexpected error: \(error).")
120-
}
121122

123+
let input = engine.inputNode
124+
let bus = 0
122125

123-
func startRecording() {
124-
engine = AVAudioEngine()
125-
126-
do {
127-
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord, options: .mixWithOthers)
128-
try AVAudioSession.sharedInstance().setActive(true)
129-
130-
if let sampleRateNotNull = sampleRate {
131-
// Try to set sample rate
132-
try AVAudioSession.sharedInstance().setPreferredSampleRate(Double(sampleRateNotNull))
133-
}
134-
135-
let input = engine.inputNode
136-
let bus = 0
137-
138-
input.installTap(onBus: bus, bufferSize: 22050, format: input.inputFormat(forBus: bus)) { buffer, _ -> Void in
139-
let samples = buffer.floatChannelData?[0]
140-
// audio callback, samples in samples[0]...samples[buffer.frameLength-1]
141-
let arr = Array(UnsafeBufferPointer(start: samples, count: Int(buffer.frameLength)))
142-
self.emitValues(values: arr)
143-
}
144-
145-
try engine.start()
146-
} catch {
147-
eventSink!(FlutterError(code: "100", message: "Unable to start audio session", details: error.localizedDescription))
148-
}
126+
input.installTap(onBus: bus, bufferSize: 22050, format: input.inputFormat(forBus: bus)) {
127+
buffer, _ -> Void in
128+
let samples = buffer.floatChannelData?[0]
129+
// audio callback, samples in samples[0]...samples[buffer.frameLength-1]
130+
let arr = Array(UnsafeBufferPointer(start: samples, count: Int(buffer.frameLength)))
131+
self.emitValues(values: arr)
132+
}
133+
134+
try engine.start()
135+
} catch {
136+
eventSink!(
137+
FlutterError(
138+
code: "100", message: "Unable to start audio session", details: error.localizedDescription
139+
))
149140
}
141+
}
150142
}

0 commit comments

Comments
 (0)