@@ -21,18 +21,18 @@ typedef struct {
21
21
typedef struct {
22
22
bool loop ;
23
23
float volume ;
24
- float pitch ;
24
+ float speed ;
25
25
bool paused ;
26
26
float time ;
27
27
} d_play_opts ;
28
28
29
29
// sound playback control handle
30
30
typedef struct {
31
31
d_sound * src ;
32
- int pos ;
32
+ float pos ;
33
+ float speed ;
33
34
bool loop ;
34
35
float volume ;
35
- float pitch ;
36
36
bool paused ;
37
37
bool done ;
38
38
} d_playback ;
@@ -61,6 +61,9 @@ d_sound d_sound_parse(uint8_t* bytes, size_t size);
61
61
#ifdef D_FS_H
62
62
d_sound d_sound_load (char * path );
63
63
#endif
64
+ d_sound d_sound_clone (d_sound * snd );
65
+ d_sound d_sound_stereo_to_mono (d_sound * snd );
66
+ d_sound d_sound_resample (d_sound * src , int input_rate , int output_rate );
64
67
float d_sound_sample (d_sound * snd , float time );
65
68
float d_sound_len (d_sound * snd );
66
69
void d_sound_free (d_sound * sound );
@@ -200,8 +203,15 @@ static float d_audio_next(void) {
200
203
}
201
204
}
202
205
203
- frame += (float )p -> src -> frames [p -> pos ] / SHRT_MAX * p -> volume ;
204
- p -> pos ++ ;
206
+ int idx = (int )p -> pos ;
207
+ float frac = p -> pos - idx ;
208
+ float f = p -> src -> frames [idx ];
209
+ float val = f ;
210
+ if (idx + 1 < p -> src -> num_frames ) {
211
+ val = ((1.0 - frac ) * f + frac * p -> src -> frames [idx + 1 ]);
212
+ }
213
+ frame += val / SHRT_MAX * p -> volume ;
214
+ p -> pos += p -> speed ;
205
215
206
216
}
207
217
@@ -409,48 +419,44 @@ d_sound d_sound_empty(void) {
409
419
};
410
420
}
411
421
412
- static short * stereo_to_mono (
413
- const short * input ,
414
- int input_len ,
415
- int * output_len
416
- ) {
417
- * output_len = input_len / 2 ;
418
- short * output = malloc (* output_len * sizeof (short ));
419
- for (int i = 0 ; i < input_len ; i += 2 ) {
420
- output [i / 2 ] = (input [i ] + input [i + 1 ]) / 2 ;
422
+ d_sound d_sound_clone (d_sound * snd ) {
423
+ return d_sound_new (snd -> frames , snd -> num_frames );
424
+ }
425
+
426
+ d_sound d_sound_stereo_to_mono (d_sound * snd ) {
427
+ d_sound snd2 = {0 };
428
+ snd2 .num_frames = snd -> num_frames / 2 ;
429
+ snd2 .frames = malloc (snd2 .num_frames * sizeof (short ));
430
+ for (int i = 0 ; i < snd -> num_frames ; i += 2 ) {
431
+ snd2 .frames [i / 2 ] = (snd -> frames [i ] + snd -> frames [i + 1 ]) / 2 ;
421
432
}
422
- return output ;
423
- }
424
-
425
- static short * resample (
426
- const short * input ,
427
- int input_len ,
428
- int input_rate ,
429
- int output_rate ,
430
- int * output_len
431
- ) {
432
- double ratio = (double ) input_rate / output_rate ;
433
- * output_len = input_len / ratio ;
434
- short * output = malloc (* output_len * sizeof (short ));
435
- for (int i = 0 ; i < * output_len ; i ++ ) {
433
+ return snd2 ;
434
+ }
435
+
436
+ d_sound d_sound_resample (d_sound * src , int input_rate , int output_rate ) {
437
+ float ratio = (float ) input_rate / output_rate ;
438
+ d_sound snd2 = {0 };
439
+ snd2 .num_frames = src -> num_frames / ratio ;
440
+ snd2 .frames = malloc (snd2 .num_frames * sizeof (short ));
441
+ for (int i = 0 ; i < snd2 .num_frames ; i ++ ) {
436
442
// find the corresponding position in the input buffer
437
- double src_pos = i * ratio ;
443
+ float src_pos = i * ratio ;
438
444
int index = (int )src_pos ;
439
- double frac = src_pos - index ;
445
+ float frac = src_pos - index ;
440
446
// linear interpolation with boundary check
441
447
int interp_val ;
442
- if (index + 1 < input_len ) {
448
+ if (index + 1 < src -> num_frames ) {
443
449
// interpolate between two neighboring samples
444
- interp_val = (int )((1.0 - frac ) * input [index ] + frac * input [index + 1 ]);
450
+ interp_val = (int )((1.0 - frac ) * src -> frames [index ] + frac * src -> frames [index + 1 ]);
445
451
} else {
446
452
// use the last sample if we're at the end of the input
447
- interp_val = input [index ];
453
+ interp_val = src -> frames [index ];
448
454
}
449
455
if (interp_val > SHRT_MAX ) interp_val = SHRT_MAX ;
450
456
if (interp_val < SHRT_MIN ) interp_val = SHRT_MIN ;
451
- output [i ] = (short )interp_val ;
457
+ snd2 . frames [i ] = (short )interp_val ;
452
458
}
453
- return output ;
459
+ return snd2 ;
454
460
}
455
461
456
462
static uint8_t OGG_SIG [] = { 0x4f , 0x67 , 0x67 , 0x53 };
@@ -459,9 +465,8 @@ static uint8_t WAV_SIG[] = { 0x52, 0x49, 0x46, 0x46 };
459
465
d_sound d_sound_parse (uint8_t * bytes , size_t size ) {
460
466
if (memcmp (bytes , OGG_SIG , sizeof (OGG_SIG )) == 0 ) {
461
467
#ifdef STB_VORBIS_IMPLEMENTATION
462
- d_sound snd = d_sound_empty ();
463
468
int num_channels , sample_rate ;
464
- short * frames ;
469
+ short * frames ;
465
470
int num_frames = stb_vorbis_decode_memory (
466
471
bytes ,
467
472
size ,
@@ -473,30 +478,21 @@ d_sound d_sound_parse(uint8_t* bytes, size_t size) {
473
478
fprintf (stderr , "failed to decode audio\n" );
474
479
return d_sound_empty ();
475
480
}
481
+ d_sound snd = {
482
+ .num_frames = num_frames ,
483
+ .frames = frames ,
484
+ };
476
485
if (num_channels == 2 && D_NUM_CHANNELS == 1 ) {
477
- short * new_frames = stereo_to_mono (
478
- frames ,
479
- num_frames ,
480
- & num_frames
481
- );
482
- free (frames );
483
- frames = new_frames ;
486
+ d_sound snd2 = d_sound_stereo_to_mono (& snd );
487
+ d_sound_free (& snd );
488
+ snd = snd2 ;
484
489
}
485
490
if (sample_rate != D_SAMPLE_RATE ) {
486
- short * new_frames = resample (
487
- frames ,
488
- num_frames ,
489
- sample_rate ,
490
- D_SAMPLE_RATE ,
491
- & num_frames
492
- );
493
- free (frames );
494
- frames = new_frames ;
491
+ d_sound snd2 = d_sound_resample (& snd , sample_rate , D_SAMPLE_RATE );
492
+ d_sound_free (& snd );
493
+ snd = snd2 ;
495
494
}
496
- return (d_sound ) {
497
- .num_frames = num_frames ,
498
- .frames = frames ,
499
- };
495
+ return snd ;
500
496
#else
501
497
fprintf (stderr , "ogg support requires 'stb_vorbis.c' and STB_VORBIS_IMPLEMENTATION flag\n" );
502
498
return d_sound_empty ();
@@ -540,13 +536,13 @@ d_playback* d_play(d_sound* snd) {
540
536
.loop = false,
541
537
.paused = false,
542
538
.volume = 1.0 ,
543
- .pitch = 1.0 ,
539
+ .speed = 1.0 ,
544
540
});
545
541
}
546
542
547
543
d_playback * d_play_ex (d_sound * snd , d_play_opts opts ) {
548
544
if (d_audio .num_playbacks >= D_MAX_PLAYBACKS ) {
549
- // TODO
545
+ return NULL ;
550
546
}
551
547
int pos = d_clampi ((int )(opts .time * D_SAMPLE_RATE ), 0 , snd -> num_frames - 1 );
552
548
d_playback src = (d_playback ) {
@@ -555,7 +551,7 @@ d_playback* d_play_ex(d_sound* snd, d_play_opts opts) {
555
551
.loop = opts .loop ,
556
552
.paused = opts .paused ,
557
553
.volume = opts .volume ,
558
- .pitch = opts .pitch ,
554
+ .speed = opts .speed ,
559
555
.done = false,
560
556
};
561
557
d_audio .playbacks [d_audio .num_playbacks ] = src ;
0 commit comments