From fb1c08639023f687c48ec5b9386b346825e4aa6e Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Tue, 8 Sep 2015 18:14:42 -0500 Subject: [PATCH 01/59] Started work on changing to libsoundio for audio --- .gitmodules | 3 + CMakeLists.txt | 1 + .../include/moon/gorilla/audio.hxx | 1 + modules/audio-gorilla/src/audio.cxx | 1 - modules/audio-gorilla/src/mrb_sound.cxx | 2 +- .../include/moon/audio/libsoundio/audio.hxx | 20 +++ .../mrbgem.rake | 0 .../mrblib/audio.rb | 0 modules/audio-libsoundio/src/audio.cxx | 55 ++++++ modules/audio-portaudio/src/audio.cxx | 19 -- modules/audio/include/moon/audio_stream.hxx | 14 ++ .../audio/include/moon/mrb/audio_stream.hxx | 12 ++ modules/audio/src/mrb_audio_stream.cxx | 168 ++++++++++++++++++ vendor/libsoundio | 1 + 14 files changed, 276 insertions(+), 21 deletions(-) create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx rename modules/{audio-portaudio => audio-libsoundio}/mrbgem.rake (100%) rename modules/{audio-portaudio => audio-libsoundio}/mrblib/audio.rb (100%) create mode 100644 modules/audio-libsoundio/src/audio.cxx delete mode 100644 modules/audio-portaudio/src/audio.cxx create mode 100644 modules/audio/include/moon/audio_stream.hxx create mode 100644 modules/audio/include/moon/mrb/audio_stream.hxx create mode 100644 modules/audio/src/mrb_audio_stream.cxx create mode 160000 vendor/libsoundio diff --git a/.gitmodules b/.gitmodules index cb03a84..639cb6c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -27,3 +27,6 @@ [submodule "vendor/gorilla-audio"] path = vendor/gorilla-audio url = https://github.com/IceDragon200/gorilla-audio.git +[submodule "vendor/libsoundio"] + path = vendor/libsoundio + url = https://github.com/andrewrk/libsoundio diff --git a/CMakeLists.txt b/CMakeLists.txt index b5c714e..2760bae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory("vendor/sil") get_filename_component(SIL_INCLUDE_DIR "vendor/sil/include" ABSOLUTE) add_subdirectory("vendor/soil") add_subdirectory("vendor/gorilla-audio/build") +add_subdirectory("vendor/libsoundio") #add_subdirectory("vendor/glm") option(freetype-gl_BUILD_DEMOS OFF) diff --git a/modules/audio-gorilla/include/moon/gorilla/audio.hxx b/modules/audio-gorilla/include/moon/gorilla/audio.hxx index 0215b19..1828b8a 100644 --- a/modules/audio-gorilla/include/moon/gorilla/audio.hxx +++ b/modules/audio-gorilla/include/moon/gorilla/audio.hxx @@ -14,6 +14,7 @@ namespace Moon { static ga_Mixer* GetMixer(); static ga_StreamManager* GetStreamMgr(); protected: + static bool m_initialized; static gau_Manager* m_mgr; static ga_Mixer* m_mixer; static ga_StreamManager* m_streamMgr; diff --git a/modules/audio-gorilla/src/audio.cxx b/modules/audio-gorilla/src/audio.cxx index 3871200..e783a4f 100644 --- a/modules/audio-gorilla/src/audio.cxx +++ b/modules/audio-gorilla/src/audio.cxx @@ -41,4 +41,3 @@ namespace Moon { return m_streamMgr; }; } - diff --git a/modules/audio-gorilla/src/mrb_sound.cxx b/modules/audio-gorilla/src/mrb_sound.cxx index e7e22de..7e4d35e 100644 --- a/modules/audio-gorilla/src/mrb_sound.cxx +++ b/modules/audio-gorilla/src/mrb_sound.cxx @@ -16,7 +16,7 @@ sound_free(mrb_state *mrb, void *p) } } -MOON_C_API const struct mrb_data_type sound_data_type = { "Sound", sound_free }; +MOON_C_API const struct mrb_data_type sound_data_type = { "Moon::Sound", sound_free }; static inline ga_Sound* get_sound(mrb_state *mrb, mrb_value self) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx new file mode 100644 index 0000000..5195742 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx @@ -0,0 +1,20 @@ +#ifndef MOON_AUDIO_H +#define MOON_AUDIO_H + +#include + +namespace Moon { + class Audio { + public: + static bool Initialize(); + static void Update(); + static void Terminate(); + protected: + static bool m_initialized; + static struct SoundIo *m_soundIO; + static struct SoundIoDevice *m_device; + static struct SoundIoOutStream *m_outStream; + }; +}; + +#endif diff --git a/modules/audio-portaudio/mrbgem.rake b/modules/audio-libsoundio/mrbgem.rake similarity index 100% rename from modules/audio-portaudio/mrbgem.rake rename to modules/audio-libsoundio/mrbgem.rake diff --git a/modules/audio-portaudio/mrblib/audio.rb b/modules/audio-libsoundio/mrblib/audio.rb similarity index 100% rename from modules/audio-portaudio/mrblib/audio.rb rename to modules/audio-libsoundio/mrblib/audio.rb diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx new file mode 100644 index 0000000..4101366 --- /dev/null +++ b/modules/audio-libsoundio/src/audio.cxx @@ -0,0 +1,55 @@ +#include "moon/audio/libsoundio/audio.hxx" + +static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frame_count_min, int frame_count_max) { + // Do evil stuff later. +} + +namespace Moon +{ + void Audio::Initialize() + { + m_soundIO = soundio_create(); + // Should I use assert, or set a flag and leave it for mruby to pick up? + assert(m_soundIO); + int err = soundio_connect(m_soundIO); + if (err) { + // Say bad things happened, and moon will now implode. + } + soundio_flush_events(m_soundIO); + const int defaultDeviceIndex = soundio_default_output_device_index(m_soundIO); + if (defaultDeviceIndex < 0) { + // Now that I think about it, we could have an error field :D + } + m_device = soundio_get_output_device(m_soundIO, defaultDeviceIndex); + // if m_device is null we should raise AudioError, "device not present, out of memory?" + m_outStream = soundio_outstream_create(m_device); + // High quality shiiit :3 + m_outStream->format = SoundIoFormatFloat32NE; + m_outStream->writeCallback = Moon_AudioWrite; + + err = soundio_outstream_open(m_outStream); + if (err) { + // raise AudioError, "stream could not be opened" + } + if (m_outStream->layout_error) { + // raise AudioError, "unable to set channel layout" + } + err = soundio_outstream_start(m_outStream); + if (err) { + // raise AudioError, "unable to start device" + } + // Finally, after bashing your head against the table, you can finally have audio? + } + + void Audio::Update() + { + soundio_flush_events(m_soundIO); + } + + void Audio::Terminate() + { + soundio_outstream_destroy(m_outStream); + soundio_device_unref(m_device); + soundio_destroy(m_soundIO); + } +} diff --git a/modules/audio-portaudio/src/audio.cxx b/modules/audio-portaudio/src/audio.cxx deleted file mode 100644 index b34e020..0000000 --- a/modules/audio-portaudio/src/audio.cxx +++ /dev/null @@ -1,19 +0,0 @@ -#include "moon/portaudio/audio.hxx" - -namespace Moon -{ - void Audio::Initialize() - { - - } - - void Audio::Update() - { - - } - - void Audio::Terminate() - { - - } -} diff --git a/modules/audio/include/moon/audio_stream.hxx b/modules/audio/include/moon/audio_stream.hxx new file mode 100644 index 0000000..637de67 --- /dev/null +++ b/modules/audio/include/moon/audio_stream.hxx @@ -0,0 +1,14 @@ +#ifndef MOON_STREAM_H +#define MOON_STREAM_H + +#include "moon/audio.hxx" + +namespace Moon { + struct Stream { + Stream() : handle(NULL), loopSrc(NULL) { }; + ga_Handle* handle; + gau_SampleSourceLoop* loopSrc; + }; +}; + +#endif diff --git a/modules/audio/include/moon/mrb/audio_stream.hxx b/modules/audio/include/moon/mrb/audio_stream.hxx new file mode 100644 index 0000000..b8544f5 --- /dev/null +++ b/modules/audio/include/moon/mrb/audio_stream.hxx @@ -0,0 +1,12 @@ +#ifndef MMRB_AUDIO_STREAM_H +#define MMRB_AUDIO_STREAM_H + +#include +#include +#include +#include "moon/api.h" + +MOON_C_API const struct mrb_data_type audio_stream_data_type; +MOON_C_API void mmrb_audio_stream_init(mrb_state *mrb, struct RClass *mod); + +#endif diff --git a/modules/audio/src/mrb_audio_stream.cxx b/modules/audio/src/mrb_audio_stream.cxx new file mode 100644 index 0000000..c113176 --- /dev/null +++ b/modules/audio/src/mrb_audio_stream.cxx @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include "moon/mrb/stream.hxx" +#include "moon/stream.hxx" +#include "moon/api.h" +#include "moon/intern.h" + +static void +audio_stream_free(mrb_state *mrb, void *p) +{ + Moon::AudioStream* music = (Moon::AudioStream*)p; + if (music) { + if (music->handle) { + ga_handle_destroy(music->handle); + } + delete(music); + } +} + +MOON_C_API const struct mrb_data_type audio_stream_data_type = { "Moon::AudioStream", audio_stream_free }; + +static inline Moon::AudioStream* +get_music(mrb_state *mrb, mrb_value self) +{ + return (Moon::AudioStream*)mrb_data_get_ptr(mrb, self, &audio_stream_data_type); +} + +static mrb_value +audio_stream_initialize(mrb_state *mrb, mrb_value self) +{ + char *filename; + char *format; + Moon::AudioStream *music; + + mrb_get_args(mrb, "zz", &filename, &format); + + music = (Moon::AudioStream*)DATA_PTR(self); + if (music) { + audio_stream_free(mrb, (void*)music); + } + music = new Moon::AudioStream(); + + if (exists(filename)) { + music->handle = gau_create_handle_buffered_file(Moon::Audio::GetMixer(), Moon::Audio::GetStreamMgr(), + filename, format, + NULL, 0, &(music->loopSrc)); + } else { + mrb_raisef(mrb, E_SCRIPT_ERROR, "cannot load such file -- %S", mrb_str_new_cstr(mrb, filename)); + } + + mrb_data_init(self, music, &audio_stream_data_type); + + return self; +} + +static mrb_value +audio_stream_play(mrb_state *mrb, mrb_value self) +{ + mrb_float gain = 1.0; + mrb_float pitch = 1.0; + mrb_float pan = 0.0; + Moon::AudioStream *music = get_music(mrb, self); + mrb_get_args(mrb, "|fff", &gain, &pitch, &pan); + ga_handle_setParamf(music->handle, GA_HANDLE_PARAM_GAIN, gain); + ga_handle_setParamf(music->handle, GA_HANDLE_PARAM_PITCH, pitch); + ga_handle_setParamf(music->handle, GA_HANDLE_PARAM_PAN, pan); + ga_handle_play(music->handle); + + return mrb_nil_value(); +}; + +static mrb_value +audio_stream_stop(mrb_state *mrb, mrb_value self) +{ + Moon::AudioStream *music = get_music(mrb, self); + ga_handle_stop(music->handle); + return mrb_nil_value(); +}; + +static mrb_value +audio_stream_is_playing(mrb_state *mrb, mrb_value self) +{ + Moon::AudioStream *music = get_music(mrb, self); + return mrb_bool_value(ga_handle_playing(music->handle)); +} + +static mrb_value +audio_stream_is_stopped(mrb_state *mrb, mrb_value self) +{ + Moon::AudioStream *music = get_music(mrb, self); + return mrb_bool_value(ga_handle_stopped(music->handle)); +} + +static mrb_value +audio_stream_is_finished(mrb_state *mrb, mrb_value self) +{ + Moon::AudioStream *music = get_music(mrb, self); + return mrb_bool_value(ga_handle_finished(music->handle)); +} + +static mrb_value +audio_stream_seek(mrb_state *mrb, mrb_value self) +{ + mrb_int offset; + Moon::AudioStream *music = get_music(mrb, self); + mrb_get_args(mrb, "i", &offset); + return mrb_bool_value(ga_handle_seek(music->handle, offset)); +} + +static mrb_value +audio_stream_pos(mrb_state *mrb, mrb_value self) +{ + Moon::AudioStream *music = get_music(mrb, self); + return mrb_fixnum_value(ga_handle_tell(music->handle, GA_TELL_PARAM_CURRENT)); +} + +static mrb_value +audio_stream_length(mrb_state *mrb, mrb_value self) +{ + Moon::AudioStream *music = get_music(mrb, self); + return mrb_fixnum_value(ga_handle_tell(music->handle, GA_TELL_PARAM_TOTAL)); +} + +static mrb_value +audio_stream_loop(mrb_state *mrb, mrb_value self) +{ + mrb_int trigger = -1; + mrb_int target = 0; + Moon::AudioStream *music = get_music(mrb, self); + mrb_get_args(mrb, "|ii", &trigger, &target); + gau_sample_source_loop_set(music->loopSrc, trigger, target); + return mrb_nil_value(); +} + +static mrb_value +audio_stream_clear_loop(mrb_state *mrb, mrb_value self) +{ + Moon::AudioStream *music = get_music(mrb, self); + gau_sample_source_loop_clear(music->loopSrc); + return mrb_bool_value(true); +} + +MOON_C_API void +mmrb_audio_stream_init(mrb_state *mrb, struct RClass *mod) +{ + struct RClass *audio_stream_class = mrb_define_class_under(mrb, mod, "Stream", mrb->object_class); + MRB_SET_INSTANCE_TT(audio_stream_class, MRB_TT_DATA); + + mrb_define_method(mrb, audio_stream_class, "initialize", audio_stream_initialize, MRB_ARGS_REQ(2)); + + /* Playback */ + mrb_define_method(mrb, audio_stream_class, "play", audio_stream_play, MRB_ARGS_OPT(3)); + mrb_define_method(mrb, audio_stream_class, "stop", audio_stream_stop, MRB_ARGS_NONE()); + + /* Position */ + mrb_define_method(mrb, audio_stream_class, "seek", audio_stream_seek, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, audio_stream_class, "pos", audio_stream_pos, MRB_ARGS_NONE()); + mrb_define_method(mrb, audio_stream_class, "length", audio_stream_length, MRB_ARGS_NONE()); + mrb_define_method(mrb, audio_stream_class, "loop", audio_stream_loop, MRB_ARGS_OPT(2)); + mrb_define_method(mrb, audio_stream_class, "clear_loop", audio_stream_clear_loop, MRB_ARGS_NONE()); + + /* Query */ + mrb_define_method(mrb, audio_stream_class, "playing?", audio_stream_is_playing, MRB_ARGS_NONE()); + mrb_define_method(mrb, audio_stream_class, "stopped?", audio_stream_is_stopped, MRB_ARGS_NONE()); + mrb_define_method(mrb, audio_stream_class, "finished?", audio_stream_is_finished, MRB_ARGS_NONE()); +} diff --git a/vendor/libsoundio b/vendor/libsoundio new file mode 160000 index 0000000..4eb5b4b --- /dev/null +++ b/vendor/libsoundio @@ -0,0 +1 @@ +Subproject commit 4eb5b4bbe4de7e316bf32038849564dda50d9ebc From dc44e7d7080c227776661c8d9d9e981c9608d64d Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 12:28:44 -0500 Subject: [PATCH 02/59] Added libsoundio paths to build, moved to libsoundio as the default audio gem Moved gorilla linker line into the gorilla audio gem --- modules/audio-gorilla/mrbgem.rake | 6 +++--- modules/audio-libsoundio/mrbgem.rake | 8 ++++++-- modules/audio-libsoundio/mrblib/audio.rb | 2 +- modules/moon.gembox | 4 +++- mrb_config.rb | 3 ++- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/modules/audio-gorilla/mrbgem.rake b/modules/audio-gorilla/mrbgem.rake index 77fc52b..aa5e0b5 100644 --- a/modules/audio-gorilla/mrbgem.rake +++ b/modules/audio-gorilla/mrbgem.rake @@ -17,9 +17,9 @@ MRuby::Gem::Specification.new('mruby-moon-audio-gorilla') do |spec| cc.flags << '-Wextra' end - #spec.cxx do |cxx| - # cxx.flags << '-std=c++11' - #end + spec.linker do |l| + l.libraries << 'gorilla' + end spec.add_dependency 'mruby-moon-system' end diff --git a/modules/audio-libsoundio/mrbgem.rake b/modules/audio-libsoundio/mrbgem.rake index 2d26341..2de2efa 100644 --- a/modules/audio-libsoundio/mrbgem.rake +++ b/modules/audio-libsoundio/mrbgem.rake @@ -1,10 +1,10 @@ #encoding:UTF-8 -MRuby::Gem::Specification.new('mruby-moon-audio-portaudio') do |spec| +MRuby::Gem::Specification.new('mruby-moon-audio-libsoundio') do |spec| spec.license = 'MIT' spec.authors = ['Blaž Hrastnik', 'Corey Powell'] spec.version = '0.0.0' spec.summary = 'Moon audio modules' - spec.description = 'Moon Engine\'s audio module (using Port Audio)' + spec.description = 'Moon Engine\'s audio module (using SoundIO)' spec.homepage = 'https://github.com/polyfox/moon' # compiler config spec.cc.include_paths << ["#{build.root}/src", "#{build.root}/include"] @@ -17,5 +17,9 @@ MRuby::Gem::Specification.new('mruby-moon-audio-portaudio') do |spec| cc.flags << '-Wextra' end + spec.linker do |l| + l.libraries << 'soundio' + end + spec.add_dependency 'mruby-moon-system' end diff --git a/modules/audio-libsoundio/mrblib/audio.rb b/modules/audio-libsoundio/mrblib/audio.rb index 7740a33..640f823 100644 --- a/modules/audio-libsoundio/mrblib/audio.rb +++ b/modules/audio-libsoundio/mrblib/audio.rb @@ -1,5 +1,5 @@ module Moon module Audio - NAME = 'moon-audio-portaudio' + NAME = 'moon-audio-libsoundio' end end diff --git a/modules/moon.gembox b/modules/moon.gembox index 41cd0a8..aad4043 100644 --- a/modules/moon.gembox +++ b/modules/moon.gembox @@ -14,9 +14,11 @@ MRuby::GemBox.new do |conf| # moon-graphics conf.gem File.join(d, 'graphics') # moon-audio-gorilla - conf.gem File.join(d, 'audio-gorilla') + #conf.gem File.join(d, 'audio-gorilla') # moon-audio-portaudio #conf.gem File.join(d, 'audio-portaudio') + # moon-audio-libsoundio + conf.gem File.join(d, 'audio-libsoundio') # moon-audio-portaudio #conf.gem File.join(d, 'audio-null') # moon-engine diff --git a/mrb_config.rb b/mrb_config.rb index 7c02b88..6bef576 100644 --- a/mrb_config.rb +++ b/mrb_config.rb @@ -100,6 +100,7 @@ c.include_paths << File.expand_path('soil/include', vd) c.include_paths << File.expand_path('sil/include', vd) c.include_paths << File.expand_path('freetype-gl', vd) + c.include_paths << File.expand_path('libsoundio', vd) # required audio includes c.include_paths << File.expand_path('gorilla-audio/include', vd) c.include_paths.uniq! @@ -111,13 +112,13 @@ l.library_paths << File.expand_path('glfw/src', bvd) l.library_paths << File.expand_path('freetype-gl', bvd) l.library_paths << File.expand_path('gorilla-audio/build', bvd) + l.library_paths << File.expand_path('libsoundio', bvd) l.library_paths << File.expand_path('sil', bvd) l.library_paths << File.expand_path('soil', bvd) l.library_paths.uniq! l.libraries << 'glfw' l.libraries << 'freetype-gl' - l.libraries << 'gorilla' l.libraries << 'freetype' l.libraries << 'SOIL' l.libraries << 'SIL' From a776a2012775a73cf11fdd08c919ec3c25100606 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 12:29:16 -0500 Subject: [PATCH 03/59] modules/audio-gorilla: Moved headers to mimic libsoundio module --- .../include/moon/{ => audio}/gorilla/audio.hxx | 5 +++-- .../include/moon/{ => audio}/gorilla/mrb/music.hxx | 0 .../include/moon/{ => audio}/gorilla/mrb/sound.hxx | 0 .../include/moon/{ => audio}/gorilla/music.hxx | 2 +- modules/audio-gorilla/src/audio.cxx | 2 +- modules/audio-gorilla/src/mrb_moon_audio.cxx | 6 +++--- modules/audio-gorilla/src/mrb_music.cxx | 4 ++-- modules/audio-gorilla/src/mrb_sound.cxx | 4 ++-- 8 files changed, 12 insertions(+), 11 deletions(-) rename modules/audio-gorilla/include/moon/{ => audio}/gorilla/audio.hxx (82%) rename modules/audio-gorilla/include/moon/{ => audio}/gorilla/mrb/music.hxx (100%) rename modules/audio-gorilla/include/moon/{ => audio}/gorilla/mrb/sound.hxx (100%) rename modules/audio-gorilla/include/moon/{ => audio}/gorilla/music.hxx (83%) diff --git a/modules/audio-gorilla/include/moon/gorilla/audio.hxx b/modules/audio-gorilla/include/moon/audio/gorilla/audio.hxx similarity index 82% rename from modules/audio-gorilla/include/moon/gorilla/audio.hxx rename to modules/audio-gorilla/include/moon/audio/gorilla/audio.hxx index 1828b8a..70f4850 100644 --- a/modules/audio-gorilla/include/moon/gorilla/audio.hxx +++ b/modules/audio-gorilla/include/moon/audio/gorilla/audio.hxx @@ -1,9 +1,10 @@ -#ifndef MOON_AUDIO_H -#define MOON_AUDIO_H +#ifndef MOON_AUDIO_GORILLA_H +#define MOON_AUDIO_GORILLA_H /* Gorilla Audio */ #include #include +#define MOON_AUDIO_BACKEND "gorilla" namespace Moon { class Audio { diff --git a/modules/audio-gorilla/include/moon/gorilla/mrb/music.hxx b/modules/audio-gorilla/include/moon/audio/gorilla/mrb/music.hxx similarity index 100% rename from modules/audio-gorilla/include/moon/gorilla/mrb/music.hxx rename to modules/audio-gorilla/include/moon/audio/gorilla/mrb/music.hxx diff --git a/modules/audio-gorilla/include/moon/gorilla/mrb/sound.hxx b/modules/audio-gorilla/include/moon/audio/gorilla/mrb/sound.hxx similarity index 100% rename from modules/audio-gorilla/include/moon/gorilla/mrb/sound.hxx rename to modules/audio-gorilla/include/moon/audio/gorilla/mrb/sound.hxx diff --git a/modules/audio-gorilla/include/moon/gorilla/music.hxx b/modules/audio-gorilla/include/moon/audio/gorilla/music.hxx similarity index 83% rename from modules/audio-gorilla/include/moon/gorilla/music.hxx rename to modules/audio-gorilla/include/moon/audio/gorilla/music.hxx index 8e97307..157f65b 100644 --- a/modules/audio-gorilla/include/moon/gorilla/music.hxx +++ b/modules/audio-gorilla/include/moon/audio/gorilla/music.hxx @@ -1,7 +1,7 @@ #ifndef MOON_MUSIC_H #define MOON_MUSIC_H -#include "moon/gorilla/audio.hxx" +#include "moon/audio/gorilla/audio.hxx" namespace Moon { struct Music { diff --git a/modules/audio-gorilla/src/audio.cxx b/modules/audio-gorilla/src/audio.cxx index e783a4f..49e3869 100644 --- a/modules/audio-gorilla/src/audio.cxx +++ b/modules/audio-gorilla/src/audio.cxx @@ -1,4 +1,4 @@ -#include "moon/gorilla/audio.hxx" +#include "moon/audio/gorilla/audio.hxx" namespace Moon { gau_Manager* Audio::m_mgr = NULL; diff --git a/modules/audio-gorilla/src/mrb_moon_audio.cxx b/modules/audio-gorilla/src/mrb_moon_audio.cxx index cd82a80..86aa53a 100644 --- a/modules/audio-gorilla/src/mrb_moon_audio.cxx +++ b/modules/audio-gorilla/src/mrb_moon_audio.cxx @@ -1,8 +1,8 @@ #include #include -#include "moon/gorilla/audio.hxx" -#include "moon/gorilla/mrb/music.hxx" -#include "moon/gorilla/mrb/sound.hxx" +#include "moon/audio/gorilla/audio.hxx" +#include "moon/audio/gorilla/mrb/music.hxx" +#include "moon/audio/gorilla/mrb/sound.hxx" /* Call once per step/frame to update the internal Audio module. */ diff --git a/modules/audio-gorilla/src/mrb_music.cxx b/modules/audio-gorilla/src/mrb_music.cxx index 1cc01be..3f40445 100644 --- a/modules/audio-gorilla/src/mrb_music.cxx +++ b/modules/audio-gorilla/src/mrb_music.cxx @@ -2,8 +2,8 @@ #include #include #include -#include "moon/gorilla/mrb/music.hxx" -#include "moon/gorilla/music.hxx" +#include "moon/audio/gorilla/mrb/music.hxx" +#include "moon/audio/gorilla/music.hxx" #include "moon/api.h" #include "moon/intern.h" diff --git a/modules/audio-gorilla/src/mrb_sound.cxx b/modules/audio-gorilla/src/mrb_sound.cxx index 7e4d35e..77aab1c 100644 --- a/modules/audio-gorilla/src/mrb_sound.cxx +++ b/modules/audio-gorilla/src/mrb_sound.cxx @@ -2,8 +2,8 @@ #include #include #include -#include "moon/gorilla/mrb/sound.hxx" -#include "moon/gorilla/audio.hxx" +#include "moon/audio/gorilla/mrb/sound.hxx" +#include "moon/audio/gorilla/audio.hxx" #include "moon/api.h" #include "moon/intern.h" From 933bb5ff21fba3d8c12ee1d878e62e9d84e62ca2 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 13:35:38 -0500 Subject: [PATCH 04/59] modules/audio-libsoundio: Stubbed audio structs So far. --- .../include/moon/audio/libsoundio/audio.hxx | 27 ++++- .../moon/audio/libsoundio/mrb/music.hxx | 12 ++ .../moon/audio/libsoundio/mrb/sound.hxx | 12 ++ .../audio/libsoundio/mrb/sound_buffer.hxx | 12 ++ .../include/moon/audio/libsoundio/music.hxx | 8 ++ .../include/moon/audio/libsoundio/sound.hxx | 12 ++ .../moon/audio/libsoundio/sound_buffer.hxx | 32 +++++ .../audio-libsoundio/mrblib/sound_buffer.rb | 13 ++ modules/audio-libsoundio/src/audio.cxx | 37 ++++-- .../audio-libsoundio/src/mrb_moon_audio.cxx | 58 +++++++++ modules/audio-libsoundio/src/mrb_music.cxx | 13 ++ modules/audio-libsoundio/src/mrb_sound.cxx | 13 ++ .../audio-libsoundio/src/mrb_sound_buffer.cxx | 114 ++++++++++++++++++ modules/system/include/moon/intern.h | 14 +++ mrb_config.rb | 4 + 15 files changed, 366 insertions(+), 15 deletions(-) create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/sound.hxx create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/sound_buffer.hxx create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx create mode 100644 modules/audio-libsoundio/mrblib/sound_buffer.rb create mode 100644 modules/audio-libsoundio/src/mrb_moon_audio.cxx create mode 100644 modules/audio-libsoundio/src/mrb_music.cxx create mode 100644 modules/audio-libsoundio/src/mrb_sound.cxx create mode 100644 modules/audio-libsoundio/src/mrb_sound_buffer.cxx diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx index 5195742..1fab774 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx @@ -2,18 +2,37 @@ #define MOON_AUDIO_H #include +#define MOON_AUDIO_BACKEND "libsoundio" namespace Moon { class Audio { public: - static bool Initialize(); + enum ErrorCode { + MOON_AUDIO_OK, + // SoundIO failed to create + MOON_AUDIO_CREATE_ERROR, + // could not establish a connection to the audio server/device + MOON_AUDIO_CONNECTION_ERROR, + // There is no default device present + MOON_AUDIO_NO_DEVICE, + // The device specified by the index, has gone away or does not exist + MOON_AUDIO_DEVICE_MISSING, + // Could not open a stream for audio output + MOON_AUDIO_COULD_NOT_OPEN_STREAM, + // The specified channel layout is not supported + MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR, + // Stream could not be started + MOON_AUDIO_STREAM_START_ERROR + }; + + static ErrorCode Initialize(); static void Update(); static void Terminate(); protected: static bool m_initialized; - static struct SoundIo *m_soundIO; - static struct SoundIoDevice *m_device; - static struct SoundIoOutStream *m_outStream; + static struct SoundIo* m_soundIO; + static struct SoundIoDevice* m_device; + static struct SoundIoOutStream* m_outStream; }; }; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx new file mode 100644 index 0000000..4789e26 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx @@ -0,0 +1,12 @@ +#ifndef MMRB_MUSIC_H +#define MMRB_MUSIC_H + +#include +#include +#include +#include "moon/api.h" + +MOON_C_API const struct mrb_data_type music_data_type; +MOON_C_API void mmrb_music_init(mrb_state *mrb, struct RClass *mod); + +#endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/sound.hxx new file mode 100644 index 0000000..8a6e3d5 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/sound.hxx @@ -0,0 +1,12 @@ +#ifndef MMRB_SOUND_H +#define MMRB_SOUND_H + +#include +#include +#include +#include "moon/api.h" + +MOON_C_API const struct mrb_data_type sound_data_type; +MOON_C_API void mmrb_sound_init(mrb_state *mrb, struct RClass *mod); + +#endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/sound_buffer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/sound_buffer.hxx new file mode 100644 index 0000000..ec63e80 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/sound_buffer.hxx @@ -0,0 +1,12 @@ +#ifndef MMRB_SOUND_BUFFER_H +#define MMRB_SOUND_BUFFER_H + +#include +#include +#include +#include "moon/api.h" + +MOON_C_API const struct mrb_data_type sound_buffer_data_type; +MOON_C_API void mmrb_sound_buffer_init(mrb_state *mrb, struct RClass *mod); + +#endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx new file mode 100644 index 0000000..81de314 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx @@ -0,0 +1,8 @@ +#ifndef MOON_AUDIO_LIBSOUNDIO_MUSIC_H +#define MOON_AUDIO_LIBSOUNDIO_MUSIC_H + +namespace Moon { + +} + +#endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx new file mode 100644 index 0000000..9ef4a40 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -0,0 +1,12 @@ +#ifndef MOON_AUDIO_LIBSOUNDIO_SOUND_H +#define MOON_AUDIO_LIBSOUNDIO_SOUND_H + +#include "moon/audio/libsoundio/sound_buffer.hxx" + +namespace Moon { + struct Sound { + Moon::SoundBuffer* buffer; + }; +} + +#endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx new file mode 100644 index 0000000..1b3f575 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx @@ -0,0 +1,32 @@ +#ifndef MOON_AUDIO_LIBSOUNDIO_SOUND_BUFFER_H +#define MOON_AUDIO_LIBSOUNDIO_SOUND_BUFFER_H + +#include "moon/intern.h" + +namespace Moon { + template struct AbstractSoundBuffer { + // How many channels does the buffer contain + int channelCount; + // in samples + int length; + // Array[channel][index] == sample for channel + T** samples; + + AbstractSoundBuffer() {} + + AbstractSoundBuffer(size_t p_channels, size_t p_length) + { + channelCount = p_channels; + length = p_length; + samples = (T**)moon_malloczero(sizeof(samples) * channelCount); + for (int i = 0; i < length; ++i) { + samples[i] = (float*)moon_malloczero(sizeof(T) * length); + } + } + }; + + typedef struct AbstractSoundBuffer Float32SoundBuffer; + typedef Float32SoundBuffer SoundBuffer; +} + +#endif diff --git a/modules/audio-libsoundio/mrblib/sound_buffer.rb b/modules/audio-libsoundio/mrblib/sound_buffer.rb new file mode 100644 index 0000000..59f4d27 --- /dev/null +++ b/modules/audio-libsoundio/mrblib/sound_buffer.rb @@ -0,0 +1,13 @@ +module Moon + class SoundBuffer + def initialize(*args) + if args.size == 2 + initialize_create(*args) + elsif args.size == 1 + initialize_by_filename(args.first) + else + raise ArgumentError, "expected wrong argument count, (expected 1 or 2)" + end + end + end +end diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 4101366..b83468f 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -1,44 +1,59 @@ +#include "moon/intern.h" #include "moon/audio/libsoundio/audio.hxx" static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frame_count_min, int frame_count_max) { - // Do evil stuff later. + // Do evil stuff later. } namespace Moon { - void Audio::Initialize() + struct SoundIo* Audio::m_soundIO = NULL; + struct SoundIoDevice* Audio::m_device = NULL; + struct SoundIoOutStream* Audio::m_outStream = NULL; + + Audio::ErrorCode Audio::Initialize() { m_soundIO = soundio_create(); // Should I use assert, or set a flag and leave it for mruby to pick up? - assert(m_soundIO); + if (!m_soundIO) { + return Moon::Audio::ErrorCode::MOON_AUDIO_CREATE_ERROR; + } int err = soundio_connect(m_soundIO); if (err) { - // Say bad things happened, and moon will now implode. + return Moon::Audio::ErrorCode::MOON_AUDIO_CONNECTION_ERROR; } soundio_flush_events(m_soundIO); + // Determine the default device const int defaultDeviceIndex = soundio_default_output_device_index(m_soundIO); if (defaultDeviceIndex < 0) { - // Now that I think about it, we could have an error field :D + return Moon::Audio::ErrorCode::MOON_AUDIO_NO_DEVICE; } + // retrieve the device specified by the index m_device = soundio_get_output_device(m_soundIO, defaultDeviceIndex); - // if m_device is null we should raise AudioError, "device not present, out of memory?" + if (!m_device) { + return Moon::Audio::ErrorCode::MOON_AUDIO_DEVICE_MISSING; + } + // create an output stream m_outStream = soundio_outstream_create(m_device); - // High quality shiiit :3 + if (m_outStream) m_outStream->format = SoundIoFormatFloat32NE; - m_outStream->writeCallback = Moon_AudioWrite; + m_outStream->write_callback = Moon_AudioWrite; + // open the stream err = soundio_outstream_open(m_outStream); if (err) { - // raise AudioError, "stream could not be opened" + return Moon::Audio::ErrorCode::MOON_AUDIO_COULD_NOT_OPEN_STREAM; } if (m_outStream->layout_error) { - // raise AudioError, "unable to set channel layout" + return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR; } err = soundio_outstream_start(m_outStream); if (err) { - // raise AudioError, "unable to start device" + return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_START_ERROR; + // raise AudioError, "unable to start device" } // Finally, after bashing your head against the table, you can finally have audio? + return Moon::Audio::ErrorCode::MOON_AUDIO_OK; } void Audio::Update() diff --git a/modules/audio-libsoundio/src/mrb_moon_audio.cxx b/modules/audio-libsoundio/src/mrb_moon_audio.cxx new file mode 100644 index 0000000..b616d72 --- /dev/null +++ b/modules/audio-libsoundio/src/mrb_moon_audio.cxx @@ -0,0 +1,58 @@ +#include +#include +#include "moon/audio/libsoundio/audio.hxx" +#include "moon/audio/libsoundio/mrb/music.hxx" +#include "moon/audio/libsoundio/mrb/sound.hxx" +#include "moon/audio/libsoundio/mrb/sound_buffer.hxx" + +static mrb_value +audio_update(mrb_state *mrb, mrb_value klass) +{ + Moon::Audio::Update(); + return klass; +} + +MOON_C_API void +mrb_mruby_moon_audio_libsoundio_gem_init(mrb_state* mrb) +{ + struct RClass *moon_module = mrb_define_module(mrb, "Moon"); + struct RClass *audio_module = mrb_define_module_under(mrb, moon_module, "Audio"); + struct RClass *audio_error = mrb_define_class_under(mrb, moon_module, "AudioError", E_RUNTIME_ERROR); + mrb_define_class_method(mrb, audio_module, "update", audio_update, MRB_ARGS_NONE()); + mmrb_sound_buffer_init(mrb, moon_module); + mmrb_music_init(mrb, moon_module); + mmrb_sound_init(mrb, moon_module); + + const Moon::Audio::ErrorCode err = Moon::Audio::Initialize(); + switch (err) { + case Moon::Audio::ErrorCode::MOON_AUDIO_CREATE_ERROR: + mrb_raise(mrb, audio_error, "Underlying backend could not be created"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_CONNECTION_ERROR: + mrb_raise(mrb, audio_error, "Could not estabish connection to backend"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_NO_DEVICE: + mrb_raise(mrb, audio_error, "No default device present"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_DEVICE_MISSING: + mrb_raise(mrb, audio_error, "Default device is missing"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_COULD_NOT_OPEN_STREAM: + mrb_raise(mrb, audio_error, "Output stream could not be opened, does the selected device support it?"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR: + mrb_raise(mrb, audio_error, "Channel layout is invalid for the stream"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_START_ERROR: + mrb_raise(mrb, audio_error, "Stream could not be started"); + break; + default: + break; + } +} + +MOON_C_API void +mrb_mruby_moon_audio_libsoundio_gem_final(mrb_state* mrb) +{ + Moon::Audio::Terminate(); +} diff --git a/modules/audio-libsoundio/src/mrb_music.cxx b/modules/audio-libsoundio/src/mrb_music.cxx new file mode 100644 index 0000000..9f726ba --- /dev/null +++ b/modules/audio-libsoundio/src/mrb_music.cxx @@ -0,0 +1,13 @@ +#include +#include +#include +#include +#include "moon/audio/libsoundio/mrb/music.hxx" +#include "moon/audio/libsoundio/music.hxx" +#include "moon/api.h" +#include "moon/intern.h" + +MOON_C_API void +mmrb_music_init(mrb_state *mrb, struct RClass *mod) +{ +} diff --git a/modules/audio-libsoundio/src/mrb_sound.cxx b/modules/audio-libsoundio/src/mrb_sound.cxx new file mode 100644 index 0000000..80f7d13 --- /dev/null +++ b/modules/audio-libsoundio/src/mrb_sound.cxx @@ -0,0 +1,13 @@ +#include +#include +#include +#include +#include "moon/audio/libsoundio/mrb/sound.hxx" +#include "moon/audio/libsoundio/sound.hxx" +#include "moon/api.h" +#include "moon/intern.h" + +MOON_C_API void +mmrb_sound_init(mrb_state *mrb, struct RClass *mod) +{ +} diff --git a/modules/audio-libsoundio/src/mrb_sound_buffer.cxx b/modules/audio-libsoundio/src/mrb_sound_buffer.cxx new file mode 100644 index 0000000..b41bcfc --- /dev/null +++ b/modules/audio-libsoundio/src/mrb_sound_buffer.cxx @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include "moon/audio/libsoundio/mrb/sound_buffer.hxx" +#include "moon/audio/libsoundio/sound_buffer.hxx" +#include "moon/api.h" +#include "moon/intern.h" + +static void +sound_buffer_free(mrb_state* mrb, void* ptr) +{ + Moon::SoundBuffer* buf = (Moon::SoundBuffer*)ptr; + if (buf) { + delete buf; + } +} + +MOON_C_API const struct mrb_data_type sound_buffer_data_type = { "Moon::SoundBuffer", sound_buffer_free }; + +MOON_C_API +Moon::SoundBuffer* mmrb_to_sound_buffer(mrb_state *mrb, mrb_value self) +{ + return static_cast(mrb_data_check_get_ptr(mrb, self, &sound_buffer_data_type)); +} + +static mrb_value +sound_buffer_initialize_by_filename(mrb_state *mrb, mrb_value self) +{ + char* str = NULL; + mrb_get_args(mrb, "z", &str); + mrb_raise(mrb, E_RUNTIME_ERROR, "not implemented"); + return self; +} + +static mrb_value +sound_buffer_initialize_create(mrb_state *mrb, mrb_value self) +{ + mrb_int channels = 0; + mrb_int length = 0; + mrb_get_args(mrb, "ii", &channels, &length); + if (channels <= 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "channels must be 1 or more"); + return self; + } + if (length <= 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "length must be 1 or more"); + return self; + } + Moon::SoundBuffer *buffer = new Moon::SoundBuffer(channels, length); + mrb_data_init(self, buffer, &sound_buffer_data_type); + return self; +} + +static mrb_value +sound_buffer_aget(mrb_state *mrb, mrb_value self) +{ + mrb_int channel = 0; + mrb_int index = 0; + mrb_get_args(mrb, "ii", &channel, &index); + Moon::SoundBuffer* buf = mmrb_to_sound_buffer(mrb, self); + if (channel < 0 || channel >= buf->channelCount) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "channel index exceeded!"); + return mrb_float_value(mrb, 0.0f); + } + + if (index < 0) { + index %= buf->length; + } + + if (index >= buf->length) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "buffer length exceeded!"); + return mrb_float_value(mrb, 0.0f); + } + + return mrb_float_value(mrb, buf->samples[channel][index]); +} + +static mrb_value +sound_buffer_aset(mrb_state *mrb, mrb_value self) +{ + mrb_int channel = 0; + mrb_int index = 0; + mrb_float value = 0.0f; + mrb_get_args(mrb, "iif", &channel, &index, &value); + Moon::SoundBuffer* buf = mmrb_to_sound_buffer(mrb, self); + if (channel < 0 || channel >= buf->channelCount) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "channel index exceeded!"); + return mrb_float_value(mrb, 0.0f); + } + + if (index < 0) { + index %= buf->length; + } + + if (index >= buf->length) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "buffer length exceeded!"); + return mrb_float_value(mrb, 0.0f); + } + + buf->samples[channel][index] = (float)value; + return self; +} + +MOON_C_API void +mmrb_sound_buffer_init(mrb_state *mrb, struct RClass *mod) +{ + struct RClass* sound_buffer_class = mrb_define_class_under(mrb, mod, "SoundBuffer", mrb->object_class); + + mrb_define_method(mrb, sound_buffer_class, "initialize_by_filename", sound_buffer_initialize_by_filename, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, sound_buffer_class, "initialize_create", sound_buffer_initialize_create, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, sound_buffer_class, "[]", sound_buffer_aget, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, sound_buffer_class, "[]=", sound_buffer_aset, MRB_ARGS_REQ(3)); +} diff --git a/modules/system/include/moon/intern.h b/modules/system/include/moon/intern.h index 6e998d9..f354c9e 100644 --- a/modules/system/include/moon/intern.h +++ b/modules/system/include/moon/intern.h @@ -23,4 +23,18 @@ exists(const std::string& name) return (stat(name.c_str(), &buffer) == 0); }; +static inline void* +moon_mallocset(size_t len, int value) +{ + void* ptr = malloc(len); + memset(ptr, value, len); + return ptr; +} + +static inline void* +moon_malloczero(size_t len) +{ + return moon_mallocset(len, 0); +} + #endif diff --git a/mrb_config.rb b/mrb_config.rb index 6bef576..3b362e4 100644 --- a/mrb_config.rb +++ b/mrb_config.rb @@ -127,6 +127,10 @@ l.libraries << 'GLEW' l.libraries << 'GL' l.libraries << 'openal' + l.libraries << 'asound' + # if you want to use jack, just enable it here + #l.libraries << 'jack' + l.libraries << 'pulse' elsif platform.windows? l.libraries << 'glew32' l.libraries << 'opengl32' From 05a2b1d9561e03d7a6fb078638e4f500bc82836d Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 13:36:09 -0500 Subject: [PATCH 05/59] Make libsoundio a dependency of moon-player --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2760bae..69cd3ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory("vendor/sil") get_filename_component(SIL_INCLUDE_DIR "vendor/sil/include" ABSOLUTE) add_subdirectory("vendor/soil") add_subdirectory("vendor/gorilla-audio/build") +set(ENABLE_JACK OFF) add_subdirectory("vendor/libsoundio") #add_subdirectory("vendor/glm") @@ -31,7 +32,7 @@ if(RAKE_VERBOSE) endif(RAKE_VERBOSE) add_custom_target(moon-mruby ALL - DEPENDS SIL SOIL glfw freetype-gl gorilla + DEPENDS SIL SOIL glfw freetype-gl gorilla libsoundio_static COMMAND rake ${RAKE_VERBOSE_FLAG} MRUBY_CONFIG="${CMAKE_SOURCE_DIR}/mrb_config.rb" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/vendor/mruby" ) From 4b83dc677def92475897b62b4dcbceca860ca41d Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 14:02:43 -0500 Subject: [PATCH 06/59] modules/audio-libsoundio: Added SoundBuffer#sampleRate I totally forgot about it --- .../moon/audio/libsoundio/sound_buffer.hxx | 24 +++++++++++-------- .../audio-libsoundio/mrblib/sound_buffer.rb | 11 +++++---- .../audio-libsoundio/src/mrb_sound_buffer.cxx | 11 ++++++--- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx index 1b3f575..1e43e0b 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx @@ -6,21 +6,25 @@ namespace Moon { template struct AbstractSoundBuffer { // How many channels does the buffer contain - int channelCount; + size_t channelCount; + // sample rate 44100 + int sampleRate; // in samples - int length; + size_t length; // Array[channel][index] == sample for channel T** samples; - AbstractSoundBuffer() {} - - AbstractSoundBuffer(size_t p_channels, size_t p_length) + static + AbstractSoundBuffer* create(size_t p_channels, size_t p_length, int p_sampleRate) { - channelCount = p_channels; - length = p_length; - samples = (T**)moon_malloczero(sizeof(samples) * channelCount); - for (int i = 0; i < length; ++i) { - samples[i] = (float*)moon_malloczero(sizeof(T) * length); + AbstractSoundBuffer* buffer = new AbstractSoundBuffer(); + buffer->channelCount = p_channels; + buffer->length = p_length; + buffer->sampleRate = p_sampleRate; + buffer->samples = (T**)moon_malloczero(sizeof(buffer->samples) * buffer->channelCount); + assert(buffer->samples); + for (int i = 0; i < buffer->length; ++i) { + buffer->samples[i] = (float*)moon_malloczero(sizeof(T) * buffer->length); } } }; diff --git a/modules/audio-libsoundio/mrblib/sound_buffer.rb b/modules/audio-libsoundio/mrblib/sound_buffer.rb index 59f4d27..1f551a8 100644 --- a/modules/audio-libsoundio/mrblib/sound_buffer.rb +++ b/modules/audio-libsoundio/mrblib/sound_buffer.rb @@ -1,12 +1,15 @@ module Moon class SoundBuffer + private :initialize_create + private :initialize_by_filename + def initialize(*args) - if args.size == 2 - initialize_create(*args) - elsif args.size == 1 + if args.size == 1 initialize_by_filename(args.first) + elsif args.size >= 2 + initialize_create(*args) else - raise ArgumentError, "expected wrong argument count, (expected 1 or 2)" + raise ArgumentError, "expected wrong argument count, (expected 1, 2 or 3)" end end end diff --git a/modules/audio-libsoundio/src/mrb_sound_buffer.cxx b/modules/audio-libsoundio/src/mrb_sound_buffer.cxx index b41bcfc..c693633 100644 --- a/modules/audio-libsoundio/src/mrb_sound_buffer.cxx +++ b/modules/audio-libsoundio/src/mrb_sound_buffer.cxx @@ -38,7 +38,8 @@ sound_buffer_initialize_create(mrb_state *mrb, mrb_value self) { mrb_int channels = 0; mrb_int length = 0; - mrb_get_args(mrb, "ii", &channels, &length); + mrb_int sampleRate = 44100; + mrb_get_args(mrb, "ii|i", &channels, &length, &sampleRate); if (channels <= 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "channels must be 1 or more"); return self; @@ -47,7 +48,11 @@ sound_buffer_initialize_create(mrb_state *mrb, mrb_value self) mrb_raise(mrb, E_ARGUMENT_ERROR, "length must be 1 or more"); return self; } - Moon::SoundBuffer *buffer = new Moon::SoundBuffer(channels, length); + if (sampleRate <= 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Sample rate MUST be greater than 0"); + return self; + } + Moon::SoundBuffer *buffer = Moon::SoundBuffer::create(channels, length, sampleRate); mrb_data_init(self, buffer, &sound_buffer_data_type); return self; } @@ -108,7 +113,7 @@ mmrb_sound_buffer_init(mrb_state *mrb, struct RClass *mod) struct RClass* sound_buffer_class = mrb_define_class_under(mrb, mod, "SoundBuffer", mrb->object_class); mrb_define_method(mrb, sound_buffer_class, "initialize_by_filename", sound_buffer_initialize_by_filename, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, sound_buffer_class, "initialize_create", sound_buffer_initialize_create, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, sound_buffer_class, "initialize_create", sound_buffer_initialize_create, MRB_ARGS_ARG(2,1)); mrb_define_method(mrb, sound_buffer_class, "[]", sound_buffer_aget, MRB_ARGS_REQ(2)); mrb_define_method(mrb, sound_buffer_class, "[]=", sound_buffer_aset, MRB_ARGS_REQ(3)); } From 6541a721b98ded96d14bae2700bd9322f76f5d5a Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 14:50:03 -0500 Subject: [PATCH 07/59] modules/audio-libsoundio: Changed SoundBuffer structure a bit Less cache hits now, hopefully --- .../moon/audio/libsoundio/sound_buffer.hxx | 17 +++++++++++------ .../audio-libsoundio/src/mrb_sound_buffer.cxx | 6 +++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx index 1e43e0b..52f1918 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx @@ -11,8 +11,16 @@ namespace Moon { int sampleRate; // in samples size_t length; - // Array[channel][index] == sample for channel - T** samples; + // Array[channel + index * channelCount] == sample for channel + T* samples; + + T GetSample(int channel, int index) { + return samples[channel + index * channelCount]; + } + + void SetSample(int channel, int index, T sample) { + samples[channel + index * channelCount] = sample; + } static AbstractSoundBuffer* create(size_t p_channels, size_t p_length, int p_sampleRate) @@ -21,11 +29,8 @@ namespace Moon { buffer->channelCount = p_channels; buffer->length = p_length; buffer->sampleRate = p_sampleRate; - buffer->samples = (T**)moon_malloczero(sizeof(buffer->samples) * buffer->channelCount); + buffer->samples = (T*)moon_malloczero(sizeof(T) * buffer->channelCount * buffer->length); assert(buffer->samples); - for (int i = 0; i < buffer->length; ++i) { - buffer->samples[i] = (float*)moon_malloczero(sizeof(T) * buffer->length); - } } }; diff --git a/modules/audio-libsoundio/src/mrb_sound_buffer.cxx b/modules/audio-libsoundio/src/mrb_sound_buffer.cxx index c693633..1c80c7a 100644 --- a/modules/audio-libsoundio/src/mrb_sound_buffer.cxx +++ b/modules/audio-libsoundio/src/mrb_sound_buffer.cxx @@ -38,7 +38,7 @@ sound_buffer_initialize_create(mrb_state *mrb, mrb_value self) { mrb_int channels = 0; mrb_int length = 0; - mrb_int sampleRate = 44100; + mrb_int sampleRate = 48000; mrb_get_args(mrb, "ii|i", &channels, &length, &sampleRate); if (channels <= 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "channels must be 1 or more"); @@ -78,7 +78,7 @@ sound_buffer_aget(mrb_state *mrb, mrb_value self) return mrb_float_value(mrb, 0.0f); } - return mrb_float_value(mrb, buf->samples[channel][index]); + return mrb_float_value(mrb, buf->GetSample(channel, index)); } static mrb_value @@ -103,7 +103,7 @@ sound_buffer_aset(mrb_state *mrb, mrb_value self) return mrb_float_value(mrb, 0.0f); } - buf->samples[channel][index] = (float)value; + buf->SetSample(channel, index, (float)value); return self; } From b92cd677e693df2da22818bf6e6c1e790a1dc254 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 16:14:31 -0500 Subject: [PATCH 08/59] Do not build examples or tests for libsoundio We don't need them. --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69cd3ac..2061292 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,8 @@ get_filename_component(SIL_INCLUDE_DIR "vendor/sil/include" ABSOLUTE) add_subdirectory("vendor/soil") add_subdirectory("vendor/gorilla-audio/build") set(ENABLE_JACK OFF) +set(BUILD_EXAMPLE_PROGRAMS OFF) +set(BUILD_TESTS OFF) add_subdirectory("vendor/libsoundio") #add_subdirectory("vendor/glm") From 6c95457ccd1cb740ff6428253b5597ff1fc2a42b Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 16:15:00 -0500 Subject: [PATCH 09/59] modules/audio-libsoundio: Force linkage static libsoundio.a --- modules/audio-libsoundio/mrbgem.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/mrbgem.rake b/modules/audio-libsoundio/mrbgem.rake index 2de2efa..d607ed6 100644 --- a/modules/audio-libsoundio/mrbgem.rake +++ b/modules/audio-libsoundio/mrbgem.rake @@ -18,7 +18,7 @@ MRuby::Gem::Specification.new('mruby-moon-audio-libsoundio') do |spec| end spec.linker do |l| - l.libraries << 'soundio' + l.libraries << ':libsoundio.a' end spec.add_dependency 'mruby-moon-system' From 05dcdcb4343b28484e2695ab637ebee25c0a2f48 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 16:38:10 -0500 Subject: [PATCH 10/59] modules/system: Added M_PI In case it wasn't defined before --- modules/system/include/moon/intern.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/system/include/moon/intern.h b/modules/system/include/moon/intern.h index f354c9e..a41c5dd 100644 --- a/modules/system/include/moon/intern.h +++ b/modules/system/include/moon/intern.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -16,6 +17,10 @@ # define stat _stat #endif +#ifndef M_PI + #define M_PI 3.1415926535f +#endif + static inline bool exists(const std::string& name) { From 21941e085ddd9e506eee42a4a7c885200dbb87a9 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 16:38:26 -0500 Subject: [PATCH 11/59] modules/audio-libsoundio: Beware the sine wave --- .../include/moon/audio/libsoundio/audio.hxx | 58 ++--- modules/audio-libsoundio/src/audio.cxx | 220 +++++++++++++----- 2 files changed, 188 insertions(+), 90 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx index 1fab774..2b2f199 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx @@ -1,39 +1,41 @@ #ifndef MOON_AUDIO_H #define MOON_AUDIO_H +#include "moon/intern.h" +#include #include #define MOON_AUDIO_BACKEND "libsoundio" namespace Moon { - class Audio { - public: - enum ErrorCode { - MOON_AUDIO_OK, - // SoundIO failed to create - MOON_AUDIO_CREATE_ERROR, - // could not establish a connection to the audio server/device - MOON_AUDIO_CONNECTION_ERROR, - // There is no default device present - MOON_AUDIO_NO_DEVICE, - // The device specified by the index, has gone away or does not exist - MOON_AUDIO_DEVICE_MISSING, - // Could not open a stream for audio output - MOON_AUDIO_COULD_NOT_OPEN_STREAM, - // The specified channel layout is not supported - MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR, - // Stream could not be started - MOON_AUDIO_STREAM_START_ERROR - }; + class Audio { + public: + enum ErrorCode { + MOON_AUDIO_OK, + // SoundIO failed to create + MOON_AUDIO_CREATE_ERROR, + // could not establish a connection to the audio server/device + MOON_AUDIO_CONNECTION_ERROR, + // There is no default device present + MOON_AUDIO_NO_DEVICE, + // The device specified by the index, has gone away or does not exist + MOON_AUDIO_DEVICE_MISSING, + // Could not open a stream for audio output + MOON_AUDIO_COULD_NOT_OPEN_STREAM, + // The specified channel layout is not supported + MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR, + // Stream could not be started + MOON_AUDIO_STREAM_START_ERROR + }; - static ErrorCode Initialize(); - static void Update(); - static void Terminate(); - protected: - static bool m_initialized; - static struct SoundIo* m_soundIO; - static struct SoundIoDevice* m_device; - static struct SoundIoOutStream* m_outStream; - }; + static ErrorCode Initialize(); + static void Update(); + static void Terminate(); + protected: + static bool m_initialized; + static struct SoundIo* m_soundIO; + static struct SoundIoDevice* m_device; + static struct SoundIoOutStream* m_outStream; + }; }; #endif diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index b83468f..472b352 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -1,70 +1,166 @@ #include "moon/intern.h" #include "moon/audio/libsoundio/audio.hxx" +#include -static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frame_count_min, int frame_count_max) { - // Do evil stuff later. +class AbstractVoice { +public: + bool active; + int frame; + + virtual float getSample(float sampleRate) { + return 0.0f; + }; + + virtual void reset() { + active = false; + frame = 0; + } +}; + +class SineVoice : public AbstractVoice { +public: + float frequency; + float velocity; + + float getSample(float sampleRate) { + if (frequency > 0) + { + return sinf((2 * M_PI * frame * frequency) / sampleRate) * velocity; + } + return 0.0f; + } + + void reset() { + AbstractVoice::reset(); + frequency = 0.0f; + velocity = 0.0f; + } +}; + +class SampleVoice : public AbstractVoice { + float getSample(float sampleRate) { + // TODO + return 0.0f; + } +}; + +static std::vector voices; +static SineVoice sineVoice; + +static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { + struct SoundIoChannelArea *areas; + const struct SoundIoChannelLayout *layout = &outstream->layout; + const float sampleRate = outstream->sample_rate; + const float secondsPerFrame = 1.0f / sampleRate; + int framesLeft = frameCountMax; + printf("Doing an audio write: %d\n", frameCountMax); + // iterate all the active voices, mix them together and then output to the stream, or something like that + printf("Voices %d\n", voices.size()); + while (framesLeft > 0) { + int frameCount = framesLeft; + int err = soundio_outstream_begin_write(outstream, &areas, &frameCount); + if (err) { + // device has died or something worse D; + printf("Error writing to outstream\n"); + break; + } + if (!frameCount) { + printf("No more frames, jumping ship\n"); + break; + } + + for (int frame = 0; frame < frameCount; ++frame) { + for (size_t channel = 0; channel < layout->channel_count; ++channel) { + float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); + float sample = 0.0f; + for (size_t voiceIndex = 0; voiceIndex < voices.size(); ++voiceIndex) { + if (voices[voiceIndex]->active) { + sample += voices[voiceIndex]->getSample(sampleRate); + voices[voiceIndex]->frame += 1; + } + } + // clipping, to avoid overdrive + *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); + } + } + + err = soundio_outstream_end_write(outstream); + if (err) { + printf("Error ending writing to outstream\n"); + // something terrible happened. >: + break; + } + framesLeft -= frameCount; + } } namespace Moon { - struct SoundIo* Audio::m_soundIO = NULL; - struct SoundIoDevice* Audio::m_device = NULL; - struct SoundIoOutStream* Audio::m_outStream = NULL; - - Audio::ErrorCode Audio::Initialize() - { - m_soundIO = soundio_create(); - // Should I use assert, or set a flag and leave it for mruby to pick up? - if (!m_soundIO) { - return Moon::Audio::ErrorCode::MOON_AUDIO_CREATE_ERROR; - } - int err = soundio_connect(m_soundIO); - if (err) { - return Moon::Audio::ErrorCode::MOON_AUDIO_CONNECTION_ERROR; - } - soundio_flush_events(m_soundIO); - // Determine the default device - const int defaultDeviceIndex = soundio_default_output_device_index(m_soundIO); - if (defaultDeviceIndex < 0) { - return Moon::Audio::ErrorCode::MOON_AUDIO_NO_DEVICE; - } - // retrieve the device specified by the index - m_device = soundio_get_output_device(m_soundIO, defaultDeviceIndex); - if (!m_device) { - return Moon::Audio::ErrorCode::MOON_AUDIO_DEVICE_MISSING; - } - // create an output stream - m_outStream = soundio_outstream_create(m_device); - if (m_outStream) - m_outStream->format = SoundIoFormatFloat32NE; - m_outStream->write_callback = Moon_AudioWrite; - - // open the stream - err = soundio_outstream_open(m_outStream); - if (err) { - return Moon::Audio::ErrorCode::MOON_AUDIO_COULD_NOT_OPEN_STREAM; - } - if (m_outStream->layout_error) { - return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR; - } - err = soundio_outstream_start(m_outStream); - if (err) { - return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_START_ERROR; - // raise AudioError, "unable to start device" - } - // Finally, after bashing your head against the table, you can finally have audio? - return Moon::Audio::ErrorCode::MOON_AUDIO_OK; - } - - void Audio::Update() - { - soundio_flush_events(m_soundIO); - } - - void Audio::Terminate() - { - soundio_outstream_destroy(m_outStream); - soundio_device_unref(m_device); - soundio_destroy(m_soundIO); - } + struct SoundIo* Audio::m_soundIO = NULL; + struct SoundIoDevice* Audio::m_device = NULL; + struct SoundIoOutStream* Audio::m_outStream = NULL; + + Audio::ErrorCode Audio::Initialize() + { + m_soundIO = soundio_create(); + // Should I use assert, or set a flag and leave it for mruby to pick up? + if (!m_soundIO) { + return Moon::Audio::ErrorCode::MOON_AUDIO_CREATE_ERROR; + } + int err = soundio_connect(m_soundIO); + if (err) { + return Moon::Audio::ErrorCode::MOON_AUDIO_CONNECTION_ERROR; + } + soundio_flush_events(m_soundIO); + // Determine the default device + const int defaultDeviceIndex = soundio_default_output_device_index(m_soundIO); + if (defaultDeviceIndex < 0) { + return Moon::Audio::ErrorCode::MOON_AUDIO_NO_DEVICE; + } + // retrieve the device specified by the index + m_device = soundio_get_output_device(m_soundIO, defaultDeviceIndex); + if (!m_device) { + return Moon::Audio::ErrorCode::MOON_AUDIO_DEVICE_MISSING; + } + // create an output stream + m_outStream = soundio_outstream_create(m_device); + if (m_outStream) + m_outStream->format = SoundIoFormatFloat32NE; + m_outStream->write_callback = Moon_AudioWrite; + + // open the stream + err = soundio_outstream_open(m_outStream); + if (err) { + return Moon::Audio::ErrorCode::MOON_AUDIO_COULD_NOT_OPEN_STREAM; + } + if (m_outStream->layout_error) { + return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR; + } + err = soundio_outstream_start(m_outStream); + if (err) { + return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_START_ERROR; + // raise AudioError, "unable to start device" + } + sineVoice.active = true; + sineVoice.velocity = 0.2; + sineVoice.frequency = 480; + voices.push_back(&sineVoice); + //for (int voiceIndex = 0; voiceIndex < AUDIO_VOICE_MAX; ++voiceIndex) { + // moonVoices[voiceIndex].reset(); + //} + // Finally, after bashing your head against the table, you can finally have audio? + return Moon::Audio::ErrorCode::MOON_AUDIO_OK; + } + + void Audio::Update() + { + soundio_flush_events(m_soundIO); + } + + void Audio::Terminate() + { + soundio_outstream_destroy(m_outStream); + soundio_device_unref(m_device); + soundio_destroy(m_soundIO); + } } From 828067ca522eeefcdcc308aa5ba4cb6e9f15b762 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 20:40:35 -0500 Subject: [PATCH 12/59] modules/audio-libsoundio: Made suggested changes ^~^ --- modules/audio-libsoundio/src/audio.cxx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 472b352..68cad2b 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -124,7 +124,8 @@ namespace Moon } // create an output stream m_outStream = soundio_outstream_create(m_device); - if (m_outStream) + // 100ms, I hope that's enough + m_outStream->software_latency = 0.01; m_outStream->format = SoundIoFormatFloat32NE; m_outStream->write_callback = Moon_AudioWrite; @@ -134,17 +135,20 @@ namespace Moon return Moon::Audio::ErrorCode::MOON_AUDIO_COULD_NOT_OPEN_STREAM; } if (m_outStream->layout_error) { - return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR; + // Could be a warning + //return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR; + printf("WARN: Requested channel could not be completed\n"); } + sineVoice.active = true; + sineVoice.velocity = 0.2; + sineVoice.frequency = 480; + voices.push_back(&sineVoice); + err = soundio_outstream_start(m_outStream); if (err) { return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_START_ERROR; // raise AudioError, "unable to start device" } - sineVoice.active = true; - sineVoice.velocity = 0.2; - sineVoice.frequency = 480; - voices.push_back(&sineVoice); //for (int voiceIndex = 0; voiceIndex < AUDIO_VOICE_MAX; ++voiceIndex) { // moonVoices[voiceIndex].reset(); //} @@ -154,7 +158,6 @@ namespace Moon void Audio::Update() { - soundio_flush_events(m_soundIO); } void Audio::Terminate() From 6e62a5a1d0b945b4cfdd38dce8c6bb515c3c98a2 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 29 Jun 2016 22:35:36 -0500 Subject: [PATCH 13/59] Updated libsoundio submodule --- vendor/libsoundio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libsoundio b/vendor/libsoundio index 4eb5b4b..552167f 160000 --- a/vendor/libsoundio +++ b/vendor/libsoundio @@ -1 +1 @@ -Subproject commit 4eb5b4bbe4de7e316bf32038849564dda50d9ebc +Subproject commit 552167fa0e52f8788c61825359414da1fcb22b31 From f8f7ff996b7154a11431cd911b96677c246907ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Thu, 30 Jun 2016 13:51:06 +0900 Subject: [PATCH 14/59] Get it to build on OS X. --- modules/audio-libsoundio/mrbgem.rake | 2 +- mrb_config.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/mrbgem.rake b/modules/audio-libsoundio/mrbgem.rake index d607ed6..2de2efa 100644 --- a/modules/audio-libsoundio/mrbgem.rake +++ b/modules/audio-libsoundio/mrbgem.rake @@ -18,7 +18,7 @@ MRuby::Gem::Specification.new('mruby-moon-audio-libsoundio') do |spec| end spec.linker do |l| - l.libraries << ':libsoundio.a' + l.libraries << 'soundio' end spec.add_dependency 'mruby-moon-system' diff --git a/mrb_config.rb b/mrb_config.rb index 3b362e4..ef1772e 100644 --- a/mrb_config.rb +++ b/mrb_config.rb @@ -138,8 +138,13 @@ elsif platform.darwin? l.libraries << 'GLEW' l.flags_after_libraries << '-framework OpenGL' + # gorilla l.flags_after_libraries << '-framework OpenAL' + # l.flags_after_libraries << '-framework CoreFoundation' + # libsoundio + l.flags_after_libraries << '-framework CoreAudio' + l.flags_after_libraries << '-framework AudioUnit' end if platform.unix? From bf37f9e53df0c8ac7e43db6483933c42e38f55e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Thu, 30 Jun 2016 23:59:35 +0900 Subject: [PATCH 15/59] Get libsndfile to compile and link. --- .gitmodules | 3 +++ CMakeLists.txt | 4 +++- cmake/BuildSndfile.cmake | 16 ++++++++++++++++ modules/audio-libsoundio/mrbgem.rake | 1 + mrb_config.rb | 2 ++ 5 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 cmake/BuildSndfile.cmake diff --git a/.gitmodules b/.gitmodules index 639cb6c..a8b2a53 100644 --- a/.gitmodules +++ b/.gitmodules @@ -30,3 +30,6 @@ [submodule "vendor/libsoundio"] path = vendor/libsoundio url = https://github.com/andrewrk/libsoundio +[submodule "vendor/libsndfile"] + path = vendor/libsndfile + url = https://github.com/erikd/libsndfile diff --git a/CMakeLists.txt b/CMakeLists.txt index 2061292..778c262 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,8 @@ project(moon) find_library(YAML yaml) +include(cmake/BuildSndfile.cmake) + add_subdirectory("vendor/sil") # cmake doesn't like relative paths for include dirs, so we'll need the absolute # path instead @@ -34,7 +36,7 @@ if(RAKE_VERBOSE) endif(RAKE_VERBOSE) add_custom_target(moon-mruby ALL - DEPENDS SIL SOIL glfw freetype-gl gorilla libsoundio_static + DEPENDS SIL SOIL glfw freetype-gl gorilla libsoundio_static libsndfile COMMAND rake ${RAKE_VERBOSE_FLAG} MRUBY_CONFIG="${CMAKE_SOURCE_DIR}/mrb_config.rb" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/vendor/mruby" ) diff --git a/cmake/BuildSndfile.cmake b/cmake/BuildSndfile.cmake new file mode 100644 index 0000000..e2816aa --- /dev/null +++ b/cmake/BuildSndfile.cmake @@ -0,0 +1,16 @@ +include(ExternalProject) + +ExternalProject_Add(libsndfile + GIT_REPOSITORY https://github.com/erikd/libsndfile.git + BUILD_IN_SOURCE 1 + INSTALL_DIR vendor/libsndfile + CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/vendor/libsndfile --disable-external-libs --disable-shared + BUILD_COMMAND $(MAKE) V=1 + INSTALL_COMMAND $(MAKE) install + ) + +ExternalProject_Add_Step(libsndfile autogen + COMMAND /autogen.sh + DEPENDEES update + DEPENDERS configure +) diff --git a/modules/audio-libsoundio/mrbgem.rake b/modules/audio-libsoundio/mrbgem.rake index 2de2efa..f679f40 100644 --- a/modules/audio-libsoundio/mrbgem.rake +++ b/modules/audio-libsoundio/mrbgem.rake @@ -19,6 +19,7 @@ MRuby::Gem::Specification.new('mruby-moon-audio-libsoundio') do |spec| spec.linker do |l| l.libraries << 'soundio' + l.libraries << 'sndfile' end spec.add_dependency 'mruby-moon-system' diff --git a/mrb_config.rb b/mrb_config.rb index ef1772e..76115e6 100644 --- a/mrb_config.rb +++ b/mrb_config.rb @@ -101,6 +101,7 @@ c.include_paths << File.expand_path('sil/include', vd) c.include_paths << File.expand_path('freetype-gl', vd) c.include_paths << File.expand_path('libsoundio', vd) + c.include_paths << File.expand_path('libsndfile/include', bvd) # required audio includes c.include_paths << File.expand_path('gorilla-audio/include', vd) c.include_paths.uniq! @@ -113,6 +114,7 @@ l.library_paths << File.expand_path('freetype-gl', bvd) l.library_paths << File.expand_path('gorilla-audio/build', bvd) l.library_paths << File.expand_path('libsoundio', bvd) + l.library_paths << File.expand_path('libsndfile/lib', bvd) l.library_paths << File.expand_path('sil', bvd) l.library_paths << File.expand_path('soil', bvd) l.library_paths.uniq! From d51ec686e2b6c72cbc7c11a0308d17165aeea9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Fri, 1 Jul 2016 00:07:33 +0900 Subject: [PATCH 16/59] Remove the sndfile submodule because cmake already fetches it. --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index a8b2a53..639cb6c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -30,6 +30,3 @@ [submodule "vendor/libsoundio"] path = vendor/libsoundio url = https://github.com/andrewrk/libsoundio -[submodule "vendor/libsndfile"] - path = vendor/libsndfile - url = https://github.com/erikd/libsndfile From 18dbfeb0785fb8debeab2d7049aecea328dd6f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Fri, 1 Jul 2016 02:05:51 +0900 Subject: [PATCH 17/59] Add Source (untested) --- .../include/moon/audio/libsoundio/source.hxx | 19 +++++++++ modules/audio-libsoundio/src/source.cxx | 39 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx create mode 100644 modules/audio-libsoundio/src/source.cxx diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx new file mode 100644 index 0000000..cbc5a33 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx @@ -0,0 +1,19 @@ +#ifndef MOON_AUDIO_LIBSOUNDIO_SOURCE_H +#define MOON_AUDIO_LIBSOUNDIO_SOURCE_H + +namespace Moon +{ + class Source { + public: + Source(const std::string filename); + SF_INFO info; + SNDFILE* file; + + bool seekable(); + sf_count_t seek(sf_count_t frames, int whence); + sf_count_t tell(); + sf_count_t read(float* ptr, sf_count_t frames); + }; +} + +#endif diff --git a/modules/audio-libsoundio/src/source.cxx b/modules/audio-libsoundio/src/source.cxx new file mode 100644 index 0000000..5651c64 --- /dev/null +++ b/modules/audio-libsoundio/src/source.cxx @@ -0,0 +1,39 @@ +#include "moon/intern.h" +#include "moon/audio/libsoundio/source.hxx" + +namespace Moon +{ + Source::Source(const std::string filename) { + info.format = 0; + file = sf_open(filename.c_str(), SFM_READ, &info); + + if (!file) { + stringstream error; + error << "Unable to open audio file '" + << filename << "'"; + throw error.str(); + } + }; + + + Source::~Source() { + if (file) sf_close(file); + } + + + sf_count_t Source::seekable() { + return info.seekable == SF_TRUE; + } + + sf_count_t Source::seek(sf_count_t frames, int whence) { + return sf_seek(file, frames, whence); + } + + sf_count_t Source::tell() { + return seek(0, SEEK_CUR); + } + + sf_count_t Source::read(float* ptr, sf_count_t frames) { + return sf_readf_float(file, ptr, frames); + } +} From 820c6c75d331a0bbb65ebbb96e28ac0dd43640ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Fri, 1 Jul 2016 02:06:07 +0900 Subject: [PATCH 18/59] Update README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 73cf57c..3c4129c 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,15 @@ doxygen # for mruby-yaml yaml + +# for libsndfile +autogen +autoconf +automake + +flac +libogg +libvorbis ``` ## Support From 70b15bd7921da4f9c07b7b02dd43cf109d5e6ede Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Thu, 30 Jun 2016 21:11:17 -0500 Subject: [PATCH 19/59] modules/audio-libsoundio: Fixed source.cxx compilation Added missing headers and corrected function prototypes --- .../include/moon/audio/libsoundio/source.hxx | 8 +++++++- modules/audio-libsoundio/src/source.cxx | 5 +++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx index cbc5a33..7890eb5 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx @@ -1,14 +1,20 @@ #ifndef MOON_AUDIO_LIBSOUNDIO_SOURCE_H #define MOON_AUDIO_LIBSOUNDIO_SOURCE_H +#include "moon/intern.h" +#include +#include + namespace Moon { class Source { public: - Source(const std::string filename); SF_INFO info; SNDFILE* file; + Source(const std::string filename); + ~Source(); + bool seekable(); sf_count_t seek(sf_count_t frames, int whence); sf_count_t tell(); diff --git a/modules/audio-libsoundio/src/source.cxx b/modules/audio-libsoundio/src/source.cxx index 5651c64..ec60bb1 100644 --- a/modules/audio-libsoundio/src/source.cxx +++ b/modules/audio-libsoundio/src/source.cxx @@ -1,5 +1,6 @@ #include "moon/intern.h" #include "moon/audio/libsoundio/source.hxx" +#include namespace Moon { @@ -8,7 +9,7 @@ namespace Moon file = sf_open(filename.c_str(), SFM_READ, &info); if (!file) { - stringstream error; + std::stringstream error; error << "Unable to open audio file '" << filename << "'"; throw error.str(); @@ -21,7 +22,7 @@ namespace Moon } - sf_count_t Source::seekable() { + bool Source::seekable() { return info.seekable == SF_TRUE; } From e57857bdc6132e65dce80ff7f6fc0ab0cb593a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 3 Jul 2016 01:15:25 +0900 Subject: [PATCH 20/59] Set the sample rate to 44.1khz. --- modules/audio-libsoundio/src/audio.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 68cad2b..2a78467 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -127,6 +127,11 @@ namespace Moon // 100ms, I hope that's enough m_outStream->software_latency = 0.01; m_outStream->format = SoundIoFormatFloat32NE; + + m_outStream.sample_rate = 44100; // defaults to 48khz,but most audiofiles are 44.1 + // would be lovely to be able to specify bits per sample + //ret->format.bitsPerSample = 16; + m_outStream->write_callback = Moon_AudioWrite; // open the stream From 972afedc35d02836cf21c025fd4ded8fcad016d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 4 Jul 2016 21:54:40 +0900 Subject: [PATCH 21/59] Use a tarball for libsndfile. Removes autotools dep + cached builds. --- README.md | 4 ---- cmake/BuildSndfile.cmake | 10 +++------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 3c4129c..bf43b63 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,6 @@ doxygen yaml # for libsndfile -autogen -autoconf -automake - flac libogg libvorbis diff --git a/cmake/BuildSndfile.cmake b/cmake/BuildSndfile.cmake index e2816aa..ac15756 100644 --- a/cmake/BuildSndfile.cmake +++ b/cmake/BuildSndfile.cmake @@ -1,16 +1,12 @@ include(ExternalProject) +set(SNDFILE_TARBALL "libsndfile-1.0.27") + ExternalProject_Add(libsndfile - GIT_REPOSITORY https://github.com/erikd/libsndfile.git + URL http://www.mega-nerd.com/libsndfile/files/${SNDFILE_TARBALL}.tar.gz BUILD_IN_SOURCE 1 INSTALL_DIR vendor/libsndfile CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/vendor/libsndfile --disable-external-libs --disable-shared BUILD_COMMAND $(MAKE) V=1 INSTALL_COMMAND $(MAKE) install - ) - -ExternalProject_Add_Step(libsndfile autogen - COMMAND /autogen.sh - DEPENDEES update - DEPENDERS configure ) From 137044f815ad41909af55f4e13f32b6446c681c8 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Sat, 2 Jul 2016 13:24:12 -0500 Subject: [PATCH 22/59] Disable soundio dynamic libs --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 778c262..196c789 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ add_subdirectory("vendor/gorilla-audio/build") set(ENABLE_JACK OFF) set(BUILD_EXAMPLE_PROGRAMS OFF) set(BUILD_TESTS OFF) +set(BUILD_DYNAMIC_LIBS OFF) add_subdirectory("vendor/libsoundio") #add_subdirectory("vendor/glm") From c2d0d9484c73d512f24dea4f5b3b9e61e5d3366c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 4 Jul 2016 23:31:44 +0900 Subject: [PATCH 23/59] Simple mixer extraction (get the code to goddamn compile) --- .../include/moon/audio/libsoundio/audio.hxx | 2 + .../include/moon/audio/libsoundio/mixer.hxx | 33 ++++++++++++++ modules/audio-libsoundio/src/audio.cxx | 45 +++++-------------- modules/audio-libsoundio/src/mixer.cxx | 25 +++++++++++ 4 files changed, 71 insertions(+), 34 deletions(-) create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx create mode 100644 modules/audio-libsoundio/src/mixer.cxx diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx index 2b2f199..2076bbd 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx @@ -5,6 +5,7 @@ #include #include #define MOON_AUDIO_BACKEND "libsoundio" +#include "moon/audio/libsoundio/mixer.hxx" namespace Moon { class Audio { @@ -30,6 +31,7 @@ namespace Moon { static ErrorCode Initialize(); static void Update(); static void Terminate(); + static Mixer* m_mixer; protected: static bool m_initialized; static struct SoundIo* m_soundIO; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx new file mode 100644 index 0000000..bc53204 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx @@ -0,0 +1,33 @@ +#ifndef MOON_AUDIO_LIBSOUNDIO_MIXER_H +#define MOON_AUDIO_LIBSOUNDIO_MIXER_H +#include +#include + +class AbstractVoice { + public: + bool active; + int frame; + + virtual float getSample(float sampleRate) { + return 0.0f; + }; + + virtual void reset() { + active = false; + frame = 0; + } +}; + +namespace Moon +{ + class Mixer { + public: + Mixer(); + + void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); + std::vector voices; + private: + }; +} + +#endif diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 2a78467..3c1d875 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -2,21 +2,6 @@ #include "moon/audio/libsoundio/audio.hxx" #include -class AbstractVoice { -public: - bool active; - int frame; - - virtual float getSample(float sampleRate) { - return 0.0f; - }; - - virtual void reset() { - active = false; - frame = 0; - } -}; - class SineVoice : public AbstractVoice { public: float frequency; @@ -44,7 +29,6 @@ class SampleVoice : public AbstractVoice { } }; -static std::vector voices; static SineVoice sineVoice; static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { @@ -54,8 +38,6 @@ static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMi const float secondsPerFrame = 1.0f / sampleRate; int framesLeft = frameCountMax; printf("Doing an audio write: %d\n", frameCountMax); - // iterate all the active voices, mix them together and then output to the stream, or something like that - printf("Voices %d\n", voices.size()); while (framesLeft > 0) { int frameCount = framesLeft; int err = soundio_outstream_begin_write(outstream, &areas, &frameCount); @@ -69,20 +51,8 @@ static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMi break; } - for (int frame = 0; frame < frameCount; ++frame) { - for (size_t channel = 0; channel < layout->channel_count; ++channel) { - float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); - float sample = 0.0f; - for (size_t voiceIndex = 0; voiceIndex < voices.size(); ++voiceIndex) { - if (voices[voiceIndex]->active) { - sample += voices[voiceIndex]->getSample(sampleRate); - voices[voiceIndex]->frame += 1; - } - } - // clipping, to avoid overdrive - *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); - } - } + // let mixer fill the buffer! + Moon::Audio::m_mixer->mix(areas, *layout, sampleRate, frameCount); err = soundio_outstream_end_write(outstream); if (err) { @@ -100,6 +70,8 @@ namespace Moon struct SoundIoDevice* Audio::m_device = NULL; struct SoundIoOutStream* Audio::m_outStream = NULL; + Mixer* Audio::m_mixer = NULL; + Audio::ErrorCode Audio::Initialize() { m_soundIO = soundio_create(); @@ -128,7 +100,7 @@ namespace Moon m_outStream->software_latency = 0.01; m_outStream->format = SoundIoFormatFloat32NE; - m_outStream.sample_rate = 44100; // defaults to 48khz,but most audiofiles are 44.1 + m_outStream->sample_rate = 44100; // defaults to 48khz,but most audiofiles are 44.1 // would be lovely to be able to specify bits per sample //ret->format.bitsPerSample = 16; @@ -144,10 +116,14 @@ namespace Moon //return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR; printf("WARN: Requested channel could not be completed\n"); } + + // create a new mixer + m_mixer = new Mixer(); + sineVoice.active = true; sineVoice.velocity = 0.2; sineVoice.frequency = 480; - voices.push_back(&sineVoice); + m_mixer->voices.push_back(&sineVoice); err = soundio_outstream_start(m_outStream); if (err) { @@ -170,5 +146,6 @@ namespace Moon soundio_outstream_destroy(m_outStream); soundio_device_unref(m_device); soundio_destroy(m_soundIO); + delete m_mixer; } } diff --git a/modules/audio-libsoundio/src/mixer.cxx b/modules/audio-libsoundio/src/mixer.cxx new file mode 100644 index 0000000..8648aa8 --- /dev/null +++ b/modules/audio-libsoundio/src/mixer.cxx @@ -0,0 +1,25 @@ +#include "moon/audio/libsoundio/mixer.hxx" + +namespace Moon { + Mixer::Mixer() { + } + + void Mixer::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) + { + + for (int frame = 0; frame < frames; ++frame) { + for (size_t channel = 0; channel < layout.channel_count; ++channel) { + float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); + float sample = 0.0f; + for (size_t voiceIndex = 0; voiceIndex < voices.size(); ++voiceIndex) { + if (voices[voiceIndex]->active) { + sample += voices[voiceIndex]->getSample(sampleRate); + voices[voiceIndex]->frame += 1; + } + } + // clipping, to avoid overdrive + *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); + } + } + } +} From 779ac8b44684b4b6ac4eda9aa5893d38078733a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 00:58:05 +0900 Subject: [PATCH 24/59] Try getting audio streaming to work. --- .../include/moon/audio/libsoundio/audio.hxx | 1 + .../include/moon/audio/libsoundio/mixer.hxx | 7 +- .../include/moon/audio/libsoundio/music.hxx | 18 ++- .../include/moon/audio/libsoundio/sound.hxx | 12 -- .../moon/audio/libsoundio/sound_buffer.hxx | 41 ------ modules/audio-libsoundio/src/audio.cxx | 5 +- modules/audio-libsoundio/src/mixer.cxx | 16 +-- .../audio-libsoundio/src/mrb_moon_audio.cxx | 3 +- .../audio-libsoundio/src/mrb_sound_buffer.cxx | 119 ------------------ modules/audio-libsoundio/src/music.cxx | 32 +++++ 10 files changed, 62 insertions(+), 192 deletions(-) delete mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx delete mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx delete mode 100644 modules/audio-libsoundio/src/mrb_sound_buffer.cxx create mode 100644 modules/audio-libsoundio/src/music.cxx diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx index 2076bbd..99a2dfd 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx @@ -6,6 +6,7 @@ #include #define MOON_AUDIO_BACKEND "libsoundio" #include "moon/audio/libsoundio/mixer.hxx" +#include "moon/audio/libsoundio/music.hxx" namespace Moon { class Audio { diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx index bc53204..62fd7c9 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx @@ -18,6 +18,11 @@ class AbstractVoice { } }; +class AbstractSource { + public: + virtual void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) {}; +}; + namespace Moon { class Mixer { @@ -25,7 +30,7 @@ namespace Moon Mixer(); void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); - std::vector voices; + std::vector handles; private: }; } diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx index 81de314..ee7b4b6 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx @@ -1,8 +1,22 @@ #ifndef MOON_AUDIO_LIBSOUNDIO_MUSIC_H #define MOON_AUDIO_LIBSOUNDIO_MUSIC_H -namespace Moon { +#include "moon/intern.h" +#include +#include +#include "moon/audio/libsoundio/mixer.hxx" -} +namespace Moon +{ + class Music : public AbstractSource { + public: + SndfileHandle file; + + Music(const std::string filename); + ~Music(); + + void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); + }; +}; #endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx deleted file mode 100644 index 9ef4a40..0000000 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MOON_AUDIO_LIBSOUNDIO_SOUND_H -#define MOON_AUDIO_LIBSOUNDIO_SOUND_H - -#include "moon/audio/libsoundio/sound_buffer.hxx" - -namespace Moon { - struct Sound { - Moon::SoundBuffer* buffer; - }; -} - -#endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx deleted file mode 100644 index 52f1918..0000000 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound_buffer.hxx +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MOON_AUDIO_LIBSOUNDIO_SOUND_BUFFER_H -#define MOON_AUDIO_LIBSOUNDIO_SOUND_BUFFER_H - -#include "moon/intern.h" - -namespace Moon { - template struct AbstractSoundBuffer { - // How many channels does the buffer contain - size_t channelCount; - // sample rate 44100 - int sampleRate; - // in samples - size_t length; - // Array[channel + index * channelCount] == sample for channel - T* samples; - - T GetSample(int channel, int index) { - return samples[channel + index * channelCount]; - } - - void SetSample(int channel, int index, T sample) { - samples[channel + index * channelCount] = sample; - } - - static - AbstractSoundBuffer* create(size_t p_channels, size_t p_length, int p_sampleRate) - { - AbstractSoundBuffer* buffer = new AbstractSoundBuffer(); - buffer->channelCount = p_channels; - buffer->length = p_length; - buffer->sampleRate = p_sampleRate; - buffer->samples = (T*)moon_malloczero(sizeof(T) * buffer->channelCount * buffer->length); - assert(buffer->samples); - } - }; - - typedef struct AbstractSoundBuffer Float32SoundBuffer; - typedef Float32SoundBuffer SoundBuffer; -} - -#endif diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 3c1d875..416cc69 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -31,6 +31,8 @@ class SampleVoice : public AbstractVoice { static SineVoice sineVoice; +static Moon::Music handle("GoSleepAlready.ogg"); + static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; const struct SoundIoChannelLayout *layout = &outstream->layout; @@ -123,7 +125,8 @@ namespace Moon sineVoice.active = true; sineVoice.velocity = 0.2; sineVoice.frequency = 480; - m_mixer->voices.push_back(&sineVoice); + //m_mixer->voices.push_back(&sineVoice); + m_mixer->handles.push_back(&handle); err = soundio_outstream_start(m_outStream); if (err) { diff --git a/modules/audio-libsoundio/src/mixer.cxx b/modules/audio-libsoundio/src/mixer.cxx index 8648aa8..9ae8f6b 100644 --- a/modules/audio-libsoundio/src/mixer.cxx +++ b/modules/audio-libsoundio/src/mixer.cxx @@ -6,20 +6,8 @@ namespace Moon { void Mixer::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { - - for (int frame = 0; frame < frames; ++frame) { - for (size_t channel = 0; channel < layout.channel_count; ++channel) { - float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); - float sample = 0.0f; - for (size_t voiceIndex = 0; voiceIndex < voices.size(); ++voiceIndex) { - if (voices[voiceIndex]->active) { - sample += voices[voiceIndex]->getSample(sampleRate); - voices[voiceIndex]->frame += 1; - } - } - // clipping, to avoid overdrive - *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); - } + for(auto const& handle: handles) { + handle->mix(areas, layout, sampleRate, frames); } } } diff --git a/modules/audio-libsoundio/src/mrb_moon_audio.cxx b/modules/audio-libsoundio/src/mrb_moon_audio.cxx index b616d72..9dc0914 100644 --- a/modules/audio-libsoundio/src/mrb_moon_audio.cxx +++ b/modules/audio-libsoundio/src/mrb_moon_audio.cxx @@ -3,7 +3,6 @@ #include "moon/audio/libsoundio/audio.hxx" #include "moon/audio/libsoundio/mrb/music.hxx" #include "moon/audio/libsoundio/mrb/sound.hxx" -#include "moon/audio/libsoundio/mrb/sound_buffer.hxx" static mrb_value audio_update(mrb_state *mrb, mrb_value klass) @@ -19,7 +18,7 @@ mrb_mruby_moon_audio_libsoundio_gem_init(mrb_state* mrb) struct RClass *audio_module = mrb_define_module_under(mrb, moon_module, "Audio"); struct RClass *audio_error = mrb_define_class_under(mrb, moon_module, "AudioError", E_RUNTIME_ERROR); mrb_define_class_method(mrb, audio_module, "update", audio_update, MRB_ARGS_NONE()); - mmrb_sound_buffer_init(mrb, moon_module); + //mmrb_sound_buffer_init(mrb, moon_module); mmrb_music_init(mrb, moon_module); mmrb_sound_init(mrb, moon_module); diff --git a/modules/audio-libsoundio/src/mrb_sound_buffer.cxx b/modules/audio-libsoundio/src/mrb_sound_buffer.cxx deleted file mode 100644 index 1c80c7a..0000000 --- a/modules/audio-libsoundio/src/mrb_sound_buffer.cxx +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include -#include -#include "moon/audio/libsoundio/mrb/sound_buffer.hxx" -#include "moon/audio/libsoundio/sound_buffer.hxx" -#include "moon/api.h" -#include "moon/intern.h" - -static void -sound_buffer_free(mrb_state* mrb, void* ptr) -{ - Moon::SoundBuffer* buf = (Moon::SoundBuffer*)ptr; - if (buf) { - delete buf; - } -} - -MOON_C_API const struct mrb_data_type sound_buffer_data_type = { "Moon::SoundBuffer", sound_buffer_free }; - -MOON_C_API -Moon::SoundBuffer* mmrb_to_sound_buffer(mrb_state *mrb, mrb_value self) -{ - return static_cast(mrb_data_check_get_ptr(mrb, self, &sound_buffer_data_type)); -} - -static mrb_value -sound_buffer_initialize_by_filename(mrb_state *mrb, mrb_value self) -{ - char* str = NULL; - mrb_get_args(mrb, "z", &str); - mrb_raise(mrb, E_RUNTIME_ERROR, "not implemented"); - return self; -} - -static mrb_value -sound_buffer_initialize_create(mrb_state *mrb, mrb_value self) -{ - mrb_int channels = 0; - mrb_int length = 0; - mrb_int sampleRate = 48000; - mrb_get_args(mrb, "ii|i", &channels, &length, &sampleRate); - if (channels <= 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "channels must be 1 or more"); - return self; - } - if (length <= 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "length must be 1 or more"); - return self; - } - if (sampleRate <= 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Sample rate MUST be greater than 0"); - return self; - } - Moon::SoundBuffer *buffer = Moon::SoundBuffer::create(channels, length, sampleRate); - mrb_data_init(self, buffer, &sound_buffer_data_type); - return self; -} - -static mrb_value -sound_buffer_aget(mrb_state *mrb, mrb_value self) -{ - mrb_int channel = 0; - mrb_int index = 0; - mrb_get_args(mrb, "ii", &channel, &index); - Moon::SoundBuffer* buf = mmrb_to_sound_buffer(mrb, self); - if (channel < 0 || channel >= buf->channelCount) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "channel index exceeded!"); - return mrb_float_value(mrb, 0.0f); - } - - if (index < 0) { - index %= buf->length; - } - - if (index >= buf->length) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "buffer length exceeded!"); - return mrb_float_value(mrb, 0.0f); - } - - return mrb_float_value(mrb, buf->GetSample(channel, index)); -} - -static mrb_value -sound_buffer_aset(mrb_state *mrb, mrb_value self) -{ - mrb_int channel = 0; - mrb_int index = 0; - mrb_float value = 0.0f; - mrb_get_args(mrb, "iif", &channel, &index, &value); - Moon::SoundBuffer* buf = mmrb_to_sound_buffer(mrb, self); - if (channel < 0 || channel >= buf->channelCount) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "channel index exceeded!"); - return mrb_float_value(mrb, 0.0f); - } - - if (index < 0) { - index %= buf->length; - } - - if (index >= buf->length) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "buffer length exceeded!"); - return mrb_float_value(mrb, 0.0f); - } - - buf->SetSample(channel, index, (float)value); - return self; -} - -MOON_C_API void -mmrb_sound_buffer_init(mrb_state *mrb, struct RClass *mod) -{ - struct RClass* sound_buffer_class = mrb_define_class_under(mrb, mod, "SoundBuffer", mrb->object_class); - - mrb_define_method(mrb, sound_buffer_class, "initialize_by_filename", sound_buffer_initialize_by_filename, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, sound_buffer_class, "initialize_create", sound_buffer_initialize_create, MRB_ARGS_ARG(2,1)); - mrb_define_method(mrb, sound_buffer_class, "[]", sound_buffer_aget, MRB_ARGS_REQ(2)); - mrb_define_method(mrb, sound_buffer_class, "[]=", sound_buffer_aset, MRB_ARGS_REQ(3)); -} diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx new file mode 100644 index 0000000..fd6be78 --- /dev/null +++ b/modules/audio-libsoundio/src/music.cxx @@ -0,0 +1,32 @@ +#include "moon/intern.h" +#include "moon/audio/libsoundio/music.hxx" + +namespace Moon +{ + Music::Music(const std::string filename) : + file(filename, SFM_READ) + { + }; + + + Music::~Music() { + } + + + void Music::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { + // TODO: compare file.channels() with layout.channel_count + // handle mono to stereo, vice versa + for (int frame = 0; frame < frames; ++frame) { + for (size_t channel = 0; channel < file.channels(); ++channel) { + float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); + float sample = 0.0f; + + // read here, write to sample + file.read(&sample, 1); + + // clipping, to avoid overdrive + *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); + } + } + } +} From 1266564a65e0d20bdbf7a0502ba48ca9acddcd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 02:09:32 +0900 Subject: [PATCH 25/59] Do proper logic for sndfile buffer reads. --- modules/audio-libsoundio/src/audio.cxx | 4 ++-- modules/audio-libsoundio/src/music.cxx | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 416cc69..8cced5f 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -31,7 +31,7 @@ class SampleVoice : public AbstractVoice { static SineVoice sineVoice; -static Moon::Music handle("GoSleepAlready.ogg"); +static Moon::Music handle("medusa.wav"); static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; @@ -39,7 +39,7 @@ static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMi const float sampleRate = outstream->sample_rate; const float secondsPerFrame = 1.0f / sampleRate; int framesLeft = frameCountMax; - printf("Doing an audio write: %d\n", frameCountMax); + //printf("Doing an audio write: %d\n", frameCountMax); while (framesLeft > 0) { int frameCount = framesLeft; int err = soundio_outstream_begin_write(outstream, &areas, &frameCount); diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index fd6be78..347ac90 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -6,6 +6,9 @@ namespace Moon Music::Music(const std::string filename) : file(filename, SFM_READ) { + printf ("Opened file '%s'\n", filename.c_str()) ; + printf (" Sample rate : %d\n", file.samplerate ()) ; + printf (" Channels : %d\n", file.channels ()) ; }; @@ -16,17 +19,23 @@ namespace Moon void Music::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { // TODO: compare file.channels() with layout.channel_count // handle mono to stereo, vice versa + int channels = file.channels(); + float* cache = new float[frames * channels * file.samplerate()]; + auto bytes = file.read(cache, frames); + printf("Read n bytes: %d\n", bytes); + + printf("file channels: %d\n", channels); for (int frame = 0; frame < frames; ++frame) { - for (size_t channel = 0; channel < file.channels(); ++channel) { + for (size_t channel = 0; channel < channel; ++channel) { float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); - float sample = 0.0f; - // read here, write to sample - file.read(&sample, 1); + float sample = cache[frame * channels + channel]; // clipping, to avoid overdrive *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); } } + file.seek(frames, SEEK_CUR); + delete cache; } } From 1092c992007987a5aeb87f49a552e7c48f2c7ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 02:09:59 +0900 Subject: [PATCH 26/59] Add missing file --- .../include/moon/audio/libsoundio/sound.hxx | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx new file mode 100644 index 0000000..d7fb38d --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -0,0 +1,9 @@ +#ifndef MOON_AUDIO_LIBSOUNDIO_SOUND_H +#define MOON_AUDIO_LIBSOUNDIO_SOUND_H + +namespace Moon { + struct Sound { + }; +} + +#endif From 5fe7ad8d368c2fb7802212d22d9ca6951a0c8f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 02:10:05 +0900 Subject: [PATCH 27/59] use submodule fork for now --- vendor/libsoundio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libsoundio b/vendor/libsoundio index 552167f..3e1033c 160000 --- a/vendor/libsoundio +++ b/vendor/libsoundio @@ -1 +1 @@ -Subproject commit 552167fa0e52f8788c61825359414da1fcb22b31 +Subproject commit 3e1033cd30fa9e23adbe467af2850845aa55f74a From 6fea83ef18d61cf3ec7842a2af41bab98ca43498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 02:13:43 +0900 Subject: [PATCH 28/59] Should be plureal --- modules/audio-libsoundio/src/music.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index 347ac90..f4075b8 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -26,7 +26,7 @@ namespace Moon printf("file channels: %d\n", channels); for (int frame = 0; frame < frames; ++frame) { - for (size_t channel = 0; channel < channel; ++channel) { + for (size_t channel = 0; channel < channels; ++channel) { float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); float sample = cache[frame * channels + channel]; From 80e9449fda418fb6e0d39921ab6358533ee38d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 02:27:29 +0900 Subject: [PATCH 29/59] GET IT TO WORK!! --- modules/audio-libsoundio/src/music.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index f4075b8..e7f6b7d 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -21,7 +21,7 @@ namespace Moon // handle mono to stereo, vice versa int channels = file.channels(); float* cache = new float[frames * channels * file.samplerate()]; - auto bytes = file.read(cache, frames); + auto bytes = file.readf(cache, frames); printf("Read n bytes: %d\n", bytes); printf("file channels: %d\n", channels); @@ -35,7 +35,7 @@ namespace Moon *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); } } - file.seek(frames, SEEK_CUR); + //file.seek(frames, SEEK_CUR); delete cache; } } From 35ff5fd11fb816f44093d29cdde4fd08faff98e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 02:51:10 +0900 Subject: [PATCH 30/59] Don't disable external libs... --- cmake/BuildSndfile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/BuildSndfile.cmake b/cmake/BuildSndfile.cmake index ac15756..c2572cc 100644 --- a/cmake/BuildSndfile.cmake +++ b/cmake/BuildSndfile.cmake @@ -6,7 +6,7 @@ ExternalProject_Add(libsndfile URL http://www.mega-nerd.com/libsndfile/files/${SNDFILE_TARBALL}.tar.gz BUILD_IN_SOURCE 1 INSTALL_DIR vendor/libsndfile - CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/vendor/libsndfile --disable-external-libs --disable-shared + CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/vendor/libsndfile --disable-shared BUILD_COMMAND $(MAKE) V=1 INSTALL_COMMAND $(MAKE) install ) From 80c7c6f4be1572e822d46ff58014a08af1ea35be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 10:49:59 +0900 Subject: [PATCH 31/59] Get mixing to work. --- modules/audio-libsoundio/src/audio.cxx | 4 +++- modules/audio-libsoundio/src/mixer.cxx | 4 ++++ modules/audio-libsoundio/src/music.cxx | 10 +++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 8cced5f..5c32124 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -31,7 +31,8 @@ class SampleVoice : public AbstractVoice { static SineVoice sineVoice; -static Moon::Music handle("medusa.wav"); +static Moon::Music handle("GoSleepAlready.ogg"); +static Moon::Music handle2("medusa.wav"); static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; @@ -127,6 +128,7 @@ namespace Moon sineVoice.frequency = 480; //m_mixer->voices.push_back(&sineVoice); m_mixer->handles.push_back(&handle); + m_mixer->handles.push_back(&handle2); err = soundio_outstream_start(m_outStream); if (err) { diff --git a/modules/audio-libsoundio/src/mixer.cxx b/modules/audio-libsoundio/src/mixer.cxx index 9ae8f6b..59d70f7 100644 --- a/modules/audio-libsoundio/src/mixer.cxx +++ b/modules/audio-libsoundio/src/mixer.cxx @@ -6,6 +6,10 @@ namespace Moon { void Mixer::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { + // silence the buffer first + for (size_t channel = 0; channel < layout.channel_count; ++channel) { + memset(areas[channel].ptr, 0, areas[channel].step * frames); + } for(auto const& handle: handles) { handle->mix(areas, layout, sampleRate, frames); } diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index e7f6b7d..47fd472 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -6,9 +6,9 @@ namespace Moon Music::Music(const std::string filename) : file(filename, SFM_READ) { - printf ("Opened file '%s'\n", filename.c_str()) ; - printf (" Sample rate : %d\n", file.samplerate ()) ; - printf (" Channels : %d\n", file.channels ()) ; + printf("Opened file '%s'\n", filename.c_str()); + printf(" Sample rate : %d\n", file.samplerate ()); + printf(" Channels : %d\n", file.channels ()); }; @@ -24,12 +24,12 @@ namespace Moon auto bytes = file.readf(cache, frames); printf("Read n bytes: %d\n", bytes); - printf("file channels: %d\n", channels); for (int frame = 0; frame < frames; ++frame) { for (size_t channel = 0; channel < channels; ++channel) { float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); - float sample = cache[frame * channels + channel]; + // mix the sample! + float sample = *buffer + cache[frame * channels + channel]; // clipping, to avoid overdrive *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); From 1b00ab43b45686bbd3f7619c2057f9ffb1c9965f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 10:50:09 +0900 Subject: [PATCH 32/59] Link ogg/vorbis/flac. --- mrb_config.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mrb_config.rb b/mrb_config.rb index 76115e6..f5aabdb 100644 --- a/mrb_config.rb +++ b/mrb_config.rb @@ -125,6 +125,11 @@ l.libraries << 'SOIL' l.libraries << 'SIL' + l.libraries << 'ogg' + l.libraries << 'vorbis' + l.libraries << 'vorbisenc' + l.libraries << 'flac' + if platform.linux? l.libraries << 'GLEW' l.libraries << 'GL' From 78aae43f3be31cae9251ed1ee5ad41bc52f174a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 10:58:34 +0900 Subject: [PATCH 33/59] Extract the clipping code. --- modules/audio-libsoundio/src/mixer.cxx | 8 ++++++++ modules/audio-libsoundio/src/music.cxx | 4 ---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/audio-libsoundio/src/mixer.cxx b/modules/audio-libsoundio/src/mixer.cxx index 59d70f7..b798657 100644 --- a/modules/audio-libsoundio/src/mixer.cxx +++ b/modules/audio-libsoundio/src/mixer.cxx @@ -13,5 +13,13 @@ namespace Moon { for(auto const& handle: handles) { handle->mix(areas, layout, sampleRate, frames); } + + // clipping, to avoid overdrive + for (int frame = 0; frame < frames; ++frame) { + for (size_t channel = 0; channel < channels; ++channel) { + float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); + *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); + } + } } } diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index 47fd472..1bc56d5 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -30,12 +30,8 @@ namespace Moon // mix the sample! float sample = *buffer + cache[frame * channels + channel]; - - // clipping, to avoid overdrive - *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); } } - //file.seek(frames, SEEK_CUR); delete cache; } } From cf3244537b35778476759d0798bd0d591253d9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 13:14:12 +0900 Subject: [PATCH 34/59] Clear the buffer in case we read less than what was expected. Also only loop over the number of frames we've read (instead of the empty parts). --- modules/audio-libsoundio/src/music.cxx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index 1bc56d5..88e219f 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -20,18 +20,24 @@ namespace Moon // TODO: compare file.channels() with layout.channel_count // handle mono to stereo, vice versa int channels = file.channels(); - float* cache = new float[frames * channels * file.samplerate()]; - auto bytes = file.readf(cache, frames); - printf("Read n bytes: %d\n", bytes); + int totalSamples = frames * channels * file.samplerate(); + float* chunk = new float[totalSamples]; + // clear the array (in case we read less data than available) + memset(chunk, 0, totalSamples); - for (int frame = 0; frame < frames; ++frame) { + int framesRead = file.readf(cache, frames); + printf("Read n frames: %d\n", framesRead); + + // TODO: compare frames with framesRead + + for (int frame = 0; frame < framesRead; ++frame) { for (size_t channel = 0; channel < channels; ++channel) { float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); // mix the sample! - float sample = *buffer + cache[frame * channels + channel]; + float sample = *buffer + chunk[frame * channels + channel]; } } - delete cache; + delete chunk; } } From 4ddb5fd8c5edd65ce030a051decf0cc26cd88c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 17:15:52 +0900 Subject: [PATCH 35/59] Update README a tiny bit. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bf43b63..003dd94 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ [![Coverity Scan Build Status](https://img.shields.io/coverity/scan/5666.svg)](https://scan.coverity.com/projects/5666) ## Introduction -Moon is a experimental prototyping 2D Game Engine written in C++ and scripted using [mruby](https://github.com/mruby/mruby). +Moon is a experimental 2D game engine prototype written in C++ and scripted using [mruby](https://github.com/mruby/mruby). ## Supported -Currently testing is done linux, moon may not run or even compile on other systems. If you managed to get Moon running on your system, please open a PR and share your changes to get it built. +Currently we have builds fo Linux and OS X. Moon may not run or even compile on other systems. If you managed to get Moon running on your system, please open a PR and share your changes to get it built. ## Requirements @@ -24,7 +24,7 @@ ruby >= 1.9.2 yard (for docs) # runtime -OpenAL +OpenAL # for gorilla audio OpenGL # For dependency docs From e40d991b3c9fbff6b15a2459c1769349ebca5b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 17:18:15 +0900 Subject: [PATCH 36/59] Oopsie, fix mixing. --- modules/audio-libsoundio/src/music.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index 88e219f..4bb58d0 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -33,9 +33,8 @@ namespace Moon for (int frame = 0; frame < framesRead; ++frame) { for (size_t channel = 0; channel < channels; ++channel) { float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); - // mix the sample! - float sample = *buffer + chunk[frame * channels + channel]; + *buffer += chunk[frame * channels + channel]; } } delete chunk; From 9aeb88de41b67deebb2cc95288a7173c6736eefb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 5 Jul 2016 22:49:53 +0900 Subject: [PATCH 37/59] Fix some things, implement Sound. --- .../include/moon/audio/libsoundio/audio.hxx | 1 + .../include/moon/audio/libsoundio/music.hxx | 4 +- .../include/moon/audio/libsoundio/sound.hxx | 26 ++++++++-- modules/audio-libsoundio/src/audio.cxx | 7 +-- modules/audio-libsoundio/src/mixer.cxx | 3 +- modules/audio-libsoundio/src/music.cxx | 4 +- modules/audio-libsoundio/src/sound.cxx | 49 +++++++++++++++++++ 7 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 modules/audio-libsoundio/src/sound.cxx diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx index 99a2dfd..18daa07 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/audio.hxx @@ -7,6 +7,7 @@ #define MOON_AUDIO_BACKEND "libsoundio" #include "moon/audio/libsoundio/mixer.hxx" #include "moon/audio/libsoundio/music.hxx" +#include "moon/audio/libsoundio/sound.hxx" namespace Moon { class Audio { diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx index ee7b4b6..c08a92a 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx @@ -10,12 +10,12 @@ namespace Moon { class Music : public AbstractSource { public: - SndfileHandle file; - Music(const std::string filename); ~Music(); void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); + private: + SndfileHandle file; }; }; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx index d7fb38d..417037c 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -1,9 +1,27 @@ #ifndef MOON_AUDIO_LIBSOUNDIO_SOUND_H #define MOON_AUDIO_LIBSOUNDIO_SOUND_H -namespace Moon { - struct Sound { - }; -} +#include "moon/intern.h" +#include +#include +#include "moon/audio/libsoundio/mixer.hxx" + +namespace Moon +{ + class Sound : public AbstractSource { + public: + Sound(const std::string filename); + ~Sound(); + + void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); + private: + float* source; // [] ? + int channels; + int sampleRate; + + int totalFrames; + int currentFrame; + }; +}; #endif diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 5c32124..f1ee8d0 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -31,8 +31,9 @@ class SampleVoice : public AbstractVoice { static SineVoice sineVoice; -static Moon::Music handle("GoSleepAlready.ogg"); -static Moon::Music handle2("medusa.wav"); +static Moon::Sound handle("sfx.wav"); +//static Moon::Music handle("GoSleepAlready.ogg"); +//static Moon::Music handle2("medusa.wav"); static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; @@ -128,7 +129,7 @@ namespace Moon sineVoice.frequency = 480; //m_mixer->voices.push_back(&sineVoice); m_mixer->handles.push_back(&handle); - m_mixer->handles.push_back(&handle2); + //m_mixer->handles.push_back(&handle2); err = soundio_outstream_start(m_outStream); if (err) { diff --git a/modules/audio-libsoundio/src/mixer.cxx b/modules/audio-libsoundio/src/mixer.cxx index b798657..98286c8 100644 --- a/modules/audio-libsoundio/src/mixer.cxx +++ b/modules/audio-libsoundio/src/mixer.cxx @@ -16,8 +16,9 @@ namespace Moon { // clipping, to avoid overdrive for (int frame = 0; frame < frames; ++frame) { - for (size_t channel = 0; channel < channels; ++channel) { + for (size_t channel = 0; channel < layout.channel_count; ++channel) { float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); + float sample = *buffer; *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); } } diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index 4bb58d0..a46188e 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -25,7 +25,7 @@ namespace Moon // clear the array (in case we read less data than available) memset(chunk, 0, totalSamples); - int framesRead = file.readf(cache, frames); + int framesRead = file.readf(chunk, frames); printf("Read n frames: %d\n", framesRead); // TODO: compare frames with framesRead @@ -37,6 +37,6 @@ namespace Moon *buffer += chunk[frame * channels + channel]; } } - delete chunk; + delete[] chunk; } } diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx new file mode 100644 index 0000000..b280d47 --- /dev/null +++ b/modules/audio-libsoundio/src/sound.cxx @@ -0,0 +1,49 @@ +#include "moon/intern.h" +#include "moon/audio/libsoundio/sound.hxx" + +namespace Moon +{ + Sound::Sound(const std::string filename) + { + SndfileHandle file(filename, SFM_READ); + printf("Opened file '%s'\n", filename.c_str()); + printf(" Sample rate : %d\n", file.samplerate ()); + printf(" Channels : %d\n", file.channels ()); + printf(" Frames : %d\n", file.frames()); + + channels = file.channels(); + sampleRate = file.samplerate(); + + currentFrame = 0; + + int totalSamples = file.frames() * channels * sampleRate; + source = new float[totalSamples]; + memset(source, 0, totalSamples); + + totalFrames = file.readf(source, file.frames()); + printf("Read n frames: %d\n", totalFrames); + // TODO: shout if totalFrames didn't match file.frames() + }; + + + Sound::~Sound() { + delete[] source; + } + + + void Sound::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { + // TODO: compare file.channels() with layout.channel_count + // handle mono to stereo, vice versa + + // compare how many frames we still have + + for (int frame = 0; frame < frames; ++frame) { + for (size_t channel = 0; channel < channels; ++channel) { + float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); + // mix the sample! + *buffer += source[(currentFrame + frame) * channels + channel]; + } + } + currentFrame += frames; + } +} From 3b0a843ea81c0fb81579f2167089a5bdfed39dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Wed, 6 Jul 2016 22:30:38 +0900 Subject: [PATCH 38/59] Implement audio handles. --- .../include/moon/audio/libsoundio/handle.hxx | 23 ++++++++++ .../include/moon/audio/libsoundio/mixer.hxx | 23 +--------- .../include/moon/audio/libsoundio/music.hxx | 8 +++- .../include/moon/audio/libsoundio/sound.hxx | 12 ++++-- .../include/moon/audio/libsoundio/source.hxx | 17 +++----- modules/audio-libsoundio/src/audio.cxx | 39 ++--------------- modules/audio-libsoundio/src/handle.cxx | 42 +++++++++++++++++++ modules/audio-libsoundio/src/music.cxx | 31 +++++--------- modules/audio-libsoundio/src/sound.cxx | 32 +++++++------- modules/audio-libsoundio/src/source.cxx | 40 ------------------ 10 files changed, 117 insertions(+), 150 deletions(-) create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx create mode 100644 modules/audio-libsoundio/src/handle.cxx delete mode 100644 modules/audio-libsoundio/src/source.cxx diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx new file mode 100644 index 0000000..461f8e6 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx @@ -0,0 +1,23 @@ +#ifndef MOON_AUDIO_LIBSOUNDIO_HANDLE_H +#define MOON_AUDIO_LIBSOUNDIO_HANDLE_H + +#include "moon/intern.h" +#include +#include +#include "moon/audio/libsoundio/source.hxx" +#include "moon/audio/libsoundio/music.hxx" +#include "moon/audio/libsoundio/sound.hxx" + +namespace Moon { + class Handle { + public: + Handle(Moon::Source* source); + ~Handle(); + + void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); + private: + Moon::Source* source; // TODO:mrb_sound/music sources will need to be wrapped... if a source deallocates, the handle will be broken (shared_ptr) + }; +}; + +#endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx index 62fd7c9..92fabf2 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx @@ -2,26 +2,7 @@ #define MOON_AUDIO_LIBSOUNDIO_MIXER_H #include #include - -class AbstractVoice { - public: - bool active; - int frame; - - virtual float getSample(float sampleRate) { - return 0.0f; - }; - - virtual void reset() { - active = false; - frame = 0; - } -}; - -class AbstractSource { - public: - virtual void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) {}; -}; +#include "moon/audio/libsoundio/handle.hxx" namespace Moon { @@ -30,7 +11,7 @@ namespace Moon Mixer(); void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); - std::vector handles; + std::vector handles; private: }; } diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx index c08a92a..446ec90 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx @@ -4,16 +4,20 @@ #include "moon/intern.h" #include #include +#include "moon/audio/libsoundio/source.hxx" #include "moon/audio/libsoundio/mixer.hxx" namespace Moon { - class Music : public AbstractSource { + class Music : public Source { public: Music(const std::string filename); ~Music(); - void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); + int read(float* dst, int frames); + + int channels(); + int sampleRate(); private: SndfileHandle file; }; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx index 417037c..0d5932d 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -4,20 +4,24 @@ #include "moon/intern.h" #include #include +#include "moon/audio/libsoundio/source.hxx" #include "moon/audio/libsoundio/mixer.hxx" namespace Moon { - class Sound : public AbstractSource { + class Sound : public Source { public: Sound(const std::string filename); ~Sound(); - void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); + int read(float* dst, int frames); + + int channels(); + int sampleRate(); private: float* source; // [] ? - int channels; - int sampleRate; + int m_channels; + int m_sampleRate; int totalFrames; int currentFrame; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx index 7890eb5..9e362cd 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx @@ -2,23 +2,16 @@ #define MOON_AUDIO_LIBSOUNDIO_SOURCE_H #include "moon/intern.h" -#include -#include namespace Moon { class Source { public: - SF_INFO info; - SNDFILE* file; - - Source(const std::string filename); - ~Source(); - - bool seekable(); - sf_count_t seek(sf_count_t frames, int whence); - sf_count_t tell(); - sf_count_t read(float* ptr, sf_count_t frames); + virtual int read(float* dst, int frames) = 0; + // seek(pos, type); + // + virtual int channels() = 0; + virtual int sampleRate() = 0; }; } diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index f1ee8d0..1b155a4 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -2,38 +2,11 @@ #include "moon/audio/libsoundio/audio.hxx" #include -class SineVoice : public AbstractVoice { -public: - float frequency; - float velocity; - - float getSample(float sampleRate) { - if (frequency > 0) - { - return sinf((2 * M_PI * frame * frequency) / sampleRate) * velocity; - } - return 0.0f; - } - - void reset() { - AbstractVoice::reset(); - frequency = 0.0f; - velocity = 0.0f; - } -}; - -class SampleVoice : public AbstractVoice { - float getSample(float sampleRate) { - // TODO - return 0.0f; - } -}; - -static SineVoice sineVoice; - -static Moon::Sound handle("sfx.wav"); +//static Moon::Sound sfx("sfx.wav"); +//static Moon::Music music("GoSleepAlready.ogg"); +static Moon::Music music("medusa.wav"); +static Moon::Handle handle(&music); //static Moon::Music handle("GoSleepAlready.ogg"); -//static Moon::Music handle2("medusa.wav"); static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; @@ -124,10 +97,6 @@ namespace Moon // create a new mixer m_mixer = new Mixer(); - sineVoice.active = true; - sineVoice.velocity = 0.2; - sineVoice.frequency = 480; - //m_mixer->voices.push_back(&sineVoice); m_mixer->handles.push_back(&handle); //m_mixer->handles.push_back(&handle2); diff --git a/modules/audio-libsoundio/src/handle.cxx b/modules/audio-libsoundio/src/handle.cxx new file mode 100644 index 0000000..2431b6f --- /dev/null +++ b/modules/audio-libsoundio/src/handle.cxx @@ -0,0 +1,42 @@ +#include "moon/intern.h" +#include "moon/audio/libsoundio/music.hxx" + +namespace Moon +{ + Handle::Handle(Moon::Source* source) // this can take mixer as arg in the future if we have more than 1 + { + this->source = source; + }; + + + Handle::~Handle() { + } + + + void Handle::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { + // TODO: compare source.channels() with layout.channel_count + // handle mono to stereo, vice versa + int channels = source->channels(); + printf(" yy : %d\n", channels); + int totalSamples = frames * channels * source->sampleRate(); + printf(" totl : %d\n", totalSamples); + printf(" aal : %d\n", source->sampleRate()); + float* chunk = new float[totalSamples]; + // clear the array (in case we read less data than available) + memset(chunk, 0, totalSamples); + + int actual = source->read(chunk, frames); + printf("Read n frames: %d\n", actual); + + // TODO: compare frames with framesRead + + for (int frame = 0; frame < actual; ++frame) { + for (size_t channel = 0; channel < channels; ++channel) { + float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); + // mix the sample! + *buffer += chunk[frame * channels + channel]; + } + } + delete[] chunk; + } +} diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index a46188e..d6318ce 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -15,28 +15,17 @@ namespace Moon Music::~Music() { } + int Music::channels() { + return file.channels(); + } - void Music::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { - // TODO: compare file.channels() with layout.channel_count - // handle mono to stereo, vice versa - int channels = file.channels(); - int totalSamples = frames * channels * file.samplerate(); - float* chunk = new float[totalSamples]; - // clear the array (in case we read less data than available) - memset(chunk, 0, totalSamples); - - int framesRead = file.readf(chunk, frames); - printf("Read n frames: %d\n", framesRead); - - // TODO: compare frames with framesRead + int Music::sampleRate() { + return file.samplerate(); + } - for (int frame = 0; frame < framesRead; ++frame) { - for (size_t channel = 0; channel < channels; ++channel) { - float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); - // mix the sample! - *buffer += chunk[frame * channels + channel]; - } - } - delete[] chunk; + // returns how many frames we actually read + int Music::read(float* dst, int frames) + { + return file.readf(dst, frames); } } diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx index b280d47..e3fbaad 100644 --- a/modules/audio-libsoundio/src/sound.cxx +++ b/modules/audio-libsoundio/src/sound.cxx @@ -11,12 +11,12 @@ namespace Moon printf(" Channels : %d\n", file.channels ()); printf(" Frames : %d\n", file.frames()); - channels = file.channels(); - sampleRate = file.samplerate(); + m_channels = file.channels(); + m_sampleRate = file.samplerate(); currentFrame = 0; - int totalSamples = file.frames() * channels * sampleRate; + int totalSamples = file.frames() * m_channels * m_sampleRate; source = new float[totalSamples]; memset(source, 0, totalSamples); @@ -30,20 +30,22 @@ namespace Moon delete[] source; } + int Sound::channels() { + return m_channels; + } - void Sound::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { - // TODO: compare file.channels() with layout.channel_count - // handle mono to stereo, vice versa + int Sound::sampleRate() { + return m_sampleRate; + } - // compare how many frames we still have + // returns how many frames we actually read + int Sound::read(float* dst, int frames) + { + if(currentFrame > totalFrames) { return 0; } + // handle buffer edges (don't point past edge) + int actual = (currentFrame > totalFrames) ? totalFrames - currentFrame : frames; + memcpy(dst, &source[currentFrame * m_channels], actual * m_channels * m_sampleRate); - for (int frame = 0; frame < frames; ++frame) { - for (size_t channel = 0; channel < channels; ++channel) { - float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); - // mix the sample! - *buffer += source[(currentFrame + frame) * channels + channel]; - } - } - currentFrame += frames; + currentFrame += actual; } } diff --git a/modules/audio-libsoundio/src/source.cxx b/modules/audio-libsoundio/src/source.cxx deleted file mode 100644 index ec60bb1..0000000 --- a/modules/audio-libsoundio/src/source.cxx +++ /dev/null @@ -1,40 +0,0 @@ -#include "moon/intern.h" -#include "moon/audio/libsoundio/source.hxx" -#include - -namespace Moon -{ - Source::Source(const std::string filename) { - info.format = 0; - file = sf_open(filename.c_str(), SFM_READ, &info); - - if (!file) { - std::stringstream error; - error << "Unable to open audio file '" - << filename << "'"; - throw error.str(); - } - }; - - - Source::~Source() { - if (file) sf_close(file); - } - - - bool Source::seekable() { - return info.seekable == SF_TRUE; - } - - sf_count_t Source::seek(sf_count_t frames, int whence) { - return sf_seek(file, frames, whence); - } - - sf_count_t Source::tell() { - return seek(0, SEEK_CUR); - } - - sf_count_t Source::read(float* ptr, sf_count_t frames) { - return sf_readf_float(file, ptr, frames); - } -} From c88697023db7d393937080c3f313802bc9faf01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Wed, 6 Jul 2016 23:41:47 +0900 Subject: [PATCH 39/59] meme-set is evil --- modules/audio-libsoundio/src/handle.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/src/handle.cxx b/modules/audio-libsoundio/src/handle.cxx index 2431b6f..da0ae33 100644 --- a/modules/audio-libsoundio/src/handle.cxx +++ b/modules/audio-libsoundio/src/handle.cxx @@ -23,7 +23,7 @@ namespace Moon printf(" aal : %d\n", source->sampleRate()); float* chunk = new float[totalSamples]; // clear the array (in case we read less data than available) - memset(chunk, 0, totalSamples); + //memset(chunk, 0, totalSamples); int actual = source->read(chunk, frames); printf("Read n frames: %d\n", actual); From d62cb854fe9f25fadda2ddc5dc51a94f258af26e Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 6 Jul 2016 09:46:33 -0500 Subject: [PATCH 40/59] FLAC vs flac! Because different systems --- mrb_config.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mrb_config.rb b/mrb_config.rb index f5aabdb..32ea78c 100644 --- a/mrb_config.rb +++ b/mrb_config.rb @@ -128,9 +128,9 @@ l.libraries << 'ogg' l.libraries << 'vorbis' l.libraries << 'vorbisenc' - l.libraries << 'flac' if platform.linux? + l.libraries << 'FLAC' l.libraries << 'GLEW' l.libraries << 'GL' l.libraries << 'openal' @@ -143,6 +143,7 @@ l.libraries << 'opengl32' l.libraries << 'OpenAL32' elsif platform.darwin? + l.libraries << 'flac' l.libraries << 'GLEW' l.flags_after_libraries << '-framework OpenGL' # gorilla From 2c986618921f3632e4b56a5ba5822d516eb3c1c2 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Wed, 6 Jul 2016 09:59:40 -0500 Subject: [PATCH 41/59] modules/system,modules/audio-libsoundio: Added moon_memzerof and code gardening Originally I did a thing with music, buuuut, because of the rebase, all of it was pointless --- .../include/moon/audio/libsoundio/mixer.hxx | 2 ++ modules/audio-libsoundio/src/audio.cxx | 1 - modules/audio-libsoundio/src/mixer.cxx | 2 +- modules/audio-libsoundio/src/music.cxx | 10 +++++----- modules/system/include/moon/intern.h | 9 +++++++++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx index 92fabf2..80df4b4 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mixer.hxx @@ -1,5 +1,7 @@ #ifndef MOON_AUDIO_LIBSOUNDIO_MIXER_H #define MOON_AUDIO_LIBSOUNDIO_MIXER_H + +#include "moon/intern.h" #include #include #include "moon/audio/libsoundio/handle.hxx" diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 1b155a4..58a685b 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -6,7 +6,6 @@ //static Moon::Music music("GoSleepAlready.ogg"); static Moon::Music music("medusa.wav"); static Moon::Handle handle(&music); -//static Moon::Music handle("GoSleepAlready.ogg"); static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; diff --git a/modules/audio-libsoundio/src/mixer.cxx b/modules/audio-libsoundio/src/mixer.cxx index 98286c8..96dec07 100644 --- a/modules/audio-libsoundio/src/mixer.cxx +++ b/modules/audio-libsoundio/src/mixer.cxx @@ -10,7 +10,7 @@ namespace Moon { for (size_t channel = 0; channel < layout.channel_count; ++channel) { memset(areas[channel].ptr, 0, areas[channel].step * frames); } - for(auto const& handle: handles) { + for(auto const& handle: handles) { handle->mix(areas, layout, sampleRate, frames); } diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index d6318ce..c7ac070 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -6,9 +6,9 @@ namespace Moon Music::Music(const std::string filename) : file(filename, SFM_READ) { - printf("Opened file '%s'\n", filename.c_str()); - printf(" Sample rate : %d\n", file.samplerate ()); - printf(" Channels : %d\n", file.channels ()); + printf("Opened file '%s'\n", filename.c_str()); + printf(" Sample rate : %d\n", file.samplerate()); + printf(" Channels : %d\n", file.channels()); }; @@ -16,11 +16,11 @@ namespace Moon } int Music::channels() { - return file.channels(); + return file.channels(); } int Music::sampleRate() { - return file.samplerate(); + return file.samplerate(); } // returns how many frames we actually read diff --git a/modules/system/include/moon/intern.h b/modules/system/include/moon/intern.h index a41c5dd..e80f55d 100644 --- a/modules/system/include/moon/intern.h +++ b/modules/system/include/moon/intern.h @@ -28,6 +28,15 @@ exists(const std::string& name) return (stat(name.c_str(), &buffer) == 0); }; +static inline void* +moon_memzerof(float* ptr, size_t len) +{ + for (size_t i = 0; i < len; ++i) { + ptr[i] = 0.0f; + } + return ptr; +} + static inline void* moon_mallocset(size_t len, int value) { From a01ab3f67a6d80c6db23285be2bae1d7ee7c710b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Wed, 6 Jul 2016 23:59:16 +0900 Subject: [PATCH 42/59] Fix Sound, sort of. It plays back really fast and weird --- modules/audio-libsoundio/src/handle.cxx | 5 +---- modules/audio-libsoundio/src/sound.cxx | 5 +++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/audio-libsoundio/src/handle.cxx b/modules/audio-libsoundio/src/handle.cxx index da0ae33..671b383 100644 --- a/modules/audio-libsoundio/src/handle.cxx +++ b/modules/audio-libsoundio/src/handle.cxx @@ -17,16 +17,13 @@ namespace Moon // TODO: compare source.channels() with layout.channel_count // handle mono to stereo, vice versa int channels = source->channels(); - printf(" yy : %d\n", channels); int totalSamples = frames * channels * source->sampleRate(); - printf(" totl : %d\n", totalSamples); - printf(" aal : %d\n", source->sampleRate()); float* chunk = new float[totalSamples]; // clear the array (in case we read less data than available) //memset(chunk, 0, totalSamples); int actual = source->read(chunk, frames); - printf("Read n frames: %d\n", actual); + //printf("Read n frames: %d\n", actual); // TODO: compare frames with framesRead diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx index e3fbaad..28f0ef7 100644 --- a/modules/audio-libsoundio/src/sound.cxx +++ b/modules/audio-libsoundio/src/sound.cxx @@ -21,7 +21,7 @@ namespace Moon memset(source, 0, totalSamples); totalFrames = file.readf(source, file.frames()); - printf("Read n frames: %d\n", totalFrames); + printf("total frames: %d\n", totalFrames); // TODO: shout if totalFrames didn't match file.frames() }; @@ -44,8 +44,9 @@ namespace Moon if(currentFrame > totalFrames) { return 0; } // handle buffer edges (don't point past edge) int actual = (currentFrame > totalFrames) ? totalFrames - currentFrame : frames; - memcpy(dst, &source[currentFrame * m_channels], actual * m_channels * m_sampleRate); + memcpy(dst, &source[currentFrame * m_channels], sizeof(float) * actual * m_channels * m_sampleRate); currentFrame += actual; + return actual; } } From 46ce621920a2a7278f2456ead994c06fc6e95291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Thu, 7 Jul 2016 00:26:45 +0900 Subject: [PATCH 43/59] hmm --- modules/audio-libsoundio/src/audio.cxx | 4 ++-- modules/audio-libsoundio/src/sound.cxx | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index 58a685b..a4b1535 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -2,10 +2,10 @@ #include "moon/audio/libsoundio/audio.hxx" #include -//static Moon::Sound sfx("sfx.wav"); +static Moon::Sound sfx("sfx.wav"); //static Moon::Music music("GoSleepAlready.ogg"); static Moon::Music music("medusa.wav"); -static Moon::Handle handle(&music); +static Moon::Handle handle(&sfx); static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx index 28f0ef7..7e40c18 100644 --- a/modules/audio-libsoundio/src/sound.cxx +++ b/modules/audio-libsoundio/src/sound.cxx @@ -18,7 +18,6 @@ namespace Moon int totalSamples = file.frames() * m_channels * m_sampleRate; source = new float[totalSamples]; - memset(source, 0, totalSamples); totalFrames = file.readf(source, file.frames()); printf("total frames: %d\n", totalFrames); @@ -43,8 +42,8 @@ namespace Moon { if(currentFrame > totalFrames) { return 0; } // handle buffer edges (don't point past edge) - int actual = (currentFrame > totalFrames) ? totalFrames - currentFrame : frames; - memcpy(dst, &source[currentFrame * m_channels], sizeof(float) * actual * m_channels * m_sampleRate); + int actual = (currentFrame + frames > totalFrames) ? totalFrames - currentFrame : frames; + memcpy(dst, &source[currentFrame], sizeof(float) * actual * m_channels * m_sampleRate); currentFrame += actual; return actual; From 87d48f7a1eb7a47ab40ecc8578330c009ab0e5f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Thu, 7 Jul 2016 00:41:24 +0900 Subject: [PATCH 44/59] Works at proper playback speed! --- modules/audio-libsoundio/src/sound.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx index 7e40c18..2cf1662 100644 --- a/modules/audio-libsoundio/src/sound.cxx +++ b/modules/audio-libsoundio/src/sound.cxx @@ -43,7 +43,7 @@ namespace Moon if(currentFrame > totalFrames) { return 0; } // handle buffer edges (don't point past edge) int actual = (currentFrame + frames > totalFrames) ? totalFrames - currentFrame : frames; - memcpy(dst, &source[currentFrame], sizeof(float) * actual * m_channels * m_sampleRate); + memcpy(dst, &source[currentFrame * m_channels], sizeof(float) * actual * m_channels); currentFrame += actual; return actual; From 02044452d08fb279be7238a2fda8833dbba9dad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 10 Jul 2016 00:23:45 +0900 Subject: [PATCH 45/59] Add support for pan/pitch/gain and map mono to stereo. This assumes we always want to play stereo (no 5.1 or 7.1) --- .../include/moon/audio/libsoundio/handle.hxx | 4 +++ .../include/moon/audio/libsoundio/sound.hxx | 4 +-- modules/audio-libsoundio/src/audio.cxx | 6 ++--- modules/audio-libsoundio/src/handle.cxx | 26 ++++++++++++------- modules/system/include/moon/intern.h | 3 +++ 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx index 461f8e6..d448d39 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx @@ -15,6 +15,10 @@ namespace Moon { ~Handle(); void mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames); + + float pan; + float pitch; + float gain; private: Moon::Source* source; // TODO:mrb_sound/music sources will need to be wrapped... if a source deallocates, the handle will be broken (shared_ptr) }; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx index 0d5932d..9a93974 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -23,8 +23,8 @@ namespace Moon int m_channels; int m_sampleRate; - int totalFrames; - int currentFrame; + std::uint32_t totalFrames; + std::uint32_t currentFrame; }; }; diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index a4b1535..cbbb210 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -3,9 +3,9 @@ #include static Moon::Sound sfx("sfx.wav"); -//static Moon::Music music("GoSleepAlready.ogg"); -static Moon::Music music("medusa.wav"); -static Moon::Handle handle(&sfx); +static Moon::Music music("GoSleepAlready.ogg"); +//static Moon::Music music("medusa.wav"); +static Moon::Handle handle(&music); static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; diff --git a/modules/audio-libsoundio/src/handle.cxx b/modules/audio-libsoundio/src/handle.cxx index 671b383..43a81d3 100644 --- a/modules/audio-libsoundio/src/handle.cxx +++ b/modules/audio-libsoundio/src/handle.cxx @@ -6,6 +6,9 @@ namespace Moon Handle::Handle(Moon::Source* source) // this can take mixer as arg in the future if we have more than 1 { this->source = source; + this->pan = 0.0f; + this->pitch = 1.0f; + this->gain = 1.0f; }; @@ -14,25 +17,30 @@ namespace Moon void Handle::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { + float pan = this->pan; + pan = (pan + 1.0f) / 2.0f; + pan = std::clamp(pan, 0.0f, 1.0f); + + // resample and pitch + float sampleScale = source->sampleRate() / sampleRate * pitch; + // TODO: compare source.channels() with layout.channel_count - // handle mono to stereo, vice versa int channels = source->channels(); int totalSamples = frames * channels * source->sampleRate(); float* chunk = new float[totalSamples]; - // clear the array (in case we read less data than available) - //memset(chunk, 0, totalSamples); int actual = source->read(chunk, frames); //printf("Read n frames: %d\n", actual); - // TODO: compare frames with framesRead + // TODO: mixer should complain if we don't have stereo for (int frame = 0; frame < actual; ++frame) { - for (size_t channel = 0; channel < channels; ++channel) { - float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); - // mix the sample! - *buffer += chunk[frame * channels + channel]; - } + float* left = (float*)(areas[0].ptr + areas[0].step * frame); + float* right = (float*)(areas[1].ptr + areas[1].step * frame); + // mix the sample! + int offset = frame * channels * sampleScale; + *left += chunk[offset] * gain * (1.0f - pan) * 2; + *right += chunk[offset + ((channels == 1) ? 0 : 1)] * gain * pan * 2; } delete[] chunk; } diff --git a/modules/system/include/moon/intern.h b/modules/system/include/moon/intern.h index e80f55d..57e56b5 100644 --- a/modules/system/include/moon/intern.h +++ b/modules/system/include/moon/intern.h @@ -12,6 +12,9 @@ #include #include +#include +#include + // _WIN32 is set for both 32 and 64 bit #ifdef _WIN32 # define stat _stat From d9edf982d8b81cab4c0d762b16d6de31bc042813 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Sat, 9 Jul 2016 13:34:58 -0500 Subject: [PATCH 46/59] modules/audio-libsoundio: Cleaned up audio.cxx Removed hardcoded paths and bits of unused code --- modules/audio-libsoundio/src/audio.cxx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/modules/audio-libsoundio/src/audio.cxx b/modules/audio-libsoundio/src/audio.cxx index cbbb210..3c11f20 100644 --- a/modules/audio-libsoundio/src/audio.cxx +++ b/modules/audio-libsoundio/src/audio.cxx @@ -2,11 +2,6 @@ #include "moon/audio/libsoundio/audio.hxx" #include -static Moon::Sound sfx("sfx.wav"); -static Moon::Music music("GoSleepAlready.ogg"); -//static Moon::Music music("medusa.wav"); -static Moon::Handle handle(&music); - static void Moon_AudioWrite(struct SoundIoOutStream *outstream, int frameCountMin, int frameCountMax) { struct SoundIoChannelArea *areas; const struct SoundIoChannelLayout *layout = &outstream->layout; @@ -96,17 +91,10 @@ namespace Moon // create a new mixer m_mixer = new Mixer(); - m_mixer->handles.push_back(&handle); - //m_mixer->handles.push_back(&handle2); - err = soundio_outstream_start(m_outStream); if (err) { return Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_START_ERROR; - // raise AudioError, "unable to start device" } - //for (int voiceIndex = 0; voiceIndex < AUDIO_VOICE_MAX; ++voiceIndex) { - // moonVoices[voiceIndex].reset(); - //} // Finally, after bashing your head against the table, you can finally have audio? return Moon::Audio::ErrorCode::MOON_AUDIO_OK; } From 0b77791119833d9a356cd94e3ec3f693420dd806 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Sat, 9 Jul 2016 13:35:25 -0500 Subject: [PATCH 47/59] modules/audio-libsoundio: clamp was not available on my system for some reason Use glm::clamp instead, that we have --- modules/audio-libsoundio/src/handle.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/src/handle.cxx b/modules/audio-libsoundio/src/handle.cxx index 43a81d3..30e5186 100644 --- a/modules/audio-libsoundio/src/handle.cxx +++ b/modules/audio-libsoundio/src/handle.cxx @@ -1,3 +1,4 @@ +#include "moon/glm.h" #include "moon/intern.h" #include "moon/audio/libsoundio/music.hxx" @@ -19,7 +20,7 @@ namespace Moon void Handle::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { float pan = this->pan; pan = (pan + 1.0f) / 2.0f; - pan = std::clamp(pan, 0.0f, 1.0f); + pan = glm::clamp(pan, 0.0f, 1.0f); // resample and pitch float sampleScale = source->sampleRate() / sampleRate * pitch; From 2f001af6e111b21d1bed8f78b25c05ebcdf16722 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Sat, 9 Jul 2016 13:37:16 -0500 Subject: [PATCH 48/59] modules/audio-libsoundio: Stubbed Music --- modules/audio-libsoundio/src/mrb_music.cxx | 121 +++++++++++++++++++- modules/system/include/moon/mrb/helpers.hxx | 10 ++ 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/src/mrb_music.cxx b/modules/audio-libsoundio/src/mrb_music.cxx index 9f726ba..6ca0fe4 100644 --- a/modules/audio-libsoundio/src/mrb_music.cxx +++ b/modules/audio-libsoundio/src/mrb_music.cxx @@ -6,8 +6,127 @@ #include "moon/audio/libsoundio/music.hxx" #include "moon/api.h" #include "moon/intern.h" +#include "moon/mrb/helpers.hxx" + +static void +music_free(mrb_state *mrb, void *p) +{ + Moon::Music *music = static_cast(p); + if (music) { + delete(music); + } +} + +MOON_C_API const struct mrb_data_type music_data_type = { "Moon::Music", music_free }; + +static mrb_value +music_initialize(mrb_state* mrb, mrb_value self) +{ + char* filename; + mrb_get_args(mrb, "z", &filename); + moon_data_cleanup(mrb, self); + if (exists(filename)) { + Moon::Music* music = new Moon::Music(std::string(filename)); + mrb_data_init(self, music, &music_data_type); + } else { + mrb_raisef(mrb, E_SCRIPT_ERROR, + "cannot load such file -- %S", + mrb_str_new_cstr(mrb, filename)); + } + return self; +} + + +static mrb_value +music_play(mrb_state* mrb, mrb_value self) +{ + mrb_float gain = 1.0f; + mrb_float pitch = 1.0f; + mrb_float pan = 1.0f; + mrb_get_args(mrb, "|fff", &gain, &pitch, &pan); + // TODO + return self; +} + +static mrb_value +music_stop(mrb_state* mrb, mrb_value self) +{ + // TODO + return self; +} + +static mrb_value +music_seek(mrb_state* mrb, mrb_value self) +{ + return self; +} + +static mrb_value +music_pos(mrb_state* mrb, mrb_value self) +{ + return mrb_fixnum_value(0); +} + +static mrb_value +music_length(mrb_state* mrb, mrb_value self) +{ + return mrb_fixnum_value(0); +} + +static mrb_value +music_loop(mrb_state* mrb, mrb_value self) +{ + return self; +} + +static mrb_value +music_clear_loop(mrb_state* mrb, mrb_value self) +{ + return self; +} + +static mrb_value +music_is_playing(mrb_state* mrb, mrb_value self) +{ + // TODO + return mrb_bool_value(true); +} + +static mrb_value +music_is_stopped(mrb_state* mrb, mrb_value self) +{ + // TODO + return mrb_bool_value(false); +} + +static mrb_value +music_is_finished(mrb_state* mrb, mrb_value self) +{ + // TODO + return mrb_bool_value(false); +} MOON_C_API void -mmrb_music_init(mrb_state *mrb, struct RClass *mod) +mmrb_music_init(mrb_state* mrb, struct RClass* mod) { + struct RClass *music_class = mrb_define_class_under(mrb, mod, "Music", mrb->object_class); + MRB_SET_INSTANCE_TT(music_class, MRB_TT_DATA); + + mrb_define_method(mrb, music_class, "initialize", music_initialize, MRB_ARGS_REQ(2)); + + /* Playback */ + mrb_define_method(mrb, music_class, "play", music_play, MRB_ARGS_OPT(3)); + mrb_define_method(mrb, music_class, "stop", music_stop, MRB_ARGS_NONE()); + + /* Position */ + mrb_define_method(mrb, music_class, "seek", music_seek, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, music_class, "pos", music_pos, MRB_ARGS_NONE()); + mrb_define_method(mrb, music_class, "length", music_length, MRB_ARGS_NONE()); + mrb_define_method(mrb, music_class, "loop", music_loop, MRB_ARGS_OPT(2)); + mrb_define_method(mrb, music_class, "clear_loop", music_clear_loop, MRB_ARGS_NONE()); + + /* Query */ + mrb_define_method(mrb, music_class, "playing?", music_is_playing, MRB_ARGS_NONE()); + mrb_define_method(mrb, music_class, "stopped?", music_is_stopped, MRB_ARGS_NONE()); + mrb_define_method(mrb, music_class, "finished?", music_is_finished, MRB_ARGS_NONE()); } diff --git a/modules/system/include/moon/mrb/helpers.hxx b/modules/system/include/moon/mrb/helpers.hxx index 86234d0..e777b43 100644 --- a/modules/system/include/moon/mrb/helpers.hxx +++ b/modules/system/include/moon/mrb/helpers.hxx @@ -27,4 +27,14 @@ moon_iv_get(mrb_state *mrb, mrb_value self, const char *name) return iv_value; } +static inline void +moon_data_cleanup(mrb_state *mrb, mrb_value self) +{ + void *ptr = DATA_PTR(self); + const struct mrb_data_type* type = DATA_TYPE(self); + if (ptr && type) { + type->dfree(mrb, ptr); + } + DATA_PTR(self) = NULL; +} #endif From 46f000a653b40ac8669c694bf4c12d0b3fc86aac Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Sat, 9 Jul 2016 13:50:43 -0500 Subject: [PATCH 49/59] modules/audio-libsoundio: Stubbed Sound mruby wrapper --- modules/audio-libsoundio/src/mrb_sound.cxx | 41 +++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/src/mrb_sound.cxx b/modules/audio-libsoundio/src/mrb_sound.cxx index 80f7d13..bdee9a2 100644 --- a/modules/audio-libsoundio/src/mrb_sound.cxx +++ b/modules/audio-libsoundio/src/mrb_sound.cxx @@ -6,8 +6,47 @@ #include "moon/audio/libsoundio/sound.hxx" #include "moon/api.h" #include "moon/intern.h" +#include "moon/mrb/helpers.hxx" + +static void +sound_free(mrb_state* mrb, void *p) +{ + Moon::Sound *sound = static_cast(p); + if (sound) { + delete(sound); + } +} + +MOON_C_API const struct mrb_data_type sound_data_type = { "Moon::Sound", sound_free }; + +static mrb_value +sound_initialize(mrb_state* mrb, mrb_value self) +{ + char* filename; + mrb_get_args(mrb, "z", &filename); + moon_data_cleanup(mrb, self); + Moon::Sound* sound = new Moon::Sound(std::string(filename)); + mrb_data_init(self, sound, &sound_data_type); + return self; +} + +static mrb_value +sound_play(mrb_state* mrb, mrb_value self) +{ + mrb_float gain = 1.0; + mrb_float pitch = 1.0; + mrb_float pan = 0.0; + mrb_get_args(mrb, "|fff", &gain, &pitch, &pan); + // TODO + return self; +} MOON_C_API void -mmrb_sound_init(mrb_state *mrb, struct RClass *mod) +mmrb_sound_init(mrb_state* mrb, struct RClass *mod) { + struct RClass *sound_class = mrb_define_class_under(mrb, mod, "Sound", mrb->object_class); + MRB_SET_INSTANCE_TT(sound_class, MRB_TT_DATA); + + mrb_define_method(mrb, sound_class, "initialize", sound_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, sound_class, "play", sound_play, MRB_ARGS_OPT(3)); } From ed5cea072c9daa3c0075db15ee7dac19c85a6a1b Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Sat, 9 Jul 2016 13:51:08 -0500 Subject: [PATCH 50/59] modules/audio-libsoundio: Code gardening --- .../include/moon/audio/libsoundio/music.hxx | 2 +- .../include/moon/audio/libsoundio/sound.hxx | 2 +- modules/audio-libsoundio/src/mixer.cxx | 6 +- .../audio-libsoundio/src/mrb_moon_audio.cxx | 72 +++++++++---------- modules/audio-libsoundio/src/sound.cxx | 10 +-- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx index 446ec90..da1f98b 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx @@ -12,7 +12,7 @@ namespace Moon class Music : public Source { public: Music(const std::string filename); - ~Music(); + virtual ~Music(); int read(float* dst, int frames); diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx index 9a93974..7068bb5 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -12,7 +12,7 @@ namespace Moon class Sound : public Source { public: Sound(const std::string filename); - ~Sound(); + virtual ~Sound(); int read(float* dst, int frames); diff --git a/modules/audio-libsoundio/src/mixer.cxx b/modules/audio-libsoundio/src/mixer.cxx index 96dec07..683f146 100644 --- a/modules/audio-libsoundio/src/mixer.cxx +++ b/modules/audio-libsoundio/src/mixer.cxx @@ -7,7 +7,7 @@ namespace Moon { void Mixer::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { // silence the buffer first - for (size_t channel = 0; channel < layout.channel_count; ++channel) { + for (int channel = 0; channel < layout.channel_count; ++channel) { memset(areas[channel].ptr, 0, areas[channel].step * frames); } for(auto const& handle: handles) { @@ -15,8 +15,8 @@ namespace Moon { } // clipping, to avoid overdrive - for (int frame = 0; frame < frames; ++frame) { - for (size_t channel = 0; channel < layout.channel_count; ++channel) { + for (size_t frame = 0; frame < frames; ++frame) { + for (int channel = 0; channel < layout.channel_count; ++channel) { float* buffer = (float*)(areas[channel].ptr + areas[channel].step * frame); float sample = *buffer; *buffer = sample > 1.0f ? 1.0f : (sample < -1.0f ? -1.0f : sample); diff --git a/modules/audio-libsoundio/src/mrb_moon_audio.cxx b/modules/audio-libsoundio/src/mrb_moon_audio.cxx index 9dc0914..d6d377e 100644 --- a/modules/audio-libsoundio/src/mrb_moon_audio.cxx +++ b/modules/audio-libsoundio/src/mrb_moon_audio.cxx @@ -7,51 +7,51 @@ static mrb_value audio_update(mrb_state *mrb, mrb_value klass) { - Moon::Audio::Update(); - return klass; + Moon::Audio::Update(); + return klass; } MOON_C_API void mrb_mruby_moon_audio_libsoundio_gem_init(mrb_state* mrb) { - struct RClass *moon_module = mrb_define_module(mrb, "Moon"); - struct RClass *audio_module = mrb_define_module_under(mrb, moon_module, "Audio"); - struct RClass *audio_error = mrb_define_class_under(mrb, moon_module, "AudioError", E_RUNTIME_ERROR); - mrb_define_class_method(mrb, audio_module, "update", audio_update, MRB_ARGS_NONE()); - //mmrb_sound_buffer_init(mrb, moon_module); - mmrb_music_init(mrb, moon_module); - mmrb_sound_init(mrb, moon_module); + struct RClass *moon_module = mrb_define_module(mrb, "Moon"); + struct RClass *audio_module = mrb_define_module_under(mrb, moon_module, "Audio"); + struct RClass *audio_error = mrb_define_class_under(mrb, moon_module, "AudioError", E_RUNTIME_ERROR); + mrb_define_class_method(mrb, audio_module, "update", audio_update, MRB_ARGS_NONE()); + //mmrb_sound_buffer_init(mrb, moon_module); + mmrb_music_init(mrb, moon_module); + mmrb_sound_init(mrb, moon_module); - const Moon::Audio::ErrorCode err = Moon::Audio::Initialize(); - switch (err) { - case Moon::Audio::ErrorCode::MOON_AUDIO_CREATE_ERROR: - mrb_raise(mrb, audio_error, "Underlying backend could not be created"); - break; - case Moon::Audio::ErrorCode::MOON_AUDIO_CONNECTION_ERROR: - mrb_raise(mrb, audio_error, "Could not estabish connection to backend"); - break; - case Moon::Audio::ErrorCode::MOON_AUDIO_NO_DEVICE: - mrb_raise(mrb, audio_error, "No default device present"); - break; - case Moon::Audio::ErrorCode::MOON_AUDIO_DEVICE_MISSING: - mrb_raise(mrb, audio_error, "Default device is missing"); - break; - case Moon::Audio::ErrorCode::MOON_AUDIO_COULD_NOT_OPEN_STREAM: - mrb_raise(mrb, audio_error, "Output stream could not be opened, does the selected device support it?"); - break; - case Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR: - mrb_raise(mrb, audio_error, "Channel layout is invalid for the stream"); - break; - case Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_START_ERROR: - mrb_raise(mrb, audio_error, "Stream could not be started"); - break; - default: - break; - } + const Moon::Audio::ErrorCode err = Moon::Audio::Initialize(); + switch (err) { + case Moon::Audio::ErrorCode::MOON_AUDIO_CREATE_ERROR: + mrb_raise(mrb, audio_error, "Underlying backend could not be created"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_CONNECTION_ERROR: + mrb_raise(mrb, audio_error, "Could not estabish connection to backend"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_NO_DEVICE: + mrb_raise(mrb, audio_error, "No default device present"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_DEVICE_MISSING: + mrb_raise(mrb, audio_error, "Default device is missing"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_COULD_NOT_OPEN_STREAM: + mrb_raise(mrb, audio_error, "Output stream could not be opened, does the selected device support it?"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_CHANNEL_LAYOUT_ERROR: + mrb_raise(mrb, audio_error, "Channel layout is invalid for the stream"); + break; + case Moon::Audio::ErrorCode::MOON_AUDIO_STREAM_START_ERROR: + mrb_raise(mrb, audio_error, "Stream could not be started"); + break; + default: + break; + } } MOON_C_API void mrb_mruby_moon_audio_libsoundio_gem_final(mrb_state* mrb) { - Moon::Audio::Terminate(); + Moon::Audio::Terminate(); } diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx index 2cf1662..fb01bee 100644 --- a/modules/audio-libsoundio/src/sound.cxx +++ b/modules/audio-libsoundio/src/sound.cxx @@ -6,10 +6,10 @@ namespace Moon Sound::Sound(const std::string filename) { SndfileHandle file(filename, SFM_READ); - printf("Opened file '%s'\n", filename.c_str()); - printf(" Sample rate : %d\n", file.samplerate ()); + printf("Opened file '%s'\n", filename.c_str()); + printf(" Sample rate : %d\n", file.samplerate ()); printf(" Channels : %d\n", file.channels ()); - printf(" Frames : %d\n", file.frames()); + printf(" Frames : %ld\n", file.frames()); m_channels = file.channels(); m_sampleRate = file.samplerate(); @@ -30,11 +30,11 @@ namespace Moon } int Sound::channels() { - return m_channels; + return m_channels; } int Sound::sampleRate() { - return m_sampleRate; + return m_sampleRate; } // returns how many frames we actually read From 1453bc2488caf226773be9abc1c047ef3c867b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 10 Jul 2016 11:40:49 +0900 Subject: [PATCH 51/59] travis: When running gcc, use gcc 4.8. --- .travis.yml | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8de6a85..cdd8444 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,10 @@ language: cpp sudo: false addons: apt: - sources: + sources: &sources - george-edison55-precise-backports - packages: + - ubuntu-toolchain-r-test + packages: &deps - cmake - cmake-data - freeglut3-dev @@ -23,13 +24,37 @@ matrix: include: - os: linux compiler: gcc - env: MOON_MRUBY_TOOLCHAIN=gcc - + env: + - MOON_MRUBY_TOOLCHAIN=gcc + - COMPILER=g++-4.9 + before_install: + - export CC="gcc-4.9" + - export CXX="g++-4.9" + addons: + apt: + sources: + - *sources + packages: + - *deps + - gcc-4.9 + - g++-4.9 - os: linux compiler: clang env: - MOON_MRUBY_TOOLCHAIN=clang + - COMPILER=clang++-3.7 - LD_LIBRARY_PATH: "${TRAVIS_BUILD_DIR}/build/vendor/glfw/src" + before_install: + - export CC="clang-3.7" + - export CXX="clang++-3.7" + addons: + apt: + sources: + - *sources + - llvm-toolchain-precise-3.7 + packages: + - *deps + - clang-3.7 - os: osx compiler: clang From e2d2b959601fd7ab82390e84ea8dead235284f79 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Sun, 10 Jul 2016 09:59:34 -0500 Subject: [PATCH 52/59] Updated libsoundio Merged in some important upstream changes --- vendor/libsoundio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libsoundio b/vendor/libsoundio index 3e1033c..7469bee 160000 --- a/vendor/libsoundio +++ b/vendor/libsoundio @@ -1 +1 @@ -Subproject commit 3e1033cd30fa9e23adbe467af2850845aa55f74a +Subproject commit 7469bee05829b62218e862eb6347f531b1869ac7 From f41df498b894166073fe01b1c69ac688b8a792d4 Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Thu, 14 Jul 2016 23:47:16 -0500 Subject: [PATCH 53/59] modules/system: Split helpers header into smaller bits There is a very good reason for this, I think... --- modules/system/include/moon/mrb/helpers.hxx | 39 ++----------------- .../system/include/moon/mrb/helpers/class.hxx | 10 +++++ .../system/include/moon/mrb/helpers/data.hxx | 18 +++++++++ .../system/include/moon/mrb/helpers/error.hxx | 8 ++++ .../include/moon/mrb/helpers/variable.hxx | 23 +++++++++++ modules/system/include/moon/mrb_err.hxx | 2 +- modules/system/mrblib/file_not_found_error.rb | 5 +++ 7 files changed, 69 insertions(+), 36 deletions(-) create mode 100644 modules/system/include/moon/mrb/helpers/class.hxx create mode 100644 modules/system/include/moon/mrb/helpers/data.hxx create mode 100644 modules/system/include/moon/mrb/helpers/error.hxx create mode 100644 modules/system/include/moon/mrb/helpers/variable.hxx create mode 100644 modules/system/mrblib/file_not_found_error.rb diff --git a/modules/system/include/moon/mrb/helpers.hxx b/modules/system/include/moon/mrb/helpers.hxx index e777b43..e09286e 100644 --- a/modules/system/include/moon/mrb/helpers.hxx +++ b/modules/system/include/moon/mrb/helpers.hxx @@ -1,40 +1,9 @@ #ifndef MOON_MRB_HELPERS #define MOON_MRB_HELPERS -#include -#include -#include -#include +#include "moon/mrb/helpers/class.hxx" +#include "moon/mrb/helpers/variable.hxx" +#include "moon/mrb/helpers/error.hxx" +#include "moon/mrb/helpers/data.hxx" -#define IVget(_name_) mrb_iv_get(mrb, self, mrb_intern_lit(mrb, _name_)) -#define IVset(_name_, _value_) mrb_iv_set(mrb, self, mrb_intern_lit(mrb, _name_), _value_) - -#define KEY_SHADER "@shader" -#define KEY_VBO "@vbo" -#define KEY_ORIGIN "@origin" - -#define MOON_GET_CLASS(__name__) mrb_class_get_under(mrb, mrb_module_get(mrb, "Moon"), __name__) -#define MOON_GET_MODULE(__name__) mrb_module_get_under(mrb, mrb_module_get(mrb, "Moon"), __name__) -; - -static inline mrb_value -moon_iv_get(mrb_state *mrb, mrb_value self, const char *name) -{ - mrb_value iv_value = mrb_iv_get(mrb, self, mrb_intern_cstr(mrb, name)); - if (mrb_nil_p(iv_value)) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "Cannot use a nil %S", mrb_str_new_cstr(mrb, name)); - } - return iv_value; -} - -static inline void -moon_data_cleanup(mrb_state *mrb, mrb_value self) -{ - void *ptr = DATA_PTR(self); - const struct mrb_data_type* type = DATA_TYPE(self); - if (ptr && type) { - type->dfree(mrb, ptr); - } - DATA_PTR(self) = NULL; -} #endif diff --git a/modules/system/include/moon/mrb/helpers/class.hxx b/modules/system/include/moon/mrb/helpers/class.hxx new file mode 100644 index 0000000..bba5384 --- /dev/null +++ b/modules/system/include/moon/mrb/helpers/class.hxx @@ -0,0 +1,10 @@ +#ifndef MOON_MRB_CLASS_HELPERS +#define MOON_MRB_CLASS_HELPERS + +#include +#include + +#define MOON_GET_CLASS(__name__) mrb_class_get_under(mrb, mrb_module_get(mrb, "Moon"), __name__) +#define MOON_GET_MODULE(__name__) mrb_module_get_under(mrb, mrb_module_get(mrb, "Moon"), __name__) + +#endif diff --git a/modules/system/include/moon/mrb/helpers/data.hxx b/modules/system/include/moon/mrb/helpers/data.hxx new file mode 100644 index 0000000..7b7e57a --- /dev/null +++ b/modules/system/include/moon/mrb/helpers/data.hxx @@ -0,0 +1,18 @@ +#ifndef MOON_MRB_DATA_HELPERS +#define MOON_MRB_DATA_HELPERS + +#include +#include + +static inline void +moon_data_cleanup(mrb_state* mrb, mrb_value self) +{ + void *ptr = DATA_PTR(self); + const struct mrb_data_type* type = DATA_TYPE(self); + if (ptr && type) { + type->dfree(mrb, ptr); + } + DATA_PTR(self) = NULL; +} + +#endif diff --git a/modules/system/include/moon/mrb/helpers/error.hxx b/modules/system/include/moon/mrb/helpers/error.hxx new file mode 100644 index 0000000..9537ca3 --- /dev/null +++ b/modules/system/include/moon/mrb/helpers/error.hxx @@ -0,0 +1,8 @@ +#ifndef MOON_MRB_ERROR_HELPERS +#define MOON_MRB_ERROR_HELPERS + +#include "moon/mrb/helpers/class.hxx" + +#define MOON_E_FILE_NOT_FOUND MOON_GET_CLASS("FileNotFoundError") + +#endif diff --git a/modules/system/include/moon/mrb/helpers/variable.hxx b/modules/system/include/moon/mrb/helpers/variable.hxx new file mode 100644 index 0000000..5c6a4ac --- /dev/null +++ b/modules/system/include/moon/mrb/helpers/variable.hxx @@ -0,0 +1,23 @@ +#ifndef MOON_MRB_VARIABLE_HELPERS +#define MOON_MRB_VARIABLE_HELPERS + +#include +#include +#include + +#define IVget(_name_) mrb_iv_get(mrb, self, mrb_intern_lit(mrb, _name_)) +#define IVset(_name_, _value_) mrb_iv_set(mrb, self, mrb_intern_lit(mrb, _name_), _value_) + +static inline mrb_value +moon_iv_get(mrb_state* mrb, mrb_value self, const char* name) +{ + mrb_value iv_value = mrb_iv_get(mrb, self, mrb_intern_cstr(mrb, name)); + if (mrb_nil_p(iv_value)) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "Cannot use a nil %S", mrb_str_new_cstr(mrb, name)); + } + return iv_value; +} + +#define KEY_VBO "@vbo" + +#endif diff --git a/modules/system/include/moon/mrb_err.hxx b/modules/system/include/moon/mrb_err.hxx index 6f4ab47..1d15cf3 100644 --- a/modules/system/include/moon/mrb_err.hxx +++ b/modules/system/include/moon/mrb_err.hxx @@ -6,6 +6,6 @@ #include #include -extern bool mmrb_check_class(mrb_state *mrb, mrb_value obj, struct RClass *klass, bool quiet); +extern bool mmrb_check_class(mrb_state *mrb, mrb_value obj, struct RClass* klass, bool quiet); #endif diff --git a/modules/system/mrblib/file_not_found_error.rb b/modules/system/mrblib/file_not_found_error.rb new file mode 100644 index 0000000..b243369 --- /dev/null +++ b/modules/system/mrblib/file_not_found_error.rb @@ -0,0 +1,5 @@ +module Moon + # Error raised when a resource cannot be found on disk + class FileNotFoundError < RuntimeError + end +end From 4053f5b8f8b739bee7f7c0e3cc23c7e7dec6904b Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Thu, 14 Jul 2016 23:50:29 -0500 Subject: [PATCH 54/59] modules/{audio-libsound,system}: Butchered audio Eh em, butchered AUDIO. Went on a refactor spree and forgot to commit piece by piece. Attempted to setup Music looping and ran into an issue where the current position of the stream could not be obtained (I didn't look that hard either...) --- .../include/moon/audio/libsoundio/handle.hxx | 2 +- .../moon/audio/libsoundio/mrb/music.hxx | 18 +++++ .../include/moon/audio/libsoundio/music.hxx | 17 ++++- .../include/moon/audio/libsoundio/sound.hxx | 6 +- modules/audio-libsoundio/src/handle.cxx | 12 ++-- modules/audio-libsoundio/src/mrb_music.cxx | 65 ++++++++++++++++--- modules/audio-libsoundio/src/mrb_sound.cxx | 9 +++ modules/audio-libsoundio/src/music.cxx | 53 +++++++++++++-- modules/audio-libsoundio/src/sound.cxx | 18 ++--- modules/system/include/moon/intern.h | 2 + 10 files changed, 165 insertions(+), 37 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx index d448d39..6f935f8 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx @@ -20,7 +20,7 @@ namespace Moon { float pitch; float gain; private: - Moon::Source* source; // TODO:mrb_sound/music sources will need to be wrapped... if a source deallocates, the handle will be broken (shared_ptr) + Moon::Source* m_source; // TODO:mrb_sound/music sources will need to be wrapped... if a source deallocates, the handle will be broken (shared_ptr) }; }; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx index 4789e26..d23f2e1 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx @@ -5,8 +5,26 @@ #include #include #include "moon/api.h" +#include "moon/audio/libsoundio/music.hxx" MOON_C_API const struct mrb_data_type music_data_type; MOON_C_API void mmrb_music_init(mrb_state *mrb, struct RClass *mod); +struct mmrb_Music +{ + Moon::Music* music; + Moon::Handle* handle; + + mmrb_Music(Moon::Music* ptr) + { + music = ptr; + handle = new Moon::Handle(music); + } + + ~mmrb_Music() + { + delete handle; + } +}; + #endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx index da1f98b..aeaa9a9 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx @@ -9,6 +9,17 @@ namespace Moon { + struct LoopSettings { + bool enabled; + unsigned int start; + unsigned int end; + + LoopSettings() : + enabled(false), + start(0), + end(0) {} + }; + class Music : public Source { public: Music(const std::string filename); @@ -16,10 +27,14 @@ namespace Moon int read(float* dst, int frames); + int length(); int channels(); int sampleRate(); + void setLoop(unsigned int loopStart, unsigned int loopEnd); + void clearLoop(); private: - SndfileHandle file; + SndfileHandle m_file; + LoopSettings m_loop; }; }; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx index 7068bb5..c79320d 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -19,12 +19,12 @@ namespace Moon int channels(); int sampleRate(); private: - float* source; // [] ? + float* m_source; // [] ? int m_channels; int m_sampleRate; - std::uint32_t totalFrames; - std::uint32_t currentFrame; + std::uint32_t m_totalFrames; + std::uint32_t m_currentFrame; }; }; diff --git a/modules/audio-libsoundio/src/handle.cxx b/modules/audio-libsoundio/src/handle.cxx index 30e5186..3d245f6 100644 --- a/modules/audio-libsoundio/src/handle.cxx +++ b/modules/audio-libsoundio/src/handle.cxx @@ -6,7 +6,7 @@ namespace Moon { Handle::Handle(Moon::Source* source) // this can take mixer as arg in the future if we have more than 1 { - this->source = source; + this->m_source = source; this->pan = 0.0f; this->pitch = 1.0f; this->gain = 1.0f; @@ -17,20 +17,20 @@ namespace Moon } - void Handle::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { + void Handle::mix(struct SoundIoChannelArea* areas, const struct SoundIoChannelLayout& layout, const float sampleRate, const unsigned int frames) { float pan = this->pan; pan = (pan + 1.0f) / 2.0f; pan = glm::clamp(pan, 0.0f, 1.0f); // resample and pitch - float sampleScale = source->sampleRate() / sampleRate * pitch; + float sampleScale = m_source->sampleRate() / sampleRate * pitch; // TODO: compare source.channels() with layout.channel_count - int channels = source->channels(); - int totalSamples = frames * channels * source->sampleRate(); + int channels = m_source->channels(); + int totalSamples = frames * channels * m_source->sampleRate(); float* chunk = new float[totalSamples]; - int actual = source->read(chunk, frames); + int actual = m_source->read(chunk, frames); //printf("Read n frames: %d\n", actual); // TODO: mixer should complain if we don't have stereo diff --git a/modules/audio-libsoundio/src/mrb_music.cxx b/modules/audio-libsoundio/src/mrb_music.cxx index 6ca0fe4..801d5dd 100644 --- a/modules/audio-libsoundio/src/mrb_music.cxx +++ b/modules/audio-libsoundio/src/mrb_music.cxx @@ -4,21 +4,48 @@ #include #include "moon/audio/libsoundio/mrb/music.hxx" #include "moon/audio/libsoundio/music.hxx" +#include "moon/audio/libsoundio/handle.hxx" #include "moon/api.h" #include "moon/intern.h" #include "moon/mrb/helpers.hxx" static void -music_free(mrb_state *mrb, void *p) +music_free(mrb_state* mrb, void* p) { - Moon::Music *music = static_cast(p); - if (music) { - delete(music); + mmrb_Music* handle = static_cast(p); + if (handle) { + Moon::Music* music = handle->music; + delete(handle); + if (music) { + delete(music); + handle->music = NULL; + } } } MOON_C_API const struct mrb_data_type music_data_type = { "Moon::Music", music_free }; +static inline mmrb_Music* +mmrb_music_container_ptr(mrb_state* mrb, mrb_value self) +{ + return static_cast(mrb_data_get_ptr(mrb, self, &music_data_type)); +} + +static inline Moon::Handle* +mmrb_music_handle_ptr(mrb_state* mrb, mrb_value self) +{ + return mmrb_music_container_ptr(mrb, self)->handle; +} + +static inline Moon::Music* +mmrb_music_ptr(mrb_state* mrb, mrb_value self) +{ + return mmrb_music_container_ptr(mrb, self)->music; +} + +/** + * @param [String] filename + */ static mrb_value music_initialize(mrb_state* mrb, mrb_value self) { @@ -27,22 +54,27 @@ music_initialize(mrb_state* mrb, mrb_value self) moon_data_cleanup(mrb, self); if (exists(filename)) { Moon::Music* music = new Moon::Music(std::string(filename)); - mrb_data_init(self, music, &music_data_type); + mmrb_Music* handle = new mmrb_Music(music); + mrb_data_init(self, handle, &music_data_type); } else { - mrb_raisef(mrb, E_SCRIPT_ERROR, + mrb_raisef(mrb, MOON_E_FILE_NOT_FOUND, "cannot load such file -- %S", mrb_str_new_cstr(mrb, filename)); } return self; } - +/** + * @param [Float] gain + * @param [Float] pitch + * @param [Float] pan + */ static mrb_value music_play(mrb_state* mrb, mrb_value self) { mrb_float gain = 1.0f; mrb_float pitch = 1.0f; - mrb_float pan = 1.0f; + mrb_float pan = 0.0f; mrb_get_args(mrb, "|fff", &gain, &pitch, &pan); // TODO return self; @@ -73,15 +105,28 @@ music_length(mrb_state* mrb, mrb_value self) return mrb_fixnum_value(0); } +/** + * @param [Integer] start_frame + * @param [Integer] end_frame + */ static mrb_value -music_loop(mrb_state* mrb, mrb_value self) +music_set_loop(mrb_state* mrb, mrb_value self) { + mrb_int start_frame = 0; + mrb_int end_frame = 0; + mrb_get_args(mrb, "ii", &start_frame, &end_frame); + if (end_frame < start_frame) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "expected end_frame to be greater than start frame"); + } + mmrb_music_ptr(mrb, self)->setLoop(start_frame, end_frame); return self; } static mrb_value music_clear_loop(mrb_state* mrb, mrb_value self) { + Moon::Music* music = mmrb_music_ptr(mrb, self); + music->clearLoop(); return self; } @@ -122,7 +167,7 @@ mmrb_music_init(mrb_state* mrb, struct RClass* mod) mrb_define_method(mrb, music_class, "seek", music_seek, MRB_ARGS_REQ(1)); mrb_define_method(mrb, music_class, "pos", music_pos, MRB_ARGS_NONE()); mrb_define_method(mrb, music_class, "length", music_length, MRB_ARGS_NONE()); - mrb_define_method(mrb, music_class, "loop", music_loop, MRB_ARGS_OPT(2)); + mrb_define_method(mrb, music_class, "set_loop", music_set_loop, MRB_ARGS_OPT(2)); mrb_define_method(mrb, music_class, "clear_loop", music_clear_loop, MRB_ARGS_NONE()); /* Query */ diff --git a/modules/audio-libsoundio/src/mrb_sound.cxx b/modules/audio-libsoundio/src/mrb_sound.cxx index bdee9a2..b26178e 100644 --- a/modules/audio-libsoundio/src/mrb_sound.cxx +++ b/modules/audio-libsoundio/src/mrb_sound.cxx @@ -19,6 +19,10 @@ sound_free(mrb_state* mrb, void *p) MOON_C_API const struct mrb_data_type sound_data_type = { "Moon::Sound", sound_free }; +/** + * @param [String] filename + * @return [self] + */ static mrb_value sound_initialize(mrb_state* mrb, mrb_value self) { @@ -30,6 +34,11 @@ sound_initialize(mrb_state* mrb, mrb_value self) return self; } +/** + * @param [Float] gain the velocity or gain of the sound (default 1.0) + * @param [Float] pitch the sound's pitch (default 1.0) + * @param [Float] pan the pan (default 0.0 (centered)) + */ static mrb_value sound_play(mrb_state* mrb, mrb_value self) { diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index c7ac070..01fd3fb 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -4,28 +4,67 @@ namespace Moon { Music::Music(const std::string filename) : - file(filename, SFM_READ) + m_file(filename, SFM_READ) { printf("Opened file '%s'\n", filename.c_str()); - printf(" Sample rate : %d\n", file.samplerate()); - printf(" Channels : %d\n", file.channels()); + printf(" Sample rate : %d\n", m_file.samplerate()); + printf(" Channels : %d\n", m_file.channels()); + m_loop.end = length(); }; - Music::~Music() { } + int Music::length() { + return m_file.frames(); + } + int Music::channels() { - return file.channels(); + return m_file.channels(); } int Music::sampleRate() { - return file.samplerate(); + return m_file.samplerate(); } // returns how many frames we actually read int Music::read(float* dst, int frames) { - return file.readf(dst, frames); + // If looping is enabled, AND the file has content + if (m_loop.enabled && length() > 0) { + // TODO: Figure out how to prevent file from being read OVER the loop.end + // If the m_file could somehow report it's current position that would be swell + int totalReadFrames = m_file.readf(dst, frames); + const int step = channels() * sizeof(float); + // While we still have frames left to fill out, keep looping + while (totalReadFrames < frames) { + // rewind to the start of the loop + m_file.seek(m_loop.start, SEEK_SET); + int diff = frames - totalReadFrames; + int readFrames = m_file.readf(dst + totalReadFrames * step, diff); + totalReadFrames += readFrames; + if (!readFrames) { + break; + } + } + return totalReadFrames; + } else { + return m_file.readf(dst, frames); + } + } + + void Music::setLoop(unsigned int loopStart, unsigned int loopEnd) + { + assert(loopStart < loopEnd); + m_loop.enabled = true; + m_loop.start = loopStart; + m_loop.end = loopEnd; + } + + void Music::clearLoop() + { + m_loop.enabled = false; + m_loop.start = 0; + m_loop.end = length(); } } diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx index fb01bee..25ca261 100644 --- a/modules/audio-libsoundio/src/sound.cxx +++ b/modules/audio-libsoundio/src/sound.cxx @@ -14,19 +14,19 @@ namespace Moon m_channels = file.channels(); m_sampleRate = file.samplerate(); - currentFrame = 0; + m_currentFrame = 0; int totalSamples = file.frames() * m_channels * m_sampleRate; - source = new float[totalSamples]; + m_source = new float[totalSamples]; - totalFrames = file.readf(source, file.frames()); - printf("total frames: %d\n", totalFrames); + m_totalFrames = file.readf(m_source, file.frames()); + printf("total frames: %d\n", m_totalFrames); // TODO: shout if totalFrames didn't match file.frames() }; Sound::~Sound() { - delete[] source; + delete[] m_source; } int Sound::channels() { @@ -40,12 +40,12 @@ namespace Moon // returns how many frames we actually read int Sound::read(float* dst, int frames) { - if(currentFrame > totalFrames) { return 0; } + if (m_currentFrame > m_totalFrames) { return 0; } // handle buffer edges (don't point past edge) - int actual = (currentFrame + frames > totalFrames) ? totalFrames - currentFrame : frames; - memcpy(dst, &source[currentFrame * m_channels], sizeof(float) * actual * m_channels); + int actual = (m_currentFrame + frames > m_totalFrames) ? m_totalFrames - m_currentFrame : frames; + memcpy(dst, &m_source[m_currentFrame * m_channels], sizeof(float) * actual * m_channels); - currentFrame += actual; + m_currentFrame += actual; return actual; } } diff --git a/modules/system/include/moon/intern.h b/modules/system/include/moon/intern.h index 57e56b5..37bccb6 100644 --- a/modules/system/include/moon/intern.h +++ b/modules/system/include/moon/intern.h @@ -1,6 +1,8 @@ #ifndef MOON_INTERN_H #define MOON_INTERN_H +#include + #include #include From 697697595794f0f153bbf3167026f6fd535f947d Mon Sep 17 00:00:00 2001 From: IceDragon200 Date: Fri, 15 Jul 2016 00:12:43 -0500 Subject: [PATCH 55/59] travis: Added missing audio packages --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index cdd8444..7675e91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,11 +10,17 @@ addons: - cmake-data - freeglut3-dev - freetype + - libasound2-dev - libdevil-dev + - libflac-dev - libgles2-mesa-dev - libglew-dev - libglu1-mesa-dev + - libogg-dev - libopenal-dev + - libpulse-dev + - libvorbis-dev + - libvorbisenc2 - libx11-dev - libxi-dev - libxmu-dev From 0c3645fdc2c9e8ff029b5d4b47599e166670b5e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 17 Jul 2016 18:16:03 +0900 Subject: [PATCH 56/59] Revert "modules/{audio-libsound,system}: Butchered audio" Well, that's what you get for forgetting to commit in between. This reverts commit 4053f5b8f8b739bee7f7c0e3cc23c7e7dec6904b. --- .../include/moon/audio/libsoundio/handle.hxx | 2 +- .../moon/audio/libsoundio/mrb/music.hxx | 18 ----- .../include/moon/audio/libsoundio/music.hxx | 17 +---- .../include/moon/audio/libsoundio/sound.hxx | 6 +- modules/audio-libsoundio/src/handle.cxx | 12 ++-- modules/audio-libsoundio/src/mrb_music.cxx | 65 +++---------------- modules/audio-libsoundio/src/mrb_sound.cxx | 9 --- modules/audio-libsoundio/src/music.cxx | 53 ++------------- modules/audio-libsoundio/src/sound.cxx | 18 ++--- modules/system/include/moon/intern.h | 2 - 10 files changed, 37 insertions(+), 165 deletions(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx index 6f935f8..d448d39 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx @@ -20,7 +20,7 @@ namespace Moon { float pitch; float gain; private: - Moon::Source* m_source; // TODO:mrb_sound/music sources will need to be wrapped... if a source deallocates, the handle will be broken (shared_ptr) + Moon::Source* source; // TODO:mrb_sound/music sources will need to be wrapped... if a source deallocates, the handle will be broken (shared_ptr) }; }; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx index d23f2e1..4789e26 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx @@ -5,26 +5,8 @@ #include #include #include "moon/api.h" -#include "moon/audio/libsoundio/music.hxx" MOON_C_API const struct mrb_data_type music_data_type; MOON_C_API void mmrb_music_init(mrb_state *mrb, struct RClass *mod); -struct mmrb_Music -{ - Moon::Music* music; - Moon::Handle* handle; - - mmrb_Music(Moon::Music* ptr) - { - music = ptr; - handle = new Moon::Handle(music); - } - - ~mmrb_Music() - { - delete handle; - } -}; - #endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx index aeaa9a9..da1f98b 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx @@ -9,17 +9,6 @@ namespace Moon { - struct LoopSettings { - bool enabled; - unsigned int start; - unsigned int end; - - LoopSettings() : - enabled(false), - start(0), - end(0) {} - }; - class Music : public Source { public: Music(const std::string filename); @@ -27,14 +16,10 @@ namespace Moon int read(float* dst, int frames); - int length(); int channels(); int sampleRate(); - void setLoop(unsigned int loopStart, unsigned int loopEnd); - void clearLoop(); private: - SndfileHandle m_file; - LoopSettings m_loop; + SndfileHandle file; }; }; diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx index c79320d..7068bb5 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -19,12 +19,12 @@ namespace Moon int channels(); int sampleRate(); private: - float* m_source; // [] ? + float* source; // [] ? int m_channels; int m_sampleRate; - std::uint32_t m_totalFrames; - std::uint32_t m_currentFrame; + std::uint32_t totalFrames; + std::uint32_t currentFrame; }; }; diff --git a/modules/audio-libsoundio/src/handle.cxx b/modules/audio-libsoundio/src/handle.cxx index 3d245f6..30e5186 100644 --- a/modules/audio-libsoundio/src/handle.cxx +++ b/modules/audio-libsoundio/src/handle.cxx @@ -6,7 +6,7 @@ namespace Moon { Handle::Handle(Moon::Source* source) // this can take mixer as arg in the future if we have more than 1 { - this->m_source = source; + this->source = source; this->pan = 0.0f; this->pitch = 1.0f; this->gain = 1.0f; @@ -17,20 +17,20 @@ namespace Moon } - void Handle::mix(struct SoundIoChannelArea* areas, const struct SoundIoChannelLayout& layout, const float sampleRate, const unsigned int frames) { + void Handle::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) { float pan = this->pan; pan = (pan + 1.0f) / 2.0f; pan = glm::clamp(pan, 0.0f, 1.0f); // resample and pitch - float sampleScale = m_source->sampleRate() / sampleRate * pitch; + float sampleScale = source->sampleRate() / sampleRate * pitch; // TODO: compare source.channels() with layout.channel_count - int channels = m_source->channels(); - int totalSamples = frames * channels * m_source->sampleRate(); + int channels = source->channels(); + int totalSamples = frames * channels * source->sampleRate(); float* chunk = new float[totalSamples]; - int actual = m_source->read(chunk, frames); + int actual = source->read(chunk, frames); //printf("Read n frames: %d\n", actual); // TODO: mixer should complain if we don't have stereo diff --git a/modules/audio-libsoundio/src/mrb_music.cxx b/modules/audio-libsoundio/src/mrb_music.cxx index 801d5dd..6ca0fe4 100644 --- a/modules/audio-libsoundio/src/mrb_music.cxx +++ b/modules/audio-libsoundio/src/mrb_music.cxx @@ -4,48 +4,21 @@ #include #include "moon/audio/libsoundio/mrb/music.hxx" #include "moon/audio/libsoundio/music.hxx" -#include "moon/audio/libsoundio/handle.hxx" #include "moon/api.h" #include "moon/intern.h" #include "moon/mrb/helpers.hxx" static void -music_free(mrb_state* mrb, void* p) +music_free(mrb_state *mrb, void *p) { - mmrb_Music* handle = static_cast(p); - if (handle) { - Moon::Music* music = handle->music; - delete(handle); - if (music) { - delete(music); - handle->music = NULL; - } + Moon::Music *music = static_cast(p); + if (music) { + delete(music); } } MOON_C_API const struct mrb_data_type music_data_type = { "Moon::Music", music_free }; -static inline mmrb_Music* -mmrb_music_container_ptr(mrb_state* mrb, mrb_value self) -{ - return static_cast(mrb_data_get_ptr(mrb, self, &music_data_type)); -} - -static inline Moon::Handle* -mmrb_music_handle_ptr(mrb_state* mrb, mrb_value self) -{ - return mmrb_music_container_ptr(mrb, self)->handle; -} - -static inline Moon::Music* -mmrb_music_ptr(mrb_state* mrb, mrb_value self) -{ - return mmrb_music_container_ptr(mrb, self)->music; -} - -/** - * @param [String] filename - */ static mrb_value music_initialize(mrb_state* mrb, mrb_value self) { @@ -54,27 +27,22 @@ music_initialize(mrb_state* mrb, mrb_value self) moon_data_cleanup(mrb, self); if (exists(filename)) { Moon::Music* music = new Moon::Music(std::string(filename)); - mmrb_Music* handle = new mmrb_Music(music); - mrb_data_init(self, handle, &music_data_type); + mrb_data_init(self, music, &music_data_type); } else { - mrb_raisef(mrb, MOON_E_FILE_NOT_FOUND, + mrb_raisef(mrb, E_SCRIPT_ERROR, "cannot load such file -- %S", mrb_str_new_cstr(mrb, filename)); } return self; } -/** - * @param [Float] gain - * @param [Float] pitch - * @param [Float] pan - */ + static mrb_value music_play(mrb_state* mrb, mrb_value self) { mrb_float gain = 1.0f; mrb_float pitch = 1.0f; - mrb_float pan = 0.0f; + mrb_float pan = 1.0f; mrb_get_args(mrb, "|fff", &gain, &pitch, &pan); // TODO return self; @@ -105,28 +73,15 @@ music_length(mrb_state* mrb, mrb_value self) return mrb_fixnum_value(0); } -/** - * @param [Integer] start_frame - * @param [Integer] end_frame - */ static mrb_value -music_set_loop(mrb_state* mrb, mrb_value self) +music_loop(mrb_state* mrb, mrb_value self) { - mrb_int start_frame = 0; - mrb_int end_frame = 0; - mrb_get_args(mrb, "ii", &start_frame, &end_frame); - if (end_frame < start_frame) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "expected end_frame to be greater than start frame"); - } - mmrb_music_ptr(mrb, self)->setLoop(start_frame, end_frame); return self; } static mrb_value music_clear_loop(mrb_state* mrb, mrb_value self) { - Moon::Music* music = mmrb_music_ptr(mrb, self); - music->clearLoop(); return self; } @@ -167,7 +122,7 @@ mmrb_music_init(mrb_state* mrb, struct RClass* mod) mrb_define_method(mrb, music_class, "seek", music_seek, MRB_ARGS_REQ(1)); mrb_define_method(mrb, music_class, "pos", music_pos, MRB_ARGS_NONE()); mrb_define_method(mrb, music_class, "length", music_length, MRB_ARGS_NONE()); - mrb_define_method(mrb, music_class, "set_loop", music_set_loop, MRB_ARGS_OPT(2)); + mrb_define_method(mrb, music_class, "loop", music_loop, MRB_ARGS_OPT(2)); mrb_define_method(mrb, music_class, "clear_loop", music_clear_loop, MRB_ARGS_NONE()); /* Query */ diff --git a/modules/audio-libsoundio/src/mrb_sound.cxx b/modules/audio-libsoundio/src/mrb_sound.cxx index b26178e..bdee9a2 100644 --- a/modules/audio-libsoundio/src/mrb_sound.cxx +++ b/modules/audio-libsoundio/src/mrb_sound.cxx @@ -19,10 +19,6 @@ sound_free(mrb_state* mrb, void *p) MOON_C_API const struct mrb_data_type sound_data_type = { "Moon::Sound", sound_free }; -/** - * @param [String] filename - * @return [self] - */ static mrb_value sound_initialize(mrb_state* mrb, mrb_value self) { @@ -34,11 +30,6 @@ sound_initialize(mrb_state* mrb, mrb_value self) return self; } -/** - * @param [Float] gain the velocity or gain of the sound (default 1.0) - * @param [Float] pitch the sound's pitch (default 1.0) - * @param [Float] pan the pan (default 0.0 (centered)) - */ static mrb_value sound_play(mrb_state* mrb, mrb_value self) { diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index 01fd3fb..c7ac070 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -4,67 +4,28 @@ namespace Moon { Music::Music(const std::string filename) : - m_file(filename, SFM_READ) + file(filename, SFM_READ) { printf("Opened file '%s'\n", filename.c_str()); - printf(" Sample rate : %d\n", m_file.samplerate()); - printf(" Channels : %d\n", m_file.channels()); - m_loop.end = length(); + printf(" Sample rate : %d\n", file.samplerate()); + printf(" Channels : %d\n", file.channels()); }; - Music::~Music() { - } - int Music::length() { - return m_file.frames(); + Music::~Music() { } int Music::channels() { - return m_file.channels(); + return file.channels(); } int Music::sampleRate() { - return m_file.samplerate(); + return file.samplerate(); } // returns how many frames we actually read int Music::read(float* dst, int frames) { - // If looping is enabled, AND the file has content - if (m_loop.enabled && length() > 0) { - // TODO: Figure out how to prevent file from being read OVER the loop.end - // If the m_file could somehow report it's current position that would be swell - int totalReadFrames = m_file.readf(dst, frames); - const int step = channels() * sizeof(float); - // While we still have frames left to fill out, keep looping - while (totalReadFrames < frames) { - // rewind to the start of the loop - m_file.seek(m_loop.start, SEEK_SET); - int diff = frames - totalReadFrames; - int readFrames = m_file.readf(dst + totalReadFrames * step, diff); - totalReadFrames += readFrames; - if (!readFrames) { - break; - } - } - return totalReadFrames; - } else { - return m_file.readf(dst, frames); - } - } - - void Music::setLoop(unsigned int loopStart, unsigned int loopEnd) - { - assert(loopStart < loopEnd); - m_loop.enabled = true; - m_loop.start = loopStart; - m_loop.end = loopEnd; - } - - void Music::clearLoop() - { - m_loop.enabled = false; - m_loop.start = 0; - m_loop.end = length(); + return file.readf(dst, frames); } } diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx index 25ca261..fb01bee 100644 --- a/modules/audio-libsoundio/src/sound.cxx +++ b/modules/audio-libsoundio/src/sound.cxx @@ -14,19 +14,19 @@ namespace Moon m_channels = file.channels(); m_sampleRate = file.samplerate(); - m_currentFrame = 0; + currentFrame = 0; int totalSamples = file.frames() * m_channels * m_sampleRate; - m_source = new float[totalSamples]; + source = new float[totalSamples]; - m_totalFrames = file.readf(m_source, file.frames()); - printf("total frames: %d\n", m_totalFrames); + totalFrames = file.readf(source, file.frames()); + printf("total frames: %d\n", totalFrames); // TODO: shout if totalFrames didn't match file.frames() }; Sound::~Sound() { - delete[] m_source; + delete[] source; } int Sound::channels() { @@ -40,12 +40,12 @@ namespace Moon // returns how many frames we actually read int Sound::read(float* dst, int frames) { - if (m_currentFrame > m_totalFrames) { return 0; } + if(currentFrame > totalFrames) { return 0; } // handle buffer edges (don't point past edge) - int actual = (m_currentFrame + frames > m_totalFrames) ? m_totalFrames - m_currentFrame : frames; - memcpy(dst, &m_source[m_currentFrame * m_channels], sizeof(float) * actual * m_channels); + int actual = (currentFrame + frames > totalFrames) ? totalFrames - currentFrame : frames; + memcpy(dst, &source[currentFrame * m_channels], sizeof(float) * actual * m_channels); - m_currentFrame += actual; + currentFrame += actual; return actual; } } diff --git a/modules/system/include/moon/intern.h b/modules/system/include/moon/intern.h index 37bccb6..57e56b5 100644 --- a/modules/system/include/moon/intern.h +++ b/modules/system/include/moon/intern.h @@ -1,8 +1,6 @@ #ifndef MOON_INTERN_H #define MOON_INTERN_H -#include - #include #include From 475afe68a0ced59cceeb0b7e0e7ea11dbdae9d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 17 Jul 2016 18:27:47 +0900 Subject: [PATCH 57/59] Add seek and tell to the Source interface. --- .../include/moon/audio/libsoundio/music.hxx | 1 + .../include/moon/audio/libsoundio/sound.hxx | 1 + .../include/moon/audio/libsoundio/source.hxx | 3 ++- modules/audio-libsoundio/src/music.cxx | 5 +++++ modules/audio-libsoundio/src/sound.cxx | 6 ++++++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx index da1f98b..2cf3496 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx @@ -15,6 +15,7 @@ namespace Moon virtual ~Music(); int read(float* dst, int frames); + std::uint32_t seek(std::uint32_t pos); int channels(); int sampleRate(); diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx index 7068bb5..c5eab20 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx @@ -15,6 +15,7 @@ namespace Moon virtual ~Sound(); int read(float* dst, int frames); + std::uint32_t seek(std::uint32_t pos); int channels(); int sampleRate(); diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx index 9e362cd..4c80f13 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx @@ -8,7 +8,8 @@ namespace Moon class Source { public: virtual int read(float* dst, int frames) = 0; - // seek(pos, type); + virtual std:uint32_t seek(std::uint32_t pos); + virtual int tell() { return seek(0); }; // virtual int channels() = 0; virtual int sampleRate() = 0; diff --git a/modules/audio-libsoundio/src/music.cxx b/modules/audio-libsoundio/src/music.cxx index c7ac070..a2593f0 100644 --- a/modules/audio-libsoundio/src/music.cxx +++ b/modules/audio-libsoundio/src/music.cxx @@ -28,4 +28,9 @@ namespace Moon { return file.readf(dst, frames); } + + // seeks to a given offset (in frames) from the start of the file + std::uint32_t Music::seek(std::uint32_t pos) { + return file.seek(pos, SEEK_SET); + } } diff --git a/modules/audio-libsoundio/src/sound.cxx b/modules/audio-libsoundio/src/sound.cxx index fb01bee..28f9e7e 100644 --- a/modules/audio-libsoundio/src/sound.cxx +++ b/modules/audio-libsoundio/src/sound.cxx @@ -48,4 +48,10 @@ namespace Moon currentFrame += actual; return actual; } + + // seeks to a given offset (in frames) from the start of the file + std::uint32_t Sound::seek(std::uint32_t pos) { + currentFrame = pos; + return currentFrame; + } } From 592c876b10ecbea69d3ffd11a93679bdb825ae1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 17 Jul 2016 18:43:58 +0900 Subject: [PATCH 58/59] Add a Loop source. --- .../include/moon/audio/libsoundio/handle.hxx | 1 + .../include/moon/audio/libsoundio/loop.hxx | 29 ++++++++++++ .../include/moon/audio/libsoundio/source.hxx | 4 +- modules/audio-libsoundio/src/loop.cxx | 47 +++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 modules/audio-libsoundio/include/moon/audio/libsoundio/loop.hxx create mode 100644 modules/audio-libsoundio/src/loop.cxx diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx index d448d39..edfac08 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx @@ -7,6 +7,7 @@ #include "moon/audio/libsoundio/source.hxx" #include "moon/audio/libsoundio/music.hxx" #include "moon/audio/libsoundio/sound.hxx" +#include "moon/audio/libsoundio/loop.hxx" namespace Moon { class Handle { diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/loop.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/loop.hxx new file mode 100644 index 0000000..5df06d5 --- /dev/null +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/loop.hxx @@ -0,0 +1,29 @@ +#ifndef MOON_AUDIO_LIBSOUNDIO_LOOP_H +#define MOON_AUDIO_LIBSOUNDIO_LOOP_H + +#include "moon/intern.h" +#include +#include +#include "moon/audio/libsoundio/source.hxx" +#include "moon/audio/libsoundio/mixer.hxx" + +namespace Moon +{ + class Loop : public Source { + public: + Loop(Moon::Source* source, std::uint32_t trigger, std::uint32_t target); + virtual ~Loop(); + + int read(float* dst, int frames); + std::uint32_t seek(std::uint32_t pos); + + int channels(); + int sampleRate(); + private: + std::uint32_t trigger; + std::uint32_t target; + Moon::Source* source; // TODO:mrb_sound/music sources will need to be wrapped... if a source deallocates, the handle will be broken (shared_ptr) + }; +}; + +#endif diff --git a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx index 4c80f13..187f437 100644 --- a/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx +++ b/modules/audio-libsoundio/include/moon/audio/libsoundio/source.hxx @@ -8,8 +8,8 @@ namespace Moon class Source { public: virtual int read(float* dst, int frames) = 0; - virtual std:uint32_t seek(std::uint32_t pos); - virtual int tell() { return seek(0); }; + virtual std::uint32_t seek(std::uint32_t pos) = 0; + virtual std::uint32_t tell() { return seek(0); }; // virtual int channels() = 0; virtual int sampleRate() = 0; diff --git a/modules/audio-libsoundio/src/loop.cxx b/modules/audio-libsoundio/src/loop.cxx new file mode 100644 index 0000000..f3897ed --- /dev/null +++ b/modules/audio-libsoundio/src/loop.cxx @@ -0,0 +1,47 @@ +#include "moon/intern.h" +#include "moon/audio/libsoundio/music.hxx" + +namespace Moon +{ + Loop::Loop(Moon::Source* source, std::uint32_t trigger, std::uint32_t target) { + this->source = source; + this->trigger = trigger; + this->target = target; + + // TODO: bounds checking (trigger/target being further than file length) + }; + + Loop::~Loop() { + } + + int Loop::channels() { + return source->channels(); + } + + int Loop::sampleRate() { + return source->sampleRate(); + } + + // returns how many frames we actually read + int Loop::read(float* dst, int frames) + { + std::uint32_t current = source->tell(); + std::uint32_t diff = trigger - current; + + // frames fit without seeking + if (frames <= diff) { + return source->read(dst, frames); + } else { // we need to read then seek + source->read(dst, diff); + source->seek(target); + dst += diff * source->channels(); + source->read(dst, frames); + } + return frames; + } + + // seeks to a given offset (in frames) from the start of the file + std::uint32_t Loop::seek(std::uint32_t pos) { + return source->seek(pos); + } +} From 30c50390dfe8084af17f1318491df304b5001f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 17 Jul 2016 19:44:56 +0900 Subject: [PATCH 59/59] Use a newer xcode7.3 and osx 10.11 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7675e91..b563101 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,6 +63,7 @@ matrix: - clang-3.7 - os: osx + osx_image: xcode7.3 compiler: clang env: - MOON_MRUBY_TOOLCHAIN=clang