Skip to content

Commit

Permalink
audio: use record/play session interface
Browse files Browse the repository at this point in the history
Issue #31
  • Loading branch information
nfeske authored and chelmuth committed Apr 19, 2024
1 parent b4acfab commit 52a096f
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 43 deletions.
2 changes: 1 addition & 1 deletion recipes/pkg/a64_audio_drv/runtime
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<platform label="audio"/>
</requires>

<provides> <audio_out/> <audio_in/> </provides>
<provides> <play/> <record/> <audio_out/> <audio_in/> </provides>

<config/>

Expand Down
2 changes: 2 additions & 0 deletions recipes/src/a64_audio_drv/used_apis
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ platform_session
report_session
audio_in_session
audio_out_session
play_session
record_session
82 changes: 44 additions & 38 deletions run/audio_pinephone.run
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
#
# Script to test audio driver on PinePhone. Test component acts a loopback
# device.
# Script to test audio driver on PinePhone
#

build {
core lib/ld init timer lib/libc lib/vfs lib/posix lib/vfs_oss
core lib/ld init timer lib/libc lib/libm lib/vfs lib/posix
drivers/platform/a64 drivers/pin/a64
drivers/audio_control/pinephone
drivers/audio/a64
server/report_rom
test/audio_in test/oss
server/record_play_mixer
app/waveform_player
}

create_boot_directory

