Skip to content

Commit 797718a

Browse files
committed
improve pfish and audio
1 parent 8b3930c commit 797718a

File tree

10 files changed

+282
-176
lines changed

10 files changed

+282
-176
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,10 @@ endif
208208
$(BIN_PATH)/%: $(DEMO_PATH)/%.c *.h
209209
@mkdir -p $(BIN_PATH)
210210
ifeq ($(TARGET),web)
211-
$(CC) $(CFLAGS) -o $@.js $< $(LDFLAGS)
211+
$(CC) $(CFLAGS) -o $@.js $< ext/stb_vorbis.c $(LDFLAGS)
212212
sed 's/{{name}}/$*/' misc/web.html > $(BIN_PATH)/index.html
213213
else
214-
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
214+
$(CC) $(CFLAGS) -o $@ $< ext/stb_vorbis.c $(LDFLAGS)
215215
endif
216216
rsync -a --delete $(DEMO_PATH)/res $(BIN_PATH)/
217217

d_audio.h

+56-60
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@ typedef struct {
2121
typedef struct {
2222
bool loop;
2323
float volume;
24-
float pitch;
24+
float speed;
2525
bool paused;
2626
float time;
2727
} d_play_opts;
2828

2929
// sound playback control handle
3030
typedef struct {
3131
d_sound* src;
32-
int pos;
32+
float pos;
33+
float speed;
3334
bool loop;
3435
float volume;
35-
float pitch;
3636
bool paused;
3737
bool done;
3838
} d_playback;
@@ -61,6 +61,9 @@ d_sound d_sound_parse(uint8_t* bytes, size_t size);
6161
#ifdef D_FS_H
6262
d_sound d_sound_load(char* path);
6363
#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);
6467
float d_sound_sample(d_sound* snd, float time);
6568
float d_sound_len(d_sound* snd);
6669
void d_sound_free(d_sound* sound);
@@ -200,8 +203,15 @@ static float d_audio_next(void) {
200203
}
201204
}
202205

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;
205215

206216
}
207217

@@ -409,48 +419,44 @@ d_sound d_sound_empty(void) {
409419
};
410420
}
411421

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;
421432
}
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++) {
436442
// find the corresponding position in the input buffer
437-
double src_pos = i * ratio;
443+
float src_pos = i * ratio;
438444
int index = (int)src_pos;
439-
double frac = src_pos - index;
445+
float frac = src_pos - index;
440446
// linear interpolation with boundary check
441447
int interp_val;
442-
if (index + 1 < input_len) {
448+
if (index + 1 < src->num_frames) {
443449
// 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]);
445451
} else {
446452
// use the last sample if we're at the end of the input
447-
interp_val = input[index];
453+
interp_val = src->frames[index];
448454
}
449455
if (interp_val > SHRT_MAX) interp_val = SHRT_MAX;
450456
if (interp_val < SHRT_MIN) interp_val = SHRT_MIN;
451-
output[i] = (short)interp_val;
457+
snd2.frames[i] = (short)interp_val;
452458
}
453-
return output;
459+
return snd2;
454460
}
455461

456462
static uint8_t OGG_SIG[] = { 0x4f, 0x67, 0x67, 0x53 };
@@ -459,9 +465,8 @@ static uint8_t WAV_SIG[] = { 0x52, 0x49, 0x46, 0x46 };
459465
d_sound d_sound_parse(uint8_t* bytes, size_t size) {
460466
if (memcmp(bytes, OGG_SIG, sizeof(OGG_SIG)) == 0) {
461467
#ifdef STB_VORBIS_IMPLEMENTATION
462-
d_sound snd = d_sound_empty();
463468
int num_channels, sample_rate;
464-
short *frames;
469+
short* frames;
465470
int num_frames = stb_vorbis_decode_memory(
466471
bytes,
467472
size,
@@ -473,30 +478,21 @@ d_sound d_sound_parse(uint8_t* bytes, size_t size) {
473478
fprintf(stderr, "failed to decode audio\n");
474479
return d_sound_empty();
475480
}
481+
d_sound snd = {
482+
.num_frames = num_frames,
483+
.frames = frames,
484+
};
476485
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;
484489
}
485490
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;
495494
}
496-
return (d_sound) {
497-
.num_frames = num_frames,
498-
.frames = frames,
499-
};
495+
return snd;
500496
#else
501497
fprintf(stderr, "ogg support requires 'stb_vorbis.c' and STB_VORBIS_IMPLEMENTATION flag\n");
502498
return d_sound_empty();
@@ -540,13 +536,13 @@ d_playback* d_play(d_sound* snd) {
540536
.loop = false,
541537
.paused = false,
542538
.volume = 1.0,
543-
.pitch = 1.0,
539+
.speed = 1.0,
544540
});
545541
}
546542

547543
d_playback* d_play_ex(d_sound* snd, d_play_opts opts) {
548544
if (d_audio.num_playbacks >= D_MAX_PLAYBACKS) {
549-
// TODO
545+
return NULL;
550546
}
551547
int pos = d_clampi((int)(opts.time * D_SAMPLE_RATE), 0, snd->num_frames - 1);
552548
d_playback src = (d_playback) {
@@ -555,7 +551,7 @@ d_playback* d_play_ex(d_sound* snd, d_play_opts opts) {
555551
.loop = opts.loop,
556552
.paused = opts.paused,
557553
.volume = opts.volume,
558-
.pitch = opts.pitch,
554+
.speed = opts.speed,
559555
.done = false,
560556
};
561557
d_audio.playbacks[d_audio.num_playbacks] = src;

0 commit comments

Comments
 (0)