Skip to content

Commit

Permalink
Switch to supporting a single buffer.
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanntg committed Nov 3, 2015
1 parent cfa9030 commit 5fc5a8b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 39 deletions.
20 changes: 11 additions & 9 deletions SyllableDetector/AudioInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ func renderOutput(inRefCon:UnsafeMutablePointer<Void>, actionFlags: UnsafeMutabl
let buffer = UnsafeMutablePointer<Float>(usableBufferList[0].mData)

// high settings
let highForLength = aoi.outputHighFor.count
let channelCountAsInt = Int(aoi.outputFormat.mChannelsPerFrame)
let frameCountAsInt = Int(frameCount)

Expand All @@ -28,12 +27,7 @@ func renderOutput(inRefCon:UnsafeMutablePointer<Void>, actionFlags: UnsafeMutabl

// create high
for var i = 0; i < frameCountAsInt; ++i {
if channel < highForLength {
buffer[j] = (i < aoi.outputHighFor[channel] ? 1.0 : 0.0)
}
else {
buffer[j] = 0.0
}
buffer[j] = (i < aoi.outputHighFor[channel] ? 1.0 : 0.0)
++j
}

Expand Down Expand Up @@ -76,7 +70,7 @@ func processInput(inRefCon:UnsafeMutablePointer<Void>, actionFlags: UnsafeMutabl
let maxi = Int(aii.inputFormat.mChannelsPerFrame)
for var i = 0; i < maxi; ++i {
// for each channel
aii.delegate?.receiveAudioFrom(aii, fromBuffer: 0, fromChannel: i, withData: data + (i * frameLength), ofLength: frameLength)
aii.delegate?.receiveAudioFrom(aii, fromChannel: i, withData: data + (i * frameLength), ofLength: frameLength)
}

return 0
Expand Down Expand Up @@ -291,6 +285,9 @@ class AudioOutputInterface: AudioInterface
assert(2 == outputFormat.mChannelsPerFrame)
assert(8 == outputFormat.mBytesPerFrame)

// initiate output array
outputHighFor = [Int](count: Int(outputFormat.mChannelsPerFrame), repeatedValue: 0)

// set frame size
var frameSize = UInt32(self.frameSize)
try checkError(AudioUnitSetProperty(audioUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, outputBus, &frameSize, UInt32(sizeof(UInt32))))
Expand Down Expand Up @@ -323,6 +320,11 @@ class AudioOutputInterface: AudioInterface
audioUnit = nil
}

func createHighOutput(channel: Int, forDuration duration: Double) {
guard channel < Int(outputFormat.mChannelsPerFrame) else { return }
outputHighFor[channel] = Int(duration * outputFormat.mSampleRate)
}

static func defaultOutputDevice() throws -> AudioDeviceID {
var size: UInt32
size = UInt32(sizeof(AudioDeviceID))
Expand All @@ -335,7 +337,7 @@ class AudioOutputInterface: AudioInterface

protocol AudioInputInterfaceDelegate: class
{
func receiveAudioFrom(interface: AudioInputInterface, fromBuffer buffer: Int, fromChannel: Int, withData data: UnsafeMutablePointer<Float>, ofLength: Int)
func receiveAudioFrom(interface: AudioInputInterface, fromChannel: Int, withData data: UnsafeMutablePointer<Float>, ofLength: Int)
}

class AudioInputInterface: AudioInterface
Expand Down
63 changes: 33 additions & 30 deletions SyllableDetector/ViewControllerProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,18 @@ import Cocoa
import AudioToolbox

struct ProcessorEntry {
let inputBuffer: Int
let inputChannel: Int
var network: String = ""
var config: SyllableDetectorConfig?
let outputBuffer: Int
let outputChannel: Int

init(inputBuffer: Int, inputChannel: Int, outputBuffer: Int, outputChannel: Int) {
self.inputBuffer = inputBuffer
init(inputChannel: Int, outputChannel: Int) {
self.inputChannel = inputChannel
self.outputBuffer = outputBuffer
self.outputChannel = outputChannel
}
}

class Processor {
class Processor: AudioInputInterfaceDelegate {
// input and output interfaces
let interfaceInput: AudioInputInterface
let interfaceOutput: AudioOutputInterface
Expand All @@ -34,6 +30,9 @@ class Processor {
let entries: [ProcessorEntry]
let detectors: [SyllableDetector]

// high duration
let highDuration = 0.001 // 1ms

init(deviceInput: AudioInterface.AudioDevice, deviceOutput: AudioInterface.AudioDevice, entries: [ProcessorEntry]) {
// setup processor entries
self.entries = entries.filter {
Expand All @@ -49,6 +48,18 @@ class Processor {
interfaceInput = AudioInputInterface(deviceID: deviceInput.deviceID)
interfaceOutput = AudioOutputInterface(deviceID: deviceOutput.deviceID)
}

func receiveAudioFrom(interface: AudioInputInterface, fromChannel channel: Int, withData data: UnsafeMutablePointer<Float>, ofLength length: Int) {
// valid channel
guard channel < detectors.count else { return }

// append audio samples
detectors[channel].appendAudioData(data, withSamples: length)

if detectors[channel].seenSyllable() {
interfaceOutput.createHighOutput(channel, forDuration: highDuration)
}
}
}

class ViewControllerProcessor: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
Expand All @@ -61,9 +72,7 @@ class ViewControllerProcessor: NSViewController, NSTableViewDelegate, NSTableVie
var deviceOutput: AudioInterface.AudioDevice!

var processorEntries = [ProcessorEntry]()

var syllableDetector: SyllableDetector?
var aiInput: AudioInputInterface?
var processor: Processor?

var isRunning = false {
didSet {
Expand Down Expand Up @@ -97,21 +106,26 @@ class ViewControllerProcessor: NSViewController, NSTableViewDelegate, NSTableVie
self.deviceOutput = deviceOutput

// get input pairs
let inputPairs = deviceInput.buffersInput.enumerate().flatMap {
(b: Int, buffer: AudioBuffer) -> [(Int, Int)] in
return (0..<Int(buffer.mNumberChannels)).map { return (b, $0) }
let inputChannels: Int
if 0 < deviceInput.buffersInput.count {
inputChannels = Int(deviceInput.buffersInput[0].mNumberChannels)
}
else {
inputChannels = 0
}

// get output pairs
let outputPairs = deviceOutput.buffersOutput.enumerate().flatMap {
(b: Int, buffer: AudioBuffer) -> [(Int, Int)] in
return (0..<Int(buffer.mNumberChannels)).map { return (b, $0) }
let outputChannels: Int
if 0 < deviceOutput.buffersOutput.count {
outputChannels = Int(deviceOutput.buffersOutput[0].mNumberChannels)
}
else {
outputChannels = 0
}

// for each pair, create an entry
let numEntries = min(inputPairs.count, outputPairs.count)
let numEntries = min(inputChannels, outputChannels)
processorEntries = (0..<numEntries).map {
return ProcessorEntry(inputBuffer: inputPairs[$0].0, inputChannel: inputPairs[$0].1, outputBuffer: outputPairs[$0].0, outputChannel: outputPairs[$0].1)
return ProcessorEntry(inputChannel: $0, outputChannel: $0)
}
}

Expand Down Expand Up @@ -205,18 +219,7 @@ class ViewControllerProcessor: NSViewController, NSTableViewDelegate, NSTableVie
guard row < processorEntries.count else { return nil }

switch identifier {
case "ColumnInput":
// support multiple buffers (will this ever happen?)
if 1 < deviceInput.buffersInput.count {
return "B \(1 + processorEntries[row].inputBuffer) Ch \(1 + processorEntries[row].inputChannel)"
}
return "Channel \(1 + processorEntries[row].inputChannel)"
case "ColumnOutput":
// support multiple buffers (will this ever happen?)
if 1 < deviceOutput.buffersOutput.count {
return "B \(1 + processorEntries[row].outputBuffer) Ch \(1 + processorEntries[row].outputChannel)"
}
return "Channel \(1 + processorEntries[row].outputChannel)"
case "ColumnInput", "ColumnOutput": return "Channel \(row + 1)"
case "ColumnInLevel", "ColumnOutLevel": return NSNumber(float: 0.0)
case "ColumnNetwork": return nil == processorEntries[row].config ? "Not Selected" : processorEntries[row].network
default: return nil
Expand Down

0 comments on commit 5fc5a8b

Please sign in to comment.