Last active
August 29, 2015 14:13
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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