Merge pull request #6 from na-2n/feature/stereo
Add stereo recording option
This commit is contained in:
@@ -7,3 +7,5 @@ DerivedData/
|
|||||||
.swiftpm/configuration/registries.json
|
.swiftpm/configuration/registries.json
|
||||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
.netrc
|
.netrc
|
||||||
|
*.pcm
|
||||||
|
*.wav
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ struct AudioTee {
|
|||||||
var includeProcesses: [Int32] = []
|
var includeProcesses: [Int32] = []
|
||||||
var excludeProcesses: [Int32] = []
|
var excludeProcesses: [Int32] = []
|
||||||
var mute: Bool = false
|
var mute: Bool = false
|
||||||
|
var stereo: Bool = false
|
||||||
var sampleRate: Double?
|
var sampleRate: Double?
|
||||||
var chunkDuration: Double = 0.2
|
var chunkDuration: Double = 0.2
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ struct AudioTee {
|
|||||||
parser.addArrayOption(
|
parser.addArrayOption(
|
||||||
name: "exclude-processes", help: "Process IDs to exclude (space-separated)")
|
name: "exclude-processes", help: "Process IDs to exclude (space-separated)")
|
||||||
parser.addFlag(name: "mute", help: "Mute processes being tapped")
|
parser.addFlag(name: "mute", help: "Mute processes being tapped")
|
||||||
|
parser.addFlag(name: "stereo", help: "Records in stereo")
|
||||||
parser.addOption(
|
parser.addOption(
|
||||||
name: "sample-rate",
|
name: "sample-rate",
|
||||||
help: "Target sample rate (8000, 16000, 22050, 24000, 32000, 44100, 48000)")
|
help: "Target sample rate (8000, 16000, 22050, 24000, 32000, 44100, 48000)")
|
||||||
@@ -56,6 +58,7 @@ struct AudioTee {
|
|||||||
audioTee.includeProcesses = try parser.getArrayValue("include-processes", as: Int32.self)
|
audioTee.includeProcesses = try parser.getArrayValue("include-processes", as: Int32.self)
|
||||||
audioTee.excludeProcesses = try parser.getArrayValue("exclude-processes", as: Int32.self)
|
audioTee.excludeProcesses = try parser.getArrayValue("exclude-processes", as: Int32.self)
|
||||||
audioTee.mute = parser.getFlag("mute")
|
audioTee.mute = parser.getFlag("mute")
|
||||||
|
audioTee.stereo = parser.getFlag("stereo")
|
||||||
audioTee.sampleRate = try parser.getOptionalValue("sample-rate", as: Double.self)
|
audioTee.sampleRate = try parser.getOptionalValue("sample-rate", as: Double.self)
|
||||||
audioTee.chunkDuration = try parser.getValue("chunk-duration", as: Double.self)
|
audioTee.chunkDuration = try parser.getValue("chunk-duration", as: Double.self)
|
||||||
|
|
||||||
@@ -107,7 +110,8 @@ struct AudioTee {
|
|||||||
let tapConfig = TapConfiguration(
|
let tapConfig = TapConfiguration(
|
||||||
processes: processes,
|
processes: processes,
|
||||||
muteBehavior: mute ? .muted : .unmuted,
|
muteBehavior: mute ? .muted : .unmuted,
|
||||||
isExclusive: isExclusive
|
isExclusive: isExclusive,
|
||||||
|
isMono: !stereo
|
||||||
)
|
)
|
||||||
|
|
||||||
let audioTapManager = AudioTapManager()
|
let audioTapManager = AudioTapManager()
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ public struct TapConfiguration {
|
|||||||
public let processes: [Int32]
|
public let processes: [Int32]
|
||||||
public let muteBehavior: TapMuteBehavior
|
public let muteBehavior: TapMuteBehavior
|
||||||
public let isExclusive: Bool
|
public let isExclusive: Bool
|
||||||
|
public let isMono: Bool
|
||||||
|
|
||||||
public init(processes: [Int32], muteBehavior: TapMuteBehavior, isExclusive: Bool) {
|
public init(processes: [Int32], muteBehavior: TapMuteBehavior, isExclusive: Bool, isMono: Bool) {
|
||||||
self.processes = processes
|
self.processes = processes
|
||||||
self.muteBehavior = muteBehavior
|
self.muteBehavior = muteBehavior
|
||||||
self.isExclusive = isExclusive
|
self.isExclusive = isExclusive
|
||||||
|
self.isMono = isMono
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,11 +130,11 @@ public class AudioFormatConverter {
|
|||||||
targetFormat.mSampleRate = sampleRate
|
targetFormat.mSampleRate = sampleRate
|
||||||
targetFormat.mFormatID = kAudioFormatLinearPCM
|
targetFormat.mFormatID = kAudioFormatLinearPCM
|
||||||
targetFormat.mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger
|
targetFormat.mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger
|
||||||
targetFormat.mBytesPerPacket = 2
|
|
||||||
targetFormat.mFramesPerPacket = 1
|
targetFormat.mFramesPerPacket = 1
|
||||||
targetFormat.mBytesPerFrame = 2
|
|
||||||
targetFormat.mChannelsPerFrame = 1 // Always mono since tap handles this
|
|
||||||
targetFormat.mBitsPerChannel = 16
|
targetFormat.mBitsPerChannel = 16
|
||||||
|
targetFormat.mChannelsPerFrame = sourceFormat.mChannelsPerFrame
|
||||||
|
targetFormat.mBytesPerFrame = (targetFormat.mBitsPerChannel / 8) * sourceFormat.mChannelsPerFrame
|
||||||
|
targetFormat.mBytesPerPacket = targetFormat.mFramesPerPacket * targetFormat.mBytesPerFrame
|
||||||
|
|
||||||
return try AudioFormatConverter(sourceFormat: sourceFormat, targetFormat: targetFormat)
|
return try AudioFormatConverter(sourceFormat: sourceFormat, targetFormat: targetFormat)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class AudioTapManager {
|
|||||||
description.isPrivate = true
|
description.isPrivate = true
|
||||||
description.muteBehavior = config.muteBehavior.coreAudioValue
|
description.muteBehavior = config.muteBehavior.coreAudioValue
|
||||||
description.isMixdown = true
|
description.isMixdown = true
|
||||||
description.isMono = true
|
description.isMono = config.isMono
|
||||||
description.isExclusive = config.isExclusive
|
description.isExclusive = config.isExclusive
|
||||||
description.deviceUID = nil // system default
|
description.deviceUID = nil // system default
|
||||||
description.stream = 0 // first stream of output device
|
description.stream = 0 // first stream of output device
|
||||||
|
|||||||
Reference in New Issue
Block a user