Start work on audio stuff

This commit is contained in:
rexy712 2020-08-17 20:04:43 -07:00
parent 56ccd0b5b7
commit e3a89822be
7 changed files with 328 additions and 3 deletions

61
include/audio/detail.hpp Normal file
View File

@ -0,0 +1,61 @@
/**
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/>.
*/
#ifndef OUR_DICK_AUDIO_DETAIL_HPP
#define OUR_DICK_AUDIO_DETAIL_HPP
#include <tuple> //tuple, get
#include <utility> //forward, integer_sequence
namespace audio::detail{
template<typename Func, typename... Args>
struct callback_helper{
Func&& m_f;
std::tuple<Args...> m_args;
template<int... Indices>
int operator()(const void* input, void* output, unsigned long frame_count, std::integer_sequence<int,Indices...>){
return std::forward<Func>(m_f)(input, output, frame_count, std::get<Indices>(m_args)...);
}
};
class callback_iface
{
public:
callback_iface() = default;
virtual ~callback_iface() = default;
virtual int operator()(const void* input, void* output, unsigned long frame_count) = 0;
};
template<typename Func, typename... Args>
class callback_impl : public callback_iface
{
private:
callback_helper<Func,Args...> m_ch;
public:
template<class Fn, class... Ts>
callback_impl(Fn&& f, Ts&&... ts):
m_ch{std::forward<Fn>(f), {std::forward<Ts>(ts)...}}{}
int operator()(const void* input, void* output, unsigned long frame_count)override{
return m_ch(input, output, frame_count, typename ::detail::sequence_gen<sizeof...(Args)>::type{});
}
};
}
#endif

33
include/audio/init.hpp Normal file
View File

@ -0,0 +1,33 @@
/**
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/>.
*/
#ifndef OUR_DICK_AUDIO_INIT_HPP
#define OUR_DICK_AUDIO_INIT_HPP
namespace audio{
class pa_system
{
public:
pa_system();
~pa_system();
};
}
#endif

73
include/audio/stream.hpp Normal file
View File

@ -0,0 +1,73 @@
/**
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/>.
*/
#ifndef OUR_DICK_AUDIO_STREAM_HPP
#define OUR_DICK_AUDIO_STREAM_HPP
#include <utility> //forward
#include <portaudio.h>
#include "detail/utility.hpp"
#include "detail.hpp"
namespace audio{
enum class stream_fmt{
float32 = paFloat32,
};
class stream
{
private:
detail::callback_iface* m_cb = nullptr;
PaStream* m_stream = nullptr;
PaError m_err = paNoError;
public:
template<typename Callback, typename... Args>
stream(int in_c, int out_c, stream_fmt fmt, double samplerate, size_t buffersize, Callback&& cb, Args&&... cbargs):
m_cb(new detail::callback_impl<Callback,Args...>(std::forward<Callback>(cb), std::forward<Args>(cbargs)...)),
m_stream(initialize_global_instance()),
m_err(open_default_stream(&m_stream, in_c, out_c, fmt, samplerate, buffersize, m_cb)){}
~stream();
int start();
int stop();
int abort();
int close();
bool is_stopped()const;
bool is_active()const;
int last_error()const;
private:
static PaStream* initialize_global_instance();
//to avoid using portaudio functions in the header
static int open_default_stream(PaStream*, int in_c, int out_c,
stream_fmt fmt, double samplerate,
size_t bufsize, detail::callback_iface* cb);
static int callback(const void* input, void* output, unsigned long framecount,
const PaStreamCallbackTimeInfo* /*timeInfo*/, PaStreamCallbackFlags /*statusFlags*/,
void* userdata);
};
}
#endif

View File

@ -0,0 +1,36 @@
/**
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/>.
*/
#ifndef OUR_DICK_UTILITY_HPP
#define OUR_DICK_UTILITY_HPP
#include <utility> //integer_sequence
namespace detail{
template<int I, int... Is>
struct sequence_gen{
using type = typename sequence_gen<I-1, Is..., sizeof...(Is)>::type;
};
template<int... Is>
struct sequence_gen<0,Is...>{
using type = std::integer_sequence<int,Is...>;
};
}
#endif

View File

@ -19,7 +19,7 @@ ifeq ($(OS),Windows_NT)
WINDOWS::=1
endif
SOURCE_DIRS::=src
SOURCE_DIRS::=src src/audio
SOURCES::=
OBJDIR::=obj
DEPDIR::=$(OBJDIR)/dep
@ -40,7 +40,7 @@ ifneq ($(WINDOWS),1)
CC::=gcc
CXX::=g++
LDLIBS::=
LDFLAGS::= -lglfw -lgl3w -ldl -lm
LDFLAGS::= -lglfw -lgl3w -ldl -lm -lportaudio -lasound
STRIP::=strip
RANLIB::=ranlib
AR::=ar
@ -51,7 +51,7 @@ else #windows
MINGW_PREFIX::=x86_64-w64-mingw32-
CC::=$(MINGW_PREFIX)gcc
CXX::=$(MINGW_PREFIX)g++
LDLIBS::=
LDLIBS::=-lglfw -lgl3w -ldl -lm -lportaudio
LDFLAGS::=
STRIP::=$(MINGW_PREFIX)strip
RANLIB::=$(MINGW_PREFIX)ranlib

44
src/audio/init.cpp Normal file
View File

@ -0,0 +1,44 @@
/**
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/init.hpp"
#include <portaudio.h>
#ifdef __gnu_linux__
#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*/,...){}
}
#endif
namespace audio{
pa_system::pa_system(){
#ifdef __gnu_linux__
//silence excessive stderr warnings from alsa
snd_lib_error_set_handler(detail::linux_alsa_error_handler);
#endif
Pa_Initialize();
}
pa_system::~pa_system(){
Pa_Terminate();
}
}

78
src/audio/stream.cpp Normal file
View File

@ -0,0 +1,78 @@
/**
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/stream.hpp"
#include "audio/init.hpp"
#include <portaudio.h>
namespace audio{
stream::~stream(){
close();
delete m_cb;
}
int stream::start(){
return m_err = Pa_StartStream(m_stream);
}
int stream::stop(){
return m_err = Pa_StopStream(m_stream);
}
int stream::abort(){
return m_err = Pa_AbortStream(m_stream);
}
bool stream::is_stopped()const{
return Pa_IsStreamStopped(m_stream);
}
bool stream::is_active()const{
return Pa_IsStreamActive(m_stream);
}
int stream::close(){
if(m_stream){
m_err = Pa_CloseStream(m_stream);
m_stream = nullptr;
return m_err;
}
return paNotInitialized;
}
int stream::last_error()const{
return m_err;
}
PaStream* stream::initialize_global_instance(){
static pa_system sys;
return nullptr;
}
int stream::open_default_stream(PaStream* stream, int in_c, int out_c,
stream_fmt fmt, double samplerate,
size_t bufsize, detail::callback_iface* cb)
{
return Pa_OpenDefaultStream(&stream, in_c, out_c, static_cast<int>(fmt), samplerate, bufsize, callback, cb);
}
int stream::callback(const void* input, void* output, unsigned long framecount,
const PaStreamCallbackTimeInfo* /*timeInfo*/, PaStreamCallbackFlags /*statusFlags*/,
void* userdata)
{
detail::callback_iface* cb = static_cast<detail::callback_iface*>(userdata);
return (*cb)(input, output, framecount);
}
}