Skip to content

Instantly share code, notes, and snippets.

@hpux735
Last active August 29, 2015 14:13
Show Gist options
  • Save hpux735/349211b19f2227cbeb2a to your computer and use it in GitHub Desktop.
Save hpux735/349211b19f2227cbeb2a to your computer and use it in GitHub Desktop.
RTL-SDR file formatter for GNURadio. Uses Swift and Accelerate framework. It's MUCH faster than the GRC on the rtlsdr website.
//
// main.swift
// rtl-formater
//
// Created by William Dillon on 1/21/15.
// Copyright (c) 2015 HouseDillon. All rights reserved.
//
import Foundation
import Accelerate
let blockSize = 100_000_000
// Temporary arrays for processing
var uosFloat = Array<Float>(count: blockSize, repeatedValue: 0.0)
var usFloat = Array<Float>(count: blockSize, repeatedValue: 0.0)
var dFloat = Array<Float>(count: blockSize, repeatedValue: 0.0)
func processBytes(input: NSData) -> NSData {
// First, we'll calculate the number of samples
// each sample is a pair of 8-bit integers; inphase and quadrature
let elements = vDSP_Length(input.length)
// Convert the bytes into floats
vDSP_vfltu8(UnsafePointer<UInt8>(input.bytes), 1, &uosFloat, 1, elements)
// Add the offset
let offset = Array<Float>(arrayLiteral: -127.0)
vDSP_vsadd(uosFloat, 1, offset, &usFloat, 1, elements)
// Scale the values
let scalar = Array<Float>(arrayLiteral: 1.0 / 127.0)
vDSP_vsmul(usFloat, 1, scalar, &dFloat, 1, elements)
return NSData(bytes: dFloat, length: Int(elements) * sizeof(Float))
}
// rtl-formatter inputFile.raw outputFile.raw
// The second argument is the input, the third is the output
let applicationName = String(UTF8String: C_ARGV[0])!.lastPathComponent
if C_ARGC < 3 {
println("Usage: \(applicationName) inputFile.raw outputFile.raw")
exit(EXIT_FAILURE)
}
let inputFileName = String(UTF8String: C_ARGV[1])
let outputFileName = String(UTF8String: C_ARGV[2])
var inputData: NSData
var outputFileHandle: NSFileHandle
// Checking everything to make sure we're happy.
if let input = inputFileName? {
let inputDataOptional = NSData(contentsOfMappedFile: inputFileName!)
if inputDataOptional? != nil {
inputData = inputDataOptional!
} else {
println("Unable to open input file.")
exit(EXIT_FAILURE)
}
} else {
println("Unable to read input file name.")
exit(EXIT_FAILURE)
}
if let output = outputFileName? {
// If the file doesn't exist, create one.
let manager = NSFileManager.defaultManager()
if !manager.fileExistsAtPath(outputFileName!) {
manager.createFileAtPath(outputFileName!, contents: nil, attributes: nil)
}
// If the file does exist, it'll be overwritten
let outputFileOptional = NSFileHandle(forWritingAtPath: outputFileName!)
if outputFileOptional? != nil {
outputFileHandle = outputFileOptional!
} else {
println("Unable to open output file.")
exit(EXIT_FAILURE)
}
} else {
println("Unable to read output file name.")
exit(EXIT_FAILURE)
}
// Create a serial dispatch queue for writing on another thread
let queue = dispatch_queue_create("Writing queue", DISPATCH_QUEUE_SERIAL)
// Ok, now we know that we have good file handles for input and output
// We'll loop on the inputFileHandle getting 100MB at a time
var readLast = 0
var readTotal = 0
var writtenTotal: UInt64 = 0
do {
// Read 100MB
let inData = inputData.subdataWithRange(NSRange(location: readTotal, length: blockSize))
readLast = inData.length
readTotal += readLast
// Process the data
let outData = processBytes(inData)
// Write to outputFile
dispatch_async(queue, {
outputFileHandle.writeData(outData)
writtenTotal += outData.length
})
} while readLast > 0
// This will fire once file writing is finished
dispatch_barrier_sync(queue, {
// Discard anything after the write head, in case we're overwriting a file
outputFileHandle.truncateFileAtOffset(writtenTotal)
println("Processed \(readTotal) input bytes and wrote \(writtenTotal) bytes.")
// And, we're done here.
exit(EXIT_SUCCESS)})
println("Something strange has happened.")
exit(EXIT_FAILURE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment