diff --git a/include/audio/channel.hpp b/include/audio/channel.hpp index beb9239..e989f16 100644 --- a/include/audio/channel.hpp +++ b/include/audio/channel.hpp @@ -46,6 +46,7 @@ namespace audio{ void resize_buffer(size_t newsize); + void play(const mixchunk& m); void play(const mixdata& m); void pause(); diff --git a/include/audio/mixdata.hpp b/include/audio/mixdata.hpp index 056be3b..7ab7500 100644 --- a/include/audio/mixdata.hpp +++ b/include/audio/mixdata.hpp @@ -24,11 +24,44 @@ namespace audio{ struct mixdata { - float* data; - size_t frames; - size_t channels; - size_t samplerate; + float* data = nullptr; + size_t frames = 0; + size_t channels = 0; + size_t samplerate = 0; float volume = 1; + bool allocated = true; + }; + + class mixchunk + { + private: + mixdata m_data; + + public: + constexpr mixchunk() = default; + mixchunk(size_t frames, size_t channels, size_t samplerate); + mixchunk(const mixdata&); + mixchunk(mixdata&&); + mixchunk(const mixchunk&); + mixchunk(mixchunk&&); + ~mixchunk(); + + mixchunk& operator=(const mixchunk&); + mixchunk& operator=(mixchunk&&); + + const float* data()const; + float* data(); + + size_t floats()const; + size_t frames()const; + size_t channels()const; + size_t samplerate()const; + float volume()const; + + void set_samplerate(size_t s); + void set_volume(float v); + + const mixdata& raw()const; }; } diff --git a/include/audio/mixer.hpp b/include/audio/mixer.hpp index 93dc23a..0efc05c 100644 --- a/include/audio/mixer.hpp +++ b/include/audio/mixer.hpp @@ -32,6 +32,7 @@ namespace audio{ { public: enum class mode : int{ + MONO = 1, STEREO = 2, }; private: diff --git a/include/audio/sndrd.hpp b/include/audio/sndrd.hpp index 00af015..62c652a 100644 --- a/include/audio/sndrd.hpp +++ b/include/audio/sndrd.hpp @@ -25,6 +25,7 @@ #include #include "error.hpp" +#include "mixdata.hpp" namespace audio{ @@ -64,7 +65,10 @@ namespace audio{ const SNDFILE* get(void)const noexcept; bool valid()const noexcept; + mixchunk read_all()noexcept; + mixchunk read(size_t items)noexcept; size_t read(float* dest, size_t items)noexcept; + mixchunk read_frames(size_t frames)noexcept; size_t read_frames(float* dest, size_t frames)noexcept; //TODO other formats diff --git a/include/config.hpp b/include/config.hpp index 39165c7..7bdeeba 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -1,5 +1,14 @@ #ifndef OUR_DICK_CONFIG_HPP #define OUR_DICK_CONFIG_HPP +//multiple levels just so i can stop alsa errors without stopping everything else +#define OUR_DICK_DEBUG 1 + +#ifdef OUR_DICK_DEBUG +#include + #define debug_print(...) fprintf(stderr, __VA_ARGS__) +#else + #define debug_print(...) +#endif #endif diff --git a/src/audio/channel.cpp b/src/audio/channel.cpp index 7b7187a..5a9763d 100644 --- a/src/audio/channel.cpp +++ b/src/audio/channel.cpp @@ -25,6 +25,9 @@ namespace audio{ channel::channel(impl::channel& c): m_impl(&c){} + void channel::play(const mixchunk& m){ + m_impl->play(m.raw()); + } void channel::play(const mixdata& m){ m_impl->play(m); } diff --git a/src/audio/init.cpp b/src/audio/init.cpp index 4dd4be3..ba19f5e 100644 --- a/src/audio/init.cpp +++ b/src/audio/init.cpp @@ -17,21 +17,28 @@ */ #include "audio/init.hpp" +#include "config.hpp" #include -#ifdef __gnu_linux__ +#if defined(__gnu_linux__) + #if !defined(OUR_DICK_DEBUG) || OUR_DICK_DEBUG <= 1 + #define ENABLE_ALSA_DEBUG + #endif +#endif + +#ifdef ENABLE_ALSA_DEBUG #include //va_arg (missing include in alsa headers) #include //snd_lib_error_set_handler namespace audio::detail{ - void linux_alsa_error_handler(const char* /*file*/, int /*line*/, const char* /*function*/, int /*err*/, const char* /*fmt*/,...){} + static void linux_alsa_error_handler(const char* /*file*/, int /*line*/, const char* /*function*/, int /*err*/, const char* /*fmt*/,...){} } #endif namespace audio{ pa_system::pa_system(){ -#ifdef __gnu_linux__ +#ifdef ENABLE_ALSA_DEBUG //silence excessive stderr warnings from alsa snd_lib_error_set_handler(detail::linux_alsa_error_handler); #endif diff --git a/src/audio/mixdata.cpp b/src/audio/mixdata.cpp new file mode 100644 index 0000000..de9d287 --- /dev/null +++ b/src/audio/mixdata.cpp @@ -0,0 +1,103 @@ +/** + This file is a part of our_dick + Copyright (C) 2020 rexy712 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +#include "audio/mixdata.hpp" + +#include //exchange, swap, move +#include //mpmcpy, memset + +namespace audio{ + + mixchunk::mixchunk(size_t frames, size_t channels, size_t samplerate): + m_data{new float[frames * channels](), frames, channels, samplerate, 1, true}{} + mixchunk::mixchunk(const mixdata& m): + m_data{new float[m.frames * m.channels](), m.frames, m.channels, m.samplerate, m.volume, true} + { + memcpy(m_data.data, m.data, m_data.frames * m_data.channels); + } + mixchunk::mixchunk(mixdata&& m): + m_data{std::exchange(m.data, nullptr), m.frames, m.channels, m.samplerate, m.volume, m.allocated}{} + mixchunk::mixchunk(const mixchunk& m): + mixchunk(m.m_data){} + mixchunk::mixchunk(mixchunk&& m): + mixchunk(std::move(m.m_data)){} + mixchunk::~mixchunk(){ + if(m_data.allocated) + delete[] m_data.data; + } + + mixchunk& mixchunk::operator=(const mixchunk& m){ + size_t this_floats = m_data.frames * m_data.channels; + size_t that_floats = m.m_data.frames * m.m_data.channels; + + if(this_floats > that_floats){ + memcpy(m_data.data, m.m_data.data, that_floats); + memset(m_data.data + that_floats, 0, this_floats - that_floats); + }else if(this_floats == that_floats){ + memcpy(m_data.data, m.m_data.data, that_floats); + }else{ + return (*this = mixchunk(m)); + } + m_data.frames = m.m_data.frames; + m_data.channels = m.m_data.channels; + m_data.samplerate = m.m_data.samplerate; + m_data.volume = m.m_data.volume; + return *this; + } + mixchunk& mixchunk::operator=(mixchunk&& m){ + std::swap(m_data.data, m.m_data.data); + std::swap(m_data.allocated, m.m_data.allocated); + m_data.frames = m.m_data.frames; + m_data.channels = m.m_data.channels; + m_data.samplerate = m.m_data.samplerate; + m_data.volume = m.m_data.volume; + return *this; + } + float* mixchunk::data(){ + return m_data.data; + } + const float* mixchunk::data()const{ + return m_data.data; + } + size_t mixchunk::floats()const{ + return frames() * channels(); + } + size_t mixchunk::frames()const{ + return m_data.frames; + } + size_t mixchunk::channels()const{ + return m_data.channels; + } + size_t mixchunk::samplerate()const{ + return m_data.samplerate; + } + float mixchunk::volume()const{ + return m_data.volume; + } + + void mixchunk::set_samplerate(size_t s){ + m_data.samplerate = s; + } + void mixchunk::set_volume(float v){ + m_data.volume = v; + } + const mixdata& mixchunk::raw()const{ + return m_data; + } + +} diff --git a/src/audio/sndrd.cpp b/src/audio/sndrd.cpp index 0d6e495..c72965d 100644 --- a/src/audio/sndrd.cpp +++ b/src/audio/sndrd.cpp @@ -74,9 +74,20 @@ namespace audio{ return m_fp && !last_error(); } + mixchunk sndrd::read_all()noexcept{ + return read_frames(frames()); + } + mixchunk sndrd::read(size_t items)noexcept{ + return read_frames(items / channels()); + } size_t sndrd::read(float* dest, size_t items)noexcept{ return sf_read_float(m_fp, dest, items); } + mixchunk sndrd::read_frames(size_t fcnt)noexcept{ + mixchunk c(fcnt, channels(), samplerate()); + read_frames(c.data(), fcnt); + return c; + } size_t sndrd::read_frames(float* dest, size_t frames)noexcept{ return sf_readf_float(m_fp, dest, frames); } diff --git a/src/main.cpp b/src/main.cpp index 0f4e4ea..2db38fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include "render.hpp" #include "game_state.hpp" #include "math/math.hpp" +#include "config.hpp" // 0 | 1 | 2 // --------- @@ -89,12 +90,12 @@ void play_audio(){ } void handle_window_close(){ - printf("[II] Window close event triggered\n"); + debug_print("[II] Window close event triggered\n"); running = false; } void handle_input_events(GLFWwindow*, int key, int, int, int){ - printf("[II] Recieved keycode %d\n", key); + debug_print("[II] Recieved keycode %d\n", key); if(key == 256) manager.request_exit(); } diff --git a/src/render.cpp b/src/render.cpp index abc0337..0027630 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -1,10 +1,11 @@ #include // Must be included first #include "render.hpp" +#include "config.hpp" #include namespace{ void handle_resize_event(GLFWwindow*, int width, int height){ - printf("Window resized\n"); + debug_print("Window resized\n"); glViewport(0, 0, width, height); } } @@ -39,7 +40,7 @@ render_manager::renderer_error render_manager::init (int width, int height, cons glViewport(0, 0, width, height); - printf("[DD] OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION)); + debug_print("[DD] OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION)); glfwSetFramebufferSizeCallback(m_main_window, handle_resize_event);