diff --git a/Libraries/LibAudio/AClientConnection.cpp b/Libraries/LibAudio/AClientConnection.cpp index de1e368657..66f107b933 100644 --- a/Libraries/LibAudio/AClientConnection.cpp +++ b/Libraries/LibAudio/AClientConnection.cpp @@ -46,3 +46,23 @@ int AClientConnection::get_remaining_samples() { return send_sync()->remaining_samples(); } + +int AClientConnection::get_played_samples() +{ + return send_sync()->played_samples(); +} + +void AClientConnection::set_paused(bool paused) +{ + send_sync(paused); +} + +void AClientConnection::clear_buffer(bool paused) +{ + send_sync(paused); +} + +int AClientConnection::get_playing_buffer() +{ + return send_sync()->buffer_id(); +} diff --git a/Libraries/LibAudio/AClientConnection.h b/Libraries/LibAudio/AClientConnection.h index c1d2523340..ff0e6f59b2 100644 --- a/Libraries/LibAudio/AClientConnection.h +++ b/Libraries/LibAudio/AClientConnection.h @@ -18,4 +18,9 @@ public: void set_main_mix_volume(int); int get_remaining_samples(); + int get_played_samples(); + int get_playing_buffer(); + + void set_paused(bool paused); + void clear_buffer(bool paused = false); }; diff --git a/Libraries/LibAudio/AWavLoader.cpp b/Libraries/LibAudio/AWavLoader.cpp index d64a65ddc6..eb8403ef0f 100644 --- a/Libraries/LibAudio/AWavLoader.cpp +++ b/Libraries/LibAudio/AWavLoader.cpp @@ -31,6 +31,20 @@ RefPtr AWavLoader::get_more_samples(size_t max_bytes_to_read_from_input return buffer; } +void AWavLoader::seek(const int position) +{ + if (position < 0 || position > m_total_samples) + return; + + m_loaded_samples = position; + m_file->seek(position * m_num_channels * (m_bits_per_sample / 8)); +} + +void AWavLoader::reset() +{ + seek(0); +} + bool AWavLoader::parse_header() { CIODeviceStreamReader stream(*m_file); @@ -80,7 +94,7 @@ bool AWavLoader::parse_header() u16 audio_format; stream >> audio_format; - CHECK_OK("Audio format"); // incomplete read check + CHECK_OK("Audio format"); // incomplete read check ok = ok && audio_format == 1; // WAVE_FORMAT_PCM ASSERT(audio_format == 1); CHECK_OK("Audio format"); // value check @@ -161,7 +175,7 @@ bool AResampleHelper::read_sample(float& next_l, float& next_r) return false; } -template +template static void read_samples_from_stream(BufferStream& stream, SampleReader read_sample, Vector& samples, AResampleHelper& resampler, int num_channels) { float norm_l = 0; @@ -169,7 +183,7 @@ static void read_samples_from_stream(BufferStream& stream, SampleReader read_sam switch (num_channels) { case 1: - for(;;) { + for (;;) { while (resampler.read_sample(norm_l, norm_r)) { samples.append(ASample(norm_l)); } @@ -182,7 +196,7 @@ static void read_samples_from_stream(BufferStream& stream, SampleReader read_sam } break; case 2: - for(;;) { + for (;;) { while (resampler.read_sample(norm_l, norm_r)) { samples.append(ASample(norm_l, norm_r)); } @@ -238,8 +252,7 @@ RefPtr ABuffer::from_pcm_data(ByteBuffer& data, AResampleHelper& resamp { BufferStream stream(data); Vector fdata; - fdata.ensure_capacity(data.size() * 2); - + 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(); #endif diff --git a/Libraries/LibAudio/AWavLoader.h b/Libraries/LibAudio/AWavLoader.h index 34fb0a0305..bd53b2ff15 100644 --- a/Libraries/LibAudio/AWavLoader.h +++ b/Libraries/LibAudio/AWavLoader.h @@ -22,6 +22,9 @@ public: RefPtr get_more_samples(size_t max_bytes_to_read_from_input = 128 * KB); + void reset(); + void seek(const int position); + int loaded_samples() const { return m_loaded_samples; } int total_samples() const { return m_total_samples; } u32 sample_rate() const { return m_sample_rate; } diff --git a/Servers/AudioServer/ASClientConnection.cpp b/Servers/AudioServer/ASClientConnection.cpp index 43e2e5e813..7bfe1df067 100644 --- a/Servers/AudioServer/ASClientConnection.cpp +++ b/Servers/AudioServer/ASClientConnection.cpp @@ -75,8 +75,38 @@ OwnPtr ASClientConnection::handle(const Audi OwnPtr ASClientConnection::handle(const AudioServer::GetRemainingSamples&) { int remaining = 0; - if(m_queue) + if (m_queue) remaining = m_queue->get_remaining_samples(); return make(remaining); } + +OwnPtr ASClientConnection::handle(const AudioServer::GetPlayedSamples&) +{ + int played = 0; + if (m_queue) + played = m_queue->get_played_samples(); + + return make(played); +} + +OwnPtr ASClientConnection::handle(const AudioServer::SetPaused& message) +{ + if (m_queue) + m_queue->set_paused(message.paused()); + return make(); +} + +OwnPtr ASClientConnection::handle(const AudioServer::ClearBuffer& message) +{ + if (m_queue) + m_queue->clear(message.paused()); + return make(); +} + +OwnPtr ASClientConnection::handle(const AudioServer::GetPlayingBuffer&){ + int id = -1; + if(m_queue) + id = m_queue->get_playing_buffer(); + return make(id); +} diff --git a/Servers/AudioServer/ASClientConnection.h b/Servers/AudioServer/ASClientConnection.h index a50fbd270e..d3946a834f 100644 --- a/Servers/AudioServer/ASClientConnection.h +++ b/Servers/AudioServer/ASClientConnection.h @@ -23,6 +23,10 @@ private: virtual OwnPtr handle(const AudioServer::SetMainMixVolume&) override; virtual OwnPtr handle(const AudioServer::EnqueueBuffer&) override; virtual OwnPtr handle(const AudioServer::GetRemainingSamples&) override; + virtual OwnPtr handle(const AudioServer::GetPlayedSamples&) override; + virtual OwnPtr handle(const AudioServer::SetPaused&) override; + virtual OwnPtr handle(const AudioServer::ClearBuffer&) override; + virtual OwnPtr handle(const AudioServer::GetPlayingBuffer&) override; ASMixer& m_mixer; RefPtr m_queue; diff --git a/Servers/AudioServer/ASMixer.h b/Servers/AudioServer/ASMixer.h index cd086d0da7..e2a823b029 100644 --- a/Servers/AudioServer/ASMixer.h +++ b/Servers/AudioServer/ASMixer.h @@ -22,6 +22,9 @@ public: bool get_next_sample(ASample& sample) { + if (m_paused) + return false; + while (!m_current && !m_queue.is_empty()) m_current = m_queue.dequeue(); @@ -29,7 +32,8 @@ public: return false; sample = m_current->samples()[m_position++]; - m_remaining_samples--; + --m_remaining_samples; + ++m_played_samples; if (m_position >= m_current->sample_count()) { m_current = nullptr; @@ -40,19 +44,35 @@ public: ASClientConnection* client() { return m_client.ptr(); } - void clear() + void clear(bool paused = false) { m_queue.clear(); m_position = 0; + m_remaining_samples = 0; + m_played_samples = 0; + m_current = nullptr; + m_paused = paused; + } + + void set_paused(bool paused) + { + m_paused = paused; } int get_remaining_samples() const { return m_remaining_samples; } + int get_played_samples() const { return m_played_samples; } + int get_playing_buffer() const { + if(m_current) return m_current->shared_buffer_id(); + return -1; + } private: RefPtr m_current; Queue> m_queue; int m_position { 0 }; int m_remaining_samples { 0 }; + int m_played_samples { 0 }; + bool m_paused { false }; WeakPtr m_client; }; diff --git a/Servers/AudioServer/AudioServer.ipc b/Servers/AudioServer/AudioServer.ipc index a68beef39a..469e226eef 100644 --- a/Servers/AudioServer/AudioServer.ipc +++ b/Servers/AudioServer/AudioServer.ipc @@ -9,6 +9,11 @@ endpoint AudioServer // Buffer playback EnqueueBuffer(i32 buffer_id, int sample_count) => (bool success) + SetPaused(bool paused) => () + ClearBuffer(bool paused) => () + //Buffer information GetRemainingSamples() => (int remaining_samples) + GetPlayedSamples() => (int played_samples) + GetPlayingBuffer() => (i32 buffer_id) }