Compare commits
	
		
			15 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9af15ed7a4 | |||
| 289d73c07e | |||
| 1be102a51c | |||
| 4446c24e07 | |||
| b56fd19a20 | |||
| 58e843f8aa | |||
| 005f102253 | |||
| 484e81e834 | |||
| e8778a51aa | |||
| 180b94ab7c | |||
| 7cdc3856ba | |||
| 9ce8a22a29 | |||
| ce5910b8df | |||
| eae5465cd1 | |||
| 7d05aaf0d4 | 
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,8 @@ | ||||
| __pycache__ | ||||
| .bck | ||||
| out | ||||
| target | ||||
| build | ||||
| *~ | ||||
| *.swp | ||||
| *.old | ||||
|   | ||||
							
								
								
									
										24
									
								
								GLD_audio-algo-chunkware-test.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								GLD_audio-algo-chunkware-test.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| { | ||||
| 	"type":"BINARY", | ||||
| 	"sub-type":"TEST", | ||||
| 	"group-id":"com.atria-soft", | ||||
| 	"description":"Chunkware test unit", | ||||
| 	"license":"MPL-2", | ||||
| 	"license-file":"file://LICENSE", | ||||
| 	"maintainer":"file://authors.txt", | ||||
| 	"author":"file://authors.txt", | ||||
| 	"version":"file://version.txt", | ||||
| 	"code-quality":"MEDIUM", | ||||
| 	 | ||||
| 	"source": [ | ||||
| 		"test/main.cpp" | ||||
| 	], | ||||
| 	"compilation-version": { | ||||
| 		"c++": 2017 | ||||
| 	}, | ||||
| 	"dependency": [ | ||||
| 		"audio-algo-chunkware", | ||||
| 		"etk", | ||||
| 		"test-debug" | ||||
| 	] | ||||
| } | ||||
							
								
								
									
										42
									
								
								GLD_audio-algo-chunkware.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								GLD_audio-algo-chunkware.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| { | ||||
| 	"type":"LIBRARY", | ||||
| 	"group-id":"com.atria-soft", | ||||
| 	"description":"Chunkware algo", | ||||
| 	"license":"MPL-2", | ||||
| 	"license-file":"file://LICENSE", | ||||
| 	"maintainer":"file://authors.txt", | ||||
| 	"author":"file://authors.txt", | ||||
| 	"version":"file://version.txt", | ||||
| 	"code-quality":"MEDIUM", | ||||
| 	 | ||||
| 	"source": [ | ||||
| 		"audio/algo/chunkware/debug.cpp", | ||||
| 		"audio/algo/chunkware/Compressor.cpp", | ||||
| 		"audio/algo/chunkware/debug.cpp", | ||||
| 		"audio/algo/chunkware/EnvelopeDetector.cpp", | ||||
| 		"audio/algo/chunkware/AttRelEnvelope.cpp", | ||||
| 		"audio/algo/chunkware/Gate.cpp", | ||||
| 		"audio/algo/chunkware/GateRms.cpp", | ||||
| 		"audio/algo/chunkware/Limiter.cpp" | ||||
| 	], | ||||
| 	"header": [ | ||||
| 		"audio/algo/chunkware/Compressor.hpp", | ||||
| 		"audio/algo/chunkware/debug.hpp", | ||||
| 		"audio/algo/chunkware/EnvelopeDetector.hpp", | ||||
| 		"audio/algo/chunkware/AttRelEnvelope.hpp", | ||||
| 		"audio/algo/chunkware/Gate.hpp", | ||||
| 		"audio/algo/chunkware/GateRms.hpp", | ||||
| 		"audio/algo/chunkware/Gain.hpp", | ||||
| 		"audio/algo/chunkware/Limiter.hpp" | ||||
| 	], | ||||
| 	"path":[ | ||||
| 		"." | ||||
| 	], | ||||
| 	"compilation-version": { | ||||
| 		"c++": 2017 | ||||
| 	}, | ||||
| 	"dependency": [ | ||||
| 		"etk", | ||||
| 		"audio" | ||||
| 	] | ||||
| } | ||||
| @@ -24,7 +24,7 @@ | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <audio/algo/chunkware/AttRelEnvelope.h> | ||||
| #include <audio/algo/chunkware/AttRelEnvelope.hpp> | ||||
|  | ||||
| audio::algo::chunkware::AttRelEnvelope::AttRelEnvelope(double _attackms, double _releasems, double _sampleRate) : | ||||
|   m_attack(_attackms, _sampleRate), | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <audio/algo/chunkware/EnvelopeDetector.h> | ||||
| #include <audio/algo/chunkware/EnvelopeDetector.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -23,8 +23,8 @@ | ||||
|  * DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <audio/algo/chunkware/Compressor.h> | ||||
| #include <audio/algo/chunkware/debug.h> | ||||
| #include <audio/algo/chunkware/Compressor.hpp> | ||||
| #include <audio/algo/chunkware/debug.hpp> | ||||
| #include <cmath> | ||||
|  | ||||
| audio::algo::chunkware::Compressor::Compressor() : | ||||
| @@ -49,15 +49,15 @@ void audio::algo::chunkware::Compressor::init() { | ||||
| 	m_isConfigured = true; | ||||
| } | ||||
|  | ||||
| std::vector<enum audio::format> audio::algo::chunkware::Compressor::getSupportedFormat() { | ||||
| 	std::vector<enum audio::format> out = getNativeSupportedFormat(); | ||||
| 	out.push_back(audio::format_int16); | ||||
| etk::Vector<enum audio::format> audio::algo::chunkware::Compressor::getSupportedFormat() { | ||||
| 	etk::Vector<enum audio::format> out = getNativeSupportedFormat(); | ||||
| 	out.pushBack(audio::format_int16); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| std::vector<enum audio::format> audio::algo::chunkware::Compressor::getNativeSupportedFormat() { | ||||
| 	std::vector<enum audio::format> out; | ||||
| 	out.push_back(audio::format_double); | ||||
| etk::Vector<enum audio::format> audio::algo::chunkware::Compressor::getNativeSupportedFormat() { | ||||
| 	etk::Vector<enum audio::format> out; | ||||
| 	out.pushBack(audio::format_double); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| @@ -82,7 +82,7 @@ void audio::algo::chunkware::Compressor::process(void* _output, const void* _inp | ||||
| 					processDouble(vals, vals, _nbChannel); | ||||
| 					for (int8_t kkk=0; kkk<_nbChannel ; ++kkk) { | ||||
| 						vals[kkk] *= 32768.0; | ||||
| 						output[iii*_nbChannel+kkk] = int16_t(std::avg(-32768.0, vals[kkk], 32767.0)); | ||||
| 						output[iii*_nbChannel+kkk] = int16_t(etk::avg(-32768.0, vals[kkk], 32767.0)); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| @@ -108,8 +108,8 @@ void audio::algo::chunkware::Compressor::processDouble(double* _out, const doubl | ||||
| 	double keyLink = 0; | ||||
| 	// get greater value; | ||||
| 	for (int8_t iii=0; iii<_nbChannel; ++iii) { | ||||
| 		double absValue = std::abs(_in[iii]); | ||||
| 		keyLink = std::max(keyLink, absValue); | ||||
| 		double absValue = etk::abs(_in[iii]); | ||||
| 		keyLink = etk::max(keyLink, absValue); | ||||
| 	} | ||||
| 	processDouble(_out, _in, _nbChannel, keyLink); | ||||
| } | ||||
|   | ||||
| @@ -24,10 +24,10 @@ | ||||
|  */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <etk/types.h> | ||||
| #include <audio/format.h> | ||||
| #include <audio/algo/chunkware/AttRelEnvelope.h> | ||||
| #include <audio/algo/chunkware/Gain.h> | ||||
| #include <etk/types.hpp> | ||||
| #include <audio/format.hpp> | ||||
| #include <audio/algo/chunkware/AttRelEnvelope.hpp> | ||||
| #include <audio/algo/chunkware/Gain.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -47,12 +47,12 @@ namespace audio { | ||||
| 					 * @brief Get list of format suported in input. | ||||
| 					 * @return list of supported format | ||||
| 					 */ | ||||
| 					virtual std::vector<enum audio::format> getSupportedFormat(); | ||||
| 					virtual etk::Vector<enum audio::format> getSupportedFormat(); | ||||
| 					/**
 | ||||
| 					 * @brief Get list of algorithm format suported. No format convertion. | ||||
| 					 * @return list of supported format | ||||
| 					 */ | ||||
| 					virtual std::vector<enum audio::format> getNativeSupportedFormat(); | ||||
| 					virtual etk::Vector<enum audio::format> getNativeSupportedFormat(); | ||||
| 					/**
 | ||||
| 					 * @brief Main input algo process. | ||||
| 					 * @param[in,out] _output Output data. | ||||
| @@ -24,7 +24,7 @@ | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <audio/algo/chunkware/CompressorRms.h> | ||||
| #include <audio/algo/chunkware/CompressorRms.hpp> | ||||
|  | ||||
|  | ||||
| audio::algo::chunkware::CompressorRms::CompressorRms() : | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <audio/algo/chunkware/Compressor.h> | ||||
| #include <audio/algo/chunkware/Compressor.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -24,8 +24,8 @@ | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <audio/algo/chunkware/debug.h> | ||||
| #include <audio/algo/chunkware/EnvelopeDetector.h> | ||||
| #include <audio/algo/chunkware/debug.hpp> | ||||
| #include <audio/algo/chunkware/EnvelopeDetector.hpp> | ||||
|  | ||||
| audio::algo::chunkware::EnvelopeDetector::EnvelopeDetector(double _ms, double _sampleRate) { | ||||
| 	AA_CHUNK_ASSERT(_sampleRate > 0.0, "input function error"); | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <etk/types.h> | ||||
| #include <etk/types.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -24,7 +24,7 @@ | ||||
|  */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <etk/types.h> | ||||
| #include <etk/types.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -24,8 +24,8 @@ | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <audio/algo/chunkware/Gate.h> | ||||
| #include <audio/algo/chunkware/debug.h> | ||||
| #include <audio/algo/chunkware/Gate.hpp> | ||||
| #include <audio/algo/chunkware/debug.hpp> | ||||
| #include <cmath> | ||||
|  | ||||
| audio::algo::chunkware::Gate::Gate() : | ||||
| @@ -47,15 +47,15 @@ void audio::algo::chunkware::Gate::init() { | ||||
| 	m_isConfigured = true; | ||||
| } | ||||
|  | ||||
| std::vector<enum audio::format> audio::algo::chunkware::Gate::getSupportedFormat() { | ||||
| 	std::vector<enum audio::format> out = getNativeSupportedFormat(); | ||||
| 	out.push_back(audio::format_int16); | ||||
| etk::Vector<enum audio::format> audio::algo::chunkware::Gate::getSupportedFormat() { | ||||
| 	etk::Vector<enum audio::format> out = getNativeSupportedFormat(); | ||||
| 	out.pushBack(audio::format_int16); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| std::vector<enum audio::format> audio::algo::chunkware::Gate::getNativeSupportedFormat() { | ||||
| 	std::vector<enum audio::format> out; | ||||
| 	out.push_back(audio::format_double); | ||||
| etk::Vector<enum audio::format> audio::algo::chunkware::Gate::getNativeSupportedFormat() { | ||||
| 	etk::Vector<enum audio::format> out; | ||||
| 	out.pushBack(audio::format_double); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| @@ -77,7 +77,7 @@ void audio::algo::chunkware::Gate::process(void* _output, const void* _input, si | ||||
| 					processDouble(vals, vals, _nbChannel); | ||||
| 					for (int8_t kkk=0; kkk<_nbChannel ; ++kkk) { | ||||
| 						vals[kkk] *= 32768.0; | ||||
| 						output[iii*_nbChannel+kkk] = int16_t(std::avg(-32768.0, vals[kkk], 32767.0)); | ||||
| 						output[iii*_nbChannel+kkk] = int16_t(etk::avg(-32768.0, vals[kkk], 32767.0)); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| @@ -103,8 +103,8 @@ void audio::algo::chunkware::Gate::processDouble(double* _out, const double* _in | ||||
| 	double keyLink = 0; | ||||
| 	// get greater value; | ||||
| 	for (int8_t iii=0; iii<_nbChannel; ++iii) { | ||||
| 		double absValue = std::abs(_in[iii]); | ||||
| 		keyLink = std::max(keyLink, absValue); | ||||
| 		double absValue = etk::abs(_in[iii]); | ||||
| 		keyLink = etk::max(keyLink, absValue); | ||||
| 	} | ||||
| 	processDouble(_out, _in, _nbChannel, keyLink); | ||||
| } | ||||
|   | ||||
| @@ -24,10 +24,10 @@ | ||||
|  */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <etk/types.h> | ||||
| #include <audio/algo/chunkware/AttRelEnvelope.h> | ||||
| #include <audio/algo/chunkware/Gain.h> | ||||
| #include <audio/format.h> | ||||
| #include <etk/types.hpp> | ||||
| #include <audio/algo/chunkware/AttRelEnvelope.hpp> | ||||
| #include <audio/algo/chunkware/Gain.hpp> | ||||
| #include <audio/format.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -47,12 +47,12 @@ namespace audio { | ||||
| 					 * @brief Get list of format suported in input. | ||||
| 					 * @return list of supported format | ||||
| 					 */ | ||||
| 					virtual std::vector<enum audio::format> getSupportedFormat(); | ||||
| 					virtual etk::Vector<enum audio::format> getSupportedFormat(); | ||||
| 					/**
 | ||||
| 					 * @brief Get list of algorithm format suported. No format convertion. | ||||
| 					 * @return list of supported format | ||||
| 					 */ | ||||
| 					virtual std::vector<enum audio::format> getNativeSupportedFormat(); | ||||
| 					virtual etk::Vector<enum audio::format> getNativeSupportedFormat(); | ||||
| 					/**
 | ||||
| 					 * @brief Main input algo process. | ||||
| 					 * @param[in,out] _output Output data. | ||||
| @@ -24,7 +24,7 @@ | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <audio/algo/chunkware/GateRms.h> | ||||
| #include <audio/algo/chunkware/GateRms.hpp> | ||||
|  | ||||
| audio::algo::chunkware::GateRms::GateRms() : | ||||
|   m_averager(5.0), | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <audio/algo/chunkware/Gate.h> | ||||
| #include <audio/algo/chunkware/Gate.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -24,8 +24,8 @@ | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <audio/algo/chunkware/Limiter.h> | ||||
| #include <audio/algo/chunkware/debug.h> | ||||
| #include <audio/algo/chunkware/Limiter.hpp> | ||||
| #include <audio/algo/chunkware/debug.hpp> | ||||
| #include <cmath> | ||||
|  | ||||
| audio::algo::chunkware::Limiter::Limiter() : | ||||
| @@ -74,25 +74,24 @@ void audio::algo::chunkware::Limiter::init(int8_t _nbChannel) { | ||||
| 	m_outputBuffer.resize(_nbChannel); | ||||
| 	for (int8_t iii=0; iii<_nbChannel; ++iii) { | ||||
| 		m_outputBuffer[iii].resize(BUFFER_SIZE, 0.0); | ||||
| 		m_outputBuffer[iii].assign(BUFFER_SIZE, 0.0); | ||||
| 	} | ||||
| 	m_isConfigured = true; | ||||
| } | ||||
|  | ||||
| void audio::algo::chunkware::FastEnvelope::setCoef() { | ||||
| 	// rises to 99% of in value over duration of time constant | ||||
| 	m_coefficient = std::pow(0.01, (1000.0 / (m_timeMs * m_sampleRate))); | ||||
| 	m_coefficient = etk::pow(0.01, (1000.0 / (m_timeMs * m_sampleRate))); | ||||
| } | ||||
|  | ||||
| std::vector<enum audio::format> audio::algo::chunkware::Limiter::getSupportedFormat() { | ||||
| 	std::vector<enum audio::format> out = getNativeSupportedFormat(); | ||||
| 	out.push_back(audio::format_int16); | ||||
| etk::Vector<enum audio::format> audio::algo::chunkware::Limiter::getSupportedFormat() { | ||||
| 	etk::Vector<enum audio::format> out = getNativeSupportedFormat(); | ||||
| 	out.pushBack(audio::format_int16); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| std::vector<enum audio::format> audio::algo::chunkware::Limiter::getNativeSupportedFormat() { | ||||
| 	std::vector<enum audio::format> out; | ||||
| 	out.push_back(audio::format_double); | ||||
| etk::Vector<enum audio::format> audio::algo::chunkware::Limiter::getNativeSupportedFormat() { | ||||
| 	etk::Vector<enum audio::format> out; | ||||
| 	out.pushBack(audio::format_double); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| @@ -117,7 +116,7 @@ void audio::algo::chunkware::Limiter::process(void* _output, const void* _input, | ||||
| 					processDouble(vals, vals, _nbChannel); | ||||
| 					for (int8_t kkk=0; kkk<_nbChannel ; ++kkk) { | ||||
| 						vals[kkk] *= 32768.0; | ||||
| 						output[iii*_nbChannel+kkk] = int16_t(std::avg(-32768.0, vals[kkk], 32767.0)); | ||||
| 						output[iii*_nbChannel+kkk] = int16_t(etk::avg(-32768.0, vals[kkk], 32767.0)); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| @@ -142,8 +141,8 @@ void audio::algo::chunkware::Limiter::processDouble(double* _out, const double* | ||||
| 	double keyLink = 0; | ||||
| 	// get greater value; | ||||
| 	for (int8_t iii=0; iii<_nbChannel; ++iii) { | ||||
| 		double absValue = std::abs(_in[iii]); | ||||
| 		keyLink = std::max(keyLink, absValue); | ||||
| 		double absValue = etk::abs(_in[iii]); | ||||
| 		keyLink = etk::max(keyLink, absValue); | ||||
| 	} | ||||
| 	// we always want to feed the sidechain AT LEATS the threshold value | ||||
| 	if (keyLink < m_threshold) { | ||||
|   | ||||
| @@ -24,12 +24,12 @@ | ||||
|  */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <etk/types.h> | ||||
| #include <audio/format.h> | ||||
| #include <audio/algo/chunkware/AttRelEnvelope.h> | ||||
| #include <audio/algo/chunkware/Gain.h> | ||||
| #include <chrono> | ||||
| #include <vector> | ||||
| #include <etk/types.hpp> | ||||
| #include <audio/format.hpp> | ||||
| #include <audio/algo/chunkware/AttRelEnvelope.hpp> | ||||
| #include <audio/algo/chunkware/Gain.hpp> | ||||
| #include <echrono/Steady.hpp> | ||||
| #include <etk/Vector.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -63,12 +63,12 @@ namespace audio { | ||||
| 					 * @brief Get list of format suported in input. | ||||
| 					 * @return list of supported format | ||||
| 					 */ | ||||
| 					virtual std::vector<enum audio::format> getSupportedFormat(); | ||||
| 					virtual etk::Vector<enum audio::format> getSupportedFormat(); | ||||
| 					/**
 | ||||
| 					 * @brief Get list of algorithm format suported. No format convertion. | ||||
| 					 * @return list of supported format | ||||
| 					 */ | ||||
| 					virtual std::vector<enum audio::format> getNativeSupportedFormat(); | ||||
| 					virtual etk::Vector<enum audio::format> getNativeSupportedFormat(); | ||||
| 					/**
 | ||||
| 					 * @brief Main input algo process. | ||||
| 					 * @param[in,out] _output Output data. | ||||
| @@ -97,7 +97,7 @@ namespace audio { | ||||
| 					} | ||||
| 				 | ||||
| 				protected: | ||||
| 					std::chrono::microseconds m_attackTime; //!< attaque time in ms.
 | ||||
| 					echrono::microseconds m_attackTime; //!< attaque time in ms.
 | ||||
| 				public: | ||||
| 					virtual void setAttack(double _ms); | ||||
| 					virtual double getAttack() const { | ||||
| @@ -105,7 +105,7 @@ namespace audio { | ||||
| 					} | ||||
| 				 | ||||
| 				protected: | ||||
| 					std::chrono::microseconds m_releaseTime; //!< attaque time in ms.
 | ||||
| 					echrono::microseconds m_releaseTime; //!< attaque time in ms.
 | ||||
| 				public: | ||||
| 					virtual void setRelease(double _ms); | ||||
| 					virtual double getRelease() const { | ||||
| @@ -150,7 +150,7 @@ namespace audio { | ||||
| 					static const int BUFFER_SIZE = 1024; //!< buffer size (always a power of 2!)
 | ||||
| 					uint32_t m_bufferMask; //!< buffer mask
 | ||||
| 					uint32_t m_cursor; //!< cursor
 | ||||
| 					std::vector<std::vector<double> > m_outputBuffer; //!< output buffer
 | ||||
| 					etk::Vector<etk::Vector<double> > m_outputBuffer; //!< output buffer
 | ||||
| 			}; | ||||
| 		} | ||||
| 	} | ||||
| @@ -23,7 +23,7 @@ | ||||
|  * DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include "debug.h" | ||||
| #include "debug.hpp" | ||||
|  | ||||
|  | ||||
| int32_t audio::algo::chunkware::getLogId() { | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <elog/log.h> | ||||
| #include <elog/log.hpp> | ||||
| 
 | ||||
| namespace audio { | ||||
| 	namespace algo { | ||||
| @@ -1,43 +0,0 @@ | ||||
| #!/usr/bin/python | ||||
| import lutin.module as module | ||||
| import lutin.tools as tools | ||||
| import lutin.debug as debug | ||||
|  | ||||
|  | ||||
| def get_type(): | ||||
| 	return "BINARY" | ||||
|  | ||||
| def get_sub_type(): | ||||
| 	return "TEST" | ||||
|  | ||||
| def get_desc(): | ||||
| 	return "test chunkware" | ||||
|  | ||||
| def get_licence(): | ||||
| 	return "APACHE-2" | ||||
|  | ||||
| def get_compagny_type(): | ||||
| 	return "com" | ||||
|  | ||||
| def get_compagny_name(): | ||||
| 	return "atria-soft" | ||||
|  | ||||
| def get_maintainer(): | ||||
| 	return "authors.txt" | ||||
|  | ||||
| def create(target, module_name): | ||||
| 	my_module = module.Module(__file__, module_name, get_type()) | ||||
| 	my_module.add_src_file([ | ||||
| 		'test/main.cpp' | ||||
| 		]) | ||||
| 	my_module.add_depend(['audio-algo-chunkware', 'test-debug']) | ||||
| 	return my_module | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -1,61 +0,0 @@ | ||||
| #!/usr/bin/python | ||||
| import lutin.module as module | ||||
| import lutin.tools as tools | ||||
| import lutin.debug as debug | ||||
|  | ||||
|  | ||||
| def get_type(): | ||||
| 	return "LIBRARY" | ||||
|  | ||||
| def get_desc(): | ||||
| 	return "chunkware algo" | ||||
|  | ||||
| def get_licence(): | ||||
| 	return "BSD-2" | ||||
|  | ||||
| def get_compagny_type(): | ||||
| 	return "com" | ||||
|  | ||||
| def get_compagny_name(): | ||||
| 	return "atria-soft" | ||||
|  | ||||
| def get_maintainer(): | ||||
| 	return "authors.txt" | ||||
|  | ||||
| def get_version(): | ||||
| 	return "version.txt" | ||||
|  | ||||
| def create(target, module_name): | ||||
| 	my_module = module.Module(__file__, module_name, get_type()) | ||||
| 	my_module.add_src_file([ | ||||
| 		'audio/algo/chunkware/debug.cpp', | ||||
| 		'audio/algo/chunkware/Compressor.cpp', | ||||
| 		'audio/algo/chunkware/debug.cpp', | ||||
| 		'audio/algo/chunkware/EnvelopeDetector.cpp', | ||||
| 		'audio/algo/chunkware/AttRelEnvelope.cpp', | ||||
| 		'audio/algo/chunkware/Gate.cpp', | ||||
| 		'audio/algo/chunkware/GateRms.cpp', | ||||
| 		'audio/algo/chunkware/Limiter.cpp' | ||||
| 		]) | ||||
| 	my_module.add_header_file([ | ||||
| 		'audio/algo/chunkware/Compressor.h', | ||||
| 		'audio/algo/chunkware/debug.h', | ||||
| 		'audio/algo/chunkware/EnvelopeDetector.h', | ||||
| 		'audio/algo/chunkware/AttRelEnvelope.h', | ||||
| 		'audio/algo/chunkware/Gate.h', | ||||
| 		'audio/algo/chunkware/GateRms.h', | ||||
| 		'audio/algo/chunkware/Gain.h', | ||||
| 		'audio/algo/chunkware/Limiter.h' | ||||
| 		]) | ||||
| 	my_module.add_depend(['etk', 'audio']) | ||||
| 	my_module.add_path(tools.get_current_path(__file__)) | ||||
| 	return my_module | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										165
									
								
								test/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										165
									
								
								test/main.cpp
									
									
									
									
									
								
							| @@ -1,21 +1,26 @@ | ||||
| /** @file | ||||
|  * @author Edouard DUPIN  | ||||
|  * @copyright 2015, Edouard DUPIN, all right reserved | ||||
|  * @license APACHE v2.0 (see license file) | ||||
|  * @license MPL v2.0 (see license file) | ||||
|  */ | ||||
|  | ||||
| #include <test-debug/debug.h> | ||||
| #include <etk/etk.h> | ||||
| #include <audio/algo/chunkware/Compressor.h> | ||||
| #include <audio/algo/chunkware/Limiter.h> | ||||
| #include <audio/algo/chunkware/Gate.h> | ||||
| #include <etk/os/FSNode.h> | ||||
| #include <chrono> | ||||
| #include <test-debug/debug.hpp> | ||||
| #include <etk/etk.hpp> | ||||
| #include <audio/algo/chunkware/Compressor.hpp> | ||||
| #include <audio/algo/chunkware/Limiter.hpp> | ||||
| #include <audio/algo/chunkware/Gate.hpp> | ||||
| #include <ememory/SharedPtr.hpp> | ||||
| #include <etk/io/Interface.hpp> | ||||
| #include <etk/path/Path.hpp> | ||||
| #include <etk/uri/uri.hpp> | ||||
| #include <echrono/Steady.hpp> | ||||
| #include <ethread/Thread.hpp> | ||||
| #include <ethread/tools.hpp> | ||||
|  | ||||
| #include <unistd.h> | ||||
|  | ||||
| static std::vector<double> convert(const std::vector<int16_t>& _data) { | ||||
| 	std::vector<double> out; | ||||
|  | ||||
| static etk::Vector<double> convert(const etk::Vector<int16_t>& _data) { | ||||
| 	etk::Vector<double> out; | ||||
| 	out.resize(_data.size(), 0.0); | ||||
| 	for (size_t iii=0; iii<_data.size(); ++iii) { | ||||
| 		out[iii] = _data[iii]; | ||||
| @@ -26,11 +31,11 @@ static std::vector<double> convert(const std::vector<int16_t>& _data) { | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| static std::vector<int16_t> convert(const std::vector<double>& _data) { | ||||
| 	std::vector<int16_t> out; | ||||
| static etk::Vector<int16_t> convert(const etk::Vector<double>& _data) { | ||||
| 	etk::Vector<int16_t> out; | ||||
| 	out.resize(_data.size(), 0.0); | ||||
| 	for (size_t iii=0; iii<_data.size(); ++iii) { | ||||
| 		out[iii] = int16_t(std::avg(-32768.0, _data[iii]*32768.0, 32767.0)); | ||||
| 		out[iii] = int16_t(etk::avg(-32768.0, _data[iii]*32768.0, 32767.0)); | ||||
| 	} | ||||
| 	return out; | ||||
| } | ||||
| @@ -38,40 +43,40 @@ static std::vector<int16_t> convert(const std::vector<double>& _data) { | ||||
|  | ||||
| class Performance { | ||||
| 	private: | ||||
| 		std::chrono::steady_clock::time_point m_timeStart; | ||||
| 		std::chrono::steady_clock::time_point m_timeStop; | ||||
| 		std::chrono::nanoseconds m_totalTimeProcessing; | ||||
| 		std::chrono::nanoseconds m_minProcessing; | ||||
| 		std::chrono::nanoseconds m_maxProcessing; | ||||
| 		echrono::Steady m_timeStart; | ||||
| 		echrono::Steady m_timeStop; | ||||
| 		echrono::Duration m_totalTimeProcessing; | ||||
| 		echrono::Duration m_minProcessing; | ||||
| 		echrono::Duration m_maxProcessing; | ||||
| 		int32_t m_totalIteration; | ||||
| 	public: | ||||
| 		Performance() : | ||||
| 		  m_totalTimeProcessing(0), | ||||
| 		  m_minProcessing(99999999999999LL), | ||||
| 		  m_minProcessing(int64_t(99999999999999LL)), | ||||
| 		  m_maxProcessing(0), | ||||
| 		  m_totalIteration(0) { | ||||
| 			 | ||||
| 		} | ||||
| 		void tic() { | ||||
| 			m_timeStart = std::chrono::steady_clock::now(); | ||||
| 			m_timeStart = echrono::Steady::now(); | ||||
| 		} | ||||
| 		void toc() { | ||||
| 			m_timeStop = std::chrono::steady_clock::now(); | ||||
| 			std::chrono::nanoseconds time = m_timeStop - m_timeStart; | ||||
| 			m_minProcessing = std::min(m_minProcessing, time); | ||||
| 			m_maxProcessing = std::max(m_maxProcessing, time); | ||||
| 			m_timeStop = echrono::Steady::now(); | ||||
| 			echrono::Duration time = m_timeStop - m_timeStart; | ||||
| 			m_minProcessing = etk::min(m_minProcessing, time); | ||||
| 			m_maxProcessing = etk::max(m_maxProcessing, time); | ||||
| 			m_totalTimeProcessing += time; | ||||
| 			m_totalIteration++; | ||||
| 			 | ||||
| 		} | ||||
| 		 | ||||
| 		std::chrono::nanoseconds getTotalTimeProcessing() { | ||||
| 		echrono::Duration getTotalTimeProcessing() { | ||||
| 			return m_totalTimeProcessing; | ||||
| 		} | ||||
| 		std::chrono::nanoseconds getMinProcessing() { | ||||
| 		echrono::Duration getMinProcessing() { | ||||
| 			return m_minProcessing; | ||||
| 		} | ||||
| 		std::chrono::nanoseconds getMaxProcessing() { | ||||
| 		echrono::Duration getMaxProcessing() { | ||||
| 			return m_maxProcessing; | ||||
| 		} | ||||
| 		int32_t getTotalIteration() { | ||||
| @@ -81,15 +86,15 @@ class Performance { | ||||
| }; | ||||
|  | ||||
| void performanceCompressor() { | ||||
| 	std::vector<double> input; | ||||
| 	etk::Vector<double> input; | ||||
| 	input.resize(8192, 0); | ||||
| 	std::vector<double> output; | ||||
| 	etk::Vector<double> output; | ||||
| 	output.resize(8192, 0); | ||||
| 	double sampleRate = 48000.0; | ||||
| 	{ | ||||
| 		double phase = 0; | ||||
| 		double baseCycle = 2.0*M_PI/sampleRate * 1280.0; | ||||
| 		for (int32_t iii=0; iii<input.size(); iii++) { | ||||
| 		for (size_t iii=0; iii<input.size(); iii++) { | ||||
| 			input[iii] = cos(phase) * 5.0; | ||||
| 			phase += baseCycle; | ||||
| 			if (phase >= 2*M_PI) { | ||||
| @@ -107,28 +112,28 @@ void performanceCompressor() { | ||||
| 		perfo.tic(); | ||||
| 		algo.process(&output[0], &input[0], input.size(), 1, audio::format_double); | ||||
| 		perfo.toc(); | ||||
| 		usleep(1000); | ||||
| 		ethread::sleepMilliSeconds((1)); | ||||
| 	} | ||||
| 	TEST_PRINT("Performance Compressor (double): "); | ||||
| 	TEST_PRINT("    blockSize=" << input.size() << " sample"); | ||||
| 	TEST_PRINT("    min < avg < max =" << perfo.getMinProcessing().count() << "ns < " | ||||
| 	                                   << perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << "ns < " | ||||
| 	                                   << perfo.getMaxProcessing().count() << "ns "); | ||||
| 	TEST_PRINT("    min < avg < max= " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                   << (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                   << (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%"); | ||||
| 	TEST_PRINT("    min < avg < max =" << perfo.getMinProcessing() << " < " | ||||
| 	                                   << perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration() << "ns < " | ||||
| 	                                   << perfo.getMaxProcessing()); | ||||
| 	TEST_PRINT("    min < avg < max= " << (float((perfo.getMinProcessing().get()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                   << (float(((perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                   << (float((perfo.getMaxProcessing().get()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%"); | ||||
| } | ||||
|  | ||||
| void performanceLimiter() { | ||||
| 	std::vector<double> input; | ||||
| 	etk::Vector<double> input; | ||||
| 	input.resize(8192, 0); | ||||
| 	std::vector<double> output; | ||||
| 	etk::Vector<double> output; | ||||
| 	output.resize(8192, 0); | ||||
| 	double sampleRate = 48000.0; | ||||
| 	{ | ||||
| 		double phase = 0; | ||||
| 		double baseCycle = 2.0*M_PI/sampleRate * 1280.0; | ||||
| 		for (int32_t iii=0; iii<input.size(); iii++) { | ||||
| 		for (size_t iii=0; iii<input.size(); iii++) { | ||||
| 			input[iii] = cos(phase) * 5.0; | ||||
| 			phase += baseCycle; | ||||
| 			if (phase >= 2*M_PI) { | ||||
| @@ -148,28 +153,28 @@ void performanceLimiter() { | ||||
| 		perfo.tic(); | ||||
| 		algo.process(&output[0], &input[0], input.size(), 1, audio::format_double); | ||||
| 		perfo.toc(); | ||||
| 		usleep(1000); | ||||
| 		ethread::sleepMilliSeconds((1)); | ||||
| 	} | ||||
| 	TEST_PRINT("Performance Limiter (double): "); | ||||
| 	TEST_PRINT("    blockSize=" << input.size() << " sample"); | ||||
| 	TEST_PRINT("    min < avg < max =" << perfo.getMinProcessing().count() << "ns < " | ||||
| 	                                   << perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << "ns < " | ||||
| 	                                   << perfo.getMaxProcessing().count() << "ns "); | ||||
| 	TEST_PRINT("    min < avg < max = " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                    << (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                    << (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%"); | ||||
| 	TEST_PRINT("    min < avg < max =" << perfo.getMinProcessing() << " < " | ||||
| 	                                   << perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration() << "ns < " | ||||
| 	                                   << perfo.getMaxProcessing()); | ||||
| 	TEST_PRINT("    min < avg < max = " << (float((perfo.getMinProcessing().get()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                    << (float(((perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                    << (float((perfo.getMaxProcessing().get()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%"); | ||||
| } | ||||
|  | ||||
| void performanceGate() { | ||||
| 	std::vector<double> input; | ||||
| 	etk::Vector<double> input; | ||||
| 	input.resize(8192, 0); | ||||
| 	std::vector<double> output; | ||||
| 	etk::Vector<double> output; | ||||
| 	output.resize(8192, 0); | ||||
| 	double sampleRate = 48000.0; | ||||
| 	{ | ||||
| 		double phase = 0; | ||||
| 		double baseCycle = 2.0*M_PI/sampleRate * 1280.0; | ||||
| 		for (int32_t iii=0; iii<input.size(); iii++) { | ||||
| 		for (size_t iii=0; iii<input.size(); iii++) { | ||||
| 			input[iii] = cos(phase) * 5.0; | ||||
| 			phase += baseCycle; | ||||
| 			if (phase >= 2*M_PI) { | ||||
| @@ -189,16 +194,16 @@ void performanceGate() { | ||||
| 		perfo.tic(); | ||||
| 		algo.process(&output[0], &input[0], input.size(), 1, audio::format_double); | ||||
| 		perfo.toc(); | ||||
| 		usleep(1000); | ||||
| 		ethread::sleepMilliSeconds((1)); | ||||
| 	} | ||||
| 	TEST_PRINT("Performance Gate (double): "); | ||||
| 	TEST_PRINT("    blockSize=" << input.size() << " sample"); | ||||
| 	TEST_PRINT("    min < avg < max =" << perfo.getMinProcessing().count() << "ns < " | ||||
| 	                                   << perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << "ns < " | ||||
| 	                                   << perfo.getMaxProcessing().count() << "ns "); | ||||
| 	TEST_PRINT("    min < avg < max = " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                    << (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                    << (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%"); | ||||
| 	TEST_PRINT("    min < avg < max =" << perfo.getMinProcessing() << " < " | ||||
| 	                                   << perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration() << "ns < " | ||||
| 	                                   << perfo.getMaxProcessing()); | ||||
| 	TEST_PRINT("    min < avg < max = " << (float((perfo.getMinProcessing().get()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                    << (float(((perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < " | ||||
| 	                                    << (float((perfo.getMaxProcessing().get()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%"); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -207,12 +212,12 @@ void performanceGate() { | ||||
| int main(int _argc, const char** _argv) { | ||||
| 	// the only one init for etk: | ||||
| 	etk::init(_argc, _argv); | ||||
| 	std::string inputName = ""; | ||||
| 	etk::Path inputName = ""; | ||||
| 	bool performance = false; | ||||
| 	bool perf = false; | ||||
| 	int64_t sampleRate = 48000; | ||||
| 	for (int32_t iii=0; iii<_argc ; ++iii) { | ||||
| 		std::string data = _argv[iii]; | ||||
| 		etk::String data = _argv[iii]; | ||||
| 		if (etk::start_with(data,"--in=")) { | ||||
| 			inputName = &data[5]; | ||||
| 		} else if (data == "--performance") { | ||||
| @@ -240,15 +245,23 @@ int main(int _argc, const char** _argv) { | ||||
| 		performanceGate(); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (inputName == "") { | ||||
| 	if (inputName.isEmpty() == true) { | ||||
| 		TEST_ERROR("Can not Process missing parameters..."); | ||||
| 		exit(-1); | ||||
| 	} | ||||
| 	TEST_INFO("Read input:"); | ||||
| 	std::vector<double> inputData = convert(etk::FSNodeReadAllDataType<int16_t>(inputName)); | ||||
| 	etk::Vector<int16_t> tmpData; | ||||
| 	{ | ||||
| 		ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(inputName); | ||||
| 		fileIO->open(etk::io::OpenMode::Read); | ||||
| 		tmpData = fileIO->readAll<int16_t>(); | ||||
| 		fileIO->close(); | ||||
| 	} | ||||
| 	 | ||||
| 	etk::Vector<double> inputData = convert(tmpData); | ||||
| 	TEST_INFO("    " << inputData.size() << " samples"); | ||||
| 	// resize output : | ||||
| 	std::vector<double> output; | ||||
| 	etk::Vector<double> output; | ||||
| 	output.resize(inputData.size(), 0); | ||||
| 	// process in chunk of 256 samples | ||||
| 	int32_t blockSize = 256; | ||||
| @@ -270,7 +283,7 @@ int main(int _argc, const char** _argv) { | ||||
| 		algo.process(audio::format_double, &output[iii*blockSize], &inputData[iii*blockSize], blockSize, 1); | ||||
| 		if (perf == true) { | ||||
| 			perfo.toc(); | ||||
| 			usleep(1000); | ||||
| 			ethread::sleepMilliSeconds((1)); | ||||
| 		} | ||||
| 	} | ||||
| 	*/ | ||||
| @@ -292,7 +305,7 @@ int main(int _argc, const char** _argv) { | ||||
| 		algo.process(&output[iii*blockSize], &inputData[iii*blockSize], blockSize, 1, audio::format_double); | ||||
| 		if (perf == true) { | ||||
| 			perfo.toc(); | ||||
| 			usleep(1000); | ||||
| 			ethread::sleepMilliSeconds((1)); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| @@ -300,15 +313,23 @@ int main(int _argc, const char** _argv) { | ||||
| 	if (perf == true) { | ||||
| 		TEST_INFO("Performance Result: "); | ||||
| 		TEST_INFO("    blockSize=" << blockSize << " sample"); | ||||
| 		TEST_INFO("    min=" << perfo.getMinProcessing().count() << " ns"); | ||||
| 		TEST_INFO("    max=" << perfo.getMaxProcessing().count() << " ns"); | ||||
| 		TEST_INFO("    avg=" << perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << " ns"); | ||||
| 		TEST_INFO("    min=" << perfo.getMinProcessing()); | ||||
| 		TEST_INFO("    max=" << perfo.getMaxProcessing()); | ||||
| 		TEST_INFO("    avg=" << perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration() << " ns"); | ||||
| 		 | ||||
| 		TEST_INFO("    min=" << (float((perfo.getMinProcessing().count()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %"); | ||||
| 		TEST_INFO("    max=" << (float((perfo.getMaxProcessing().count()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %"); | ||||
| 		TEST_INFO("    avg=" << (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/blockSize)/1000000000.0)*100.0 << " %"); | ||||
| 		TEST_INFO("    min=" << (float((perfo.getMinProcessing().get()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %"); | ||||
| 		TEST_INFO("    max=" << (float((perfo.getMaxProcessing().get()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %"); | ||||
| 		TEST_INFO("    avg=" << (float(((perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration())*sampleRate)/blockSize)/1000000000.0)*100.0 << " %"); | ||||
| 	} | ||||
| 	etk::FSNodeWriteAllDataType<int16_t>("output.raw", convert(output)); | ||||
| 	{ | ||||
| 		ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(etk::Path("output.raw")); | ||||
| 		if (fileIO->open(etk::io::OpenMode::Write) == false) { | ||||
| 			return -1; | ||||
| 		} | ||||
| 		fileIO->writeAll<double>(output); | ||||
| 		fileIO->close(); | ||||
| 	} | ||||
| 	return 0; | ||||
| 	 | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| 0.1.1 | ||||
| 1.0.0-dev | ||||
		Reference in New Issue
	
	Block a user