diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:23:01 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:23:01 +0100 |
commit | c7ac7e6eaff862c1ea4f99e0c6ce75e095106d9c (patch) | |
tree | ce2a3fef96f0b8eebe907743f1e03739457c11a6 /Services/AudioServer/Mixer.cpp | |
parent | 4055b0329117c1a280080bbd638eb48bafe29638 (diff) | |
download | serenity-c7ac7e6eaff862c1ea4f99e0c6ce75e095106d9c.zip |
Services: Move to Userland/Services/
Diffstat (limited to 'Services/AudioServer/Mixer.cpp')
-rw-r--r-- | Services/AudioServer/Mixer.cpp | 166 |
1 files changed, 0 insertions, 166 deletions
diff --git a/Services/AudioServer/Mixer.cpp b/Services/AudioServer/Mixer.cpp deleted file mode 100644 index 66a33ed23d..0000000000 --- a/Services/AudioServer/Mixer.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <AK/Array.h> -#include <AK/MemoryStream.h> -#include <AK/NumericLimits.h> -#include <AudioServer/ClientConnection.h> -#include <AudioServer/Mixer.h> -#include <pthread.h> -#include <strings.h> - -namespace AudioServer { - -Mixer::Mixer() - : m_device(Core::File::construct("/dev/audio", this)) - , m_sound_thread(LibThread::Thread::construct( - [this] { - mix(); - return 0; - }, - "AudioServer[mixer]")) -{ - if (!m_device->open(Core::IODevice::WriteOnly)) { - dbgln("Can't open audio device: {}", m_device->error_string()); - return; - } - - pthread_mutex_init(&m_pending_mutex, nullptr); - pthread_cond_init(&m_pending_cond, nullptr); - - m_zero_filled_buffer = (u8*)malloc(4096); - bzero(m_zero_filled_buffer, 4096); - m_sound_thread->start(); -} - -Mixer::~Mixer() -{ -} - -NonnullRefPtr<BufferQueue> Mixer::create_queue(ClientConnection& client) -{ - auto queue = adopt(*new BufferQueue(client)); - pthread_mutex_lock(&m_pending_mutex); - m_pending_mixing.append(*queue); - m_added_queue = true; - pthread_cond_signal(&m_pending_cond); - pthread_mutex_unlock(&m_pending_mutex); - return queue; -} - -void Mixer::mix() -{ - decltype(m_pending_mixing) active_mix_queues; - - for (;;) { - if (active_mix_queues.is_empty() || m_added_queue) { - pthread_mutex_lock(&m_pending_mutex); - pthread_cond_wait(&m_pending_cond, &m_pending_mutex); - active_mix_queues.append(move(m_pending_mixing)); - pthread_mutex_unlock(&m_pending_mutex); - m_added_queue = false; - } - - active_mix_queues.remove_all_matching([&](auto& entry) { return !entry->client(); }); - - Audio::Sample mixed_buffer[1024]; - auto mixed_buffer_length = (int)(sizeof(mixed_buffer) / sizeof(Audio::Sample)); - - // Mix the buffers together into the output - for (auto& queue : active_mix_queues) { - if (!queue->client()) { - queue->clear(); - continue; - } - - for (int i = 0; i < mixed_buffer_length; ++i) { - auto& mixed_sample = mixed_buffer[i]; - Audio::Sample sample; - if (!queue->get_next_sample(sample)) - break; - mixed_sample += sample; - } - } - - if (m_muted) { - m_device->write(m_zero_filled_buffer, 4096); - } else { - Array<u8, 4096> buffer; - OutputMemoryStream stream { buffer }; - - for (int i = 0; i < mixed_buffer_length; ++i) { - auto& mixed_sample = mixed_buffer[i]; - - mixed_sample.scale(m_main_volume); - mixed_sample.clip(); - - LittleEndian<i16> out_sample; - out_sample = mixed_sample.left * NumericLimits<i16>::max(); - stream << out_sample; - - out_sample = mixed_sample.right * NumericLimits<i16>::max(); - stream << out_sample; - } - - ASSERT(stream.is_end()); - ASSERT(!stream.has_any_error()); - m_device->write(stream.data(), stream.size()); - } - } -} - -void Mixer::set_main_volume(int volume) -{ - if (volume > 100) - m_main_volume = 100; - else - m_main_volume = volume; - ClientConnection::for_each([volume](ClientConnection& client) { - client.did_change_main_mix_volume({}, volume); - }); -} - -void Mixer::set_muted(bool muted) -{ - if (m_muted == muted) - return; - m_muted = muted; - ClientConnection::for_each([muted](ClientConnection& client) { - client.did_change_muted_state({}, muted); - }); -} - -BufferQueue::BufferQueue(ClientConnection& client) - : m_client(client) -{ -} - -void BufferQueue::enqueue(NonnullRefPtr<Audio::Buffer>&& buffer) -{ - m_remaining_samples += buffer->sample_count(); - m_queue.enqueue(move(buffer)); -} -} |