Skip to content

Commit d3cbbce

Browse files
committed
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...)
1 parent eafea43 commit d3cbbce

File tree

10 files changed

+165
-37
lines changed

10 files changed

+165
-37
lines changed

modules/audio-libsoundio/include/moon/audio/libsoundio/handle.hxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace Moon {
2020
float pitch;
2121
float gain;
2222
private:
23-
Moon::Source* source; // TODO:mrb_sound/music sources will need to be wrapped... if a source deallocates, the handle will be broken (shared_ptr)
23+
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)
2424
};
2525
};
2626

modules/audio-libsoundio/include/moon/audio/libsoundio/mrb/music.hxx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,26 @@
55
#include <mruby/class.h>
66
#include <mruby/data.h>
77
#include "moon/api.h"
8+
#include "moon/audio/libsoundio/music.hxx"
89

910
MOON_C_API const struct mrb_data_type music_data_type;
1011
MOON_C_API void mmrb_music_init(mrb_state *mrb, struct RClass *mod);
1112

13+
struct mmrb_Music
14+
{
15+
Moon::Music* music;
16+
Moon::Handle* handle;
17+
18+
mmrb_Music(Moon::Music* ptr)
19+
{
20+
music = ptr;
21+
handle = new Moon::Handle(music);
22+
}
23+
24+
~mmrb_Music()
25+
{
26+
delete handle;
27+
}
28+
};
29+
1230
#endif

modules/audio-libsoundio/include/moon/audio/libsoundio/music.hxx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,32 @@
99

1010
namespace Moon
1111
{
12+
struct LoopSettings {
13+
bool enabled;
14+
unsigned int start;
15+
unsigned int end;
16+
17+
LoopSettings() :
18+
enabled(false),
19+
start(0),
20+
end(0) {}
21+
};
22+
1223
class Music : public Source {
1324
public:
1425
Music(const std::string filename);
1526
virtual ~Music();
1627

1728
int read(float* dst, int frames);
1829

30+
int length();
1931
int channels();
2032
int sampleRate();
33+
void setLoop(unsigned int loopStart, unsigned int loopEnd);
34+
void clearLoop();
2135
private:
22-
SndfileHandle file;
36+
SndfileHandle m_file;
37+
LoopSettings m_loop;
2338
};
2439
};
2540

modules/audio-libsoundio/include/moon/audio/libsoundio/sound.hxx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ namespace Moon
1919
int channels();
2020
int sampleRate();
2121
private:
22-
float* source; // [] ?
22+
float* m_source; // [] ?
2323
int m_channels;
2424
int m_sampleRate;
2525

26-
std::uint32_t totalFrames;
27-
std::uint32_t currentFrame;
26+
std::uint32_t m_totalFrames;
27+
std::uint32_t m_currentFrame;
2828
};
2929
};
3030

