Mercurial > repos > blastem
annotate 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 |
rev | line source |
---|---|
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
1 #include <limits.h> |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
2 #include <string.h> |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
3 #include <stdlib.h> |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
4 #include <math.h> |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
5 #include "render_audio.h" |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
6 #include "util.h" |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
7 #include "config.h" |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
8 #include "blastem.h" |
2304
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
9 #include "wave.h" |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
10 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
11 static uint8_t output_channels; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
12 static uint32_t buffer_samples, sample_rate; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
13 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
14 static audio_source *audio_sources[8]; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
15 static audio_source *inactive_audio_sources[8]; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
16 static uint8_t num_audio_sources; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
17 static uint8_t num_inactive_audio_sources; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
18 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
19 static float overall_gain_mult, *mix_buf; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
20 static int sample_size; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
21 |
2304
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
22 static FILE *wav_file; |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
23 void render_end_audio(void) |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
24 { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
25 render_lock_audio(); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
26 if (wav_file) { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
27 wave_finalize(wav_file); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
28 fclose(wav_file); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
29 wav_file = NULL; |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
30 } |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
31 render_unlock_audio(); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
32 } |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
33 |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
34 void render_save_audio(char *path) |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
35 { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
36 render_end_audio(); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
37 FILE *f = fopen(path, "wb"); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
38 if (f) { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
39 wave_init(f, sample_rate, 16, 2); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
40 render_lock_audio(); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
41 wav_file = f; |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
42 render_unlock_audio(); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
43 printf("Saving audio to %s\n", path); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
44 } else { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
45 warning("Failed to open %s for writing\n", path); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
46 } |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
47 free(path); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
48 } |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
49 |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
50 typedef void (*conv_func)(float *samples, void *vstream, int sample_count); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
51 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
52 static void convert_null(float *samples, void *vstream, int sample_count) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
53 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
54 memset(vstream, 0, sample_count * sample_size); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
55 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
56 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
57 static void convert_s16(float *samples, void *vstream, int sample_count) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
58 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
59 int16_t *stream = vstream; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
60 for (int16_t *end = stream + sample_count; stream < end; stream++, samples++) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
61 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
62 float sample = *samples; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
63 int16_t out_sample; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
64 if (sample >= 1.0f) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
65 out_sample = 0x7FFF; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
66 } else if (sample <= -1.0f) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
67 out_sample = -0x8000; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
68 } else { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
69 out_sample = sample * 0x7FFF; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
70 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
71 *stream = out_sample; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
72 } |
2304
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
73 if (wav_file) { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
74 fwrite(vstream, sizeof(int16_t), sample_count, wav_file); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
75 } |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
76 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
77 |
2304
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
78 static int16_t *wave_buffer; |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
79 static int wave_buffer_samples; |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
80 static void clamp_f32(float *samples, void *vstream, int sample_count) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
81 { |
2304
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
82 float *start = samples; |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
83 for (int cur_count = sample_count; cur_count > 0; cur_count--, samples++) |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
84 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
85 float sample = *samples; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
86 if (sample > 1.0f) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
87 sample = 1.0f; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
88 } else if (sample < -1.0f) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
89 sample = -1.0f; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
90 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
91 *samples = sample; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
92 } |
2304
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
93 if (wav_file) { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
94 if (!wave_buffer) { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
95 wave_buffer = calloc(sample_count, sizeof(int16_t)); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
96 wave_buffer_samples = sample_count; |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
97 } else if (sample_count < wave_buffer_samples) { |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
98 wave_buffer = realloc(wave_buffer, sizeof(int16_t) * sample_count); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
99 wave_buffer_samples = sample_count; |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
100 } |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
101 convert_s16(start, wave_buffer, sample_count); |
b3832f73444f
Save audio to a wave file when saving video to APNG
Michael Pavone <pavone@retrodev.com>
parents:
2093
diff
changeset
|
102 } |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
103 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
104 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
105 static int32_t mix_f32(audio_source *audio, float *stream, int samples) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
106 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
107 float *end = stream + samples; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
108 int16_t *src = audio->front; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
109 uint32_t i = audio->read_start; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
110 uint32_t i_end = audio->read_end; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
111 float *cur = stream; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
112 float gain_mult = audio->gain_mult * overall_gain_mult; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
113 size_t first_add = output_channels > 1 ? 1 : 0, second_add = output_channels > 1 ? output_channels - 1 : 1; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
114 if (audio->num_channels == 1) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
115 while (cur < end && i != i_end) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
116 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
117 *cur += gain_mult * ((float)src[i]) / 0x7FFF; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
118 cur += first_add; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
119 *cur += gain_mult * ((float)src[i++]) / 0x7FFF; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
120 cur += second_add; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
121 i &= audio->mask; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
122 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
123 } else { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
124 while(cur < end && i != i_end) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
125 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
126 *cur += gain_mult * ((float)src[i++]) / 0x7FFF; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
127 cur += first_add; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
128 *cur += gain_mult * ((float)src[i++]) / 0x7FFF; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
129 cur += second_add; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
130 i &= audio->mask; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
131 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
132 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
133 if (!render_is_audio_sync()) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
134 audio->read_start = i; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
135 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
136 if (cur != end) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
137 debug_message("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
138 return (cur-end)/2; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
139 } else { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
140 return ((i_end - i) & audio->mask) / audio->num_channels; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
141 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
142 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
143 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
144 static conv_func convert; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
145 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
146 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
147 int mix_and_convert(unsigned char *byte_stream, int len, int *min_remaining_out) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
148 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
149 int samples = len / sample_size; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
150 float *mix_dest = mix_buf ? mix_buf : (float *)byte_stream; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
151 memset(mix_dest, 0, samples * sizeof(float)); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
152 int min_buffered = INT_MAX; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
153 int min_remaining_buffer = INT_MAX; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
154 for (uint8_t i = 0; i < num_audio_sources; i++) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
155 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
156 int buffered = mix_f32(audio_sources[i], mix_dest, samples); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
157 int remaining = (audio_sources[i]->mask + 1) / audio_sources[i]->num_channels - buffered; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
158 min_buffered = buffered < min_buffered ? buffered : min_buffered; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
159 min_remaining_buffer = remaining < min_remaining_buffer ? remaining : min_remaining_buffer; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
160 audio_sources[i]->front_populated = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
161 render_buffer_consumed(audio_sources[i]); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
162 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
163 convert(mix_dest, byte_stream, samples); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
164 if (min_remaining_out) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
165 *min_remaining_out = min_remaining_buffer; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
166 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
167 return min_buffered; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
168 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
169 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
170 uint8_t all_sources_ready(void) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
171 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
172 uint8_t num_populated = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
173 num_populated = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
174 for (uint8_t i = 0; i < num_audio_sources; i++) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
175 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
176 if (audio_sources[i]->front_populated) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
177 num_populated++; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
178 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
179 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
180 return num_populated == num_audio_sources; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
181 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
182 |
2093
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
183 uint8_t audio_deadlock_hack(void) |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
184 { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
185 uint32_t min_buffer_pos = 0xFFFFFFFFU; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
186 for (uint8_t i = 0; i < num_audio_sources; i++) |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
187 { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
188 if (audio_sources[i]->front_populated) { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
189 uint32_t buffer_pos = audio_sources[i]->buffer_pos; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
190 if (audio_sources[i]->num_channels == 1) { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
191 buffer_pos *= 2; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
192 } |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
193 if (buffer_pos < min_buffer_pos) { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
194 min_buffer_pos = buffer_pos; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
195 } |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
196 } |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
197 } |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
198 uint8_t do_signal = 0; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
199 for (uint8_t i = 0; i < num_audio_sources; i++) |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
200 { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
201 if (!audio_sources[i]->front_populated) { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
202 audio_sources[i]->front_populated = 1; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
203 int16_t *tmp = audio_sources[i]->front; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
204 audio_sources[i]->front = audio_sources[i]->back; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
205 audio_sources[i]->back = tmp; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
206 if (audio_sources[i]->num_channels == 2) { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
207 audio_sources[i]->buffer_pos = min_buffer_pos; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
208 } else { |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
209 audio_sources[i]->buffer_pos = min_buffer_pos / 2; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
210 } |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
211 do_signal = 1; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
212 } |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
213 } |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
214 return do_signal; |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
215 } |
46ee354f29bd
Hack fix for audio deadlock issue
Michael Pavone <pavone@retrodev.com>
parents:
2081
diff
changeset
|
216 |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
217 #define BUFFER_INC_RES 0x40000000UL |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
218 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
219 void render_audio_adjust_clock(audio_source *src, uint64_t master_clock, uint64_t sample_divider) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
220 { |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
221 src->buffer_inc = ((BUFFER_INC_RES * sample_divider * (uint64_t)sample_rate) / master_clock); |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
222 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
223 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
224 void render_audio_adjust_speed(float adjust_ratio) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
225 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
226 for (uint8_t i = 0; i < num_audio_sources; i++) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
227 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
228 audio_sources[i]->buffer_inc = ((double)audio_sources[i]->buffer_inc) + ((double)audio_sources[i]->buffer_inc) * adjust_ratio + 0.5; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
229 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
230 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
231 |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
232 audio_source *render_audio_source(const char *name, uint64_t master_clock, uint64_t sample_divider, uint8_t channels) |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
233 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
234 audio_source *ret = NULL; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
235 uint32_t alloc_size = render_is_audio_sync() ? channels * buffer_samples : nearest_pow2(render_min_buffered() * 4 * channels); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
236 render_lock_audio(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
237 if (num_audio_sources < 8) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
238 ret = calloc(1, sizeof(audio_source)); |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
239 ret->name = name; |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
240 ret->back = malloc(alloc_size * sizeof(int16_t)); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
241 ret->front = render_is_audio_sync() ? malloc(alloc_size * sizeof(int16_t)) : ret->back; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
242 ret->front_populated = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
243 ret->opaque = render_new_audio_opaque(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
244 ret->num_channels = channels; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
245 audio_sources[num_audio_sources++] = ret; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
246 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
247 render_unlock_audio(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
248 if (!ret) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
249 fatal_error("Too many audio sources!"); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
250 } else { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
251 render_audio_adjust_clock(ret, master_clock, sample_divider); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
252 double lowpass_cutoff = get_lowpass_cutoff(config); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
253 double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
254 ret->dt = 1.0 / ((double)master_clock / (double)(sample_divider)); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
255 double alpha = ret->dt / (ret->dt + rc); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
256 ret->lowpass_alpha = (int32_t)(((double)0x10000) * alpha); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
257 ret->buffer_pos = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
258 ret->buffer_fraction = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
259 ret->last_left = ret->last_right = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
260 ret->read_start = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
261 ret->read_end = render_is_audio_sync() ? buffer_samples * channels : 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
262 ret->mask = render_is_audio_sync() ? 0xFFFFFFFF : alloc_size-1; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
263 ret->gain_mult = 1.0f; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
264 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
265 render_audio_created(ret); |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
266 |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
267 return ret; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
268 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
269 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
270 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
271 static float db_to_mult(float gain) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
272 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
273 return powf(10.0f, gain/20.0f); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
274 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
275 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
276 void render_audio_source_gaindb(audio_source *src, float gain) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
277 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
278 src->gain_mult = db_to_mult(gain); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
279 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
280 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
281 void render_pause_source(audio_source *src) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
282 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
283 uint8_t found = 0, remaining_sources; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
284 render_lock_audio(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
285 for (uint8_t i = 0; i < num_audio_sources; i++) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
286 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
287 if (audio_sources[i] == src) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
288 audio_sources[i] = audio_sources[--num_audio_sources]; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
289 found = 1; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
290 remaining_sources = num_audio_sources; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
291 break; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
292 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
293 } |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
294 |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
295 render_unlock_audio(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
296 if (found) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
297 render_source_paused(src, remaining_sources); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
298 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
299 inactive_audio_sources[num_inactive_audio_sources++] = src; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
300 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
301 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
302 void render_resume_source(audio_source *src) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
303 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
304 render_lock_audio(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
305 if (num_audio_sources < 8) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
306 audio_sources[num_audio_sources++] = src; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
307 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
308 render_unlock_audio(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
309 for (uint8_t i = 0; i < num_inactive_audio_sources; i++) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
310 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
311 if (inactive_audio_sources[i] == src) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
312 inactive_audio_sources[i] = inactive_audio_sources[--num_inactive_audio_sources]; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
313 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
314 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
315 render_source_resumed(src); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
316 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
317 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
318 void render_free_source(audio_source *src) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
319 { |
1870
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
320 uint8_t found = 0; |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
321 for (uint8_t i = 0; i < num_inactive_audio_sources; i++) |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
322 { |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
323 if (inactive_audio_sources[i] == src) { |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
324 inactive_audio_sources[i] = inactive_audio_sources[--num_inactive_audio_sources]; |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
325 found = 1; |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
326 break; |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
327 } |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
328 } |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
329 if (!found) { |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
330 render_pause_source(src); |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
331 num_inactive_audio_sources--; |
e4671a39d155
Properly handle freeing a paused audio source. Fixes crash when repeatedly reloading a ROM or loading a sequence of different ROMs
Michael Pavone <pavone@retrodev.com>
parents:
1865
diff
changeset
|
332 } |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
333 |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
334 free(src->front); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
335 if (render_is_audio_sync()) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
336 free(src->back); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
337 render_free_audio_opaque(src->opaque); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
338 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
339 free(src); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
340 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
341 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
342 static int16_t lowpass_sample(audio_source *src, int16_t last, int16_t current) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
343 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
344 int32_t tmp = current * src->lowpass_alpha + last * (0x10000 - src->lowpass_alpha); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
345 current = tmp >> 16; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
346 return current; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
347 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
348 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
349 static void interp_sample(audio_source *src, int16_t last, int16_t current) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
350 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
351 int64_t tmp = last * ((src->buffer_fraction << 16) / src->buffer_inc); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
352 tmp += current * (0x10000 - ((src->buffer_fraction << 16) / src->buffer_inc)); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
353 src->back[src->buffer_pos++] = tmp >> 16; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
354 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
355 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
356 static uint32_t sync_samples; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
357 void render_put_mono_sample(audio_source *src, int16_t value) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
358 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
359 value = lowpass_sample(src, src->last_left, value); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
360 src->buffer_fraction += src->buffer_inc; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
361 uint32_t base = render_is_audio_sync() ? 0 : src->read_end; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
362 while (src->buffer_fraction > BUFFER_INC_RES) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
363 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
364 src->buffer_fraction -= BUFFER_INC_RES; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
365 interp_sample(src, src->last_left, value); |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
366 |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
367 if (((src->buffer_pos - base) & src->mask) >= sync_samples) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
368 render_do_audio_ready(src); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
369 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
370 src->buffer_pos &= src->mask; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
371 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
372 src->last_left = value; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
373 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
374 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
375 void render_put_stereo_sample(audio_source *src, int16_t left, int16_t right) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
376 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
377 left = lowpass_sample(src, src->last_left, left); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
378 right = lowpass_sample(src, src->last_right, right); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
379 src->buffer_fraction += src->buffer_inc; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
380 uint32_t base = render_is_audio_sync() ? 0 : src->read_end; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
381 while (src->buffer_fraction > BUFFER_INC_RES) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
382 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
383 src->buffer_fraction -= BUFFER_INC_RES; |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
384 |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
385 interp_sample(src, src->last_left, left); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
386 interp_sample(src, src->last_right, right); |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
387 |
1865
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
388 if (((src->buffer_pos - base) & src->mask)/2 >= sync_samples) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
389 render_do_audio_ready(src); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
390 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
391 src->buffer_pos &= src->mask; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
392 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
393 src->last_left = left; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
394 src->last_right = right; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
395 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
396 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
397 static void update_source(audio_source *src, double rc, uint8_t sync_changed) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
398 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
399 double alpha = src->dt / (src->dt + rc); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
400 int32_t lowpass_alpha = (int32_t)(((double)0x10000) * alpha); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
401 src->lowpass_alpha = lowpass_alpha; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
402 if (sync_changed) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
403 uint32_t alloc_size = render_is_audio_sync() ? src->num_channels * buffer_samples : nearest_pow2(render_min_buffered() * 4 * src->num_channels); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
404 src->back = realloc(src->back, alloc_size * sizeof(int16_t)); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
405 if (render_is_audio_sync()) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
406 src->front = malloc(alloc_size * sizeof(int16_t)); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
407 } else { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
408 free(src->front); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
409 src->front = src->back; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
410 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
411 src->mask = render_is_audio_sync() ? 0xFFFFFFFF : alloc_size-1; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
412 src->read_start = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
413 src->read_end = render_is_audio_sync() ? buffer_samples * src->num_channels : 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
414 src->buffer_pos = 0; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
415 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
416 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
417 |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
418 uint8_t old_audio_sync; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
419 void render_audio_initialized(render_audio_format format, uint32_t rate, uint8_t channels, uint32_t buffer_size, int sample_size_in) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
420 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
421 sample_rate = rate; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
422 output_channels = channels; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
423 buffer_samples = buffer_size; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
424 sample_size = sample_size_in; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
425 if (mix_buf) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
426 free(mix_buf); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
427 mix_buf = NULL; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
428 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
429 switch(format) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
430 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
431 case RENDER_AUDIO_S16: |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
432 convert = convert_s16; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
433 mix_buf = calloc(output_channels * buffer_samples, sizeof(float)); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
434 break; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
435 case RENDER_AUDIO_FLOAT: |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
436 convert = clamp_f32; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
437 break; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
438 case RENDER_AUDIO_UNKNOWN: |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
439 convert = convert_null; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
440 mix_buf = calloc(output_channels * buffer_samples, sizeof(float)); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
441 break; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
442 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
443 uint32_t syncs = render_audio_syncs_per_sec(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
444 if (syncs) { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
445 sync_samples = rate / syncs; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
446 } else { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
447 sync_samples = buffer_samples; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
448 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
449 char * gain_str = tern_find_path(config, "audio\0gain\0", TVAL_PTR).ptrval; |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
450 overall_gain_mult = db_to_mult(gain_str ? atof(gain_str) : 0.0f); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
451 uint8_t sync_changed = old_audio_sync != render_is_audio_sync(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
452 old_audio_sync = render_is_audio_sync(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
453 double lowpass_cutoff = get_lowpass_cutoff(config); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
454 double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
455 render_lock_audio(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
456 for (uint8_t i = 0; i < num_audio_sources; i++) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
457 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
458 update_source(audio_sources[i], rc, sync_changed); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
459 } |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
460 render_unlock_audio(); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
461 for (uint8_t i = 0; i < num_inactive_audio_sources; i++) |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
462 { |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
463 update_source(inactive_audio_sources[i], rc, sync_changed); |
4c322abd9fa5
Split generic part of audio code into a separate file so it can be used in other targets besides SDL
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
464 } |
2081
cfd53c94fffb
Initial stab at RF5C164 emulation
Michael Pavone <pavone@retrodev.com>
parents:
1870
diff
changeset
|
465 } |