install_config {
<config verbose="yes">
<config verbose="yes" prio_levels="2">
<parent-provides>
<service name="LOG"/>
<service name="PD"/>
Expand All @@ -32,19 +32,20 @@ install_config {
<any-service> <parent/> <any-child/> </any-service>
</default-route>

<start name="timer">
<start name="timer" priority="0">
<resource name="RAM" quantum="1M"/>
<resource name="CPU" quantum="20"/>
<route> <any-service> <parent/> </any-service> </route>
<provides> <service name="Timer"/> </provides>
</start>

<start name="report_rom">
<start name="report_rom" priority="-1">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config verbose="yes"/>
</start>

<start name="platform_drv" caps="200" managing_system="yes">
<start name="platform_drv" caps="200" managing_system="yes" priority="-1">
<resource name="RAM" quantum="2M"/>
<binary name="a64_platform_drv"/>
<provides> <service name="Platform"/> <service name="Scp"/> </provides>
Expand All @@ -65,7 +66,7 @@ install_config {
<route> <any-service> <parent/> </any-service> </route>
</start>

<start name="a64_pio_drv">
<start name="a64_pio_drv" priority="-1">
<resource name="RAM" quantum="1M"/>
<provides>
<service name="Pin_state"/>
Expand All @@ -85,13 +86,13 @@ install_config {
</config>
</start>

<start name="audio_control">
<start name="audio_control" priority="-1">
<binary name="pinephone_audio_control"/>
<resource name="RAM" quantum="1M"/>
<config>
<mic volume="60"/>
<earpiece volume="100"/>
<speaker volume="0"/>
<speaker volume="20"/>
<codec target="soc"/>
</config>
<route>
Expand All @@ -100,42 +101,47 @@ install_config {
</route>
</start>

<start name="audio_drv">
<binary name="a64_audio_drv"/>
<resource name="RAM" quantum="1M"/>
<provides>
<service name="Audio_out"/>
<service name="Audio_in"/>
</provides>
<route>
<service name="Platform"> <child name="platform_drv"/> </service>
<any-service> <parent/> </any-service>
</route>
<start name="mixer" priority="0">
<resource name="RAM" quantum="2M"/>
<resource name="CPU" quantum="20"/>
<binary name="record_play_mixer"/>
<provides> <service name="Record"/> <service name="Play"/> </provides>
<config jitter_ms="10">

<mix name="left"> <play label="waveform_player -> left" /> </mix>
<mix name="right"> <play label="waveform_player -> right"/> </mix>

<mix name="mic_left"> <!-- <play label="audio_drv -> mic_left"/> --> </mix>
<mix name="mic_right"> <!-- <play label="audio_drv -> mic_right"/> --> </mix>

<policy label="audio_drv -> left" record="left" volume="0.6"/>
<policy label="audio_drv -> right" record="right" volume="0.0"/>
</config>
</start>

<start name="test-oss">
<resource name="RAM" quantum="10M"/>
<config>
<vfs>
<dir name="dev">
<log/>
<oss name="dsp"/>
</dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log"/>
<start name="waveform_player" priority="0">
<resource name="RAM" quantum="1M"/>
<config period_ms="11">
<play label="left" wave="sine" hz="1000" sample_rate_hz="44100"/>
<play label="right" wave="square" hz="1000" sample_rate_hz="44100"/>
</config>
<route>
<service name="Audio_in"> <child name="audio_drv"/> </service>
<service name="Audio_out"> <child name="audio_drv"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>

<!--
<start name="test-audio_in">
<resource name="RAM" quantum="8M"/>
<start name="audio_drv" priority="0">
<binary name="a64_audio_drv"/>
<resource name="RAM" quantum="1M"/>
<resource name="CPU" quantum="20"/>
<config record_play="yes"/>
<route>
<service name="Platform"> <child name="platform_drv"/> </service>
<service name="Record"> <child name="mixer"/> </service>
<service name="Play"> <child name="mixer"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
-->
</config>
}

Expand Down
128 changes: 124 additions & 4 deletions src/drivers/audio/a64/session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@

#include <audio_in_session/rpc_object.h>
#include <audio_out_session/rpc_object.h>
#include <play_session/connection.h>
#include <record_session/connection.h>
#include <base/attached_rom_dataspace.h>
#include <base/session_label.h>
#include <base/component.h>
#include <base/heap.h>
#include <base/log.h>
#include <os/reporter.h>
#include <root/component.h>

#include "session.h"
Expand Down Expand Up @@ -451,9 +451,129 @@ struct Audio_aggregator : Audio::Session
};


struct Record_play_aggregator : Audio::Session
{
static constexpr unsigned SAMPLES_PER_PERIOD = Audio_in::PERIOD;
static constexpr unsigned CHANNELS = 2;

Env &_env;

struct Stereo_output : private Noncopyable
{
Env &_env;

/* 16 bit per sample, interleaved left and right */
int16_t data[SAMPLES_PER_PERIOD*CHANNELS] { };

Record::Connection _left { _env, "left" };
Record::Connection _right { _env, "right" };

Stereo_output(Env &env) : _env(env) { }

void clear() { for (auto &e : data) e = 0; }

void from_record_sessions()
{
using Samples_ptr = Record::Connection::Samples_ptr;

Record::Num_samples const num_samples { SAMPLES_PER_PERIOD };

auto clamped = [&] (float v)
{
return (v > 1.0) ? 1.0
: (v < -1.0) ? -1.0
: v;
};

auto float_to_s16 = [&] (float v) { return int16_t(clamped(v)*32767); };

_left.record(num_samples,
[&] (Record::Time_window const tw, Samples_ptr const &samples) {

for (unsigned i = 0; i < SAMPLES_PER_PERIOD; i++)
data[i*CHANNELS] = float_to_s16(samples.start[i]);

_right.record_at(tw, num_samples,
[&] (Samples_ptr const &samples) {
for (unsigned i = 0; i < SAMPLES_PER_PERIOD; i++)
data[i*CHANNELS + 1] = float_to_s16(samples.start[i]);
});
},
[&] { clear(); }
);
}
};

Stereo_output _stereo_output { _env };

struct Stereo_input : private Noncopyable
{
struct Frame { float left, right; };

void _for_each_frame(Packet const &packet, auto const &fn) const
{
float const scale = 1.0f/32768;

for (unsigned i = 0; i < SAMPLES_PER_PERIOD; i++)
fn(Frame { .left = scale*float(packet.data[i*CHANNELS]),
.right = scale*float(packet.data[i*CHANNELS + 1]) });
}

Env &_env;

Play::Connection _left { _env, "mic_left" };
Play::Connection _right { _env, "mic_right" };

Play::Time_window _time_window { };

Stereo_input(Env &env) : _env(env) { }

void from_packet(Packet const &packet)
{
if (!packet.valid())
return;

Play::Duration const duration_us { 11*1000 };
_time_window = _left.schedule_and_enqueue(_time_window, duration_us,
[&] (auto &submit) {
_for_each_frame(packet, [&] (Frame const frame) {
submit(frame.left); }); });

_right.enqueue(_time_window,
[&] (auto &submit) {
_for_each_frame(packet, [&] (Frame const frame) {
submit(frame.right); }); });
}
};

Stereo_input _stereo_input { _env };

Record_play_aggregator(Env &env) : _env(env) { }

Packet play_packet() override
{
_stereo_output.from_record_sessions();

return { _stereo_output.data, sizeof(Stereo_output::data) };
}

void record_packet(Packet packet) override
{
_stereo_input.from_packet(packet);
}
};


Audio::Session &Audio::Session::construct(Env &env, Allocator &alloc)
{
static Audio_aggregator _audio { env, alloc };
bool const use_record_play_interface =
Attached_rom_dataspace(env, "config").xml().attribute_value("record_play", false);

if (!use_record_play_interface) {
static Audio_aggregator _audio { env, alloc };
return _audio;
}

static Record_play_aggregator _audio { env };
return _audio;
}

0 comments on commit 52a096f

Please sign in to comment.