annotate render_audio.c @ 2493:b62336ceb626 default tip

Kinda hacky fix to make sure Nuklear has the right GL context
author Michael Pavone <pavone@retrodev.com>
date Wed, 17 Apr 2024 22:18:45 -0700
parents b3832f73444f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }