Class: SFML::SoundBuffer
- Inherits:
-
Object
- Object
- SFML::SoundBuffer
- Defined in:
- ext/audio/sound_buffer.c,
ext/audio/sound_buffer.c
Overview
Audio samples held fully decoded in memory, ready to be played through one or more Sound instances (a single buffer may back several simultaneous Sounds). For long audio, prefer Music, which streams instead of loading everything up front.
Class Method Summary collapse
-
.from_file(path) ⇒ SoundBuffer
Loads and decodes an audio file into a buffer.
-
.from_memory(data) ⇒ SoundBuffer
Decodes audio held in a String into a buffer.
-
.from_samples(*args) ⇒ SoundBuffer
samplesis an Array of Integer samples or a packed String of int16 samples, interleaved by channel. -
.from_stream(stream) ⇒ SoundBuffer
Decodes audio read from an SFML InputStream into a buffer.
Instance Method Summary collapse
-
#channel_count ⇒ Integer
Returns the number of audio channels in the buffer.
-
#channel_map ⇒ Array<Symbol>
Returns the channel layout of the buffer.
-
#copy ⇒ SoundBuffer
Creates an independent copy of the buffer.
-
#duration ⇒ Time
Returns the buffer's total playing duration.
-
#sample_count ⇒ Integer
Returns the total number of samples stored in the buffer.
-
#sample_rate ⇒ Integer
Returns the buffer's sample rate in samples per second.
-
#samples ⇒ Array<Integer>
Returns the buffer's raw audio samples as Integers.
-
#save_to_file(path) ⇒ Boolean
Writes the buffer to an audio file.
Class Method Details
.from_file(path) ⇒ SoundBuffer
Loads and decodes an audio file into a buffer.
72 73 74 |
# File 'ext/audio/sound_buffer.c', line 72
static VALUE SoundBuffer_from_file(VALUE klass, VALUE rb_path) {
return SoundBuffer_wrap(klass, sfSoundBuffer_createFromFile(StringValueCStr(rb_path)));
}
|
.from_memory(data) ⇒ SoundBuffer
Decodes audio held in a String into a buffer.
84 85 86 87 88 89 |
# File 'ext/audio/sound_buffer.c', line 84
static VALUE SoundBuffer_from_memory(VALUE klass, VALUE rb_data) {
StringValue(rb_data);
return SoundBuffer_wrap(
klass, sfSoundBuffer_createFromMemory(RSTRING_PTR(rb_data), (size_t)RSTRING_LEN(rb_data)));
}
|
.from_samples(samples, channel_count, sample_rate) ⇒ SoundBuffer .from_samples(samples, channel_count, sample_rate, channel_map) ⇒ SoundBuffer
samples is an Array of Integer samples or a packed String of int16
samples, interleaved by channel. channel_map, if given, is an Array of
channel Symbols (see SoundChannel), one per channel; if omitted, a
conventional layout is assumed for 1 and 2 channels.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'ext/audio/sound_buffer.c', line 172
static VALUE SoundBuffer_from_samples(int argc, VALUE* argv, VALUE klass) {
VALUE rb_samples, rb_channel_count, rb_sample_rate, rb_channel_map;
int16_t* samples;
sfSoundChannel* channel_map;
unsigned int channel_count;
uint64_t sample_count;
sfSoundBuffer* buffer;
rb_scan_args(argc, argv, "31", &rb_samples, &rb_channel_count, &rb_sample_rate,
&rb_channel_map);
channel_count = (unsigned int)NUM2INT(rb_channel_count);
if (channel_count == 0) {
rb_raise(rb_eArgError, "channel count must be positive");
}
/* channel_map's malloc below (sizeof(sfSoundChannel) * channel_count) can
wrap on the 32-bit targets this gem ships if channel_count is large
enough, allocating far less than the subsequent write loop assumes.
Check before any allocation happens, so there's nothing to clean up on
the raise path. (Written with channel_count as the divisor, not
compared directly against a constant bound, so this isn't optimized
away as tautological on 64-bit hosts where it can't actually trigger
-- it still does real work on the 32-bit targets.) */
if (SIZE_MAX / channel_count < sizeof(sfSoundChannel)) {
rb_raise(rb_eArgError, "channel count too large");
}
if (RB_TYPE_P(rb_samples, T_STRING)) {
size_t bytes = (size_t)RSTRING_LEN(rb_samples);
if (bytes % sizeof(int16_t) != 0) {
rb_raise(rb_eArgError, "sample string length must be a multiple of 2 bytes");
}
sample_count = bytes / sizeof(int16_t);
samples = malloc(bytes > 0 ? bytes : 1);
if (bytes > 0) {
const int16_t* src = (const int16_t*)RSTRING_PTR(rb_samples);
size_t i;
for (i = 0; i < sample_count; i++) {
samples[i] = src[i];
}
}
} else if (RB_TYPE_P(rb_samples, T_ARRAY)) {
long i;
sample_count = (uint64_t)RARRAY_LEN(rb_samples);
samples = malloc(sizeof(int16_t) * ((size_t)sample_count + 1));
for (i = 0; i < (long)sample_count; i++) {
samples[i] = (int16_t)NUM2INT(rb_ary_entry(rb_samples, i));
}
} else {
rb_raise(rb_eArgError, "samples must be an Array of integers or a String");
return Qnil;
}
channel_map = malloc(sizeof(sfSoundChannel) * channel_count);
if (NIL_P(rb_channel_map)) {
SoundBuffer_default_channel_map(channel_count, channel_map);
} else {
ChannelMapFillContext ctx = {.channel_map = channel_map,
.rb_channel_map = rb_channel_map,
.channel_count = channel_count};
int state = 0;
if (!RB_TYPE_P(rb_channel_map, T_ARRAY) ||
(unsigned long)RARRAY_LEN(rb_channel_map) != channel_count) {
free(samples);
free(channel_map);
rb_raise(rb_eArgError, "channel map must have exactly one entry per channel");
}
rb_protect(SoundBuffer_fill_channel_map, (VALUE)&ctx, &state);
if (state) {
free(samples);
free(channel_map);
rb_jump_tag(state);
}
}
buffer = sfSoundBuffer_createFromSamples(samples, sample_count, channel_count,
(unsigned int)NUM2INT(rb_sample_rate), channel_map,
channel_count);
free(samples);
free(channel_map);
return SoundBuffer_wrap(klass, buffer);
}
|
.from_stream(stream) ⇒ SoundBuffer
Decodes audio read from an SFML InputStream into a buffer.
99 100 101 102 103 104 105 106 |
# File 'ext/audio/sound_buffer.c', line 99
static VALUE SoundBuffer_from_stream(VALUE klass, VALUE rb_stream) {
VALUE holder = Qnil;
sfInputStream* stream = input_stream_from_rb(rb_stream, &holder);
(void)holder;
return SoundBuffer_wrap(klass, sfSoundBuffer_createFromStream(stream));
}
|
Instance Method Details
#channel_count ⇒ Integer
Returns the number of audio channels in the buffer.
344 345 346 |
# File 'ext/audio/sound_buffer.c', line 344 static VALUE SoundBuffer_channel_count(VALUE self) { return UINT2NUM(sfSoundBuffer_getChannelCount(Get_SoundBuffer_Struct(self))); } |
#channel_map ⇒ Array<Symbol>
Returns the channel layout of the buffer.
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'ext/audio/sound_buffer.c', line 355
static VALUE SoundBuffer_channel_map(VALUE self) {
size_t count = 0;
sfSoundChannel* map = sfSoundBuffer_getChannelMap(Get_SoundBuffer_Struct(self), &count);
VALUE rb_array;
size_t i;
if (map == NULL) {
return rb_ary_new();
}
rb_array = rb_ary_new_capa((long)count);
for (i = 0; i < count; i++) {
rb_ary_push(rb_array, ID2SYM(rb_intern(sound_channel_name(map[i]))));
}
return rb_array;
}
|
#copy ⇒ SoundBuffer
Creates an independent copy of the buffer.
275 276 277 278 |
# File 'ext/audio/sound_buffer.c', line 275 static VALUE SoundBuffer_copy(VALUE self) { return SoundBuffer_wrap(Get_Klass_SoundBuffer(), sfSoundBuffer_copy(Get_SoundBuffer_Struct(self))); } |
#duration ⇒ Time
Returns the buffer's total playing duration.
380 381 382 |
# File 'ext/audio/sound_buffer.c', line 380 static VALUE SoundBuffer_duration(VALUE self) { return time_to_rb(sfSoundBuffer_getDuration(Get_SoundBuffer_Struct(self))); } |
#sample_count ⇒ Integer
Returns the total number of samples stored in the buffer.
324 325 326 |
# File 'ext/audio/sound_buffer.c', line 324 static VALUE SoundBuffer_sample_count(VALUE self) { return ULL2NUM(sfSoundBuffer_getSampleCount(Get_SoundBuffer_Struct(self))); } |
#sample_rate ⇒ Integer
Returns the buffer's sample rate in samples per second.
334 335 336 |
# File 'ext/audio/sound_buffer.c', line 334 static VALUE SoundBuffer_sample_rate(VALUE self) { return UINT2NUM(sfSoundBuffer_getSampleRate(Get_SoundBuffer_Struct(self))); } |
#samples ⇒ Array<Integer>
Returns the buffer's raw audio samples as Integers.
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'ext/audio/sound_buffer.c', line 299
static VALUE SoundBuffer_samples(VALUE self) {
const int16_t* samples = sfSoundBuffer_getSamples(Get_SoundBuffer_Struct(self));
uint64_t count = sfSoundBuffer_getSampleCount(Get_SoundBuffer_Struct(self));
VALUE rb_array;
uint64_t i;
if (samples == NULL) {
return rb_ary_new();
}
rb_array = rb_ary_new_capa((long)count);
for (i = 0; i < count; i++) {
rb_ary_push(rb_array, INT2NUM(samples[i]));
}
return rb_array;
}
|
#save_to_file(path) ⇒ Boolean
Writes the buffer to an audio file.
287 288 289 290 |
# File 'ext/audio/sound_buffer.c', line 287
static VALUE SoundBuffer_save_to_file(VALUE self, VALUE rb_path) {
return BOOL2RB(
sfSoundBuffer_saveToFile(Get_SoundBuffer_Struct(self), StringValueCStr(rb_path)));
}
|