From 7898113f99f4638cfbfb99f56e188129e9776da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Fri, 8 May 2015 16:51:18 +0200 Subject: [PATCH] os: add sporadic sound test This scripts starts two Audio_out session clients. These clients access the soundcard via the mixer. The first client simply streams a sample file in a loop while the second client generates a click sound when any key is pressed. Issue #1666. --- repos/os/run/audio_out_click.run | 119 +++++++++++++++ repos/os/src/test/audio_out_click/README | 14 ++ repos/os/src/test/audio_out_click/main.cc | 160 ++++++++++++++++++++ repos/os/src/test/audio_out_click/target.mk | 3 + 4 files changed, 296 insertions(+) create mode 100644 repos/os/run/audio_out_click.run create mode 100644 repos/os/src/test/audio_out_click/README create mode 100644 repos/os/src/test/audio_out_click/main.cc create mode 100644 repos/os/src/test/audio_out_click/target.mk diff --git a/repos/os/run/audio_out_click.run b/repos/os/run/audio_out_click.run new file mode 100644 index 000000000..90f87f9ca --- /dev/null +++ b/repos/os/run/audio_out_click.run @@ -0,0 +1,119 @@ +assert_spec x86 + +# +# Build +# + +set build_components { + core init + drivers/timer + drivers/audio + drivers/input + server/mixer + test/audio_out + test/audio_out_click +} + +source ${genode_dir}/repos/base/run/platform_drv.inc +append_platform_drv_build_components + +build $build_components + +create_boot_directory + +# +# Config +# + +append config { + + + + + + + + + + + + + + + + + + + + + } + +append_platform_drv_config + +append config { + + + + + + + + + + + + + + + + + + + + + + sample.raw + + + + + + + + + + + + + +} + +install_config $config + + +if {[expr ![file exists bin/sample.raw] || ![file exists bin/click.raw]]} { + puts "" + puts "The sample and/or click file is missing. Please take a look at" + puts "repos/dde_bsd/README, create 'sample.raw' and/or 'click.raw'" + puts "and put the file(s) into './bin'. afterwards" + puts "" + exit 1 +} + +# +# Boot modules +# + +set boot_modules { + core init timer mixer ps2_drv audio_drv + test-audio_out test-audio_out_click + sample.raw click.raw } + +# platform-specific modules +append_platform_drv_boot_modules + +build_boot_image $boot_modules + +append qemu_args " -m 128 -nographic -soundhw es1370 " + +run_genode_until forever diff --git a/repos/os/src/test/audio_out_click/README b/repos/os/src/test/audio_out_click/README new file mode 100644 index 000000000..770d87cc9 --- /dev/null +++ b/repos/os/src/test/audio_out_click/README @@ -0,0 +1,14 @@ +test-audio_out sends one or more raw audio streams to the "Audio_out" +service. The raw data must comply the Audio_out standard format. + +! +! test-audio_out +! 1M +! +! audio1.raw +! audio2.raw +! ... +! +! + + Example configuration entry diff --git a/repos/os/src/test/audio_out_click/main.cc b/repos/os/src/test/audio_out_click/main.cc new file mode 100644 index 000000000..b2a1948a6 --- /dev/null +++ b/repos/os/src/test/audio_out_click/main.cc @@ -0,0 +1,160 @@ +/* + * \brief Audio-out test implementation + * \author Sebastian Sumpf + * \author Christian Helmuth + * \date 2009-12-03 + * + * The test program plays several tracks simultaneously to the Audio_out + * service. See README for the configuration. + */ + +/* + * Copyright (C) 2009-2013 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace Genode; +using namespace Audio_out; + +static const bool verbose = false; + +enum { + CHANNELS = 2, /* number of channels */ + FRAME_SIZE = sizeof(float), + PERIOD_CSIZE = FRAME_SIZE * PERIOD, /* size of channel packet (bytes) */ + PERIOD_FSIZE = CHANNELS * PERIOD_CSIZE, /* size of period in file (bytes) */ +}; + + +static const char *channel_names[] = { "front left", "front right" }; + + +class Click +{ + private: + + Audio_out::Connection *_audio_out[CHANNELS]; + char const *_base; + Genode::size_t _size; + + public: + + Click(char const *file) + { + for (int i = 0; i < CHANNELS; ++i) { + /* allocation signal for first channel only */ + _audio_out[i] = new (env()->heap()) + Audio_out::Connection(channel_names[i], i == 0); + _audio_out[i]->start(); + } + + Dataspace_capability ds_cap; + + try { + Rom_connection rom(file); + rom.on_destruction(Rom_connection::KEEP_OPEN); + ds_cap = rom.dataspace(); + _base = env()->rm_session()->attach(ds_cap); + } catch (...) { + PDBG("Error: Could not open: %s", file); + return; + } + + Dataspace_client ds_client(ds_cap); + _size = ds_client.size(); + } + + void play() + { + PLOG("play click"); + + for (int i = 0; i < CHANNELS; i++) + _audio_out[i]->stream()->reset(); + + for (Genode::size_t offset = 0; offset < _size; offset += PERIOD_FSIZE) { + + /* + * The current chunk (in number of frames of one channel) + * is the size of the period except at the end of the + * file. + */ + size_t chunk = (offset + PERIOD_FSIZE > _size) + ? (_size - offset) / CHANNELS / FRAME_SIZE + : PERIOD; + + Packet *p[CHANNELS]; + + while (true) + try { + p[0] = _audio_out[0]->stream()->alloc(); + break; + } catch (Audio_out::Stream::Alloc_failed) { + _audio_out[0]->wait_for_alloc(); + } + + unsigned pos = _audio_out[0]->stream()->packet_position(p[0]); + for (int chn = 1; chn < CHANNELS; ++chn) + p[chn] = _audio_out[chn]->stream()->get(pos); + + /* copy channel contents into sessions */ + float *content = (float *)(_base + offset); + for (unsigned c = 0; c < CHANNELS * chunk; c += CHANNELS) + for (int i = 0; i < CHANNELS; ++i) + p[i]->content()[c / 2] = content[c + i]; + + /* handle last packet gracefully */ + if (chunk < PERIOD) { + for (int i = 0; i < CHANNELS; ++i) + memset(p[i]->content() + chunk, + 0, PERIOD_CSIZE - FRAME_SIZE * chunk); + } + + for (int i = 0; i < CHANNELS; i++) + _audio_out[i]->submit(p[i]); + } + } +}; + +int main(int argc, char **argv) +{ + PDBG("--- Audio_out click test ---\n"); + + Genode::Signal_context sig_ctx; + Genode::Signal_receiver sig_rec; + + Genode::Signal_context_capability sig_cap = sig_rec.manage(&sig_ctx); + + Input::Connection input; + Input::Event *ev_buf; + + input.sigh(sig_cap); + ev_buf = static_cast(Genode::env()->rm_session()->attach(input.dataspace())); + + Click click("click.raw"); + + for (;;) { + Genode::Signal sig = sig_rec.wait_for_signal(); + + for (int i = 0, num_ev = input.flush(); i < num_ev; ++i) { + Input::Event &ev = ev_buf[i]; + if (ev.type() == Input::Event::PRESS) { + click.play(); + break; + } + } + } + + return 0; +} diff --git a/repos/os/src/test/audio_out_click/target.mk b/repos/os/src/test/audio_out_click/target.mk new file mode 100644 index 000000000..d731cef59 --- /dev/null +++ b/repos/os/src/test/audio_out_click/target.mk @@ -0,0 +1,3 @@ +TARGET = test-audio_out_click +SRC_CC = main.cc +LIBS = base config