From 4d7be7ce9051bddb5d9ee414dbd250847522b595 Mon Sep 17 00:00:00 2001 From: Nathan Perkins Date: Tue, 3 Nov 2015 09:58:55 -0500 Subject: [PATCH] Automatically adjust sampling rates based on device. --- SyllableDetector/SyllableDetector.swift | 3 +- SyllableDetector/SyllableDetectorConfig.swift | 33 +++++++++++++++++-- SyllableDetector/ViewControllerMenu.swift | 13 +++++--- .../ViewControllerProcessor.swift | 9 ++--- sample.txt | 6 ++-- 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/SyllableDetector/SyllableDetector.swift b/SyllableDetector/SyllableDetector.swift index 8a734d3..dc2be66 100644 --- a/SyllableDetector/SyllableDetector.swift +++ b/SyllableDetector/SyllableDetector.swift @@ -12,7 +12,8 @@ import AVFoundation class SyllableDetector: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate { - let config: SyllableDetectorConfig + // should be constant, but sampling rate can be changed when initializing + var config: SyllableDetectorConfig // very specific audio settings required, since down sampling signal var audioSettings: [String: AnyObject] { diff --git a/SyllableDetector/SyllableDetectorConfig.swift b/SyllableDetector/SyllableDetectorConfig.swift index 69e3477..57b1765 100644 --- a/SyllableDetector/SyllableDetectorConfig.swift +++ b/SyllableDetector/SyllableDetectorConfig.swift @@ -10,9 +10,9 @@ import Foundation struct SyllableDetectorConfig { - let samplingRate: Double // eqv: samplerate - let fourierLength: Int // eqv: FFT_SIZE - let fourierOverlap: Int // eqv: NOVERLAP = FFT_SIZE - (floor(samplerate * FFT_TIME_SHIFT)) + var samplingRate: Double // eqv: samplerate + var fourierLength: Int // eqv: FFT_SIZE + var fourierOverlap: Int // eqv: NOVERLAP = FFT_SIZE - (floor(samplerate * FFT_TIME_SHIFT)) let freqRange: (Double, Double) // eqv: freq_range let timeRange: Int // eqv: time_window_steps = double(floor(time_window / timestep)) @@ -20,6 +20,33 @@ struct SyllableDetectorConfig let threshold: Double // eqv: trigger threshold let net: NeuralNet + + mutating func modifySamplingRate(newSamplingRate: Double) { + // store old things + let oldSamplingRate = samplingRate + let oldFourierLength = fourierLength + let oldFourierOverlap = fourierOverlap + + if oldSamplingRate == newSamplingRate { return } + + + // get new approximate fourier length + let newApproximateFourierLength = newSamplingRate * Double(oldFourierLength) / oldSamplingRate + + // convert to closest power of 2 + let newFourierLength = 1 << Int(round(log2(newApproximateFourierLength))) + + // get new fourier overlap + let newFourierOverlap = newFourierLength - Int(round(newSamplingRate * Double(oldFourierLength - oldFourierOverlap) / oldSamplingRate)) + + // change the to new things + samplingRate = newSamplingRate + fourierLength = newFourierLength + fourierOverlap = newFourierOverlap + + DLog("New fourier length: \(newFourierLength)") + DLog("New fourier overlap: \(newFourierOverlap)") + } } // make parsable diff --git a/SyllableDetector/ViewControllerMenu.swift b/SyllableDetector/ViewControllerMenu.swift index d755d15..27d56dd 100644 --- a/SyllableDetector/ViewControllerMenu.swift +++ b/SyllableDetector/ViewControllerMenu.swift @@ -24,10 +24,10 @@ class ViewControllerMenu: NSViewController, WindowControllerProcessorDelegate { reloadDevices() } - override func viewDidDisappear() { - // terminate - NSApp.terminate(nil) - } +// override func viewDidDisappear() { +// // terminate +// NSApp.terminate(nil) +// } func reloadDevices() { // fetch list of devices @@ -106,6 +106,11 @@ class ViewControllerMenu: NSViewController, WindowControllerProcessorDelegate { controller.delegate = self // custom delegate used to clean up open processor list when windows are closed controller.showWindow(sender) openProcessors.append(controller) + + // reset selector + selectInput.selectItemAtIndex(0) + selectOutput.selectItemAtIndex(0) + buttonLaunch.enabled = false } func windowControllerDone(controller: WindowControllerProcessor) { diff --git a/SyllableDetector/ViewControllerProcessor.swift b/SyllableDetector/ViewControllerProcessor.swift index f95278b..1904a31 100644 --- a/SyllableDetector/ViewControllerProcessor.swift +++ b/SyllableDetector/ViewControllerProcessor.swift @@ -62,18 +62,19 @@ class Processor: AudioInputInterfaceDelegate { // create queue queueProcessing = dispatch_queue_create("ProcessorQueue", DISPATCH_QUEUE_SERIAL) - // set self as delegate - interfaceInput.delegate = self - try interfaceOutput.initializeAudio() try interfaceInput.initializeAudio() // check sampling rates for d in self.detectors { if (1 < abs(d.config.samplingRate - interfaceInput.inputFormat.mSampleRate)) { - DLog("Mismatched sampling rates.") + DLog("Mismatched sampling rates. Expecting: \(d.config.samplingRate). Device: \(interfaceInput.inputFormat.mSampleRate).") + d.config.modifySamplingRate(interfaceInput.inputFormat.mSampleRate) } } + + // set self as delegate + interfaceInput.delegate = self } deinit { diff --git a/sample.txt b/sample.txt index 9a71f6c..9d08236 100644 --- a/sample.txt +++ b/sample.txt @@ -1,7 +1,7 @@ # AUTOMATICALLY GENERATED SYLLABLE DETECTOR CONFIGURATION -samplingRate = 44100.0 -fourierLength = 512 -fourierOverlap = 380 +samplingRate = 20000.0 +fourierLength = 256 +fourierOverlap = 196 freqRange = 1992.0, 6992.0 timeRange = 9 threshold = 0.351351351351351