diff --git a/doc/001_bases.bb b/doc/001_bases.bb new file mode 100644 index 0000000..e8a625e --- /dev/null +++ b/doc/001_bases.bb @@ -0,0 +1,41 @@ +=?=RIVER: Bases =?= +__________________________________________________ +[right][tutorial[000_Build | Next: Tutorals]][/right] + +=== Overview:=== + +===User requires:=== +To use ewol you need to know only C++ language. It could be usefull to know: +:** [b]Python[/b] for all build tool. +:** [b]git[/b] for all version management +:** [b]Audio[/b] Basic knowlege of audio streaming af data organisation. + +=== Architecture:=== +River has been designed to replace the pulseAudio basic asyncronous interface that create +more problem that it will solve. The second point is that is not enougth portable to be +embended in a proprietary software without distributing all the sources (Ios). + +Start at this point we will have simple objectives : +:** manage multiple Low level interface: (done by the [lib[airtaudio | AirTAudio]] interface): +::** for linux +:::** Alsa +:::** Pulse +:::** Oss +::** for Mac-OsX +:::** CoreAudio +::** for IOs +:::** CoreAudio (embended version) +::** for Windows +:::** ASIO +::** For Android +:::** Java (JDK-6) +:** Synchronous interface ==> no delay and reduce latency +:** Manage the thread priority (need sometimes to be more reactive) +:** manage mixing of some flow (2 inputs stereo and the user want 1 input quad) +:** AEC Acoustic Echo Cancelation (TODO : in the current implementation we have a simple sound cutter) +:** Equalizer (done with [lib[drain | Drain]) +:** Resmpling (done by the libspeexDSP) +:** Correct volume management (and configurable) +:** Fade-in and Fade-out (done with [lib[drain | Drain]) +:** Channel reorganisation (done with [lib[drain | Drain]) +:** A correct feedback interface diff --git a/doc/faq.bb b/doc/faq.bb new file mode 100644 index 0000000..4a76074 --- /dev/null +++ b/doc/faq.bb @@ -0,0 +1,36 @@ +=?= FAQ =?= + +== What is ewol licence == + +This is really simple : APACHE-2 : + +Copyright ewol Edouard DUPIN + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + [[http://www.apache.org/licenses/LICENSE-2.0]] + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + + +== Why we use "DECLARE_FACTORY" Macro ? == + +For some reason!!! But everything might be clear: +:** In ewol we masively use std::shared_ptr (I have create my own but it is not "standard" (I like when we use genecic system)). +:** The main class : [class[ewol::Object]] herited from [i]std::enable_shared_from_this[/i] to permit to access at his own [i]std::shared_ptr[/i]. +:** Acces At his own [i]std::shared_ptr[/i] is not allowed in the class contructor/destructor. +:** Many time for meta-widget we need to propagate our [i]std::shared_ptr[/i] in child. + +Then for all these reasons, I have create a simple MACRO that create a static template funtion that create the object and just after +creation call the init(...) function to permit to create a complex widget or others with some writing convinience. + + + diff --git a/doc/index.bb b/doc/index.bb new file mode 100644 index 0000000..344f05b --- /dev/null +++ b/doc/index.bb @@ -0,0 +1,69 @@ +== [center]RIVER library[/center] == +__________________________________________________ + +===What is RIVER, and how can I use it?=== +RIVER is a multi-platform library to manage the input and output audio flow. +It can be compared with PulseAudio or Jack, but at the difference at the 2 interfaces +it is designed to be multi-platform and is based on licence that permit to integrate it +on every program we want. + +===Where can I use it?=== +Everywhere! RIVER is cross-platform devolopped to support bases OS: +: ** Linux (over Alsa, Pulseaudio, JackD) +: ** Windows (over ASIO) +: ** MacOs (over CoreAudio) +: ** Android (Over Ewol wrapper little complicated need to be change later) +: ** IOs (over CoreAudio for ios) + +===What languages are supported?=== +RIVER is written in C++11 with posibilities to compile it with C++03 + Boost + +===Are there any licensing restrictions?=== +RIVER is [b]FREE software[/b] and [i]all sub-library are FREE and staticly linkable !!![/i] + +That allow you to use it for every program you want, including those developing proprietary software, without any license fees or royalties. + +[note]The static support is important for some platform like IOs, and this limit the external library use at some license like : +:** BSD* +:** MIT +:** APPACHE-2 +:** PNG +:** ZLIB +This exclude the classical extern library with licence: +:** L-GPL +:** GPL +[/note] + +==== License (APACHE 2) ==== +Copyright ewol Edouard DUPIN + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + [[http://www.apache.org/licenses/LICENSE-2.0]] + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +==== Depends library: ==== +===== License: ===== +:** [b][lib[etk | e-tk]][/b] : APACHE-2 +:** [b][lib[airtaudio | airtaudio]][/b] : MIT/APACHE-2 +:** [b][lib[ejson | e-json]][/b] : APACHE-2 +:** [b][lib[drain | Drain]][/b] : APACHE-2 + + +===== Program Using RIVER ===== +:** [b][[http://play.google.com/store/apps/details?id=com.edouarddupin.worddown | worddown]][/b] : (Proprietary) Worddown is a simple word game threw [lib[ewolsa | ewol-simple-audio]]. + +== Main documentation: == + +[doc[001_bases | Global Documantation]] + +[tutorial[000_Build | Tutorials]] + diff --git a/doc/tutorial/000_Build.bb b/doc/tutorial/000_Build.bb new file mode 100644 index 0000000..e4afbac --- /dev/null +++ b/doc/tutorial/000_Build.bb @@ -0,0 +1,59 @@ +=?=River extract and build examples an example=?= +__________________________________________________ +[left][doc[001_bases | Previous: Doc]][/left] [right][tutorial[001_Read | Next: Create an input interface]][/right] + +All developpement software will start by getting the dependency and the sources. + +=== Linux dependency packages === +[code style=shell] + sudo apt-get install g++ zlib1g-dev libasound2-dev + # if you want to compile with clang : + sudo apt-get install clang +[/code] + + +=== Download instructions === + +Download the software : This is the simple way You really need only a part of the ewol framework +[code style=shell] + # create a working directory path + mkdir your_workspace_path + cd your_workspace_path + # clone ewol and all sub-library + git clone git://github.com/HeeroYui/ewol.git + cd ewol + git submodule init + git submodule update + cd .. +[/code] + +If you prefer creating with the packege you needed : +[code style=shell] + mkdir -p your_workspace_path + cd your_workspace_path + # download all you needs + git clone git://github.com/HeeroYui/lutin.git + git clone git://github.com/HeeroYui/etk.git + git clone git://github.com/HeeroYui/audio.git + git clone git://github.com/HeeroYui/ejson.git + git clone git://github.com/HeeroYui/airtaudio.git + git clone git://github.com/HeeroYui/drain.git + git clone git://github.com/HeeroYui/river.git +[/code] + +[note] +The full build tool documentation is availlable here : [[http://heeroyui.github.io/lutin/ | lutin]] +[/note] + +=== Common build instructions === + +Build the basic examples & test: +[code style=shell] + ./ewol/build/lutin.py -mdebug river_sample_read +[/code] + +To run an application you will find it directly on the out 'staging' tree : +[code style=shell] + ./out/Linux/debug/staging/clang/river_sample_read/usr/bin/river_sample_read -l4 +[/code] + diff --git a/doc/tutorial/001_Read.bb b/doc/tutorial/001_Read.bb new file mode 100644 index 0000000..f06ffc4 --- /dev/null +++ b/doc/tutorial/001_Read.bb @@ -0,0 +1,97 @@ + +=== Objectif === +:** Understand basis of river +:** Create a simple recording interface that print the average of sample absolute value. + +=== sample source: === + [[http:://github.com/HeeroYui/river.git/sample/read/ | sample source]] + +=== Bases: === + +When you will create an application based on the river audio interface you need : + +==== Include: ==== + +Include manager and interface node + +[code style=c++] +#include +#include +#include +[/code] + +==== Initilize the River library: ==== + +We first need to initialize etk sub library (needed to select the log level of sub-libraries and file access abstraction +[code style=c++] + // the only one init for etk: + etk::init(_argc, _argv); +[/code] + +Now we will initilaize the river library. +To do this We have 2 posibilities: +:** With a file: +[code style=c++] + // initialize river interface + river::init("DATA:configFileName.json"); +[/code] +:** With a json string: +[code style=c++] + static const std::string configurationRiver = + "{\n" + " microphone:{\n" + " io:'input',\n" + " map-on:{\n" + " interface:'auto',\n" + " name:'default',\n" + " },\n" + " frequency:0,\n" + " channel-map:['front-left', 'front-right'],\n" + " type:'auto',\n" + " nb-chunk:1024\n" + " }\n" + "}\n"; + // initialize river interface + river::initString(configurationRiver); +[/code] + +For the example we select the second solution (faster to implement example and resource at the same position. + +river::init / river::initString must be called only one time for all the application, this represent the hardware configuration. +It is Nearly not dynamic + +To understand the configuration file Please see [tutorial[004_ConfigurationFile | Configuration file]] + + + + // Create the River manager for tha application or part of the application. + std11::shared_ptr manager = river::Manager::create("river_sample_read"); + // create interface: + std11::shared_ptr interface; + //Get the generic input: + interface = manager->createInput(48000, + std::vector(), + audio::format_int16, + "microphone"); + if(interface == nullptr) { + std::cout << "nullptr interface" << std::endl; + return -1; + } + // set callback mode ... + interface->setInputCallback(std11::bind(&onDataReceived, + std11::placeholders::_1, + std11::placeholders::_2, + std11::placeholders::_3, + std11::placeholders::_4, + std11::placeholders::_5, + std11::placeholders::_6)); + // start the stream + interface->start(); + // wait 10 second ... + sleep(10); + // stop the stream + interface->stop(); + // remove interface and manager. + interface.reset(); + manager.reset(); + return 0; \ No newline at end of file diff --git a/doc/tutorial/002_Write.bb b/doc/tutorial/002_Write.bb new file mode 100644 index 0000000..e69de29 diff --git a/doc/tutorial/003_FeadBack.bb b/doc/tutorial/003_FeadBack.bb new file mode 100644 index 0000000..e69de29 diff --git a/doc/tutorial/004_ConfigurationFile.bb b/doc/tutorial/004_ConfigurationFile.bb new file mode 100644 index 0000000..e69de29 diff --git a/lutin_river_test.py b/lutin_river_test.py index cf40e96..c8432a4 100644 --- a/lutin_river_test.py +++ b/lutin_river_test.py @@ -31,7 +31,6 @@ def create(target): myModule.add_module_depend(['river', 'gtest', 'etk']) - # add the currrent module at the return myModule diff --git a/sample/read/lutin_river_sample_read.py b/sample/read/lutin_river_sample_read.py new file mode 100644 index 0000000..558a563 --- /dev/null +++ b/sample/read/lutin_river_sample_read.py @@ -0,0 +1,27 @@ +#!/usr/bin/python +import lutinModule as module +import lutinTools as tools +import lutinDebug as debug + +def get_desc(): + return "river_sample_read : Read some data" + + +def create(target): + myModule = module.Module(__file__, 'river_sample_read', 'BINARY') + + myModule.add_src_file([ + 'main.cpp', + ]) + myModule.add_module_depend(['river', 'etk']) + + return myModule + + + + + + + + + diff --git a/sample/read/main.cpp b/sample/read/main.cpp new file mode 100644 index 0000000..3df8e80 --- /dev/null +++ b/sample/read/main.cpp @@ -0,0 +1,93 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2015, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#include +#include +#include + + +static const std::string configurationRiver = + "{\n" + " microphone:{\n" + " io:'input',\n" + " map-on:{\n" + " interface:'auto',\n" + " name:'default',\n" + " },\n" + " frequency:0,\n" + " channel-map:['front-left', 'front-right'],\n" + " type:'auto',\n" + " nb-chunk:1024\n" + " }\n" + "}\n"; + +void onDataReceived(const void* _data, + const std11::chrono::system_clock::time_point& _time, + size_t _nbChunk, + enum audio::format _format, + uint32_t _frequency, + const std::vector& _map) { + if (_format != audio::format_int16) { + std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl; + } + const int16_t* data = static_cast(_data); + int64_t value = 0; + for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) { + value += std::abs(data[iii]); + } + value /= (_nbChunk*_map.size()); + std::cout << "Get data ... average=" << int32_t(value) << std::endl; +} + +int main(int _argc, char **_argv) { + // the only one init for etk: + etk::init(_argc, _argv); + for (int32_t iii=0; iii<_argc ; ++iii) { + std::string data = _argv[iii]; + if ( data == "-h" + || data == "--help") { + std::cout << "Help : " << std::endl; + std::cout << " ./xxx ---" << std::endl; + exit(0); + } + } + // initialize river interface + river::initString(configurationRiver); + // Create the River manager for tha application or part of the application. + std11::shared_ptr manager = river::Manager::create("river_sample_read"); + // create interface: + std11::shared_ptr interface; + //Get the generic input: + interface = manager->createInput(48000, + std::vector(), + audio::format_int16, + "microphone"); + if(interface == nullptr) { + std::cout << "nullptr interface" << std::endl; + return -1; + } + // set callback mode ... + interface->setInputCallback(std11::bind(&onDataReceived, + std11::placeholders::_1, + std11::placeholders::_2, + std11::placeholders::_3, + std11::placeholders::_4, + std11::placeholders::_5, + std11::placeholders::_6)); + // start the stream + interface->start(); + // wait 10 second ... + sleep(10); + // stop the stream + interface->stop(); + // remove interface and manager. + interface.reset(); + manager.reset(); + return 0; +} + diff --git a/sample/write/lutin_river_sample_write.py b/sample/write/lutin_river_sample_write.py new file mode 100644 index 0000000..dc36a60 --- /dev/null +++ b/sample/write/lutin_river_sample_write.py @@ -0,0 +1,27 @@ +#!/usr/bin/python +import lutinModule as module +import lutinTools as tools +import lutinDebug as debug + +def get_desc(): + return "river_sample_write : Write some data" + + +def create(target): + myModule = module.Module(__file__, 'river_sample_write', 'BINARY') + + myModule.add_src_file([ + 'main.cpp', + ]) + myModule.add_module_depend(['river', 'etk']) + + return myModule + + + + + + + + + diff --git a/sample/write/main.cpp b/sample/write/main.cpp new file mode 100644 index 0000000..150dc9b --- /dev/null +++ b/sample/write/main.cpp @@ -0,0 +1,99 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2015, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#include +#include +#include + + +static const std::string configurationRiver = + "{\n" + " speaker:{\n" + " io:'output',\n" + " map-on:{\n" + " interface:'auto',\n" + " name:'default',\n" + " },\n" + " frequency:0,\n" + " channel-map:['front-left', 'front-right'],\n" + " type:'auto',\n" + " nb-chunk:1024,\n" + " volume-name:'MASTER'\n" + " }\n" + "}\n"; + +void onDataNeeded(void* _data, + const std11::chrono::system_clock::time_point& _time, + size_t _nbChunk, + enum audio::format _format, + uint32_t _frequency, + const std::vector& _map) { + static double phase = 0; + if (_format != audio::format_int16) { + std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl; + } + int16_t* data = static_cast(_data); + double baseCycle = 2.0*M_PI/(double)48000 * (double)550; + for (int32_t iii=0; iii<_nbChunk; iii++) { + for (int32_t jjj=0; jjj<_map.size(); jjj++) { + data[_map.size()*iii+jjj] = cos(phase) * 30000; + } + phase += baseCycle; + if (phase >= 2*M_PI) { + phase -= 2*M_PI; + } + } +} + +int main(int _argc, char **_argv) { + // the only one init for etk: + etk::init(_argc, _argv); + for (int32_t iii=0; iii<_argc ; ++iii) { + std::string data = _argv[iii]; + if ( data == "-h" + || data == "--help") { + std::cout << "Help : " << std::endl; + std::cout << " ./xxx ---" << std::endl; + exit(0); + } + } + // initialize river interface + river::initString(configurationRiver); + // Create the River manager for tha application or part of the application. + std11::shared_ptr manager = river::Manager::create("river_sample_read"); + // create interface: + std11::shared_ptr interface; + //Get the generic input: + interface = manager->createOutput(48000, + std::vector(), + audio::format_int16, + "speaker"); + if(interface == nullptr) { + std::cout << "nullptr interface" << std::endl; + return -1; + } + // set callback mode ... + interface->setOutputCallback(std11::bind(&onDataNeeded, + std11::placeholders::_1, + std11::placeholders::_2, + std11::placeholders::_3, + std11::placeholders::_4, + std11::placeholders::_5, + std11::placeholders::_6)); + // start the stream + interface->start(); + // wait 10 second ... + sleep(10); + // stop the stream + interface->stop(); + // remove interface and manager. + interface.reset(); + manager.reset(); + return 0; +} +