Actually call on_reset callback
[lsnes.git] / src / core / audioapi.cpp
blobe4fbf31790a7e2ce2891d8c7e20e701d32614bda
1 #include "core/advdumper.hpp"
2 #include "core/audioapi.hpp"
3 #include "core/dispatch.hpp"
4 #include "core/framerate.hpp"
5 #include "core/instance.hpp"
6 #include "library/minmax.hpp"
7 #include "library/threads.hpp"
9 #include <cstring>
10 #include <cmath>
11 #include <iostream>
12 #include <unistd.h>
13 #include <sys/time.h>
15 #define MUSIC_BUFFERS 8
16 #define MAX_VOICE_ADJUST 200
18 bool audioapi_instance::vu_disabled = false;
20 audioapi_instance::dummy_cb_proc::dummy_cb_proc(audioapi_instance& _parent)
21 : parent(_parent)
25 int audioapi_instance::dummy_cb_proc::operator()()
27 int16_t buf[16384];
28 uint64_t last_ts = framerate_regulator::get_utime();
29 while(!parent.dummy_cb_quit) {
30 uint64_t cur_ts = framerate_regulator::get_utime();
31 uint64_t dt = cur_ts - last_ts;
32 last_ts = cur_ts;
33 unsigned samples = dt / 25;
34 if(samples > 16384)
35 samples = 16384; //Don't get crazy.
36 if(parent.dummy_cb_active_play)
37 parent.get_mixed(buf, samples, false);
38 if(parent.dummy_cb_active_record)
39 parent.put_voice(NULL, samples);
40 usleep(10000);
42 return 0;
45 namespace
47 // | -1 1 -1 1 | 1 0 0 0 |
48 // | 0 0 0 1 | 0 1 0 0 |
49 // | 1 1 1 1 | 0 0 1 0 |
50 // | 8 4 2 1 | 0 0 0 1 |
53 // | 6 0 0 0 |-1 4 -3 1 | |-1 3 -3 1|
54 // | 0 6 0 0 | 3 -6 3 0 | 1/6 | 3 -6 3 0|
55 // | 0 0 6 0 |-2 -4 6 -1 | |-2 -3 6 -1|
56 // | 0 0 0 6 | 0 6 0 0 | | 0 6 0 0|
60 void cubicitr_solve(double v1, double v2, double v3, double v4, double& A, double& B, double& C, double& D)
62 A = (-v1 + 3 * v2 - 3 * v3 + v4) / 6;
63 B = (v1 - 2 * v2 + v3) / 2;
64 C = (-2 * v1 - 3 * v2 + 6 * v3 - v4) / 6;
65 D = v2;
69 audioapi_instance::resampler::resampler()
71 position = 0;
72 vAl = vBl = vCl = vDl = 0;
73 vAr = vBr = vCr = vDr = 0;
76 void audioapi_instance::resampler::resample(float*& in, size_t& insize, float*& out, size_t& outsize, double ratio,
77 bool stereo)
79 double iratio = 1 / ratio;
80 while(outsize) {
81 double newpos = position + iratio;
82 while(newpos >= 1) {
83 //Gotta load a new sample.
84 if(!insize)
85 goto exit;
86 vAl = vBl; vBl = vCl; vCl = vDl; vDl = in[0];
87 vAr = vBr; vBr = vCr; vCr = vDr; vDr = in[stereo ? 1 : 0];
88 --insize;
89 in += (stereo ? 2 : 1);
90 newpos = newpos - 1;
92 position = newpos;
93 double A, B, C, D;
94 cubicitr_solve(vAl, vBl, vCl, vDl, A, B, C, D);
95 *(out++) = ((A * position + B) * position + C) * position + D;
96 if(stereo) {
97 cubicitr_solve(vAr, vBr, vCr, vDr, A, B, C, D);
98 *(out++) = ((A * position + B) * position + C) * position + D;
100 --outsize;
102 exit:
106 audioapi_instance::audioapi_instance()
107 : dummyproc(*this)
109 dummythread = NULL;
110 music_ptr = 0;
111 last_complete_music_seen = MUSIC_BUFFERS + 1;
112 last_complete_music = MUSIC_BUFFERS;
113 for(unsigned i = 0; i < MUSIC_BUFFERS; i++) {
114 music_size[i] = 0;
115 music_rate[i] = 48000;
116 music_stereo[i] = false;
118 voicep_get = 0;
119 voicep_put = 0;
120 voicer_get = 0;
121 voicer_put = 0;
122 voice_rate_play = 40000;
123 orig_voice_rate_play = 40000;
124 voice_rate_rec = 40000;
125 dummy_cb_active_record = false;
126 dummy_cb_active_play = false;
127 dummy_cb_quit = false;
128 _music_volume = 1;
129 _voicep_volume = 32767.0;
130 _voicer_volume = 1.0/32768;
131 last_adjust = false;
134 audioapi_instance::~audioapi_instance()
136 quit();
139 std::pair<unsigned, unsigned> audioapi_instance::voice_rate()
141 return std::make_pair(voice_rate_rec, voice_rate_play);
144 unsigned audioapi_instance::orig_voice_rate()
146 return orig_voice_rate_play;
149 void audioapi_instance::voice_rate(unsigned rate_rec, unsigned rate_play)
151 if(rate_rec)
152 voice_rate_rec = rate_rec;
153 else
154 voice_rate_rec = 40000;
155 dummy_cb_active_record = !rate_rec;
156 if(rate_play)
157 orig_voice_rate_play = voice_rate_play = rate_play;
158 else
159 orig_voice_rate_play = voice_rate_play = 40000;
160 dummy_cb_active_play = !rate_play;
163 unsigned audioapi_instance::voice_p_status()
165 unsigned p = voicep_put;
166 unsigned g = voicep_get;
167 if(g > p)
168 return g - p - 1;
169 else
170 return voicep_bufsize - (p - g) - 1;
173 unsigned audioapi_instance::voice_p_status2()
175 unsigned p = voicep_put;
176 unsigned g = voicep_get;
177 if(g > p)
178 return voicep_bufsize - (g - p);
179 else
180 return (p - g);
183 unsigned audioapi_instance::voice_r_status()
185 unsigned p = voicer_put;
186 unsigned g = voicer_get;
187 if(g > p)
188 return voicer_bufsize - (g - p);
189 else
190 return (p - g);
193 void audioapi_instance::play_voice(float* samples, size_t count)
195 unsigned ptr = voicep_put;
196 for(size_t i = 0; i < count; i++) {
197 voicep_buffer[ptr++] = samples[i];
198 if(ptr == voicep_bufsize)
199 ptr = 0;
201 voicep_put = ptr;
204 void audioapi_instance::record_voice(float* samples, size_t count)
206 unsigned ptr = voicer_get;
207 for(size_t i = 0; i < count; i++) {
208 samples[i] = voicer_buffer[ptr++];
209 if(ptr == voicer_bufsize)
210 ptr = 0;
212 voicer_get = ptr;
215 void audioapi_instance::submit_buffer(int16_t* samples, size_t count, bool stereo, double rate)
217 if(stereo)
218 for(unsigned i = 0; i < count; i++)
219 CORE().mdumper->on_sample(samples[2 * i + 0], samples[2 * i + 1]);
220 else
221 for(unsigned i = 0; i < count; i++)
222 CORE().mdumper->on_sample(samples[i], samples[i]);
223 //Limit buffers to avoid overrunning.
224 if(count > music_bufsize / (stereo ? 2 : 1))
225 count = music_bufsize / (stereo ? 2 : 1);
226 unsigned bidx = last_complete_music;
227 bidx = (bidx > (MUSIC_BUFFERS - 2)) ? 0 : bidx + 1;
228 memcpy(music_buffer + bidx * music_bufsize, samples, count * (stereo ? 2 : 1) * sizeof(int16_t));
229 music_stereo[bidx] = stereo;
230 music_rate[bidx] = rate;
231 music_size[bidx] = count;
232 last_complete_music = bidx;
235 struct audioapi_instance::buffer audioapi_instance::get_music(size_t played)
237 unsigned midx = last_complete_music_seen;
238 unsigned midx2 = last_complete_music;
239 if(midx2 >= MUSIC_BUFFERS) {
240 //Special case: No buffer.
241 struct buffer out;
242 out.samples = NULL;
243 out.pointer = 0;
244 //The rest are arbitrary.
245 out.total = 64;
246 out.stereo = false;
247 out.rate = 48000;
248 return out;
250 //Handle ACK. If the current buffer is too old, we want to ignore the ACK.
251 if(midx >= MUSIC_BUFFERS) {
252 //Load initial buffer.
253 midx = last_complete_music_seen = 0;
254 music_ptr = 0;
255 } else {
256 music_ptr += played;
257 //Otherwise, check if current buffer is not next on the line to be overwritten.
258 if((midx2 + 1) % MUSIC_BUFFERS == midx) {
259 //It is, bump buffer by one.
260 if(!last_adjust && voice_rate_play > orig_voice_rate_play - MAX_VOICE_ADJUST)
261 voice_rate_play--;
262 last_adjust = true;
263 midx = last_complete_music_seen = (midx + 1) % MUSIC_BUFFERS;
264 music_ptr = 0;
265 } else if(music_ptr >= music_size[midx] && midx != midx2) {
266 //It isn't, but current buffer is finished.
267 midx = last_complete_music_seen = (midx + 1) % MUSIC_BUFFERS;
268 music_ptr = 0;
269 last_adjust = false;
270 } else if(music_ptr >= music_size[midx] && midx == midx2) {
271 if(!last_adjust && voice_rate_play < orig_voice_rate_play + MAX_VOICE_ADJUST)
272 voice_rate_play++;
273 last_adjust = true;
274 //Current buffer is finished, but there is no new buffer.
275 //Send silence.
276 } else {
277 last_adjust = false;
278 //Can continue.
281 //Fill the structure.
282 struct buffer out;
283 if(music_ptr < music_size[midx]) {
284 out.samples = music_buffer + midx * music_bufsize;
285 out.pointer = music_ptr;
286 out.total = music_size[midx];
287 out.stereo = music_stereo[midx];
288 out.rate = music_rate[midx];
289 } else {
290 //Run out of buffers to play.
291 out.samples = NULL;
292 out.pointer = 0;
293 out.total = 64; //Arbitrary.
294 out.stereo = music_stereo[midx];
295 out.rate = music_rate[midx];
296 if(out.rate < 100)
297 out.rate = 48000; //Apparently there are buffers with zero rate.
299 return out;
302 void audioapi_instance::get_voice(float* samples, size_t count)
304 unsigned g = voicep_get;
305 unsigned p = voicep_put;
306 if(samples) {
307 for(size_t i = 0; i < count; i++) {
308 if(g != p)
309 samples[i] = _voicep_volume * voicep_buffer[g++];
310 else
311 samples[i] = 0.0;
312 if(g == voicep_bufsize)
313 g = 0;
315 } else {
316 for(size_t i = 0; i < count; i++) {
317 if(g != p)
318 g++;
319 if(g == voicep_bufsize)
320 g = 0;
323 voicep_get = g;
326 void audioapi_instance::put_voice(float* samples, size_t count)
328 unsigned ptr = voicer_put;
329 vu_vin(samples, count, false, voice_rate_rec, _voicer_volume);
330 for(size_t i = 0; i < count; i++) {
331 voicer_buffer[ptr++] = samples ? _voicer_volume * samples[i] : 0.0;
332 if(ptr == voicer_bufsize)
333 ptr = 0;
335 voicer_put = ptr;
338 void audioapi_instance::init()
340 voicep_get = 0;
341 voicep_put = 0;
342 voicer_get = 0;
343 voicer_put = 0;
344 last_complete_music = 3;
345 last_complete_music_seen = 4;
346 dummy_cb_active_play = true;
347 dummy_cb_active_record = true;
348 dummy_cb_quit = false;
349 dummythread = new threads::thread(dummyproc);
352 void audioapi_instance::quit()
354 dummy_cb_quit = true;
355 if(dummythread) {
356 dummythread->join();
357 dummythread = NULL;
361 void audioapi_instance::music_volume(float volume)
363 _music_volume = volume;
366 float audioapi_instance::music_volume()
368 return _music_volume;
371 void audioapi_instance::voicep_volume(float volume)
373 _voicep_volume = volume * 32767;
376 float audioapi_instance::voicep_volume()
378 return _voicep_volume / 32767;
381 void audioapi_instance::voicer_volume(float volume)
383 _voicer_volume = volume / 32768;
386 float audioapi_instance::voicer_volume()
388 return _voicer_volume * 32768;
391 void audioapi_instance::get_mixed(int16_t* samples, size_t count, bool stereo)
393 const size_t intbuf_size = 256;
394 float intbuf[intbuf_size];
395 float intbuf2[intbuf_size];
396 while(count > 0) {
397 buffer b = get_music(0);
398 float* in = intbuf;
399 float* out = intbuf2;
400 size_t outdata_used;
401 if(b.stereo) {
402 size_t indata = min(b.total - b.pointer, intbuf_size / 2);
403 size_t outdata = min(intbuf_size / 2, count);
404 size_t indata_used = indata;
405 outdata_used = outdata;
406 if(b.samples)
407 for(size_t i = 0; i < 2 * indata; i++)
408 intbuf[i] = _music_volume * b.samples[i + 2 * b.pointer];
409 else
410 for(size_t i = 0; i < 2 * indata; i++)
411 intbuf[i] = 0;
412 music_resampler.resample(in, indata, out, outdata, (double)voice_rate_play / b.rate, true);
413 indata_used -= indata;
414 outdata_used -= outdata;
415 get_music(indata_used);
416 get_voice(intbuf, outdata_used);
418 vu_mleft(intbuf2, outdata_used, true, voice_rate_play, 1 / 32768.0);
419 vu_mright(intbuf2 + 1, outdata_used, true, voice_rate_play, 1 / 32768.0);
420 vu_vout(intbuf, outdata_used, false, voice_rate_play, 1 / 32768.0);
422 for(size_t i = 0; i < outdata_used * (stereo ? 2 : 1); i++)
423 intbuf2[i] = max(min(intbuf2[i] + intbuf[i / 2], 32766.0f), -32767.0f);
424 if(stereo)
425 for(size_t i = 0; i < outdata_used * 2; i++)
426 samples[i] = intbuf2[i];
427 else
428 for(size_t i = 0; i < outdata_used; i++)
429 samples[i] = (intbuf2[2 * i + 0] + intbuf2[2 * i + 1]) / 2;
430 } else {
431 size_t indata = min(b.total - b.pointer, intbuf_size);
432 size_t outdata = min(intbuf_size, count);
433 size_t indata_used = indata;
434 outdata_used = outdata;
435 if(b.samples)
436 for(size_t i = 0; i < indata; i++)
437 intbuf[i] = _music_volume * b.samples[i + b.pointer];
438 else
439 for(size_t i = 0; i < indata; i++)
440 intbuf[i] = 0;
441 music_resampler.resample(in, indata, out, outdata, (double)voice_rate_play / b.rate, false);
442 indata_used -= indata;
443 outdata_used -= outdata;
444 get_music(indata_used);
445 get_voice(intbuf, outdata_used);
447 vu_mleft(intbuf2, outdata_used, false, voice_rate_play, 1 / 32768.0);
448 vu_mright(intbuf2, outdata_used, false, voice_rate_play, 1 / 32768.0);
449 vu_vout(intbuf, outdata_used, false, voice_rate_play, 1 / 32768.0);
451 for(size_t i = 0; i < outdata_used; i++)
452 intbuf2[i] = max(min(intbuf2[i] + intbuf[i], 32766.0f), -32767.0f);
453 if(stereo)
454 for(size_t i = 0; i < outdata_used; i++) {
455 samples[2 * i + 0] = intbuf2[i];
456 samples[2 * i + 1] = intbuf2[i];
458 else
459 for(size_t i = 0; i < outdata_used; i++)
460 samples[i] = intbuf2[i];
462 samples += (stereo ? 2 : 1) * outdata_used;
463 count -= outdata_used;
467 audioapi_instance::vumeter::vumeter()
469 accumulator = 0;
470 samples = 0;
471 vu = -999.0;
474 void audioapi_instance::vumeter::operator()(float* asamples, size_t count, bool stereo, double rate, double scale)
476 size_t limit = rate / 25;
477 //If we already at or exceed limit, cut immediately.
478 if(samples >= limit)
479 update_vu();
480 if(asamples) {
481 double sscale = scale * scale;
482 size_t j = 0;
483 if(stereo)
484 for(size_t i = 0; i < count; i++) {
485 accumulator += sscale * asamples[j] * asamples[j];
486 j += 2;
487 samples++;
488 if(samples >= limit)
489 update_vu();
491 else
492 for(size_t i = 0; i < count; i++) {
493 accumulator += sscale * asamples[i] * asamples[i];
494 samples++;
495 if(samples >= limit)
496 update_vu();
498 } else
499 for(size_t i = 0; i < count; i++) {
500 samples++;
501 if(samples >= limit)
502 update_vu();
506 void audioapi_instance::vumeter::update_vu()
508 if(vu_disabled)
509 return;
510 if(!samples) {
511 vu = -999.0;
512 accumulator = 0;
513 } else {
514 double a = accumulator;
515 if(a < 1e-120)
516 a = 1e-120; //Don't take log of zero.
517 vu = 10 / log(10) * (log(a) - log(samples));
518 if(vu < -999.0)
519 vu = -999.0;
520 accumulator = 0;
521 samples = 0;
523 CORE().dispatch->vu_change();
526 void audioapi_instance::disable_vu_updates()
528 vu_disabled = true;