modules/audio-libsoundio/src/handle.cxx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Moon
66
{
77
Handle::Handle(Moon::Source* source) // this can take mixer as arg in the future if we have more than 1
88
{
9-
this->source = source;
9+
this->m_source = source;
1010
this->pan = 0.0f;
1111
this->pitch = 1.0f;
1212
this->gain = 1.0f;
@@ -17,20 +17,20 @@ namespace Moon
1717
}
1818

1919

20-
void Handle::mix(struct SoundIoChannelArea *areas, const struct SoundIoChannelLayout &layout, const float sampleRate, unsigned int frames) {
20+
void Handle::mix(struct SoundIoChannelArea* areas, const struct SoundIoChannelLayout& layout, const float sampleRate, const unsigned int frames) {
2121
float pan = this->pan;
2222
pan = (pan + 1.0f) / 2.0f;
2323
pan = glm::clamp(pan, 0.0f, 1.0f);
2424

2525
// resample and pitch
26-
float sampleScale = source->sampleRate() / sampleRate * pitch;
26+
float sampleScale = m_source->sampleRate() / sampleRate * pitch;
2727

2828
// TODO: compare source.channels() with layout.channel_count
29-
int channels = source->channels();
30-
int totalSamples = frames * channels * source->sampleRate();
29+
int channels = m_source->channels();
30+
int totalSamples = frames * channels * m_source->sampleRate();
3131
float* chunk = new float[totalSamples];
3232

33-
int actual = source->read(chunk, frames);
33+
int actual = m_source->read(chunk, frames);
3434
//printf("Read n frames: %d\n", actual);
3535

3636
// TODO: mixer should complain if we don't have stereo

modules/audio-libsoundio/src/mrb_music.cxx

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,48 @@
44
#include <mruby/numeric.h>
55
#include "moon/audio/libsoundio/mrb/music.hxx"
66
#include "moon/audio/libsoundio/music.hxx"
7+
#include "moon/audio/libsoundio/handle.hxx"
78
#include "moon/api.h"
89
#include "moon/intern.h"
910
#include "moon/mrb/helpers.hxx"
1011

1112
static void
12-
music_free(mrb_state *mrb, void *p)
13+
music_free(mrb_state* mrb, void* p)
1314
{
14-
Moon::Music *music = static_cast<Moon::Music*>(p);
15-
if (music) {
16-
delete(music);
15+
mmrb_Music* handle = static_cast<mmrb_Music*>(p);
16+
if (handle) {
17+
Moon::Music* music = handle->music;
18+
delete(handle);
19+
if (music) {
20+
delete(music);
21+
handle->music = NULL;
22+
}
1723
}
1824
}
1925

2026
MOON_C_API const struct mrb_data_type music_data_type = { "Moon::Music", music_free };
2127

28+
static inline mmrb_Music*
29+
mmrb_music_container_ptr(mrb_state* mrb, mrb_value self)
30+
{
31+
return static_cast<mmrb_Music*>(mrb_data_get_ptr(mrb, self, &music_data_type));
32+
}
33+
34+
static inline Moon::Handle*
35+
mmrb_music_handle_ptr(mrb_state* mrb, mrb_value self)
36+
{
37+
return mmrb_music_container_ptr(mrb, self)->handle;
38+
}
39+
40+
static inline Moon::Music*
41+
mmrb_music_ptr(mrb_state* mrb, mrb_value self)
42+
{
43+
return mmrb_music_container_ptr(mrb, self)->music;
44+
}
45+
46+
/**
47+
* @param [String] filename
48+
*/
2249
static mrb_value
2350
music_initialize(mrb_state* mrb, mrb_value self)
2451
{
@@ -27,22 +54,27 @@ music_initialize(mrb_state* mrb, mrb_value self)
2754
moon_data_cleanup(mrb, self);
2855
if (exists(filename)) {
2956
Moon::Music* music = new Moon::Music(std::string(filename));
30-
mrb_data_init(self, music, &music_data_type);
57+
mmrb_Music* handle = new mmrb_Music(music);
58+
mrb_data_init(self, handle, &music_data_type);
3159
} else {
32-
mrb_raisef(mrb, E_SCRIPT_ERROR,
60+
mrb_raisef(mrb, MOON_E_FILE_NOT_FOUND,
3361
"cannot load such file -- %S",
3462
mrb_str_new_cstr(mrb, filename));
3563
}
3664
return self;
3765
}
3866

39-
67+
/**
68+
* @param [Float] gain
69+
* @param [Float] pitch
70+
* @param [Float] pan
71+
*/
4072
static mrb_value
4173
music_play(mrb_state* mrb, mrb_value self)
4274
{
4375
mrb_float gain = 1.0f;
4476
mrb_float pitch = 1.0f;
45-
mrb_float pan = 1.0f;
77+
mrb_float pan = 0.0f;
4678
mrb_get_args(mrb, "|fff", &gain, &pitch, &pan);
4779
// TODO
4880
return self;
@@ -73,15 +105,28 @@ music_length(mrb_state* mrb, mrb_value self)
73105
return mrb_fixnum_value(0);
74106
}
75107

108+
/**
109+
* @param [Integer] start_frame
110+
* @param [Integer] end_frame
111+
*/
76112
static mrb_value
77-
music_loop(mrb_state* mrb, mrb_value self)
113+
music_set_loop(mrb_state* mrb, mrb_value self)
78114
{
115+
mrb_int start_frame = 0;
116+
mrb_int end_frame = 0;
117+
mrb_get_args(mrb, "ii", &start_frame, &end_frame);
118+
if (end_frame < start_frame) {
119+
mrb_raisef(mrb, E_ARGUMENT_ERROR, "expected end_frame to be greater than start frame");
120+
}
121+
mmrb_music_ptr(mrb, self)->setLoop(start_frame, end_frame);
79122
return self;
80123
}
81124

82125
static mrb_value
83126
music_clear_loop(mrb_state* mrb, mrb_value self)
84127
{
128+
Moon::Music* music = mmrb_music_ptr(mrb, self);
129+
music->clearLoop();
85130
return self;
86131
}
87132

@@ -122,7 +167,7 @@ mmrb_music_init(mrb_state* mrb, struct RClass* mod)
122167
mrb_define_method(mrb, music_class, "seek", music_seek, MRB_ARGS_REQ(1));
123168
mrb_define_method(mrb, music_class, "pos", music_pos, MRB_ARGS_NONE());
124169
mrb_define_method(mrb, music_class, "length", music_length, MRB_ARGS_NONE());
125-
mrb_define_method(mrb, music_class, "loop", music_loop, MRB_ARGS_OPT(2));
170+
mrb_define_method(mrb, music_class, "set_loop", music_set_loop, MRB_ARGS_OPT(2));
126171
mrb_define_method(mrb, music_class, "clear_loop", music_clear_loop, MRB_ARGS_NONE());
127172

128173
/* Query */

modules/audio-libsoundio/src/mrb_sound.cxx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ sound_free(mrb_state* mrb, void *p)
1919

2020
MOON_C_API const struct mrb_data_type sound_data_type = { "Moon::Sound", sound_free };
2121

22+
/**
23+
* @param [String] filename
24+
* @return [self]
25+
*/
2226
static mrb_value
2327
sound_initialize(mrb_state* mrb, mrb_value self)
2428
{
@@ -30,6 +34,11 @@ sound_initialize(mrb_state* mrb, mrb_value self)
3034
return self;
3135
}
3236

37+
/**
38+
* @param [Float] gain the velocity or gain of the sound (default 1.0)
39+
* @param [Float] pitch the sound's pitch (default 1.0)
40+
* @param [Float] pan the pan (default 0.0 (centered))
41+
*/
3342
static mrb_value
3443
sound_play(mrb_state* mrb, mrb_value self)
3544
{

modules/audio-libsoundio/src/music.cxx

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,67 @@
44
namespace Moon
55
{
66
Music::Music(const std::string filename) :
7-
file(filename, SFM_READ)
7+
m_file(filename, SFM_READ)
88
{
99
printf("Opened file '%s'\n", filename.c_str());
10-
printf(" Sample rate : %d\n", file.samplerate());
11-
printf(" Channels : %d\n", file.channels());
10+
printf(" Sample rate : %d\n", m_file.samplerate());
11+
printf(" Channels : %d\n", m_file.channels());
12+
m_loop.end = length();
1213
};
1314

14-
1515
Music::~Music() {
1616
}
1717

18+
int Music::length() {
19+
return m_file.frames();
20+
}
21+
1822
int Music::channels() {
19-
return file.channels();
23+
return m_file.channels();
2024
}
2125

2226
int Music::sampleRate() {
23-
return file.samplerate();
27+
return m_file.samplerate();
2428
}
2529

2630
// returns how many frames we actually read
2731
int Music::read(float* dst, int frames)
2832
{
29-
return file.readf(dst, frames);
33+
// If looping is enabled, AND the file has content
34+
if (m_loop.enabled && length() > 0) {
35+
// TODO: Figure out how to prevent file from being read OVER the loop.end
36+
// If the m_file could somehow report it's current position that would be swell
37+
int totalReadFrames = m_file.readf(dst, frames);
38+
const int step = channels() * sizeof(float);
39+
// While we still have frames left to fill out, keep looping
40+
while (totalReadFrames < frames) {
41+
// rewind to the start of the loop
42+
m_file.seek(m_loop.start, SEEK_SET);
43+
int diff = frames - totalReadFrames;
44+
int readFrames = m_file.readf(dst + totalReadFrames * step, diff);
45+
totalReadFrames += readFrames;
46+
if (!readFrames) {
47+
break;
48+
}
49+
}
50+
return totalReadFrames;
51+
} else {
52+
return m_file.readf(dst, frames);
53+
}
54+
}
55+
56+
void Music::setLoop(unsigned int loopStart, unsigned int loopEnd)
57+
{
58+
assert(loopStart < loopEnd);
59+
m_loop.enabled = true;
60+
m_loop.start = loopStart;
61+
m_loop.end = loopEnd;
62+
}
63+
64+
void Music::clearLoop()
65+
{
66+
m_loop.enabled = false;
67+
m_loop.start = 0;
68+
m_loop.end = length();
3069
}
3170
}

modules/audio-libsoundio/src/sound.cxx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@ namespace Moon
1414
m_channels = file.channels();
1515
m_sampleRate = file.samplerate();
1616

17-
currentFrame = 0;
17+
m_currentFrame = 0;
1818

1919
int totalSamples = file.frames() * m_channels * m_sampleRate;
20-
source = new float[totalSamples];
20+
m_source = new float[totalSamples];
2121

22-
totalFrames = file.readf(source, file.frames());
23-
printf("total frames: %d\n", totalFrames);
22+
m_totalFrames = file.readf(m_source, file.frames());
23+
printf("total frames: %d\n", m_totalFrames);
2424
// TODO: shout if totalFrames didn't match file.frames()
2525
};
2626

2727

2828
Sound::~Sound() {
29-
delete[] source;
29+
delete[] m_source;
3030
}
3131

3232
int Sound::channels() {
@@ -40,12 +40,12 @@ namespace Moon
4040
// returns how many frames we actually read
4141
int Sound::read(float* dst, int frames)
4242
{
43-
if(currentFrame > totalFrames) { return 0; }
43+
if (m_currentFrame > m_totalFrames) { return 0; }
4444
// handle buffer edges (don't point past edge)
45-
int actual = (currentFrame + frames > totalFrames) ? totalFrames - currentFrame : frames;
46-
memcpy(dst, &source[currentFrame * m_channels], sizeof(float) * actual * m_channels);
45+
int actual = (m_currentFrame + frames > m_totalFrames) ? m_totalFrames - m_currentFrame : frames;
46+
memcpy(dst, &m_source[m_currentFrame * m_channels], sizeof(float) * actual * m_channels);
4747

48-
currentFrame += actual;
48+
m_currentFrame += actual;
4949
return actual;
5050
}
5151
}

modules/system/include/moon/intern.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef MOON_INTERN_H
22
#define MOON_INTERN_H
33

4+
#include <assert.h>
5+
46
#include <string>
57
#include <cstring>
68

0 commit comments

Comments
 (0)