1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 06:57:44 +00:00

LibAudio: Put all classes in the Audio namespace and remove leading A

This commit is contained in:
Andreas Kling 2020-02-06 10:40:02 +01:00
parent 0bce5f7403
commit 92f77864de
20 changed files with 127 additions and 103 deletions

View file

@ -31,24 +31,26 @@
#include <AK/Vector.h>
#include <AK/SharedBuffer.h>
namespace Audio {
// A single sample in an audio buffer.
// Values are floating point, and should range from -1.0 to +1.0
struct ASample {
ASample()
struct Sample {
Sample()
: left(0)
, right(0)
{
}
// For mono
ASample(float left)
Sample(float left)
: left(left)
, right(left)
{
}
// For stereo
ASample(float left, float right)
Sample(float left, float right)
: left(left)
, right(right)
{
@ -74,7 +76,7 @@ struct ASample {
right *= pct;
}
ASample& operator+=(const ASample& other)
Sample& operator+=(const Sample& other)
{
left += other.left;
right += other.right;
@ -88,9 +90,9 @@ struct ASample {
// Small helper to resample from one playback rate to another
// This isn't really "smart", in that we just insert (or drop) samples.
// Should do better...
class AResampleHelper {
class ResampleHelper {
public:
AResampleHelper(float source, float target);
ResampleHelper(float source, float target);
void process_sample(float sample_l, float sample_r);
bool read_sample(float& next_l, float& next_r);
@ -103,34 +105,34 @@ private:
};
// A buffer of audio samples, normalized to 44100hz.
class ABuffer : public RefCounted<ABuffer> {
class Buffer : public RefCounted<Buffer> {
public:
static RefPtr<ABuffer> from_pcm_data(ByteBuffer& data, AResampleHelper& resampler, int num_channels, int bits_per_sample);
static NonnullRefPtr<ABuffer> create_with_samples(Vector<ASample>&& samples)
static RefPtr<Buffer> from_pcm_data(ByteBuffer& data, ResampleHelper& resampler, int num_channels, int bits_per_sample);
static NonnullRefPtr<Buffer> create_with_samples(Vector<Sample>&& samples)
{
return adopt(*new ABuffer(move(samples)));
return adopt(*new Buffer(move(samples)));
}
static NonnullRefPtr<ABuffer> create_with_shared_buffer(NonnullRefPtr<SharedBuffer>&& buffer, int sample_count)
static NonnullRefPtr<Buffer> create_with_shared_buffer(NonnullRefPtr<SharedBuffer>&& buffer, int sample_count)
{
return adopt(*new ABuffer(move(buffer), sample_count));
return adopt(*new Buffer(move(buffer), sample_count));
}
const ASample* samples() const { return (const ASample*)data(); }
const Sample* samples() const { return (const Sample*)data(); }
int sample_count() const { return m_sample_count; }
const void* data() const { return m_buffer->data(); }
int size_in_bytes() const { return m_sample_count * (int)sizeof(ASample); }
int size_in_bytes() const { return m_sample_count * (int)sizeof(Sample); }
int shared_buffer_id() const { return m_buffer->shared_buffer_id(); }
SharedBuffer& shared_buffer() { return *m_buffer; }
private:
explicit ABuffer(Vector<ASample>&& samples)
: m_buffer(*SharedBuffer::create_with_size(samples.size() * sizeof(ASample))),
explicit Buffer(Vector<Sample>&& samples)
: m_buffer(*SharedBuffer::create_with_size(samples.size() * sizeof(Sample))),
m_sample_count(samples.size())
{
memcpy(m_buffer->data(), samples.data(), samples.size() * sizeof(ASample));
memcpy(m_buffer->data(), samples.data(), samples.size() * sizeof(Sample));
}
explicit ABuffer(NonnullRefPtr<SharedBuffer>&& buffer, int sample_count)
explicit Buffer(NonnullRefPtr<SharedBuffer>&& buffer, int sample_count)
: m_buffer(move(buffer)),
m_sample_count(sample_count)
{
@ -139,3 +141,5 @@ private:
NonnullRefPtr<SharedBuffer> m_buffer;
const int m_sample_count;
};
}

View file

@ -28,21 +28,23 @@
#include <LibAudio/ABuffer.h>
#include <LibAudio/AClientConnection.h>
AClientConnection::AClientConnection()
namespace Audio {
ClientConnection::ClientConnection()
: IPC::ServerConnection<AudioClientEndpoint, AudioServerEndpoint>(*this, "/tmp/portal/audio")
{
}
void AClientConnection::handshake()
void ClientConnection::handshake()
{
auto response = send_sync<AudioServer::Greet>();
set_my_client_id(response->client_id());
}
void AClientConnection::enqueue(const ABuffer& buffer)
void ClientConnection::enqueue(const Buffer& buffer)
{
for (;;) {
const_cast<ABuffer&>(buffer).shared_buffer().share_with(server_pid());
const_cast<Buffer&>(buffer).shared_buffer().share_with(server_pid());
auto response = send_sync<AudioServer::EnqueueBuffer>(buffer.shared_buffer_id(), buffer.sample_count());
if (response->success())
break;
@ -50,66 +52,68 @@ void AClientConnection::enqueue(const ABuffer& buffer)
}
}
bool AClientConnection::try_enqueue(const ABuffer& buffer)
bool ClientConnection::try_enqueue(const Buffer& buffer)
{
const_cast<ABuffer&>(buffer).shared_buffer().share_with(server_pid());
const_cast<Buffer&>(buffer).shared_buffer().share_with(server_pid());
auto response = send_sync<AudioServer::EnqueueBuffer>(buffer.shared_buffer_id(), buffer.sample_count());
return response->success();
}
bool AClientConnection::get_muted()
bool ClientConnection::get_muted()
{
return send_sync<AudioServer::GetMuted>()->muted();
}
void AClientConnection::set_muted(bool muted)
void ClientConnection::set_muted(bool muted)
{
send_sync<AudioServer::SetMuted>(muted);
}
int AClientConnection::get_main_mix_volume()
int ClientConnection::get_main_mix_volume()
{
return send_sync<AudioServer::GetMainMixVolume>()->volume();
}
void AClientConnection::set_main_mix_volume(int volume)
void ClientConnection::set_main_mix_volume(int volume)
{
send_sync<AudioServer::SetMainMixVolume>(volume);
}
int AClientConnection::get_remaining_samples()
int ClientConnection::get_remaining_samples()
{
return send_sync<AudioServer::GetRemainingSamples>()->remaining_samples();
}
int AClientConnection::get_played_samples()
int ClientConnection::get_played_samples()
{
return send_sync<AudioServer::GetPlayedSamples>()->played_samples();
}
void AClientConnection::set_paused(bool paused)
void ClientConnection::set_paused(bool paused)
{
send_sync<AudioServer::SetPaused>(paused);
}
void AClientConnection::clear_buffer(bool paused)
void ClientConnection::clear_buffer(bool paused)
{
send_sync<AudioServer::ClearBuffer>(paused);
}
int AClientConnection::get_playing_buffer()
int ClientConnection::get_playing_buffer()
{
return send_sync<AudioServer::GetPlayingBuffer>()->buffer_id();
}
void AClientConnection::handle(const AudioClient::FinishedPlayingBuffer& message)
void ClientConnection::handle(const AudioClient::FinishedPlayingBuffer& message)
{
if (on_finish_playing_buffer)
on_finish_playing_buffer(message.buffer_id());
}
void AClientConnection::handle(const AudioClient::MutedStateChanged& message)
void ClientConnection::handle(const AudioClient::MutedStateChanged& message)
{
if (on_muted_state_change)
on_muted_state_change(message.muted());
}
}

View file

@ -30,17 +30,19 @@
#include <AudioServer/AudioServerEndpoint.h>
#include <LibIPC/IServerConnection.h>
class ABuffer;
namespace Audio {
class AClientConnection : public IPC::ServerConnection<AudioClientEndpoint, AudioServerEndpoint>
class Buffer;
class ClientConnection : public IPC::ServerConnection<AudioClientEndpoint, AudioServerEndpoint>
, public AudioClientEndpoint {
C_OBJECT(AClientConnection)
C_OBJECT(ClientConnection)
public:
AClientConnection();
ClientConnection();
virtual void handshake() override;
void enqueue(const ABuffer&);
bool try_enqueue(const ABuffer&);
void enqueue(const Buffer&);
bool try_enqueue(const Buffer&);
bool get_muted();
void set_muted(bool);
@ -62,3 +64,5 @@ private:
virtual void handle(const AudioClient::FinishedPlayingBuffer&) override;
virtual void handle(const AudioClient::MutedStateChanged&) override;
};
}

View file

@ -30,7 +30,9 @@
#include <LibCore/CIODeviceStreamReader.h>
#include <limits>
AWavLoader::AWavLoader(const StringView& path)
namespace Audio {
WavLoader::WavLoader(const StringView& path)
: m_file(Core::File::construct(path))
{
if (!m_file->open(Core::IODevice::ReadOnly)) {
@ -39,10 +41,10 @@ AWavLoader::AWavLoader(const StringView& path)
}
parse_header();
m_resampler = make<AResampleHelper>(m_sample_rate, 44100);
m_resampler = make<ResampleHelper>(m_sample_rate, 44100);
}
RefPtr<ABuffer> AWavLoader::get_more_samples(size_t max_bytes_to_read_from_input)
RefPtr<Buffer> WavLoader::get_more_samples(size_t max_bytes_to_read_from_input)
{
#ifdef AWAVLOADER_DEBUG
dbgprintf("Read WAV of format PCM with num_channels %u sample rate %u, bits per sample %u\n", m_num_channels, m_sample_rate, m_bits_per_sample);
@ -52,14 +54,14 @@ RefPtr<ABuffer> AWavLoader::get_more_samples(size_t max_bytes_to_read_from_input
if (raw_samples.is_empty())
return nullptr;
auto buffer = ABuffer::from_pcm_data(raw_samples, *m_resampler, m_num_channels, m_bits_per_sample);
auto buffer = Buffer::from_pcm_data(raw_samples, *m_resampler, m_num_channels, m_bits_per_sample);
//Buffer contains normalized samples, but m_loaded_samples should containt the ammount of actually loaded samples
m_loaded_samples += static_cast<int>(max_bytes_to_read_from_input) / (m_num_channels * (m_bits_per_sample / 8));
m_loaded_samples = min(m_total_samples, m_loaded_samples);
return buffer;
}
void AWavLoader::seek(const int position)
void WavLoader::seek(const int position)
{
if (position < 0 || position > m_total_samples)
return;
@ -68,12 +70,12 @@ void AWavLoader::seek(const int position)
m_file->seek(position * m_num_channels * (m_bits_per_sample / 8));
}
void AWavLoader::reset()
void WavLoader::reset()
{
seek(0);
}
bool AWavLoader::parse_header()
bool WavLoader::parse_header()
{
Core::IODeviceStreamReader stream(*m_file);
@ -179,19 +181,19 @@ bool AWavLoader::parse_header()
return true;
}
AResampleHelper::AResampleHelper(float source, float target)
ResampleHelper::ResampleHelper(float source, float target)
: m_ratio(source / target)
{
}
void AResampleHelper::process_sample(float sample_l, float sample_r)
void ResampleHelper::process_sample(float sample_l, float sample_r)
{
m_last_sample_l = sample_l;
m_last_sample_r = sample_r;
m_current_ratio += 1;
}
bool AResampleHelper::read_sample(float& next_l, float& next_r)
bool ResampleHelper::read_sample(float& next_l, float& next_r)
{
if (m_current_ratio > 0) {
m_current_ratio -= m_ratio;
@ -204,7 +206,7 @@ bool AResampleHelper::read_sample(float& next_l, float& next_r)
}
template<typename SampleReader>
static void read_samples_from_stream(BufferStream& stream, SampleReader read_sample, Vector<ASample>& samples, AResampleHelper& resampler, int num_channels)
static void read_samples_from_stream(BufferStream& stream, SampleReader read_sample, Vector<Sample>& samples, ResampleHelper& resampler, int num_channels)
{
float norm_l = 0;
float norm_r = 0;
@ -213,7 +215,7 @@ static void read_samples_from_stream(BufferStream& stream, SampleReader read_sam
case 1:
for (;;) {
while (resampler.read_sample(norm_l, norm_r)) {
samples.append(ASample(norm_l));
samples.append(Sample(norm_l));
}
norm_l = read_sample(stream);
@ -226,7 +228,7 @@ static void read_samples_from_stream(BufferStream& stream, SampleReader read_sam
case 2:
for (;;) {
while (resampler.read_sample(norm_l, norm_r)) {
samples.append(ASample(norm_l, norm_r));
samples.append(Sample(norm_l, norm_r));
}
norm_l = read_sample(stream);
norm_r = read_sample(stream);
@ -276,10 +278,10 @@ static float read_norm_sample_8(BufferStream& stream)
// ### can't const this because BufferStream is non-const
// perhaps we need a reading class separate from the writing one, that can be
// entirely consted.
RefPtr<ABuffer> ABuffer::from_pcm_data(ByteBuffer& data, AResampleHelper& resampler, int num_channels, int bits_per_sample)
RefPtr<Buffer> Buffer::from_pcm_data(ByteBuffer& data, ResampleHelper& resampler, int num_channels, int bits_per_sample)
{
BufferStream stream(data);
Vector<ASample> fdata;
Vector<Sample> fdata;
fdata.ensure_capacity(data.size() / (bits_per_sample / 8));
#ifdef AWAVLOADER_DEBUG
dbg() << "Reading " << bits_per_sample << " bits and " << num_channels << " channels, total bytes: " << data.size();
@ -304,5 +306,7 @@ RefPtr<ABuffer> ABuffer::from_pcm_data(ByteBuffer& data, AResampleHelper& resamp
// don't belong.
ASSERT(!stream.handle_read_failure());
return ABuffer::create_with_samples(move(fdata));
return Buffer::create_with_samples(move(fdata));
}
}

View file

@ -26,27 +26,28 @@
#pragma once
#include <AK/String.h>
#include <AK/RefPtr.h>
#include <AK/String.h>
#include <AK/StringView.h>
#include <LibCore/CFile.h>
#include <LibAudio/ABuffer.h>
class ABuffer;
#include <LibCore/CFile.h>
namespace AK {
class ByteBuffer;
}
// Parses a WAV file and produces an ABuffer instance from it
class AWavLoader {
namespace Audio {
class Buffer;
// Parses a WAV file and produces an Audio::Buffer.
class WavLoader {
public:
explicit AWavLoader(const StringView& path);
explicit WavLoader(const StringView& path);
bool has_error() const { return !m_error_string.is_null(); }
const char* error_string() { return m_error_string.characters(); }
RefPtr<ABuffer> get_more_samples(size_t max_bytes_to_read_from_input = 128 * KB);
RefPtr<Buffer> get_more_samples(size_t max_bytes_to_read_from_input = 128 * KB);
void reset();
void seek(const int position);
@ -62,7 +63,7 @@ private:
bool parse_header();
RefPtr<Core::File> m_file;
String m_error_string;
OwnPtr<AResampleHelper> m_resampler;
OwnPtr<ResampleHelper> m_resampler;
u32 m_sample_rate { 0 };
u16 m_num_channels { 0 };
@ -71,3 +72,5 @@ private:
int m_loaded_samples { 0 };
int m_total_samples { 0 };
};
}