NCKitStreamProcessor
Live / real-time denoise adapter for AudioRecord or any PCM source. Resamples to 48 kHz mono, accumulates 10 ms hops, and drives NCKitProcessor.processFrame.
APIโ
Kotlin
class NCKitStreamProcessor(
val processor: NCKitProcessor,
) {
val frameLength: Int
fun prepare(inputFormat: NCKitPcmFormat)
fun convertToTargetFormat(samples: FloatArray, format: NCKitPcmFormat): FloatArray
fun convertToTargetFormat(samples: ShortArray, format: NCKitPcmFormat): FloatArray
fun process(samples: FloatArray, format: NCKitPcmFormat): List<FloatArray>
fun process(samples: ShortArray, format: NCKitPcmFormat): List<FloatArray>
fun processConverted(samples: FloatArray): List<FloatArray>
fun flush(): List<FloatArray>
fun reset()
fun setAttenLim(db: Float)
fun setPostFilterBeta(beta: Float)
}
Setupโ
Kotlin
import com.fiveexceptions.nckit.NCKitModelLocator
import com.fiveexceptions.nckit.NCKitPcmFormat
import com.fiveexceptions.nckit.NCKitProcessor
import com.fiveexceptions.nckit.NCKitStreamProcessor
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
val processor = withContext(Dispatchers.IO) {
val modelFile = NCKitModelLocator.modelFile(context)
NCKitProcessor(modelFile, attenLimDb = 100f, postFilterBeta = 0f)
}
val stream = NCKitStreamProcessor(processor)
val format = NCKitPcmFormat(48_000, 1)
Recreate NCKitStreamProcessor(processor) at the start of each capture session.
Process microphone buffersโ
Kotlin
val readBuf = FloatArray(minBuf / 4)
while (capturing) {
val n = audioRecord.read(readBuf, 0, readBuf.size, AudioRecord.READ_BLOCKING)
if (n <= 0) continue
val micSamples = readBuf.copyOf(n)
stream.prepare(format)
val frames = stream.process(micSamples, format)
for (frame in frames) {
// Each frame: 480 Float samples @ 48 kHz mono (denoised)
}
}
Dry + denoised (A/B)โ
Kotlin
stream.prepare(format)
val dry = stream.convertToTargetFormat(micSamples, format)
val denoised = stream.processConverted(dry)
End of sessionโ
Kotlin
val tail = stream.flush()
stream.reset()
Threadingโ
Not thread-safe โ call prepare, process, processConverted, flush, and reset from one serial thread (capture thread or HandlerThread).
Relatedโ
Live / real-time denoise adapter for AVAudioEngine microphone taps. Resamples to 48 kHz mono, accumulates 10 ms hops, and drives NCKitProcessor.processFrame.
Requires NCKit 1.1.1+ for reset().
APIโ
Swift
public final class NCKitStreamProcessor {
public let frameLength: Int
public init(processor: NCKitProcessor) throws
public func prepare(inputFormat: AVAudioFormat) throws
public func convertToTargetFormat(_ buffer: AVAudioPCMBuffer) throws -> AVAudioPCMBuffer
public func process(buffer: AVAudioPCMBuffer) throws -> [AVAudioPCMBuffer]
public func processConverted(_ buffer: AVAudioPCMBuffer) throws -> [AVAudioPCMBuffer]
public func flush() throws -> [AVAudioPCMBuffer]
public func reset()
public func setAttenLim(_ db: Float)
public func setPostFilterBeta(_ b: Float)
}
Setupโ
Swift
import NCKit
import AVFoundation
let modelURL = try NCKitModelLocator.modelTarGzURL()
let processor = try NCKitProcessor(modelURL: modelURL)
let stream = try NCKitStreamProcessor(processor: processor)
Install microphone tapโ
Swift
inputNode.installTap(onBus: 0, bufferSize: 4096, format: tapFormat) { buffer, _ in
try stream.prepare(inputFormat: buffer.format)
let frames = try stream.process(buffer: buffer)
for frame in frames {
// 480 Float samples @ 48 kHz mono
}
}
Dry + denoised (A/B)โ
Swift
try stream.prepare(inputFormat: buffer.format)
let dry = try stream.convertToTargetFormat(buffer)
let denoised = try stream.processConverted(dry)
End of sessionโ
Swift
let tail = try stream.flush()
stream.reset()
Threadingโ
Not thread-safe โ call prepare, process, processConverted, flush, and reset from one serial queue (typically the audio tap thread).