-#include <unistd.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <map>
-#include <memory>
-#include <iostream>
-
-#include <audio_io.h>
-#include <sound_manager.h>
-#include <sound_manager_internal.h>
-
-#ifndef TIZEN_FEATURE_TV_PROD
-
-enum Receiver
-{
- ECHO_CANCELLER = 0,
- NOISE_GENERATOR,
-};
-
-class Command
-{
-public:
- virtual void execute() const = 0;
-};
-
-class EchoCanceller
-{
-public:
- EchoCanceller() = default;
- virtual ~EchoCanceller() = default;
-
- void on() {
- int ret = sound_manager_start_aec();
- if (ret != 0)
- std::cerr << "failed to start echo cancellation, " << ret << std::endl;
- else
- std::cout << "[ON] Echo Canceller" << std::endl;
- }
- void off() {
- int ret = sound_manager_stop_aec();
- if (ret != 0)
- std::cerr << "failed to stop echo cancellation, " << ret << std::endl;
- else
- std::cout << "[OFF] Echo Canceller" << std::endl;
- }
-};
-
-class NoiseGenerator
-{
-public:
- NoiseGenerator() = default;
- virtual ~NoiseGenerator() = default;
-
- void on() {
- std::cout << "[ON] Noise Generator" << std::endl;
- playWhiteNoise();
- }
- void off() {
- std::cout << "[OFF] Noise Generator" << std::endl;
- stopWhiteNoise();
- }
-
-private:
- void playWhiteNoise();
- void stopWhiteNoise();
-
- static void _streamWriteCb(audio_out_h handle, size_t nbytes, void *user_data);
- static double _getRandDoubleRange(double min, double max);
-
- audio_out_h output{};
-};
-
-void NoiseGenerator::playWhiteNoise()
-{
- audio_out_h _output = nullptr;
-
- srand(time(NULL));
-
- int ret = audio_out_create_new(48000, AUDIO_CHANNEL_STEREO, AUDIO_SAMPLE_TYPE_S16_LE, &_output);
- if (ret != AUDIO_IO_ERROR_NONE) {
- std::cerr << "failed to create audio out" << std::endl;
- return;
- }
-
- ret = audio_out_set_stream_cb(_output, _streamWriteCb, NULL);
- if (ret != AUDIO_IO_ERROR_NONE) {
- std::cerr << "failed to set stream callback" << std::endl;
- audio_out_destroy(_output);
- return;
- }
-
- ret = audio_out_prepare(_output);
- if (ret != AUDIO_IO_ERROR_NONE) {
- std::cerr << "failed to prepare " << std::endl;
- audio_out_destroy(_output);
- return;
- }
-
- output = _output;
-}
-
-void NoiseGenerator::stopWhiteNoise()
-{
- if (!output)
- return;
-
- int ret = audio_out_unprepare(output);
- if (ret != AUDIO_IO_ERROR_NONE)
- std::cerr << "failed to prepare" << std::endl;
-
- ret = audio_out_destroy(output);
- if (ret != AUDIO_IO_ERROR_NONE)
- std::cerr << "failed to destroy output" << std::endl;
-
- output = nullptr;
-}
-
-double NoiseGenerator::_getRandDoubleRange(double min, double max)
-{
- static unsigned int seedp;
- int r = rand_r(&seedp);
- return (max / RAND_MAX) * r * (r & 0x1 ? 1 : -1);
-}
-
-void NoiseGenerator::_streamWriteCb(audio_out_h handle, size_t nbytes, void *user_data)
-{
- constexpr double amp = 0.3 * 32767.0;
-
- auto buffer = static_cast<short *>(malloc(nbytes));
- if (!buffer)
- return;
-
- auto ptr = buffer;
- for (size_t i = 0; i < nbytes; i += 2, ptr++)
- ptr[0] = (short)(amp * _getRandDoubleRange(-1.0, 1.0));
-
- audio_out_write(handle, static_cast<void*>(buffer), nbytes);
-
- free(buffer);
-}
-
-class EchoCancellerOnCommand : public Command
-{
-public:
- explicit EchoCancellerOnCommand(std::shared_ptr<EchoCanceller>& ec) : ec(ec) {}
- virtual ~EchoCancellerOnCommand() = default;
- void execute() const override { ec->on(); }
-
-private:
- std::shared_ptr<EchoCanceller> ec;
-};
-
-class EchoCancellerOffCommand : public Command
-{
-public:
- explicit EchoCancellerOffCommand(std::shared_ptr<EchoCanceller>& ec) : ec(ec) {}
- virtual ~EchoCancellerOffCommand() = default;
- void execute() const override { ec->off(); }
-
-private:
- std::shared_ptr<EchoCanceller> ec;
-};
-
-class NoiseGeneratorOnCommand : public Command
-{
-public:
- explicit NoiseGeneratorOnCommand(std::shared_ptr<NoiseGenerator>& ng) : ng(ng) {}
- virtual ~NoiseGeneratorOnCommand() = default;
- void execute() const override { ng->on(); }
-
-private:
- std::shared_ptr<NoiseGenerator> ng;
-};
-
-class NoiseGeneratorOffCommand : public Command
-{
-public:
- explicit NoiseGeneratorOffCommand(std::shared_ptr<NoiseGenerator>& ng) : ng(ng) {}
- virtual ~NoiseGeneratorOffCommand() = default;
- void execute() const override { ng->off(); }
-
-private:
- std::shared_ptr<NoiseGenerator> ng;
-};
-
-
-class RemoteControl
-{
-public:
- RemoteControl() = default;
-
- void addCommand(Receiver id, std::pair<std::shared_ptr<Command>, std::shared_ptr<Command>> Commands) {
- commands.insert({id, Commands});
- }
-
- void onButtonPressed(Receiver id) {
- if (commands.find(id) != commands.end())
- commands[id].first->execute();
- }
-
- void offButtonPressed(Receiver id) {
- if (commands.find(id) != commands.end())
- commands[id].second->execute();
- }
-
-private:
- std::map<Receiver, std::pair<std::shared_ptr<Command>, std::shared_ptr<Command>>> commands{};
-};
-
-int capture_sound(char **buffer, int *length, int sec)
-{
- int ret;
- char *_buffer = NULL;
- audio_in_h input = NULL;
- int _length = 16000 * 1 * 2 * sec; // 16Khz, mono, S16LE
-
- if (!buffer) {
- std::cout << "buffer is null" << std::endl;
- return -1;
- }
-
- ret = audio_in_create(16000, AUDIO_CHANNEL_MONO, AUDIO_SAMPLE_TYPE_S16_LE, &input);
- if (ret != AUDIO_IO_ERROR_NONE) {
- std::cerr << "failed to create audio_input" << std::endl;
- return -1;
- }
-
- ret = audio_in_prepare(input);
- if (ret != AUDIO_IO_ERROR_NONE) {
- std::cerr << "failed to prepare, " << ret << std::endl;
- goto fail;
- }
-
- _buffer = static_cast<char *>(malloc(_length));
- if (!_buffer) {
- std::cerr << "_buffer is null" << std::endl;
- goto fail;
- }
-
- ret = audio_in_read(input, _buffer, _length);
- if (ret <= 0) {
- std::cerr << "failed to read, " << ret << ", " << _length << std::endl;
- goto fail;
- }
- ret = audio_in_unprepare(input);
- if (ret != AUDIO_IO_ERROR_NONE) {
- std::cerr << "failed to unprepare, " << ret << std::endl;
- goto fail;
- }
-
- *buffer = _buffer;
- *length = _length;
-
- return 0;
-
-fail:
- if (input)
- audio_in_destroy(input);
- if (buffer)
- free(buffer);
-
- return -1;
-}
-
-int test_echo_cancellation(char **buffer, bool enable_ec, bool enable_ref, int time_sec)
-{
- int ret;
- char *_buffer = NULL;
- int length = -1;
-
- auto ec = std::make_shared<EchoCanceller>();
- auto ng = std::make_shared<NoiseGenerator>();
-
- RemoteControl control;
- control.addCommand(Receiver::ECHO_CANCELLER,
- { std::make_shared<EchoCancellerOnCommand>(ec),
- std::make_shared<EchoCancellerOffCommand>(ec) });
- control.addCommand(Receiver::NOISE_GENERATOR,
- { std::make_shared<NoiseGeneratorOnCommand>(ng),
- std::make_shared<NoiseGeneratorOffCommand>(ng) });
-
- if (enable_ec)
- control.onButtonPressed(Receiver::ECHO_CANCELLER);
- if (enable_ref)
- control.onButtonPressed(Receiver::NOISE_GENERATOR);
-
- std::cout << "Say something for " << time_sec << " seconds.. ec " << enable_ec << ", ref " << enable_ref << std::endl;
-
- ret = capture_sound(&_buffer, &length, time_sec);
-
- if (enable_ref)
- control.offButtonPressed(Receiver::NOISE_GENERATOR);
- if (enable_ec)
- control.offButtonPressed(Receiver::ECHO_CANCELLER);
-
- if (ret == 0)
- *buffer = _buffer;
- else
- free(_buffer);
-
- return length;
-}
-
-int dump_to_file(const char *filename, char *buffer, int length)
-{
- int fd = open(filename, O_CREAT|O_TRUNC|O_RDWR, 0644);
- if (fd < 0) {
- std::cerr << "failed to open file" << std::endl;
- return -1;
- }
-
- ssize_t ret = write(fd, buffer, length);
- if (ret < 0)
- std::cerr << "failed to write" << std::endl;
-
- close(fd);
-
- return 0;
-}
-#endif
-
-int main(int argc, char **argv)
-{
-#ifndef TIZEN_FEATURE_TV_PROD
- bool enable_ec;
- bool enable_ref;
- int time_sec;
- char *filename;
-
- char *buffer = NULL;
- int size;
-
- if (argc != 5) {
- std::cout << "- Usages :" << std::endl;
- std::cout << "- # audio_io_test_ec [filename] [on/off 0:1] [noise 0:1] [seconds]" << std::endl;
- return -1;
- }
-
- filename = argv[1];
- enable_ec = !!atoi(argv[2]);
- enable_ref = !!atoi(argv[3]);
- time_sec = atoi(argv[4]);
-
- size = test_echo_cancellation(&buffer, enable_ec, enable_ref, time_sec);
- if (size <= 0) {
- std::cerr << "failed to test aec" << std::endl;
- return -1;
- }
-
- if (dump_to_file(filename, buffer, size))
- std::cerr << "failed to save file, " << filename << std::endl;
- if (buffer)
- free(buffer);
-#else
- std::cout << "not supported yet" << std::endl;
-#endif
-
- return 0;
-}
\ No newline at end of file