dde_bsd: add Audio_in test application

This test is a simple audio monitor that plays all recorded frames
back.

Issue #1644.
This commit is contained in:
Josef Söntgen 2015-05-15 22:24:31 +02:00 committed by Christian Helmuth
parent 8a34d21577
commit fb761283a2
4 changed files with 235 additions and 0 deletions

View File

@ -0,0 +1,85 @@
assert_spec x86
#
# Build
#
set build_components {
core init
drivers/timer
drivers/audio_out
test/audio_in
}
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
create_boot_directory
#
# Config
#
append config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL" />
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>}
append_platform_drv_config
append config {
<start name="audio_out_drv">
<resource name="RAM" quantum="8M"/>
<provides>
<service name="Audio_out"/>
<service name="Audio_in"/>
</provides>
<config recording="yes">
<mixer field="outputs.master" value="255"/>
<mixer field="record.adc-0:1_source" value="sel2"/>
<mixer field="record.adc-0:1" value="255"/>
</config>
</start>
<start name="test-audio_in">
<resource name="RAM" quantum="8M"/>
</start>
</config>}
install_config $config
#
# Boot modules
#
set boot_modules {
core init timer audio_out_drv test-audio_in
}
append_platform_drv_boot_modules
build_boot_image $boot_modules
append qemu_args " -m 128 -nographic -soundhw es1370 "
run_genode_until forever

View File

@ -0,0 +1,3 @@
This test captures input from an Audio_in session and directly plays
all packets by sending them to the Audio_out session. It is merely a
simple audio monitor program.

View File

@ -0,0 +1,144 @@
/*
* \brief Audio-in test implementation
* \author Josef Soentgen
* \date 2015-05-11
*
* The test program records on channel.
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <audio_out_session/connection.h>
#include <audio_in_session/connection.h>
#include <base/printf.h>
#include <base/sleep.h>
#include <dataspace/client.h>
#include <os/config.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_receiver &_sig_rec;
Genode::Signal_dispatcher<Recording> _record_progress;
Genode::Signal_dispatcher<Recording> _record_overrun;
Audio_out::Connection *_audio_out[CHANNELS];
Audio_in::Connection _audio_in { "left" };
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(unsigned)
{
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)
{
unsigned pos = _stream.pos();
unsigned tail = _stream.tail();
PWRN("record overrun, pos: %u tail: %u overriden: %u",
pos, tail, 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::Allocator &md_alloc, Genode::Signal_receiver &sig_rec)
:
_sig_rec(sig_rec),
_record_progress(_sig_rec, *this, &Recording::_handle_record_progress),
_record_overrun(_sig_rec, *this, &Recording::_handle_record_overrun),
_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("front left", true);
_audio_out[1] = new (&md_alloc) Audio_out::Connection("front right", true);
_audio_out[0]->start();
_audio_out[1]->start();
_audio_in.start();
}
};
int main(int argc, char *argv[])
{
PDBG("--- Audio_in test ---\n");
using namespace Genode;
Signal_receiver sig_rec;
Recording record(*env()->heap(), sig_rec);
for (;;) {
Signal sig = sig_rec.wait_for_signal();
Signal_dispatcher_base *dispatcher =
dynamic_cast<Signal_dispatcher_base *>(sig.context());
if (dispatcher)
dispatcher->dispatch(sig.num());
}
return 0;
}

View File

@ -0,0 +1,3 @@
TARGET = test-audio_in
SRC_CC = main.cc
LIBS = base config