1 #include "core/audioapi.hpp"
2 #include "core/dispatch.hpp"
3 #include "core/framerate.hpp"
4 #include "library/minmax.hpp"
5 #include "library/threadtypes.hpp"
12 //3 music buffers is not enough due to huge blocksizes used by SDL.
13 #define MUSIC_BUFFERS 8
14 #define MAX_VOICE_ADJUST 200
18 const unsigned voicep_bufsize
= 65536;
19 const unsigned voicer_bufsize
= 65536;
20 const unsigned music_bufsize
= 8192;
21 float voicep_buffer
[voicep_bufsize
];
22 float voicer_buffer
[voicer_bufsize
];
23 int16_t music_buffer
[MUSIC_BUFFERS
* music_bufsize
];
24 volatile bool music_stereo
[MUSIC_BUFFERS
];
25 volatile double music_rate
[MUSIC_BUFFERS
];
26 volatile size_t music_size
[MUSIC_BUFFERS
];
28 unsigned last_complete_music_seen
= MUSIC_BUFFERS
+ 1;
29 volatile unsigned last_complete_music
= MUSIC_BUFFERS
;
30 volatile unsigned voicep_get
= 0;
31 volatile unsigned voicep_put
= 0;
32 volatile unsigned voicer_get
= 0;
33 volatile unsigned voicer_put
= 0;
34 volatile unsigned voice_rate_play
= 40000;
35 volatile unsigned orig_voice_rate_play
= 40000;
36 volatile unsigned voice_rate_rec
= 40000;
37 volatile bool dummy_cb_active_record
= false;
38 volatile bool dummy_cb_active_play
= false;
39 volatile bool dummy_cb_quit
= false;
40 volatile float music_volume
= 1;
41 volatile float voicep_volume
= 32767.0;
42 volatile float voicer_volume
= 1.0/32768;
49 uint64_t last_ts
= get_utime();
50 while(!dummy_cb_quit
) {
51 uint64_t cur_ts
= get_utime();
52 uint64_t dt
= cur_ts
- last_ts
;
54 unsigned samples
= dt
/ 25;
56 samples
= 16384; //Don't get crazy.
57 if(dummy_cb_active_play
)
58 audioapi_get_mixed(buf
, samples
, false);
59 if(dummy_cb_active_record
)
60 audioapi_put_voice(NULL
, samples
);
67 dummy_cb_proc
* dummy_cb_proc_obj
;
68 thread_class
* dummy_cb_thread
;
71 // | -1 1 -1 1 | 1 0 0 0 |
72 // | 0 0 0 1 | 0 1 0 0 |
73 // | 1 1 1 1 | 0 0 1 0 |
74 // | 8 4 2 1 | 0 0 0 1 |
77 // | 6 0 0 0 |-1 4 -3 1 | |-1 3 -3 1|
78 // | 0 6 0 0 | 3 -6 3 0 | 1/6 | 3 -6 3 0|
79 // | 0 0 6 0 |-2 -4 6 -1 | |-2 -3 6 -1|
80 // | 0 0 0 6 | 0 6 0 0 | | 0 6 0 0|
84 void cubicitr_solve(double v1
, double v2
, double v3
, double v4
, double& A
, double& B
, double& C
, double& D
)
86 A
= (-v1
+ 3 * v2
- 3 * v3
+ v4
) / 6;
87 B
= (v1
- 2 * v2
+ v3
) / 2;
88 C
= (-2 * v1
- 3 * v2
+ 6 * v3
- v4
) / 6;
92 void linintr_solve(double v1
, double v2
, double& A
, double& B
)
99 audioapi_resampler::audioapi_resampler()
102 vAl
= vBl
= vCl
= vDl
= 0;
103 vAr
= vBr
= vCr
= vDr
= 0;
106 void audioapi_resampler::resample(float*& in
, size_t& insize
, float*& out
, size_t& outsize
, double ratio
, bool stereo
)
108 double iratio
= 1 / ratio
;
110 double newpos
= position
+ iratio
;
112 //Gotta load a new sample.
115 vAl
= vBl
; vBl
= vCl
; vCl
= vDl
; vDl
= in
[0];
116 vAr
= vBr
; vBr
= vCr
; vCr
= vDr
; vDr
= in
[stereo
? 1 : 0];
118 in
+= (stereo
? 2 : 1);
123 cubicitr_solve(vAl
, vBl
, vCl
, vDl
, A
, B
, C
, D
);
124 *(out
++) = ((A
* position
+ B
) * position
+ C
) * position
+ D
;
126 cubicitr_solve(vAr
, vBr
, vCr
, vDr
, A
, B
, C
, D
);
127 *(out
++) = ((A
* position
+ B
) * position
+ C
) * position
+ D
;
136 std::pair
<unsigned, unsigned> audioapi_voice_rate()
138 return std::make_pair(voice_rate_rec
, voice_rate_play
);
141 unsigned audioapi_orig_voice_rate()
143 return orig_voice_rate_play
;
146 void audioapi_voice_rate(unsigned rate_rec
, unsigned rate_play
)
149 voice_rate_rec
= rate_rec
;
151 voice_rate_rec
= 40000;
152 dummy_cb_active_record
= !rate_rec
;
154 orig_voice_rate_play
= voice_rate_play
= rate_play
;
156 orig_voice_rate_play
= voice_rate_play
= 40000;
157 dummy_cb_active_play
= !rate_play
;
160 unsigned audioapi_voice_p_status()
162 unsigned p
= voicep_put
;
163 unsigned g
= voicep_get
;
167 return voicep_bufsize
- (p
- g
) - 1;
170 unsigned audioapi_voice_p_status2()
172 unsigned p
= voicep_put
;
173 unsigned g
= voicep_get
;
175 return voicep_bufsize
- (g
- p
);
180 unsigned audioapi_voice_r_status()
182 unsigned p
= voicer_put
;
183 unsigned g
= voicer_get
;
185 return voicer_bufsize
- (g
- p
);
190 void audioapi_play_voice(float* samples
, size_t count
)
192 unsigned ptr
= voicep_put
;
193 for(size_t i
= 0; i
< count
; i
++) {
194 voicep_buffer
[ptr
++] = samples
[i
];
195 if(ptr
== voicep_bufsize
)
201 void audioapi_record_voice(float* samples
, size_t count
)
203 unsigned ptr
= voicer_get
;
204 for(size_t i
= 0; i
< count
; i
++) {
205 samples
[i
] = voicer_buffer
[ptr
++];
206 if(ptr
== voicer_bufsize
)
212 void audioapi_submit_buffer(int16_t* samples
, size_t count
, bool stereo
, double rate
)
215 for(unsigned i
= 0; i
< count
; i
++)
216 information_dispatch::do_sample(samples
[2 * i
+ 0], samples
[2 * i
+ 1]);
218 for(unsigned i
= 0; i
< count
; i
++)
219 information_dispatch::do_sample(samples
[i
], samples
[i
]);
220 //Limit buffers to avoid overrunning.
221 if(count
> music_bufsize
/ (stereo
? 2 : 1))
222 count
= music_bufsize
/ (stereo
? 2 : 1);
223 unsigned bidx
= last_complete_music
;
224 bidx
= (bidx
> (MUSIC_BUFFERS
- 2)) ? 0 : bidx
+ 1;
225 memcpy(music_buffer
+ bidx
* music_bufsize
, samples
, count
* (stereo
? 2 : 1) * sizeof(int16_t));
226 music_stereo
[bidx
] = stereo
;
227 music_rate
[bidx
] = rate
;
228 music_size
[bidx
] = count
;
229 last_complete_music
= bidx
;
232 struct audioapi_buffer
audioapi_get_music(size_t played
)
234 static bool last_adjust
= false; //Adjusting consequtively is too hard.
235 unsigned midx
= last_complete_music_seen
;
236 unsigned midx2
= last_complete_music
;
237 if(midx2
>= MUSIC_BUFFERS
) {
238 //Special case: No buffer.
239 struct audioapi_buffer out
;
242 //The rest are arbitrary.
248 //Handle ACK. If the current buffer is too old, we want to ignore the ACK.
249 if(midx
>= MUSIC_BUFFERS
) {
250 //Load initial buffer.
251 midx
= last_complete_music_seen
= 0;
255 //Otherwise, check if current buffer is not next on the line to be overwritten.
256 if((midx2
+ 1) % MUSIC_BUFFERS
== midx
) {
257 //It is, bump buffer by one.
258 if(!last_adjust
&& voice_rate_play
> orig_voice_rate_play
- MAX_VOICE_ADJUST
)
261 midx
= last_complete_music_seen
= (midx
+ 1) % MUSIC_BUFFERS
;
263 } else if(music_ptr
>= music_size
[midx
] && midx
!= midx2
) {
264 //It isn't, but current buffer is finished.
265 midx
= last_complete_music_seen
= (midx
+ 1) % MUSIC_BUFFERS
;
268 } else if(music_ptr
>= music_size
[midx
] && midx
== midx2
) {
269 if(!last_adjust
&& voice_rate_play
< orig_voice_rate_play
+ MAX_VOICE_ADJUST
)
272 //Current buffer is finished, but there is no new buffer.
279 //Fill the structure.
280 struct audioapi_buffer out
;
281 if(music_ptr
< music_size
[midx
]) {
282 out
.samples
= music_buffer
+ midx
* music_bufsize
;
283 out
.pointer
= music_ptr
;
284 out
.total
= music_size
[midx
];
285 out
.stereo
= music_stereo
[midx
];
286 out
.rate
= music_rate
[midx
];
288 //Run out of buffers to play.
291 out
.total
= 64; //Arbitrary.
292 out
.stereo
= music_stereo
[midx
];
293 out
.rate
= music_rate
[midx
];
295 out
.rate
= 48000; //Apparently there are buffers with zero rate.
300 void audioapi_get_voice(float* samples
, size_t count
)
302 unsigned g
= voicep_get
;
303 unsigned p
= voicep_put
;
305 for(size_t i
= 0; i
< count
; i
++) {
307 samples
[i
] = voicep_volume
* voicep_buffer
[g
++];
310 if(g
== voicep_bufsize
)
314 for(size_t i
= 0; i
< count
; i
++) {
317 if(g
== voicep_bufsize
)
324 void audioapi_put_voice(float* samples
, size_t count
)
326 unsigned ptr
= voicer_put
;
327 audioapi_vu_vin(samples
, count
, false, voice_rate_rec
, voicer_volume
);
328 for(size_t i
= 0; i
< count
; i
++) {
329 voicer_buffer
[ptr
++] = samples
? voicer_volume
* samples
[i
] : 0.0;
330 if(ptr
== voicer_bufsize
)
342 last_complete_music
= 3;
343 last_complete_music_seen
= 4;
344 dummy_cb_active_play
= true;
345 dummy_cb_active_record
= true;
346 dummy_cb_quit
= false;
347 dummy_cb_proc_obj
= new dummy_cb_proc
;
348 dummy_cb_thread
= new thread_class(*dummy_cb_proc_obj
);
353 dummy_cb_quit
= true;
354 dummy_cb_thread
->join();
355 delete dummy_cb_proc_obj
;
358 void audioapi_music_volume(float volume
)
360 music_volume
= volume
;
363 float audioapi_music_volume()
368 void audioapi_voicep_volume(float volume
)
370 voicep_volume
= volume
* 32767;
373 float audioapi_voicep_volume()
375 return voicep_volume
/ 32767;
378 void audioapi_voicer_volume(float volume
)
380 voicer_volume
= volume
/ 32768;
383 float audioapi_voicer_volume()
385 return voicer_volume
* 32768;
388 void audioapi_get_mixed(int16_t* samples
, size_t count
, bool stereo
)
390 static audioapi_resampler music_resampler
;
391 const size_t intbuf_size
= 256;
392 float intbuf
[intbuf_size
];
393 float intbuf2
[intbuf_size
];
395 audioapi_buffer b
= audioapi_get_music(0);
397 float* out
= intbuf2
;
400 size_t indata
= min(b
.total
- b
.pointer
, intbuf_size
/ 2);
401 size_t outdata
= min(intbuf_size
/ 2, count
);
402 size_t indata_used
= indata
;
403 outdata_used
= outdata
;
405 for(size_t i
= 0; i
< 2 * indata
; i
++)
406 intbuf
[i
] = music_volume
* b
.samples
[i
+ 2 * b
.pointer
];
408 for(size_t i
= 0; i
< 2 * indata
; i
++)
410 music_resampler
.resample(in
, indata
, out
, outdata
, (double)voice_rate_play
/ b
.rate
, true);
411 indata_used
-= indata
;
412 outdata_used
-= outdata
;
413 audioapi_get_music(indata_used
);
414 audioapi_get_voice(intbuf
, outdata_used
);
416 audioapi_vu_mleft(intbuf2
, outdata_used
, true, voice_rate_play
, 1 / 32768.0);
417 audioapi_vu_mright(intbuf2
+ 1, outdata_used
, true, voice_rate_play
, 1 / 32768.0);
418 audioapi_vu_vout(intbuf
, outdata_used
, false, voice_rate_play
, 1 / 32768.0);
420 for(size_t i
= 0; i
< outdata_used
* (stereo
? 2 : 1); i
++)
421 intbuf2
[i
] = max(min(intbuf2
[i
] + intbuf
[i
/ 2], 32766.0f
), -32767.0f
);
423 for(size_t i
= 0; i
< outdata_used
* 2; i
++)
424 samples
[i
] = intbuf2
[i
];
426 for(size_t i
= 0; i
< outdata_used
; i
++)
427 samples
[i
] = (intbuf2
[2 * i
+ 0] + intbuf2
[2 * i
+ 1]) / 2;
429 size_t indata
= min(b
.total
- b
.pointer
, intbuf_size
);
430 size_t outdata
= min(intbuf_size
, count
);
431 size_t indata_used
= indata
;
432 outdata_used
= outdata
;
434 for(size_t i
= 0; i
< indata
; i
++)
435 intbuf
[i
] = music_volume
* b
.samples
[i
+ b
.pointer
];
437 for(size_t i
= 0; i
< indata
; i
++)
439 music_resampler
.resample(in
, indata
, out
, outdata
, (double)voice_rate_play
/ b
.rate
, false);
440 indata_used
-= indata
;
441 outdata_used
-= outdata
;
442 audioapi_get_music(indata_used
);
443 audioapi_get_voice(intbuf
, outdata_used
);
445 audioapi_vu_mleft(intbuf2
, outdata_used
, false, voice_rate_play
, 1 / 32768.0);
446 audioapi_vu_mright(intbuf2
, outdata_used
, false, voice_rate_play
, 1 / 32768.0);
447 audioapi_vu_vout(intbuf
, outdata_used
, false, voice_rate_play
, 1 / 32768.0);
449 for(size_t i
= 0; i
< outdata_used
; i
++)
450 intbuf2
[i
] = max(min(intbuf2
[i
] + intbuf
[i
], 32766.0f
), -32767.0f
);
452 for(size_t i
= 0; i
< outdata_used
; i
++) {
453 samples
[2 * i
+ 0] = intbuf2
[i
];
454 samples
[2 * i
+ 1] = intbuf2
[i
];
457 for(size_t i
= 0; i
< outdata_used
; i
++)
458 samples
[i
] = intbuf2
[i
];
460 samples
+= (stereo
? 2 : 1) * outdata_used
;
461 count
-= outdata_used
;
465 audioapi_vumeter::audioapi_vumeter()
472 void audioapi_vumeter::operator()(float* asamples
, size_t count
, bool stereo
, double rate
, double scale
)
474 size_t limit
= rate
/ 25;
475 //If we already at or exceed limit, cut immediately.
479 double sscale
= scale
* scale
;
482 for(size_t i
= 0; i
< count
; i
++) {
483 accumulator
+= sscale
* asamples
[j
] * asamples
[j
];
490 for(size_t i
= 0; i
< count
; i
++) {
491 accumulator
+= sscale
* asamples
[i
] * asamples
[i
];
497 for(size_t i
= 0; i
< count
; i
++) {
504 void audioapi_vumeter::update_vu()
510 double a
= accumulator
;
512 a
= 1e-120; //Don't take log of zero.
513 vu
= 10 / log(10) * (log(a
) - log(samples
));
523 audioapi_vumeter audioapi_vu_mleft
;
524 audioapi_vumeter audioapi_vu_mright
;
525 audioapi_vumeter audioapi_vu_vout
;
526 audioapi_vumeter audioapi_vu_vin
;