mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-05 18:18:34 +00:00
130 lines
3.1 KiB
C++
130 lines
3.1 KiB
C++
/*
|
|
* \brief Audio-in test implementation
|
|
* \author Josef Soentgen
|
|
* \date 2015-05-11
|
|
*
|
|
* The test program records on channel.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2015-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
/* Genode includes */
|
|
#include <audio_out_session/connection.h>
|
|
#include <audio_in_session/connection.h>
|
|
#include <base/component.h>
|
|
#include <base/heap.h>
|
|
#include <base/log.h>
|
|
#include <dataspace/client.h>
|
|
#include <rom_session/connection.h>
|
|
|
|
|
|
enum {
|
|
LEFT = 0,
|
|
RIGHT = 1,
|
|
CHANNELS = 2,
|
|
FRAME_SIZE = sizeof(float),
|
|
PERIOD_SIZE = FRAME_SIZE * Audio_in::PERIOD, /* size of period frame */
|
|
};
|
|
|
|
|
|
class Recording
|
|
{
|
|
private:
|
|
|
|
Genode::Signal_handler<Recording> _record_progress;
|
|
Genode::Signal_handler<Recording> _record_overrun;
|
|
|
|
Audio_out::Connection *_audio_out[CHANNELS];
|
|
Audio_in::Connection _audio_in;
|
|
Audio_in::Stream &_stream;
|
|
|
|
void _play(Audio_in::Packet *ip)
|
|
{
|
|
float *in = ip->content();
|
|
|
|
Audio_out::Packet *op[CHANNELS];
|
|
|
|
/* get left channel packet pos and sync right channel */
|
|
try {
|
|
op[LEFT] = _audio_out[LEFT]->stream()->alloc();
|
|
unsigned pos = _audio_out[LEFT]->stream()->packet_position(op[LEFT]);
|
|
op[RIGHT] = _audio_out[RIGHT]->stream()->get(pos);
|
|
} catch (...) { return; }
|
|
|
|
for (int c = 0; c < CHANNELS; c++) {
|
|
float *out = op[c]->content();
|
|
for (int i = 0; i < Audio_in::PERIOD; i++) {
|
|
out[i] = in[i];
|
|
}
|
|
}
|
|
|
|
for (int c = 0; c < CHANNELS; c++)
|
|
_audio_out[c]->submit(op[c]);
|
|
}
|
|
|
|
void _handle_record_progress()
|
|
{
|
|
Audio_in::Packet *p = _stream.get(_stream.pos());
|
|
|
|
if (!p->valid())
|
|
return;
|
|
|
|
_play(p);
|
|
|
|
p->invalidate();
|
|
p->mark_as_recorded();
|
|
|
|
_stream.increment_position();
|
|
}
|
|
|
|
void _handle_record_overrun()
|
|
{
|
|
unsigned pos = _stream.pos();
|
|
unsigned tail = _stream.tail();
|
|
|
|
Genode::warning("record overrun, pos: ", pos, " tail: ", tail, " ",
|
|
"overriden: ", tail - pos);
|
|
|
|
/*
|
|
* Normally you would handle this case properly by saving all
|
|
* packet that have not been already overriden. For simplicity
|
|
* we just discard all packets by setting pos to current tail.
|
|
*/
|
|
_stream.pos(tail);
|
|
}
|
|
|
|
public:
|
|
|
|
Recording(Genode::Env &env, Genode::Allocator &md_alloc)
|
|
:
|
|
_record_progress(env.ep(), *this, &Recording::_handle_record_progress),
|
|
_record_overrun(env.ep(), *this, &Recording::_handle_record_overrun),
|
|
_audio_in(env, "left" ),
|
|
_stream(*_audio_in.stream())
|
|
{
|
|
_audio_in.progress_sigh(_record_progress);
|
|
_audio_in.overrun_sigh(_record_overrun);
|
|
|
|
_audio_out[0] = new (&md_alloc) Audio_out::Connection(env, "front left", true);
|
|
_audio_out[1] = new (&md_alloc) Audio_out::Connection(env, "front right", true);
|
|
|
|
_audio_out[0]->start();
|
|
_audio_out[1]->start();
|
|
|
|
_audio_in.start();
|
|
}
|
|
};
|
|
|
|
void Component::construct(Genode::Env &env)
|
|
{
|
|
Genode::log("--- Audio_in test ---");
|
|
|
|
static Genode::Heap heap { env.ram(), env.rm() };
|
|
static Recording record(env, heap);
|
|
}
|