Audio file simplifications, add a couple debug utilities

This commit is contained in:
rexy712 2020-08-22 11:59:12 -07:00
parent a71c3c27c4
commit 1987f3b9fa
11 changed files with 185 additions and 11 deletions

View File

@ -46,6 +46,7 @@ namespace audio{
void resize_buffer(size_t newsize);
void play(const mixchunk& m);
void play(const mixdata& m);
void pause();

View File

@ -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;
};
}

View File

@ -32,6 +32,7 @@ namespace audio{
{
public:
enum class mode : int{
MONO = 1,
STEREO = 2,
};
private:

View File

@ -25,6 +25,7 @@
#include <type_traits>
#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

View File

@ -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 <cstdio>
#define debug_print(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug_print(...)
#endif
#endif

View File

@ -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);
}

View File

@ -17,21 +17,28 @@
*/
#include "audio/init.hpp"
#include "config.hpp"
#include <portaudio.h>
#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 <cstdarg> //va_arg (missing include in alsa headers)
#include <alsa/error.h> //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

103
src/audio/mixdata.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "audio/mixdata.hpp"
#include <utility> //exchange, swap, move
#include <cstring> //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;
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -1,10 +1,11 @@
#include <gl3w/GL/gl3w.h> // Must be included first
#include "render.hpp"
#include "config.hpp"
#include <cstdio>
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);