102 Patches: Detours to the Rescue
C reference for DttR maintainers and modders.
Loading...
Searching...
No Matches
mss_sample.c
Go to the documentation of this file.
1#include "mss_private.h"
2
3#include <dttr_log.h>
4
5#include <SDL3/SDL.h>
6#include <SDL3_mixer/SDL_mixer.h>
7
8#include <limits.h>
9#include <stdbool.h>
10#include <stdint.h>
11#include <stdlib.h>
12#include <string.h>
13
14typedef struct {
15 uint32_t magic;
16 MIX_Audio *audio;
17 MIX_Track *track;
18 float *pcm_frames;
24 int volume;
25 int pan;
26 int loops;
27 int status;
32
33static const uint32_t SAMPLE_MAGIC = 0x4453414d;
34
36
37static void apply_rate(mss_sample *sample) {
38 if (!sample->track) {
39 return;
40 }
41
42 const int reference_rate = sample->rendered_rate > 0 ? sample->rendered_rate
43 : sample->base_rate;
44 const float ratio = dttr_mss_track_frequency_ratio(
45 sample->current_rate,
46 reference_rate
47 );
48 if (ratio == 0.0f) {
49 return;
50 }
51
52 if (!MIX_SetTrackFrequencyRatio(sample->track, ratio)) {
53 DTTR_LOG_ERROR("MIX_SetTrackFrequencyRatio failed: %s", SDL_GetError());
54 }
55}
56
57static void reset_sample_defaults(mss_sample *sample) {
61 const int default_volume = dttr_mss_core_get_preference(
63 );
64 sample->volume = default_volume > 0 ? default_volume : DTTR_MSS_DEFAULT_VOLUME;
65 sample->pan = DTTR_MSS_DEFAULT_PAN;
68 sample->rate_overridden = false;
69 sample->paused_by_rate = false;
70}
71
72static bool is_sample(const void *ptr) {
73 const mss_sample *sample = ptr;
74 return sample && sample >= samples
76 && sample->magic == SAMPLE_MAGIC && sample->allocated;
77}
78
79static int sample_slot(const mss_sample *sample) {
80 return sample ? (int)(sample - samples) : -1;
81}
82
83static mss_sample *require_sample(void *sample_ptr) {
84 if (is_sample(sample_ptr)) {
85 return sample_ptr;
86 }
87
88 return NULL;
89}
90
91static void apply_sample_gain(mss_sample *sample) {
92 if (!sample->track) {
93 return;
94 }
95
96 MIX_SetTrackGain(
97 sample->track,
99 sample->volume,
102 )
103 );
104}
105
107 if (sample->track) {
108 MIX_SetTrackAudio(sample->track, NULL);
109 }
110
111 if (sample->audio) {
112 MIX_DestroyAudio(sample->audio);
113 sample->audio = NULL;
114 }
115
116 sample->rendered_rate = 0;
117 sample->paused_by_rate = false;
118}
119
120static void clear_sample_wave(mss_sample *sample) {
122 sample->pcm_frames = NULL;
123 sample->pcm_frame_count = 0;
124 memset(&sample->wave, 0, sizeof(sample->wave));
125}
126
127static void free_sample_audio(mss_sample *sample) {
129 if (sample->track) {
130 MIX_DestroyTrack(sample->track);
131 sample->track = NULL;
132 }
133
134 clear_sample_wave(sample);
135}
136
137static void reset_sample_slot(mss_sample *sample) {
138 memset(sample, 0, sizeof(*sample));
139
140 sample->magic = SAMPLE_MAGIC;
141
142 reset_sample_defaults(sample);
143
144 sample->allocated = true;
145}
146
148 mss_sample *sample,
149 const void *file_image,
150 size_t size,
151 const mss_wave_info *wave
152) {
153 mss_wave_info decoded = *wave;
154 float *frames = NULL;
155 if (!dttr_mss_wave_decode_f32(file_image, size, &decoded, &frames)) {
156 return false;
157 }
158
159 if (decoded.frame_count > (uint64_t)SIZE_MAX) {
160 dttr_mss_wave_free(frames);
161 return false;
162 }
163
164 sample->pcm_frames = frames;
165 sample->pcm_frame_count = (size_t)decoded.frame_count;
166 sample->wave = decoded;
167 return true;
168}
169
171 mss_sample *sample,
172 const void *file_image,
173 size_t size
174) {
175 SDL_IOStream *io = SDL_IOFromConstMem(file_image, size);
176 if (!io) {
177 DTTR_LOG_ERROR("SDL_IOFromConstMem failed: %s", SDL_GetError());
178 return false;
179 }
180
181 sample->audio = MIX_LoadAudio_IO(dttr_mss_core_mixer(), io, true, true);
182 if (!sample->audio) {
183 DTTR_LOG_ERROR("MIX_LoadAudio_IO sample failed: %s", SDL_GetError());
184 return false;
185 }
186
187 sample->rendered_rate = sample->base_rate;
188 return true;
189}
190
191static void apply_sample_track(mss_sample *sample) {
192 if (!sample->track || !sample->audio) {
193 return;
194 }
195
196 MIX_SetTrackAudio(sample->track, sample->audio);
197 apply_sample_gain(sample);
198 dttr_mss_track_apply_pan(sample->track, sample->pan);
199 apply_rate(sample);
200}
201
202static void stop_sample(mss_sample *sample) {
203 if (sample->track) {
204 MIX_StopTrack(sample->track, 0);
205 }
206
208 sample->paused_by_rate = false;
209}
210
211static bool render_sample_audio(mss_sample *sample) {
212 if (!dttr_mss_core_mixer() || !sample->pcm_frames || sample->pcm_frame_count == 0
213 || sample->current_rate <= 0 || sample->wave.channels == 0) {
214 return false;
215 }
216
217 const SDL_AudioSpec mixer_spec = dttr_mss_core_mixer_spec();
218 const int out_rate = mixer_spec.freq > 0 ? mixer_spec.freq : DTTR_MSS_MIXER_RATE;
219 const int channels = (int)sample->wave.channels;
220 const size_t in_frames_size = sample->pcm_frame_count;
221
222 if (in_frames_size > INT_MAX) {
223 return false;
224 }
225
226 const int in_frames = (int)in_frames_size;
227
228 int64_t out_frames64 = ((int64_t)in_frames * out_rate + sample->current_rate - 1)
229 / sample->current_rate;
230 if (out_frames64 <= 0 || out_frames64 > INT_MAX) {
231 return false;
232 }
233
234 const int out_frames = (int)out_frames64;
235 float previous_values[8] = {0};
236
237 if (channels > (int)SDL_arraysize(previous_values)) {
238 return false;
239 }
240
241 if ((size_t)out_frames > SIZE_MAX / (size_t)channels) {
242 return false;
243 }
244
245 const size_t out_values = (size_t)out_frames * (size_t)channels;
246 if (out_values > SIZE_MAX / sizeof(float)) {
247 return false;
248 }
249
250 float *converted = calloc(out_values, sizeof(float));
251 if (!converted) {
252 return false;
253 }
254
255 const float preemphasis = dttr_mss_core_sample_preemphasis();
256
257 uint64_t source_pos = 0;
258 const uint64_t source_step = ((uint64_t)sample->current_rate << 32) / out_rate;
259
260 for (int frame = 0; frame < out_frames; frame++) {
261 size_t source_frame = (size_t)(source_pos >> 32);
262
263 if (source_frame >= in_frames_size) {
264 source_frame = in_frames_size - 1;
265 }
266
267 for (int channel = 0; channel < channels; channel++) {
268 const size_t source_index = source_frame * (size_t)channels + (size_t)channel;
269 const float value = sample->pcm_frames[source_index];
270
271 converted
272 [(size_t)frame * (size_t)channels
273 + (size_t)channel] = value
274 + preemphasis * (value - previous_values[channel]);
275 previous_values[channel] = value;
276 }
277
278 source_pos += source_step;
279 }
280
281 const SDL_AudioSpec spec = {
282 .format = SDL_AUDIO_F32,
283 .channels = channels,
284 .freq = out_rate,
285 };
286
287 MIX_Audio *audio = MIX_LoadRawAudio(
289 converted,
290 out_values * sizeof(float),
291 &spec
292 );
293 free(converted);
294 if (!audio) {
295 DTTR_LOG_ERROR("MSS sample render load failed: %s", SDL_GetError());
296 return false;
297 }
298
300
301 sample->audio = audio;
302 sample->rendered_rate = sample->current_rate;
303
304 if (!sample->track) {
305 return true;
306 }
307
308 MIX_SetTrackAudio(sample->track, sample->audio);
309 return true;
310}
311
313 for (int i = 0; i < DTTR_MSS_DEFAULT_MIXER_CHANNELS; i++) {
315 memset(&samples[i], 0, sizeof(samples[i]));
316 }
317}
318
320 for (int i = 0; i < DTTR_MSS_DEFAULT_MIXER_CHANNELS; i++) {
321 if (!samples[i].allocated) {
322 continue;
323 }
324
325 stop_sample(&samples[i]);
326 }
327}
328
330 for (int i = 0; i < DTTR_MSS_DEFAULT_MIXER_CHANNELS; i++) {
331 if (!samples[i].allocated) {
332 continue;
333 }
334
336 }
337}
338
339void *__stdcall dttr_mss_ail_allocate_sample_handle(void *driver) {
340 DTTR_LOG_TRACE("MSS AIL_allocate_sample_handle(driver=%p)", driver);
341
343 DTTR_LOG_TRACE("MSS AIL_allocate_sample_handle -> NULL (mixer unavailable)");
344 return NULL;
345 }
346
347 for (int i = 0; i < DTTR_MSS_DEFAULT_MIXER_CHANNELS; i++) {
348 if (samples[i].allocated) {
349 continue;
350 }
351
352 mss_sample *sample = &samples[i];
353 reset_sample_slot(sample);
354 DTTR_LOG_TRACE("MSS AIL_allocate_sample_handle -> sample[%d]=%p", i, sample);
355 return sample;
356 }
357
358 DTTR_LOG_TRACE("MSS AIL_allocate_sample_handle -> NULL (pool exhausted)");
359
360 return NULL;
361}
362
363void __stdcall dttr_mss_ail_release_sample_handle(void *sample_ptr) {
364 mss_sample *sample = require_sample(sample_ptr);
365 if (!sample) {
366 return;
367 }
368
370 "MSS AIL_release_sample_handle(sample[%d]=%p)",
371 sample_slot(sample),
372 sample
373 );
374
375 free_sample_audio(sample);
376 memset(sample, 0, sizeof(*sample));
377}
378
379void __stdcall dttr_mss_ail_init_sample(void *sample_ptr) {
380 mss_sample *sample = require_sample(sample_ptr);
381 if (!sample) {
382 return;
383 }
384
385 DTTR_LOG_TRACE("MSS AIL_init_sample(sample[%d]=%p)", sample_slot(sample), sample);
386
387 free_sample_audio(sample);
388 reset_sample_defaults(sample);
389}
390
392 void *sample_ptr,
393 const void *file_image,
394 int block
395) {
396 if (!is_sample(sample_ptr) || !file_image || !dttr_mss_core_ensure_mixer()) {
398 "MSS AIL_set_sample_file(sample=%p, file=%p, block=%d) -> 0 (invalid)",
399 sample_ptr,
400 file_image,
401 block
402 );
403 return 0;
404 }
405
406 mss_sample *sample = sample_ptr;
407
409 "MSS AIL_set_sample_file(sample[%d]=%p, file=%p, block=%d)",
410 sample_slot(sample),
411 sample,
412 file_image,
413 block
414 );
415
416 free_sample_audio(sample);
417
418 const size_t size = dttr_mss_wave_riff_size(file_image);
419 if (block > 0 && size > (size_t)block) {
420 DTTR_LOG_ERROR("AIL_set_sample_file received truncated WAVE data");
421 return 0;
422 }
423
424 mss_wave_info wave = {0};
425 if (!size || !dttr_mss_wave_parse(file_image, &wave)) {
426 DTTR_LOG_ERROR("AIL_set_sample_file received non-WAVE data");
427 return 0;
428 }
429
431 "MSS AIL_set_sample_file sample[%d] RIFF size=%zu format=%u channels=%u "
432 "rate=%u "
433 "bits=%u data=%zu",
434 sample_slot(sample),
435 size,
436 wave.format_tag,
437 wave.channels,
438 wave.sample_rate,
439 wave.bits_per_sample,
440 wave.data_size
441 );
442
443 sample->track = MIX_CreateTrack(dttr_mss_core_mixer());
444 if (!sample->track) {
445 DTTR_LOG_ERROR("MIX_CreateTrack sample failed: %s", SDL_GetError());
446 free_sample_audio(sample);
447 return 0;
448 }
449
450 const int requested_rate = sample->current_rate;
451 sample->base_rate = dttr_mss_wave_rate(&wave);
452 sample->current_rate = sample->rate_overridden && requested_rate > 0
453 ? requested_rate
454 : sample->base_rate;
455
456 const bool loaded = load_sample_frames(sample, file_image, size, &wave)
457 || load_sample_audio_from_memory(sample, file_image, size);
458 if (!loaded) {
459 free_sample_audio(sample);
460 return 0;
461 }
462
463 if (!sample->audio && !sample->pcm_frames) {
464 DTTR_LOG_ERROR("MSS sample load failed: %s", SDL_GetError());
465 free_sample_audio(sample);
466 return 0;
467 }
468
469 apply_sample_track(sample);
471 "MSS AIL_set_sample_file sample[%d] -> 1 track=%p audio=%p pcm_frames=%zu "
472 "base_rate=%d current_rate=%d",
473 sample_slot(sample),
474 sample->track,
475 sample->audio,
476 sample->pcm_frame_count,
477 sample->base_rate,
478 sample->current_rate
479 );
480 return 1;
481}
482
483void __stdcall dttr_mss_ail_start_sample(void *sample_ptr) {
484 mss_sample *sample = require_sample(sample_ptr);
485 if (!sample) {
486 return;
487 }
488
490 "MSS AIL_start_sample(sample[%d]=%p status=%d loops=%d volume=%d pan=%d "
491 "rate=%d "
492 "track=%p audio=%p)",
493 sample_slot(sample),
494 sample,
495 sample->status,
496 sample->loops,
497 sample->volume,
498 sample->pan,
499 sample->current_rate,
500 sample->track,
501 sample->audio
502 );
503
504 if (sample->pcm_frames && sample->track && !sample->audio
505 && !render_sample_audio(sample)) {
506 DTTR_LOG_ERROR("MSS sample render failed before start");
507 return;
508 }
509
510 if (!sample->track || !sample->audio) {
512 "MSS AIL_start_sample sample[%d] skipped missing track/audio",
513 sample_slot(sample)
514 );
515 return;
516 }
517
518 apply_sample_track(sample);
519 sample->paused_by_rate = false;
521 const int sdl_loops = dttr_mss_loops_to_sdl(sample->loops);
522 dttr_mss_track_play(sample->track, sdl_loops);
524 "MSS AIL_start_sample sample[%d] played sdl_loops=%d",
525 sample_slot(sample),
526 sdl_loops
527 );
528}
529
530void __stdcall dttr_mss_ail_stop_sample(void *sample_ptr) {
531 mss_sample *sample = require_sample(sample_ptr);
532 if (!sample) {
533 return;
534 }
535
537 "MSS AIL_stop_sample(sample[%d]=%p status=%d track=%p)",
538 sample_slot(sample),
539 sample,
540 sample->status,
541 sample->track
542 );
543 stop_sample(sample);
544}
545
546void __stdcall dttr_mss_ail_end_sample(void *sample_ptr) {
547 dttr_mss_ail_stop_sample(sample_ptr);
548}
549
550int __stdcall dttr_mss_ail_sample_status(void *sample_ptr) {
551 if (!is_sample(sample_ptr)) {
553 }
554
555 mss_sample *sample = sample_ptr;
556 sample->status = dttr_mss_track_status(sample->track, sample->status);
557 return sample->status;
558}
559
560void __stdcall dttr_mss_ail_set_sample_loop_count(void *sample_ptr, int loops) {
561 mss_sample *sample = require_sample(sample_ptr);
562 if (!sample) {
563 return;
564 }
565
566 sample->loops = loops;
567 if (sample->track) {
568 MIX_SetTrackLoops(sample->track, dttr_mss_loops_to_sdl(loops));
569 }
570}
571
572void __stdcall dttr_mss_ail_set_sample_volume(void *sample_ptr, int volume) {
573 mss_sample *sample = require_sample(sample_ptr);
574 if (!sample) {
575 return;
576 }
577
578 sample->volume = volume;
579 apply_sample_gain(sample);
580}
581
582void __stdcall dttr_mss_ail_set_sample_pan(void *sample_ptr, int pan) {
583 mss_sample *sample = require_sample(sample_ptr);
584 if (!sample) {
585 return;
586 }
587
588 sample->pan = pan;
589 dttr_mss_track_apply_pan(sample->track, pan);
590}
591
592void __stdcall dttr_mss_ail_set_sample_playback_rate(void *sample_ptr, int rate) {
593 mss_sample *sample = require_sample(sample_ptr);
594 if (!sample) {
595 return;
596 }
597
598 const int previous = sample->current_rate;
599 const bool pause_for_rate = dttr_mss_sample_rate_pauses_playback(rate);
600
601 if (pause_for_rate) {
602 if (sample->track) {
603 MIX_PauseTrack(sample->track);
604 }
605
606 sample->paused_by_rate = true;
609 "MSS AIL_set_sample_playback_rate(sample[%d]=%p, rate=%d previous=%d) "
610 "paused sample",
611 sample_slot(sample),
612 sample,
613 rate,
614 previous
615 );
616 return;
617 }
618
619 sample->current_rate = rate;
620 sample->rate_overridden = true;
621 if (sample->pcm_frames && sample->track && !MIX_TrackPlaying(sample->track)
622 && sample->rendered_rate != sample->current_rate) {
623 render_sample_audio(sample);
624 }
625
626 apply_rate(sample);
627 if (sample->paused_by_rate && sample->track) {
628 MIX_ResumeTrack(sample->track);
629 }
630
631 sample->paused_by_rate = false;
633 "MSS AIL_set_sample_playback_rate(sample[%d]=%p, rate=%d previous=%d "
634 "current=%d "
635 "base=%d resumed=%d)",
636 sample_slot(sample),
637 sample,
638 rate,
639 previous,
640 sample->current_rate,
641 sample->base_rate,
642 sample->track ? !MIX_TrackPaused(sample->track) : 0
643 );
644}
645
646int __stdcall dttr_mss_ail_sample_playback_rate(void *sample_ptr) {
647 if (!is_sample(sample_ptr)) {
649 }
650
651 mss_sample *sample = sample_ptr;
652 return sample->current_rate > 0 ? sample->current_rate : DTTR_MSS_DEFAULT_RATE;
653}
void DWORD DWORD * free
const DWORD size
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
#define DTTR_LOG_TRACE(...)
Definition dttr_log.h:27
#define DTTR_LOG_ERROR(...)
Definition dttr_log.h:31
float dttr_mss_core_sample_headroom_gain()
Definition mss_core.c:71
void dttr_mss_core_ensure_preferences()
Definition mss_core.c:41
float dttr_mss_core_master_gain()
Definition mss_core.c:184
float dttr_mss_core_sample_preemphasis()
Definition mss_core.c:75
SDL_AudioSpec dttr_mss_core_mixer_spec()
Definition mss_core.c:150
bool dttr_mss_core_ensure_mixer()
Definition mss_core.c:93
static SDL_AudioSpec mixer_spec
Definition mss_core.c:15
int dttr_mss_core_get_preference(unsigned int preference)
Definition mss_core.c:49
MIX_Mixer * dttr_mss_core_mixer()
Definition mss_core.c:146
#define DTTR_MSS_DEFAULT_RATE
Definition mss_private.h:29
#define DTTR_MSS_PREF_DIG_DEFAULT_VOLUME
Definition mss_private.h:20
float dttr_mss_track_frequency_ratio(int rate, int reference_rate)
Definition mss_track.c:54
static int dttr_mss_loops_to_sdl(int mss_loop_count)
Definition mss_private.h:88
void dttr_mss_wave_free(void *ptr)
Definition mss_wave.c:115
#define DTTR_MSS_STATUS_PLAYING
Definition mss_private.h:16
void dttr_mss_track_apply_pan(MIX_Track *track, int pan)
Definition mss_track.c:22
#define DTTR_MSS_STATUS_STOPPED
Definition mss_private.h:17
#define DTTR_MSS_DEFAULT_VOLUME
Definition mss_private.h:25
#define DTTR_MSS_MIXER_RATE
Definition mss_private.h:32
void dttr_mss_track_play(MIX_Track *track, int sdl_loops)
Definition mss_track.c:38
bool dttr_mss_wave_parse(const void *file_image, mss_wave_info *info)
Definition mss_wave.c:29
#define DTTR_MSS_STATUS_DONE
Definition mss_private.h:15
float dttr_mss_track_gain(int volume, float master_gain, float headroom)
Definition mss_track.c:9
static bool dttr_mss_sample_rate_pauses_playback(int rate)
Definition mss_private.h:69
size_t dttr_mss_wave_riff_size(const void *file_image)
Definition mss_wave.c:20
bool dttr_mss_wave_decode_f32(const void *file_image, size_t size, mss_wave_info *info, float **frames_out)
Definition mss_wave.c:77
#define DTTR_MSS_DEFAULT_MIXER_CHANNELS
Definition mss_private.h:21
#define DTTR_MSS_DEFAULT_PAN
Definition mss_private.h:24
int dttr_mss_wave_rate(const mss_wave_info *info)
Definition mss_wave.c:68
int dttr_mss_track_status(MIX_Track *track, int previous_status)
Definition mss_track.c:71
#define DTTR_MSS_DEFAULT_LOOP_COUNT
Definition mss_private.h:22
static void destroy_sample_audio_object(mss_sample *sample)
Definition mss_sample.c:106
static bool load_sample_audio_from_memory(mss_sample *sample, const void *file_image, size_t size)
Definition mss_sample.c:170
void dttr_mss_sample_stop_all()
Definition mss_sample.c:319
void dttr_mss_ail_set_sample_loop_count(void *sample_ptr, int loops)
Definition mss_sample.c:560
static void apply_sample_track(mss_sample *sample)
Definition mss_sample.c:191
void dttr_mss_ail_end_sample(void *sample_ptr)
Definition mss_sample.c:546
void dttr_mss_sample_shutdown_all()
Definition mss_sample.c:312
static bool is_sample(const void *ptr)
Definition mss_sample.c:72
void dttr_mss_ail_start_sample(void *sample_ptr)
Definition mss_sample.c:483
static void clear_sample_wave(mss_sample *sample)
Definition mss_sample.c:120
void dttr_mss_ail_init_sample(void *sample_ptr)
Definition mss_sample.c:379
static void reset_sample_slot(mss_sample *sample)
Definition mss_sample.c:137
void dttr_mss_ail_stop_sample(void *sample_ptr)
Definition mss_sample.c:530
void dttr_mss_ail_set_sample_pan(void *sample_ptr, int pan)
Definition mss_sample.c:582
int dttr_mss_ail_sample_playback_rate(void *sample_ptr)
Definition mss_sample.c:646
int dttr_mss_ail_set_sample_file(void *sample_ptr, const void *file_image, int block)
Definition mss_sample.c:391
static void free_sample_audio(mss_sample *sample)
Definition mss_sample.c:127
static int sample_slot(const mss_sample *sample)
Definition mss_sample.c:79
static void stop_sample(mss_sample *sample)
Definition mss_sample.c:202
static bool render_sample_audio(mss_sample *sample)
Definition mss_sample.c:211
static void apply_rate(mss_sample *sample)
Definition mss_sample.c:37
int dttr_mss_ail_sample_status(void *sample_ptr)
Definition mss_sample.c:550
static void reset_sample_defaults(mss_sample *sample)
Definition mss_sample.c:57
void dttr_mss_ail_set_sample_volume(void *sample_ptr, int volume)
Definition mss_sample.c:572
static void apply_sample_gain(mss_sample *sample)
Definition mss_sample.c:91
static mss_sample * require_sample(void *sample_ptr)
Definition mss_sample.c:83
static mss_sample samples[DTTR_MSS_DEFAULT_MIXER_CHANNELS]
Definition mss_sample.c:35
void dttr_mss_ail_set_sample_playback_rate(void *sample_ptr, int rate)
Definition mss_sample.c:592
void dttr_mss_sample_apply_master_gain()
Definition mss_sample.c:329
void * dttr_mss_ail_allocate_sample_handle(void *driver)
Definition mss_sample.c:339
void dttr_mss_ail_release_sample_handle(void *sample_ptr)
Definition mss_sample.c:363
static const uint32_t SAMPLE_MAGIC
Definition mss_sample.c:33
static bool load_sample_frames(mss_sample *sample, const void *file_image, size_t size, const mss_wave_info *wave)
Definition mss_sample.c:147
float * pcm_frames
Definition mss_sample.c:18
MIX_Audio * audio
Definition mss_sample.c:16
bool rate_overridden
Definition mss_sample.c:28
bool paused_by_rate
Definition mss_sample.c:29
size_t pcm_frame_count
Definition mss_sample.c:19
bool allocated
Definition mss_sample.c:30
uint32_t magic
Definition mss_sample.c:15
MIX_Track * track
Definition mss_sample.c:17
int rendered_rate
Definition mss_sample.c:23
int current_rate
Definition mss_sample.c:22
int base_rate
Definition mss_sample.c:21
mss_wave_info wave
Definition mss_sample.c:20
uint64_t frame_count
Definition mss_private.h:45
uint16_t bits_per_sample
Definition mss_private.h:42
uint16_t format_tag
Definition mss_private.h:38
uint16_t channels
Definition mss_private.h:39
uint32_t sample_rate
Definition mss_private.h:40
size_t data_size
Definition mss_private.h:44