-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit of Ripple-To-FLAC conversion code.
- Loading branch information
0 parents
commit e5bc131
Showing
18 changed files
with
1,337 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
#include "Config.h" | ||
|
||
|
||
Config::Config(void) : valid(false), desc("Convert a Ripple NSx file to FLAC") { | ||
desc.add_options() | ||
("help", "Show this help message") | ||
("input-file,i", | ||
opts::value<std::string>(), | ||
"NSx file to convert") | ||
("output-dir,o", | ||
opts::value<std::string>()->default_value("./"), | ||
"Place the converted FLAC files in this directory") | ||
("output-prefix", | ||
opts::value<std::string>()->default_value("ch"), | ||
"The converted FLAC filenames start with this, followed by the channel number") | ||
("threads", | ||
opts::value<unsigned>()->default_value(1), | ||
"Number of threads to use for compression") | ||
("read-size", | ||
opts::value<unsigned>()->default_value(60000), | ||
"Maximum number of samples to read at once") | ||
("flac-compression", | ||
opts::value<unsigned>()->default_value(8), | ||
"FLAC compression level") | ||
; | ||
|
||
|
||
pos.add("input-file", 1); | ||
pos.add("output-dir", 2); | ||
pos.add("output-prefix", 3); | ||
} | ||
|
||
unsigned int Config::nThreads(void) const { | ||
if(valid) | ||
return _nThreads; | ||
else | ||
throw(std::runtime_error("Options not initalized")); | ||
} | ||
|
||
unsigned int Config::readSize(void) const { | ||
if(valid) | ||
return _readSize; | ||
else | ||
throw(std::runtime_error("Options not initalized")); | ||
} | ||
|
||
unsigned int Config::flacCompression(void) const { | ||
if(valid) | ||
return _flacCompression; | ||
else | ||
throw(std::runtime_error("Options not initalized")); | ||
} | ||
|
||
std::string Config::inputFile(void) const { | ||
if(valid) | ||
return _inputFile; | ||
else | ||
throw(std::runtime_error("Options not initalized")); | ||
} | ||
|
||
std::string Config::outputDir(void) const { | ||
if(valid) | ||
return _outputDir; | ||
else | ||
throw(std::runtime_error("Options not initalized")); | ||
} | ||
|
||
std::string Config::outputPrefix(void) const { | ||
if(valid) | ||
return _outputPrefix; | ||
else | ||
throw(std::runtime_error("Options not initalized")); | ||
} | ||
|
||
void Config::parse(int argc, char* argv[]) { | ||
|
||
opts::variables_map vm; | ||
opts::store(opts::command_line_parser(argc, argv). | ||
options(desc).positional(pos).run(), vm); | ||
|
||
if(vm.count("help") || argc==1) { | ||
std::cout << desc << std::endl; | ||
exit(0); | ||
} | ||
|
||
opts::notify(vm); | ||
|
||
// Check input file and return it if valid | ||
_inputFile = getInputFilename(vm); | ||
|
||
// Check output directory and return it if valid | ||
_outputDir = getOutputDir(vm); | ||
|
||
_outputPrefix = vm["output-prefix"].as<std::string>(); | ||
_nThreads = vm["threads"].as<unsigned>(); | ||
_readSize = vm["read-size"].as<unsigned>(); | ||
_flacCompression = vm["flac-compression"].as<unsigned>(); | ||
valid = true; | ||
} | ||
|
||
|
||
std::string Config::getInputFilename(const opts::variables_map& vm) { | ||
|
||
if(!vm.count("input-file")) { | ||
throw(std::runtime_error("No input file found!")); | ||
} else { | ||
|
||
std::string filename = vm["input-file"].as<std::string>(); | ||
fs::path inputPath(filename); | ||
if(fs::exists(inputPath)) { | ||
if(fs::is_regular_file(inputPath) || fs::is_symlink(inputPath)) { | ||
return filename; | ||
} else { | ||
throw(std::runtime_error("The input file is not a regular file")); | ||
} | ||
} else { | ||
throw(std::runtime_error("The input file does not exist")); | ||
} | ||
} | ||
} | ||
|
||
std::string Config::getOutputDir(const opts::variables_map& vm) { | ||
std::string filename = vm["output-dir"].as<std::string>(); | ||
outputPath = fs::path(filename); | ||
|
||
if(fs::exists(outputPath) && fs::is_regular_file(outputPath)) | ||
throw(std::runtime_error("Cannot create a directory with the same name as a file!")); | ||
|
||
fs::create_directories(outputPath); //Throws on failure, does nothing if exists | ||
return filename; | ||
} | ||
|
||
std::string Config::outputFilename(std::uint16_t electrode) const { | ||
std::ostringstream str; | ||
|
||
str << outputPrefix() << std::setfill('0') << std::setw(3) << electrode; | ||
str << ".flac"; | ||
std::string outfile = (outputPath / str.str()).string(); | ||
|
||
return(outfile); | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#ifndef __CONVERT_CONFIG__ | ||
#define __CONVERT_CONFIG__ | ||
|
||
#include <exception> | ||
#include <iostream> | ||
#include <iomanip> | ||
#include <sstream> | ||
#include <string> | ||
|
||
#include <boost/program_options.hpp> | ||
#include <boost/filesystem.hpp> | ||
|
||
namespace opts = boost::program_options; | ||
namespace fs = boost::filesystem; | ||
|
||
class Config { | ||
|
||
public: | ||
Config(); | ||
void parse(int argc, char* argv[]); | ||
|
||
std::string inputFile(void) const; | ||
std::string outputDir(void) const; | ||
std::string outputPrefix(void) const; | ||
|
||
unsigned int nThreads(void) const; | ||
unsigned int readSize(void) const; | ||
unsigned int flacCompression(void) const; | ||
|
||
std::string outputFilename(std::uint16_t electrode) const; | ||
|
||
private: | ||
bool valid; | ||
|
||
std::string _inputFile; | ||
std::string _outputDir; | ||
std::string _outputPrefix; | ||
|
||
fs::path outputPath; | ||
unsigned _nThreads; | ||
unsigned _readSize; | ||
unsigned _flacCompression; | ||
|
||
opts::positional_options_description pos; | ||
opts::options_description desc; | ||
|
||
std::string getInputFilename(const opts::variables_map& vm); | ||
std::string getOutputDir(const opts::variables_map& vm); | ||
}; | ||
|
||
|
||
#endif /* __CONVERT_CONFIG__*/ |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
CC=g++ | ||
CFLAGS= -O3 -Wall -Werror -std=gnu++11 | ||
LIBS=-lFLAC++ -lboost_program_options -lboost_filesystem -lboost_system | ||
TARGET = rippleToFlac | ||
DEPS = NSxFile.h Config.h | ||
OBJ = Config.o NSxFile.o NSxChannel.o NSxHeader.o rippleToFlac.o | ||
|
||
|
||
%.o: %.cpp $(DEPS) | ||
$(CC) -c -o $@ $< $(CFLAGS) | ||
|
||
rippleToFlac: $(OBJ) | ||
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) | ||
|
||
.PHONY: clean | ||
clean: | ||
rm -f *.o *~ core |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
CC=i686-pc-mingw32-g++ | ||
CFLAGS= -O3 -Wall -Werror -std=gnu++11 | ||
LIBS=-logg -lFLAC -logg -lFLAC++ -logg -lFLAC -logg -lboost_program_options-mt -lboost_filesystem-mt -lboost_system-mt | ||
TARGET = rippleToFlac | ||
DEPS = NSxFile.h Config.h | ||
OBJ = Config.o NSxFile.o NSxChannel.o NSxHeader.o rippleToFlac.o | ||
|
||
|
||
%.o: %.cpp $(DEPS) | ||
$(CC) -c -o $@ $< $(CFLAGS) -DWINDOWS | ||
|
||
rippleToFlac.exe: $(OBJ) | ||
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) -static | ||
|
||
.PHONY: clean | ||
clean: | ||
rm -f *.o *~ core |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
NEVFile::NEVFile(std::string filename) { | ||
|
||
file.open(filename, std::ios_base::binary | std::ios_base::binary); | ||
file.exceptions(std::ifstream::failbit | std::ifstream::badbit); | ||
if(!file) { | ||
throw(std::runtime_error("Cannot open file for reading")); | ||
} | ||
|
||
/* Read the magic word to ensure this is the right kind of file*/ | ||
std::string typeString = "NEURALEV"; | ||
file.read | ||
|
||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef __NEVFile.h__ | ||
#define __NEVFile.h__ | ||
|
||
#include <cstdint> | ||
#include <ifstream> | ||
#include <stdexcept> | ||
#include <string> | ||
|
||
|
||
class NEVFile { | ||
public: | ||
NEVFile(std::string filename); | ||
|
||
|
||
protected: | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// | ||
// NSxChannel.cpp | ||
// dumpNEV | ||
// | ||
// Created by Matthew Krause on 2/23/15. | ||
// Copyright (c) 2015 Matthew Krause. All rights reserved. | ||
// | ||
|
||
#include "NSxChannel.h" | ||
|
||
NSxChannel::NSxChannel(std::ifstream &file) { | ||
std::streampos start= file.tellg(); | ||
|
||
try { | ||
char buffer[2]; | ||
file.read(buffer, 2); | ||
if((buffer[0] != 'C') || (buffer[1] != 'C')) { | ||
std::cerr << "Failed on filetype " << int(buffer[0]) << int(buffer[1]) << "@" << file.tellg() << std::endl; | ||
throw(std::runtime_error("Incorrect file type; expected a Ripple .ns5 (or other .nsX) file")); | ||
} | ||
|
||
file.read(reinterpret_cast<char *>(&electrodeID), sizeof(electrodeID)); | ||
file.read(reinterpret_cast<char *>(&electrodeLabel), sizeof(electrodeLabel)); | ||
file.read(reinterpret_cast<char *>(&frontEndID), sizeof(frontEndID)); | ||
file.read(reinterpret_cast<char *>(&pin), sizeof(pin)); | ||
file.read(reinterpret_cast<char *>(&maxDigital), sizeof(maxDigital)); | ||
file.read(reinterpret_cast<char *>(&minDigital), sizeof(minDigital)); | ||
file.read(reinterpret_cast<char *>(&minAnalog), sizeof(minAnalog)); | ||
file.read(reinterpret_cast<char *>(&maxAnalog), sizeof(maxAnalog)); | ||
file.read(reinterpret_cast<char *>(&unitLabel), sizeof(unitLabel)); | ||
file.read(reinterpret_cast<char *>(&highpass), sizeof(highpass)); | ||
file.read(reinterpret_cast<char *>(&lowpass), sizeof(lowpass)); | ||
} | ||
|
||
catch (...) { | ||
std::cerr << "Error at " << file.tellg() << std::endl; | ||
file.seekg(start); | ||
throw; | ||
} | ||
} | ||
|
||
|
||
std::string NSxChannel::rippleSpec() const { | ||
std::ostringstream s; | ||
|
||
char port = (frontEndID/4) + 'A'; | ||
unsigned frontEnd = unsigned(frontEndID % 4) + 1; | ||
|
||
s << char(port) << '-' << frontEnd << '-' << int(pin); | ||
return(s.str()); | ||
} | ||
|
||
|
||
std::ostream& operator<<(std::ostream& out, const NSxChannel& c) { | ||
out << "Electrode #" << c.electrodeID << " (" << c.electrodeLabel << "): " << c.rippleSpec() << std::endl; | ||
return out; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#ifndef ___NSxChannel_h__ | ||
#define ___NSxChannel_h__ | ||
|
||
#include <cstdint> | ||
#include <fstream> | ||
#include <stdexcept> | ||
#include <iostream> | ||
#include <sstream> | ||
|
||
|
||
enum FilterType : std::uint16_t {NONE = 0, BUTTERWORTH = 1, CHEBYSHEV = 2}; | ||
|
||
#pragma pack(push,1) | ||
struct Filter { | ||
std::uint32_t cornerFreq; | ||
std::uint32_t order; | ||
FilterType type; | ||
}; | ||
#pragma pack(pop) | ||
|
||
|
||
class NSxChannel { | ||
|
||
public: | ||
NSxChannel(); | ||
NSxChannel(std::ifstream &file); | ||
|
||
std::string rippleSpec() const; | ||
std::uint16_t getNumericID() const {return electrodeID;} | ||
|
||
friend std::ostream& operator<<(std::ostream& out, const NSxChannel& c); | ||
protected: | ||
std::uint16_t electrodeID; | ||
char electrodeLabel[16]; | ||
char unitLabel[16]; | ||
|
||
std::uint8_t frontEndID; | ||
std::uint8_t pin; | ||
|
||
std::int16_t minDigital; | ||
std::int16_t maxDigital; | ||
|
||
std::int16_t minAnalog; | ||
std::int16_t maxAnalog; | ||
|
||
Filter lowpass; | ||
Filter highpass; | ||
|
||
}; | ||
#endif /* ___NSxChannel_h__ */ |
Oops, something went wrong.