From e77b794ddb048a52490816ab4637952fbb0ce4e2 Mon Sep 17 00:00:00 2001 From: Nathan Perkins Date: Tue, 3 Nov 2015 12:23:16 -0500 Subject: [PATCH] Resize syllable config before creating detector (bug in fourier transform). --- SyllableDetector.xcodeproj/project.pbxproj | 3 ++ SyllableDetector/AudioInterface.swift | 47 +++++++++++++------ SyllableDetector/Info.plist | 6 ++- SyllableDetector/SyllableDetector.swift | 2 +- .../ViewControllerProcessor.swift | 20 ++++---- 5 files changed, 49 insertions(+), 29 deletions(-) diff --git a/SyllableDetector.xcodeproj/project.pbxproj b/SyllableDetector.xcodeproj/project.pbxproj index 2ef286c..35e17ef 100644 --- a/SyllableDetector.xcodeproj/project.pbxproj +++ b/SyllableDetector.xcodeproj/project.pbxproj @@ -135,6 +135,7 @@ TargetAttributes = { D8625C781BE14922000922D8 = { CreatedOnToolsVersion = 7.1; + DevelopmentTeam = WRZPP65FJN; }; }; }; @@ -286,6 +287,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Developer ID Application"; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = SyllableDetector/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; @@ -300,6 +302,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Developer ID Application"; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = SyllableDetector/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; diff --git a/SyllableDetector/AudioInterface.swift b/SyllableDetector/AudioInterface.swift index ca63ba3..ec526ee 100644 --- a/SyllableDetector/AudioInterface.swift +++ b/SyllableDetector/AudioInterface.swift @@ -15,27 +15,26 @@ func renderOutput(inRefCon:UnsafeMutablePointer, actionFlags: UnsafeMutabl // get audio out interface let aoi = unsafeBitCast(inRefCon, AudioOutputInterface.self) let usableBufferList = UnsafeMutableAudioBufferListPointer(data) - let buffer = UnsafeMutablePointer(usableBufferList[0].mData) - // high settings - let channelCountAsInt = Int(aoi.outputFormat.mChannelsPerFrame) + // number of frames let frameCountAsInt = Int(frameCount) // fill output - var j = 0 - for var channel = 0; channel < channelCountAsInt; ++channel { - // TODO: must be faster way to fill vectors using vDSP + for (channel, buffer) in usableBufferList.enumerate() { + let data = UnsafeMutablePointer(buffer.mData) + let high = aoi.outputHighFor[channel] - // create high - for var i = 0; i < frameCountAsInt; ++i { - buffer[j] = (i < aoi.outputHighFor[channel] ? 1.0 : 0.0) - ++j + // decrement high for + if 0 < high { + aoi.outputHighFor[channel] = high - min(high, frameCountAsInt) + DLog("write high") } - // decrement high for - if 0 < aoi.outputHighFor[channel] { - aoi.outputHighFor[channel] = aoi.outputHighFor[channel] - min(aoi.outputHighFor[channel], frameCountAsInt) + // write data out + for var i = 0; i < frameCountAsInt; ++i { + data[i] = (i < high ? 1.0 : 0.0) } + } return 0 @@ -65,7 +64,7 @@ func processInput(inRefCon:UnsafeMutablePointer, actionFlags: UnsafeMutabl // number of floats per channel let frameCountAsInteger = Int(frameCount) - // multiple channels? de-interleave + // multiple channels for var channel = 0; channel < numberOfChannels; ++channel { // call delegate aii.delegate?.receiveAudioFrom(aii, fromChannel: channel, withData: UnsafeMutablePointer(aii.bufferList[channel].mData), ofLength: frameCountAsInteger) @@ -100,6 +99,8 @@ class AudioInterface let deviceManufacturer: String let streamsInput: Int let streamsOutput: Int + let sampleRateInput: Float64 + let sampleRateOutput: Float64 let buffersInput: [AudioBuffer] let buffersOutput: [AudioBuffer] @@ -143,6 +144,14 @@ class AudioInterface self.streamsInput = Int(size) / sizeof(AudioStreamID) if 0 < self.streamsInput { + // get sample rate + size = UInt32(sizeof(Float64)) + var sampleRateInput: Float64 = 0.0 + propertyAddress.mSelector = kAudioDevicePropertyNominalSampleRate + status = AudioObjectGetPropertyData(deviceID, &propertyAddress, 0, nil, &size, &sampleRateInput) + guard noErr == status else { return nil } + self.sampleRateInput = sampleRateInput + // get stream configuration size = 0 propertyAddress.mSelector = kAudioDevicePropertyStreamConfiguration @@ -169,6 +178,7 @@ class AudioInterface } else { self.buffersInput = [] + self.sampleRateInput = 0.0 } propertyAddress.mSelector = kAudioDevicePropertyStreams @@ -178,6 +188,14 @@ class AudioInterface self.streamsOutput = Int(size) / sizeof(AudioStreamID) if 0 < self.streamsOutput { + // get sample rate + size = UInt32(sizeof(Float64)) + var sampleRateOutput: Float64 = 0.0 + propertyAddress.mSelector = kAudioDevicePropertyNominalSampleRate + status = AudioObjectGetPropertyData(deviceID, &propertyAddress, 0, nil, &size, &sampleRateOutput) + guard noErr == status else { return nil } + self.sampleRateOutput = sampleRateOutput + // get stream configuration size = 0 propertyAddress.mSelector = kAudioDevicePropertyStreamConfiguration @@ -204,6 +222,7 @@ class AudioInterface } else { self.buffersOutput = [] + self.sampleRateOutput = 0.0 } } } diff --git a/SyllableDetector/Info.plist b/SyllableDetector/Info.plist index d698710..fb59666 100644 --- a/SyllableDetector/Info.plist +++ b/SyllableDetector/Info.plist @@ -17,11 +17,13 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 0.1.0 CFBundleSignature ???? CFBundleVersion - 1 + 2 + LSApplicationCategoryType + public.app-category.education LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright diff --git a/SyllableDetector/SyllableDetector.swift b/SyllableDetector/SyllableDetector.swift index dc2be66..1a0429b 100644 --- a/SyllableDetector/SyllableDetector.swift +++ b/SyllableDetector/SyllableDetector.swift @@ -13,7 +13,7 @@ import AVFoundation class SyllableDetector: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate { // should be constant, but sampling rate can be changed when initializing - var config: SyllableDetectorConfig + let config: SyllableDetectorConfig // very specific audio settings required, since down sampling signal var audioSettings: [String: AnyObject] { diff --git a/SyllableDetector/ViewControllerProcessor.swift b/SyllableDetector/ViewControllerProcessor.swift index 1904a31..996f27a 100644 --- a/SyllableDetector/ViewControllerProcessor.swift +++ b/SyllableDetector/ViewControllerProcessor.swift @@ -65,14 +65,6 @@ class Processor: AudioInputInterfaceDelegate { 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. Expecting: \(d.config.samplingRate). Device: \(interfaceInput.inputFormat.mSampleRate).") - d.config.modifySamplingRate(interfaceInput.inputFormat.mSampleRate) - } - } - // set self as delegate interfaceInput.delegate = self } @@ -96,9 +88,6 @@ class Processor: AudioInputInterfaceDelegate { // process dispatch_async(queueProcessing) { if self.detectors[index].seenSyllable() { - // record playing - DLog("\(channel) play") - // play high self.interfaceOutput.createHighOutput(self.entries[index].outputChannel, forDuration: self.highDuration) } @@ -323,7 +312,14 @@ class ViewControllerProcessor: NSViewController, NSTableViewDelegate, NSTableVie if let url = panel.URL, let path = url.path { do { // load file - let config = try SyllableDetectorConfig(fromTextFile: path) + var config = try SyllableDetectorConfig(fromTextFile: path) + + // check sampling rate + if (1 < abs(config.samplingRate - self.deviceInput.sampleRateInput)) { + DLog("Mismatched sampling rates. Expecting: \(config.samplingRate). Device: \(self.deviceInput.sampleRateInput).") + config.modifySamplingRate(self.deviceInput.sampleRateInput) + } + self.processorEntries[row].config = config self.processorEntries[row].network = url.lastPathComponent ?? "Unknown Network" }