Mercurial > repos > blastem
comparison render_audio.c @ 2304:b3832f73444f
Save audio to a wave file when saving video to APNG
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 15 Mar 2023 18:50:24 -0700 |
parents | 46ee354f29bd |
children | 35f765c2bc87 |
comparison
equal
deleted
inserted
replaced
2303:c79896ff1a2d | 2304:b3832f73444f |
---|---|
4 #include <math.h> | 4 #include <math.h> |
5 #include "render_audio.h" | 5 #include "render_audio.h" |
6 #include "util.h" | 6 #include "util.h" |
7 #include "config.h" | 7 #include "config.h" |
8 #include "blastem.h" | 8 #include "blastem.h" |
9 #include "wave.h" | |
9 | 10 |
10 static uint8_t output_channels; | 11 static uint8_t output_channels; |
11 static uint32_t buffer_samples, sample_rate; | 12 static uint32_t buffer_samples, sample_rate; |
12 | 13 |
13 static audio_source *audio_sources[8]; | 14 static audio_source *audio_sources[8]; |
15 static uint8_t num_audio_sources; | 16 static uint8_t num_audio_sources; |
16 static uint8_t num_inactive_audio_sources; | 17 static uint8_t num_inactive_audio_sources; |
17 | 18 |
18 static float overall_gain_mult, *mix_buf; | 19 static float overall_gain_mult, *mix_buf; |
19 static int sample_size; | 20 static int sample_size; |
21 | |
22 static FILE *wav_file; | |
23 void render_end_audio(void) | |
24 { | |
25 render_lock_audio(); | |
26 if (wav_file) { | |
27 wave_finalize(wav_file); | |
28 fclose(wav_file); | |
29 wav_file = NULL; | |
30 } | |
31 render_unlock_audio(); | |
32 } | |
33 | |
34 void render_save_audio(char *path) | |
35 { | |
36 render_end_audio(); | |
37 FILE *f = fopen(path, "wb"); | |
38 if (f) { | |
39 wave_init(f, sample_rate, 16, 2); | |
40 render_lock_audio(); | |
41 wav_file = f; | |
42 render_unlock_audio(); | |
43 printf("Saving audio to %s\n", path); | |
44 } else { | |
45 warning("Failed to open %s for writing\n", path); | |
46 } | |
47 free(path); | |
48 } | |
20 | 49 |
21 typedef void (*conv_func)(float *samples, void *vstream, int sample_count); | 50 typedef void (*conv_func)(float *samples, void *vstream, int sample_count); |
22 | 51 |
23 static void convert_null(float *samples, void *vstream, int sample_count) | 52 static void convert_null(float *samples, void *vstream, int sample_count) |
24 { | 53 { |
39 } else { | 68 } else { |
40 out_sample = sample * 0x7FFF; | 69 out_sample = sample * 0x7FFF; |
41 } | 70 } |
42 *stream = out_sample; | 71 *stream = out_sample; |
43 } | 72 } |
44 } | 73 if (wav_file) { |
45 | 74 fwrite(vstream, sizeof(int16_t), sample_count, wav_file); |
75 } | |
76 } | |
77 | |
78 static int16_t *wave_buffer; | |
79 static int wave_buffer_samples; | |
46 static void clamp_f32(float *samples, void *vstream, int sample_count) | 80 static void clamp_f32(float *samples, void *vstream, int sample_count) |
47 { | 81 { |
48 for (; sample_count > 0; sample_count--, samples++) | 82 float *start = samples; |
83 for (int cur_count = sample_count; cur_count > 0; cur_count--, samples++) | |
49 { | 84 { |
50 float sample = *samples; | 85 float sample = *samples; |
51 if (sample > 1.0f) { | 86 if (sample > 1.0f) { |
52 sample = 1.0f; | 87 sample = 1.0f; |
53 } else if (sample < -1.0f) { | 88 } else if (sample < -1.0f) { |
54 sample = -1.0f; | 89 sample = -1.0f; |
55 } | 90 } |
56 *samples = sample; | 91 *samples = sample; |
92 } | |
93 if (wav_file) { | |
94 if (!wave_buffer) { | |
95 wave_buffer = calloc(sample_count, sizeof(int16_t)); | |
96 wave_buffer_samples = sample_count; | |
97 } else if (sample_count < wave_buffer_samples) { | |
98 wave_buffer = realloc(wave_buffer, sizeof(int16_t) * sample_count); | |
99 wave_buffer_samples = sample_count; | |
100 } | |
101 convert_s16(start, wave_buffer, sample_count); | |
57 } | 102 } |
58 } | 103 } |
59 | 104 |
60 static int32_t mix_f32(audio_source *audio, float *stream, int samples) | 105 static int32_t mix_f32(audio_source *audio, float *stream, int samples) |
61 { | 106 { |