Skip to content

Commit

Permalink
Initial implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanntg committed Nov 3, 2015
1 parent 5fc5a8b commit 5d1bd5f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 55 deletions.
3 changes: 3 additions & 0 deletions SyllableDetector/SyllableDetector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ class SyllableDetector: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate
}

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
// append sample data
processSampleBuffer(sampleBuffer)

// process immediately
while processNewValue() {}
}

Expand Down
114 changes: 59 additions & 55 deletions SyllableDetector/ViewControllerProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ class Processor: AudioInputInterfaceDelegate {
// processor entries
let entries: [ProcessorEntry]
let detectors: [SyllableDetector]
let channels: [Int]

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

init(deviceInput: AudioInterface.AudioDevice, deviceOutput: AudioInterface.AudioDevice, entries: [ProcessorEntry]) {
init(deviceInput: AudioInterface.AudioDevice, deviceOutput: AudioInterface.AudioDevice, entries: [ProcessorEntry]) throws {
// setup processor entries
self.entries = entries.filter {
return $0.config != nil
Expand All @@ -44,20 +45,48 @@ class Processor: AudioInputInterfaceDelegate {
return SyllableDetector(config: $0.config!)
}

// setup channels
var channels = [Int](count: 1 + (self.entries.map { return max($0.inputChannel, $0.outputChannel) }.maxElement() ?? -1), repeatedValue: -1)
for (i, p) in self.entries.enumerate() {
channels[p.inputChannel] = i
}
self.channels = channels

// setup input and output devices
interfaceInput = AudioInputInterface(deviceID: deviceInput.deviceID)
interfaceOutput = AudioOutputInterface(deviceID: deviceOutput.deviceID)

// set self as delegate
interfaceInput.delegate = self

try interfaceOutput.initializeAudio()
try interfaceInput.initializeAudio()
}

deinit {
DLog("stop")
interfaceInput.tearDownAudio()
interfaceOutput.tearDownAudio()
}

func receiveAudioFrom(interface: AudioInputInterface, fromChannel channel: Int, withData data: UnsafeMutablePointer<Float>, ofLength length: Int) {
DLog("\(channel) \(data[0])")

// valid channel
guard channel < detectors.count else { return }
guard channel < channels.count else { return }

// get index
let index = channels[channel]
guard index >= 0 else { return }

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

if detectors[channel].seenSyllable() {
interfaceOutput.createHighOutput(channel, forDuration: highDuration)
DLog("play") // for debugging

// play high
interfaceOutput.createHighOutput(entries[index].outputChannel, forDuration: highDuration)
}
}
}
Expand Down Expand Up @@ -130,64 +159,39 @@ class ViewControllerProcessor: NSViewController, NSTableViewDelegate, NSTableVie
}

@IBAction func toggle(sender: NSButton) {
if nil == syllableDetector {
// set stop text
buttonToggle.title = "Stop"

// setup audio processor
setupAudioProcessorWithSyllableDetector()
if isRunning {
// stop everything
processor = nil
// clear is running
isRunning = false
}
else {
// set start text
buttonToggle.title = "Start"
// create process
do {
processor = try Processor(deviceInput: deviceInput, deviceOutput: deviceOutput, entries: processorEntries)
}
catch {
// show an error message
let alert = NSAlert()
alert.messageText = "Unable to initialize audio"
alert.informativeText = "There was an error initializing the audio interfaces: \(error)."
alert.addButtonWithTitle("Ok")
alert.beginSheetModalForWindow(self.view.window!, completionHandler:nil)
return
}

// tear down audio processor
tearDownAudioProcessor()
}
}

override func viewDidDisappear() {
// tear down
tearDownAudioProcessor()
}

func setupAudioProcessorWithSyllableDetector() {
let config: SyllableDetectorConfig
do {
config = try SyllableDetectorConfig(fromTextFile: "sample.txt")
}
catch {
DLog("Unable to parse: \(error)")
return
}

// create interface
aiInput = AudioInputInterface()

// create syllabe detector
let sd = SyllableDetector(config: config)
syllableDetector = sd

// set delegate
aiInput?.delegate = sd

// start
do {
try aiInput?.initializeAudio()
}
catch {
DLog("ERROR WITH INPUT: \(error)")
return
// set as running
isRunning = true
}
}

func tearDownAudioProcessor() {
// tear down input
aiInput?.tearDownAudio()
aiInput = nil
override func viewWillDisappear() {
// clear processor
processor = nil
isRunning = false

// free processors
syllableDetector = nil
super.viewWillDisappear()
}

func numberOfRowsInTableView(tableView: NSTableView) -> Int {
Expand Down

0 comments on commit 5d1bd5f

Please sign in to comment.